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>
This commit is contained in:
parent
6e7c40f62d
commit
e2ef3b44fa
|
@ -753,7 +753,7 @@ DAMAGEPROTO="damageproto >= 1.1"
|
||||||
XCMISCPROTO="xcmiscproto >= 1.2.0"
|
XCMISCPROTO="xcmiscproto >= 1.2.0"
|
||||||
BIGREQSPROTO="bigreqsproto >= 1.1.0"
|
BIGREQSPROTO="bigreqsproto >= 1.1.0"
|
||||||
XTRANS="xtrans >= 1.3.5"
|
XTRANS="xtrans >= 1.3.5"
|
||||||
PRESENTPROTO="presentproto >= 1.0"
|
PRESENTPROTO="presentproto >= 1.1"
|
||||||
|
|
||||||
dnl List of libraries that require a specific version
|
dnl List of libraries that require a specific version
|
||||||
LIBAPPLEWM="applewm >= 1.4"
|
LIBAPPLEWM="applewm >= 1.4"
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
/* Present */
|
/* Present */
|
||||||
#define SERVER_PRESENT_MAJOR_VERSION 1
|
#define SERVER_PRESENT_MAJOR_VERSION 1
|
||||||
#define SERVER_PRESENT_MINOR_VERSION 0
|
#define SERVER_PRESENT_MINOR_VERSION 1
|
||||||
|
|
||||||
/* RandR */
|
/* RandR */
|
||||||
#define SERVER_RANDR_MAJOR_VERSION 1
|
#define SERVER_RANDR_MAJOR_VERSION 1
|
||||||
|
|
|
@ -13,7 +13,7 @@ libxserver_present = static_library('libxserver_present',
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
common_dep,
|
common_dep,
|
||||||
dependency('presentproto', version: '>= 1.0')
|
dependency('presentproto', version: '>= 1.1')
|
||||||
],
|
],
|
||||||
c_args: '-DHAVE_XORG_CONFIG_H'
|
c_args: '-DHAVE_XORG_CONFIG_H'
|
||||||
)
|
)
|
||||||
|
|
|
@ -124,13 +124,17 @@ present_check_flip(RRCrtcPtr crtc,
|
||||||
Bool sync_flip,
|
Bool sync_flip,
|
||||||
RegionPtr valid,
|
RegionPtr valid,
|
||||||
int16_t x_off,
|
int16_t x_off,
|
||||||
int16_t y_off)
|
int16_t y_off,
|
||||||
|
PresentFlipReason *reason)
|
||||||
{
|
{
|
||||||
ScreenPtr screen = window->drawable.pScreen;
|
ScreenPtr screen = window->drawable.pScreen;
|
||||||
PixmapPtr window_pixmap;
|
PixmapPtr window_pixmap;
|
||||||
WindowPtr root = screen->root;
|
WindowPtr root = screen->root;
|
||||||
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
|
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
|
||||||
|
|
||||||
|
if (reason)
|
||||||
|
*reason = PRESENT_FLIP_REASON_UNKNOWN;
|
||||||
|
|
||||||
if (!screen_priv)
|
if (!screen_priv)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -177,7 +181,12 @@ present_check_flip(RRCrtcPtr crtc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ask the driver for permission */
|
/* 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)) {
|
if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) {
|
||||||
DebugPresent(("\td %08lx -> %08lx\n", window->drawable.id, pixmap ? pixmap->drawable.id : 0));
|
DebugPresent(("\td %08lx -> %08lx\n", window->drawable.id, pixmap ? pixmap->drawable.id : 0));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -564,6 +573,7 @@ present_check_flip_window (WindowPtr window)
|
||||||
present_window_priv_ptr window_priv = present_window_priv(window);
|
present_window_priv_ptr window_priv = present_window_priv(window);
|
||||||
present_vblank_ptr flip_pending = screen_priv->flip_pending;
|
present_vblank_ptr flip_pending = screen_priv->flip_pending;
|
||||||
present_vblank_ptr vblank;
|
present_vblank_ptr vblank;
|
||||||
|
PresentFlipReason reason;
|
||||||
|
|
||||||
/* If this window hasn't ever been used with Present, it can't be
|
/* If this window hasn't ever been used with Present, it can't be
|
||||||
* flipping
|
* flipping
|
||||||
|
@ -580,7 +590,7 @@ present_check_flip_window (WindowPtr window)
|
||||||
*/
|
*/
|
||||||
if (flip_pending->window == window) {
|
if (flip_pending->window == window) {
|
||||||
if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap,
|
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);
|
present_set_abort_flip(screen);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -588,15 +598,16 @@ present_check_flip_window (WindowPtr window)
|
||||||
* Check current flip
|
* Check current flip
|
||||||
*/
|
*/
|
||||||
if (window == screen_priv->flip_window) {
|
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);
|
present_unflip(screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check any queued vblanks */
|
/* Now check any queued vblanks */
|
||||||
xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
|
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->flip = FALSE;
|
||||||
|
vblank->reason = reason;
|
||||||
if (vblank->sync_flip)
|
if (vblank->sync_flip)
|
||||||
vblank->requeue = TRUE;
|
vblank->requeue = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -756,11 +767,15 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
|
||||||
/* Compute correct CompleteMode
|
/* Compute correct CompleteMode
|
||||||
*/
|
*/
|
||||||
if (vblank->kind == PresentCompleteKindPixmap) {
|
if (vblank->kind == PresentCompleteKindPixmap) {
|
||||||
if (vblank->pixmap && vblank->window)
|
if (vblank->pixmap && vblank->window) {
|
||||||
mode = PresentCompleteModeCopy;
|
if (vblank->has_suboptimal && vblank->reason == PRESENT_FLIP_REASON_BUFFER_FORMAT)
|
||||||
|
mode = PresentCompleteModeSuboptimalCopy;
|
||||||
else
|
else
|
||||||
|
mode = PresentCompleteModeCopy;
|
||||||
|
} else {
|
||||||
mode = PresentCompleteModeSkip;
|
mode = PresentCompleteModeSkip;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mode = PresentCompleteModeCopy;
|
mode = PresentCompleteModeCopy;
|
||||||
|
|
||||||
|
@ -795,6 +810,7 @@ present_pixmap(WindowPtr window,
|
||||||
ScreenPtr screen = window->drawable.pScreen;
|
ScreenPtr screen = window->drawable.pScreen;
|
||||||
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
|
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
|
||||||
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
|
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
|
||||||
|
PresentFlipReason reason = PRESENT_FLIP_REASON_UNKNOWN;
|
||||||
|
|
||||||
if (!window_priv)
|
if (!window_priv)
|
||||||
return BadAlloc;
|
return BadAlloc;
|
||||||
|
@ -912,22 +928,24 @@ present_pixmap(WindowPtr window,
|
||||||
vblank->msc_offset = window_priv->msc_offset;
|
vblank->msc_offset = window_priv->msc_offset;
|
||||||
vblank->notifies = notifies;
|
vblank->notifies = notifies;
|
||||||
vblank->num_notifies = num_notifies;
|
vblank->num_notifies = num_notifies;
|
||||||
|
vblank->has_suboptimal = (options & PresentOptionSuboptimal);
|
||||||
|
|
||||||
if (pixmap != NULL &&
|
if (pixmap != NULL &&
|
||||||
!(options & PresentOptionCopy) &&
|
!(options & PresentOptionCopy) &&
|
||||||
screen_priv->info) {
|
screen_priv->info) {
|
||||||
if (msc_is_after(target_msc, crtc_msc) &&
|
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->flip = TRUE;
|
||||||
vblank->sync_flip = TRUE;
|
vblank->sync_flip = TRUE;
|
||||||
target_msc--;
|
target_msc--;
|
||||||
} else if ((screen_priv->info->capabilities & PresentCapabilityAsync) &&
|
} 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->flip = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vblank->reason = reason;
|
||||||
|
|
||||||
if (wait_fence) {
|
if (wait_fence) {
|
||||||
vblank->wait_fence = present_fence_create(wait_fence);
|
vblank->wait_fence = present_fence_create(wait_fence);
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
#include "randrstr.h"
|
#include "randrstr.h"
|
||||||
#include "presentext.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;
|
typedef struct present_vblank present_vblank_rec, *present_vblank_ptr;
|
||||||
|
|
||||||
/* Return the current CRTC for 'window'.
|
/* 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);
|
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.
|
/* Flip pixmap, return false if it didn't happen.
|
||||||
*
|
*
|
||||||
* 'crtc' is to be used for any necessary synchronization.
|
* '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,
|
typedef void (*present_unflip_ptr) (ScreenPtr screen,
|
||||||
uint64_t event_id);
|
uint64_t event_id);
|
||||||
|
|
||||||
#define PRESENT_SCREEN_INFO_VERSION 0
|
#define PRESENT_SCREEN_INFO_VERSION 1
|
||||||
|
|
||||||
typedef struct present_screen_info {
|
typedef struct present_screen_info {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
@ -97,6 +106,7 @@ typedef struct present_screen_info {
|
||||||
present_check_flip_ptr check_flip;
|
present_check_flip_ptr check_flip;
|
||||||
present_flip_ptr flip;
|
present_flip_ptr flip;
|
||||||
present_unflip_ptr unflip;
|
present_unflip_ptr unflip;
|
||||||
|
present_check_flip2_ptr check_flip2;
|
||||||
|
|
||||||
} present_screen_info_rec, *present_screen_info_ptr;
|
} present_screen_info_rec, *present_screen_info_ptr;
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,8 @@ struct present_vblank {
|
||||||
Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */
|
Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */
|
||||||
Bool sync_flip; /* do flip synchronous to vblank */
|
Bool sync_flip; /* do flip synchronous to vblank */
|
||||||
Bool abort_flip; /* aborting this flip */
|
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 {
|
typedef struct present_screen_priv {
|
||||||
|
|
Loading…
Reference in New Issue