summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac20
-rw-r--r--src/Makefile.am4
-rw-r--r--src/common_drm.c7
-rw-r--r--src/common_drm.h3
-rw-r--r--src/common_present.c132
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);
+}