[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