[RFC 5/5] modesetting: Implement page flipping support for Present.

Mario Kleiner mario.kleiner.de at gmail.com
Sun Feb 8 04:55:01 PST 2015


Hi Kenneth,

i reviewed and tested the pageflip patches on top of XOrg 1.17.0.

Testing results so far:

My own pageflip stress tests on Intel HD 4000 Ivybridge mobile,
KDE/KWin, with external timing measurement equipment attached to get
true flip completion time and compare it against the present
timestamps, show it mostly works nicely, with robust and precise onset
time (almost no skipped frames) and precise onset timestamps, so
that's good. Tested both single display and dual-display, on a single
x-screen.

I also stress tested once on nouveau single display, without the
measurement equipment, looked mostly ok.

And i ran it the last few days on Intel HD Ironlake mobile, single
display on KDE/KWin, stress test and regular desktop use, all mostly
good.

However, i had a few crashes, usually after a few hours of light
desktop use, always ending with no backtrace, but :

"[ 11093.538] (WW) modeset(0): flip queue failed: Device or resource busy"

-> There seems to be bugs in the error handling for that path, see my
comments interspersed below in the code for likely reason and fix, so
far untested.

Testing on GNOME-3 once got me a hang at the end of a testing session,
followed by a crash with this backtrace:

[ 38554.786] (EE) Backtrace:
[ 38554.786] (EE) 0: /usr/local/bin/X (xorg_backtrace+0x56) [0x58f246]
[ 38554.786] (EE) 1: /usr/local/bin/X (0x400000+0x193399) [0x593399]
[ 38554.786] (EE) 2: /lib/x86_64-linux-gnu/libc.so.6
(0x7fd28bcfc000+0x36eb0) [0x7fd28bd32eb0]
[ 38554.786] (EE) 3: /usr/local/bin/X (dixDestroyPixmap+0x4) [0x4347a4]
[ 38554.786] (EE) 4: /usr/local/bin/X (0x400000+0x5ba92) [0x45ba92]
[ 38554.786] (EE) 5: /usr/local/bin/X (FreeClientResources+0x6c) [0x45cb4c]
[ 38554.786] (EE) 6: /usr/local/bin/X (CloseDownClient+0x70) [0x438680]
[ 38554.786] (EE) 7: /usr/local/bin/X (0x400000+0x391ee) [0x4391ee]
[ 38554.786] (EE) 8: /usr/local/bin/X (0x400000+0x3d34b) [0x43d34b]
[ 38554.786] (EE) 9: /lib/x86_64-linux-gnu/libc.so.6
(__libc_start_main+0xf5) [0x7fd28bd1dec5]
[ 38554.787] (EE) 10: /usr/local/bin/X (0x400000+0x277ce) [0x4277ce]
[ 38554.787] (EE)
[ 38554.787] (EE) Segmentation fault at address 0xb400000337

Could be unrelated to pageflipping bugs, just triggered by it?

See code below for review comments. Other than those it so far looks good to me.

