diff options
-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); +} |