diff options
author | Russell King <rmk@arm.linux.org.uk> | 2015-10-25 20:32:51 +0000 |
---|---|---|
committer | Russell King <rmk@arm.linux.org.uk> | 2015-10-26 19:38:58 +0000 |
commit | 66a869459a2dfc98d402fa71c2e84c3ce88cc9ac (patch) | |
tree | bffedeaa320a16a097c9e1f6a79211d8a973994a | |
parent | 63488a4bf346b23658ac5eefb3438222b8b77c05 (diff) |
src: initial present extension support
Add initial support for the X present extension to the DDX driver.
This allows DRI3 clients to synchronise with the scanout hardware by
waiting for vblank events, and supports reading the current media
stamp counter and monotonic time values.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/common_drm.c | 7 | ||||
-rw-r--r-- | src/common_drm.h | 3 | ||||
-rw-r--r-- | src/common_present.c | 132 |
5 files changed, 166 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 9b13c22..b14d4cf 100644 --- a/configure.ac +++ b/configure.ac @@ -205,6 +205,11 @@ AC_ARG_ENABLE(dri2, AC_HELP_STRING([--disable-dri2], [DRI2="$enableval"], [DRI2=auto]) +AC_ARG_ENABLE(present, AC_HELP_STRING([--disable-present], + [Disable PRESENT support [[default=auto]]]), + [PRESENT="$enableval"], + [PRESENT=auto]) + # Checks for pkg-config packages PKG_CHECK_MODULES(XORG, [xorg-server >= 1.9.99.1 xproto fontsproto]) sdkdir=$(pkg-config --variable=sdkdir xorg-server) @@ -242,6 +247,21 @@ if test x$DRI2 = xyes; then AC_DEFINE(HAVE_DRI2,1,[Enable DRI2 driver support]) fi +PKG_CHECK_MODULES(PRESENT, [presentproto >= 1.0], , PRESENT=no) +if test x$PRESENT != xno; then + save_CFLAGS=$CFLAGS + CFLAGS="$XORG_CFLAGS $PRESENT_CFLAGS" + AC_CHECK_HEADERS([present.h], PRESENT=yes, PRESENT=no, [#include <dixstruct.h>]) + CFLAGS=$save_CFLAGS +fi +AC_MSG_CHECKING([whether to include PRESENT support]) +AM_CONDITIONAL(HAVE_PRESENT, test x$PRESENT = xyes) +AC_MSG_RESULT([$PRESENT]) +if test x$PRESENT = xyes; then + AC_DEFINE(HAVE_PRESENT,1,[Enable PRESENT driver support]) +fi + + # Checks for header files. AC_HEADER_STDC diff --git a/src/Makefile.am b/src/Makefile.am index 82dd108..3afed38 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,3 +38,7 @@ armada_drv_la_SOURCES += \ common_drm_dri2.c \ common_drm_dri2.h endif + +if HAVE_PRESENT +armada_drv_la_SOURCES += common_present.c +endif diff --git a/src/common_drm.c b/src/common_drm.c index 1523694..19110d1 100644 --- a/src/common_drm.c +++ b/src/common_drm.c @@ -36,11 +36,13 @@ enum { OPTION_HW_CURSOR, OPTION_HOTPLUG, + OPTION_PRESENT, }; const OptionInfoRec common_drm_options[] = { { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HOTPLUG, "HotPlug", OPTV_BOOLEAN, {0}, TRUE }, + { OPTION_PRESENT, "Present", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -1156,6 +1158,11 @@ Bool common_drm_PostScreenInit(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct common_drm_info *drm = GET_DRM_INFO(pScrn); +#ifdef HAVE_PRESENT + if (xf86ReturnOptValBool(drm->Options, OPTION_PRESENT, TRUE)) + common_present_init(pScreen); +#endif + pScreen->SaveScreen = xf86SaveScreen; /* software cursor */ diff --git a/src/common_drm.h b/src/common_drm.h index 605ab5c..b55a34b 100644 --- a/src/common_drm.h +++ b/src/common_drm.h @@ -105,4 +105,7 @@ void common_drm_LeaveVT(VT_FUNC_ARGS_DECL); void common_drm_FreeScreen(FREE_SCREEN_ARGS_DECL); +/* Present extension support */ +Bool common_present_init(ScreenPtr pScreen); + #endif diff --git a/src/common_present.c b/src/common_present.c new file mode 100644 index 0000000..44b0427 --- /dev/null +++ b/src/common_present.c @@ -0,0 +1,132 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <xf86drm.h> + +#include "common_drm.h" +#include "common_drm_helper.h" + +#include "present.h" + +struct common_present_event { + struct common_drm_event base; + uint64_t event_id; + struct xorg_list node; +}; + +static struct xorg_list events = { &events, &events }; + +static void common_present_handler(struct common_drm_event *base, + uint64_t msc, unsigned int tv_sec, unsigned int tv_usec) +{ + struct common_present_event *event; + + event = container_of(base, struct common_present_event, base); + + if (!xorg_list_is_empty(&event->node)) { + present_event_notify(event->event_id, + (uint64_t)tv_sec * 1000000 + tv_usec, + msc); + + xorg_list_del(&event->node); + } + free(event); +} + +static RRCrtcPtr common_present_get_crtc(WindowPtr window) +{ + xf86CrtcPtr crtc = common_drm_drawable_covering_crtc(&window->drawable); + + return crtc ? crtc->randr_crtc : NULL; +} + +static int common_present_get_ust_msc(RRCrtcPtr rr_crtc, uint64_t *ust, + uint64_t *msc) +{ + xf86CrtcPtr crtc = rr_crtc->devPrivate; + + return common_drm_get_msc(crtc, ust, msc); +} + +static Bool common_present_queue_vblank(RRCrtcPtr rr_crtc, uint64_t event_id, + uint64_t msc) +{ + xf86CrtcPtr crtc = rr_crtc->devPrivate; + struct common_present_event *event; + int ret; + + event = calloc(1, sizeof *event); + if (!event) + return BadAlloc; + + event->base.crtc = crtc; + event->base.handler = common_present_handler; + event->event_id = event_id; + + ret = common_drm_queue_msc_event(crtc->scrn, crtc, &msc, + __FUNCTION__, FALSE, &event->base); + if (ret == 0) { + xorg_list_append(&event->node, &events); + return Success; + } + + free(event); + + return BadMatch; /* FIXME */ +} + +static void common_present_abort_vblank(RRCrtcPtr rr_crtc, uint64_t event_id, + uint64_t msc) +{ + struct common_present_event *event; + + xorg_list_for_each_entry(event, &events, node) { + if (event->event_id == event_id) { + /* + * Cancel the event by taking it off the events list. + * We still expect DRM to trigger the event. + */ + xorg_list_del(&event->node); + xorg_list_init(&event->node); + break; + } + } +} + +static void common_present_flush(WindowPtr window) +{ + /* Flush queued rendering - and wait for it? */ +} + +//static Bool common_present_check_flip(RRCrtcPtr crtc, WindowPtr window, +// PixmapPtr pixmap, Bool sync_flip) +//{ +//} + +//static Bool common_present_flip(RRCrtcPtr crtc, uint64_t event_id, +// uint64_t target_msc, PixmapPtr pixmap, Bool sync_flip) +//{ +//} + +//static void common_present_unflip(ScreenPtr screen, uint64_t event_id) +//{ +//} + +static present_screen_info_rec common_present_screen_info = { + .version = PRESENT_SCREEN_INFO_VERSION, + .get_crtc = common_present_get_crtc, + .get_ust_msc = common_present_get_ust_msc, + .queue_vblank = common_present_queue_vblank, + .abort_vblank = common_present_abort_vblank, + .flush = common_present_flush, + .capabilities = PresentCapabilityNone, +// .check_flip = common_present_check_flip, +// .flip = common_present_flip, +// .unflip = common_present_unflip, +}; + +Bool common_present_init(ScreenPtr pScreen) +{ + return present_screen_init(pScreen, &common_present_screen_info); +} |