Home | History | Annotate | Line # | Download | only in vmwgfx
      1 /*	$NetBSD: vmwgfx_scrn.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
      2 
      3 // SPDX-License-Identifier: GPL-2.0 OR MIT
      4 /**************************************************************************
      5  *
      6  * Copyright 2011-2015 VMware, Inc., Palo Alto, CA., USA
      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.3 2021/12/18 23:45:45 riastradh Exp $");
     32 
     33 #include <drm/drm_atomic.h>
     34 #include <drm/drm_atomic_helper.h>
     35 #include <drm/drm_damage_helper.h>
     36 #include <drm/drm_fourcc.h>
     37 #include <drm/drm_plane_helper.h>
     38 #include <drm/drm_vblank.h>
     39 
     40 #include "vmwgfx_kms.h"
     41 
     42 #define vmw_crtc_to_sou(x) \
     43 	container_of(x, struct vmw_screen_object_unit, base.crtc)
     44 #define vmw_encoder_to_sou(x) \
     45 	container_of(x, struct vmw_screen_object_unit, base.encoder)
     46 #define vmw_connector_to_sou(x) \
     47 	container_of(x, struct vmw_screen_object_unit, base.connector)
     48 
     49 /**
     50  * struct vmw_kms_sou_surface_dirty - Closure structure for
     51  * blit surface to screen command.
     52  * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
     53  * @left: Left side of bounding box.
     54  * @right: Right side of bounding box.
     55  * @top: Top side of bounding box.
     56  * @bottom: Bottom side of bounding box.
     57  * @dst_x: Difference between source clip rects and framebuffer coordinates.
     58  * @dst_y: Difference between source clip rects and framebuffer coordinates.
     59  * @sid: Surface id of surface to copy from.
     60  */
     61 struct vmw_kms_sou_surface_dirty {
     62 	struct vmw_kms_dirty base;
     63 	s32 left, right, top, bottom;
     64 	s32 dst_x, dst_y;
     65 	u32 sid;
     66 };
     67 
     68 /*
     69  * SVGA commands that are used by this code. Please see the device headers
     70  * for explanation.
     71  */
     72 struct vmw_kms_sou_readback_blit {
     73 	uint32 header;
     74 	SVGAFifoCmdBlitScreenToGMRFB body;
     75 };
     76 
     77 struct vmw_kms_sou_bo_blit {
     78 	uint32 header;
     79 	SVGAFifoCmdBlitGMRFBToScreen body;
     80 };
     81 
     82 struct vmw_kms_sou_dirty_cmd {
     83 	SVGA3dCmdHeader header;
     84 	SVGA3dCmdBlitSurfaceToScreen body;
     85 };
     86 
     87 struct vmw_kms_sou_define_gmrfb {
     88 	uint32_t header;
     89 	SVGAFifoCmdDefineGMRFB body;
     90 };
     91 
     92 /**
     93  * Display unit using screen objects.
     94  */
     95 struct vmw_screen_object_unit {
     96 	struct vmw_display_unit base;
     97 
     98 	unsigned long buffer_size; /**< Size of allocated buffer */
     99 	struct vmw_buffer_object *buffer; /**< Backing store buffer */
    100 
    101 	bool defined;
    102 };
    103 
    104 static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
    105 {
    106 	vmw_du_cleanup(&sou->base);
    107 	kfree(sou);
    108 }
    109 
    110 
    111 /*
    112  * Screen Object Display Unit CRTC functions
    113  */
    114 
    115 static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
    116 {
    117 	vmw_sou_destroy(vmw_crtc_to_sou(crtc));
    118 }
    119 
    120 /**
    121  * Send the fifo command to create a screen.
    122  */
    123 static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
    124 			       struct vmw_screen_object_unit *sou,
    125 			       int x, int y,
    126 			       struct drm_display_mode *mode)
    127 {
    128 	size_t fifo_size;
    129 
    130 	struct {
    131 		struct {
    132 			uint32_t cmdType;
    133 		} header;
    134 		SVGAScreenObject obj;
    135 	} *cmd;
    136 
    137 	BUG_ON(!sou->buffer);
    138 
    139 	fifo_size = sizeof(*cmd);
    140 	cmd = VMW_FIFO_RESERVE(dev_priv, fifo_size);
    141 	if (unlikely(cmd == NULL))
    142 		return -ENOMEM;
    143 
    144 	memset(cmd, 0, fifo_size);
    145 	cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
    146 	cmd->obj.structSize = sizeof(SVGAScreenObject);
    147 	cmd->obj.id = sou->base.unit;
    148 	cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
    149 		(sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
    150 	cmd->obj.size.width = mode->hdisplay;
    151 	cmd->obj.size.height = mode->vdisplay;
    152 	cmd->obj.root.x = x;
    153 	cmd->obj.root.y = y;
    154 	sou->base.set_gui_x = cmd->obj.root.x;
    155 	sou->base.set_gui_y = cmd->obj.root.y;
    156 
    157 	/* Ok to assume that buffer is pinned in vram */
    158 	vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
    159 	cmd->obj.backingStore.pitch = mode->hdisplay * 4;
    160 
    161 	vmw_fifo_commit(dev_priv, fifo_size);
    162 
    163 	sou->defined = true;
    164 
    165 	return 0;
    166 }
    167 
    168 /**
    169  * Send the fifo command to destroy a screen.
    170  */
    171 static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
    172 				struct vmw_screen_object_unit *sou)
    173 {
    174 	size_t fifo_size;
    175 	int ret;
    176 
    177 	struct {
    178 		struct {
    179 			uint32_t cmdType;
    180 		} header;
    181 		SVGAFifoCmdDestroyScreen body;
    182 	} *cmd;
    183 
    184 	/* no need to do anything */
    185 	if (unlikely(!sou->defined))
    186 		return 0;
    187 
    188 	fifo_size = sizeof(*cmd);
    189 	cmd = VMW_FIFO_RESERVE(dev_priv, fifo_size);
    190 	if (unlikely(cmd == NULL))
    191 		return -ENOMEM;
    192 
    193 	memset(cmd, 0, fifo_size);
    194 	cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
    195 	cmd->body.screenId = sou->base.unit;
    196 
    197 	vmw_fifo_commit(dev_priv, fifo_size);
    198 
    199 	/* Force sync */
    200 	ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
    201 	if (unlikely(ret != 0))
    202 		DRM_ERROR("Failed to sync with HW");
    203 	else
    204 		sou->defined = false;
    205 
    206 	return ret;
    207 }
    208 
    209 /**
    210  * vmw_sou_crtc_mode_set_nofb - Create new screen
    211  *
    212  * @crtc: CRTC associated with the new screen
    213  *
    214  * This function creates/destroys a screen.  This function cannot fail, so if
    215  * somehow we run into a failure, just do the best we can to get out.
    216  */
    217 static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc)
    218 {
    219 	struct vmw_private *dev_priv;
    220 	struct vmw_screen_object_unit *sou;
    221 	struct vmw_framebuffer *vfb;
    222 	struct drm_framebuffer *fb;
    223 	struct drm_plane_state *ps;
    224 	struct vmw_plane_state *vps;
    225 	int ret;
    226 
    227 	sou = vmw_crtc_to_sou(crtc);
    228 	dev_priv = vmw_priv(crtc->dev);
    229 	ps = crtc->primary->state;
    230 	fb = ps->fb;
    231 	vps = vmw_plane_state_to_vps(ps);
    232 
    233 	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
    234 
    235 	if (sou->defined) {
    236 		ret = vmw_sou_fifo_destroy(dev_priv, sou);
    237 		if (ret) {
    238 			DRM_ERROR("Failed to destroy Screen Object\n");
    239 			return;
    240 		}
    241 	}
    242 
    243 	if (vfb) {
    244 		struct drm_connector_state *conn_state;
    245 		struct vmw_connector_state *vmw_conn_state;
    246 		int x, y;
    247 
    248 		sou->buffer = vps->bo;
    249 		sou->buffer_size = vps->bo_size;
    250 
    251 		conn_state = sou->base.connector.state;
    252 		vmw_conn_state = vmw_connector_state_to_vcs(conn_state);
    253 
    254 		x = vmw_conn_state->gui_x;
    255 		y = vmw_conn_state->gui_y;
    256 
    257 		ret = vmw_sou_fifo_create(dev_priv, sou, x, y, &crtc->mode);
    258 		if (ret)
    259 			DRM_ERROR("Failed to define Screen Object %dx%d\n",
    260 				  crtc->x, crtc->y);
    261 
    262 	} else {
    263 		sou->buffer = NULL;
    264 		sou->buffer_size = 0;
    265 	}
    266 }
    267 
    268 /**
    269  * vmw_sou_crtc_helper_prepare - Noop
    270  *
    271  * @crtc: CRTC associated with the new screen
    272  *
    273  * Prepares the CRTC for a mode set, but we don't need to do anything here.
    274  */
    275 static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc)
    276 {
    277 }
    278 
    279 /**
    280  * vmw_sou_crtc_atomic_enable - Noop
    281  *
    282  * @crtc: CRTC associated with the new screen
    283  *
    284  * This is called after a mode set has been completed.
    285  */
    286 static void vmw_sou_crtc_atomic_enable(struct drm_crtc *crtc,
    287 				       struct drm_crtc_state *old_state)
    288 {
    289 }
    290 
    291 /**
    292  * vmw_sou_crtc_atomic_disable - Turns off CRTC
    293  *
    294  * @crtc: CRTC to be turned off
    295  */
    296 static void vmw_sou_crtc_atomic_disable(struct drm_crtc *crtc,
    297 					struct drm_crtc_state *old_state)
    298 {
    299 	struct vmw_private *dev_priv;
    300 	struct vmw_screen_object_unit *sou;
    301 	int ret;
    302 
    303 
    304 	if (!crtc) {
    305 		DRM_ERROR("CRTC is NULL\n");
    306 		return;
    307 	}
    308 
    309 	sou = vmw_crtc_to_sou(crtc);
    310 	dev_priv = vmw_priv(crtc->dev);
    311 
    312 	if (sou->defined) {
    313 		ret = vmw_sou_fifo_destroy(dev_priv, sou);
    314 		if (ret)
    315 			DRM_ERROR("Failed to destroy Screen Object\n");
    316 	}
    317 }
    318 
    319 static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
    320 	.gamma_set = vmw_du_crtc_gamma_set,
    321 	.destroy = vmw_sou_crtc_destroy,
    322 	.reset = vmw_du_crtc_reset,
    323 	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
    324 	.atomic_destroy_state = vmw_du_crtc_destroy_state,
    325 	.set_config = drm_atomic_helper_set_config,
    326 	.page_flip = drm_atomic_helper_page_flip,
    327 };
    328 
    329 /*
    330  * Screen Object Display Unit encoder functions
    331  */
    332 
    333 static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
    334 {
    335 	vmw_sou_destroy(vmw_encoder_to_sou(encoder));
    336 }
    337 
    338 static const struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
    339 	.destroy = vmw_sou_encoder_destroy,
    340 };
    341 
    342 /*
    343  * Screen Object Display Unit connector functions
    344  */
    345 
    346 static void vmw_sou_connector_destroy(struct drm_connector *connector)
    347 {
    348 	vmw_sou_destroy(vmw_connector_to_sou(connector));
    349 }
    350 
    351 static const struct drm_connector_funcs vmw_sou_connector_funcs = {
    352 	.dpms = vmw_du_connector_dpms,
    353 	.detect = vmw_du_connector_detect,
    354 	.fill_modes = vmw_du_connector_fill_modes,
    355 	.destroy = vmw_sou_connector_destroy,
    356 	.reset = vmw_du_connector_reset,
    357 	.atomic_duplicate_state = vmw_du_connector_duplicate_state,
    358 	.atomic_destroy_state = vmw_du_connector_destroy_state,
    359 };
    360 
    361 
    362 static const struct
    363 drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
    364 };
    365 
    366 
    367 
    368 /*
    369  * Screen Object Display Plane Functions
    370  */
    371 
    372 /**
    373  * vmw_sou_primary_plane_cleanup_fb - Frees sou backing buffer
    374  *
    375  * @plane:  display plane
    376  * @old_state: Contains the FB to clean up
    377  *
    378  * Unpins the display surface
    379  *
    380  * Returns 0 on success
    381  */
    382 static void
    383 vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane,
    384 				 struct drm_plane_state *old_state)
    385 {
    386 	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
    387 	struct drm_crtc *crtc = plane->state->crtc ?
    388 		plane->state->crtc : old_state->crtc;
    389 
    390 	if (vps->bo)
    391 		vmw_bo_unpin(vmw_priv(crtc->dev), vps->bo, false);
    392 	vmw_bo_unreference(&vps->bo);
    393 	vps->bo_size = 0;
    394 
    395 	vmw_du_plane_cleanup_fb(plane, old_state);
    396 }
    397 
    398 
    399 /**
    400  * vmw_sou_primary_plane_prepare_fb - allocate backing buffer
    401  *
    402  * @plane:  display plane
    403  * @new_state: info on the new plane state, including the FB
    404  *
    405  * The SOU backing buffer is our equivalent of the display plane.
    406  *
    407  * Returns 0 on success
    408  */
    409 static int
    410 vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane,
    411 				 struct drm_plane_state *new_state)
    412 {
    413 	struct drm_framebuffer *new_fb = new_state->fb;
    414 	struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc;
    415 	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
    416 	struct vmw_private *dev_priv;
    417 	size_t size;
    418 	int ret;
    419 
    420 
    421 	if (!new_fb) {
    422 		vmw_bo_unreference(&vps->bo);
    423 		vps->bo_size = 0;
    424 
    425 		return 0;
    426 	}
    427 
    428 	size = new_state->crtc_w * new_state->crtc_h * 4;
    429 	dev_priv = vmw_priv(crtc->dev);
    430 
    431 	if (vps->bo) {
    432 		if (vps->bo_size == size) {
    433 			/*
    434 			 * Note that this might temporarily up the pin-count
    435 			 * to 2, until cleanup_fb() is called.
    436 			 */
    437 			return vmw_bo_pin_in_vram(dev_priv, vps->bo,
    438 						      true);
    439 		}
    440 
    441 		vmw_bo_unreference(&vps->bo);
    442 		vps->bo_size = 0;
    443 	}
    444 
    445 	vps->bo = kzalloc(sizeof(*vps->bo), GFP_KERNEL);
    446 	if (!vps->bo)
    447 		return -ENOMEM;
    448 
    449 	vmw_svga_enable(dev_priv);
    450 
    451 	/* After we have alloced the backing store might not be able to
    452 	 * resume the overlays, this is preferred to failing to alloc.
    453 	 */
    454 	vmw_overlay_pause_all(dev_priv);
    455 	ret = vmw_bo_init(dev_priv, vps->bo, size,
    456 			      &vmw_vram_ne_placement,
    457 			      false, &vmw_bo_bo_free);
    458 	vmw_overlay_resume_all(dev_priv);
    459 	if (ret) {
    460 		vps->bo = NULL; /* vmw_bo_init frees on error */
    461 		return ret;
    462 	}
    463 
    464 	vps->bo_size = size;
    465 
    466 	/*
    467 	 * TTM already thinks the buffer is pinned, but make sure the
    468 	 * pin_count is upped.
    469 	 */
    470 	return vmw_bo_pin_in_vram(dev_priv, vps->bo, true);
    471 }
    472 
    473 static uint32_t vmw_sou_bo_fifo_size(struct vmw_du_update_plane *update,
    474 				     uint32_t num_hits)
    475 {
    476 	return sizeof(struct vmw_kms_sou_define_gmrfb) +
    477 		sizeof(struct vmw_kms_sou_bo_blit) * num_hits;
    478 }
    479 
    480 static uint32_t vmw_sou_bo_define_gmrfb(struct vmw_du_update_plane *update,
    481 					void *cmd)
    482 {
    483 	struct vmw_framebuffer_bo *vfbbo =
    484 		container_of(update->vfb, typeof(*vfbbo), base);
    485 	struct vmw_kms_sou_define_gmrfb *gmr = cmd;
    486 	int depth = update->vfb->base.format->depth;
    487 
    488 	/* Emulate RGBA support, contrary to svga_reg.h this is not
    489 	 * supported by hosts. This is only a problem if we are reading
    490 	 * this value later and expecting what we uploaded back.
    491 	 */
    492 	if (depth == 32)
    493 		depth = 24;
    494 
    495 	gmr->header = SVGA_CMD_DEFINE_GMRFB;
    496 
    497 	gmr->body.format.bitsPerPixel = update->vfb->base.format->cpp[0] * 8;
    498 	gmr->body.format.colorDepth = depth;
    499 	gmr->body.format.reserved = 0;
    500 	gmr->body.bytesPerLine = update->vfb->base.pitches[0];
    501 	vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &gmr->body.ptr);
    502 
    503 	return sizeof(*gmr);
    504 }
    505 
    506 static uint32_t vmw_sou_bo_populate_clip(struct vmw_du_update_plane  *update,
    507 					 void *cmd, struct drm_rect *clip,
    508 					 uint32_t fb_x, uint32_t fb_y)
    509 {
    510 	struct vmw_kms_sou_bo_blit *blit = cmd;
    511 
    512 	blit->header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
    513 	blit->body.destScreenId = update->du->unit;
    514 	blit->body.srcOrigin.x = fb_x;
    515 	blit->body.srcOrigin.y = fb_y;
    516 	blit->body.destRect.left = clip->x1;
    517 	blit->body.destRect.top = clip->y1;
    518 	blit->body.destRect.right = clip->x2;
    519 	blit->body.destRect.bottom = clip->y2;
    520 
    521 	return sizeof(*blit);
    522 }
    523 
    524 static uint32_t vmw_stud_bo_post_clip(struct vmw_du_update_plane  *update,
    525 				      void *cmd, struct drm_rect *bb)
    526 {
    527 	return 0;
    528 }
    529 
    530 /**
    531  * vmw_sou_plane_update_bo - Update display unit for bo backed fb.
    532  * @dev_priv: Device private.
    533  * @plane: Plane state.
    534  * @old_state: Old plane state.
    535  * @vfb: Framebuffer which is blitted to display unit.
    536  * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
    537  *             The returned fence pointer may be NULL in which case the device
    538  *             has already synchronized.
    539  *
    540  * Return: 0 on success or a negative error code on failure.
    541  */
    542 static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv,
    543 				   struct drm_plane *plane,
    544 				   struct drm_plane_state *old_state,
    545 				   struct vmw_framebuffer *vfb,
    546 				   struct vmw_fence_obj **out_fence)
    547 {
    548 	struct vmw_du_update_plane_buffer bo_update;
    549 
    550 	memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
    551 	bo_update.base.plane = plane;
    552 	bo_update.base.old_state = old_state;
    553 	bo_update.base.dev_priv = dev_priv;
    554 	bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
    555 	bo_update.base.vfb = vfb;
    556 	bo_update.base.out_fence = out_fence;
    557 	bo_update.base.mutex = NULL;
    558 	bo_update.base.cpu_blit = false;
    559 	bo_update.base.intr = true;
    560 
    561 	bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size;
    562 	bo_update.base.post_prepare = vmw_sou_bo_define_gmrfb;
    563 	bo_update.base.clip = vmw_sou_bo_populate_clip;
    564 	bo_update.base.post_clip = vmw_stud_bo_post_clip;
    565 
    566 	return vmw_du_helper_plane_update(&bo_update.base);
    567 }
    568 
    569 static uint32_t vmw_sou_surface_fifo_size(struct vmw_du_update_plane *update,
    570 					  uint32_t num_hits)
    571 {
    572 	return sizeof(struct vmw_kms_sou_dirty_cmd) + sizeof(SVGASignedRect) *
    573 		num_hits;
    574 }
    575 
    576 static uint32_t vmw_sou_surface_post_prepare(struct vmw_du_update_plane *update,
    577 					     void *cmd)
    578 {
    579 	struct vmw_du_update_plane_surface *srf_update;
    580 
    581 	srf_update = container_of(update, typeof(*srf_update), base);
    582 
    583 	/*
    584 	 * SOU SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN is special in the sense that
    585 	 * its bounding box is filled before iterating over all the clips. So
    586 	 * store the FIFO start address and revisit to fill the details.
    587 	 */
    588 	srf_update->cmd_start = cmd;
    589 
    590 	return 0;
    591 }
    592 
    593 static uint32_t vmw_sou_surface_pre_clip(struct vmw_du_update_plane *update,
    594 					 void *cmd, uint32_t num_hits)
    595 {
    596 	struct vmw_kms_sou_dirty_cmd *blit = cmd;
    597 	struct vmw_framebuffer_surface *vfbs;
    598 
    599 	vfbs = container_of(update->vfb, typeof(*vfbs), base);
    600 
    601 	blit->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN;
    602 	blit->header.size = sizeof(blit->body) + sizeof(SVGASignedRect) *
    603 		num_hits;
    604 
    605 	blit->body.srcImage.sid = vfbs->surface->res.id;
    606 	blit->body.destScreenId = update->du->unit;
    607 
    608 	/* Update the source and destination bounding box later in post_clip */
    609 	blit->body.srcRect.left = 0;
    610 	blit->body.srcRect.top = 0;
    611 	blit->body.srcRect.right = 0;
    612 	blit->body.srcRect.bottom = 0;
    613 
    614 	blit->body.destRect.left = 0;
    615 	blit->body.destRect.top = 0;
    616 	blit->body.destRect.right = 0;
    617 	blit->body.destRect.bottom = 0;
    618 
    619 	return sizeof(*blit);
    620 }
    621 
    622 static uint32_t vmw_sou_surface_clip_rect(struct vmw_du_update_plane *update,
    623 					  void *cmd, struct drm_rect *clip,
    624 					  uint32_t src_x, uint32_t src_y)
    625 {
    626 	SVGASignedRect *rect = cmd;
    627 
    628 	/*
    629 	 * rects are relative to dest bounding box rect on screen object, so
    630 	 * translate to it later in post_clip
    631 	 */
    632 	rect->left = clip->x1;
    633 	rect->top = clip->y1;
    634 	rect->right = clip->x2;
    635 	rect->bottom = clip->y2;
    636 
    637 	return sizeof(*rect);
    638 }
    639 
    640 static uint32_t vmw_sou_surface_post_clip(struct vmw_du_update_plane *update,
    641 					  void *cmd, struct drm_rect *bb)
    642 {
    643 	struct vmw_du_update_plane_surface *srf_update;
    644 	struct drm_plane_state *state = update->plane->state;
    645 	struct drm_rect src_bb;
    646 	struct vmw_kms_sou_dirty_cmd *blit;
    647 	SVGASignedRect *rect;
    648 	uint32_t num_hits;
    649 	int translate_src_x;
    650 	int translate_src_y;
    651 	int i;
    652 
    653 	srf_update = container_of(update, typeof(*srf_update), base);
    654 
    655 	blit = srf_update->cmd_start;
    656 	rect = (SVGASignedRect *)&blit[1];
    657 
    658 	num_hits = (blit->header.size - sizeof(blit->body))/
    659 		sizeof(SVGASignedRect);
    660 
    661 	src_bb = *bb;
    662 
    663 	/* To translate bb back to fb src coord */
    664 	translate_src_x = (state->src_x >> 16) - state->crtc_x;
    665 	translate_src_y = (state->src_y >> 16) - state->crtc_y;
    666 
    667 	drm_rect_translate(&src_bb, translate_src_x, translate_src_y);
    668 
    669 	blit->body.srcRect.left = src_bb.x1;
    670 	blit->body.srcRect.top = src_bb.y1;
    671 	blit->body.srcRect.right = src_bb.x2;
    672 	blit->body.srcRect.bottom = src_bb.y2;
    673 
    674 	blit->body.destRect.left = bb->x1;
    675 	blit->body.destRect.top = bb->y1;
    676 	blit->body.destRect.right = bb->x2;
    677 	blit->body.destRect.bottom = bb->y2;
    678 
    679 	/* rects are relative to dest bb rect */
    680 	for (i = 0; i < num_hits; i++) {
    681 		rect->left -= bb->x1;
    682 		rect->top -= bb->y1;
    683 		rect->right -= bb->x1;
    684 		rect->bottom -= bb->y1;
    685 		rect++;
    686 	}
    687 
    688 	return 0;
    689 }
    690 
    691 /**
    692  * vmw_sou_plane_update_surface - Update display unit for surface backed fb.
    693  * @dev_priv: Device private.
    694  * @plane: Plane state.
    695  * @old_state: Old plane state.
    696  * @vfb: Framebuffer which is blitted to display unit
    697  * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
    698  *             The returned fence pointer may be NULL in which case the device
    699  *             has already synchronized.
    700  *
    701  * Return: 0 on success or a negative error code on failure.
    702  */
    703 static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv,
    704 					struct drm_plane *plane,
    705 					struct drm_plane_state *old_state,
    706 					struct vmw_framebuffer *vfb,
    707 					struct vmw_fence_obj **out_fence)
    708 {
    709 	struct vmw_du_update_plane_surface srf_update;
    710 
    711 	memset(&srf_update, 0, sizeof(struct vmw_du_update_plane_surface));
    712 	srf_update.base.plane = plane;
    713 	srf_update.base.old_state = old_state;
    714 	srf_update.base.dev_priv = dev_priv;
    715 	srf_update.base.du = vmw_crtc_to_du(plane->state->crtc);
    716 	srf_update.base.vfb = vfb;
    717 	srf_update.base.out_fence = out_fence;
    718 	srf_update.base.mutex = &dev_priv->cmdbuf_mutex;
    719 	srf_update.base.cpu_blit = false;
    720 	srf_update.base.intr = true;
    721 
    722 	srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size;
    723 	srf_update.base.post_prepare = vmw_sou_surface_post_prepare;
    724 	srf_update.base.pre_clip = vmw_sou_surface_pre_clip;
    725 	srf_update.base.clip = vmw_sou_surface_clip_rect;
    726 	srf_update.base.post_clip = vmw_sou_surface_post_clip;
    727 
    728 	return vmw_du_helper_plane_update(&srf_update.base);
    729 }
    730 
    731 static void
    732 vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
    733 				    struct drm_plane_state *old_state)
    734 {
    735 	struct drm_crtc *crtc = plane->state->crtc;
    736 	struct drm_pending_vblank_event *event = NULL;
    737 	struct vmw_fence_obj *fence = NULL;
    738 	int ret;
    739 
    740 	/* In case of device error, maintain consistent atomic state */
    741 	if (crtc && plane->state->fb) {
    742 		struct vmw_private *dev_priv = vmw_priv(crtc->dev);
    743 		struct vmw_framebuffer *vfb =
    744 			vmw_framebuffer_to_vfb(plane->state->fb);
    745 
    746 		if (vfb->bo)
    747 			ret = vmw_sou_plane_update_bo(dev_priv, plane,
    748 						      old_state, vfb, &fence);
    749 		else
    750 			ret = vmw_sou_plane_update_surface(dev_priv, plane,
    751 							   old_state, vfb,
    752 							   &fence);
    753 		if (ret != 0)
    754 			DRM_ERROR("Failed to update screen.\n");
    755 	} else {
    756 		/* Do nothing when fb and crtc is NULL (blank crtc) */
    757 		return;
    758 	}
    759 
    760 	/* For error case vblank event is send from vmw_du_crtc_atomic_flush */
    761 	event = crtc->state->event;
    762 	if (event && fence) {
    763 		struct drm_file *file_priv = event->base.file_priv;
    764 
    765 		ret = vmw_event_fence_action_queue(file_priv,
    766 						   fence,
    767 						   &event->base,
    768 						   &event->event.vbl.tv_sec,
    769 						   &event->event.vbl.tv_usec,
    770 						   true);
    771 
    772 		if (unlikely(ret != 0))
    773 			DRM_ERROR("Failed to queue event on fence.\n");
    774 		else
    775 			crtc->state->event = NULL;
    776 	}
    777 
    778 	if (fence)
    779 		vmw_fence_obj_unreference(&fence);
    780 }
    781 
    782 
    783 static const struct drm_plane_funcs vmw_sou_plane_funcs = {
    784 	.update_plane = drm_atomic_helper_update_plane,
    785 	.disable_plane = drm_atomic_helper_disable_plane,
    786 	.destroy = vmw_du_primary_plane_destroy,
    787 	.reset = vmw_du_plane_reset,
    788 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
    789 	.atomic_destroy_state = vmw_du_plane_destroy_state,
    790 };
    791 
    792 static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
    793 	.update_plane = drm_atomic_helper_update_plane,
    794 	.disable_plane = drm_atomic_helper_disable_plane,
    795 	.destroy = vmw_du_cursor_plane_destroy,
    796 	.reset = vmw_du_plane_reset,
    797 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
    798 	.atomic_destroy_state = vmw_du_plane_destroy_state,
    799 };
    800 
    801 /*
    802  * Atomic Helpers
    803  */
    804 static const struct
    805 drm_plane_helper_funcs vmw_sou_cursor_plane_helper_funcs = {
    806 	.atomic_check = vmw_du_cursor_plane_atomic_check,
    807 	.atomic_update = vmw_du_cursor_plane_atomic_update,
    808 	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
    809 	.cleanup_fb = vmw_du_plane_cleanup_fb,
    810 };
    811 
    812 static const struct
    813 drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = {
    814 	.atomic_check = vmw_du_primary_plane_atomic_check,
    815 	.atomic_update = vmw_sou_primary_plane_atomic_update,
    816 	.prepare_fb = vmw_sou_primary_plane_prepare_fb,
    817 	.cleanup_fb = vmw_sou_primary_plane_cleanup_fb,
    818 };
    819 
    820 static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
    821 	.prepare = vmw_sou_crtc_helper_prepare,
    822 	.mode_set_nofb = vmw_sou_crtc_mode_set_nofb,
    823 	.atomic_check = vmw_du_crtc_atomic_check,
    824 	.atomic_begin = vmw_du_crtc_atomic_begin,
    825 	.atomic_flush = vmw_du_crtc_atomic_flush,
    826 	.atomic_enable = vmw_sou_crtc_atomic_enable,
    827 	.atomic_disable = vmw_sou_crtc_atomic_disable,
    828 };
    829 
    830 
    831 static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
    832 {
    833 	struct vmw_screen_object_unit *sou;
    834 	struct drm_device *dev = dev_priv->dev;
    835 	struct drm_connector *connector;
    836 	struct drm_encoder *encoder;
    837 	struct drm_plane *primary, *cursor;
    838 	struct drm_crtc *crtc;
    839 	int ret;
    840 
    841 	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
    842 	if (!sou)
    843 		return -ENOMEM;
    844 
    845 	sou->base.unit = unit;
    846 	crtc = &sou->base.crtc;
    847 	encoder = &sou->base.encoder;
    848 	connector = &sou->base.connector;
    849 	primary = &sou->base.primary;
    850 	cursor = &sou->base.cursor;
    851 
    852 	sou->base.pref_active = (unit == 0);
    853 	sou->base.pref_width = dev_priv->initial_width;
    854 	sou->base.pref_height = dev_priv->initial_height;
    855 	sou->base.pref_mode = NULL;
    856 
    857 	/*
    858 	 * Remove this after enabling atomic because property values can
    859 	 * only exist in a state object
    860 	 */
    861 	sou->base.is_implicit = false;
    862 
    863 	/* Initialize primary plane */
    864 	vmw_du_plane_reset(primary);
    865 
    866 	ret = drm_universal_plane_init(dev, &sou->base.primary,
    867 				       0, &vmw_sou_plane_funcs,
    868 				       vmw_primary_plane_formats,
    869 				       ARRAY_SIZE(vmw_primary_plane_formats),
    870 				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
    871 	if (ret) {
    872 		DRM_ERROR("Failed to initialize primary plane");
    873 		goto err_free;
    874 	}
    875 
    876 	drm_plane_helper_add(primary, &vmw_sou_primary_plane_helper_funcs);
    877 	drm_plane_enable_fb_damage_clips(primary);
    878 
    879 	/* Initialize cursor plane */
    880 	vmw_du_plane_reset(cursor);
    881 
    882 	ret = drm_universal_plane_init(dev, &sou->base.cursor,
    883 			0, &vmw_sou_cursor_funcs,
    884 			vmw_cursor_plane_formats,
    885 			ARRAY_SIZE(vmw_cursor_plane_formats),
    886 			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
    887 	if (ret) {
    888 		DRM_ERROR("Failed to initialize cursor plane");
    889 		drm_plane_cleanup(&sou->base.primary);
    890 		goto err_free;
    891 	}
    892 
    893 	drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs);
    894 
    895 	vmw_du_connector_reset(connector);
    896 	ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
    897 				 DRM_MODE_CONNECTOR_VIRTUAL);
    898 	if (ret) {
    899 		DRM_ERROR("Failed to initialize connector\n");
    900 		goto err_free;
    901 	}
    902 
    903 	drm_connector_helper_add(connector, &vmw_sou_connector_helper_funcs);
    904 	connector->status = vmw_du_connector_detect(connector, true);
    905 
    906 	ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
    907 			       DRM_MODE_ENCODER_VIRTUAL, NULL);
    908 	if (ret) {
    909 		DRM_ERROR("Failed to initialize encoder\n");
    910 		goto err_free_connector;
    911 	}
    912 
    913 	(void) drm_connector_attach_encoder(connector, encoder);
    914 	encoder->possible_crtcs = (1 << unit);
    915 	encoder->possible_clones = 0;
    916 
    917 	ret = drm_connector_register(connector);
    918 	if (ret) {
    919 		DRM_ERROR("Failed to register connector\n");
    920 		goto err_free_encoder;
    921 	}
    922 
    923 
    924 	vmw_du_crtc_reset(crtc);
    925 	ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
    926 					&sou->base.cursor,
    927 					&vmw_screen_object_crtc_funcs, NULL);
    928 	if (ret) {
    929 		DRM_ERROR("Failed to initialize CRTC\n");
    930 		goto err_free_unregister;
    931 	}
    932 
    933 	drm_crtc_helper_add(crtc, &vmw_sou_crtc_helper_funcs);
    934 
    935 	drm_mode_crtc_set_gamma_size(crtc, 256);
    936 
    937 	drm_object_attach_property(&connector->base,
    938 				   dev_priv->hotplug_mode_update_property, 1);
    939 	drm_object_attach_property(&connector->base,
    940 				   dev->mode_config.suggested_x_property, 0);
    941 	drm_object_attach_property(&connector->base,
    942 				   dev->mode_config.suggested_y_property, 0);
    943 	return 0;
    944 
    945 err_free_unregister:
    946 	drm_connector_unregister(connector);
    947 err_free_encoder:
    948 	drm_encoder_cleanup(encoder);
    949 err_free_connector:
    950 	drm_connector_cleanup(connector);
    951 err_free:
    952 	kfree(sou);
    953 	return ret;
    954 }
    955 
    956 int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
    957 {
    958 	struct drm_device *dev = dev_priv->dev;
    959 	int i, ret;
    960 
    961 	if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
    962 		DRM_INFO("Not using screen objects,"
    963 			 " missing cap SCREEN_OBJECT_2\n");
    964 		return -ENOSYS;
    965 	}
    966 
    967 	ret = -ENOMEM;
    968 
    969 	ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
    970 	if (unlikely(ret != 0))
    971 		return ret;
    972 
    973 	for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
    974 		vmw_sou_init(dev_priv, i);
    975 
    976 	dev_priv->active_display_unit = vmw_du_screen_object;
    977 
    978 	DRM_INFO("Screen Objects Display Unit initialized\n");
    979 
    980 	return 0;
    981 }
    982 
    983 static int do_bo_define_gmrfb(struct vmw_private *dev_priv,
    984 				  struct vmw_framebuffer *framebuffer)
    985 {
    986 	struct vmw_buffer_object *buf =
    987 		container_of(framebuffer, struct vmw_framebuffer_bo,
    988 			     base)->buffer;
    989 	int depth = framebuffer->base.format->depth;
    990 	struct {
    991 		uint32_t header;
    992 		SVGAFifoCmdDefineGMRFB body;
    993 	} *cmd;
    994 
    995 	/* Emulate RGBA support, contrary to svga_reg.h this is not
    996 	 * supported by hosts. This is only a problem if we are reading
    997 	 * this value later and expecting what we uploaded back.
    998 	 */
    999 	if (depth == 32)
   1000 		depth = 24;
   1001 
   1002 	cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
   1003 	if (!cmd)
   1004 		return -ENOMEM;
   1005 
   1006 	cmd->header = SVGA_CMD_DEFINE_GMRFB;
   1007 	cmd->body.format.bitsPerPixel = framebuffer->base.format->cpp[0] * 8;
   1008 	cmd->body.format.colorDepth = depth;
   1009 	cmd->body.format.reserved = 0;
   1010 	cmd->body.bytesPerLine = framebuffer->base.pitches[0];
   1011 	/* Buffer is reserved in vram or GMR */
   1012 	vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr);
   1013 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
   1014 
   1015 	return 0;
   1016 }
   1017 
   1018 /**
   1019  * vmw_sou_surface_fifo_commit - Callback to fill in and submit a
   1020  * blit surface to screen command.
   1021  *
   1022  * @dirty: The closure structure.
   1023  *
   1024  * Fills in the missing fields in the command, and translates the cliprects
   1025  * to match the destination bounding box encoded.
   1026  */
   1027 static void vmw_sou_surface_fifo_commit(struct vmw_kms_dirty *dirty)
   1028 {
   1029 	struct vmw_kms_sou_surface_dirty *sdirty =
   1030 		container_of(dirty, typeof(*sdirty), base);
   1031 	struct vmw_kms_sou_dirty_cmd *cmd = dirty->cmd;
   1032 	s32 trans_x = dirty->unit->crtc.x - sdirty->dst_x;
   1033 	s32 trans_y = dirty->unit->crtc.y - sdirty->dst_y;
   1034 	size_t region_size = dirty->num_hits * sizeof(SVGASignedRect);
   1035 	SVGASignedRect *blit = (SVGASignedRect *) &cmd[1];
   1036 	int i;
   1037 
   1038 	if (!dirty->num_hits) {
   1039 		vmw_fifo_commit(dirty->dev_priv, 0);
   1040 		return;
   1041 	}
   1042 
   1043 	cmd->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN;
   1044 	cmd->header.size = sizeof(cmd->body) + region_size;
   1045 
   1046 	/*
   1047 	 * Use the destination bounding box to specify destination - and
   1048 	 * source bounding regions.
   1049 	 */
   1050 	cmd->body.destRect.left = sdirty->left;
   1051 	cmd->body.destRect.right = sdirty->right;
   1052 	cmd->body.destRect.top = sdirty->top;
   1053 	cmd->body.destRect.bottom = sdirty->bottom;
   1054 
   1055 	cmd->body.srcRect.left = sdirty->left + trans_x;
   1056 	cmd->body.srcRect.right = sdirty->right + trans_x;
   1057 	cmd->body.srcRect.top = sdirty->top + trans_y;
   1058 	cmd->body.srcRect.bottom = sdirty->bottom + trans_y;
   1059 
   1060 	cmd->body.srcImage.sid = sdirty->sid;
   1061 	cmd->body.destScreenId = dirty->unit->unit;
   1062 
   1063 	/* Blits are relative to the destination rect. Translate. */
   1064 	for (i = 0; i < dirty->num_hits; ++i, ++blit) {
   1065 		blit->left -= sdirty->left;
   1066 		blit->right -= sdirty->left;
   1067 		blit->top -= sdirty->top;
   1068 		blit->bottom -= sdirty->top;
   1069 	}
   1070 
   1071 	vmw_fifo_commit(dirty->dev_priv, region_size + sizeof(*cmd));
   1072 
   1073 	sdirty->left = sdirty->top = S32_MAX;
   1074 	sdirty->right = sdirty->bottom = S32_MIN;
   1075 }
   1076 
   1077 /**
   1078  * vmw_sou_surface_clip - Callback to encode a blit surface to screen cliprect.
   1079  *
   1080  * @dirty: The closure structure
   1081  *
   1082  * Encodes a SVGASignedRect cliprect and updates the bounding box of the
   1083  * BLIT_SURFACE_TO_SCREEN command.
   1084  */
   1085 static void vmw_sou_surface_clip(struct vmw_kms_dirty *dirty)
   1086 {
   1087 	struct vmw_kms_sou_surface_dirty *sdirty =
   1088 		container_of(dirty, typeof(*sdirty), base);
   1089 	struct vmw_kms_sou_dirty_cmd *cmd = dirty->cmd;
   1090 	SVGASignedRect *blit = (SVGASignedRect *) &cmd[1];
   1091 
   1092 	/* Destination rect. */
   1093 	blit += dirty->num_hits;
   1094 	blit->left = dirty->unit_x1;
   1095 	blit->top = dirty->unit_y1;
   1096 	blit->right = dirty->unit_x2;
   1097 	blit->bottom = dirty->unit_y2;
   1098 
   1099 	/* Destination bounding box */
   1100 	sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1);
   1101 	sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1);
   1102 	sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2);
   1103 	sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2);
   1104 
   1105 	dirty->num_hits++;
   1106 }
   1107 
   1108 /**
   1109  * vmw_kms_sou_do_surface_dirty - Dirty part of a surface backed framebuffer
   1110  *
   1111  * @dev_priv: Pointer to the device private structure.
   1112  * @framebuffer: Pointer to the surface-buffer backed framebuffer.
   1113  * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
   1114  * @vclips: Alternate array of clip rects. Either @clips or @vclips must
   1115  * be NULL.
   1116  * @srf: Pointer to surface to blit from. If NULL, the surface attached
   1117  * to @framebuffer will be used.
   1118  * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
   1119  * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
   1120  * @num_clips: Number of clip rects in @clips.
   1121  * @inc: Increment to use when looping over @clips.
   1122  * @out_fence: If non-NULL, will return a ref-counted pointer to a
   1123  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
   1124  * case the device has already synchronized.
   1125  * @crtc: If crtc is passed, perform surface dirty on that crtc only.
   1126  *
   1127  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
   1128  * interrupted.
   1129  */
   1130 int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
   1131 				 struct vmw_framebuffer *framebuffer,
   1132 				 struct drm_clip_rect *clips,
   1133 				 struct drm_vmw_rect *vclips,
   1134 				 struct vmw_resource *srf,
   1135 				 s32 dest_x,
   1136 				 s32 dest_y,
   1137 				 unsigned num_clips, int inc,
   1138 				 struct vmw_fence_obj **out_fence,
   1139 				 struct drm_crtc *crtc)
   1140 {
   1141 	struct vmw_framebuffer_surface *vfbs =
   1142 		container_of(framebuffer, typeof(*vfbs), base);
   1143 	struct vmw_kms_sou_surface_dirty sdirty;
   1144 	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
   1145 	int ret;
   1146 
   1147 	if (!srf)
   1148 		srf = &vfbs->surface->res;
   1149 
   1150 	ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE,
   1151 					  NULL, NULL);
   1152 	if (ret)
   1153 		return ret;
   1154 
   1155 	ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true);
   1156 	if (ret)
   1157 		goto out_unref;
   1158 
   1159 	sdirty.base.fifo_commit = vmw_sou_surface_fifo_commit;
   1160 	sdirty.base.clip = vmw_sou_surface_clip;
   1161 	sdirty.base.dev_priv = dev_priv;
   1162 	sdirty.base.fifo_reserve_size = sizeof(struct vmw_kms_sou_dirty_cmd) +
   1163 	  sizeof(SVGASignedRect) * num_clips;
   1164 	sdirty.base.crtc = crtc;
   1165 
   1166 	sdirty.sid = srf->id;
   1167 	sdirty.left = sdirty.top = S32_MAX;
   1168 	sdirty.right = sdirty.bottom = S32_MIN;
   1169 	sdirty.dst_x = dest_x;
   1170 	sdirty.dst_y = dest_y;
   1171 
   1172 	ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
   1173 				   dest_x, dest_y, num_clips, inc,
   1174 				   &sdirty.base);
   1175 	vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
   1176 					 NULL);
   1177 
   1178 	return ret;
   1179 
   1180 out_unref:
   1181 	vmw_validation_unref_lists(&val_ctx);
   1182 	return ret;
   1183 }
   1184 
   1185 /**
   1186  * vmw_sou_bo_fifo_commit - Callback to submit a set of readback clips.
   1187  *
   1188  * @dirty: The closure structure.
   1189  *
   1190  * Commits a previously built command buffer of readback clips.
   1191  */
   1192 static void vmw_sou_bo_fifo_commit(struct vmw_kms_dirty *dirty)
   1193 {
   1194 	if (!dirty->num_hits) {
   1195 		vmw_fifo_commit(dirty->dev_priv, 0);
   1196 		return;
   1197 	}
   1198 
   1199 	vmw_fifo_commit(dirty->dev_priv,
   1200 			sizeof(struct vmw_kms_sou_bo_blit) *
   1201 			dirty->num_hits);
   1202 }
   1203 
   1204 /**
   1205  * vmw_sou_bo_clip - Callback to encode a readback cliprect.
   1206  *
   1207  * @dirty: The closure structure
   1208  *
   1209  * Encodes a BLIT_GMRFB_TO_SCREEN cliprect.
   1210  */
   1211 static void vmw_sou_bo_clip(struct vmw_kms_dirty *dirty)
   1212 {
   1213 	struct vmw_kms_sou_bo_blit *blit = dirty->cmd;
   1214 
   1215 	blit += dirty->num_hits;
   1216 	blit->header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
   1217 	blit->body.destScreenId = dirty->unit->unit;
   1218 	blit->body.srcOrigin.x = dirty->fb_x;
   1219 	blit->body.srcOrigin.y = dirty->fb_y;
   1220 	blit->body.destRect.left = dirty->unit_x1;
   1221 	blit->body.destRect.top = dirty->unit_y1;
   1222 	blit->body.destRect.right = dirty->unit_x2;
   1223 	blit->body.destRect.bottom = dirty->unit_y2;
   1224 	dirty->num_hits++;
   1225 }
   1226 
   1227 /**
   1228  * vmw_kms_do_bo_dirty - Dirty part of a buffer-object backed framebuffer
   1229  *
   1230  * @dev_priv: Pointer to the device private structure.
   1231  * @framebuffer: Pointer to the buffer-object backed framebuffer.
   1232  * @clips: Array of clip rects.
   1233  * @vclips: Alternate array of clip rects. Either @clips or @vclips must
   1234  * be NULL.
   1235  * @num_clips: Number of clip rects in @clips.
   1236  * @increment: Increment to use when looping over @clips.
   1237  * @interruptible: Whether to perform waits interruptible if possible.
   1238  * @out_fence: If non-NULL, will return a ref-counted pointer to a
   1239  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
   1240  * case the device has already synchronized.
   1241  * @crtc: If crtc is passed, perform bo dirty on that crtc only.
   1242  *
   1243  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
   1244  * interrupted.
   1245  */
   1246 int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv,
   1247 				struct vmw_framebuffer *framebuffer,
   1248 				struct drm_clip_rect *clips,
   1249 				struct drm_vmw_rect *vclips,
   1250 				unsigned num_clips, int increment,
   1251 				bool interruptible,
   1252 				struct vmw_fence_obj **out_fence,
   1253 				struct drm_crtc *crtc)
   1254 {
   1255 	struct vmw_buffer_object *buf =
   1256 		container_of(framebuffer, struct vmw_framebuffer_bo,
   1257 			     base)->buffer;
   1258 	struct vmw_kms_dirty dirty;
   1259 	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
   1260 	int ret;
   1261 
   1262 	ret = vmw_validation_add_bo(&val_ctx, buf, false, false);
   1263 	if (ret)
   1264 		return ret;
   1265 
   1266 	ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);
   1267 	if (ret)
   1268 		goto out_unref;
   1269 
   1270 	ret = do_bo_define_gmrfb(dev_priv, framebuffer);
   1271 	if (unlikely(ret != 0))
   1272 		goto out_revert;
   1273 
   1274 	dirty.crtc = crtc;
   1275 	dirty.fifo_commit = vmw_sou_bo_fifo_commit;
   1276 	dirty.clip = vmw_sou_bo_clip;
   1277 	dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_bo_blit) *
   1278 		num_clips;
   1279 	ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
   1280 				   0, 0, num_clips, increment, &dirty);
   1281 	vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
   1282 					 NULL);
   1283 
   1284 	return ret;
   1285 
   1286 out_revert:
   1287 	vmw_validation_revert(&val_ctx);
   1288 out_unref:
   1289 	vmw_validation_unref_lists(&val_ctx);
   1290 
   1291 	return ret;
   1292 }
   1293 
   1294 
   1295 /**
   1296  * vmw_sou_readback_fifo_commit - Callback to submit a set of readback clips.
   1297  *
   1298  * @dirty: The closure structure.
   1299  *
   1300  * Commits a previously built command buffer of readback clips.
   1301  */
   1302 static void vmw_sou_readback_fifo_commit(struct vmw_kms_dirty *dirty)
   1303 {
   1304 	if (!dirty->num_hits) {
   1305 		vmw_fifo_commit(dirty->dev_priv, 0);
   1306 		return;
   1307 	}
   1308 
   1309 	vmw_fifo_commit(dirty->dev_priv,
   1310 			sizeof(struct vmw_kms_sou_readback_blit) *
   1311 			dirty->num_hits);
   1312 }
   1313 
   1314 /**
   1315  * vmw_sou_readback_clip - Callback to encode a readback cliprect.
   1316  *
   1317  * @dirty: The closure structure
   1318  *
   1319  * Encodes a BLIT_SCREEN_TO_GMRFB cliprect.
   1320  */
   1321 static void vmw_sou_readback_clip(struct vmw_kms_dirty *dirty)
   1322 {
   1323 	struct vmw_kms_sou_readback_blit *blit = dirty->cmd;
   1324 
   1325 	blit += dirty->num_hits;
   1326 	blit->header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB;
   1327 	blit->body.srcScreenId = dirty->unit->unit;
   1328 	blit->body.destOrigin.x = dirty->fb_x;
   1329 	blit->body.destOrigin.y = dirty->fb_y;
   1330 	blit->body.srcRect.left = dirty->unit_x1;
   1331 	blit->body.srcRect.top = dirty->unit_y1;
   1332 	blit->body.srcRect.right = dirty->unit_x2;
   1333 	blit->body.srcRect.bottom = dirty->unit_y2;
   1334 	dirty->num_hits++;
   1335 }
   1336 
   1337 /**
   1338  * vmw_kms_sou_readback - Perform a readback from the screen object system to
   1339  * a buffer-object backed framebuffer.
   1340  *
   1341  * @dev_priv: Pointer to the device private structure.
   1342  * @file_priv: Pointer to a struct drm_file identifying the caller.
   1343  * Must be set to NULL if @user_fence_rep is NULL.
   1344  * @vfb: Pointer to the buffer-object backed framebuffer.
   1345  * @user_fence_rep: User-space provided structure for fence information.
   1346  * Must be set to non-NULL if @file_priv is non-NULL.
   1347  * @vclips: Array of clip rects.
   1348  * @num_clips: Number of clip rects in @vclips.
   1349  * @crtc: If crtc is passed, readback on that crtc only.
   1350  *
   1351  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
   1352  * interrupted.
   1353  */
   1354 int vmw_kms_sou_readback(struct vmw_private *dev_priv,
   1355 			 struct drm_file *file_priv,
   1356 			 struct vmw_framebuffer *vfb,
   1357 			 struct drm_vmw_fence_rep __user *user_fence_rep,
   1358 			 struct drm_vmw_rect *vclips,
   1359 			 uint32_t num_clips,
   1360 			 struct drm_crtc *crtc)
   1361 {
   1362 	struct vmw_buffer_object *buf =
   1363 		container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;
   1364 	struct vmw_kms_dirty dirty;
   1365 	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
   1366 	int ret;
   1367 
   1368 	ret = vmw_validation_add_bo(&val_ctx, buf, false, false);
   1369 	if (ret)
   1370 		return ret;
   1371 
   1372 	ret = vmw_validation_prepare(&val_ctx, NULL, true);
   1373 	if (ret)
   1374 		goto out_unref;
   1375 
   1376 	ret = do_bo_define_gmrfb(dev_priv, vfb);
   1377 	if (unlikely(ret != 0))
   1378 		goto out_revert;
   1379 
   1380 	dirty.crtc = crtc;
   1381 	dirty.fifo_commit = vmw_sou_readback_fifo_commit;
   1382 	dirty.clip = vmw_sou_readback_clip;
   1383 	dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_readback_blit) *
   1384 		num_clips;
   1385 	ret = vmw_kms_helper_dirty(dev_priv, vfb, NULL, vclips,
   1386 				   0, 0, num_clips, 1, &dirty);
   1387 	vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL,
   1388 					 user_fence_rep);
   1389 
   1390 	return ret;
   1391 
   1392 out_revert:
   1393 	vmw_validation_revert(&val_ctx);
   1394 out_unref:
   1395 	vmw_validation_unref_lists(&val_ctx);
   1396 
   1397 	return ret;
   1398 }
   1399