summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vmwgfx/vmwgfx_crtc.c23
-rw-r--r--vmwgfx/vmwgfx_driver.c26
-rw-r--r--vmwgfx/vmwgfx_driver.h1
-rw-r--r--vmwgfx/vmwgfx_drm.h1
-rw-r--r--vmwgfx/vmwgfx_saa.c15
-rw-r--r--vmwgfx/vmwgfx_saa.h7
-rw-r--r--vmwgfx/vmwgfx_saa_priv.h1
7 files changed, 61 insertions, 13 deletions
diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c
index dad8815..1e85b08 100644
--- a/vmwgfx/vmwgfx_crtc.c
+++ b/vmwgfx/vmwgfx_crtc.c
@@ -121,6 +121,26 @@ vmwgfx_disable_scanout(ScrnInfoPtr 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");
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
index 2925227..48f8a63 100644
--- a/vmwgfx/vmwgfx_driver.c
+++ b/vmwgfx/vmwgfx_driver.c
@@ -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);
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
index 31dfc0f..b57d523 100644
--- a/vmwgfx/vmwgfx_driver.h
+++ b/vmwgfx/vmwgfx_driver.h
@@ -115,6 +115,7 @@ typedef struct _modesettingRec
Bool only_hw_presents;
MessageType from_hwp;
Bool isMaster;
+ Bool has_screen_targets;
/* Broken-out options. */
diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h
index 906a41c..d5234e6 100644
--- a/vmwgfx/vmwgfx_drm.h
+++ b/vmwgfx/vmwgfx_drm.h
@@ -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
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
index bca3d93..b8ad2a7 100644
--- a/vmwgfx/vmwgfx_saa.c
+++ b/vmwgfx/vmwgfx_saa.c
@@ -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.
diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h
index 921fabd..15ae770 100644
--- a/vmwgfx/vmwgfx_saa.h
+++ b/vmwgfx/vmwgfx_saa.h
@@ -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);
diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h
index 4a0c302..507833a 100644
--- a/vmwgfx/vmwgfx_saa_priv.h
+++ b/vmwgfx/vmwgfx_saa_priv.h
@@ -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;