summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-10-31 10:50:09 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2011-10-31 15:27:12 +0100
commitcc7c1c961b77c139b95fbb6948204def1b4b908a (patch)
tree72960207eb10dd617ee39965657e23861845d94a
parent427064b57c52c8881c7a64d9c9e21411e79e644b (diff)
vmwgfx: Fall back to sw cursors if needed
If there is a risc that we need two simultaneous cursors, (two outputs showing the same contents, at least one of them explicit), fall back to sw cursor. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
-rw-r--r--vmwgfx/vmwgfx_driver.c84
-rw-r--r--vmwgfx/vmwgfx_driver.h5
-rw-r--r--vmwgfx/vmwgfx_output.c102
3 files changed, 180 insertions, 11 deletions
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
index 1b02a7b..c1938a5 100644
--- a/vmwgfx/vmwgfx_driver.c
+++ b/vmwgfx/vmwgfx_driver.c
@@ -671,6 +671,86 @@ drv_set_master(ScrnInfoPtr pScrn)
return TRUE;
}
+/**
+ * vmwgfx_use_hw_cursor_argb - wrapper around hw argb cursor check.
+ *
+ * screen: Pointer to the current screen metadata.
+ * cursor: Pointer to the current cursor metadata.
+ *
+ * In addition to the default test, also check whether we might be
+ * needing more than one hw cursor (which we don't support).
+ */
+static Bool
+vmwgfx_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
+{
+ ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ modesettingPtr ms = modesettingPTR(pScrn);
+ Bool ret;
+
+ vmwgfx_swap(ms, cursor_info, UseHWCursorARGB);
+ ret = cursor_info->UseHWCursorARGB(screen, cursor);
+ vmwgfx_swap(ms, cursor_info, UseHWCursorARGB);
+ if (!ret)
+ return FALSE;
+
+ /*
+ * If there is a chance we might need two cursors,
+ * revert to sw cursor.
+ */
+ return !vmwgfx_output_explicit_overlap(pScrn);
+}
+
+/**
+ * vmwgfx_use_hw_cursor - wrapper around hw cursor check.
+ *
+ * screen: Pointer to the current screen metadata.
+ * cursor: Pointer to the current cursor metadata.
+ *
+ * In addition to the default test, also check whether we might be
+ * needing more than one hw cursor (which we don't support).
+ */
+static Bool
+vmwgfx_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
+{
+ ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ modesettingPtr ms = modesettingPTR(pScrn);
+ Bool ret;
+
+ vmwgfx_swap(ms, cursor_info, UseHWCursor);
+ ret = cursor_info->UseHWCursor(screen, cursor);
+ vmwgfx_swap(ms, cursor_info, UseHWCursor);
+ if (!ret)
+ return FALSE;
+
+ /*
+ * If there is a chance we might need two simultaneous cursors,
+ * revert to sw cursor.
+ */
+ return !vmwgfx_output_explicit_overlap(pScrn);
+}
+
+/**
+ * vmwgfx_wrap_use_hw_cursor - Wrap functions that check for hw cursor
+ * support.
+ *
+ * pScrn: Pointer to current screen info.
+ *
+ * Enables the device-specific hw cursor support check functions.
+ */
+static void vmwgfx_wrap_use_hw_cursor(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ vmwgfx_wrap(ms, cursor_info, UseHWCursor, vmwgfx_use_hw_cursor);
+ vmwgfx_wrap(ms, cursor_info, UseHWCursorARGB, vmwgfx_use_hw_cursor_argb);
+}
+
static void drv_load_palette(ScrnInfoPtr pScrn, int numColors,
int *indices, LOCO *colors, VisualPtr pVisual)
@@ -865,11 +945,13 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
/* Need to extend HWcursor support to handle mask interleave */
- if (!ms->SWCursor)
+ if (!ms->SWCursor) {
xf86_cursors_init(pScreen, 64, 64,
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
HARDWARE_CURSOR_ARGB |
HARDWARE_CURSOR_UPDATE_UNHIDDEN);
+ vmwgfx_wrap_use_hw_cursor(pScrn);
+ }
/* Must force it before EnterVT, so we are in control of VT and
* later memory should be bound when allocating, e.g rotate_mem */
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
index c672b62..da07a73 100644
--- a/vmwgfx/vmwgfx_driver.h
+++ b/vmwgfx/vmwgfx_driver.h
@@ -105,6 +105,8 @@ typedef struct _modesettingRec
Bool (*saved_EnterVT)(int, int);
void (*saved_LeaveVT)(int, int);
void (*saved_AdjustFrame)(int, int, int, int);
+ Bool (*saved_UseHWCursor)(ScreenPtr, CursorPtr);
+ Bool (*saved_UseHWCursorARGB)(ScreenPtr, CursorPtr);
uint16_t lut_r[256], lut_g[256], lut_b[256];
@@ -157,6 +159,9 @@ xorg_output_init(ScrnInfoPtr pScrn);
unsigned
xorg_output_get_id(xf86OutputPtr output);
+Bool
+vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn);
+
/***********************************************************************
* xorg_xv.c
diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
index d0f238d..1a0835d 100644
--- a/vmwgfx/vmwgfx_output.c
+++ b/vmwgfx/vmwgfx_output.c
@@ -56,6 +56,8 @@ struct output_private
drmModeConnectorPtr drm_connector;
int c;
+
+ Bool is_implicit;
};
static char *output_enum_list[] = {
@@ -237,6 +239,75 @@ static const xf86OutputFuncsRec output_funcs = {
.destroy = output_destroy,
};
+/**
+ * vmwgfx_output_explicit_overlap -- Check for explicit output overlaps
+ *
+ * This function returns TRUE iff the bounding box in screen space of an
+ * exlplicit output overlaps the bounding box in screen space of any other
+ * output.
+ */
+Bool
+vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86OutputPtr output;
+ ScreenPtr pScreen = pScrn->pScreen;
+ RegionRec output_union;
+ RegionRec cur_output;
+ RegionRec result;
+ struct output_private *priv;
+ xf86CrtcPtr crtc;
+ Bool overlap = FALSE;
+ int i;
+
+ (void) pScreen;
+ REGION_NULL(pScreen, &output_union);
+ REGION_NULL(pScreen, &cur_output);
+ REGION_NULL(pScreen, &result);
+
+ /*
+ * Collect a region of implicit outputs. These may overlap.
+ */
+ for (i = 0; i < config->num_output; i++) {
+ output = config->output[i];
+ priv = output->driver_private;
+ crtc = output->crtc;
+
+ if (!crtc || !crtc->enabled || !priv->is_implicit)
+ continue;
+
+ REGION_RESET(pScreen, &cur_output, &crtc->bounds);
+ REGION_UNION(pScreen, &output_union, &output_union, &cur_output);
+ }
+
+ /*
+ * Explicit outputs may not overlap any other output.
+ */
+ for (i = 0; i < config->num_output; i++) {
+ output = config->output[i];
+ priv = output->driver_private;
+ crtc = output->crtc;
+
+ if (!crtc || !crtc->enabled || priv->is_implicit)
+ continue;
+
+ REGION_RESET(pScreen, &cur_output, &crtc->bounds);
+ REGION_NULL(pScreen, &result);
+ REGION_INTERSECT(pScreen, &result, &output_union, &cur_output);
+ overlap = REGION_NOTEMPTY(vsaa->pScreen, &result);
+ if (overlap)
+ break;
+
+ REGION_UNION(pScreen, &output_union, &output_union, &cur_output);
+ }
+
+ REGION_UNINIT(pScreen, &output_union);
+ REGION_UNINIT(pScreen, &cur_output);
+ REGION_UNINIT(pScreen, &result);
+
+ return overlap;
+}
+
void
xorg_output_init(ScrnInfoPtr pScrn)
{
@@ -247,7 +318,7 @@ xorg_output_init(ScrnInfoPtr pScrn)
drmModeEncoderPtr drm_encoder = NULL;
struct output_private *priv;
char name[32];
- int c, v, p;
+ int c, p;
res = drmModeGetResources(ms->fd);
if (res == 0) {
@@ -256,28 +327,37 @@ xorg_output_init(ScrnInfoPtr pScrn)
}
for (c = 0; c < res->count_connectors; c++) {
+ Bool is_implicit = TRUE;
+
drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
if (!drm_connector)
goto out;
-#if 0
+
for (p = 0; p < drm_connector->count_props; p++) {
drmModePropertyPtr prop;
prop = drmModeGetProperty(ms->fd, drm_connector->props[p]);
- name = NULL;
if (prop) {
- ErrorF("VALUES %d\n", prop->count_values);
- for (v = 0; v < prop->count_values; v++)
- ErrorF("%s %lld\n", prop->name, prop->values[v]);
+#if 0
+ /*
+ * Disabled until we sort out what the interface should
+ * look like.
+ */
+
+ if (strcmp(prop->name, "implicit placement") == 0) {
+ drmModeConnectorSetProperty(ms->fd,
+ drm_connector->connector_id,
+ prop->prop_id,
+ 0);
+ is_implicit = FALSE;
+ }
+#endif
+ drmModeFreeProperty(prop);
}
}
-#else
- (void)p;
- (void)v;
-#endif
if (drm_connector->connector_type >=
sizeof(output_enum_list) / sizeof(output_enum_list[0]))
@@ -299,6 +379,8 @@ xorg_output_init(ScrnInfoPtr pScrn)
continue;
}
+ priv->is_implicit = is_implicit;
+
drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
if (drm_encoder) {
output->possible_crtcs = drm_encoder->possible_crtcs;