mirror of
https://github.com/X11Libre/xf86-video-vmware.git
synced 2026-03-23 17:19:24 +00:00
vmware/vmwgfx: Try to use only_hw_present semantics if screen targets are enabled
If screen targets are enabled and there is a reasonable chance that the vmwgfx drm driver can use the surface backing a pixmap as a screen target surface, then make that surface a modesetting framebuffer rather than the corresponding DMA buffer. In practice this applies when we start scanning out from the origin (0,0) of the pixmap. However, we would also like to apply the constraint that the scanout area is the entire pixmap, since that is the constraint used by the drm driver, but that would currently require drm framebuffer reallocations and possible flicker, so disable that for now. The drm driver will correctly handle the possibly oversized surface handed to it anyway, and the cost we pay for this is an extra hardware copy of the dirtied area when doing a software update of the scanout. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
@@ -120,6 +120,26 @@ vmwgfx_disable_scanout(ScrnInfoPtr pScrn)
|
||||
xf86RotateFreeShadow(pScrn);
|
||||
}
|
||||
|
||||
static Bool
|
||||
vmwgfx_scanout_equals_pixmap(DisplayModePtr mode, PixmapPtr pixmap,
|
||||
int x, int y)
|
||||
{
|
||||
return x == 0 && y == 0;
|
||||
/*
|
||||
* Mode test is disabled for now, since the X server has a tendency to first
|
||||
* change the pixmap dimensions, then change the mode, keeping the pixmap.
|
||||
* This would lead to a lot of false non-equals, or flickering if we were to
|
||||
* kill the drm fb in between.
|
||||
* However, currently we prefer false equals as long as x == 0 and y == 0.
|
||||
* The false equals will then typically correspond to the primary screen in a
|
||||
* multimon setup. Let's live with that for now.
|
||||
*/
|
||||
#if 0
|
||||
&& mode->HDisplay == pixmap->drawable.width &&
|
||||
mode->VDisplay == pixmap->drawable.height;
|
||||
#endif
|
||||
}
|
||||
|
||||
static Bool
|
||||
crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
||||
Rotation rotation, int x, int y)
|
||||
@@ -191,7 +211,8 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
||||
vmwgfx_scanout_unref(&crtcp->entry);
|
||||
|
||||
crtcp->entry.pixmap = pixmap;
|
||||
crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->entry);
|
||||
crtcp->scanout_id = vmwgfx_scanout_ref
|
||||
(&crtcp->entry, vmwgfx_scanout_equals_pixmap(mode, pixmap, x, y));
|
||||
if (crtcp->scanout_id == -1) {
|
||||
crtcp->entry.pixmap = NULL;
|
||||
LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n");
|
||||
|
||||
@@ -541,6 +541,14 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags)
|
||||
ms->drm_major, ms->drm_minor, ms->drm_patch);
|
||||
}
|
||||
|
||||
ms->has_screen_targets = ms->drm_major > 2 ||
|
||||
(ms->drm_major == 2 && ms->drm_minor >= 7);
|
||||
ms->has_screen_targets = (ms->has_screen_targets &&
|
||||
!vmwgfx_get_param(ms->fd,
|
||||
DRM_VMW_PARAM_SCREEN_TARGET,
|
||||
&cap) &&
|
||||
cap != 0);
|
||||
|
||||
ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0);
|
||||
|
||||
if (vmwgfx_get_param(ms->fd, DRM_VMW_PARAM_HW_CAPS, &cap) != 0) {
|
||||
@@ -744,7 +752,7 @@ void xorg_flush(ScreenPtr pScreen)
|
||||
|
||||
if (vpix->fb_id != -1) {
|
||||
if (vpix->pending_update) {
|
||||
if (ms->only_hw_presents &&
|
||||
if (vpix->scanout_hw &&
|
||||
REGION_NOTEMPTY(pscreen, vpix->pending_update)) {
|
||||
(void) vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT,
|
||||
0, NULL);
|
||||
@@ -756,7 +764,7 @@ void xorg_flush(ScreenPtr pScreen)
|
||||
REGION_EMPTY(pScreen, vpix->pending_update);
|
||||
}
|
||||
if (vpix->pending_present) {
|
||||
if (ms->only_hw_presents)
|
||||
if (vpix->scanout_hw)
|
||||
(void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
|
||||
vpix->pending_present);
|
||||
else
|
||||
@@ -1071,7 +1079,8 @@ drv_screen_init(SCREEN_INIT_ARGS_DECL)
|
||||
if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush,
|
||||
ms->direct_presents,
|
||||
ms->only_hw_presents,
|
||||
ms->rendercheck)) {
|
||||
ms->rendercheck,
|
||||
ms->has_screen_targets)) {
|
||||
FatalError("Failed to initialize SAA.\n");
|
||||
}
|
||||
|
||||
@@ -1102,9 +1111,14 @@ drv_screen_init(SCREEN_INIT_ARGS_DECL)
|
||||
if (ms->xat != NULL) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n",
|
||||
(ms->direct_presents) ? "enabled" : "disabled");
|
||||
xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
|
||||
"are %s.\n",
|
||||
(ms->only_hw_presents) ? "enabled" : "disabled");
|
||||
if (ms->only_hw_presents)
|
||||
xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
|
||||
"are enabled.\n");
|
||||
else
|
||||
xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
|
||||
"are %s.\n",
|
||||
(ms->has_screen_targets) ? "automatic per scanout" :
|
||||
"disabled");
|
||||
}
|
||||
|
||||
xf86SetBackingStore(pScreen);
|
||||
|
||||
@@ -115,6 +115,7 @@ typedef struct _modesettingRec
|
||||
Bool only_hw_presents;
|
||||
MessageType from_hwp;
|
||||
Bool isMaster;
|
||||
Bool has_screen_targets;
|
||||
|
||||
|
||||
/* Broken-out options. */
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#define DRM_VMW_PARAM_FIFO_CAPS 4
|
||||
#define DRM_VMW_PARAM_MAX_FB_SIZE 5
|
||||
#define DRM_VMW_PARAM_FIFO_HW_VERSION 6
|
||||
#define DRM_VMW_PARAM_SCREEN_TARGET 11
|
||||
|
||||
/**
|
||||
* struct drm_vmw_getparam_arg
|
||||
|
||||
@@ -1318,7 +1318,7 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap,
|
||||
* just before we call the kms update function for the hw
|
||||
* surface.
|
||||
*/
|
||||
if (vsaa->only_hw_presents) {
|
||||
if (vpix->scanout_hw) {
|
||||
if (!hw && !vmwgfx_upload_to_hw(&vsaa->driver, pixmap, damage))
|
||||
return FALSE;
|
||||
|
||||
@@ -1408,7 +1408,8 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
|
||||
void (*present_flush)(ScreenPtr pScreen),
|
||||
Bool direct_presents,
|
||||
Bool only_hw_presents,
|
||||
Bool rendercheck)
|
||||
Bool rendercheck,
|
||||
Bool has_screen_targets)
|
||||
{
|
||||
struct vmwgfx_saa *vsaa;
|
||||
|
||||
@@ -1419,6 +1420,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
|
||||
if (xat == NULL) {
|
||||
direct_presents = FALSE;
|
||||
only_hw_presents = FALSE;
|
||||
has_screen_targets = FALSE;
|
||||
}
|
||||
|
||||
vsaa->pScreen = pScreen;
|
||||
@@ -1433,6 +1435,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
|
||||
vsaa->rendercheck = rendercheck;
|
||||
vsaa->is_master = TRUE;
|
||||
vsaa->known_prime_format = FALSE;
|
||||
vsaa->has_screen_targets = has_screen_targets;
|
||||
WSBMINITLISTHEAD(&vsaa->sync_x_list);
|
||||
WSBMINITLISTHEAD(&vsaa->pixmaps);
|
||||
|
||||
@@ -1492,7 +1495,8 @@ vmwgfx_scanout_refresh(PixmapPtr pixmap)
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry)
|
||||
vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry,
|
||||
Bool scanout_equals_pixmap)
|
||||
{
|
||||
PixmapPtr pixmap = entry->pixmap;
|
||||
struct vmwgfx_saa *vsaa =
|
||||
@@ -1503,7 +1507,10 @@ vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry)
|
||||
uint32_t handle, dummy;
|
||||
unsigned int depth;
|
||||
|
||||
if (vsaa->only_hw_presents) {
|
||||
vpix->scanout_hw = vsaa->only_hw_presents ||
|
||||
(vsaa->has_screen_targets && scanout_equals_pixmap);
|
||||
|
||||
if (vpix->scanout_hw) {
|
||||
/*
|
||||
* The KMS fb will be a HW surface. Create it, add damage
|
||||
* and get the handle.
|
||||
|
||||
@@ -56,6 +56,7 @@ struct vmwgfx_saa_pixmap {
|
||||
struct _WsbmListHead sync_x_head;
|
||||
struct _WsbmListHead scanout_list;
|
||||
struct _WsbmListHead pixmap_list;
|
||||
Bool scanout_hw;
|
||||
|
||||
uint32_t xa_flags;
|
||||
uint32_t staging_add_flags;
|
||||
@@ -85,10 +86,12 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
|
||||
void (*present_flush)(ScreenPtr pScreen),
|
||||
Bool direct_presents,
|
||||
Bool only_hw_presents,
|
||||
Bool rendercheck);
|
||||
Bool rendercheck,
|
||||
Bool has_screen_targets);
|
||||
|
||||
extern uint32_t
|
||||
vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box);
|
||||
vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry,
|
||||
Bool scanout_equals_pixmap);
|
||||
|
||||
extern void
|
||||
vmwgfx_scanout_unref(struct vmwgfx_screen_entry *box);
|
||||
|
||||
@@ -56,6 +56,7 @@ struct vmwgfx_saa {
|
||||
Bool rendercheck;
|
||||
Bool is_master;
|
||||
Bool known_prime_format;
|
||||
Bool has_screen_targets;
|
||||
void (*present_flush) (ScreenPtr pScreen);
|
||||
struct _WsbmListHead sync_x_list;
|
||||
struct _WsbmListHead pixmaps;
|
||||
|
||||
Reference in New Issue
Block a user