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

Jason Ekstrand jason at jlekstrand.net
Fri Dec 12 14:21:57 PST 2014


Another note: With this patch, I had an issue that, when it woke my monitor
up after a lock, it was entirely black + cursor.  VT switching didn't
help.  I killed gnome shell and, when I came back things were mostly OK
except it was tearing like crazy.  Not sure if it's related, but I haven't
seen it without the patch.
--Jason

On Fri, Dec 12, 2014 at 10:21 AM, Jason Ekstrand <jason at jlekstrand.net>
wrote:
>
>
>
> 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/18c7d8b4/attachment-0001.html>


More information about the xorg-devel mailing list