summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-11-01 15:39:07 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2011-11-01 18:37:10 +0100
commitaff799d007c8383321213ad177e5a9deec2b3978 (patch)
treeed9d7dac0d0a402b6aab6dafc62d5198003ad1da
parent5137e8736edfab1aaebef4046baab37361584b2e (diff)
vmwgfx: Add an option to use a scanout surface
With this option enabled, we compose all contents (both sw and hw) in the guest before presenting it. Just like the old xorg state tracker did when 3D was enabled. It's not as bad as the old xorg state tracker was for interactivity, but there's a small but noticeable lag when moving windows. It's mainly intended for testing purposes, like testing the surface dirty paths in the kernel module. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
-rw-r--r--vmwgfx/vmwgfx_driver.c34
-rw-r--r--vmwgfx/vmwgfx_driver.h2
-rw-r--r--vmwgfx/vmwgfx_saa.c87
-rw-r--r--vmwgfx/vmwgfx_saa.h3
4 files changed, 93 insertions, 33 deletions
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
index 4ac829f..0504c2d 100644
--- a/vmwgfx/vmwgfx_driver.c
+++ b/vmwgfx/vmwgfx_driver.c
@@ -107,6 +107,7 @@ typedef enum
OPTION_RENDER_ACCEL,
OPTION_DRI,
OPTION_DIRECT_PRESENTS,
+ OPTION_HW_PRESENTS
} drv_option_enums;
static const OptionInfoRec drv_options[] = {
@@ -114,6 +115,7 @@ static const OptionInfoRec drv_options[] = {
{OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
@@ -417,6 +419,11 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags)
&ms->direct_presents) ?
X_CONFIG : X_DEFAULT;
+ ms->only_hw_presents = FALSE;
+ ms->from_hwp = xf86GetOptValBool(ms->Options, OPTION_HW_PRESENTS,
+ &ms->only_hw_presents) ?
+ X_CONFIG : X_DEFAULT;
+
/* Allocate an xf86CrtcConfig */
xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -551,7 +558,7 @@ vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd,
}
if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) {
- LogMessage(X_ERROR, "Could not get present surface handle.\n");
+ LogMessage(X_ERROR, "Failed present kernel call.\n");
return FALSE;
}
@@ -610,13 +617,24 @@ void xorg_flush(ScreenPtr pScreen)
if (vpix->fb_id != -1) {
if (vpix->pending_update) {
- (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
- vpix->pending_update);
+ if (ms->only_hw_presents &&
+ REGION_NOTEMPTY(pscreen, vpix->pending_update)) {
+ (void) vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT,
+ 0, NULL);
+ REGION_UNION(pScreen, vpix->pending_present,
+ vpix->pending_present, vpix->pending_update);
+ } else
+ (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
+ vpix->pending_update);
REGION_EMPTY(pScreen, vpix->pending_update);
}
if (vpix->pending_present) {
- (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix,
- vpix->pending_present);
+ if (ms->only_hw_presents)
+ (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
+ vpix->pending_present);
+ else
+ (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix,
+ vpix->pending_present);
REGION_EMPTY(pScreen, vpix->pending_present);
}
}
@@ -916,7 +934,8 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
}
if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush,
- ms->direct_presents)) {
+ ms->direct_presents,
+ ms->only_hw_presents)) {
FatalError("Failed to initialize SAA.\n");
}
@@ -944,6 +963,9 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
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");
}
miInitializeBackingStore(pScreen);
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
index a88fa82..d0d4e52 100644
--- a/vmwgfx/vmwgfx_driver.h
+++ b/vmwgfx/vmwgfx_driver.h
@@ -94,6 +94,8 @@ typedef struct _modesettingRec
Bool from_dri;
Bool direct_presents;
Bool from_dp;
+ Bool only_hw_presents;
+ Bool from_hwp;
Bool isMaster;
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
index 50b9fe6..bd90b3d 100644
--- a/vmwgfx/vmwgfx_saa.c
+++ b/vmwgfx/vmwgfx_saa.c
@@ -1194,19 +1194,22 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap,
if (WSBMLISTEMPTY(&vpix->scanout_list))
return TRUE;
+#if 0
+ /*
+ * This code can be enabled to immediately upload scanout sw
+ * contents to the hw surface. Otherwise this is done
+ * just before we call the kms update function for the hw
+ * surface.
+ */
if (vsaa->only_hw_presents) {
- if (!vpix->hw) {
- if (!vmwgfx_hw_accel_stage(pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
- return FALSE;
- if (!vmwgfx_hw_commit(pixmap))
- return FALSE;
- }
if (!hw && !vmwgfx_upload_to_hw(&vsaa->driver, pixmap, damage))
return FALSE;
+
REGION_SUBTRACT(&vsaa->pScreen, &spix->dirty_shadow,
&spix->dirty_shadow, damage);
hw = TRUE;
}
+#endif
/*
* Is the new scanout damage hw or sw?
@@ -1286,7 +1289,8 @@ static const struct saa_driver vmwgfx_saa_driver = {
Bool
vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
void (*present_flush)(ScreenPtr pScreen),
- Bool direct_presents)
+ Bool direct_presents,
+ Bool only_hw_presents)
{
struct vmwgfx_saa *vsaa;
@@ -1294,6 +1298,11 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
if (!vsaa)
return FALSE;
+ if (xat == NULL) {
+ direct_presents = FALSE;
+ only_hw_presents = FALSE;
+ }
+
vsaa->pScreen = pScreen;
vsaa->xat = xat;
if (xat)
@@ -1302,7 +1311,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
vsaa->present_flush = present_flush;
vsaa->can_optimize_dma = FALSE;
vsaa->use_present_opt = direct_presents;
- vsaa->only_hw_presents = FALSE;
+ vsaa->only_hw_presents = only_hw_presents;
WSBMINITLISTHEAD(&vsaa->sync_x_list);
vsaa->driver = vmwgfx_saa_driver;
@@ -1365,33 +1374,59 @@ vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry)
struct vmwgfx_saa *vsaa =
to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
- int ret;
if (WSBMLISTEMPTY(&vpix->scanout_list)) {
- ret = !vmwgfx_pixmap_create_gmr(vsaa, pixmap);
- if (!ret)
- ret = !vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt);
- if (!ret)
- ret = drmModeAddFB(vsaa->drm_fd,
- pixmap->drawable.width,
- pixmap->drawable.height,
- pixmap->drawable.depth,
- pixmap->drawable.bitsPerPixel,
- pixmap->devKind,
- vpix->gmr->handle,
- &vpix->fb_id);
- if (ret) {
- entry->pixmap = NULL;
- vpix->fb_id = -1;
- goto out_err;
+ uint32_t handle, dummy;
+ unsigned int depth;
+
+ if (vsaa->only_hw_presents) {
+ /*
+ * The KMS fb will be a HW surface. Create it, add damage
+ * and get the handle.
+ */
+ if (!vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT, 0, NULL))
+ goto out_err;
+ if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0)
+ goto out_err;
+ depth = xa_format_depth(xa_surface_format(vpix->hw));
+
+ } else {
+ /*
+ * The KMS fb will be a Guest Memory Region. Create it,
+ * add damage and get the handle.
+ */
+ if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap))
+ goto out_err;
+
+ handle = vpix->gmr->handle;
+ depth = pixmap->drawable.depth;
+
}
+ if (!vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt))
+ goto out_no_present;
+
+ if (drmModeAddFB(vsaa->drm_fd,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ depth,
+ pixmap->drawable.bitsPerPixel,
+ pixmap->devKind,
+ handle,
+ &vpix->fb_id) != 0)
+ goto out_no_fb;;
}
pixmap->refcnt += 1;
WSBMLISTADDTAIL(&entry->scanout_head, &vpix->scanout_list);
+ return vpix->fb_id;
+ out_no_fb:
+ vmwgfx_pixmap_remove_present(vpix);
+ out_no_present:
+ vmwgfx_pixmap_remove_damage(pixmap);
out_err:
- return vpix->fb_id;
+ vpix->fb_id = -1;
+ return -1;
}
/*
diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h
index 1fd06b6..1276768 100644
--- a/vmwgfx/vmwgfx_saa.h
+++ b/vmwgfx/vmwgfx_saa.h
@@ -81,7 +81,8 @@ vmwgfx_saa_pixmap(PixmapPtr pix)
extern Bool
vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
void (*present_flush)(ScreenPtr pScreen),
- Bool direct_presents);
+ Bool direct_presents,
+ Bool only_hw_presents);
extern uint32_t
vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box);