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