[RFC xserver v3 08/11] present: Add hooks for the drivers to create out-fences
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Mon Nov 6 21:42:57 UTC 2017
Drivers need to implement flip_with_fence and flush_with_fence
to create out-fences.
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
configure.ac | 2 +-
include/protocol-versions.h | 2 +-
present/meson.build | 2 +-
present/present.c | 68 +++++++++++++++++++++++++++++++++------------
present/present.h | 10 ++++++-
present/present_priv.h | 2 ++
present/present_request.c | 9 +++++-
7 files changed, 73 insertions(+), 22 deletions(-)
diff --git a/configure.ac b/configure.ac
index 435daf71f..81d18b2e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -755,7 +755,7 @@ DAMAGEPROTO="damageproto >= 1.1"
XCMISCPROTO="xcmiscproto >= 1.2.0"
BIGREQSPROTO="bigreqsproto >= 1.1.0"
XTRANS="xtrans >= 1.3.5"
-PRESENTPROTO="presentproto >= 1.1"
+PRESENTPROTO="presentproto >= 1.2"
dnl List of libraries that require a specific version
LIBAPPLEWM="applewm >= 1.4"
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index 524a630e8..0147c708c 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -69,7 +69,7 @@
/* Present */
#define SERVER_PRESENT_MAJOR_VERSION 1
-#define SERVER_PRESENT_MINOR_VERSION 1
+#define SERVER_PRESENT_MINOR_VERSION 2
/* RandR */
#define SERVER_RANDR_MAJOR_VERSION 1
diff --git a/present/meson.build b/present/meson.build
index cf725302a..66d58bd34 100644
--- a/present/meson.build
+++ b/present/meson.build
@@ -13,7 +13,7 @@ libxserver_present = static_library('libxserver_present',
include_directories: inc,
dependencies: [
common_dep,
- dependency('presentproto', version: '>= 1.1')
+ dependency('presentproto', version: '>= 1.2')
],
c_args: '-DHAVE_XORG_CONFIG_H'
)
diff --git a/present/present.c b/present/present.c
index a6f85fe59..694bee890 100644
--- a/present/present.c
+++ b/present/present.c
@@ -193,24 +193,49 @@ present_check_flip(RRCrtcPtr crtc,
return TRUE;
}
+static void
+present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
+{
+ if (present_fence)
+ present_fence_set_triggered(present_fence);
+ if (window) {
+ DebugPresent(("\ti %08lx\n", pixmap ? pixmap->drawable.id : 0));
+ present_send_idle_notify(window, serial, pixmap, present_fence);
+ }
+}
+
static Bool
present_flip(present_vblank_ptr vblank)
{
ScreenPtr screen = vblank->crtc->pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
- if (vblank->wait_fence &&
+ if ((vblank->notify_fence || vblank->wait_fence) &&
screen_priv->info->flip_with_fence != NULL) {
+ SyncFence *idle_fence = NULL;
Bool ret;
+ if (vblank->notify_fence && screen_priv->flip_idle_fence)
+ idle_fence = present_fence_get_fence(screen_priv->flip_idle_fence);
+
ret = (*screen_priv->info->flip_with_fence) (vblank->crtc,
vblank->event_id,
vblank->target_msc,
vblank->pixmap,
present_fence_get_fence(vblank->wait_fence),
+ idle_fence,
vblank->sync_flip);
+ if (ret && screen_priv->flip_notify_fence) {
+ present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
+ screen_priv->flip_serial, screen_priv->flip_idle_fence);
+ }
+
return ret;
+ } else if (vblank->notify_fence) {
+ /* The driver shouldn't have advertised support for IdleFence capability
+ * or the client should have check for it before using the option */
+ return FALSE;
} else if (vblank->wait_fence) {
if (!present_fence_check_triggered(vblank->wait_fence)) {
/* The can_wait_fence() hook should have returned FALSE before we
@@ -240,17 +265,6 @@ present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_
}
}
-static void
-present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
-{
- if (present_fence)
- present_fence_set_triggered(present_fence);
- if (window) {
- DebugPresent(("\ti %08lx\n", pixmap ? pixmap->drawable.id : 0));
- present_send_idle_notify(window, serial, pixmap, present_fence);
- }
-}
-
RRCrtcPtr
present_get_crtc(WindowPtr window)
{
@@ -297,8 +311,9 @@ present_get_ust_msc(ScreenPtr screen, RRCrtcPtr crtc, uint64_t *ust, uint64_t *m
}
static void
-present_flush(WindowPtr window)
+present_flush(present_vblank_ptr vblank)
{
+ WindowPtr window = vblank->window;
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
@@ -308,7 +323,12 @@ present_flush(WindowPtr window)
if (!screen_priv->info)
return;
- (*screen_priv->info->flush) (window);
+ if (vblank->notify_fence && screen_priv->info->flush_with_fence) {
+ (*screen_priv->info->flush_with_fence) (window,
+ present_fence_get_fence(vblank->idle_fence));
+ } else {
+ (*screen_priv->info->flush) (window);
+ }
}
static int
@@ -389,8 +409,10 @@ present_flip_idle(ScreenPtr screen)
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
if (screen_priv->flip_pixmap) {
- present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
- screen_priv->flip_serial, screen_priv->flip_idle_fence);
+ if (!screen_priv->flip_notify_fence) {
+ present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
+ screen_priv->flip_serial, screen_priv->flip_idle_fence);
+ }
if (screen_priv->flip_idle_fence)
present_fence_destroy(screen_priv->flip_idle_fence);
dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id);
@@ -521,6 +543,7 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
screen_priv->flip_pixmap = vblank->pixmap;
screen_priv->flip_sync = vblank->sync_flip;
screen_priv->flip_idle_fence = vblank->idle_fence;
+ screen_priv->flip_notify_fence = vblank->notify_fence;
vblank->pixmap = NULL;
vblank->idle_fence = NULL;
@@ -824,7 +847,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
* which is then freed, freeing the region
*/
vblank->update = NULL;
- present_flush(window);
+ present_flush(vblank);
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
}
@@ -1024,6 +1047,17 @@ present_pixmap(WindowPtr window,
goto no_mem;
}
+ if (options & PresentOptionIdleFence) {
+ if (vblank->idle_fence == NULL) {
+ vblank->notifies = NULL;
+ present_vblank_destroy(vblank);
+ return BadValue;
+ }
+ if (!(screen_priv->info->capabilities & PresentCapabilityIdleFence))
+ return BadValue;
+ vblank->notify_fence = TRUE;
+ }
+
if (pixmap)
DebugPresent(("q %lld %p %8lld: %08lx -> %08lx (crtc %p) flip %d vsync %d serial %d\n",
vblank->event_id, vblank, target_msc,
diff --git a/present/present.h b/present/present.h
index 2c7175f4a..af8395ad4 100644
--- a/present/present.h
+++ b/present/present.h
@@ -59,6 +59,12 @@ typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uin
*/
typedef void (*present_flush_ptr) (WindowPtr window);
+/* Flush pending drawing on 'window' to the hardware.
+ *
+ * 'idle_fence' should return the out-fence
+ */
+typedef void (*present_flush_with_fence_ptr) (WindowPtr window, SyncFence *idle_fence);
+
/* Check if 'pixmap' is suitable for flipping to 'window'.
*/
typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip);
@@ -89,6 +95,7 @@ typedef Bool (*present_flip_with_fence_ptr) (RRCrtcPtr crtc,
uint64_t target_msc,
PixmapPtr pixmap,
SyncFence *wait_fence,
+ SyncFence *idle_fence,
Bool sync_flip);
/* "unflip" back to the regular screen scanout buffer
@@ -108,7 +115,7 @@ typedef Bool (*present_can_wait_fence_ptr) (RRCrtcPtr crtc,
typedef void (*present_wait_fence_ptr) (RRCrtcPtr crtc,
SyncFence *fence);
-#define PRESENT_SCREEN_INFO_VERSION 2
+#define PRESENT_SCREEN_INFO_VERSION 3
typedef struct present_screen_info {
uint32_t version;
@@ -126,6 +133,7 @@ typedef struct present_screen_info {
present_flip_with_fence_ptr flip_with_fence;
present_can_wait_fence_ptr can_wait_fence;
present_wait_fence_ptr wait_fence;
+ present_flush_with_fence_ptr flush_with_fence;
} present_screen_info_rec, *present_screen_info_ptr;
diff --git a/present/present_priv.h b/present/present_priv.h
index 985780d01..1bfeb62ba 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -77,6 +77,7 @@ struct present_vblank {
Bool abort_flip; /* aborting this flip */
int reason; /* reason for which flip is not possible */
Bool has_suboptimal; /* whether client can support SuboptimalCopy mode */
+ Bool notify_fence; /* send fence with Idle event */
};
typedef struct present_screen_priv {
@@ -97,6 +98,7 @@ typedef struct present_screen_priv {
PixmapPtr flip_pixmap;
present_fence_ptr flip_idle_fence;
Bool flip_sync;
+ Bool flip_notify_fence;
present_screen_info_ptr info;
} present_screen_priv_rec, *present_screen_priv_ptr;
diff --git a/present/present_request.c b/present/present_request.c
index c6afe5fa7..4bad47fd2 100644
--- a/present/present_request.c
+++ b/present/present_request.c
@@ -102,13 +102,20 @@ proc_present_pixmap(ClientPtr client)
VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
- VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
if (stuff->options & ~(PresentAllOptions)) {
client->errorValue = stuff->options;
return BadValue;
}
+ if (stuff->options & PresentOptionIdleFence) {
+ LEGAL_NEW_RESOURCE(stuff->idle_fence, client);
+ ret = SyncCreateFenceFromDMAFenceFD(client, &pixmap->drawable, stuff->idle_fence, -1);
+ if (ret != Success)
+ return ret;
+ }
+ VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
+
/*
* Check to see if remainder is sane
*/
--
2.13.0
More information about the xorg-devel
mailing list