diff options
author | Jakob Bornecrantz <jakob@vmware.com> | 2011-10-07 09:23:07 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-10-10 04:01:51 -0400 |
commit | c6ca8391793762713e81153a0c1206f7e20e2189 (patch) | |
tree | 4bc14f488f17d97edec0b3362694e2ae97bd2922 /drivers/gpu/drm/vmwgfx | |
parent | 414ee50b3a111983056b1a828fac08f9e8fbc7e9 (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.c | 272 |
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 | ||
618 | static int do_dmabuf_dirty_sou(struct drm_file *file_priv, | 678 | static 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 | ||
714 | static 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 | |||
673 | int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | 796 | int 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 | ||