On 1/29/15, Kenneth Graunke <kenneth at whitecape.org> wrote:
> Based on code by Keith Packard, Eric Anholt, and Jason Ekstrand.
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  hw/xfree86/drivers/modesetting/driver.h          |  10 +
>  hw/xfree86/drivers/modesetting/drmmode_display.c |  33 ++-
>  hw/xfree86/drivers/modesetting/drmmode_display.h |   3 +
>  hw/xfree86/drivers/modesetting/present.c         | 363
> ++++++++++++++++++++++-
>  4 files changed, 404 insertions(+), 5 deletions(-)
>
>  Here's a first stab at implementing page flipping support for the
>  modesetting driver, assuming you're using DRI3/Present.
>
>  I've been running this all day, with cloned eDP and external DP monitors,
>  with and without compositing, and it appears to be working fine.  I haven't
>  seen any tearing with this patch; it was consistently present before while
>  playing a game.  Jason Ekstrand also tested it.  drago01 also tested it on
>  AMD.
>
>  A couple of thoughts:
>  1. The page flipping fields may need to be moved from modesettingRec to
>     drmmode_crtc.  Not sure.
>  2. Do we need to alter drmmode->front_bo at all?
>  3. We can probably do this without Glamor, I just haven't tried it and
>     hooked up the dumb BO stuff properly.  We should.
>  4. DRI2 pageflipping?  I don't see any real point - it's a bunch of extra
>     complexity for no real gain.  DRI3 is working fine.  We do need to port
>     Mesa's EGL code to use DRI3, still, but that's doable.
>  5. Option "Pageflip"...we should probably add one.  And man page updates.
>
>  I doubt this is ready to merge, but I figured I'd send it so people could
>  take a look and provide initial feedback.  This is pretty unfamiliar
>  territory for me, so don't assume I know what I'm doing :)
>
> diff --git a/hw/xfree86/drivers/modesetting/driver.h
> b/hw/xfree86/drivers/modesetting/driver.h
> index 843a105..2d63cae 100644
> --- a/hw/xfree86/drivers/modesetting/driver.h
> +++ b/hw/xfree86/drivers/modesetting/driver.h
> @@ -101,6 +101,16 @@ typedef struct _modesettingRec {
>
>      drmEventContext event_context;
>
> +    /**
> +     * Page flipping stuff.
> +     *  @{
> +     */
> +    int flip_count;
> +    uint64_t fe_msc;
> +    uint64_t fe_usec;
> +    struct ms_present_vblank_event *flip_vblank_event;
> +    /** @} */
> +
>      DamagePtr damage;
>      Bool dirty_enabled;
>
> diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c
> b/hw/xfree86/drivers/modesetting/drmmode_display.c
> index 1ea799b..7fd8669 100644
> --- a/hw/xfree86/drivers/modesetting/drmmode_display.c
> +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
> @@ -50,7 +50,7 @@
>
>  #include "driver.h"
>
> -static int
> +int
>  drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
>  {
>      int ret;
> @@ -71,7 +71,7 @@ drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
>      return 0;
>  }
>
> -static uint32_t
> +uint32_t
>  drmmode_bo_get_pitch(drmmode_bo *bo)
>  {
>  #ifdef GLAMOR_HAS_GBM
> @@ -142,6 +142,35 @@ drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
>  }
>
>  Bool
> +drmmode_bo_for_pixmap(drmmode_ptr drmmode, drmmode_bo *bo, PixmapPtr
> pixmap)
> +{
> +    ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn);
> +    uint16_t pitch;
> +    uint32_t size;
> +    int fd;
> +
> +#ifdef GLAMOR_HAS_GBM
> +    if (drmmode->glamor) {
> +        bo->gbm = glamor_gbm_bo_from_pixmap(screen, pixmap);
> +        bo->dumb = NULL;
> +        return bo->gbm != NULL;
> +    }
> +#endif
> +
> +    fd = glamor_fd_from_pixmap(screen, pixmap, &pitch, &size);
> +    if (fd < 0) {
> +        xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
> +                   "Failed to get fd for flip to new front.\n");
> +        return FALSE;
> +    }
> +
> +    bo->dumb = dumb_get_bo_from_fd(drmmode->fd, fd, pitch, size);
> +    close(fd);
> +
> +    return bo->dumb != NULL;
> +}
> +
> +Bool
>  drmmode_SetSlaveBO(PixmapPtr ppix,
>                     drmmode_ptr drmmode, int fd_handle, int pitch, int size)
>  {
> diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h
> b/hw/xfree86/drivers/modesetting/drmmode_display.h
> index 3a8959a..adc2de6 100644
> --- a/hw/xfree86/drivers/modesetting/drmmode_display.h
> +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
> @@ -139,6 +139,9 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec;
>
>  #define msGetPixmapPriv(drmmode, p)
> ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates,
> &(drmmode)->pixmapPrivateKeyRec))
>
> +Bool drmmode_bo_for_pixmap(drmmode_ptr drmmode, drmmode_bo *bo, PixmapPtr
> pixmap);
> +int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo);
> +uint32_t drmmode_bo_get_pitch(drmmode_bo *bo);
>  uint32_t drmmode_bo_get_handle(drmmode_bo *bo);
>  Bool drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode);
>  void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv);
> diff --git a/hw/xfree86/drivers/modesetting/present.c
> b/hw/xfree86/drivers/modesetting/present.c
> index 359e113..3ca1b94 100644
> --- a/hw/xfree86/drivers/modesetting/present.c
> +++ b/hw/xfree86/drivers/modesetting/present.c
> @@ -44,6 +44,7 @@
>  #include <present.h>
>
>  #include "driver.h"
> +#include "drmmode_display.h"
>
>  #if 0
>  #define DebugPresent(x) ErrorF x
> @@ -206,6 +207,360 @@ ms_present_flush(WindowPtr window)
>  #endif
>  }
>
> +#ifdef GLAMOR
> +struct ms_pageflip {
> +    ScreenPtr screen;
> +    Bool on_reference_crtc;
> +};
> +
> +/**
> + * Notify Present that the flip is complete
> + */
> +static void
> +ms_pageflip_complete(ScreenPtr screen)
> +{
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +    uint64_t event_id = ms->flip_vblank_event->event_id;
> +
> +    DebugPresent(("\t\tms:fc %lld %p c %d msc %llu ust %llu\n",
> +                  (long long) event_id, ms->flip_vblank_event,
> +                  ms->flip_count,
> +                  (long long) ms->fe_msc, (long long) ms->fe_usec));
> +
> +    free(ms->flip_vblank_event);
> +    ms->flip_vblank_event = NULL;
> +
> +    /* Release framebuffer */
> +    drmModeRmFB(ms->fd, ms->drmmode.old_fb_id);
> +
> +    /* Notify Present that the flip is complete. */
> +    present_event_notify(event_id, ms->fe_usec, ms->fe_msc);
> +}
> +
> +/**
> + * Called after processing a pageflip complete event from DRM.
> + *
> + * Update the saved msc/ust values as needed, then check to see if the
> + * whole set of events are complete and notify the application at that
> + * point.
> + */
> +static Bool
> +ms_handle_pageflip(struct ms_pageflip *flip, uint64_t msc, uint64_t usec)
> +{
> +    ScreenPtr screen = flip->screen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +
> +    if (flip->on_reference_crtc) {
> +        /* Cache msc, ust for later delivery with a Present event or
> +         * GLX reply.
> +         */
> +        ms->fe_msc = msc;
> +        ms->fe_usec = usec;
> +    }
> +    free(flip);
> +
> +    ms->flip_count--;
> +
> +    /* Tell the caller if this was the last DRM flip complete event
> expected. */
> +    return ms->flip_count == 0;
> +}
> +
> +/**
> + * Callback for the DRM event queue when a single flip has completed
> + *
> + * Once the flip has been completed on all pipes, notify the
> + * extension code telling it when that happened
> + */
> +static void
> +ms_flip_handler(uint64_t msc, uint64_t ust, void *data)
> +{
> +    struct ms_pageflip *flip = data;
> +    ScreenPtr screen = flip->screen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +    (void) ms;
> +
> +    DebugPresent(("\t\tms:fh %lld %p c %d msc %llu ust %llu\n",
> +                 (long long) ms->flip_vblank_event->event_id,
> +                 ms->flip_vblank_event, ms->flip_count,
> +                 (long long) msc, (long long) ust));
> +
> +    if (ms_handle_pageflip(flip, msc, ust))
> +        ms_pageflip_complete(screen);
> +}
> +
> +/*
> + * Callback for the DRM queue abort code.  A flip has been aborted.
> + */
> +static void
> +ms_present_flip_abort(void *data)
> +{
> +    struct ms_pageflip *flip = data;
> +    ScreenPtr screen = flip->screen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +    struct ms_present_vblank_event *event = ms->flip_vblank_event;
> +
> +    DebugPresent(("\t\tms:fa %lld\n", (long long) event->event_id));
> +
> +    if (ms_handle_pageflip(flip, 0, 0)) {
> +        /* Present abort handling */
> +        free(event);
> +        ms->flip_vblank_event = NULL;
> +
> +        /* Release framebuffer */
> +        drmModeRmFB(ms->drmmode.fd, ms->drmmode.old_fb_id);
> +    }
> +}
> +
> +static Bool
> +queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
> +                   int ref_crtc_vblank_pipe, int new_fb_id, uint32_t flags)
> +{
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +    struct ms_pageflip *flip;
> +    uint32_t seq;
> +    int err;
> +
> +    flip = calloc(1, sizeof(struct ms_pageflip));
> +    if (flip == NULL) {
> +        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
> +                   "flip queue: carrier alloc failed.\n");
> +        return FALSE;
> +    }
> +
> +    /* Only the reference crtc will finally deliver its page flip
> +     * completion event. All other crtc's events will be discarded.
> +     */
> +    flip->on_reference_crtc = (drmmode_crtc->vblank_pipe ==
> ref_crtc_vblank_pipe);
> +    flip->screen = screen;
> +
> +    seq = ms_drm_queue_alloc(crtc, flip, ms_flip_handler,
> ms_present_flip_abort);
> +    if (!seq) {
> +        free(flip);
> +        return FALSE;
> +    }
> +
> +    DebugPresent(("\t\tms:fq %lld %p c %d -> %d seq %llu\n",
> +                  (long long) ms->flip_vblank_event->event_id,
> +                  ms->flip_vblank_event, ms->flip_count, ms->flip_count +
> 1,
> +                  (long long) seq));
> +    assert(ms->flip_count >= 0);
> +    ms->flip_count++;
> +
> +    while (drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
> +                           new_fb_id, flags, (void *) (uintptr_t) seq)) {
> +        err = errno;
> +        /* We may have failed because the event queue was full.  Flush it
> +         * and retry.  If there was nothing to flush, then we failed for
> +         * some other reason and should just return an error.
> +         */
> +        if (ms_flush_drm_events(screen)) {

--> As far as i can see a TRUE return code of ms_flush_drm_events() is
supposed to mean "success", so this should probably be

if (!ms_flush_drm_events(screen)) {

Indeed, ms_present_queue_vblank() takes !ms_flush_drm_events() as
failure instead of success.

I assume this is inspired by intel/uxa and looked at its code. There
seems to be some confusion there as well, which seems to have spilled
over into your pageflip code:
intel_mode_read_drm_events() in intel_display.c reports zero aka false
as success, whereas the intel_present_flush_drm_events() in
intel_present.c reports true as success. The intel_do_pageflip()
routine in intel_display.c seems to do the wrong thing: It retries
queuing a failed pageflip if intel_mode_read_drm_events() returns true
== it failed to flush the event queue, whereas it fails the pageflip
if intel_mode_read_drm_events managed to flush the event queue.

> +            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
> +                       "flip queue failed: %s\n", strerror(err));
> +            ms->flip_count--;
> +            ms_drm_abort_seq(scrn, seq);
> +            free(flip);

--> Afaics, ms_drm_abort_seq() triggers the ms_present_flip_abort()
callback, which itself calls ms_handle_pageflio() which does
ms->flip_count--; and free(flip);, so those instructions seem to be
redundant and would cause an underflowing ms->flip_count and a double
free(flip);

Probably the reason for the infrequent crashes i see when that code path is hit?

A similar problem could be in intel_display.c intel_do_pageflip()
where intel_drm_abort_seq() already seems to free(flip) but then
another free(flip) is there, causing a double free()?

> +            return FALSE;
> +        }
> +
> +        /* We flushed some events, so try again. */
> +        xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n");
> +    }
> +
> +    /* The page flip succeded. */
> +    return TRUE;
> +}
> +
> +
> +static Bool
> +ms_do_pageflip(ScreenPtr screen,
> +               PixmapPtr new_front,
> +               int ref_crtc_vblank_pipe,
> +               Bool async,
> +               uint64_t event_id)
> +{
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
> +    drmmode_bo new_front_bo;
> +    uint32_t new_fb_id;
> +    uint32_t flags;
> +    int i;
> +
> +    glamor_block_handler(screen);
> +
> +    ms->flip_vblank_event = calloc(1, sizeof(struct
> ms_present_vblank_event));
> +    if (!ms->flip_vblank_event)
> +        return FALSE;
> +    ms->flip_vblank_event->event_id = event_id;
> +
> +    new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
> +    new_front_bo.dumb = NULL;
> +    if (!new_front_bo.gbm) {
> +        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
> +                   "Failed to get GBM bo for flip to new front.\n");
> +        free(ms->flip_vblank_event);
> +        ms->flip_vblank_event = NULL;
> +        return FALSE;
> +    }
> +
> +    /* Create a new handle for the back buffer */
> +    if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY,
> +                     scrn->depth, scrn->bitsPerPixel,
> +                     drmmode_bo_get_pitch(&new_front_bo),
> +                     drmmode_bo_get_handle(&new_front_bo), &new_fb_id))
> +        goto error_out;

