From cc7c1c961b77c139b95fbb6948204def1b4b908a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 31 Oct 2011 10:50:09 +0100 Subject: [PATCH] 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 Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 84 +++++++++++++++++++++++++++++++++++++++- vmwgfx/vmwgfx_driver.h | 5 +++ vmwgfx/vmwgfx_output.c | 102 ++++++++++++++++++++++++++++++++++++++++++++----- 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; -- 2.7.4