Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2013 Keith Packard | |
3 | * | |
4 | * Permission to use, copy, modify, distribute, and sell this software and its | |
5 | * documentation for any purpose is hereby granted without fee, provided that | |
6 | * the above copyright notice appear in all copies and that both that copyright | |
7 | * notice and this permission notice appear in supporting documentation, and | |
8 | * that the name of the copyright holders not be used in advertising or | |
9 | * publicity pertaining to distribution of the software without specific, | |
10 | * written prior permission. The copyright holders make no representations | |
11 | * about the suitability of this software for any purpose. It is provided "as | |
12 | * is" without express or implied warranty. | |
13 | * | |
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
20 | * OF THIS SOFTWARE. | |
21 | */ | |
22 | ||
23 | #ifdef HAVE_XORG_CONFIG_H | |
24 | #include <xorg-config.h> | |
25 | #endif | |
26 | ||
27 | #include "present_priv.h" | |
28 | ||
29 | int present_request; | |
30 | DevPrivateKeyRec present_screen_private_key; | |
31 | DevPrivateKeyRec present_window_private_key; | |
32 | ||
33 | /* | |
34 | * Get a pointer to a present window private, creating if necessary | |
35 | */ | |
36 | present_window_priv_ptr | |
37 | present_get_window_priv(WindowPtr window, Bool create) | |
38 | { | |
39 | present_window_priv_ptr window_priv = present_window_priv(window); | |
40 | ||
41 | if (!create || window_priv != NULL) | |
42 | return window_priv; | |
43 | window_priv = calloc (1, sizeof (present_window_priv_rec)); | |
44 | if (!window_priv) | |
45 | return NULL; | |
46 | xorg_list_init(&window_priv->vblank); | |
47 | xorg_list_init(&window_priv->notifies); | |
48 | dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); | |
49 | return window_priv; | |
50 | } | |
51 | ||
52 | /* | |
53 | * Hook the close screen function to clean up our screen private | |
54 | */ | |
55 | static Bool | |
56 | present_close_screen(ScreenPtr screen) | |
57 | { | |
58 | present_screen_priv_ptr screen_priv = present_screen_priv(screen); | |
59 | ||
60 | present_flip_destroy(screen); | |
61 | ||
62 | unwrap(screen_priv, screen, CloseScreen); | |
63 | (*screen->CloseScreen) (screen); | |
64 | free(screen_priv); | |
65 | return TRUE; | |
66 | } | |
67 | ||
68 | /* | |
69 | * Free any queued presentations for this window | |
70 | */ | |
71 | static void | |
72 | present_free_window_vblank(WindowPtr window) | |
73 | { | |
74 | present_window_priv_ptr window_priv = present_window_priv(window); | |
75 | present_vblank_ptr vblank, tmp; | |
76 | ||
77 | xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { | |
78 | present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc); | |
79 | present_vblank_destroy(vblank); | |
80 | } | |
81 | } | |
82 | ||
83 | /* | |
84 | * Clean up any pending or current flips for this window | |
85 | */ | |
86 | static void | |
87 | present_clear_window_flip(WindowPtr window) | |
88 | { | |
89 | ScreenPtr screen = window->drawable.pScreen; | |
90 | present_screen_priv_ptr screen_priv = present_screen_priv(screen); | |
91 | present_vblank_ptr flip_pending = screen_priv->flip_pending; | |
92 | ||
93 | if (flip_pending && flip_pending->window == window) { | |
94 | assert (flip_pending->abort_flip); | |
95 | flip_pending->window = NULL; | |
96 | } | |
97 | if (screen_priv->flip_window == window) | |
98 | screen_priv->flip_window = NULL; | |
99 | } | |
100 | ||
101 | /* | |
102 | * Hook the close window function to clean up our window private | |
103 | */ | |
104 | static Bool | |
105 | present_destroy_window(WindowPtr window) | |
106 | { | |
107 | Bool ret; | |
108 | ScreenPtr screen = window->drawable.pScreen; | |
109 | present_screen_priv_ptr screen_priv = present_screen_priv(screen); | |
110 | present_window_priv_ptr window_priv = present_window_priv(window); | |
111 | ||
112 | if (window_priv) { | |
113 | present_clear_window_notifies(window); | |
114 | present_free_events(window); | |
115 | present_free_window_vblank(window); | |
116 | present_clear_window_flip(window); | |
117 | free(window_priv); | |
118 | } | |
119 | unwrap(screen_priv, screen, DestroyWindow); | |
120 | if (screen->DestroyWindow) | |
121 | ret = screen->DestroyWindow (window); | |
122 | else | |
123 | ret = TRUE; | |
124 | wrap(screen_priv, screen, DestroyWindow, present_destroy_window); | |
125 | return ret; | |
126 | } | |
127 | ||
128 | /* | |
129 | * Hook the config notify screen function to deliver present config notify events | |
130 | */ | |
131 | static int | |
132 | present_config_notify(WindowPtr window, | |
133 | int x, int y, int w, int h, int bw, | |
134 | WindowPtr sibling) | |
135 | { | |
136 | int ret; | |
137 | ScreenPtr screen = window->drawable.pScreen; | |
138 | present_screen_priv_ptr screen_priv = present_screen_priv(screen); | |
139 | ||
140 | present_send_config_notify(window, x, y, w, h, bw, sibling); | |
141 | ||
142 | unwrap(screen_priv, screen, ConfigNotify); | |
143 | if (screen->ConfigNotify) | |
144 | ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); | |
145 | else | |
146 | ret = 0; | |
147 | wrap(screen_priv, screen, ConfigNotify, present_config_notify); | |
148 | return ret; | |
149 | } | |
150 | ||
151 | /* | |
152 | * Hook the clip notify screen function to un-flip as necessary | |
153 | */ | |
154 | ||
155 | static void | |
156 | present_clip_notify(WindowPtr window, int dx, int dy) | |
157 | { | |
158 | ScreenPtr screen = window->drawable.pScreen; | |
159 | present_screen_priv_ptr screen_priv = present_screen_priv(screen); | |
160 | ||
161 | present_check_flip_window(window); | |
162 | unwrap(screen_priv, screen, ClipNotify) | |
163 | if (screen->ClipNotify) | |
164 | screen->ClipNotify (window, dx, dy); | |
165 | wrap(screen_priv, screen, ClipNotify, present_clip_notify); | |
166 | } | |
167 | ||
168 | /* | |
169 | * Initialize a screen for use with present | |
170 | */ | |
171 | int | |
172 | present_screen_init(ScreenPtr screen, present_screen_info_ptr info) | |
173 | { | |
174 | if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) | |
175 | return FALSE; | |
176 | ||
177 | if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) | |
178 | return FALSE; | |
179 | ||
180 | if (!present_screen_priv(screen)) { | |
181 | present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec)); | |
182 | if (!screen_priv) | |
183 | return FALSE; | |
184 | ||
185 | wrap(screen_priv, screen, CloseScreen, present_close_screen); | |
186 | wrap(screen_priv, screen, DestroyWindow, present_destroy_window); | |
187 | wrap(screen_priv, screen, ConfigNotify, present_config_notify); | |
188 | wrap(screen_priv, screen, ClipNotify, present_clip_notify); | |
189 | ||
190 | screen_priv->info = info; | |
191 | ||
192 | dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); | |
193 | ||
194 | present_fake_screen_init(screen); | |
195 | } | |
196 | ||
197 | return TRUE; | |
198 | } | |
199 | ||
200 | /* | |
201 | * Initialize the present extension | |
202 | */ | |
203 | void | |
204 | present_extension_init(void) | |
205 | { | |
206 | ExtensionEntry *extension; | |
207 | int i; | |
208 | ||
209 | #ifdef PANORAMIX | |
210 | if (!noPanoramiXExtension) | |
211 | return; | |
212 | #endif | |
213 | ||
214 | extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, | |
215 | proc_present_dispatch, sproc_present_dispatch, | |
216 | NULL, StandardMinorOpcode); | |
217 | if (!extension) | |
218 | goto bail; | |
219 | ||
220 | present_request = extension->base; | |
221 | ||
222 | if (!present_init()) | |
223 | goto bail; | |
224 | ||
225 | if (!present_event_init()) | |
226 | goto bail; | |
227 | ||
228 | for (i = 0; i < screenInfo.numScreens; i++) { | |
229 | if (!present_screen_init(screenInfo.screens[i], NULL)) | |
230 | goto bail; | |
231 | } | |
232 | return; | |
233 | ||
234 | bail: | |
235 | FatalError("Cannot initialize Present extension"); | |
236 | } |