diff options
-rw-r--r-- | vmwgfx/vmwgfx_crtc.c | 23 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_driver.c | 26 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_driver.h | 1 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_drm.h | 1 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_saa.c | 15 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_saa.h | 7 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_saa_priv.h | 1 |
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; |