linux/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
/**
 * vmw_kms_helper_dirty - Helper to build commands and perform actions based
 * on a set of cliprects and a set of display units.
 *
 * @dev_priv: Pointer to a device private structure.
 * @framebuffer: Pointer to the framebuffer on which to perform the actions.
 * @clips: A set of struct drm_clip_rect. Either this os @vclips must be NULL.
 * Cliprects are given in framebuffer coordinates.
 * @vclips: A set of struct drm_vmw_rect cliprects. Either this or @clips must
 * be NULL. Cliprects are given in source coordinates.
 * @dest_x: X coordinate offset for the crtc / destination clip rects.
 * @dest_y: Y coordinate offset for the crtc / destination clip rects.
 * @num_clips: Number of cliprects in the @clips or @vclips array.
 * @increment: Integer with which to increment the clip counter when looping.
 * Used to skip a predetermined number of clip rects.
 * @dirty: Closure structure. See the description of struct vmw_kms_dirty.
 */
Helper to build commands and perform actions based
on a set of cliprects and a set of display units.

@dev_priv: Pointer to a device private structure.
@framebuffer: Pointer to the framebuffer on which to perform the actions.
@clips: A set of struct drm_clip_rect. Either this os @vclips must be NULL.
Cliprects are given in framebuffer coordinates.
@vclips: A set of struct drm_vmw_rect cliprects. Either this or @clips must
be NULL. Cliprects are given in source coordinates.
@dest_x: X coordinate offset for the crtc / destination clip rects.
@dest_y: Y coordinate offset for the crtc / destination clip rects.
@num_clips: Number of cliprects in the @clips or @vclips array.
@increment: Integer with which to increment the clip counter when looping.
Used to skip a predetermined number of clip rects.
@dirty: Closure structure. See the description of struct vmw_kms_dirty.
Helper to build commands and perform actions based on a set of cliprects and a set of display units . @dev_priv : Pointer to a device private structure . @framebuffer : Pointer to the framebuffer on which to perform the actions . @clips : A set of struct drm_clip_rect . Either this os @vclips must be NULL . Cliprects are given in framebuffer coordinates . @vclips : A set of struct drm_vmw_rect cliprects . Either this or @clips must be NULL . Cliprects are given in source coordinates . @dest_x : X coordinate offset for the crtc / destination clip rects . @dest_y : Y coordinate offset for the crtc / destination clip rects . @num_clips : Number of cliprects in the @clips or @vclips array . @increment : Integer with which to increment the clip counter when looping . Used to skip a predetermined number of clip rects . @dirty : Closure structure . See the description of struct vmw_kms_dirty .
int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
			 struct vmw_framebuffer *framebuffer,
			 const struct drm_clip_rect *clips,
			 const struct drm_vmw_rect *vclips,
			 s32 dest_x, s32 dest_y,
			 int num_clips,
			 int increment,
			 struct vmw_kms_dirty *dirty)
{
	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
	struct drm_crtc *crtc;
	u32 num_units = 0;
	u32 i, k;
	dirty->dev_priv = dev_priv;
	if (dirty->crtc) {
		units[num_units++] = vmw_crtc_to_du(dirty->crtc);
	} else {
		list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
				    head) {
			struct drm_plane *plane = crtc->primary;
			if (plane->state->fb == &framebuffer->base)
				units[num_units++] = vmw_crtc_to_du(crtc);
		}
	}
	for (k = 0; k < num_units; k++) {
		struct vmw_display_unit *unit = units[k];
		s32 crtc_x = unit->crtc.x;
		s32 crtc_y = unit->crtc.y;
		s32 crtc_width = unit->crtc.mode.hdisplay;
		s32 crtc_height = unit->crtc.mode.vdisplay;
		const struct drm_clip_rect *clips_ptr = clips;
		const struct drm_vmw_rect *vclips_ptr = vclips;
		dirty->unit = unit;
		if (dirty->fifo_reserve_size > 0) {
			dirty->cmd = vmw_fifo_reserve(dev_priv,
						      dirty->fifo_reserve_size);
			if (!dirty->cmd) {
				DRM_ERROR("Couldn't reserve fifo space "
					  "for dirty blits.\n");
				return -ENOMEM;
			}
			memset(dirty->cmd, 0, dirty->fifo_reserve_size);
		}
		dirty->num_hits = 0;
		for (i = 0; i < num_clips; i++, clips_ptr += increment,
		       vclips_ptr += increment) {
			s32 clip_left;
			s32 clip_top;
			if (clips) {
				dirty->fb_x = (s32) clips_ptr->x1;
				dirty->fb_y = (s32) clips_ptr->y1;
				dirty->unit_x2 = (s32) clips_ptr->x2 + dest_x -
					crtc_x;
				dirty->unit_y2 = (s32) clips_ptr->y2 + dest_y -
					crtc_y;
			} else {
				dirty->fb_x = vclips_ptr->x;
				dirty->fb_y = vclips_ptr->y;
				dirty->unit_x2 = dirty->fb_x + vclips_ptr->w +
					dest_x - crtc_x;
				dirty->unit_y2 = dirty->fb_y + vclips_ptr->h +
					dest_y - crtc_y;
			}
			dirty->unit_x1 = dirty->fb_x + dest_x - crtc_x;
			dirty->unit_y1 = dirty->fb_y + dest_y - crtc_y;
			if (dirty->unit_x1 >= crtc_width ||
			    dirty->unit_y1 >= crtc_height ||
			    dirty->unit_x2 <= 0 || dirty->unit_y2 <= 0)
				continue;
			dirty->unit_x2 = min_t(s32, dirty->unit_x2,
					       crtc_width);
			dirty->unit_y2 = min_t(s32, dirty->unit_y2,
					       crtc_height);
			clip_left = min_t(s32, dirty->unit_x1, 0);
			clip_top = min_t(s32, dirty->unit_y1, 0);
			dirty->unit_x1 -= clip_left;
			dirty->unit_y1 -= clip_top;
			dirty->fb_x -= clip_left;
			dirty->fb_y -= clip_top;
			dirty->clip(dirty);
		}
		dirty->fifo_commit(dirty);
	}
	return 0;
}
int vmw_kms_helper_dirty ( struct vmw_private * dev_priv , struct vmw_framebuffer * framebuffer , const struct drm_clip_rect * clips , const struct drm_vmw_rect * vclips , s32 dest_x , s32 dest_y , int num_clips , int increment , struct vmw_kms_dirty * dirty ) { struct vmw_display_unit * units [ VMWGFX_NUM_DISPLAY_UNITS ] ; struct drm_crtc * crtc ; u32 num_units = 0 ; u32 i , k ; dirty -> dev_priv = dev_priv ; if ( dirty -> crtc ) { units [ num_units ++ ] = vmw_crtc_to_du ( dirty -> crtc ) ; } else { list_for_each_entry ( crtc , & dev_priv -> dev -> mode_config . crtc_list , head ) { struct drm_plane * plane = crtc -> primary ; if ( plane -> state -> fb == & framebuffer -> base ) units [ num_units ++ ] = vmw_crtc_to_du ( crtc ) ; } } for ( k = 0 ; k < num_units ; k ++ ) { struct vmw_display_unit * unit = units [ k ] ; s32 crtc_x = unit -> crtc . x ; s32 crtc_y = unit -> crtc . y ; s32 crtc_width = unit -> crtc . mode . hdisplay ; s32 crtc_height = unit -> crtc . mode . vdisplay ; const struct drm_clip_rect * clips_ptr = clips ; const struct drm_vmw_rect * vclips_ptr = vclips ; dirty -> unit = unit ; if ( dirty -> fifo_reserve_size > 0 ) { dirty -> cmd = vmw_fifo_reserve ( dev_priv , dirty -> fifo_reserve_size ) ; if ( ! dirty -> cmd ) { DRM_ERROR ( " " " \n " ) ; return - ENOMEM ; } memset ( dirty -> cmd , 0 , dirty -> fifo_reserve_size ) ; } dirty -> num_hits = 0 ; for ( i = 0 ; i < num_clips ; i ++ , clips_ptr += increment , vclips_ptr += increment ) { s32 clip_left ; s32 clip_top ; if ( clips ) { dirty -> fb_x = ( s32 ) clips_ptr -> x1 ; dirty -> fb_y = ( s32 ) clips_ptr -> y1 ; dirty -> unit_x2 = ( s32 ) clips_ptr -> x2 + dest_x - crtc_x ; dirty -> unit_y2 = ( s32 ) clips_ptr -> y2 + dest_y - crtc_y ; } else { dirty -> fb_x = vclips_ptr -> x ; dirty -> fb_y = vclips_ptr -> y ; dirty -> unit_x2 = dirty -> fb_x + vclips_ptr -> w + dest_x - crtc_x ; dirty -> unit_y2 = dirty -> fb_y + vclips_ptr -> h + dest_y - crtc_y ; } dirty -> unit_x1 = dirty -> fb_x + dest_x - crtc_x ; dirty -> unit_y1 = dirty -> fb_y + dest_y - crtc_y ; if ( dirty -> unit_x1 >= crtc_width || dirty -> unit_y1 >= crtc_height || dirty -> unit_x2 <= 0 || dirty -> unit_y2 <= 0 ) continue ; dirty -> unit_x2 = min_t ( s32 , dirty -> unit_x2 , crtc_width ) ; dirty -> unit_y2 = min_t ( s32 , dirty -> unit_y2 , crtc_height ) ; clip_left = min_t ( s32 , dirty -> unit_x1 , 0 ) ; clip_top = min_t ( s32 , dirty -> unit_y1 , 0 ) ; dirty -> unit_x1 -= clip_left ; dirty -> unit_y1 -= clip_top ; dirty -> fb_x -= clip_left ; dirty -> fb_y -= clip_top ; dirty -> clip ( dirty ) ; } dirty -> fifo_commit ( dirty ) ; } return 0 ; }
vmw_kms_helper_dirty - Helper to build commands and perform actions based
 on a set of cliprects and a set of display units.
vmw_kms_helper_dirty - Helper to build commands and perform actions based on a set of cliprects and a set of display units .
/* If crtc is passed, no need to iterate over other display units */ /*
			 * Select clip array type. Note that integer type
			 * in @clips is unsigned short, whereas in @vclips
			 * it's 32-bit.
			 */ /* Skip this clip if it's outside the crtc region */ /* Clip right and bottom to crtc limits */ /* Clip left and top to crtc limits */