Add patch that contain Mali fixes.
[deb_xorg-server.git] / present / present_screen.c
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 }