summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
diff options
context:
space:
mode:
authorSinclair Yeh <syeh@vmware.com>2017-03-23 15:39:16 -0700
committerSinclair Yeh <syeh@vmware.com>2017-03-31 15:21:19 -0700
commit810b3e1683d00e51c8392bcee7dc7a1c65354777 (patch)
treef2190d9a3db87d37c24869236409729009e41e85 /drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
parent2f9545cec6ffd490b08c5675c94c249f169a7e87 (diff)
drm/vmwgfx: Support topology greater than texture size
Most of the display servers today use a single surface to represent the entire desktop even if it's stretched across multiple screens. For vmwgfx with STDU, the maximum surface size is limited to the maximum texture size on the host. On a 2D VM, this limits our ability to support configurations with more than one 4K monitor. To get past this limitation, we will now allow using a large DMA buf as the framebuffer, and take care of blitting contents from this DMA buf to the display buffer. Signed-off-by: Sinclair Yeh <syeh@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_kms.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index fe226e723287..0832381242b1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -801,6 +801,11 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane)
vps->pinned = 0;
+ /* Mapping is managed by prepare_fb/cleanup_fb */
+ memset(&vps->guest_map, 0, sizeof(vps->guest_map));
+ memset(&vps->host_map, 0, sizeof(vps->host_map));
+ vps->cpp = 0;
+
/* Each ref counted resource needs to be acquired again */
if (vps->surf)
(void) vmw_surface_reference(vps->surf);
@@ -859,6 +864,17 @@ vmw_du_plane_destroy_state(struct drm_plane *plane,
struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
+ /* Should have been freed by cleanup_fb */
+ if (vps->guest_map.virtual) {
+ DRM_ERROR("Guest mapping not freed\n");
+ ttm_bo_kunmap(&vps->guest_map);
+ }
+
+ if (vps->host_map.virtual) {
+ DRM_ERROR("Host mapping not freed\n");
+ ttm_bo_kunmap(&vps->host_map);
+ }
+
if (vps->surf)
vmw_surface_unreference(&vps->surf);
@@ -1433,6 +1449,25 @@ out_err1:
return ret;
}
+
+/**
+ * vmw_kms_srf_ok - check if a surface can be created
+ *
+ * @width: requested width
+ * @height: requested height
+ *
+ * Surfaces need to be less than texture size
+ */
+static bool
+vmw_kms_srf_ok(struct vmw_private *dev_priv, uint32_t width, uint32_t height)
+{
+ if (width > dev_priv->texture_max_width ||
+ height > dev_priv->texture_max_height)
+ return false;
+
+ return true;
+}
+
/**
* vmw_kms_new_framebuffer - Create a new framebuffer.
*
@@ -1461,7 +1496,8 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
* therefore, wrap the DMA buf in a surface so we can use the
* SurfaceCopy command.
*/
- if (dmabuf && only_2d &&
+ if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) &&
+ dmabuf && only_2d &&
dev_priv->active_display_unit == vmw_du_screen_target) {
ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd,
dmabuf, &surface);
@@ -1554,6 +1590,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
if (ret)
goto err_out;
+
+ if (!bo &&
+ !vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) {
+ DRM_ERROR("Surface size cannot exceed %dx%d",
+ dev_priv->texture_max_width,
+ dev_priv->texture_max_height);
+ goto err_out;
+ }
+
+
vfb = vmw_kms_new_framebuffer(dev_priv, bo, surface,
!(dev_priv->capabilities & SVGA_CAP_3D),
mode_cmd);