aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@vmware.com>2011-10-07 09:23:07 -0400
committerDave Airlie <airlied@redhat.com>2011-10-10 04:01:51 -0400
commitc6ca8391793762713e81153a0c1206f7e20e2189 (patch)
tree4bc14f488f17d97edec0b3362694e2ae97bd2922 /drivers/gpu/drm/vmwgfx
parent414ee50b3a111983056b1a828fac08f9e8fbc7e9 (diff)
vmwgfx: Don't use virtual coords when using screen objects
Signed-off-by: Jakob Bornecrantz <jakob@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c272
1 files changed, 215 insertions, 57 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index fc62c8798c4c..2421d0cd0df9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -358,49 +358,109 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
358 struct drm_clip_rect *clips, 358 struct drm_clip_rect *clips,
359 unsigned num_clips, int inc) 359 unsigned num_clips, int inc)
360{ 360{
361 int left = clips->x2, right = clips->x1; 361 struct drm_clip_rect *clips_ptr;
362 int top = clips->y2, bottom = clips->y1; 362 struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
363 struct drm_crtc *crtc;
363 size_t fifo_size; 364 size_t fifo_size;
364 int i, ret; 365 int i, num_units;
366 int ret = 0; /* silence warning */
367 int left, right, top, bottom;
365 368
366 struct { 369 struct {
367 SVGA3dCmdHeader header; 370 SVGA3dCmdHeader header;
368 SVGA3dCmdBlitSurfaceToScreen body; 371 SVGA3dCmdBlitSurfaceToScreen body;
369 } *cmd; 372 } *cmd;
373 SVGASignedRect *blits;
370 374
371 375
372 fifo_size = sizeof(*cmd); 376 num_units = 0;
377 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
378 head) {
379 if (crtc->fb != &framebuffer->base)
380 continue;
381 units[num_units++] = vmw_crtc_to_du(crtc);
382 }
383
384 BUG_ON(surf == NULL);
385 BUG_ON(!clips || !num_clips);
386
387 fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
373 cmd = kzalloc(fifo_size, GFP_KERNEL); 388 cmd = kzalloc(fifo_size, GFP_KERNEL);
374 if (unlikely(cmd == NULL)) { 389 if (unlikely(cmd == NULL)) {
375 DRM_ERROR("Temporary fifo memory alloc failed.\n"); 390 DRM_ERROR("Temporary fifo memory alloc failed.\n");
376 return -ENOMEM; 391 return -ENOMEM;
377 } 392 }
378 393
379 cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); 394 left = clips->x1;
380 cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 395 right = clips->x2;
381 396 top = clips->y1;
382 cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle); 397 bottom = clips->y2;
383 cmd->body.destScreenId = SVGA_ID_INVALID; /* virtual coords */ 398
384 399 clips_ptr = clips;
385 for (i = 0; i < num_clips; i++, clips += inc) { 400 for (i = 1; i < num_clips; i++, clips_ptr += inc) {
386 left = min_t(int, left, (int)clips->x1); 401 left = min_t(int, left, (int)clips_ptr->x1);
387 right = max_t(int, right, (int)clips->x2); 402 right = max_t(int, right, (int)clips_ptr->x2);
388 top = min_t(int, top, (int)clips->y1); 403 top = min_t(int, top, (int)clips_ptr->y1);
389 bottom = max_t(int, bottom, (int)clips->y2); 404 bottom = max_t(int, bottom, (int)clips_ptr->y2);
390 } 405 }
391 406
407 /* only need to do this once */
408 memset(cmd, 0, fifo_size);
409 cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
410 cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
411
392 cmd->body.srcRect.left = left; 412 cmd->body.srcRect.left = left;
393 cmd->body.srcRect.right = right; 413 cmd->body.srcRect.right = right;
394 cmd->body.srcRect.top = top; 414 cmd->body.srcRect.top = top;
395 cmd->body.srcRect.bottom = bottom; 415 cmd->body.srcRect.bottom = bottom;
396 416
397 cmd->body.destRect.left = left; 417 clips_ptr = clips;
398 cmd->body.destRect.right = right; 418 blits = (SVGASignedRect *)&cmd[1];
399 cmd->body.destRect.top = top; 419 for (i = 0; i < num_clips; i++, clips_ptr += inc) {
400 cmd->body.destRect.bottom = bottom; 420 blits[i].left = clips_ptr->x1 - left;
421 blits[i].right = clips_ptr->x2 - left;
422 blits[i].top = clips_ptr->y1 - top;
423 blits[i].bottom = clips_ptr->y2 - top;
424 }
425
426 /* do per unit writing, reuse fifo for each */
427 for (i = 0; i < num_units; i++) {
428 struct vmw_display_unit *unit = units[i];
429 int clip_x1 = left - unit->crtc.x;
430 int clip_y1 = top - unit->crtc.y;
431 int clip_x2 = right - unit->crtc.x;
432 int clip_y2 = bottom - unit->crtc.y;
433
434 /* skip any crtcs that misses the clip region */
435 if (clip_x1 >= unit->crtc.mode.hdisplay ||
436 clip_y1 >= unit->crtc.mode.vdisplay ||
437 clip_x2 <= 0 || clip_y2 <= 0)
438 continue;
439
440 /* need to reset sid as it is changed by execbuf */
441 cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle);
442
443 cmd->body.destScreenId = unit->unit;
444
445 /*
446 * The blit command is a lot more resilient then the
447 * readback command when it comes to clip rects. So its
448 * okay to go out of bounds.
449 */
450
451 cmd->body.destRect.left = clip_x1;
452 cmd->body.destRect.right = clip_x2;
453 cmd->body.destRect.top = clip_y1;
454 cmd->body.destRect.bottom = clip_y2;
455
456
457 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
458 fifo_size, 0, NULL);
459
460 if (unlikely(ret != 0))
461 break;
462 }
401 463
402 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size,
403 0, NULL);
404 kfree(cmd); 464 kfree(cmd);
405 465
406 return ret; 466 return ret;
@@ -615,27 +675,19 @@ static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv,
615 return 0; 675 return 0;
616} 676}
617 677
618static int do_dmabuf_dirty_sou(struct drm_file *file_priv, 678static int do_dmabuf_define_gmrfb(struct drm_file *file_priv,
619 struct vmw_private *dev_priv, 679 struct vmw_private *dev_priv,
620 struct vmw_framebuffer *framebuffer, 680 struct vmw_framebuffer *framebuffer)
621 struct vmw_dma_buffer *buffer,
622 unsigned flags, unsigned color,
623 struct drm_clip_rect *clips,
624 unsigned num_clips, int increment)
625{ 681{
626 size_t fifo_size; 682 size_t fifo_size;
627 int i, ret; 683 int ret;
628 684
629 struct { 685 struct {
630 uint32_t header; 686 uint32_t header;
631 SVGAFifoCmdDefineGMRFB body; 687 SVGAFifoCmdDefineGMRFB body;
632 } *cmd; 688 } *cmd;
633 struct {
634 uint32_t header;
635 SVGAFifoCmdBlitGMRFBToScreen body;
636 } *blits;
637 689
638 fifo_size = sizeof(*cmd) + sizeof(*blits) * num_clips; 690 fifo_size = sizeof(*cmd);
639 cmd = kmalloc(fifo_size, GFP_KERNEL); 691 cmd = kmalloc(fifo_size, GFP_KERNEL);
640 if (unlikely(cmd == NULL)) { 692 if (unlikely(cmd == NULL)) {
641 DRM_ERROR("Failed to allocate temporary cmd buffer.\n"); 693 DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
@@ -651,17 +703,6 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
651 cmd->body.ptr.gmrId = framebuffer->user_handle; 703 cmd->body.ptr.gmrId = framebuffer->user_handle;
652 cmd->body.ptr.offset = 0; 704 cmd->body.ptr.offset = 0;
653 705
654 blits = (void *)&cmd[1];
655 for (i = 0; i < num_clips; i++, clips += increment) {
656 blits[i].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
657 blits[i].body.srcOrigin.x = clips->x1;
658 blits[i].body.srcOrigin.y = clips->y1;
659 blits[i].body.destRect.left = clips->x1;
660 blits[i].body.destRect.top = clips->y1;
661 blits[i].body.destRect.right = clips->x2;
662 blits[i].body.destRect.bottom = clips->y2;
663 }
664
665 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, 706 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
666 fifo_size, 0, NULL); 707 fifo_size, 0, NULL);
667 708
@@ -670,6 +711,88 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
670 return ret; 711 return ret;
671} 712}
672 713
714static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
715 struct vmw_private *dev_priv,
716 struct vmw_framebuffer *framebuffer,
717 struct vmw_dma_buffer *buffer,
718 unsigned flags, unsigned color,
719 struct drm_clip_rect *clips,
720 unsigned num_clips, int increment)
721{
722 struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
723 struct drm_clip_rect *clips_ptr;
724 int i, k, num_units, ret;
725 struct drm_crtc *crtc;
726 size_t fifo_size;
727
728 struct {
729 uint32_t header;
730 SVGAFifoCmdBlitGMRFBToScreen body;
731 } *blits;
732
733 ret = do_dmabuf_define_gmrfb(file_priv, dev_priv, framebuffer);
734 if (unlikely(ret != 0))
735 return ret; /* define_gmrfb prints warnings */
736
737 fifo_size = sizeof(*blits) * num_clips;
738 blits = kmalloc(fifo_size, GFP_KERNEL);
739 if (unlikely(blits == NULL)) {
740 DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
741 return -ENOMEM;
742 }
743
744 num_units = 0;
745 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
746 if (crtc->fb != &framebuffer->base)
747 continue;
748 units[num_units++] = vmw_crtc_to_du(crtc);
749 }
750
751 for (k = 0; k < num_units; k++) {
752 struct vmw_display_unit *unit = units[k];
753 int hit_num = 0;
754
755 clips_ptr = clips;
756 for (i = 0; i < num_clips; i++, clips_ptr += increment) {
757 int clip_x1 = clips_ptr->x1 - unit->crtc.x;
758 int clip_y1 = clips_ptr->y1 - unit->crtc.y;
759 int clip_x2 = clips_ptr->x2 - unit->crtc.x;
760 int clip_y2 = clips_ptr->y2 - unit->crtc.y;
761
762 /* skip any crtcs that misses the clip region */
763 if (clip_x1 >= unit->crtc.mode.hdisplay ||
764 clip_y1 >= unit->crtc.mode.vdisplay ||
765 clip_x2 <= 0 || clip_y2 <= 0)
766 continue;
767
768 blits[hit_num].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
769 blits[hit_num].body.destScreenId = unit->unit;
770 blits[hit_num].body.srcOrigin.x = clips_ptr->x1;
771 blits[hit_num].body.srcOrigin.y = clips_ptr->y1;
772 blits[hit_num].body.destRect.left = clip_x1;
773 blits[hit_num].body.destRect.top = clip_y1;
774 blits[hit_num].body.destRect.right = clip_x2;
775 blits[hit_num].body.destRect.bottom = clip_y2;
776 hit_num++;
777 }
778
779 /* no clips hit the crtc */
780 if (hit_num == 0)
781 continue;
782
783 fifo_size = sizeof(*blits) * hit_num;
784 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits,
785 fifo_size, 0, NULL);
786
787 if (unlikely(ret != 0))
788 break;
789 }
790
791 kfree(blits);
792
793 return ret;
794}
795
673int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, 796int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
674 struct drm_file *file_priv, 797 struct drm_file *file_priv,
675 unsigned flags, unsigned color, 798 unsigned flags, unsigned color,
@@ -959,8 +1082,11 @@ int vmw_kms_present(struct vmw_private *dev_priv,
959 struct drm_vmw_rect *clips, 1082 struct drm_vmw_rect *clips,
960 uint32_t num_clips) 1083 uint32_t num_clips)
961{ 1084{
1085 struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
1086 struct drm_crtc *crtc;
962 size_t fifo_size; 1087 size_t fifo_size;
963 int i, ret; 1088 int i, k, num_units;
1089 int ret = 0; /* silence warning */
964 1090
965 struct { 1091 struct {
966 SVGA3dCmdHeader header; 1092 SVGA3dCmdHeader header;
@@ -968,6 +1094,13 @@ int vmw_kms_present(struct vmw_private *dev_priv,
968 } *cmd; 1094 } *cmd;
969 SVGASignedRect *blits; 1095 SVGASignedRect *blits;
970 1096
1097 num_units = 0;
1098 list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
1099 if (crtc->fb != &vfb->base)
1100 continue;
1101 units[num_units++] = vmw_crtc_to_du(crtc);
1102 }
1103
971 BUG_ON(surface == NULL); 1104 BUG_ON(surface == NULL);
972 BUG_ON(!clips || !num_clips); 1105 BUG_ON(!clips || !num_clips);
973 1106
@@ -978,24 +1111,16 @@ int vmw_kms_present(struct vmw_private *dev_priv,
978 return -ENOMEM; 1111 return -ENOMEM;
979 } 1112 }
980 1113
1114 /* only need to do this once */
981 memset(cmd, 0, fifo_size); 1115 memset(cmd, 0, fifo_size);
982
983 cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); 1116 cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
984 cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); 1117 cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
985 1118
986 cmd->body.srcImage.sid = sid;
987 cmd->body.destScreenId = SVGA_ID_INVALID; /* virtual coords */
988
989 cmd->body.srcRect.left = 0; 1119 cmd->body.srcRect.left = 0;
990 cmd->body.srcRect.right = surface->sizes[0].width; 1120 cmd->body.srcRect.right = surface->sizes[0].width;
991 cmd->body.srcRect.top = 0; 1121 cmd->body.srcRect.top = 0;
992 cmd->body.srcRect.bottom = surface->sizes[0].height; 1122 cmd->body.srcRect.bottom = surface->sizes[0].height;
993 1123
994 cmd->body.destRect.left = destX;
995 cmd->body.destRect.right = destX + surface->sizes[0].width;
996 cmd->body.destRect.top = destY;
997 cmd->body.destRect.bottom = destY + surface->sizes[0].height;
998
999 blits = (SVGASignedRect *)&cmd[1]; 1124 blits = (SVGASignedRect *)&cmd[1];
1000 for (i = 0; i < num_clips; i++) { 1125 for (i = 0; i < num_clips; i++) {
1001 blits[i].left = clips[i].x; 1126 blits[i].left = clips[i].x;
@@ -1004,8 +1129,41 @@ int vmw_kms_present(struct vmw_private *dev_priv,
1004 blits[i].bottom = clips[i].y + clips[i].h; 1129 blits[i].bottom = clips[i].y + clips[i].h;
1005 } 1130 }
1006 1131
1007 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, 1132 for (k = 0; k < num_units; k++) {
1008 fifo_size, 0, NULL); 1133 struct vmw_display_unit *unit = units[k];
1134 int clip_x1 = destX - unit->crtc.x;
1135 int clip_y1 = destY - unit->crtc.y;
1136 int clip_x2 = clip_x1 + surface->sizes[0].width;
1137 int clip_y2 = clip_y1 + surface->sizes[0].height;
1138
1139 /* skip any crtcs that misses the clip region */
1140 if (clip_x1 >= unit->crtc.mode.hdisplay ||
1141 clip_y1 >= unit->crtc.mode.vdisplay ||
1142 clip_x2 <= 0 || clip_y2 <= 0)
1143 continue;
1144
1145 /* need to reset sid as it is changed by execbuf */
1146 cmd->body.srcImage.sid = sid;
1147
1148 cmd->body.destScreenId = unit->unit;
1149
1150 /*
1151 * The blit command is a lot more resilient then the
1152 * readback command when it comes to clip rects. So its
1153 * okay to go out of bounds.
1154 */
1155
1156 cmd->body.destRect.left = clip_x1;
1157 cmd->body.destRect.right = clip_x2;
1158 cmd->body.destRect.top = clip_y1;
1159 cmd->body.destRect.bottom = clip_y2;
1160
1161 ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
1162 fifo_size, 0, NULL);
1163
1164 if (unlikely(ret != 0))
1165 break;
1166 }
1009 1167
1010 kfree(cmd); 1168 kfree(cmd);
1011 1169