[PATCH] modesetting: Add vblank synchronization support when using Present.

Jason Ekstrand jason at jlekstrand.net
Fri Dec 12 10:21:35 PST 2014


On Thu, Dec 11, 2014 at 3:16 PM, Kenneth Graunke <kenneth at whitecape.org>
wrote:
>
> modesetting hooked up vblank support for DRI2, but was missing support
> for vblanks in Present.
>
> This is mostly copy and pasted from Keith's code in the intel driver.
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  hw/xfree86/drivers/modesetting/Makefile.am |   1 +
>  hw/xfree86/drivers/modesetting/driver.c    |   5 +
>  hw/xfree86/drivers/modesetting/driver.h    |   6 +
>  hw/xfree86/drivers/modesetting/present.c   | 237
> +++++++++++++++++++++++++++++
>  hw/xfree86/drivers/modesetting/vblank.c    |  18 +++
>  5 files changed, 267 insertions(+)
>  create mode 100644 hw/xfree86/drivers/modesetting/present.c
>
> diff --git a/hw/xfree86/drivers/modesetting/Makefile.am
> b/hw/xfree86/drivers/modesetting/Makefile.am
> index 921ca00..82c4f2f 100644
> --- a/hw/xfree86/drivers/modesetting/Makefile.am
> +++ b/hw/xfree86/drivers/modesetting/Makefile.am
> @@ -50,6 +50,7 @@ modesetting_drv_la_SOURCES = \
>          drmmode_display.h \
>          dumb_bo.c \
>          dumb_bo.h \
> +        present.c \
>          vblank.c \
>          $(NULL)
>
> diff --git a/hw/xfree86/drivers/modesetting/driver.c
> b/hw/xfree86/drivers/modesetting/driver.c
> index 476c814..5dda96b 100644
> --- a/hw/xfree86/drivers/modesetting/driver.c
> +++ b/hw/xfree86/drivers/modesetting/driver.c
> @@ -1113,6 +1113,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
>              xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
>                         "Failed to initialize the DRI2 extension.\n");
>          }
> +
> +        if (!ms_present_screen_init(pScreen)) {
> +            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
> +                       "Failed to initialize the Present extension.\n");
> +        }
>      }
>  #endif
>
> diff --git a/hw/xfree86/drivers/modesetting/driver.h
> b/hw/xfree86/drivers/modesetting/driver.h
> index 4267fa1..3decc3e 100644
> --- a/hw/xfree86/drivers/modesetting/driver.h
> +++ b/hw/xfree86/drivers/modesetting/driver.h
> @@ -114,6 +114,10 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
>                              ms_drm_handler_proc handler,
>                              ms_drm_abort_proc abort);
>
> +void ms_drm_abort(ScrnInfoPtr scrn,
> +                  Bool (*match)(void *data, void *match_data),
> +                  void *match_data);
> +
>  xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
>  xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
>                               xf86CrtcPtr desired, BoxPtr crtc_box_ret);
> @@ -129,3 +133,5 @@ void ms_dri2_close_screen(ScreenPtr screen);
>
>  Bool ms_vblank_screen_init(ScreenPtr screen);
>  void ms_vblank_close_screen(ScreenPtr screen);
> +
> +Bool ms_present_screen_init(ScreenPtr screen);
> diff --git a/hw/xfree86/drivers/modesetting/present.c
> b/hw/xfree86/drivers/modesetting/present.c
> new file mode 100644
> index 0000000..92de421
> --- /dev/null
> +++ b/hw/xfree86/drivers/modesetting/present.c
> @@ -0,0 +1,237 @@
> +/*
> + * Copyright © 2014 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software
> and its
> + * documentation for any purpose is hereby granted without fee, provided
> that
> + * the above copyright notice appear in all copies and that both that
> copyright
> + * notice and this permission notice appear in supporting documentation,
> and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no
> representations
> + * about the suitability of this software for any purpose.  It is
> provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
> SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
> OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
> USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
> PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#ifdef HAVE_DIX_CONFIG_H
> +#include "dix-config.h"
> +#endif
> +
> +#include <assert.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <poll.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <sys/time.h>
> +#include <sys/types.h>
> +#include <time.h>
> +
> +#include <xf86.h>
> +#include <xf86Crtc.h>
> +#include <xf86drm.h>
> +#include <xf86str.h>
> +#include <present.h>
> +
> +#include "driver.h"
>

You need to include galmor.h here.  It won't build for me without it.
--Jason


> +
> +#if 0
> +#define DebugPresent(x) ErrorF x
> +#else
> +#define DebugPresent(x)
> +#endif
> +
> +struct ms_present_vblank_event {
> +    uint64_t        event_id;
> +};
> +
> +static RRCrtcPtr
> +ms_present_get_crtc(WindowPtr window)
> +{
> +    ScreenPtr screen = window->drawable.pScreen;
> +    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
> +    BoxRec box, crtcbox;
> +    xf86CrtcPtr crtc;
> +    RRCrtcPtr randr_crtc = NULL;
> +
> +    box.x1 = window->drawable.x;
> +    box.y1 = window->drawable.y;
> +    box.x2 = box.x1 + window->drawable.width;
> +    box.y2 = box.y1 + window->drawable.height;
> +
> +    crtc = ms_covering_crtc(pScrn, &box, NULL, &crtcbox);
> +
> +    /* Make sure the CRTC is valid and this is the real front buffer */
> +    if (crtc != NULL && !crtc->rotatedData)
> +        randr_crtc = crtc->randr_crtc;
> +
> +    return randr_crtc;
> +}
> +
> +static int
> +ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
> +{
> +    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
> +
> +    return ms_get_crtc_ust_msc(xf86_crtc, ust, msc);
> +}
> +
> +/*
> + * Flush the DRM event queue when full; makes space for new events.
> + */
> +static Bool
> +ms_flush_drm_events(ScreenPtr screen)
> +{
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +
> +    struct pollfd p = { .fd = ms->fd, .events = POLLIN };
> +    int r;
> +
> +    do {
> +            r = poll(&p, 1, 0);
> +    } while (r == -1 && (errno == EINTR || errno == EAGAIN));
> +
> +    if (r <= 0)
> +        return 0;
> +
> +    return drmHandleEvent(ms->fd, &ms->event_context);
> +}
> +
> +/*
> + * Called when the queued vblank event has occurred
> + */
> +static void
> +ms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data)
> +{
> +    struct ms_present_vblank_event *event = data;
> +
> +    present_event_notify(event->event_id, usec, msc);
> +    free(event);
> +}
> +
> +/*
> + * Called when the queued vblank is aborted
> + */
> +static void
> +ms_present_vblank_abort(void *data)
> +{
> +    struct ms_present_vblank_event *event = data;
> +
> +    free(event);
> +}
> +
> +/*
> + * Queue an event to report back to the Present extension when the
> specified
> + * MSC has past
> + */
> +static int
> +ms_present_queue_vblank(RRCrtcPtr crtc,
> +                        uint64_t event_id,
> +                        uint64_t msc)
> +{
> +    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
> +    ScreenPtr screen = crtc->pScreen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
> +    struct ms_present_vblank_event *event;
> +    drmVBlank vbl;
> +    int ret;
> +    uint32_t seq;
> +
> +    event = calloc(sizeof(struct ms_present_vblank_event), 1);
> +    if (!event)
> +        return BadAlloc;
> +    event->event_id = event_id;
> +    seq = ms_drm_queue_alloc(xf86_crtc, event,
> +                             ms_present_vblank_handler,
> +                             ms_present_vblank_abort);
> +    if (!seq) {
> +        free(event);
> +        return BadAlloc;
> +    }
> +
> +    vbl.request.type =
> +        DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT |
> drmmode_crtc->vblank_pipe;
> +    vbl.request.sequence = msc;
> +    vbl.request.signal = seq;
> +    for (;;) {
> +        ret = drmWaitVBlank(ms->fd, &vbl);
> +        if (!ret)
> +            break;
> +        if (errno != EBUSY || !ms_flush_drm_events(screen))
> +            return BadAlloc;
> +    }
> +    DebugPresent(("\t\tiq %lld seq %u msc %llu (hw msc %u)\n",
> +                 (long long) event_id, seq, (long long) msc,
> +                 vbl.request.sequence));
> +    return Success;
> +}
> +
> +static Bool
> +ms_present_event_match(void *data, void *match_data)
> +{
> +    struct ms_present_vblank_event *event = data;
> +    uint64_t *match = match_data;
> +
> +    return *match == event->event_id;
> +}
> +
> +/*
> + * Remove a pending vblank event from the DRM queue so that it is not
> reported
> + * to the extension
> + */
> +static void
> +ms_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
> +{
> +    ScreenPtr screen = crtc->pScreen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +
> +    ms_drm_abort(scrn, ms_present_event_match, &event_id);
> +}
> +
> +/*
> + * Flush our batch buffer when requested by the Present extension.
> + */
> +static void
> +ms_present_flush(WindowPtr window)
> +{
> +    ScreenPtr screen = window->drawable.pScreen;
> +    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    modesettingPtr ms = modesettingPTR(scrn);
> +
> +    if (ms->drmmode.glamor)
> +        glamor_block_handler(screen);
> +}
> +
> +static present_screen_info_rec ms_present_screen_info = {
> +    .version = PRESENT_SCREEN_INFO_VERSION,
> +
> +    .get_crtc = ms_present_get_crtc,
> +    .get_ust_msc = ms_present_get_ust_msc,
> +    .queue_vblank = ms_present_queue_vblank,
> +    .abort_vblank = ms_present_abort_vblank,
> +    .flush = ms_present_flush,
> +
> +    .capabilities = PresentCapabilityNone,
> +    .check_flip = 0,
> +    .flip = 0,
> +    .unflip = 0,
> +};
> +
> +Bool
> +ms_present_screen_init(ScreenPtr screen)
> +{
> +    return present_screen_init(screen, &ms_present_screen_info);
> +}
> diff --git a/hw/xfree86/drivers/modesetting/vblank.c
> b/hw/xfree86/drivers/modesetting/vblank.c
> index 5031ef8..c123205 100644
> --- a/hw/xfree86/drivers/modesetting/vblank.c
> +++ b/hw/xfree86/drivers/modesetting/vblank.c
> @@ -323,6 +323,24 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn)
>  }
>
>  /*
> + * Externally usable abort function that uses a callback to match a single
> + * queued entry to abort
> + */
> +void
> +ms_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void
> *match_data),
> +             void *match_data)
> +{
> +    struct ms_drm_queue *q;
> +
> +    xorg_list_for_each_entry(q, &ms_drm_queue, list) {
> +        if (match(q->data, match_data)) {
> +            ms_drm_abort_one(q);
> +            break;
> +        }
> +    }
> +}
> +
> +/*
>   * General DRM kernel handler. Looks for the matching sequence number in
> the
>   * drm event queue and calls the handler for it.
>   */
> --
> 2.1.3
>
> _______________________________________________
> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.x.org/archives/xorg-devel/attachments/20141212/1a8b2a34/attachment-0001.html>


More information about the xorg-devel mailing list