xref: /OK3568_Linux_fs/external/xserver/present/present_wnmd.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2018 Roman Gilg
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 /*
30*4882a593Smuzhiyun  * Window flip mode
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  * Provides per-window flips. Flips can be processed on windows that
33*4882a593Smuzhiyun  * have the same size as their parents, which they share their pixmap with.
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * A flip still requires a copy currently, since the original pixmap needs
36*4882a593Smuzhiyun  * to be updated with the new pixmap content. Just a flip of all windows
37*4882a593Smuzhiyun  * to the new pixmap is diffcult, because the original pixmap might not be
38*4882a593Smuzhiyun  * controlled by the Xserver.
39*4882a593Smuzhiyun  *
40*4882a593Smuzhiyun  */
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun static void
43*4882a593Smuzhiyun present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static int
present_wnmd_queue_vblank(ScreenPtr screen,WindowPtr window,RRCrtcPtr crtc,uint64_t event_id,uint64_t msc)46*4882a593Smuzhiyun present_wnmd_queue_vblank(ScreenPtr screen,
47*4882a593Smuzhiyun                           WindowPtr window,
48*4882a593Smuzhiyun                           RRCrtcPtr crtc,
49*4882a593Smuzhiyun                           uint64_t event_id,
50*4882a593Smuzhiyun                           uint64_t msc)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
53*4882a593Smuzhiyun     return (*screen_priv->wnmd_info->queue_vblank) (window, crtc, event_id, msc);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static void
present_wnmd_create_event_id(present_window_priv_ptr window_priv,present_vblank_ptr vblank)57*4882a593Smuzhiyun present_wnmd_create_event_id(present_window_priv_ptr window_priv, present_vblank_ptr vblank)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun     vblank->event_id = ++window_priv->event_id;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static uint32_t
present_wnmd_query_capabilities(present_screen_priv_ptr screen_priv)63*4882a593Smuzhiyun present_wnmd_query_capabilities(present_screen_priv_ptr screen_priv)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun     return screen_priv->wnmd_info->capabilities;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun static RRCrtcPtr
present_wnmd_get_crtc(present_screen_priv_ptr screen_priv,WindowPtr window)69*4882a593Smuzhiyun present_wnmd_get_crtc(present_screen_priv_ptr screen_priv, WindowPtr window)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun     return (*screen_priv->wnmd_info->get_crtc)(window);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static int
present_wnmd_get_ust_msc(ScreenPtr screen,WindowPtr window,uint64_t * ust,uint64_t * msc)75*4882a593Smuzhiyun present_wnmd_get_ust_msc(ScreenPtr screen, WindowPtr window, uint64_t *ust, uint64_t *msc)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
78*4882a593Smuzhiyun     return (*screen_priv->wnmd_info->get_ust_msc)(window, ust, msc);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun  * When the wait fence or previous flip is completed, it's time
83*4882a593Smuzhiyun  * to re-try the request
84*4882a593Smuzhiyun  */
85*4882a593Smuzhiyun static void
present_wnmd_re_execute(present_vblank_ptr vblank)86*4882a593Smuzhiyun present_wnmd_re_execute(present_vblank_ptr vblank)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun     uint64_t ust = 0, crtc_msc = 0;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun     (void) present_wnmd_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc);
91*4882a593Smuzhiyun     present_wnmd_execute(vblank, ust, crtc_msc);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static void
present_wnmd_flip_try_ready(WindowPtr window)95*4882a593Smuzhiyun present_wnmd_flip_try_ready(WindowPtr window)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
98*4882a593Smuzhiyun     present_vblank_ptr      vblank;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
101*4882a593Smuzhiyun         if (vblank->queued) {
102*4882a593Smuzhiyun             present_wnmd_re_execute(vblank);
103*4882a593Smuzhiyun             return;
104*4882a593Smuzhiyun         }
105*4882a593Smuzhiyun     }
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static void
present_wnmd_free_idle_vblank(present_vblank_ptr vblank)109*4882a593Smuzhiyun present_wnmd_free_idle_vblank(present_vblank_ptr vblank)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun     present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
112*4882a593Smuzhiyun     present_vblank_destroy(vblank);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /*
116*4882a593Smuzhiyun  * Free any left over idle vblanks
117*4882a593Smuzhiyun  */
118*4882a593Smuzhiyun static void
present_wnmd_free_idle_vblanks(WindowPtr window)119*4882a593Smuzhiyun present_wnmd_free_idle_vblanks(WindowPtr window)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun     present_window_priv_ptr         window_priv = present_window_priv(window);
122*4882a593Smuzhiyun     present_vblank_ptr              vblank, tmp;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->idle_queue, event_queue) {
125*4882a593Smuzhiyun         if (vblank->flip)
126*4882a593Smuzhiyun             present_wnmd_free_idle_vblank(vblank);
127*4882a593Smuzhiyun     }
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun     if (window_priv->flip_active) {
130*4882a593Smuzhiyun         present_wnmd_free_idle_vblank(window_priv->flip_active);
131*4882a593Smuzhiyun         window_priv->flip_active = NULL;
132*4882a593Smuzhiyun     }
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static WindowPtr
present_wnmd_toplvl_pixmap_window(WindowPtr window)136*4882a593Smuzhiyun present_wnmd_toplvl_pixmap_window(WindowPtr window)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun     ScreenPtr       screen = window->drawable.pScreen;
139*4882a593Smuzhiyun     PixmapPtr       pixmap = (*screen->GetWindowPixmap)(window);
140*4882a593Smuzhiyun     WindowPtr       w = window;
141*4882a593Smuzhiyun     WindowPtr       next_w;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     while(w->parent) {
144*4882a593Smuzhiyun         next_w = w->parent;
145*4882a593Smuzhiyun         if ( (*screen->GetWindowPixmap)(next_w) != pixmap) {
146*4882a593Smuzhiyun             break;
147*4882a593Smuzhiyun         }
148*4882a593Smuzhiyun         w = next_w;
149*4882a593Smuzhiyun     }
150*4882a593Smuzhiyun     return w;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun void
present_wnmd_set_abort_flip(WindowPtr window)154*4882a593Smuzhiyun present_wnmd_set_abort_flip(WindowPtr window)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun     if (!window_priv->flip_pending->abort_flip) {
159*4882a593Smuzhiyun         window_priv->flip_pending->abort_flip = TRUE;
160*4882a593Smuzhiyun     }
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun static void
present_wnmd_flips_stop(WindowPtr window)164*4882a593Smuzhiyun present_wnmd_flips_stop(WindowPtr window)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
167*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     assert (!window_priv->flip_pending);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     (*screen_priv->wnmd_info->flips_stop) (window);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun     present_wnmd_free_idle_vblanks(window_priv->window);
174*4882a593Smuzhiyun     present_wnmd_flip_try_ready(window_priv->window);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static void
present_wnmd_flip_notify(present_vblank_ptr vblank,uint64_t ust,uint64_t crtc_msc)178*4882a593Smuzhiyun present_wnmd_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun     WindowPtr                   window = vblank->window;
181*4882a593Smuzhiyun     present_window_priv_ptr     window_priv = present_window_priv(window);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun     DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
184*4882a593Smuzhiyun                   vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
185*4882a593Smuzhiyun                   vblank->pixmap ? vblank->pixmap->drawable.id : 0,
186*4882a593Smuzhiyun                   vblank->window ? vblank->window->drawable.id : 0));
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun     assert (vblank == window_priv->flip_pending);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     xorg_list_del(&vblank->event_queue);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun     if (window_priv->flip_active) {
193*4882a593Smuzhiyun         if (window_priv->flip_active->flip_idler)
194*4882a593Smuzhiyun             present_wnmd_free_idle_vblank(window_priv->flip_active);
195*4882a593Smuzhiyun         else
196*4882a593Smuzhiyun             /* Put the previous flip in the idle_queue and wait for further notice from DDX */
197*4882a593Smuzhiyun             xorg_list_append(&window_priv->flip_active->event_queue, &window_priv->idle_queue);
198*4882a593Smuzhiyun     }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun     window_priv->flip_active = vblank;
201*4882a593Smuzhiyun     window_priv->flip_pending = NULL;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     if (vblank->abort_flip)
206*4882a593Smuzhiyun         present_wnmd_flips_stop(window);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun     present_wnmd_flip_try_ready(window);
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun void
present_wnmd_event_notify(WindowPtr window,uint64_t event_id,uint64_t ust,uint64_t msc)212*4882a593Smuzhiyun present_wnmd_event_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun     present_window_priv_ptr     window_priv = present_window_priv(window);
215*4882a593Smuzhiyun     present_vblank_ptr          vblank;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun     if (!window_priv)
218*4882a593Smuzhiyun         return;
219*4882a593Smuzhiyun     if (!event_id)
220*4882a593Smuzhiyun         return;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun     if (window_priv->flip_active && window_priv->flip_active->event_id == event_id) {
223*4882a593Smuzhiyun         /* Notify for active flip, means it is allowed to become idle */
224*4882a593Smuzhiyun         window_priv->flip_active->flip_idler = TRUE;
225*4882a593Smuzhiyun         return;
226*4882a593Smuzhiyun     }
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun     DebugPresent(("\te %" PRIu64 " ust %" PRIu64 " msc %" PRIu64 "\n", event_id, ust, msc));
229*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->exec_queue, event_queue) {
230*4882a593Smuzhiyun         if (event_id == vblank->event_id) {
231*4882a593Smuzhiyun             present_wnmd_execute(vblank, ust, msc);
232*4882a593Smuzhiyun             return;
233*4882a593Smuzhiyun         }
234*4882a593Smuzhiyun     }
235*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
236*4882a593Smuzhiyun         if (vblank->event_id == event_id) {
237*4882a593Smuzhiyun             if (vblank->queued) {
238*4882a593Smuzhiyun                 present_wnmd_execute(vblank, ust, msc);
239*4882a593Smuzhiyun             } else {
240*4882a593Smuzhiyun                 assert(vblank->window);
241*4882a593Smuzhiyun                 present_wnmd_flip_notify(vblank, ust, msc);
242*4882a593Smuzhiyun             }
243*4882a593Smuzhiyun             return;
244*4882a593Smuzhiyun         }
245*4882a593Smuzhiyun     }
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->idle_queue, event_queue) {
248*4882a593Smuzhiyun         if (vblank->event_id == event_id) {
249*4882a593Smuzhiyun             if (vblank->flip)
250*4882a593Smuzhiyun                 present_wnmd_free_idle_vblank(vblank);
251*4882a593Smuzhiyun             else
252*4882a593Smuzhiyun                 /* Copies which were executed but need their completion event sent */
253*4882a593Smuzhiyun                 present_execute_post(vblank, ust, msc);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun             return;
256*4882a593Smuzhiyun         }
257*4882a593Smuzhiyun     }
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun static Bool
present_wnmd_check_flip(RRCrtcPtr crtc,WindowPtr window,PixmapPtr pixmap,Bool sync_flip,RegionPtr valid,int16_t x_off,int16_t y_off,PresentFlipReason * reason)261*4882a593Smuzhiyun present_wnmd_check_flip(RRCrtcPtr           crtc,
262*4882a593Smuzhiyun                         WindowPtr           window,
263*4882a593Smuzhiyun                         PixmapPtr           pixmap,
264*4882a593Smuzhiyun                         Bool                sync_flip,
265*4882a593Smuzhiyun                         RegionPtr           valid,
266*4882a593Smuzhiyun                         int16_t             x_off,
267*4882a593Smuzhiyun                         int16_t             y_off,
268*4882a593Smuzhiyun                         PresentFlipReason   *reason)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun     ScreenPtr               screen = window->drawable.pScreen;
271*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
272*4882a593Smuzhiyun     WindowPtr               toplvl_window = present_wnmd_toplvl_pixmap_window(window);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun     if (reason)
275*4882a593Smuzhiyun         *reason = PRESENT_FLIP_REASON_UNKNOWN;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun     if (!screen_priv)
278*4882a593Smuzhiyun         return FALSE;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun     if (!screen_priv->wnmd_info)
281*4882a593Smuzhiyun         return FALSE;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun     if (!crtc)
284*4882a593Smuzhiyun         return FALSE;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     /* Check to see if the driver supports flips at all */
287*4882a593Smuzhiyun     if (!screen_priv->wnmd_info->flip)
288*4882a593Smuzhiyun         return FALSE;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     /* Source pixmap must align with window exactly */
291*4882a593Smuzhiyun     if (x_off || y_off)
292*4882a593Smuzhiyun         return FALSE;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun     /* Valid area must contain window (for simplicity for now just never flip when one is set). */
295*4882a593Smuzhiyun     if (valid)
296*4882a593Smuzhiyun         return FALSE;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun     /* Flip pixmap must have same dimensions as window */
299*4882a593Smuzhiyun     if (window->drawable.width != pixmap->drawable.width ||
300*4882a593Smuzhiyun             window->drawable.height != pixmap->drawable.height)
301*4882a593Smuzhiyun         return FALSE;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun     /* Window must be same region as toplevel window */
304*4882a593Smuzhiyun     if ( !RegionEqual(&window->winSize, &toplvl_window->winSize) )
305*4882a593Smuzhiyun         return FALSE;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     /* Can't flip if window clipped by children */
308*4882a593Smuzhiyun     if (!RegionEqual(&window->clipList, &window->winSize))
309*4882a593Smuzhiyun         return FALSE;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     /* Ask the driver for permission */
312*4882a593Smuzhiyun     if (screen_priv->wnmd_info->check_flip2) {
313*4882a593Smuzhiyun         if (!(*screen_priv->wnmd_info->check_flip2) (crtc, window, pixmap, sync_flip, reason)) {
314*4882a593Smuzhiyun             DebugPresent(("\td %08" PRIx32 " -> %08" PRIx32 "\n",
315*4882a593Smuzhiyun                           window->drawable.id, pixmap ? pixmap->drawable.id : 0));
316*4882a593Smuzhiyun             return FALSE;
317*4882a593Smuzhiyun         }
318*4882a593Smuzhiyun     }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun     return TRUE;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun /*
324*4882a593Smuzhiyun  * 'window' is being reconfigured. Check to see if it is involved
325*4882a593Smuzhiyun  * in flipping and clean up as necessary.
326*4882a593Smuzhiyun  */
327*4882a593Smuzhiyun static void
present_wnmd_check_flip_window(WindowPtr window)328*4882a593Smuzhiyun present_wnmd_check_flip_window (WindowPtr window)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
331*4882a593Smuzhiyun     present_vblank_ptr      flip_pending;
332*4882a593Smuzhiyun     present_vblank_ptr      flip_active;
333*4882a593Smuzhiyun     present_vblank_ptr      vblank;
334*4882a593Smuzhiyun     PresentFlipReason       reason;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun     /* If this window hasn't ever been used with Present, it can't be
337*4882a593Smuzhiyun      * flipping
338*4882a593Smuzhiyun      */
339*4882a593Smuzhiyun     if (!window_priv)
340*4882a593Smuzhiyun         return;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     flip_pending = window_priv->flip_pending;
343*4882a593Smuzhiyun     flip_active = window_priv->flip_active;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun     if (flip_pending) {
346*4882a593Smuzhiyun         if (!present_wnmd_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap,
347*4882a593Smuzhiyun                                 flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL))
348*4882a593Smuzhiyun             present_wnmd_set_abort_flip(window);
349*4882a593Smuzhiyun     } else if (flip_active) {
350*4882a593Smuzhiyun         if (!present_wnmd_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap,
351*4882a593Smuzhiyun                                      flip_active->sync_flip, flip_active->valid, 0, 0, NULL))
352*4882a593Smuzhiyun             present_wnmd_flips_stop(window);
353*4882a593Smuzhiyun     }
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun     /* Now check any queued vblanks */
356*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
357*4882a593Smuzhiyun         if (vblank->queued && vblank->flip &&
358*4882a593Smuzhiyun                 !present_wnmd_check_flip(vblank->crtc, window, vblank->pixmap,
359*4882a593Smuzhiyun                                          vblank->sync_flip, vblank->valid, 0, 0, &reason)) {
360*4882a593Smuzhiyun             vblank->flip = FALSE;
361*4882a593Smuzhiyun             vblank->reason = reason;
362*4882a593Smuzhiyun         }
363*4882a593Smuzhiyun     }
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun static Bool
present_wnmd_flip(WindowPtr window,RRCrtcPtr crtc,uint64_t event_id,uint64_t target_msc,PixmapPtr pixmap,Bool sync_flip,RegionPtr damage)367*4882a593Smuzhiyun present_wnmd_flip(WindowPtr window,
368*4882a593Smuzhiyun                   RRCrtcPtr crtc,
369*4882a593Smuzhiyun                   uint64_t event_id,
370*4882a593Smuzhiyun                   uint64_t target_msc,
371*4882a593Smuzhiyun                   PixmapPtr pixmap,
372*4882a593Smuzhiyun                   Bool sync_flip,
373*4882a593Smuzhiyun                   RegionPtr damage)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun     ScreenPtr                   screen = window->drawable.pScreen;
376*4882a593Smuzhiyun     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     return (*screen_priv->wnmd_info->flip) (window,
379*4882a593Smuzhiyun                                             crtc,
380*4882a593Smuzhiyun                                             event_id,
381*4882a593Smuzhiyun                                             target_msc,
382*4882a593Smuzhiyun                                             pixmap,
383*4882a593Smuzhiyun                                             sync_flip,
384*4882a593Smuzhiyun                                             damage);
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun static void
present_wnmd_cancel_flip(WindowPtr window)388*4882a593Smuzhiyun present_wnmd_cancel_flip(WindowPtr window)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun     if (window_priv->flip_pending)
393*4882a593Smuzhiyun         present_wnmd_set_abort_flip(window);
394*4882a593Smuzhiyun     else if (window_priv->flip_active)
395*4882a593Smuzhiyun         present_wnmd_flips_stop(window);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun static Bool
present_wnmd_can_window_flip(WindowPtr window)399*4882a593Smuzhiyun present_wnmd_can_window_flip(WindowPtr window)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun     ScreenPtr                   screen = window->drawable.pScreen;
402*4882a593Smuzhiyun     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
403*4882a593Smuzhiyun     WindowPtr                   toplvl_window = present_wnmd_toplvl_pixmap_window(window);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun     if (!screen_priv)
406*4882a593Smuzhiyun         return FALSE;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun     if (!screen_priv->wnmd_info)
409*4882a593Smuzhiyun         return FALSE;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun     /* Check to see if the driver supports flips at all */
412*4882a593Smuzhiyun     if (!screen_priv->wnmd_info->flip)
413*4882a593Smuzhiyun         return FALSE;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun     /* Don't flip redirected windows */
416*4882a593Smuzhiyun     if (window->redirectDraw != RedirectDrawNone)
417*4882a593Smuzhiyun         return FALSE;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun     /* Window must be same region as toplevel window */
420*4882a593Smuzhiyun     if ( !RegionEqual(&window->winSize, &toplvl_window->winSize) )
421*4882a593Smuzhiyun         return FALSE;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun     return TRUE;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun /*
427*4882a593Smuzhiyun  * Once the required MSC has been reached, execute the pending request.
428*4882a593Smuzhiyun  *
429*4882a593Smuzhiyun  * For requests to actually present something, either blt contents to
430*4882a593Smuzhiyun  * the window pixmap or queue a window buffer swap on the backend.
431*4882a593Smuzhiyun  *
432*4882a593Smuzhiyun  * For requests to just get the current MSC/UST combo, skip that part and
433*4882a593Smuzhiyun  * go straight to event delivery.
434*4882a593Smuzhiyun  */
435*4882a593Smuzhiyun static void
present_wnmd_execute(present_vblank_ptr vblank,uint64_t ust,uint64_t crtc_msc)436*4882a593Smuzhiyun present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun     WindowPtr               window = vblank->window;
439*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun     if (present_execute_wait(vblank, crtc_msc))
442*4882a593Smuzhiyun         return;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun     if (vblank->flip && vblank->pixmap && vblank->window) {
445*4882a593Smuzhiyun         if (window_priv->flip_pending) {
446*4882a593Smuzhiyun             DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n",
447*4882a593Smuzhiyun                           vblank->event_id, vblank,
448*4882a593Smuzhiyun                           window_priv->flip_pending));
449*4882a593Smuzhiyun             xorg_list_del(&vblank->event_queue);
450*4882a593Smuzhiyun             xorg_list_append(&vblank->event_queue, &window_priv->flip_queue);
451*4882a593Smuzhiyun             vblank->flip_ready = TRUE;
452*4882a593Smuzhiyun             return;
453*4882a593Smuzhiyun         }
454*4882a593Smuzhiyun     }
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     xorg_list_del(&vblank->event_queue);
457*4882a593Smuzhiyun     xorg_list_del(&vblank->window_list);
458*4882a593Smuzhiyun     vblank->queued = FALSE;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun     if (vblank->pixmap && vblank->window) {
461*4882a593Smuzhiyun         ScreenPtr screen = window->drawable.pScreen;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun         if (vblank->flip) {
464*4882a593Smuzhiyun             RegionPtr damage;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun             DebugPresent(("\tf %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
467*4882a593Smuzhiyun                           vblank->event_id, vblank, crtc_msc,
468*4882a593Smuzhiyun                           vblank->pixmap->drawable.id, vblank->window->drawable.id));
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun             /* Prepare to flip by placing it in the flip queue
471*4882a593Smuzhiyun              */
472*4882a593Smuzhiyun             xorg_list_add(&vblank->event_queue, &window_priv->flip_queue);
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun             /* Set update region as damaged */
475*4882a593Smuzhiyun             if (vblank->update) {
476*4882a593Smuzhiyun                 damage = RegionDuplicate(vblank->update);
477*4882a593Smuzhiyun                 /* Translate update region to screen space */
478*4882a593Smuzhiyun                 assert(vblank->x_off == 0 && vblank->y_off == 0);
479*4882a593Smuzhiyun                 RegionTranslate(damage, window->drawable.x, window->drawable.y);
480*4882a593Smuzhiyun                 RegionIntersect(damage, damage, &window->clipList);
481*4882a593Smuzhiyun             } else
482*4882a593Smuzhiyun                 damage = RegionDuplicate(&window->clipList);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun             /* Try to flip - the vblank is now pending
485*4882a593Smuzhiyun              */
486*4882a593Smuzhiyun             window_priv->flip_pending = vblank;
487*4882a593Smuzhiyun             // ask the driver
488*4882a593Smuzhiyun             if (present_wnmd_flip(vblank->window, vblank->crtc, vblank->event_id,
489*4882a593Smuzhiyun                                      vblank->target_msc, vblank->pixmap, vblank->sync_flip, damage)) {
490*4882a593Smuzhiyun                 WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(vblank->window);
491*4882a593Smuzhiyun                 PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun                 /* Replace window pixmap with flip pixmap */
494*4882a593Smuzhiyun #ifdef COMPOSITE
495*4882a593Smuzhiyun                 vblank->pixmap->screen_x = old_pixmap->screen_x;
496*4882a593Smuzhiyun                 vblank->pixmap->screen_y = old_pixmap->screen_y;
497*4882a593Smuzhiyun #endif
498*4882a593Smuzhiyun                 present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap);
499*4882a593Smuzhiyun                 vblank->pixmap->refcnt++;
500*4882a593Smuzhiyun                 dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun                 /* Report damage */
503*4882a593Smuzhiyun                 DamageDamageRegion(&vblank->window->drawable, damage);
504*4882a593Smuzhiyun                 RegionDestroy(damage);
505*4882a593Smuzhiyun                 return;
506*4882a593Smuzhiyun             }
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun             xorg_list_del(&vblank->event_queue);
509*4882a593Smuzhiyun             /* Flip failed. Clear the flip_pending field
510*4882a593Smuzhiyun               */
511*4882a593Smuzhiyun             window_priv->flip_pending = NULL;
512*4882a593Smuzhiyun             vblank->flip = FALSE;
513*4882a593Smuzhiyun         }
514*4882a593Smuzhiyun         DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
515*4882a593Smuzhiyun                       vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun         present_wnmd_cancel_flip(window);
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun         present_execute_copy(vblank, crtc_msc);
520*4882a593Smuzhiyun         assert(!vblank->queued);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun         if (present_wnmd_queue_vblank(screen, window, vblank->crtc,
523*4882a593Smuzhiyun                                       vblank->event_id, crtc_msc + 1)
524*4882a593Smuzhiyun             == Success) {
525*4882a593Smuzhiyun             xorg_list_add(&vblank->event_queue, &window_priv->idle_queue);
526*4882a593Smuzhiyun             xorg_list_append(&vblank->window_list, &window_priv->vblank);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun             return;
529*4882a593Smuzhiyun         }
530*4882a593Smuzhiyun     }
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun     present_execute_post(vblank, ust, crtc_msc);
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun static uint64_t
present_wnmd_window_to_crtc_msc(WindowPtr window,RRCrtcPtr crtc,uint64_t window_msc,uint64_t new_msc)536*4882a593Smuzhiyun present_wnmd_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun     if (crtc != window_priv->crtc) {
541*4882a593Smuzhiyun         if (window_priv->crtc == PresentCrtcNeverSet) {
542*4882a593Smuzhiyun             window_priv->msc_offset = 0;
543*4882a593Smuzhiyun         } else {
544*4882a593Smuzhiyun             /* The old CRTC may have been turned off, in which case
545*4882a593Smuzhiyun              * we'll just use whatever previous MSC we'd seen from this CRTC
546*4882a593Smuzhiyun              */
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun             window_priv->msc_offset += new_msc - window_priv->msc;
549*4882a593Smuzhiyun         }
550*4882a593Smuzhiyun         window_priv->crtc = crtc;
551*4882a593Smuzhiyun     }
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun     return window_msc + window_priv->msc_offset;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun static int
present_wnmd_pixmap(WindowPtr window,PixmapPtr pixmap,CARD32 serial,RegionPtr valid,RegionPtr update,int16_t x_off,int16_t y_off,RRCrtcPtr target_crtc,SyncFence * wait_fence,SyncFence * idle_fence,uint32_t options,uint64_t window_msc,uint64_t divisor,uint64_t remainder,present_notify_ptr notifies,int num_notifies)557*4882a593Smuzhiyun present_wnmd_pixmap(WindowPtr window,
558*4882a593Smuzhiyun                     PixmapPtr pixmap,
559*4882a593Smuzhiyun                     CARD32 serial,
560*4882a593Smuzhiyun                     RegionPtr valid,
561*4882a593Smuzhiyun                     RegionPtr update,
562*4882a593Smuzhiyun                     int16_t x_off,
563*4882a593Smuzhiyun                     int16_t y_off,
564*4882a593Smuzhiyun                     RRCrtcPtr target_crtc,
565*4882a593Smuzhiyun                     SyncFence *wait_fence,
566*4882a593Smuzhiyun                     SyncFence *idle_fence,
567*4882a593Smuzhiyun                     uint32_t options,
568*4882a593Smuzhiyun                     uint64_t window_msc,
569*4882a593Smuzhiyun                     uint64_t divisor,
570*4882a593Smuzhiyun                     uint64_t remainder,
571*4882a593Smuzhiyun                     present_notify_ptr notifies,
572*4882a593Smuzhiyun                     int num_notifies)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun     uint64_t                    ust = 0;
575*4882a593Smuzhiyun     uint64_t                    target_msc;
576*4882a593Smuzhiyun     uint64_t                    crtc_msc = 0;
577*4882a593Smuzhiyun     int                         ret;
578*4882a593Smuzhiyun     present_vblank_ptr          vblank, tmp;
579*4882a593Smuzhiyun     ScreenPtr                   screen = window->drawable.pScreen;
580*4882a593Smuzhiyun     present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
581*4882a593Smuzhiyun     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun     if (!window_priv)
584*4882a593Smuzhiyun         return BadAlloc;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun     target_crtc = present_wnmd_get_crtc(screen_priv, window);
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun     ret = present_wnmd_get_ust_msc(screen, window, &ust, &crtc_msc);
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun     target_msc = present_wnmd_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun     if (ret == Success) {
593*4882a593Smuzhiyun         /* Stash the current MSC away in case we need it later
594*4882a593Smuzhiyun          */
595*4882a593Smuzhiyun         window_priv->msc = crtc_msc;
596*4882a593Smuzhiyun     }
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun     present_adjust_timings(options,
599*4882a593Smuzhiyun                            &crtc_msc,
600*4882a593Smuzhiyun                            &target_msc,
601*4882a593Smuzhiyun                            divisor,
602*4882a593Smuzhiyun                            remainder);
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun     /*
605*4882a593Smuzhiyun      * Look for a matching presentation already on the list...
606*4882a593Smuzhiyun      */
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun     if (!update && pixmap) {
609*4882a593Smuzhiyun         xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun             if (!vblank->pixmap)
612*4882a593Smuzhiyun                 continue;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun             if (!vblank->queued)
615*4882a593Smuzhiyun                 continue;
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun             if (vblank->target_msc != target_msc)
618*4882a593Smuzhiyun                 continue;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun             present_vblank_scrap(vblank);
621*4882a593Smuzhiyun             if (vblank->flip_ready)
622*4882a593Smuzhiyun                 present_wnmd_re_execute(vblank);
623*4882a593Smuzhiyun         }
624*4882a593Smuzhiyun     }
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun     vblank = present_vblank_create(window,
627*4882a593Smuzhiyun                                    pixmap,
628*4882a593Smuzhiyun                                    serial,
629*4882a593Smuzhiyun                                    valid,
630*4882a593Smuzhiyun                                    update,
631*4882a593Smuzhiyun                                    x_off,
632*4882a593Smuzhiyun                                    y_off,
633*4882a593Smuzhiyun                                    target_crtc,
634*4882a593Smuzhiyun                                    wait_fence,
635*4882a593Smuzhiyun                                    idle_fence,
636*4882a593Smuzhiyun                                    options,
637*4882a593Smuzhiyun                                    &screen_priv->wnmd_info->capabilities,
638*4882a593Smuzhiyun                                    notifies,
639*4882a593Smuzhiyun                                    num_notifies,
640*4882a593Smuzhiyun                                    target_msc,
641*4882a593Smuzhiyun                                    crtc_msc);
642*4882a593Smuzhiyun     if (!vblank)
643*4882a593Smuzhiyun         return BadAlloc;
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun     /* WNMD presentations always complete (at least) one frame after they
646*4882a593Smuzhiyun      * are executed
647*4882a593Smuzhiyun      */
648*4882a593Smuzhiyun     vblank->exec_msc = vblank->target_msc - 1;
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun     xorg_list_append(&vblank->event_queue, &window_priv->exec_queue);
651*4882a593Smuzhiyun     vblank->queued = TRUE;
652*4882a593Smuzhiyun     if (crtc_msc < vblank->exec_msc) {
653*4882a593Smuzhiyun         if (present_wnmd_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success) {
654*4882a593Smuzhiyun             return Success;
655*4882a593Smuzhiyun         }
656*4882a593Smuzhiyun         DebugPresent(("present_queue_vblank failed\n"));
657*4882a593Smuzhiyun     }
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun     present_wnmd_execute(vblank, ust, crtc_msc);
660*4882a593Smuzhiyun     return Success;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun static void
present_wnmd_abort_vblank(ScreenPtr screen,WindowPtr window,RRCrtcPtr crtc,uint64_t event_id,uint64_t msc)664*4882a593Smuzhiyun present_wnmd_abort_vblank(ScreenPtr screen, WindowPtr window, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
667*4882a593Smuzhiyun     present_window_priv_ptr window_priv = present_window_priv(window);
668*4882a593Smuzhiyun     present_vblank_ptr      vblank;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun     (*screen_priv->wnmd_info->abort_vblank) (window, crtc, event_id, msc);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->exec_queue, event_queue) {
673*4882a593Smuzhiyun         if (vblank->event_id == event_id) {
674*4882a593Smuzhiyun             xorg_list_del(&vblank->event_queue);
675*4882a593Smuzhiyun             vblank->queued = FALSE;
676*4882a593Smuzhiyun             return;
677*4882a593Smuzhiyun         }
678*4882a593Smuzhiyun     }
679*4882a593Smuzhiyun     xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
680*4882a593Smuzhiyun         if (vblank->event_id == event_id) {
681*4882a593Smuzhiyun             xorg_list_del(&vblank->event_queue);
682*4882a593Smuzhiyun             vblank->queued = FALSE;
683*4882a593Smuzhiyun             return;
684*4882a593Smuzhiyun         }
685*4882a593Smuzhiyun     }
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun static void
present_wnmd_flip_destroy(ScreenPtr screen)689*4882a593Smuzhiyun present_wnmd_flip_destroy(ScreenPtr screen)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun     /* Cleanup done on window destruction */
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun static void
present_wnmd_flush(WindowPtr window)695*4882a593Smuzhiyun present_wnmd_flush(WindowPtr window)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun     ScreenPtr               screen = window->drawable.pScreen;
698*4882a593Smuzhiyun     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun     (*screen_priv->wnmd_info->flush) (window);
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun void
present_wnmd_init_mode_hooks(present_screen_priv_ptr screen_priv)704*4882a593Smuzhiyun present_wnmd_init_mode_hooks(present_screen_priv_ptr screen_priv)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun     screen_priv->query_capabilities =   &present_wnmd_query_capabilities;
707*4882a593Smuzhiyun     screen_priv->get_crtc           =   &present_wnmd_get_crtc;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun     screen_priv->check_flip         =   &present_wnmd_check_flip;
710*4882a593Smuzhiyun     screen_priv->check_flip_window  =   &present_wnmd_check_flip_window;
711*4882a593Smuzhiyun     screen_priv->can_window_flip    =   &present_wnmd_can_window_flip;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun     screen_priv->present_pixmap     =   &present_wnmd_pixmap;
714*4882a593Smuzhiyun     screen_priv->create_event_id    =   &present_wnmd_create_event_id;
715*4882a593Smuzhiyun     screen_priv->queue_vblank       =   &present_wnmd_queue_vblank;
716*4882a593Smuzhiyun     screen_priv->flush              =   &present_wnmd_flush;
717*4882a593Smuzhiyun     screen_priv->re_execute         =   &present_wnmd_re_execute;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun     screen_priv->abort_vblank       =   &present_wnmd_abort_vblank;
720*4882a593Smuzhiyun     screen_priv->flip_destroy       =   &present_wnmd_flip_destroy;
721*4882a593Smuzhiyun }
722