-> error_out doesn't free(ms->flip_vblank_event); and
ms->flip_vblank_event = NULL; Memory leak?


> +
> +    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
> +
> +    flags = DRM_MODE_PAGE_FLIP_EVENT;
> +    if (async)
> +        flags |= DRM_MODE_PAGE_FLIP_ASYNC;
> +
> +    /* Queue flips on all enabled CRTCs.
> +     *
> +     * Note that if/when we get per-CRTC buffers, we'll have to update
> this.
> +     * Right now it assumes a single shared fb across all CRTCs, with the
> +     * kernel fixing up the offset of each CRTC as necessary.
> +     *
> +     * Also, flips queued on disabled or incorrectly configured displays
> +     * may never complete; this is a configuration error.
> +     */
> +    ms->fe_msc = 0;
> +    ms->fe_usec = 0;
> +
> +    for (i = 0; i < config->num_crtc; i++) {
> +        xf86CrtcPtr crtc = config->crtc[i];
> +
> +        if (!ms_crtc_on(crtc))
> +            continue;
> +
> +        if (!queue_flip_on_crtc(screen, crtc, ref_crtc_vblank_pipe,
> new_fb_id,
> +                                flags)) {
> +            goto error_undo;
> +        }
> +    }

-> queue_flip_on_crtc() has at least one error path where it doesn't
free(ms->flip_vblank_event). Maybe that was partially the purpose of
the currently uncommented intel_crtc_apply() in error_undo?



