Home | History | Annotate | Line # | Download | only in vmwgfx
vmwgfx_scrn.c revision 1.2
      1 /*	$NetBSD: vmwgfx_scrn.c,v 1.2 2018/08/27 04:58:37 riastradh Exp $	*/
      2 
      3 /**************************************************************************
      4  *
      5  * Copyright  2011-2015 VMware, Inc., Palo Alto, CA., USA
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial portions
     18  * of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     23  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     26  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  *
     28  **************************************************************************/
     29 
     30 #include <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: vmwgfx_scrn.c,v 1.2 2018/08/27 04:58:37 riastradh Exp $");
     32 
     33 #include "vmwgfx_kms.h"
     34 #include <drm/drm_plane_helper.h>
     35 
     36 
     37 #define vmw_crtc_to_sou(x) \
     38 	container_of(x, struct vmw_screen_object_unit, base.crtc)
     39 #define vmw_encoder_to_sou(x) \
     40 	container_of(x, struct vmw_screen_object_unit, base.encoder)
     41 #define vmw_connector_to_sou(x) \
     42 	container_of(x, struct vmw_screen_object_unit, base.connector)
     43 
     44 /**
     45  * struct vmw_kms_sou_surface_dirty - Closure structure for
     46  * blit surface to screen command.
     47  * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
     48  * @left: Left side of bounding box.
     49  * @right: Right side of bounding box.
     50  * @top: Top side of bounding box.
     51  * @bottom: Bottom side of bounding box.
     52  * @dst_x: Difference between source clip rects and framebuffer coordinates.
     53  * @dst_y: Difference between source clip rects and framebuffer coordinates.
     54  * @sid: Surface id of surface to copy from.
     55  */
     56 struct vmw_kms_sou_surface_dirty {
     57 	struct vmw_kms_dirty base;
     58 	s32 left, right, top, bottom;
     59 	s32 dst_x, dst_y;
     60 	u32 sid;
     61 };
     62 
     63 /*
     64  * SVGA commands that are used by this code. Please see the device headers
     65  * for explanation.
     66  */
     67 struct vmw_kms_sou_readback_blit {
     68 	uint32 header;
     69 	SVGAFifoCmdBlitScreenToGMRFB body;
     70 };
     71 
     72 struct vmw_kms_sou_dmabuf_blit {
     73 	uint32 header;
     74 	SVGAFifoCmdBlitGMRFBToScreen body;
     75 };
     76 
     77 struct vmw_kms_sou_dirty_cmd {
     78 	SVGA3dCmdHeader header;
     79 	SVGA3dCmdBlitSurfaceToScreen body;
     80 };
     81 
     82 
     83 /*
     84  * Other structs.
     85  */
     86 
     87 struct vmw_screen_object_display {
     88 	unsigned num_implicit;
     89 
     90 	struct vmw_framebuffer *implicit_fb;
     91 	SVGAFifoCmdDefineGMRFB cur;
     92 	struct vmw_dma_buffer *pinned_gmrfb;
     93 };
     94 
     95 /**
     96  * Display unit using screen objects.
     97  */
     98 struct vmw_screen_object_unit {
     99 	struct vmw_display_unit base;
    100 
    101 	unsigned long buffer_size; /**< Size of allocated buffer */
    102 	struct vmw_dma_buffer *buffer; /**< Backing store buffer */
    103 
    104 	bool defined;
    105 	bool active_implicit;
    106 };
    107 
    108 static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
    109 {
    110 	vmw_du_cleanup(&sou->base);
    111 	kfree(sou);
    112 }
    113 
    114 
    115 /*
    116  * Screen Object Display Unit CRTC functions
    117  */
    118 
    119 static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
    120 {
    121 	vmw_sou_destroy(vmw_crtc_to_sou(crtc));
    122 }
    123 
    124 static void vmw_sou_del_active(struct vmw_private *vmw_priv,
    125 			       struct vmw_screen_object_unit *sou)
    126 {
    127 	struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
    128 
    129 	if (sou->active_implicit) {
    130 		if (--(ld->num_implicit) == 0)
    131 			ld->implicit_fb = NULL;
    132 		sou->active_implicit = false;
    133 	}
    134 }
    135 
    136 static void vmw_sou_add_active(struct vmw_private *vmw_priv,
    137 			       struct vmw_screen_object_unit *sou,
    138 			       struct vmw_framebuffer *vfb)
    139 {
    140 	struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
    141 
    142 	BUG_ON(!ld->num_implicit && ld->implicit_fb);
    143 
    144 	if (!sou->active_implicit && sou->base.is_implicit) {
    145 		ld->implicit_fb = vfb;
    146 		sou->active_implicit = true;
    147 		ld->num_implicit++;
    148 	}
    149 }
    150 
    151 /**
    152  * Send the fifo command to create a screen.
    153  */
    154 static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
    155 			       struct vmw_screen_object_unit *sou,
    156 			       uint32_t x, uint32_t y,
    157 			       struct drm_display_mode *mode)
    158 {
    159 	size_t fifo_size;
    160 
    161 	struct {
    162 		struct {
    163 			uint32_t cmdType;
    164 		} header;
    165 		SVGAScreenObject obj;
    166 	} *cmd;
    167 
    168 	BUG_ON(!sou->buffer);
    169 
    170 	fifo_size = sizeof(*cmd);
    171 	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
    172 	/* The hardware has hung, nothing we can do about it here. */
    173 	if (unlikely(cmd == NULL)) {
    174 		DRM_ERROR("Fifo reserve failed.\n");
    175 		return -ENOMEM;
    176 	}
    177 
    178 	memset(cmd, 0, fifo_size);
    179 	cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
    180 	cmd->obj.structSize = sizeof(SVGAScreenObject);
    181 	cmd->obj.id = sou->base.unit;
    182 	cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
    183 		(sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
    184 	cmd->obj.size.width = mode->hdisplay;
    185 	cmd->obj.size.height = mode->vdisplay;
    186 	if (sou->base.is_implicit) {
    187 		cmd->obj.root.x = x;
    188 		cmd->obj.root.y = y;
    189 	} else {
    190 		cmd->obj.root.x = sou->base.gui_x;
    191 		cmd->obj.root.y = sou->base.gui_y;
    192 	}
    193 
    194 	/* Ok to assume that buffer is pinned in vram */
    195 	vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
    196 	cmd->obj.backingStore.pitch = mode->hdisplay * 4;
    197 
    198 	vmw_fifo_commit(dev_priv, fifo_size);
    199 
    200 	sou->defined = true;
    201 
    202 	return 0;
    203 }
    204 
    205 /**
    206  * Send the fifo command to destroy a screen.
    207  */
    208 static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
    209 				struct vmw_screen_object_unit *sou)
    210 {
    211 	size_t fifo_size;
    212 	int ret;
    213 
    214 	struct {
    215 		struct {
    216 			uint32_t cmdType;
    217 		} header;
    218 		SVGAFifoCmdDestroyScreen body;
    219 	} *cmd;
    220 
    221 	/* no need to do anything */
    222 	if (unlikely(!sou->defined))
    223 		return 0;
    224 
    225 	fifo_size = sizeof(*cmd);
    226 	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
    227 	/* the hardware has hung, nothing we can do about it here */
    228 	if (unlikely(cmd == NULL)) {
    229 		DRM_ERROR("Fifo reserve failed.\n");
    230 		return -ENOMEM;
    231 	}
    232 
    233 	memset(cmd, 0, fifo_size);
    234 	cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
    235 	cmd->body.screenId = sou->base.unit;
    236 
    237 	vmw_fifo_commit(dev_priv, fifo_size);
    238 
    239 	/* Force sync */
    240 	ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
    241 	if (unlikely(ret != 0))
    242 		DRM_ERROR("Failed to sync with HW");
    243 	else
    244 		sou->defined = false;
    245 
    246 	return ret;
    247 }
    248 
    249 /**
    250  * Free the backing store.
    251  */
    252 static void vmw_sou_backing_free(struct vmw_private *dev_priv,
    253 				 struct vmw_screen_object_unit *sou)
    254 {
    255 	vmw_dmabuf_unreference(&sou->buffer);
    256 	sou->buffer_size = 0;
    257 }
    258 
    259 /**
    260  * Allocate the backing store for the buffer.
    261  */
    262 static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
    263 				 struct vmw_screen_object_unit *sou,
    264 				 unsigned long size)
    265 {
    266 	int ret;
    267 
    268 	if (sou->buffer_size == size)
    269 		return 0;
    270 
    271 	if (sou->buffer)
    272 		vmw_sou_backing_free(dev_priv, sou);
    273 
    274 	sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
    275 	if (unlikely(sou->buffer == NULL))
    276 		return -ENOMEM;
    277 
    278 	/* After we have alloced the backing store might not be able to
    279 	 * resume the overlays, this is preferred to failing to alloc.
    280 	 */
    281 	vmw_overlay_pause_all(dev_priv);
    282 	ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
    283 			      &vmw_vram_ne_placement,
    284 			      false, &vmw_dmabuf_bo_free);
    285 	vmw_overlay_resume_all(dev_priv);
    286 
    287 	if (unlikely(ret != 0))
    288 		sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
    289 	else
    290 		sou->buffer_size = size;
    291 
    292 	return ret;
    293 }
    294 
    295 static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
    296 {
    297 	struct vmw_private *dev_priv;
    298 	struct vmw_screen_object_unit *sou;
    299 	struct drm_connector *connector;
    300 	struct drm_display_mode *mode;
    301 	struct drm_encoder *encoder;
    302 	struct vmw_framebuffer *vfb;
    303 	struct drm_framebuffer *fb;
    304 	struct drm_crtc *crtc;
    305 	int ret = 0;
    306 
    307 	if (!set)
    308 		return -EINVAL;
    309 
    310 	if (!set->crtc)
    311 		return -EINVAL;
    312 
    313 	/* get the sou */
    314 	crtc = set->crtc;
    315 	sou = vmw_crtc_to_sou(crtc);
    316 	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
    317 	dev_priv = vmw_priv(crtc->dev);
    318 
    319 	if (set->num_connectors > 1) {
    320 		DRM_ERROR("Too many connectors\n");
    321 		return -EINVAL;
    322 	}
    323 
    324 	if (set->num_connectors == 1 &&
    325 	    set->connectors[0] != &sou->base.connector) {
    326 		DRM_ERROR("Connector doesn't match %p %p\n",
    327 			set->connectors[0], &sou->base.connector);
    328 		return -EINVAL;
    329 	}
    330 
    331 	/* sou only supports one fb active at the time */
    332 	if (sou->base.is_implicit &&
    333 	    dev_priv->sou_priv->implicit_fb && vfb &&
    334 	    !(dev_priv->sou_priv->num_implicit == 1 &&
    335 	      sou->active_implicit) &&
    336 	    dev_priv->sou_priv->implicit_fb != vfb) {
    337 		DRM_ERROR("Multiple framebuffers not supported\n");
    338 		return -EINVAL;
    339 	}
    340 
    341 	/* since they always map one to one these are safe */
    342 	connector = &sou->base.connector;
    343 	encoder = &sou->base.encoder;
    344 
    345 	/* should we turn the crtc off */
    346 	if (set->num_connectors == 0 || !set->mode || !set->fb) {
    347 		ret = vmw_sou_fifo_destroy(dev_priv, sou);
    348 		/* the hardware has hung don't do anything more */
    349 		if (unlikely(ret != 0))
    350 			return ret;
    351 
    352 		connector->encoder = NULL;
    353 		encoder->crtc = NULL;
    354 		crtc->primary->fb = NULL;
    355 		crtc->x = 0;
    356 		crtc->y = 0;
    357 		crtc->enabled = false;
    358 
    359 		vmw_sou_del_active(dev_priv, sou);
    360 
    361 		vmw_sou_backing_free(dev_priv, sou);
    362 
    363 		return 0;
    364 	}
    365 
    366 
    367 	/* we now know we want to set a mode */
    368 	mode = set->mode;
    369 	fb = set->fb;
    370 
    371 	if (set->x + mode->hdisplay > fb->width ||
    372 	    set->y + mode->vdisplay > fb->height) {
    373 		DRM_ERROR("set outside of framebuffer\n");
    374 		return -EINVAL;
    375 	}
    376 
    377 	vmw_svga_enable(dev_priv);
    378 
    379 	if (mode->hdisplay != crtc->mode.hdisplay ||
    380 	    mode->vdisplay != crtc->mode.vdisplay) {
    381 		/* no need to check if depth is different, because backing
    382 		 * store depth is forced to 4 by the device.
    383 		 */
    384 
    385 		ret = vmw_sou_fifo_destroy(dev_priv, sou);
    386 		/* the hardware has hung don't do anything more */
    387 		if (unlikely(ret != 0))
    388 			return ret;
    389 
    390 		vmw_sou_backing_free(dev_priv, sou);
    391 	}
    392 
    393 	if (!sou->buffer) {
    394 		/* forced to depth 4 by the device */
    395 		size_t size = mode->hdisplay * mode->vdisplay * 4;
    396 		ret = vmw_sou_backing_alloc(dev_priv, sou, size);
    397 		if (unlikely(ret != 0))
    398 			return ret;
    399 	}
    400 
    401 	ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
    402 	if (unlikely(ret != 0)) {
    403 		/*
    404 		 * We are in a bit of a situation here, the hardware has
    405 		 * hung and we may or may not have a buffer hanging of
    406 		 * the screen object, best thing to do is not do anything
    407 		 * if we where defined, if not just turn the crtc of.
    408 		 * Not what userspace wants but it needs to htfu.
    409 		 */
    410 		if (sou->defined)
    411 			return ret;
    412 
    413 		connector->encoder = NULL;
    414 		encoder->crtc = NULL;
    415 		crtc->primary->fb = NULL;
    416 		crtc->x = 0;
    417 		crtc->y = 0;
    418 		crtc->enabled = false;
    419 
    420 		return ret;
    421 	}
    422 
    423 	vmw_sou_add_active(dev_priv, sou, vfb);
    424 
    425 	connector->encoder = encoder;
    426 	encoder->crtc = crtc;
    427 	crtc->mode = *mode;
    428 	crtc->primary->fb = fb;
    429 	crtc->x = set->x;
    430 	crtc->y = set->y;
    431 	crtc->enabled = true;
    432 
    433 	return 0;
    434 }
    435 
    436 /**
    437  * Returns if this unit can be page flipped.
    438  * Must be called with the mode_config mutex held.
    439  */
    440 static bool vmw_sou_screen_object_flippable(struct vmw_private *dev_priv,
    441 					    struct drm_crtc *crtc)
    442 {
    443 	struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
    444 
    445 	if (!sou->base.is_implicit)
    446 		return true;
    447 
    448 	if (dev_priv->sou_priv->num_implicit != 1)
    449 		return false;
    450 
    451 	return true;
    452 }
    453 
    454 /**
    455  * Update the implicit fb to the current fb of this crtc.
    456  * Must be called with the mode_config mutex held.
    457  */
    458 static void vmw_sou_update_implicit_fb(struct vmw_private *dev_priv,
    459 				       struct drm_crtc *crtc)
    460 {
    461 	struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
    462 
    463 	BUG_ON(!sou->base.is_implicit);
    464 
    465 	dev_priv->sou_priv->implicit_fb =
    466 		vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
    467 }
    468 
    469 static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
    470 				  struct drm_framebuffer *fb,
    471 				  struct drm_pending_vblank_event *event,
    472 				  uint32_t flags)
    473 {
    474 	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
    475 	struct drm_framebuffer *old_fb = crtc->primary->fb;
    476 	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
    477 	struct vmw_fence_obj *fence = NULL;
    478 	struct drm_clip_rect clips;
    479 	int ret;
    480 
    481 	/* require ScreenObject support for page flipping */
    482 	if (!dev_priv->sou_priv)
    483 		return -ENOSYS;
    484 
    485 	if (!vmw_sou_screen_object_flippable(dev_priv, crtc))
    486 		return -EINVAL;
    487 
    488 	crtc->primary->fb = fb;
    489 
    490 	/* do a full screen dirty update */
    491 	clips.x1 = clips.y1 = 0;
    492 	clips.x2 = fb->width;
    493 	clips.y2 = fb->height;
    494 
    495 	if (vfb->dmabuf)
    496 		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
    497 						  &clips, 1, 1,
    498 						  true, &fence);
    499 	else
    500 		ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
    501 						   &clips, NULL, NULL,
    502 						   0, 0, 1, 1, &fence);
    503 
    504 
    505 	if (ret != 0)
    506 		goto out_no_fence;
    507 	if (!fence) {
    508 		ret = -EINVAL;
    509 		goto out_no_fence;
    510 	}
    511 
    512 	if (event) {
    513 		struct drm_file *file_priv = event->base.file_priv;
    514 
    515 		ret = vmw_event_fence_action_queue(file_priv, fence,
    516 						   &event->base,
    517 						   &event->event.tv_sec,
    518 						   &event->event.tv_usec,
    519 						   true);
    520 	}
    521 
    522 	/*
    523 	 * No need to hold on to this now. The only cleanup
    524 	 * we need to do if we fail is unref the fence.
    525 	 */
    526 	vmw_fence_obj_unreference(&fence);
    527 
    528 	if (vmw_crtc_to_du(crtc)->is_implicit)
    529 		vmw_sou_update_implicit_fb(dev_priv, crtc);
    530 
    531 	return ret;
    532 
    533 out_no_fence:
    534 	crtc->primary->fb = old_fb;
    535 	return ret;
    536 }
    537 
    538 static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
    539 	.save = vmw_du_crtc_save,
    540 	.restore = vmw_du_crtc_restore,
    541 	.cursor_set2 = vmw_du_crtc_cursor_set2,
    542 	.cursor_move = vmw_du_crtc_cursor_move,
    543 	.gamma_set = vmw_du_crtc_gamma_set,
    544 	.destroy = vmw_sou_crtc_destroy,
    545 	.set_config = vmw_sou_crtc_set_config,
    546 	.page_flip = vmw_sou_crtc_page_flip,
    547 };
    548 
    549 /*
    550  * Screen Object Display Unit encoder functions
    551  */
    552 
    553 static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
    554 {
    555 	vmw_sou_destroy(vmw_encoder_to_sou(encoder));
    556 }
    557 
    558 static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
    559 	.destroy = vmw_sou_encoder_destroy,
    560 };
    561 
    562 /*
    563  * Screen Object Display Unit connector functions
    564  */
    565 
    566 static void vmw_sou_connector_destroy(struct drm_connector *connector)
    567 {
    568 	vmw_sou_destroy(vmw_connector_to_sou(connector));
    569 }
    570 
    571 static struct drm_connector_funcs vmw_sou_connector_funcs = {
    572 	.dpms = vmw_du_connector_dpms,
    573 	.save = vmw_du_connector_save,
    574 	.restore = vmw_du_connector_restore,
    575 	.detect = vmw_du_connector_detect,
    576 	.fill_modes = vmw_du_connector_fill_modes,
    577 	.set_property = vmw_du_connector_set_property,
    578 	.destroy = vmw_sou_connector_destroy,
    579 };
    580 
    581 static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
    582 {
    583 	struct vmw_screen_object_unit *sou;
    584 	struct drm_device *dev = dev_priv->dev;
    585 	struct drm_connector *connector;
    586 	struct drm_encoder *encoder;
    587 	struct drm_crtc *crtc;
    588 
    589 	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
    590 	if (!sou)
    591 		return -ENOMEM;
    592 
    593 	sou->base.unit = unit;
    594 	crtc = &sou->base.crtc;
    595 	encoder = &sou->base.encoder;
    596 	connector = &sou->base.connector;
    597 
    598 	sou->active_implicit = false;
    599 
    600 	sou->base.pref_active = (unit == 0);
    601 	sou->base.pref_width = dev_priv->initial_width;
    602 	sou->base.pref_height = dev_priv->initial_height;
    603 	sou->base.pref_mode = NULL;
    604 	sou->base.is_implicit = true;
    605 
    606 	drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
    607 			   DRM_MODE_CONNECTOR_VIRTUAL);
    608 	connector->status = vmw_du_connector_detect(connector, true);
    609 
    610 	drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
    611 			 DRM_MODE_ENCODER_VIRTUAL);
    612 	drm_mode_connector_attach_encoder(connector, encoder);
    613 	encoder->possible_crtcs = (1 << unit);
    614 	encoder->possible_clones = 0;
    615 
    616 	(void) drm_connector_register(connector);
    617 
    618 	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
    619 
    620 	drm_mode_crtc_set_gamma_size(crtc, 256);
    621 
    622 	drm_object_attach_property(&connector->base,
    623 				      dev->mode_config.dirty_info_property,
    624 				      1);
    625 
    626 	return 0;
    627 }
    628 
    629 int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
    630 {
    631 	struct drm_device *dev = dev_priv->dev;
    632 	int i, ret;
    633 
    634 	if (dev_priv->sou_priv) {
    635 		DRM_INFO("sou system already on\n");
    636 		return -EINVAL;
    637 	}
    638 
    639 	if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
    640 		DRM_INFO("Not using screen objects,"
    641 			 " missing cap SCREEN_OBJECT_2\n");
    642 		return -ENOSYS;
    643 	}
    644 
    645 	ret = -ENOMEM;
    646 	dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
    647 	if (unlikely(!dev_priv->sou_priv))
    648 		goto err_no_mem;
    649 
    650 	dev_priv->sou_priv->num_implicit = 0;
    651 	dev_priv->sou_priv->implicit_fb = NULL;
    652 
    653 	ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
    654 	if (unlikely(ret != 0))
    655 		goto err_free;
    656 
    657 	ret = drm_mode_create_dirty_info_property(dev);
    658 	if (unlikely(ret != 0))
    659 		goto err_vblank_cleanup;
    660 
    661 	for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
    662 		vmw_sou_init(dev_priv, i);
    663 
    664 	dev_priv->active_display_unit = vmw_du_screen_object;
    665 
    666 	DRM_INFO("Screen Objects Display Unit initialized\n");
    667 
    668 	return 0;
    669 
    670 err_vblank_cleanup:
    671 	drm_vblank_cleanup(dev);
    672 err_free:
    673 	kfree(dev_priv->sou_priv);
    674 	dev_priv->sou_priv = NULL;
    675 err_no_mem:
    676 	return ret;
    677 }
    678 
    679 int vmw_kms_sou_close_display(struct vmw_private *dev_priv)
    680 {
    681 	struct drm_device *dev = dev_priv->dev;
    682 
    683 	if (!dev_priv->sou_priv)
    684 		return -ENOSYS;
    685 
    686 	drm_vblank_cleanup(dev);
    687 
    688 	kfree(dev_priv->sou_priv);
    689 
    690 	return 0;
    691 }
    692 
    693 static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv,
    694 				  struct vmw_framebuffer *framebuffer)
    695 {
    696 	struct vmw_dma_buffer *buf =
    697 		container_of(framebuffer, struct vmw_framebuffer_dmabuf,
    698 			     base)->buffer;
    699 	int depth = framebuffer->base.depth;
    700 	struct {
    701 		uint32_t header;
    702 		SVGAFifoCmdDefineGMRFB body;
    703 	} *cmd;
    704 
    705 	/* Emulate RGBA support, contrary to svga_reg.h this is not
    706 	 * supported by hosts. This is only a problem if we are reading
    707 	 * this value later and expecting what we uploaded back.
    708 	 */
    709 	if (depth == 32)
    710 		depth = 24;
    711 
    712 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
    713 	if (!cmd) {
    714 		DRM_ERROR("Out of fifo space for dirty framebuffer command.\n");
    715 		return -ENOMEM;
    716 	}
    717 
    718 	cmd->header = SVGA_CMD_DEFINE_GMRFB;
    719 	cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
    720 	cmd->body.format.colorDepth = depth;
    721 	cmd->body.format.reserved = 0;
    722 	cmd->body.bytesPerLine = framebuffer->base.pitches[0];
    723 	/* Buffer is reserved in vram or GMR */
    724 	vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr);
    725 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
    726 
    727 	return 0;
    728 }
    729 
    730 /**
    731  * vmw_sou_surface_fifo_commit - Callback to fill in and submit a
    732  * blit surface to screen command.
    733  *
    734  * @dirty: The closure structure.
    735  *
    736  * Fills in the missing fields in the command, and translates the cliprects
    737  * to match the destination bounding box encoded.
    738  */
    739 static void vmw_sou_surface_fifo_commit(struct vmw_kms_dirty *dirty)
    740 {
    741 	struct vmw_kms_sou_surface_dirty *sdirty =
    742 		container_of(dirty, typeof(*sdirty), base);
    743 	struct vmw_kms_sou_dirty_cmd *cmd = dirty->cmd;
    744 	s32 trans_x = dirty->unit->crtc.x - sdirty->dst_x;
    745 	s32 trans_y = dirty->unit->crtc.y - sdirty->dst_y;
    746 	size_t region_size = dirty->num_hits * sizeof(SVGASignedRect);
    747 	SVGASignedRect *blit = (SVGASignedRect *) &cmd[1];
    748 	int i;
    749 
    750 	cmd->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN;
    751 	cmd->header.size = sizeof(cmd->body) + region_size;
    752 
    753 	/*
    754 	 * Use the destination bounding box to specify destination - and
    755 	 * source bounding regions.
    756 	 */
    757 	cmd->body.destRect.left = sdirty->left;
    758 	cmd->body.destRect.right = sdirty->right;
    759 	cmd->body.destRect.top = sdirty->top;
    760 	cmd->body.destRect.bottom = sdirty->bottom;
    761 
    762 	cmd->body.srcRect.left = sdirty->left + trans_x;
    763 	cmd->body.srcRect.right = sdirty->right + trans_x;
    764 	cmd->body.srcRect.top = sdirty->top + trans_y;
    765 	cmd->body.srcRect.bottom = sdirty->bottom + trans_y;
    766 
    767 	cmd->body.srcImage.sid = sdirty->sid;
    768 	cmd->body.destScreenId = dirty->unit->unit;
    769 
    770 	/* Blits are relative to the destination rect. Translate. */
    771 	for (i = 0; i < dirty->num_hits; ++i, ++blit) {
    772 		blit->left -= sdirty->left;
    773 		blit->right -= sdirty->left;
    774 		blit->top -= sdirty->top;
    775 		blit->bottom -= sdirty->top;
    776 	}
    777 
    778 	vmw_fifo_commit(dirty->dev_priv, region_size + sizeof(*cmd));
    779 
    780 	sdirty->left = sdirty->top = S32_MAX;
    781 	sdirty->right = sdirty->bottom = S32_MIN;
    782 }
    783 
    784 /**
    785  * vmw_sou_surface_clip - Callback to encode a blit surface to screen cliprect.
    786  *
    787  * @dirty: The closure structure
    788  *
    789  * Encodes a SVGASignedRect cliprect and updates the bounding box of the
    790  * BLIT_SURFACE_TO_SCREEN command.
    791  */
    792 static void vmw_sou_surface_clip(struct vmw_kms_dirty *dirty)
    793 {
    794 	struct vmw_kms_sou_surface_dirty *sdirty =
    795 		container_of(dirty, typeof(*sdirty), base);
    796 	struct vmw_kms_sou_dirty_cmd *cmd = dirty->cmd;
    797 	SVGASignedRect *blit = (SVGASignedRect *) &cmd[1];
    798 
    799 	/* Destination rect. */
    800 	blit += dirty->num_hits;
    801 	blit->left = dirty->unit_x1;
    802 	blit->top = dirty->unit_y1;
    803 	blit->right = dirty->unit_x2;
    804 	blit->bottom = dirty->unit_y2;
    805 
    806 	/* Destination bounding box */
    807 	sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1);
    808 	sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1);
    809 	sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2);
    810 	sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2);
    811 
    812 	dirty->num_hits++;
    813 }
    814 
    815 /**
    816  * vmw_kms_sou_do_surface_dirty - Dirty part of a surface backed framebuffer
    817  *
    818  * @dev_priv: Pointer to the device private structure.
    819  * @framebuffer: Pointer to the surface-buffer backed framebuffer.
    820  * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
    821  * @vclips: Alternate array of clip rects. Either @clips or @vclips must
    822  * be NULL.
    823  * @srf: Pointer to surface to blit from. If NULL, the surface attached
    824  * to @framebuffer will be used.
    825  * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
    826  * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
    827  * @num_clips: Number of clip rects in @clips.
    828  * @inc: Increment to use when looping over @clips.
    829  * @out_fence: If non-NULL, will return a ref-counted pointer to a
    830  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
    831  * case the device has already synchronized.
    832  *
    833  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
    834  * interrupted.
    835  */
    836 int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
    837 				 struct vmw_framebuffer *framebuffer,
    838 				 struct drm_clip_rect *clips,
    839 				 struct drm_vmw_rect *vclips,
    840 				 struct vmw_resource *srf,
    841 				 s32 dest_x,
    842 				 s32 dest_y,
    843 				 unsigned num_clips, int inc,
    844 				 struct vmw_fence_obj **out_fence)
    845 {
    846 	struct vmw_framebuffer_surface *vfbs =
    847 		container_of(framebuffer, typeof(*vfbs), base);
    848 	struct vmw_kms_sou_surface_dirty sdirty;
    849 	struct vmw_validation_ctx ctx;
    850 	int ret;
    851 
    852 	if (!srf)
    853 		srf = &vfbs->surface->res;
    854 
    855 	ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
    856 	if (ret)
    857 		return ret;
    858 
    859 	sdirty.base.fifo_commit = vmw_sou_surface_fifo_commit;
    860 	sdirty.base.clip = vmw_sou_surface_clip;
    861 	sdirty.base.dev_priv = dev_priv;
    862 	sdirty.base.fifo_reserve_size = sizeof(struct vmw_kms_sou_dirty_cmd) +
    863 	  sizeof(SVGASignedRect) * num_clips;
    864 
    865 	sdirty.sid = srf->id;
    866 	sdirty.left = sdirty.top = S32_MAX;
    867 	sdirty.right = sdirty.bottom = S32_MIN;
    868 	sdirty.dst_x = dest_x;
    869 	sdirty.dst_y = dest_y;
    870 
    871 	ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
    872 				   dest_x, dest_y, num_clips, inc,
    873 				   &sdirty.base);
    874 	vmw_kms_helper_resource_finish(&ctx, out_fence);
    875 
    876 	return ret;
    877 }
    878 
    879 /**
    880  * vmw_sou_dmabuf_fifo_commit - Callback to submit a set of readback clips.
    881  *
    882  * @dirty: The closure structure.
    883  *
    884  * Commits a previously built command buffer of readback clips.
    885  */
    886 static void vmw_sou_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
    887 {
    888 	vmw_fifo_commit(dirty->dev_priv,
    889 			sizeof(struct vmw_kms_sou_dmabuf_blit) *
    890 			dirty->num_hits);
    891 }
    892 
    893 /**
    894  * vmw_sou_dmabuf_clip - Callback to encode a readback cliprect.
    895  *
    896  * @dirty: The closure structure
    897  *
    898  * Encodes a BLIT_GMRFB_TO_SCREEN cliprect.
    899  */
    900 static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty)
    901 {
    902 	struct vmw_kms_sou_dmabuf_blit *blit = dirty->cmd;
    903 
    904 	blit += dirty->num_hits;
    905 	blit->header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
    906 	blit->body.destScreenId = dirty->unit->unit;
    907 	blit->body.srcOrigin.x = dirty->fb_x;
    908 	blit->body.srcOrigin.y = dirty->fb_y;
    909 	blit->body.destRect.left = dirty->unit_x1;
    910 	blit->body.destRect.top = dirty->unit_y1;
    911 	blit->body.destRect.right = dirty->unit_x2;
    912 	blit->body.destRect.bottom = dirty->unit_y2;
    913 	dirty->num_hits++;
    914 }
    915 
    916 /**
    917  * vmw_kms_do_dmabuf_dirty - Dirty part of a dma-buffer backed framebuffer
    918  *
    919  * @dev_priv: Pointer to the device private structure.
    920  * @framebuffer: Pointer to the dma-buffer backed framebuffer.
    921  * @clips: Array of clip rects.
    922  * @num_clips: Number of clip rects in @clips.
    923  * @increment: Increment to use when looping over @clips.
    924  * @interruptible: Whether to perform waits interruptible if possible.
    925  * @out_fence: If non-NULL, will return a ref-counted pointer to a
    926  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
    927  * case the device has already synchronized.
    928  *
    929  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
    930  * interrupted.
    931  */
    932 int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
    933 				struct vmw_framebuffer *framebuffer,
    934 				struct drm_clip_rect *clips,
    935 				unsigned num_clips, int increment,
    936 				bool interruptible,
    937 				struct vmw_fence_obj **out_fence)
    938 {
    939 	struct vmw_dma_buffer *buf =
    940 		container_of(framebuffer, struct vmw_framebuffer_dmabuf,
    941 			     base)->buffer;
    942 	struct vmw_kms_dirty dirty;
    943 	int ret;
    944 
    945 	ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible,
    946 					    false);
    947 	if (ret)
    948 		return ret;
    949 
    950 	ret = do_dmabuf_define_gmrfb(dev_priv, framebuffer);
    951 	if (unlikely(ret != 0))
    952 		goto out_revert;
    953 
    954 	dirty.fifo_commit = vmw_sou_dmabuf_fifo_commit;
    955 	dirty.clip = vmw_sou_dmabuf_clip;
    956 	dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_dmabuf_blit) *
    957 		num_clips;
    958 	ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, NULL,
    959 				   0, 0, num_clips, increment, &dirty);
    960 	vmw_kms_helper_buffer_finish(dev_priv, NULL, buf, out_fence, NULL);
    961 
    962 	return ret;
    963 
    964 out_revert:
    965 	vmw_kms_helper_buffer_revert(buf);
    966 
    967 	return ret;
    968 }
    969 
    970 
    971 /**
    972  * vmw_sou_readback_fifo_commit - Callback to submit a set of readback clips.
    973  *
    974  * @dirty: The closure structure.
    975  *
    976  * Commits a previously built command buffer of readback clips.
    977  */
    978 static void vmw_sou_readback_fifo_commit(struct vmw_kms_dirty *dirty)
    979 {
    980 	vmw_fifo_commit(dirty->dev_priv,
    981 			sizeof(struct vmw_kms_sou_readback_blit) *
    982 			dirty->num_hits);
    983 }
    984 
    985 /**
    986  * vmw_sou_readback_clip - Callback to encode a readback cliprect.
    987  *
    988  * @dirty: The closure structure
    989  *
    990  * Encodes a BLIT_SCREEN_TO_GMRFB cliprect.
    991  */
    992 static void vmw_sou_readback_clip(struct vmw_kms_dirty *dirty)
    993 {
    994 	struct vmw_kms_sou_readback_blit *blit = dirty->cmd;
    995 
    996 	blit += dirty->num_hits;
    997 	blit->header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB;
    998 	blit->body.srcScreenId = dirty->unit->unit;
    999 	blit->body.destOrigin.x = dirty->fb_x;
   1000 	blit->body.destOrigin.y = dirty->fb_y;
   1001 	blit->body.srcRect.left = dirty->unit_x1;
   1002 	blit->body.srcRect.top = dirty->unit_y1;
   1003 	blit->body.srcRect.right = dirty->unit_x2;
   1004 	blit->body.srcRect.bottom = dirty->unit_y2;
   1005 	dirty->num_hits++;
   1006 }
   1007 
   1008 /**
   1009  * vmw_kms_sou_readback - Perform a readback from the screen object system to
   1010  * a dma-buffer backed framebuffer.
   1011  *
   1012  * @dev_priv: Pointer to the device private structure.
   1013  * @file_priv: Pointer to a struct drm_file identifying the caller.
   1014  * Must be set to NULL if @user_fence_rep is NULL.
   1015  * @vfb: Pointer to the dma-buffer backed framebuffer.
   1016  * @user_fence_rep: User-space provided structure for fence information.
   1017  * Must be set to non-NULL if @file_priv is non-NULL.
   1018  * @vclips: Array of clip rects.
   1019  * @num_clips: Number of clip rects in @vclips.
   1020  *
   1021  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
   1022  * interrupted.
   1023  */
   1024 int vmw_kms_sou_readback(struct vmw_private *dev_priv,
   1025 			 struct drm_file *file_priv,
   1026 			 struct vmw_framebuffer *vfb,
   1027 			 struct drm_vmw_fence_rep __user *user_fence_rep,
   1028 			 struct drm_vmw_rect *vclips,
   1029 			 uint32_t num_clips)
   1030 {
   1031 	struct vmw_dma_buffer *buf =
   1032 		container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer;
   1033 	struct vmw_kms_dirty dirty;
   1034 	int ret;
   1035 
   1036 	ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, true, false);
   1037 	if (ret)
   1038 		return ret;
   1039 
   1040 	ret = do_dmabuf_define_gmrfb(dev_priv, vfb);
   1041 	if (unlikely(ret != 0))
   1042 		goto out_revert;
   1043 
   1044 	dirty.fifo_commit = vmw_sou_readback_fifo_commit;
   1045 	dirty.clip = vmw_sou_readback_clip;
   1046 	dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_readback_blit) *
   1047 		num_clips;
   1048 	ret = vmw_kms_helper_dirty(dev_priv, vfb, NULL, vclips,
   1049 				   0, 0, num_clips, 1, &dirty);
   1050 	vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL,
   1051 				     user_fence_rep);
   1052 
   1053 	return ret;
   1054 
   1055 out_revert:
   1056 	vmw_kms_helper_buffer_revert(buf);
   1057 
   1058 	return ret;
   1059 }
   1060