Add 'check_flip2' hook for driver to let know the core about why flipping is not possible ('reason'). If it is because of unsupported buffer format/modifier, a PresentCompleteNotify event is sent to the client with the PresentCompleteModeSuboptimalCopy mode.
v4: It replaces the old mechanism for format renegotiation Signed-off-by: Louis-Francis Ratté-Boulianne <l...@collabora.com> squash: present send a PresentWindowCrtc --- configure.ac | 2 +- include/protocol-versions.h | 2 +- present/meson.build | 2 +- present/present.c | 34 ++++++++++++++++++++++++---------- present/present.h | 10 +++++++++- present/present_priv.h | 1 + 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 342b07f94..7fb1c99ab 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.0" +PRESENTPROTO="presentproto >= 1.1" 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 b4498927b..fd8d8df88 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 0 +#define SERVER_PRESENT_MINOR_VERSION 1 /* RandR */ #define SERVER_RANDR_MAJOR_VERSION 1 diff --git a/present/meson.build b/present/meson.build index a4296ca7a..cf725302a 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.0') + dependency('presentproto', version: '>= 1.1') ], c_args: '-DHAVE_XORG_CONFIG_H' ) diff --git a/present/present.c b/present/present.c index 176e89c0b..4d38d2d84 100644 --- a/present/present.c +++ b/present/present.c @@ -124,7 +124,8 @@ present_check_flip(RRCrtcPtr crtc, Bool sync_flip, RegionPtr valid, int16_t x_off, - int16_t y_off) + int16_t y_off, + int *reason) { ScreenPtr screen = window->drawable.pScreen; PixmapPtr window_pixmap; @@ -177,7 +178,12 @@ present_check_flip(RRCrtcPtr crtc, } /* Ask the driver for permission */ - if (screen_priv->info->check_flip) { + if (screen_priv->info->check_flip2 && reason) { + if (!(*screen_priv->info->check_flip2) (crtc, window, pixmap, sync_flip, reason)) { + DebugPresent(("\td %08lx -> %08lx\n", window->drawable.id, pixmap ? pixmap->drawable.id : 0)); + return FALSE; + } + } else if (screen_priv->info->check_flip) { if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) { DebugPresent(("\td %08lx -> %08lx\n", window->drawable.id, pixmap ? pixmap->drawable.id : 0)); return FALSE; @@ -564,6 +570,7 @@ present_check_flip_window (WindowPtr window) present_window_priv_ptr window_priv = present_window_priv(window); present_vblank_ptr flip_pending = screen_priv->flip_pending; present_vblank_ptr vblank; + int reason = 0; /* If this window hasn't ever been used with Present, it can't be * flipping @@ -580,7 +587,7 @@ present_check_flip_window (WindowPtr window) */ if (flip_pending->window == window) { if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap, - flip_pending->sync_flip, NULL, 0, 0)) + flip_pending->sync_flip, NULL, 0, 0, NULL)) present_set_abort_flip(screen); } } else { @@ -588,15 +595,16 @@ present_check_flip_window (WindowPtr window) * Check current flip */ if (window == screen_priv->flip_window) { - if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, screen_priv->flip_sync, NULL, 0, 0)) + if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, screen_priv->flip_sync, NULL, 0, 0, NULL)) present_unflip(screen); } } /* Now check any queued vblanks */ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { - if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0)) { + if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0, &reason)) { vblank->flip = FALSE; + vblank->reason = reason; if (vblank->sync_flip) vblank->requeue = TRUE; } @@ -756,10 +764,14 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) /* Compute correct CompleteMode */ if (vblank->kind == PresentCompleteKindPixmap) { - if (vblank->pixmap && vblank->window) - mode = PresentCompleteModeCopy; - else + if (vblank->pixmap && vblank->window) { + if (vblank->reason == PresentFlipReasonBufferFormat) + mode = PresentCompleteModeSuboptimalCopy; + else + mode = PresentCompleteModeCopy; + } else { mode = PresentCompleteModeSkip; + } } else mode = PresentCompleteModeCopy; @@ -795,6 +807,7 @@ present_pixmap(WindowPtr window, ScreenPtr screen = window->drawable.pScreen; present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); present_screen_priv_ptr screen_priv = present_screen_priv(screen); + int reason = 0; if (!window_priv) return BadAlloc; @@ -917,17 +930,18 @@ present_pixmap(WindowPtr window, !(options & PresentOptionCopy) && screen_priv->info) { if (msc_is_after(target_msc, crtc_msc) && - present_check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off)) + present_check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason)) { vblank->flip = TRUE; vblank->sync_flip = TRUE; target_msc--; } else if ((screen_priv->info->capabilities & PresentCapabilityAsync) && - present_check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off)) + present_check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason)) { vblank->flip = TRUE; } } + vblank->reason = reason; if (wait_fence) { vblank->wait_fence = present_fence_create(wait_fence); diff --git a/present/present.h b/present/present.h index aab2e168a..094946a7c 100644 --- a/present/present.h +++ b/present/present.h @@ -27,6 +27,9 @@ #include "randrstr.h" #include "presentext.h" +#define PresentFlipReasonUnknown 0 +#define PresentFlipReasonBufferFormat 1 + typedef struct present_vblank present_vblank_rec, *present_vblank_ptr; /* Return the current CRTC for 'window'. @@ -59,6 +62,10 @@ typedef void (*present_flush_ptr) (WindowPtr window); */ typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip); +/* Same as 'check_flip' but it can return a 'reason' why the flip would fail. + */ +typedef Bool (*present_check_flip2_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip, int *reason); + /* Flip pixmap, return false if it didn't happen. * * 'crtc' is to be used for any necessary synchronization. @@ -83,7 +90,7 @@ typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc, typedef void (*present_unflip_ptr) (ScreenPtr screen, uint64_t event_id); -#define PRESENT_SCREEN_INFO_VERSION 0 +#define PRESENT_SCREEN_INFO_VERSION 1 typedef struct present_screen_info { uint32_t version; @@ -97,6 +104,7 @@ typedef struct present_screen_info { present_check_flip_ptr check_flip; present_flip_ptr flip; present_unflip_ptr unflip; + present_check_flip2_ptr check_flip2; } present_screen_info_rec, *present_screen_info_ptr; diff --git a/present/present_priv.h b/present/present_priv.h index dfb4bdea9..fa8db887d 100644 --- a/present/present_priv.h +++ b/present/present_priv.h @@ -73,6 +73,7 @@ struct present_vblank { Bool requeue; /* on queue, but target_msc has changed */ Bool flip; /* planning on using flip */ Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */ + Bool reason; /* reason for which flip is not possible */ Bool sync_flip; /* do flip synchronous to vblank */ Bool abort_flip; /* aborting this flip */ }; -- 2.13.0 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel