diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2021-04-21 12:50:02 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2021-07-09 16:11:22 +0200 |
commit | b6419359b6b11ec659f59cc74075fcf049591425 (patch) | |
tree | 0cf6c308a345be543567b2c8b72e26e26dc0f8d2 /hw/xwayland/xwayland-present.c | |
parent | c35a716b02921e2fcae5fe89295a99c6dd5dec8c (diff) |
present: Move present_wnmd.c contents to hw/xwayland/xwayland-present.c
This will allow eliminating indirections and making the Xwayland Present
code more efficient and easier to follow.
While this technically changes the Xorg video driver ABI, I don't know
of any drivers using the dropped present_wnmd_* symbols, and I doubt a
Xorg driver could make use of them as is anyway.
(As a bonus, Xorg no longer links any Xwayland specific Present code)
v2:
* Wrap DestroyWindow before initializing Present, so that
present_destroy_window runs before xwl_present_cleanup. Avoids crash
due to present_destroy_window calling xwl_present_* functions when
xwl_present_window was already freed. (Olivier Fourdan)
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Diffstat (limited to 'hw/xwayland/xwayland-present.c')
-rw-r--r-- | hw/xwayland/xwayland-present.c | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index 83d67517a..ca0de1516 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -43,6 +43,8 @@ #define TIMER_LEN_COPY 17 // ~60fps #define TIMER_LEN_FLIP 1000 // 1fps +static uint64_t present_wnmd_event_id; + static DevPrivateKeyRec xwl_present_window_private_key; static struct xwl_present_window * @@ -69,6 +71,9 @@ xwl_present_window_get_priv(WindowPtr window) xorg_list_init(&xwl_present_window->frame_callback_list); xorg_list_init(&xwl_present_window->wait_list); xorg_list_init(&xwl_present_window->release_list); + xorg_list_init(&xwl_present_window->exec_queue); + xorg_list_init(&xwl_present_window->flip_queue); + xorg_list_init(&xwl_present_window->idle_queue); dixSetPrivate(&window->devPrivates, &xwl_present_window_private_key, @@ -117,6 +122,722 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) } } + +static void +present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); + +static int +present_wnmd_queue_vblank(ScreenPtr screen, + WindowPtr window, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + return (*screen_priv->wnmd_info->queue_vblank) (window, crtc, event_id, msc); +} + +static uint32_t +present_wnmd_query_capabilities(present_screen_priv_ptr screen_priv) +{ + return screen_priv->wnmd_info->capabilities; +} + +static RRCrtcPtr +present_wnmd_get_crtc(present_screen_priv_ptr screen_priv, WindowPtr window) +{ + return (*screen_priv->wnmd_info->get_crtc)(window); +} + +static int +present_wnmd_get_ust_msc(ScreenPtr screen, WindowPtr window, uint64_t *ust, uint64_t *msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + return (*screen_priv->wnmd_info->get_ust_msc)(window, ust, msc); +} + +/* + * When the wait fence or previous flip is completed, it's time + * to re-try the request + */ +static void +present_wnmd_re_execute(present_vblank_ptr vblank) +{ + uint64_t ust = 0, crtc_msc = 0; + + (void) present_wnmd_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc); + present_wnmd_execute(vblank, ust, crtc_msc); +} + +static void +present_wnmd_flip_try_ready(WindowPtr window) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_vblank_ptr vblank; + + xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) { + if (vblank->queued) { + present_wnmd_re_execute(vblank); + return; + } + } +} + +static void +present_wnmd_free_idle_vblank(present_vblank_ptr vblank) +{ + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_vblank_destroy(vblank); +} + +/* + * Free any left over idle vblanks + */ +static void +present_wnmd_free_idle_vblanks(WindowPtr window) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_vblank_ptr vblank, tmp; + + xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->idle_queue, event_queue) { + present_wnmd_free_idle_vblank(vblank); + } + + if (xwl_present_window->flip_active) { + present_wnmd_free_idle_vblank(xwl_present_window->flip_active); + xwl_present_window->flip_active = NULL; + } +} + +static WindowPtr +present_wnmd_toplvl_pixmap_window(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + PixmapPtr pixmap = (*screen->GetWindowPixmap)(window); + WindowPtr w = window; + WindowPtr next_w; + + while(w->parent) { + next_w = w->parent; + if ( (*screen->GetWindowPixmap)(next_w) != pixmap) { + break; + } + w = next_w; + } + return w; +} + +static void +present_wnmd_flips_stop(WindowPtr window) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen); + + assert (!xwl_present_window->flip_pending); + + (*screen_priv->wnmd_info->flips_stop) (window); + + present_wnmd_free_idle_vblanks(window); + present_wnmd_flip_try_ready(window); +} + +static void +present_wnmd_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + + DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", + vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window ? vblank->window->drawable.id : 0)); + + assert (vblank == xwl_present_window->flip_pending); + + xorg_list_del(&vblank->event_queue); + + if (xwl_present_window->flip_active) { + if (xwl_present_window->flip_active->flip_idler) + present_wnmd_free_idle_vblank(xwl_present_window->flip_active); + else + /* Put the previous flip in the idle_queue and wait for further notice from + * the Wayland compositor + */ + xorg_list_append(&xwl_present_window->flip_active->event_queue, &xwl_present_window->idle_queue); + } + + xwl_present_window->flip_active = vblank; + xwl_present_window->flip_pending = NULL; + + present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); + + if (vblank->abort_flip) + present_wnmd_flips_stop(window); + + present_wnmd_flip_try_ready(window); +} + +static void +present_wnmd_event_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr vblank; + + if (!window_priv) + return; + if (!event_id) + return; + + DebugPresent(("\te %" PRIu64 " ust %" PRIu64 " msc %" PRIu64 "\n", event_id, ust, msc)); + xorg_list_for_each_entry(vblank, &xwl_present_window->exec_queue, event_queue) { + if (event_id == vblank->event_id) { + present_wnmd_execute(vblank, ust, msc); + return; + } + } + xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) { + if (vblank->event_id == event_id) { + assert(vblank->queued); + present_wnmd_execute(vblank, ust, msc); + return; + } + } + + /* Copies which were executed but need their completion event sent */ + xorg_list_for_each_entry(vblank, &xwl_present_window->idle_queue, event_queue) { + if (vblank->event_id == event_id) { + present_execute_post(vblank, ust, msc); + return; + } + } +} + +static void +present_wnmd_flip_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_vblank_ptr vblank; + + xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) { + if (vblank->event_id == event_id) { + assert(!vblank->queued); + assert(vblank->window); + present_wnmd_flip_notify_vblank(vblank, ust, msc); + return; + } + } +} + +static void +present_wnmd_idle_notify(WindowPtr window, uint64_t event_id) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_vblank_ptr vblank; + + if (xwl_present_window->flip_active && xwl_present_window->flip_active->event_id == event_id) { + /* Active flip is allowed to become idle directly when it becomes unactive again. */ + xwl_present_window->flip_active->flip_idler = TRUE; + return; + } + + xorg_list_for_each_entry(vblank, &xwl_present_window->idle_queue, event_queue) { + if (vblank->event_id == event_id) { + present_wnmd_free_idle_vblank(vblank); + return; + } + } + + xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) { + if (vblank->event_id == event_id) { + vblank->flip_idler = TRUE; + return; + } + } +} + +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) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(window); + + if (reason) + *reason = PRESENT_FLIP_REASON_UNKNOWN; + + if (!screen_priv) + return FALSE; + + if (!screen_priv->wnmd_info) + return FALSE; + + if (!crtc) + return FALSE; + + /* Check to see if the driver supports flips at all */ + if (!screen_priv->wnmd_info->flip) + return FALSE; + + /* Source pixmap must align with window exactly */ + if (x_off || y_off) + return FALSE; + + /* Valid area must contain window (for simplicity for now just never flip when one is set). */ + if (valid) + return FALSE; + + /* Flip pixmap must have same dimensions as window */ + if (window->drawable.width != pixmap->drawable.width || + window->drawable.height != pixmap->drawable.height) + return FALSE; + + /* Window must be same region as toplevel window */ + if ( !RegionEqual(&window->winSize, &toplvl_window->winSize) ) + return FALSE; + + /* Can't flip if window clipped by children */ + if (!RegionEqual(&window->clipList, &window->winSize)) + return FALSE; + + /* Ask the driver for permission */ + if (screen_priv->wnmd_info->check_flip2) { + if (!(*screen_priv->wnmd_info->check_flip2) (crtc, window, pixmap, sync_flip, reason)) { + DebugPresent(("\td %08" PRIx32 " -> %08" PRIx32 "\n", + window->drawable.id, pixmap ? pixmap->drawable.id : 0)); + return FALSE; + } + } + + return TRUE; +} + +/* + * 'window' is being reconfigured. Check to see if it is involved + * in flipping and clean up as necessary. + */ +static void +present_wnmd_check_flip_window (WindowPtr window) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr flip_pending; + present_vblank_ptr flip_active; + present_vblank_ptr vblank; + PresentFlipReason reason; + + /* If this window hasn't ever been used with Present, it can't be + * flipping + */ + if (!xwl_present_window || !window_priv) + return; + + flip_pending = xwl_present_window->flip_pending; + flip_active = xwl_present_window->flip_active; + + if (flip_pending) { + if (!present_wnmd_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap, + flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL)) + xwl_present_window->flip_pending->abort_flip = TRUE; + } else if (flip_active) { + if (!present_wnmd_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap, + flip_active->sync_flip, flip_active->valid, 0, 0, NULL)) + present_wnmd_flips_stop(window); + } + + /* Now check any queued vblanks */ + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + if (vblank->queued && vblank->flip && + !present_wnmd_check_flip(vblank->crtc, window, vblank->pixmap, + vblank->sync_flip, vblank->valid, 0, 0, &reason)) { + vblank->flip = FALSE; + vblank->reason = reason; + } + } +} + +/* + * Clean up any pending or current flips for this window + */ +static void +present_wnmd_clear_window_flip(WindowPtr window) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); + present_vblank_ptr vblank, tmp; + + xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->flip_queue, event_queue) { + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_vblank_destroy(vblank); + } + + xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->idle_queue, event_queue) { + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_vblank_destroy(vblank); + } + + vblank = xwl_present_window->flip_active; + if (vblank) { + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_vblank_destroy(vblank); + } + xwl_present_window->flip_active = NULL; +} + +static Bool +present_wnmd_flip(WindowPtr window, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip, + RegionPtr damage) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + return (*screen_priv->wnmd_info->flip) (window, + crtc, + event_id, + target_msc, + pixmap, + sync_flip, + damage); +} + +static void +present_wnmd_cancel_flip(WindowPtr window) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + + if (xwl_present_window->flip_pending) + xwl_present_window->flip_pending->abort_flip = TRUE; + else if (xwl_present_window->flip_active) + present_wnmd_flips_stop(window); +} + +/* + * Once the required MSC has been reached, execute the pending request. + * + * For requests to actually present something, either blt contents to + * the window pixmap or queue a window buffer swap on the backend. + * + * For requests to just get the current MSC/UST combo, skip that part and + * go straight to event delivery. + */ +static void +present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); + present_window_priv_ptr window_priv = present_window_priv(window); + + if (present_execute_wait(vblank, crtc_msc)) + return; + + if (vblank->flip && vblank->pixmap && vblank->window) { + if (xwl_present_window->flip_pending) { + DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n", + vblank->event_id, vblank, + xwl_present_window->flip_pending)); + xorg_list_del(&vblank->event_queue); + xorg_list_append(&vblank->event_queue, &xwl_present_window->flip_queue); + vblank->flip_ready = TRUE; + return; + } + } + + xorg_list_del(&vblank->event_queue); + xorg_list_del(&vblank->window_list); + vblank->queued = FALSE; + + if (vblank->pixmap && vblank->window) { + ScreenPtr screen = window->drawable.pScreen; + + if (vblank->flip) { + RegionPtr damage; + + DebugPresent(("\tf %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", + vblank->event_id, vblank, crtc_msc, + vblank->pixmap->drawable.id, vblank->window->drawable.id)); + + /* Prepare to flip by placing it in the flip queue + */ + xorg_list_add(&vblank->event_queue, &xwl_present_window->flip_queue); + + /* Set update region as damaged */ + if (vblank->update) { + damage = RegionDuplicate(vblank->update); + /* Translate update region to screen space */ + assert(vblank->x_off == 0 && vblank->y_off == 0); + RegionTranslate(damage, window->drawable.x, window->drawable.y); + RegionIntersect(damage, damage, &window->clipList); + } else + damage = RegionDuplicate(&window->clipList); + + /* Try to flip - the vblank is now pending + */ + xwl_present_window->flip_pending = vblank; + // ask the driver + if (present_wnmd_flip(vblank->window, vblank->crtc, vblank->event_id, + vblank->target_msc, vblank->pixmap, vblank->sync_flip, damage)) { + WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(vblank->window); + PixmapPtr old_pixmap = screen->GetWindowPixmap(window); + + /* Replace window pixmap with flip pixmap */ +#ifdef COMPOSITE + vblank->pixmap->screen_x = old_pixmap->screen_x; + vblank->pixmap->screen_y = old_pixmap->screen_y; +#endif + present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap); + vblank->pixmap->refcnt++; + dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id); + + /* Report damage */ + DamageDamageRegion(&vblank->window->drawable, damage); + RegionDestroy(damage); + return; + } + + xorg_list_del(&vblank->event_queue); + /* Flip failed. Clear the flip_pending field + */ + xwl_present_window->flip_pending = NULL; + vblank->flip = FALSE; + } + DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", + vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + + present_wnmd_cancel_flip(window); + + present_execute_copy(vblank, crtc_msc); + assert(!vblank->queued); + + if (present_wnmd_queue_vblank(screen, window, vblank->crtc, + vblank->event_id, crtc_msc + 1) + == Success) { + xorg_list_add(&vblank->event_queue, &xwl_present_window->idle_queue); + xorg_list_append(&vblank->window_list, &window_priv->vblank); + + return; + } + } + + present_execute_post(vblank, ust, crtc_msc); +} + +static void +present_wnmd_update_window_crtc(WindowPtr window, RRCrtcPtr crtc, uint64_t new_msc) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + /* Crtc unchanged, no offset. */ + if (crtc == window_priv->crtc) + return; + + /* No crtc earlier to offset against, just set the crtc. */ + if (window_priv->crtc == PresentCrtcNeverSet) { + window_priv->msc_offset = 0; + window_priv->crtc = crtc; + return; + } + + /* In window-mode the last correct msc-offset is always kept + * in window-priv struct because msc is saved per window and + * not per crtc as in screen-mode. + */ + window_priv->msc_offset += new_msc - window_priv->msc; + window_priv->crtc = crtc; +} + +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 target_window_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies) +{ + uint64_t ust = 0; + uint64_t target_msc; + uint64_t crtc_msc = 0; + int ret; + present_vblank_ptr vblank, tmp; + ScreenPtr screen = window->drawable.pScreen; + struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!window_priv) + return BadAlloc; + + target_crtc = present_wnmd_get_crtc(screen_priv, window); + + ret = present_wnmd_get_ust_msc(screen, window, &ust, &crtc_msc); + + present_wnmd_update_window_crtc(window, target_crtc, crtc_msc); + + if (ret == Success) { + /* Stash the current MSC away in case we need it later + */ + window_priv->msc = crtc_msc; + } + + target_msc = present_get_target_msc(target_window_msc + window_priv->msc_offset, + crtc_msc, + divisor, + remainder, + options); + + /* + * Look for a matching presentation already on the list... + */ + + if (!update && pixmap) { + xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { + + if (!vblank->pixmap) + continue; + + if (!vblank->queued) + continue; + + if (vblank->target_msc != target_msc) + continue; + + present_vblank_scrap(vblank); + if (vblank->flip_ready) + present_wnmd_re_execute(vblank); + } + } + + vblank = present_vblank_create(window, + pixmap, + serial, + valid, + update, + x_off, + y_off, + target_crtc, + wait_fence, + idle_fence, + options, + screen_priv->wnmd_info->capabilities, + notifies, + num_notifies, + target_msc, + crtc_msc); + if (!vblank) + return BadAlloc; + + vblank->event_id = ++present_wnmd_event_id; + + /* WNMD presentations always complete (at least) one frame after they + * are executed + */ + vblank->exec_msc = vblank->target_msc - 1; + + xorg_list_append(&vblank->event_queue, &xwl_present_window->exec_queue); + vblank->queued = TRUE; + if (crtc_msc < vblank->exec_msc) { + if (present_wnmd_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success) { + return Success; + } + DebugPresent(("present_queue_vblank failed\n")); + } + + present_wnmd_execute(vblank, ust, crtc_msc); + return Success; +} + +static void +present_wnmd_abort_vblank(ScreenPtr screen, WindowPtr window, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) +{ + struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_vblank_ptr vblank; + + (*screen_priv->wnmd_info->abort_vblank) (window, crtc, event_id, msc); + + xorg_list_for_each_entry(vblank, &xwl_present_window->exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + vblank->queued = FALSE; + return; + } + } + xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + vblank->queued = FALSE; + return; + } + } +} + +static void +present_wnmd_flush(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + (*screen_priv->wnmd_info->flush) (window); +} + +/* + * Initialize a screen for use with present in window flip mode (wnmd) + */ +static int +present_wnmd_screen_init(ScreenPtr screen, present_wnmd_info_ptr info) +{ + present_screen_priv_ptr screen_priv; + + if (!present_screen_register_priv_keys()) + return FALSE; + + if (present_screen_priv(screen)) + return TRUE; + + screen_priv = present_screen_priv_init(screen); + if (!screen_priv) + return FALSE; + + screen_priv->wnmd_info = info; + + screen_priv->query_capabilities = &present_wnmd_query_capabilities; + screen_priv->get_crtc = &present_wnmd_get_crtc; + + screen_priv->check_flip = &present_wnmd_check_flip; + screen_priv->check_flip_window = &present_wnmd_check_flip_window; + screen_priv->clear_window_flip = &present_wnmd_clear_window_flip; + + screen_priv->present_pixmap = &present_wnmd_pixmap; + screen_priv->queue_vblank = &present_wnmd_queue_vblank; + screen_priv->flush = &present_wnmd_flush; + screen_priv->re_execute = &present_wnmd_re_execute; + + screen_priv->abort_vblank = &present_wnmd_abort_vblank; + + return TRUE; +} + + static void xwl_present_release_pixmap(struct xwl_present_event *event) { |