[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