1 /******************************************************************************
3 * COPYRIGHT © 2014-2015 VMware, Inc., Palo Alto, CA., USA
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 ******************************************************************************/
28 #include "vmwgfx_kms.h"
29 #include "device_include/svga3d_surfacedefs.h"
30 #include <drm/drm_plane_helper.h>
32 #define vmw_crtc_to_stdu(x) \
33 container_of(x, struct vmw_screen_target_display_unit, base.crtc)
34 #define vmw_encoder_to_stdu(x) \
35 container_of(x, struct vmw_screen_target_display_unit, base.encoder)
36 #define vmw_connector_to_stdu(x) \
37 container_of(x, struct vmw_screen_target_display_unit, base.connector)
41 enum stdu_content_type
{
48 * struct vmw_stdu_dirty - closure structure for the update functions
50 * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
51 * @transfer: Transfer direction for DMA command.
52 * @left: Left side of bounding box.
53 * @right: Right side of bounding box.
54 * @top: Top side of bounding box.
55 * @bottom: Bottom side of bounding box.
56 * @buf: DMA buffer when DMA-ing between buffer and screen targets.
57 * @sid: Surface ID when copying between surface and screen targets.
59 struct vmw_stdu_dirty
{
60 struct vmw_kms_dirty base
;
61 SVGA3dTransferType transfer
;
62 s32 left
, right
, top
, bottom
;
65 struct vmw_dma_buffer
*buf
;
71 * SVGA commands that are used by this code. Please see the device headers
74 struct vmw_stdu_update
{
75 SVGA3dCmdHeader header
;
76 SVGA3dCmdUpdateGBScreenTarget body
;
80 SVGA3dCmdHeader header
;
81 SVGA3dCmdSurfaceDMA body
;
84 struct vmw_stdu_surface_copy
{
85 SVGA3dCmdHeader header
;
86 SVGA3dCmdSurfaceCopy body
;
91 * struct vmw_screen_target_display_unit
93 * @base: VMW specific DU structure
94 * @display_srf: surface to be displayed. The dimension of this will always
95 * match the display mode. If the display mode matches
96 * content_vfbs dimensions, then this is a pointer into the
97 * corresponding field in content_vfbs. If not, then this
98 * is a separate buffer to which content_vfbs will blit to.
99 * @content_fb: holds the rendered content, can be a surface or DMA buffer
100 * @content_type: content_fb type
101 * @defined: true if the current display unit has been initialized
103 struct vmw_screen_target_display_unit
{
104 struct vmw_display_unit base
;
106 struct vmw_surface
*display_srf
;
107 struct drm_framebuffer
*content_fb
;
109 enum stdu_content_type content_fb_type
;
116 static void vmw_stdu_destroy(struct vmw_screen_target_display_unit
*stdu
);
120 /******************************************************************************
121 * Screen Target Display Unit helper Functions
122 *****************************************************************************/
125 * vmw_stdu_pin_display - pins the resource associated with the display surface
127 * @stdu: contains the display surface
129 * Since the display surface can either be a private surface allocated by us,
130 * or it can point to the content surface, we use this function to not pin the
131 * same resource twice.
133 static int vmw_stdu_pin_display(struct vmw_screen_target_display_unit
*stdu
)
135 return vmw_resource_pin(&stdu
->display_srf
->res
, false);
141 * vmw_stdu_unpin_display - unpins the resource associated with display surface
143 * @stdu: contains the display surface
145 * If the display surface was privatedly allocated by
146 * vmw_surface_gb_priv_define() and not registered as a framebuffer, then it
147 * won't be automatically cleaned up when all the framebuffers are freed. As
148 * such, we have to explicitly call vmw_resource_unreference() to get it freed.
150 static void vmw_stdu_unpin_display(struct vmw_screen_target_display_unit
*stdu
)
152 if (stdu
->display_srf
) {
153 struct vmw_resource
*res
= &stdu
->display_srf
->res
;
155 vmw_resource_unpin(res
);
157 if (stdu
->content_fb_type
!= SAME_AS_DISPLAY
) {
158 vmw_resource_unreference(&res
);
159 stdu
->content_fb_type
= SAME_AS_DISPLAY
;
162 stdu
->display_srf
= NULL
;
168 /******************************************************************************
169 * Screen Target Display Unit CRTC Functions
170 *****************************************************************************/
174 * vmw_stdu_crtc_destroy - cleans up the STDU
176 * @crtc: used to get a reference to the containing STDU
178 static void vmw_stdu_crtc_destroy(struct drm_crtc
*crtc
)
180 vmw_stdu_destroy(vmw_crtc_to_stdu(crtc
));
184 * vmw_stdu_define_st - Defines a Screen Target
186 * @dev_priv: VMW DRM device
187 * @stdu: display unit to create a Screen Target for
189 * Creates a STDU that we can used later. This function is called whenever the
190 * framebuffer size changes.
193 * 0 on success, error code on failure
195 static int vmw_stdu_define_st(struct vmw_private
*dev_priv
,
196 struct vmw_screen_target_display_unit
*stdu
)
199 SVGA3dCmdHeader header
;
200 SVGA3dCmdDefineGBScreenTarget body
;
203 cmd
= vmw_fifo_reserve(dev_priv
, sizeof(*cmd
));
205 if (unlikely(cmd
== NULL
)) {
206 DRM_ERROR("Out of FIFO space defining Screen Target\n");
210 cmd
->header
.id
= SVGA_3D_CMD_DEFINE_GB_SCREENTARGET
;
211 cmd
->header
.size
= sizeof(cmd
->body
);
213 cmd
->body
.stid
= stdu
->base
.unit
;
214 cmd
->body
.width
= stdu
->display_srf
->base_size
.width
;
215 cmd
->body
.height
= stdu
->display_srf
->base_size
.height
;
216 cmd
->body
.flags
= (0 == cmd
->body
.stid
) ? SVGA_STFLAG_PRIMARY
: 0;
218 cmd
->body
.xRoot
= stdu
->base
.crtc
.x
;
219 cmd
->body
.yRoot
= stdu
->base
.crtc
.y
;
221 if (!stdu
->base
.is_implicit
) {
222 cmd
->body
.xRoot
= stdu
->base
.gui_x
;
223 cmd
->body
.yRoot
= stdu
->base
.gui_y
;
226 vmw_fifo_commit(dev_priv
, sizeof(*cmd
));
228 stdu
->defined
= true;
236 * vmw_stdu_bind_st - Binds a surface to a Screen Target
238 * @dev_priv: VMW DRM device
239 * @stdu: display unit affected
240 * @res: Buffer to bind to the screen target. Set to NULL to blank screen.
242 * Binding a surface to a Screen Target the same as flipping
244 static int vmw_stdu_bind_st(struct vmw_private
*dev_priv
,
245 struct vmw_screen_target_display_unit
*stdu
,
246 struct vmw_resource
*res
)
248 SVGA3dSurfaceImageId image
;
251 SVGA3dCmdHeader header
;
252 SVGA3dCmdBindGBScreenTarget body
;
256 if (!stdu
->defined
) {
257 DRM_ERROR("No screen target defined\n");
261 /* Set up image using information in vfb */
262 memset(&image
, 0, sizeof(image
));
263 image
.sid
= res
? res
->id
: SVGA3D_INVALID_ID
;
265 cmd
= vmw_fifo_reserve(dev_priv
, sizeof(*cmd
));
267 if (unlikely(cmd
== NULL
)) {
268 DRM_ERROR("Out of FIFO space binding a screen target\n");
272 cmd
->header
.id
= SVGA_3D_CMD_BIND_GB_SCREENTARGET
;
273 cmd
->header
.size
= sizeof(cmd
->body
);
275 cmd
->body
.stid
= stdu
->base
.unit
;
276 cmd
->body
.image
= image
;
278 vmw_fifo_commit(dev_priv
, sizeof(*cmd
));
284 * vmw_stdu_populate_update - populate an UPDATE_GB_SCREENTARGET command with a
287 * @cmd: Pointer to command stream.
288 * @unit: Screen target unit.
289 * @left: Left side of bounding box.
290 * @right: Right side of bounding box.
291 * @top: Top side of bounding box.
292 * @bottom: Bottom side of bounding box.
294 static void vmw_stdu_populate_update(void *cmd
, int unit
,
295 s32 left
, s32 right
, s32 top
, s32 bottom
)
297 struct vmw_stdu_update
*update
= cmd
;
299 update
->header
.id
= SVGA_3D_CMD_UPDATE_GB_SCREENTARGET
;
300 update
->header
.size
= sizeof(update
->body
);
302 update
->body
.stid
= unit
;
303 update
->body
.rect
.x
= left
;
304 update
->body
.rect
.y
= top
;
305 update
->body
.rect
.w
= right
- left
;
306 update
->body
.rect
.h
= bottom
- top
;
310 * vmw_stdu_update_st - Full update of a Screen Target
312 * @dev_priv: VMW DRM device
313 * @stdu: display unit affected
315 * This function needs to be called whenever the content of a screen
316 * target has changed completely. Typically as a result of a backing
320 * 0 on success, error code on failure
322 static int vmw_stdu_update_st(struct vmw_private
*dev_priv
,
323 struct vmw_screen_target_display_unit
*stdu
)
325 struct vmw_stdu_update
*cmd
;
326 struct drm_crtc
*crtc
= &stdu
->base
.crtc
;
328 if (!stdu
->defined
) {
329 DRM_ERROR("No screen target defined");
333 cmd
= vmw_fifo_reserve(dev_priv
, sizeof(*cmd
));
335 if (unlikely(cmd
== NULL
)) {
336 DRM_ERROR("Out of FIFO space updating a Screen Target\n");
340 vmw_stdu_populate_update(cmd
, stdu
->base
.unit
, 0, crtc
->mode
.hdisplay
,
341 0, crtc
->mode
.vdisplay
);
343 vmw_fifo_commit(dev_priv
, sizeof(*cmd
));
351 * vmw_stdu_destroy_st - Destroy a Screen Target
353 * @dev_priv: VMW DRM device
354 * @stdu: display unit to destroy
356 static int vmw_stdu_destroy_st(struct vmw_private
*dev_priv
,
357 struct vmw_screen_target_display_unit
*stdu
)
362 SVGA3dCmdHeader header
;
363 SVGA3dCmdDestroyGBScreenTarget body
;
367 /* Nothing to do if not successfully defined */
368 if (unlikely(!stdu
->defined
))
371 cmd
= vmw_fifo_reserve(dev_priv
, sizeof(*cmd
));
373 if (unlikely(cmd
== NULL
)) {
374 DRM_ERROR("Out of FIFO space, screen target not destroyed\n");
378 cmd
->header
.id
= SVGA_3D_CMD_DESTROY_GB_SCREENTARGET
;
379 cmd
->header
.size
= sizeof(cmd
->body
);
381 cmd
->body
.stid
= stdu
->base
.unit
;
383 vmw_fifo_commit(dev_priv
, sizeof(*cmd
));
386 ret
= vmw_fallback_wait(dev_priv
, false, true, 0, false, 3*HZ
);
387 if (unlikely(ret
!= 0))
388 DRM_ERROR("Failed to sync with HW");
390 stdu
->defined
= false;
398 * vmw_stdu_crtc_set_config - Sets a mode
400 * @set: mode parameters
402 * This function is the device-specific portion of the DRM CRTC mode set.
403 * For the SVGA device, we do this by defining a Screen Target, binding a
404 * GB Surface to that target, and finally update the screen target.
407 * 0 on success, error code otherwise
409 static int vmw_stdu_crtc_set_config(struct drm_mode_set
*set
)
411 struct vmw_private
*dev_priv
;
412 struct vmw_screen_target_display_unit
*stdu
;
413 struct vmw_framebuffer
*vfb
;
414 struct vmw_framebuffer_surface
*new_vfbs
;
415 struct drm_display_mode
*mode
;
416 struct drm_framebuffer
*new_fb
;
417 struct drm_crtc
*crtc
;
418 struct drm_encoder
*encoder
;
419 struct drm_connector
*connector
;
423 if (!set
|| !set
->crtc
)
429 stdu
= vmw_crtc_to_stdu(crtc
);
432 dev_priv
= vmw_priv(crtc
->dev
);
435 if (set
->num_connectors
> 1) {
436 DRM_ERROR("Too many connectors\n");
440 if (set
->num_connectors
== 1 &&
441 set
->connectors
[0] != &stdu
->base
.connector
) {
442 DRM_ERROR("Connectors don't match %p %p\n",
443 set
->connectors
[0], &stdu
->base
.connector
);
448 /* Since they always map one to one these are safe */
449 connector
= &stdu
->base
.connector
;
450 encoder
= &stdu
->base
.encoder
;
454 * After this point the CRTC will be considered off unless a new fb
458 /* Unbind current surface by binding an invalid one */
459 ret
= vmw_stdu_bind_st(dev_priv
, stdu
, NULL
);
460 if (unlikely(ret
!= 0))
463 /* Update Screen Target, display will now be blank */
464 if (crtc
->primary
->fb
) {
465 vmw_stdu_update_st(dev_priv
, stdu
);
466 if (unlikely(ret
!= 0))
470 crtc
->primary
->fb
= NULL
;
471 crtc
->enabled
= false;
472 encoder
->crtc
= NULL
;
473 connector
->encoder
= NULL
;
475 vmw_stdu_unpin_display(stdu
);
476 stdu
->content_fb
= NULL
;
477 stdu
->content_fb_type
= SAME_AS_DISPLAY
;
479 ret
= vmw_stdu_destroy_st(dev_priv
, stdu
);
480 /* The hardware is hung, give up */
481 if (unlikely(ret
!= 0))
486 /* Any of these conditions means the caller wants CRTC off */
487 if (set
->num_connectors
== 0 || !mode
|| !new_fb
)
491 if (set
->x
+ mode
->hdisplay
> new_fb
->width
||
492 set
->y
+ mode
->vdisplay
> new_fb
->height
) {
493 DRM_ERROR("Set outside of framebuffer\n");
497 stdu
->content_fb
= new_fb
;
498 vfb
= vmw_framebuffer_to_vfb(stdu
->content_fb
);
501 stdu
->content_fb_type
= SEPARATE_DMA
;
504 * If the requested mode is different than the width and height
505 * of the FB or if the content buffer is a DMA buf, then allocate
506 * a display FB that matches the dimension of the mode
508 if (mode
->hdisplay
!= new_fb
->width
||
509 mode
->vdisplay
!= new_fb
->height
||
510 stdu
->content_fb_type
!= SAME_AS_DISPLAY
) {
511 struct vmw_surface content_srf
;
512 struct drm_vmw_size display_base_size
= {0};
513 struct vmw_surface
*display_srf
;
516 display_base_size
.width
= mode
->hdisplay
;
517 display_base_size
.height
= mode
->vdisplay
;
518 display_base_size
.depth
= 1;
521 * If content buffer is a DMA buf, then we have to construct
524 if (stdu
->content_fb_type
== SEPARATE_DMA
) {
526 switch (new_fb
->bits_per_pixel
) {
528 content_srf
.format
= SVGA3D_X8R8G8B8
;
532 content_srf
.format
= SVGA3D_R5G6B5
;
536 content_srf
.format
= SVGA3D_P8
;
540 DRM_ERROR("Invalid format\n");
542 goto err_unref_content
;
545 content_srf
.flags
= 0;
546 content_srf
.mip_levels
[0] = 1;
547 content_srf
.multisample_count
= 0;
550 stdu
->content_fb_type
= SEPARATE_SURFACE
;
552 new_vfbs
= vmw_framebuffer_to_vfbs(new_fb
);
553 content_srf
= *new_vfbs
->surface
;
557 ret
= vmw_surface_gb_priv_define(crtc
->dev
,
558 0, /* because kernel visible only */
561 true, /* a scanout buffer */
562 content_srf
.mip_levels
[0],
563 content_srf
.multisample_count
,
567 if (unlikely(ret
!= 0)) {
568 DRM_ERROR("Cannot allocate a display FB.\n");
569 goto err_unref_content
;
572 stdu
->display_srf
= display_srf
;
574 new_vfbs
= vmw_framebuffer_to_vfbs(new_fb
);
575 stdu
->display_srf
= new_vfbs
->surface
;
579 ret
= vmw_stdu_pin_display(stdu
);
580 if (unlikely(ret
!= 0)) {
581 stdu
->display_srf
= NULL
;
582 goto err_unref_content
;
585 vmw_svga_enable(dev_priv
);
588 * Steps to displaying a surface, assume surface is already
590 * 1. define a screen target
591 * 2. bind a fb to the screen target
592 * 3. update that screen target (this is done later by
593 * vmw_kms_stdu_do_surface_dirty_or_present)
595 ret
= vmw_stdu_define_st(dev_priv
, stdu
);
596 if (unlikely(ret
!= 0))
597 goto err_unpin_display_and_content
;
599 ret
= vmw_stdu_bind_st(dev_priv
, stdu
, &stdu
->display_srf
->res
);
600 if (unlikely(ret
!= 0))
601 goto err_unpin_destroy_st
;
604 connector
->encoder
= encoder
;
605 encoder
->crtc
= crtc
;
608 crtc
->primary
->fb
= new_fb
;
609 crtc
->enabled
= true;
613 err_unpin_destroy_st
:
614 vmw_stdu_destroy_st(dev_priv
, stdu
);
615 err_unpin_display_and_content
:
616 vmw_stdu_unpin_display(stdu
);
618 stdu
->content_fb
= NULL
;
625 * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
627 * @crtc: CRTC to attach FB to
629 * @event: Event to be posted. This event should've been alloced
630 * using k[mz]alloc, and should've been completely initialized.
631 * @page_flip_flags: Input flags.
633 * If the STDU uses the same display and content buffers, i.e. a true flip,
634 * this function will replace the existing display buffer with the new content
637 * If the STDU uses different display and content buffers, i.e. a blit, then
638 * only the content buffer will be updated.
641 * 0 on success, error code on failure
643 static int vmw_stdu_crtc_page_flip(struct drm_crtc
*crtc
,
644 struct drm_framebuffer
*new_fb
,
645 struct drm_pending_vblank_event
*event
,
649 struct vmw_private
*dev_priv
= vmw_priv(crtc
->dev
);
650 struct vmw_screen_target_display_unit
*stdu
;
656 dev_priv
= vmw_priv(crtc
->dev
);
657 stdu
= vmw_crtc_to_stdu(crtc
);
658 crtc
->primary
->fb
= new_fb
;
659 stdu
->content_fb
= new_fb
;
661 if (stdu
->display_srf
) {
663 * If the display surface is the same as the content surface
664 * then remove the reference
666 if (stdu
->content_fb_type
== SAME_AS_DISPLAY
) {
668 /* Unbind the current surface */
669 ret
= vmw_stdu_bind_st(dev_priv
, stdu
, NULL
);
670 if (unlikely(ret
!= 0))
673 vmw_stdu_unpin_display(stdu
);
674 stdu
->display_srf
= NULL
;
680 /* Blanks the display */
681 (void) vmw_stdu_update_st(dev_priv
, stdu
);
687 if (stdu
->content_fb_type
== SAME_AS_DISPLAY
) {
688 stdu
->display_srf
= vmw_framebuffer_to_vfbs(new_fb
)->surface
;
689 ret
= vmw_stdu_pin_display(stdu
);
691 stdu
->display_srf
= NULL
;
695 /* Bind display surface */
696 ret
= vmw_stdu_bind_st(dev_priv
, stdu
, &stdu
->display_srf
->res
);
697 if (unlikely(ret
!= 0))
698 goto err_unpin_display_and_content
;
701 /* Update display surface: after this point everything is bound */
702 ret
= vmw_stdu_update_st(dev_priv
, stdu
);
703 if (unlikely(ret
!= 0))
707 struct vmw_fence_obj
*fence
= NULL
;
708 struct drm_file
*file_priv
= event
->base
.file_priv
;
710 vmw_execbuf_fence_commands(NULL
, dev_priv
, &fence
, NULL
);
714 ret
= vmw_event_fence_action_queue(file_priv
, fence
,
716 &event
->event
.tv_sec
,
717 &event
->event
.tv_usec
,
719 vmw_fence_obj_unreference(&fence
);
721 vmw_fifo_flush(dev_priv
, false);
726 err_unpin_display_and_content
:
727 vmw_stdu_unpin_display(stdu
);
729 crtc
->primary
->fb
= NULL
;
730 stdu
->content_fb
= NULL
;
736 * vmw_stdu_dmabuf_clip - Callback to encode a suface DMA command cliprect
738 * @dirty: The closure structure.
740 * Encodes a surface DMA command cliprect and updates the bounding box
743 static void vmw_stdu_dmabuf_clip(struct vmw_kms_dirty
*dirty
)
745 struct vmw_stdu_dirty
*ddirty
=
746 container_of(dirty
, struct vmw_stdu_dirty
, base
);
747 struct vmw_stdu_dma
*cmd
= dirty
->cmd
;
748 struct SVGA3dCopyBox
*blit
= (struct SVGA3dCopyBox
*) &cmd
[1];
750 blit
+= dirty
->num_hits
;
751 blit
->srcx
= dirty
->fb_x
;
752 blit
->srcy
= dirty
->fb_y
;
753 blit
->x
= dirty
->unit_x1
;
754 blit
->y
= dirty
->unit_y1
;
756 blit
->w
= dirty
->unit_x2
- dirty
->unit_x1
;
757 blit
->h
= dirty
->unit_y2
- dirty
->unit_y1
;
760 if (ddirty
->transfer
!= SVGA3D_WRITE_HOST_VRAM
)
763 /* Destination bounding box */
764 ddirty
->left
= min_t(s32
, ddirty
->left
, dirty
->unit_x1
);
765 ddirty
->top
= min_t(s32
, ddirty
->top
, dirty
->unit_y1
);
766 ddirty
->right
= max_t(s32
, ddirty
->right
, dirty
->unit_x2
);
767 ddirty
->bottom
= max_t(s32
, ddirty
->bottom
, dirty
->unit_y2
);
771 * vmw_stdu_dmabuf_fifo_commit - Callback to fill in and submit a DMA command.
773 * @dirty: The closure structure.
775 * Fills in the missing fields in a DMA command, and optionally encodes
776 * a screen target update command, depending on transfer direction.
778 static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty
*dirty
)
780 struct vmw_stdu_dirty
*ddirty
=
781 container_of(dirty
, struct vmw_stdu_dirty
, base
);
782 struct vmw_screen_target_display_unit
*stdu
=
783 container_of(dirty
->unit
, typeof(*stdu
), base
);
784 struct vmw_stdu_dma
*cmd
= dirty
->cmd
;
785 struct SVGA3dCopyBox
*blit
= (struct SVGA3dCopyBox
*) &cmd
[1];
786 SVGA3dCmdSurfaceDMASuffix
*suffix
=
787 (SVGA3dCmdSurfaceDMASuffix
*) &blit
[dirty
->num_hits
];
788 size_t blit_size
= sizeof(*blit
) * dirty
->num_hits
+ sizeof(*suffix
);
790 if (!dirty
->num_hits
) {
791 vmw_fifo_commit(dirty
->dev_priv
, 0);
795 cmd
->header
.id
= SVGA_3D_CMD_SURFACE_DMA
;
796 cmd
->header
.size
= sizeof(cmd
->body
) + blit_size
;
797 vmw_bo_get_guest_ptr(&ddirty
->buf
->base
, &cmd
->body
.guest
.ptr
);
798 cmd
->body
.guest
.pitch
= ddirty
->pitch
;
799 cmd
->body
.host
.sid
= stdu
->display_srf
->res
.id
;
800 cmd
->body
.host
.face
= 0;
801 cmd
->body
.host
.mipmap
= 0;
802 cmd
->body
.transfer
= ddirty
->transfer
;
803 suffix
->suffixSize
= sizeof(*suffix
);
804 suffix
->maximumOffset
= ddirty
->buf
->base
.num_pages
* PAGE_SIZE
;
806 if (ddirty
->transfer
== SVGA3D_WRITE_HOST_VRAM
) {
807 blit_size
+= sizeof(struct vmw_stdu_update
);
809 vmw_stdu_populate_update(&suffix
[1], stdu
->base
.unit
,
810 ddirty
->left
, ddirty
->right
,
811 ddirty
->top
, ddirty
->bottom
);
814 vmw_fifo_commit(dirty
->dev_priv
, sizeof(*cmd
) + blit_size
);
816 ddirty
->left
= ddirty
->top
= S32_MAX
;
817 ddirty
->right
= ddirty
->bottom
= S32_MIN
;
821 * vmw_kms_stdu_dma - Perform a DMA transfer between a dma-buffer backed
822 * framebuffer and the screen target system.
824 * @dev_priv: Pointer to the device private structure.
825 * @file_priv: Pointer to a struct drm-file identifying the caller. May be
826 * set to NULL, but then @user_fence_rep must also be set to NULL.
827 * @vfb: Pointer to the dma-buffer backed framebuffer.
828 * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
829 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
831 * @num_clips: Number of clip rects in @clips or @vclips.
832 * @increment: Increment to use when looping over @clips or @vclips.
833 * @to_surface: Whether to DMA to the screen target system as opposed to
834 * from the screen target system.
835 * @interruptible: Whether to perform waits interruptible if possible.
837 * If DMA-ing till the screen target system, the function will also notify
838 * the screen target system that a bounding box of the cliprects has been
840 * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
843 int vmw_kms_stdu_dma(struct vmw_private
*dev_priv
,
844 struct drm_file
*file_priv
,
845 struct vmw_framebuffer
*vfb
,
846 struct drm_vmw_fence_rep __user
*user_fence_rep
,
847 struct drm_clip_rect
*clips
,
848 struct drm_vmw_rect
*vclips
,
854 struct vmw_dma_buffer
*buf
=
855 container_of(vfb
, struct vmw_framebuffer_dmabuf
, base
)->buffer
;
856 struct vmw_stdu_dirty ddirty
;
859 ret
= vmw_kms_helper_buffer_prepare(dev_priv
, buf
, interruptible
,
864 ddirty
.transfer
= (to_surface
) ? SVGA3D_WRITE_HOST_VRAM
:
865 SVGA3D_READ_HOST_VRAM
;
866 ddirty
.left
= ddirty
.top
= S32_MAX
;
867 ddirty
.right
= ddirty
.bottom
= S32_MIN
;
868 ddirty
.pitch
= vfb
->base
.pitches
[0];
870 ddirty
.base
.fifo_commit
= vmw_stdu_dmabuf_fifo_commit
;
871 ddirty
.base
.clip
= vmw_stdu_dmabuf_clip
;
872 ddirty
.base
.fifo_reserve_size
= sizeof(struct vmw_stdu_dma
) +
873 num_clips
* sizeof(SVGA3dCopyBox
) +
874 sizeof(SVGA3dCmdSurfaceDMASuffix
);
876 ddirty
.base
.fifo_reserve_size
+= sizeof(struct vmw_stdu_update
);
878 ret
= vmw_kms_helper_dirty(dev_priv
, vfb
, clips
, vclips
,
879 0, 0, num_clips
, increment
, &ddirty
.base
);
880 vmw_kms_helper_buffer_finish(dev_priv
, file_priv
, buf
, NULL
,
887 * vmw_stdu_surface_clip - Callback to encode a surface copy command cliprect
889 * @dirty: The closure structure.
891 * Encodes a surface copy command cliprect and updates the bounding box
894 static void vmw_kms_stdu_surface_clip(struct vmw_kms_dirty
*dirty
)
896 struct vmw_stdu_dirty
*sdirty
=
897 container_of(dirty
, struct vmw_stdu_dirty
, base
);
898 struct vmw_stdu_surface_copy
*cmd
= dirty
->cmd
;
899 struct vmw_screen_target_display_unit
*stdu
=
900 container_of(dirty
->unit
, typeof(*stdu
), base
);
902 if (sdirty
->sid
!= stdu
->display_srf
->res
.id
) {
903 struct SVGA3dCopyBox
*blit
= (struct SVGA3dCopyBox
*) &cmd
[1];
905 blit
+= dirty
->num_hits
;
906 blit
->srcx
= dirty
->fb_x
;
907 blit
->srcy
= dirty
->fb_y
;
908 blit
->x
= dirty
->unit_x1
;
909 blit
->y
= dirty
->unit_y1
;
911 blit
->w
= dirty
->unit_x2
- dirty
->unit_x1
;
912 blit
->h
= dirty
->unit_y2
- dirty
->unit_y1
;
917 /* Destination bounding box */
918 sdirty
->left
= min_t(s32
, sdirty
->left
, dirty
->unit_x1
);
919 sdirty
->top
= min_t(s32
, sdirty
->top
, dirty
->unit_y1
);
920 sdirty
->right
= max_t(s32
, sdirty
->right
, dirty
->unit_x2
);
921 sdirty
->bottom
= max_t(s32
, sdirty
->bottom
, dirty
->unit_y2
);
925 * vmw_stdu_surface_fifo_commit - Callback to fill in and submit a surface
928 * @dirty: The closure structure.
930 * Fills in the missing fields in a surface copy command, and encodes a screen
931 * target update command.
933 static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty
*dirty
)
935 struct vmw_stdu_dirty
*sdirty
=
936 container_of(dirty
, struct vmw_stdu_dirty
, base
);
937 struct vmw_screen_target_display_unit
*stdu
=
938 container_of(dirty
->unit
, typeof(*stdu
), base
);
939 struct vmw_stdu_surface_copy
*cmd
= dirty
->cmd
;
940 struct vmw_stdu_update
*update
;
941 size_t blit_size
= sizeof(SVGA3dCopyBox
) * dirty
->num_hits
;
944 if (!dirty
->num_hits
) {
945 vmw_fifo_commit(dirty
->dev_priv
, 0);
949 if (sdirty
->sid
!= stdu
->display_srf
->res
.id
) {
950 struct SVGA3dCopyBox
*blit
= (struct SVGA3dCopyBox
*) &cmd
[1];
952 cmd
->header
.id
= SVGA_3D_CMD_SURFACE_COPY
;
953 cmd
->header
.size
= sizeof(cmd
->body
) + blit_size
;
954 cmd
->body
.src
.sid
= sdirty
->sid
;
955 cmd
->body
.dest
.sid
= stdu
->display_srf
->res
.id
;
956 update
= (struct vmw_stdu_update
*) &blit
[dirty
->num_hits
];
957 commit_size
= sizeof(*cmd
) + blit_size
+ sizeof(*update
);
960 commit_size
= sizeof(*update
);
963 vmw_stdu_populate_update(update
, stdu
->base
.unit
, sdirty
->left
,
964 sdirty
->right
, sdirty
->top
, sdirty
->bottom
);
966 vmw_fifo_commit(dirty
->dev_priv
, commit_size
);
968 sdirty
->left
= sdirty
->top
= S32_MAX
;
969 sdirty
->right
= sdirty
->bottom
= S32_MIN
;
973 * vmw_kms_stdu_surface_dirty - Dirty part of a surface backed framebuffer
975 * @dev_priv: Pointer to the device private structure.
976 * @framebuffer: Pointer to the surface-buffer backed framebuffer.
977 * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
978 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
980 * @srf: Pointer to surface to blit from. If NULL, the surface attached
981 * to @framebuffer will be used.
982 * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
983 * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
984 * @num_clips: Number of clip rects in @clips.
985 * @inc: Increment to use when looping over @clips.
986 * @out_fence: If non-NULL, will return a ref-counted pointer to a
987 * struct vmw_fence_obj. The returned fence pointer may be NULL in which
988 * case the device has already synchronized.
990 * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
993 int vmw_kms_stdu_surface_dirty(struct vmw_private
*dev_priv
,
994 struct vmw_framebuffer
*framebuffer
,
995 struct drm_clip_rect
*clips
,
996 struct drm_vmw_rect
*vclips
,
997 struct vmw_resource
*srf
,
1000 unsigned num_clips
, int inc
,
1001 struct vmw_fence_obj
**out_fence
)
1003 struct vmw_framebuffer_surface
*vfbs
=
1004 container_of(framebuffer
, typeof(*vfbs
), base
);
1005 struct vmw_stdu_dirty sdirty
;
1009 srf
= &vfbs
->surface
->res
;
1011 ret
= vmw_kms_helper_resource_prepare(srf
, true);
1015 if (vfbs
->is_dmabuf_proxy
) {
1016 ret
= vmw_kms_update_proxy(srf
, clips
, num_clips
, inc
);
1021 sdirty
.base
.fifo_commit
= vmw_kms_stdu_surface_fifo_commit
;
1022 sdirty
.base
.clip
= vmw_kms_stdu_surface_clip
;
1023 sdirty
.base
.fifo_reserve_size
= sizeof(struct vmw_stdu_surface_copy
) +
1024 sizeof(SVGA3dCopyBox
) * num_clips
+
1025 sizeof(struct vmw_stdu_update
);
1026 sdirty
.sid
= srf
->id
;
1027 sdirty
.left
= sdirty
.top
= S32_MAX
;
1028 sdirty
.right
= sdirty
.bottom
= S32_MIN
;
1030 ret
= vmw_kms_helper_dirty(dev_priv
, framebuffer
, clips
, vclips
,
1031 dest_x
, dest_y
, num_clips
, inc
,
1034 vmw_kms_helper_resource_finish(srf
, out_fence
);
1041 * Screen Target CRTC dispatch table
1043 static struct drm_crtc_funcs vmw_stdu_crtc_funcs
= {
1044 .save
= vmw_du_crtc_save
,
1045 .restore
= vmw_du_crtc_restore
,
1046 .cursor_set2
= vmw_du_crtc_cursor_set2
,
1047 .cursor_move
= vmw_du_crtc_cursor_move
,
1048 .gamma_set
= vmw_du_crtc_gamma_set
,
1049 .destroy
= vmw_stdu_crtc_destroy
,
1050 .set_config
= vmw_stdu_crtc_set_config
,
1051 .page_flip
= vmw_stdu_crtc_page_flip
,
1056 /******************************************************************************
1057 * Screen Target Display Unit Encoder Functions
1058 *****************************************************************************/
1061 * vmw_stdu_encoder_destroy - cleans up the STDU
1063 * @encoder: used the get the containing STDU
1065 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
1066 * this can be a no-op. Nevertheless, it doesn't hurt of have this in case
1067 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
1070 static void vmw_stdu_encoder_destroy(struct drm_encoder
*encoder
)
1072 vmw_stdu_destroy(vmw_encoder_to_stdu(encoder
));
1075 static struct drm_encoder_funcs vmw_stdu_encoder_funcs
= {
1076 .destroy
= vmw_stdu_encoder_destroy
,
1081 /******************************************************************************
1082 * Screen Target Display Unit Connector Functions
1083 *****************************************************************************/
1086 * vmw_stdu_connector_destroy - cleans up the STDU
1088 * @connector: used to get the containing STDU
1090 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
1091 * this can be a no-op. Nevertheless, it doesn't hurt of have this in case
1092 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
1095 static void vmw_stdu_connector_destroy(struct drm_connector
*connector
)
1097 vmw_stdu_destroy(vmw_connector_to_stdu(connector
));
1102 static struct drm_connector_funcs vmw_stdu_connector_funcs
= {
1103 .dpms
= vmw_du_connector_dpms
,
1104 .save
= vmw_du_connector_save
,
1105 .restore
= vmw_du_connector_restore
,
1106 .detect
= vmw_du_connector_detect
,
1107 .fill_modes
= vmw_du_connector_fill_modes
,
1108 .set_property
= vmw_du_connector_set_property
,
1109 .destroy
= vmw_stdu_connector_destroy
,
1115 * vmw_stdu_init - Sets up a Screen Target Display Unit
1117 * @dev_priv: VMW DRM device
1118 * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS
1120 * This function is called once per CRTC, and allocates one Screen Target
1121 * display unit to represent that CRTC. Since the SVGA device does not separate
1122 * out encoder and connector, they are represented as part of the STDU as well.
1124 static int vmw_stdu_init(struct vmw_private
*dev_priv
, unsigned unit
)
1126 struct vmw_screen_target_display_unit
*stdu
;
1127 struct drm_device
*dev
= dev_priv
->dev
;
1128 struct drm_connector
*connector
;
1129 struct drm_encoder
*encoder
;
1130 struct drm_crtc
*crtc
;
1133 stdu
= kzalloc(sizeof(*stdu
), GFP_KERNEL
);
1137 stdu
->base
.unit
= unit
;
1138 crtc
= &stdu
->base
.crtc
;
1139 encoder
= &stdu
->base
.encoder
;
1140 connector
= &stdu
->base
.connector
;
1142 stdu
->base
.pref_active
= (unit
== 0);
1143 stdu
->base
.pref_width
= dev_priv
->initial_width
;
1144 stdu
->base
.pref_height
= dev_priv
->initial_height
;
1145 stdu
->base
.is_implicit
= true;
1147 drm_connector_init(dev
, connector
, &vmw_stdu_connector_funcs
,
1148 DRM_MODE_CONNECTOR_VIRTUAL
);
1149 connector
->status
= vmw_du_connector_detect(connector
, false);
1151 drm_encoder_init(dev
, encoder
, &vmw_stdu_encoder_funcs
,
1152 DRM_MODE_ENCODER_VIRTUAL
);
1153 drm_mode_connector_attach_encoder(connector
, encoder
);
1154 encoder
->possible_crtcs
= (1 << unit
);
1155 encoder
->possible_clones
= 0;
1157 (void) drm_connector_register(connector
);
1159 drm_crtc_init(dev
, crtc
, &vmw_stdu_crtc_funcs
);
1161 drm_mode_crtc_set_gamma_size(crtc
, 256);
1163 drm_object_attach_property(&connector
->base
,
1164 dev
->mode_config
.dirty_info_property
,
1173 * vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit
1175 * @stdu: Screen Target Display Unit to be destroyed
1177 * Clean up after vmw_stdu_init
1179 static void vmw_stdu_destroy(struct vmw_screen_target_display_unit
*stdu
)
1181 vmw_stdu_unpin_display(stdu
);
1183 vmw_du_cleanup(&stdu
->base
);
1189 /******************************************************************************
1190 * Screen Target Display KMS Functions
1192 * These functions are called by the common KMS code in vmwgfx_kms.c
1193 *****************************************************************************/
1196 * vmw_kms_stdu_init_display - Initializes a Screen Target based display
1198 * @dev_priv: VMW DRM device
1200 * This function initialize a Screen Target based display device. It checks
1201 * the capability bits to make sure the underlying hardware can support
1202 * screen targets, and then creates the maximum number of CRTCs, a.k.a Display
1203 * Units, as supported by the display hardware.
1206 * 0 on success, error code otherwise
1208 int vmw_kms_stdu_init_display(struct vmw_private
*dev_priv
)
1210 struct drm_device
*dev
= dev_priv
->dev
;
1214 /* Do nothing if Screen Target support is turned off */
1215 if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE
)
1218 if (!(dev_priv
->capabilities
& SVGA_CAP_GBOBJECTS
))
1221 ret
= drm_vblank_init(dev
, VMWGFX_NUM_DISPLAY_UNITS
);
1222 if (unlikely(ret
!= 0))
1225 ret
= drm_mode_create_dirty_info_property(dev
);
1226 if (unlikely(ret
!= 0))
1227 goto err_vblank_cleanup
;
1229 dev_priv
->active_display_unit
= vmw_du_screen_target
;
1231 for (i
= 0; i
< VMWGFX_NUM_DISPLAY_UNITS
; ++i
) {
1232 ret
= vmw_stdu_init(dev_priv
, i
);
1234 if (unlikely(ret
!= 0)) {
1235 DRM_ERROR("Failed to initialize STDU %d", i
);
1236 goto err_vblank_cleanup
;
1240 DRM_INFO("Screen Target Display device initialized\n");
1245 drm_vblank_cleanup(dev
);
1252 * vmw_kms_stdu_close_display - Cleans up after vmw_kms_stdu_init_display
1254 * @dev_priv: VMW DRM device
1256 * Frees up any resources allocated by vmw_kms_stdu_init_display
1261 int vmw_kms_stdu_close_display(struct vmw_private
*dev_priv
)
1263 struct drm_device
*dev
= dev_priv
->dev
;
1265 drm_vblank_cleanup(dev
);