diff options
author | Louis-Francis Ratté-Boulianne <lfrb@collabora.com> | 2018-02-28 01:19:36 +0000 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2018-03-05 13:27:32 -0500 |
commit | e2ef3b44fa697f2ed453767e98da72ea56d4046f (patch) | |
tree | 81c12224fc3def129f3aa708a5d1fa76ac3ab820 /present | |
parent | 6e7c40f62db66f5b59b2cf59f1e6a26e4fd21bda (diff) |
present: Send PresentCompleteModeSuboptimalCopy appropriately
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.
v2: Check for PresentOptionSuboptimal and check driver version
before using 'check_flip2'.
v3: Only require one of 'check_flip' or 'check_flip2' to be
implemented by the driver.
Refactor reasons list to enum
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'present')
-rw-r--r-- | present/meson.build | 2 | ||||
-rw-r--r-- | present/present.c | 50 | ||||
-rw-r--r-- | present/present.h | 12 | ||||
-rw-r--r-- | present/present_priv.h | 2 |
4 files changed, 48 insertions, 18 deletions
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..42e5fb4fc 100644 --- a/present/present.c +++ b/present/present.c @@ -118,19 +118,23 @@ present_flip_pending_pixmap(ScreenPtr screen) } static Bool -present_check_flip(RRCrtcPtr crtc, - WindowPtr window, - PixmapPtr pixmap, - Bool sync_flip, - RegionPtr valid, - int16_t x_off, - int16_t y_off) +present_check_flip(RRCrtcPtr crtc, + WindowPtr window, + PixmapPtr pixmap, + Bool sync_flip, + RegionPtr valid, + int16_t x_off, + int16_t y_off, + PresentFlipReason *reason) { ScreenPtr screen = window->drawable.pScreen; PixmapPtr window_pixmap; WindowPtr root = screen->root; present_screen_priv_ptr screen_priv = present_screen_priv(screen); + if (reason) + *reason = PRESENT_FLIP_REASON_UNKNOWN; + if (!screen_priv) return FALSE; @@ -177,7 +181,12 @@ present_check_flip(RRCrtcPtr crtc, } /* Ask the driver for permission */ - if (screen_priv->info->check_flip) { + if (screen_priv->info->version >= 1 && screen_priv->info->check_flip2) { + 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 +573,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; + PresentFlipReason reason; /* If this window hasn't ever been used with Present, it can't be * flipping @@ -580,7 +590,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 +598,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 +767,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->has_suboptimal && vblank->reason == PRESENT_FLIP_REASON_BUFFER_FORMAT) + mode = PresentCompleteModeSuboptimalCopy; + else + mode = PresentCompleteModeCopy; + } else { mode = PresentCompleteModeSkip; + } } else mode = PresentCompleteModeCopy; @@ -795,6 +810,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); + PresentFlipReason reason = PRESENT_FLIP_REASON_UNKNOWN; if (!window_priv) return BadAlloc; @@ -912,22 +928,24 @@ present_pixmap(WindowPtr window, vblank->msc_offset = window_priv->msc_offset; vblank->notifies = notifies; vblank->num_notifies = num_notifies; + vblank->has_suboptimal = (options & PresentOptionSuboptimal); if (pixmap != NULL && !(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..6542dc385 100644 --- a/present/present.h +++ b/present/present.h @@ -27,6 +27,11 @@ #include "randrstr.h" #include "presentext.h" +typedef enum { + PRESENT_FLIP_REASON_UNKNOWN, + PRESENT_FLIP_REASON_BUFFER_FORMAT +} PresentFlipReason; + typedef struct present_vblank present_vblank_rec, *present_vblank_ptr; /* Return the current CRTC for 'window'. @@ -59,6 +64,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, PresentFlipReason *reason); + /* Flip pixmap, return false if it didn't happen. * * 'crtc' is to be used for any necessary synchronization. @@ -83,7 +92,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 +106,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..6980ddd11 100644 --- a/present/present_priv.h +++ b/present/present_priv.h @@ -75,6 +75,8 @@ struct present_vblank { Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */ Bool sync_flip; /* do flip synchronous to vblank */ Bool abort_flip; /* aborting this flip */ + PresentFlipReason reason; /* reason for which flip is not possible */ + Bool has_suboptimal; /* whether client can support SuboptimalCopy mode */ }; typedef struct present_screen_priv { |