xref: /OK3568_Linux_fs/external/xserver/present/present_screen.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2013 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that copyright
7*4882a593Smuzhiyun  * notice and this permission notice appear in supporting documentation, and
8*4882a593Smuzhiyun  * that the name of the copyright holders not be used in advertising or
9*4882a593Smuzhiyun  * publicity pertaining to distribution of the software without specific,
10*4882a593Smuzhiyun  * written prior permission.  The copyright holders make no representations
11*4882a593Smuzhiyun  * about the suitability of this software for any purpose.  It is provided "as
12*4882a593Smuzhiyun  * is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20*4882a593Smuzhiyun  * OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
24*4882a593Smuzhiyun #include <xorg-config.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include "present_priv.h"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun int present_request;
30*4882a593Smuzhiyun DevPrivateKeyRec present_screen_private_key;
31*4882a593Smuzhiyun DevPrivateKeyRec present_window_private_key;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /*
34*4882a593Smuzhiyun  * Get a pointer to a present window private, creating if necessary
35*4882a593Smuzhiyun  */
36*4882a593Smuzhiyun present_window_priv_ptr
present_get_window_priv(WindowPtr window,Bool create)37*4882a593Smuzhiyun present_get_window_priv(WindowPtr window, Bool create)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun     if (!create || window_priv != NULL)
42*4882a593Smuzhiyun         return window_priv;
43*4882a593Smuzhiyun     window_priv = calloc (1, sizeof (present_window_priv_rec));
44*4882a593Smuzhiyun     if (!window_priv)
45*4882a593Smuzhiyun         return NULL;
46*4882a593Smuzhiyun     xorg_list_init(&window_priv->vblank);
47*4882a593Smuzhiyun     xorg_list_init(&window_priv->notifies);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun     xorg_list_init(&window_priv->exec_queue);
50*4882a593Smuzhiyun     xorg_list_init(&window_priv->flip_queue);
51*4882a593Smuzhiyun     xorg_list_init(&window_priv->idle_queue);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun     window_priv->window = window;
54*4882a593Smuzhiyun     window_priv->crtc = PresentCrtcNeverSet;
55*4882a593Smuzhiyun     dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
56*4882a593Smuzhiyun     return window_priv;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun  * Hook the close screen function to clean up our screen private
61*4882a593Smuzhiyun  */
62*4882a593Smuzhiyun static Bool
present_close_screen(ScreenPtr screen)63*4882a593Smuzhiyun present_close_screen(ScreenPtr screen)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun     screen_priv->flip_destroy(screen);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun     unwrap(screen_priv, screen, CloseScreen);
70*4882a593Smuzhiyun     (*screen->CloseScreen) (screen);
71*4882a593Smuzhiyun     free(screen_priv);
72*4882a593Smuzhiyun     return TRUE;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun  * Free any queued presentations for this window
77*4882a593Smuzhiyun  */
78*4882a593Smuzhiyun static void
present_free_window_vblank(WindowPtr window)79*4882a593Smuzhiyun present_free_window_vblank(WindowPtr window)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun     ScreenPtr                   screen = window->drawable.pScreen;
82*4882a593Smuzhiyun     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
83*4882a593Smuzhiyun     present_window_priv_ptr     window_priv = present_window_priv(window);
84*4882a593Smuzhiyun     present_vblank_ptr          vblank, tmp;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun     xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
87*4882a593Smuzhiyun         screen_priv->abort_vblank(window->drawable.pScreen, window, vblank->crtc, vblank->event_id, vblank->target_msc);
88*4882a593Smuzhiyun         present_vblank_destroy(vblank);
89*4882a593Smuzhiyun     }
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun  * Clean up any pending or current flips for this window
94*4882a593Smuzhiyun  */
95*4882a593Smuzhiyun static void
present_clear_window_flip(WindowPtr window)96*4882a593Smuzhiyun present_clear_window_flip(WindowPtr window)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun     ScreenPtr                   screen = window->drawable.pScreen;
99*4882a593Smuzhiyun     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
100*4882a593Smuzhiyun     present_vblank_ptr          flip_pending = screen_priv->flip_pending;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun     if (flip_pending && flip_pending->window == window) {
103*4882a593Smuzhiyun         present_set_abort_flip(screen);
104*4882a593Smuzhiyun         flip_pending->window = NULL;
105*4882a593Smuzhiyun     }
106*4882a593Smuzhiyun     if (screen_priv->flip_window == window) {
107*4882a593Smuzhiyun         present_restore_screen_pixmap(screen);
108*4882a593Smuzhiyun         screen_priv->flip_window = NULL;
109*4882a593Smuzhiyun     }
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun static void
present_wnmd_clear_window_flip(WindowPtr window)113*4882a593Smuzhiyun present_wnmd_clear_window_flip(WindowPtr window)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun     present_window_priv_ptr     window_priv = present_window_priv(window);
116*4882a593Smuzhiyun     present_vblank_ptr          vblank, tmp;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun     xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->flip_queue, event_queue) {
119*4882a593Smuzhiyun         present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
120*4882a593Smuzhiyun         present_vblank_destroy(vblank);
121*4882a593Smuzhiyun     }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun     xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->idle_queue, event_queue) {
124*4882a593Smuzhiyun         present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
125*4882a593Smuzhiyun         present_vblank_destroy(vblank);
126*4882a593Smuzhiyun     }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun     vblank = window_priv->flip_active;
129*4882a593Smuzhiyun     if (vblank) {
130*4882a593Smuzhiyun         present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
131*4882a593Smuzhiyun         present_vblank_destroy(vblank);
132*4882a593Smuzhiyun     }
133*4882a593Smuzhiyun     window_priv->flip_active = NULL;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun  * Hook the close window function to clean up our window private
138*4882a593Smuzhiyun  */
139*4882a593Smuzhiyun static Bool
present_destroy_window(WindowPtr window)140*4882a593Smuzhiyun present_destroy_window(WindowPtr window)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun     Bool ret;
143*4882a593Smuzhiyun     ScreenPtr screen = window->drawable.pScreen;
144*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
145*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun     if (window_priv) {
148*4882a593Smuzhiyun         present_clear_window_notifies(window);
149*4882a593Smuzhiyun         present_free_events(window);
150*4882a593Smuzhiyun         present_free_window_vblank(window);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun         if (screen_priv->wnmd_info)
153*4882a593Smuzhiyun             present_wnmd_clear_window_flip(window);
154*4882a593Smuzhiyun         else
155*4882a593Smuzhiyun             present_clear_window_flip(window);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun         free(window_priv);
158*4882a593Smuzhiyun     }
159*4882a593Smuzhiyun     unwrap(screen_priv, screen, DestroyWindow);
160*4882a593Smuzhiyun     if (screen->DestroyWindow)
161*4882a593Smuzhiyun         ret = screen->DestroyWindow (window);
162*4882a593Smuzhiyun     else
163*4882a593Smuzhiyun         ret = TRUE;
164*4882a593Smuzhiyun     wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
165*4882a593Smuzhiyun     return ret;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun /*
169*4882a593Smuzhiyun  * Hook the config notify screen function to deliver present config notify events
170*4882a593Smuzhiyun  */
171*4882a593Smuzhiyun static int
present_config_notify(WindowPtr window,int x,int y,int w,int h,int bw,WindowPtr sibling)172*4882a593Smuzhiyun present_config_notify(WindowPtr window,
173*4882a593Smuzhiyun                    int x, int y, int w, int h, int bw,
174*4882a593Smuzhiyun                    WindowPtr sibling)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun     int ret;
177*4882a593Smuzhiyun     ScreenPtr screen = window->drawable.pScreen;
178*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun     present_send_config_notify(window, x, y, w, h, bw, sibling);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun     unwrap(screen_priv, screen, ConfigNotify);
183*4882a593Smuzhiyun     if (screen->ConfigNotify)
184*4882a593Smuzhiyun         ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
185*4882a593Smuzhiyun     else
186*4882a593Smuzhiyun         ret = 0;
187*4882a593Smuzhiyun     wrap(screen_priv, screen, ConfigNotify, present_config_notify);
188*4882a593Smuzhiyun     return ret;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun /*
192*4882a593Smuzhiyun  * Hook the clip notify screen function to un-flip as necessary
193*4882a593Smuzhiyun  */
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun static void
present_clip_notify(WindowPtr window,int dx,int dy)196*4882a593Smuzhiyun present_clip_notify(WindowPtr window, int dx, int dy)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun     ScreenPtr screen = window->drawable.pScreen;
199*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun     screen_priv->check_flip_window(window);
202*4882a593Smuzhiyun     unwrap(screen_priv, screen, ClipNotify)
203*4882a593Smuzhiyun     if (screen->ClipNotify)
204*4882a593Smuzhiyun         screen->ClipNotify (window, dx, dy);
205*4882a593Smuzhiyun     wrap(screen_priv, screen, ClipNotify, present_clip_notify);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun static Bool
present_screen_register_priv_keys(void)209*4882a593Smuzhiyun present_screen_register_priv_keys(void)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
212*4882a593Smuzhiyun         return FALSE;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
215*4882a593Smuzhiyun         return FALSE;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun     return TRUE;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun static present_screen_priv_ptr
present_screen_priv_init(ScreenPtr screen)221*4882a593Smuzhiyun present_screen_priv_init(ScreenPtr screen)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     screen_priv = calloc(1, sizeof (present_screen_priv_rec));
226*4882a593Smuzhiyun     if (!screen_priv)
227*4882a593Smuzhiyun         return NULL;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun     wrap(screen_priv, screen, CloseScreen, present_close_screen);
230*4882a593Smuzhiyun     wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
231*4882a593Smuzhiyun     wrap(screen_priv, screen, ConfigNotify, present_config_notify);
232*4882a593Smuzhiyun     wrap(screen_priv, screen, ClipNotify, present_clip_notify);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun     dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     return screen_priv;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun /*
240*4882a593Smuzhiyun  * Initialize a screen for use with present in window flip mode (wnmd)
241*4882a593Smuzhiyun  */
242*4882a593Smuzhiyun int
present_wnmd_screen_init(ScreenPtr screen,present_wnmd_info_ptr info)243*4882a593Smuzhiyun present_wnmd_screen_init(ScreenPtr screen, present_wnmd_info_ptr info)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun     if (!present_screen_register_priv_keys())
246*4882a593Smuzhiyun         return FALSE;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun     if (!present_screen_priv(screen)) {
249*4882a593Smuzhiyun         present_screen_priv_ptr screen_priv = present_screen_priv_init(screen);
250*4882a593Smuzhiyun         if (!screen_priv)
251*4882a593Smuzhiyun             return FALSE;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun         screen_priv->wnmd_info = info;
254*4882a593Smuzhiyun         present_wnmd_init_mode_hooks(screen_priv);
255*4882a593Smuzhiyun     }
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun     return TRUE;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun /*
261*4882a593Smuzhiyun  * Initialize a screen for use with present in default screen flip mode (scmd)
262*4882a593Smuzhiyun  */
263*4882a593Smuzhiyun int
present_screen_init(ScreenPtr screen,present_screen_info_ptr info)264*4882a593Smuzhiyun present_screen_init(ScreenPtr screen, present_screen_info_ptr info)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun     if (!present_screen_register_priv_keys())
267*4882a593Smuzhiyun         return FALSE;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun     if (!present_screen_priv(screen)) {
270*4882a593Smuzhiyun         present_screen_priv_ptr screen_priv = present_screen_priv_init(screen);
271*4882a593Smuzhiyun         if (!screen_priv)
272*4882a593Smuzhiyun             return FALSE;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun         screen_priv->info = info;
275*4882a593Smuzhiyun         present_scmd_init_mode_hooks(screen_priv);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun         present_fake_screen_init(screen);
278*4882a593Smuzhiyun     }
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun     return TRUE;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun  * Initialize the present extension
285*4882a593Smuzhiyun  */
286*4882a593Smuzhiyun void
present_extension_init(void)287*4882a593Smuzhiyun present_extension_init(void)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun     ExtensionEntry *extension;
290*4882a593Smuzhiyun     int i;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun #ifdef PANORAMIX
293*4882a593Smuzhiyun     if (!noPanoramiXExtension)
294*4882a593Smuzhiyun         return;
295*4882a593Smuzhiyun #endif
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
298*4882a593Smuzhiyun                              proc_present_dispatch, sproc_present_dispatch,
299*4882a593Smuzhiyun                              NULL, StandardMinorOpcode);
300*4882a593Smuzhiyun     if (!extension)
301*4882a593Smuzhiyun         goto bail;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun     present_request = extension->base;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     if (!present_init())
306*4882a593Smuzhiyun         goto bail;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun     if (!present_event_init())
309*4882a593Smuzhiyun         goto bail;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++) {
312*4882a593Smuzhiyun         if (!present_screen_init(screenInfo.screens[i], NULL))
313*4882a593Smuzhiyun             goto bail;
314*4882a593Smuzhiyun     }
315*4882a593Smuzhiyun     return;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun bail:
318*4882a593Smuzhiyun     FatalError("Cannot initialize Present extension");
319*4882a593Smuzhiyun }
320