> +
> +    ms->drmmode.old_fb_id = ms->drmmode.fb_id;
> +    ms->drmmode.fb_id = new_fb_id;
> +
> +    assert(ms->flip_count >= 0);
> +    if (ms->flip_count == 0) {
> +        ms_pageflip_complete(screen);
> +    }
> +
> +    return TRUE;
> +
> +error_undo:
> +    drmModeRmFB(ms->fd, new_fb_id);

--> drmModeRmFB() could get called here even if a few
queue_flip_on_crtc() calls succeeded for a multi-crtc flip, so the FB
would be in use? Not sure though...

Feel free to add a

Reviewed-and-Tested-by: Mario Kleiner <mario.kleiner.de at gmail.com>

for the bits i tested and reviewed if that helps. The other patches in
the series seem to be fine,

thanks,
-mario


> +    for (i = 0; i < config->num_crtc; i++) {
> +        if (config->crtc[i]->enabled) {
> +            ErrorF("XXX: crtc apply\n");
> +            /* intel_crtc_apply(config->crtc[i]); */
> +        }
> +    }
> +
> +error_out:
> +    xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
> +               strerror(errno));
> +
> +    assert(ms->flip_count >= 0);
> +    ms->flip_count = 0;
> +    return FALSE;
> +}
> +
> +/*
> + * Test to see if page flipping is possible on the target crtc
> + */
> +static Bool
> +ms_present_check_flip(RRCrtcPtr crtc,
> +                      WindowPtr window,
> +                      PixmapPtr pixmap,
> +                      Bool sync_flip)
> +{
> +    ScreenPtr screen = window->drawable.pScreen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +
> +    /* We only support page flipping with Glamor, for now. */
> +    if (!ms->drmmode.glamor)
> +        return FALSE;
> +
> +    if (!scrn->vtSema)
> +        return FALSE;
> +
> +    if (ms->drmmode.shadow_enable)
> +        return FALSE;
> +
> +    if (crtc && !ms_crtc_on(crtc->devPrivate))
> +        return FALSE;
> +
> +    /* Check stride, can't change that on flip */
> +    if (pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo))
> +        return FALSE;
> +
> +    /* Make sure there's a bo we can get to */
> +    /* XXX: actually do this.  also...is it sufficient?
> +     * if (!glamor_get_pixmap_private(pixmap))
> +     *     return FALSE;
> +     */
> +
> +    return TRUE;
> +}
> +
> +/*
> + * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is
> true,
> + * then wait for vblank. Otherwise, flip immediately
> + */
> +static Bool
> +ms_present_flip(RRCrtcPtr crtc,
> +                uint64_t event_id,
> +                uint64_t target_msc,
> +                PixmapPtr pixmap,
> +                Bool sync_flip)
> +{
> +    ScreenPtr screen = crtc->pScreen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
> +    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
> +    Bool ret;
> +
> +    if (!ms_present_check_flip(crtc, screen->root, pixmap, sync_flip))
> +        return FALSE;
> +
> +    ret = ms_do_pageflip(screen, pixmap, drmmode_crtc->vblank_pipe,
> !sync_flip,
> +                         event_id);
> +    if (!ret)
> +        xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
> +
> +    return ret;
> +}
> +
> +/*
> + * Queue a flip back to the normal frame buffer
> + */
> +static void
> +ms_present_unflip(ScreenPtr screen, uint64_t event_id)
> +{
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    PixmapPtr pixmap = screen->GetScreenPixmap(screen);
> +    Bool ret;
> +
> +    if (!ms_present_check_flip(NULL, screen->root, pixmap, FALSE))
> +        return;
> +
> +    ret = ms_do_pageflip(screen, pixmap, -1, FALSE, event_id);
> +    if (!ret) {
> +        xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
> +    }
> +}
> +#endif
> +
>  static present_screen_info_rec ms_present_screen_info = {
>      .version = PRESENT_SCREEN_INFO_VERSION,
>
> @@ -216,9 +571,11 @@ static present_screen_info_rec ms_present_screen_info =
> {
>      .flush = ms_present_flush,
>
>      .capabilities = PresentCapabilityNone,
> -    .check_flip = 0,
> -    .flip = 0,
> -    .unflip = 0,
> +    .check_flip = ms_present_check_flip,
> +#ifdef GLAMOR
> +    .flip = ms_present_flip,
> +    .unflip = ms_present_unflip,
> +#endif
>  };
>
>  Bool
> --
> 2.2.2
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel


More information about the xorg-devel mailing list