.. | .. |
---|
25 | 25 | * |
---|
26 | 26 | ******************************************************************************/ |
---|
27 | 27 | |
---|
28 | | -#include "vmwgfx_kms.h" |
---|
29 | | -#include "device_include/svga3d_surfacedefs.h" |
---|
30 | | -#include <drm/drm_plane_helper.h> |
---|
31 | 28 | #include <drm/drm_atomic.h> |
---|
32 | 29 | #include <drm/drm_atomic_helper.h> |
---|
| 30 | +#include <drm/drm_damage_helper.h> |
---|
| 31 | +#include <drm/drm_fourcc.h> |
---|
| 32 | +#include <drm/drm_plane_helper.h> |
---|
| 33 | +#include <drm/drm_vblank.h> |
---|
33 | 34 | |
---|
| 35 | +#include "vmwgfx_kms.h" |
---|
| 36 | +#include "device_include/svga3d_surfacedefs.h" |
---|
34 | 37 | |
---|
35 | 38 | #define vmw_crtc_to_stdu(x) \ |
---|
36 | 39 | container_of(x, struct vmw_screen_target_display_unit, base.crtc) |
---|
.. | .. |
---|
92 | 95 | SVGA3dCmdSurfaceCopy body; |
---|
93 | 96 | }; |
---|
94 | 97 | |
---|
| 98 | +struct vmw_stdu_update_gb_image { |
---|
| 99 | + SVGA3dCmdHeader header; |
---|
| 100 | + SVGA3dCmdUpdateGBImage body; |
---|
| 101 | +}; |
---|
95 | 102 | |
---|
96 | 103 | /** |
---|
97 | 104 | * struct vmw_screen_target_display_unit |
---|
.. | .. |
---|
107 | 114 | */ |
---|
108 | 115 | struct vmw_screen_target_display_unit { |
---|
109 | 116 | struct vmw_display_unit base; |
---|
110 | | - const struct vmw_surface *display_srf; |
---|
| 117 | + struct vmw_surface *display_srf; |
---|
111 | 118 | enum stdu_content_type content_fb_type; |
---|
112 | 119 | s32 display_width, display_height; |
---|
113 | 120 | |
---|
.. | .. |
---|
163 | 170 | SVGA3dCmdDefineGBScreenTarget body; |
---|
164 | 171 | } *cmd; |
---|
165 | 172 | |
---|
166 | | - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
---|
167 | | - |
---|
168 | | - if (unlikely(cmd == NULL)) { |
---|
169 | | - DRM_ERROR("Out of FIFO space defining Screen Target\n"); |
---|
| 173 | + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); |
---|
| 174 | + if (unlikely(cmd == NULL)) |
---|
170 | 175 | return -ENOMEM; |
---|
171 | | - } |
---|
172 | 176 | |
---|
173 | 177 | cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SCREENTARGET; |
---|
174 | 178 | cmd->header.size = sizeof(cmd->body); |
---|
.. | .. |
---|
225 | 229 | memset(&image, 0, sizeof(image)); |
---|
226 | 230 | image.sid = res ? res->id : SVGA3D_INVALID_ID; |
---|
227 | 231 | |
---|
228 | | - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
---|
229 | | - |
---|
230 | | - if (unlikely(cmd == NULL)) { |
---|
231 | | - DRM_ERROR("Out of FIFO space binding a screen target\n"); |
---|
| 232 | + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); |
---|
| 233 | + if (unlikely(cmd == NULL)) |
---|
232 | 234 | return -ENOMEM; |
---|
233 | | - } |
---|
234 | 235 | |
---|
235 | 236 | cmd->header.id = SVGA_3D_CMD_BIND_GB_SCREENTARGET; |
---|
236 | 237 | cmd->header.size = sizeof(cmd->body); |
---|
.. | .. |
---|
292 | 293 | return -EINVAL; |
---|
293 | 294 | } |
---|
294 | 295 | |
---|
295 | | - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
---|
296 | | - |
---|
297 | | - if (unlikely(cmd == NULL)) { |
---|
298 | | - DRM_ERROR("Out of FIFO space updating a Screen Target\n"); |
---|
| 296 | + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); |
---|
| 297 | + if (unlikely(cmd == NULL)) |
---|
299 | 298 | return -ENOMEM; |
---|
300 | | - } |
---|
301 | 299 | |
---|
302 | 300 | vmw_stdu_populate_update(cmd, stdu->base.unit, |
---|
303 | 301 | 0, stdu->display_width, |
---|
.. | .. |
---|
331 | 329 | if (unlikely(!stdu->defined)) |
---|
332 | 330 | return 0; |
---|
333 | 331 | |
---|
334 | | - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
---|
335 | | - |
---|
336 | | - if (unlikely(cmd == NULL)) { |
---|
337 | | - DRM_ERROR("Out of FIFO space, screen target not destroyed\n"); |
---|
| 332 | + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); |
---|
| 333 | + if (unlikely(cmd == NULL)) |
---|
338 | 334 | return -ENOMEM; |
---|
339 | | - } |
---|
340 | 335 | |
---|
341 | 336 | cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET; |
---|
342 | 337 | cmd->header.size = sizeof(cmd->body); |
---|
.. | .. |
---|
396 | 391 | if (!crtc->state->enable) |
---|
397 | 392 | return; |
---|
398 | 393 | |
---|
399 | | - if (stdu->base.is_implicit) { |
---|
400 | | - x = crtc->x; |
---|
401 | | - y = crtc->y; |
---|
402 | | - } else { |
---|
403 | | - x = vmw_conn_state->gui_x; |
---|
404 | | - y = vmw_conn_state->gui_y; |
---|
405 | | - } |
---|
| 394 | + x = vmw_conn_state->gui_x; |
---|
| 395 | + y = vmw_conn_state->gui_y; |
---|
406 | 396 | |
---|
407 | 397 | vmw_svga_enable(dev_priv); |
---|
408 | 398 | ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, x, y); |
---|
.. | .. |
---|
417 | 407 | { |
---|
418 | 408 | } |
---|
419 | 409 | |
---|
420 | | - |
---|
421 | 410 | static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc, |
---|
422 | 411 | struct drm_crtc_state *old_state) |
---|
423 | 412 | { |
---|
424 | | - struct drm_plane_state *plane_state = crtc->primary->state; |
---|
425 | | - struct vmw_private *dev_priv; |
---|
426 | | - struct vmw_screen_target_display_unit *stdu; |
---|
427 | | - struct vmw_framebuffer *vfb; |
---|
428 | | - struct drm_framebuffer *fb; |
---|
429 | | - |
---|
430 | | - |
---|
431 | | - stdu = vmw_crtc_to_stdu(crtc); |
---|
432 | | - dev_priv = vmw_priv(crtc->dev); |
---|
433 | | - fb = plane_state->fb; |
---|
434 | | - |
---|
435 | | - vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL; |
---|
436 | | - |
---|
437 | | - if (vfb) |
---|
438 | | - vmw_kms_add_active(dev_priv, &stdu->base, vfb); |
---|
439 | | - else |
---|
440 | | - vmw_kms_del_active(dev_priv, &stdu->base); |
---|
441 | 413 | } |
---|
442 | 414 | |
---|
443 | 415 | static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, |
---|
.. | .. |
---|
470 | 442 | stdu->content_fb_type = SAME_AS_DISPLAY; |
---|
471 | 443 | } |
---|
472 | 444 | } |
---|
473 | | - |
---|
474 | | -/** |
---|
475 | | - * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target |
---|
476 | | - * |
---|
477 | | - * @crtc: CRTC to attach FB to |
---|
478 | | - * @fb: FB to attach |
---|
479 | | - * @event: Event to be posted. This event should've been alloced |
---|
480 | | - * using k[mz]alloc, and should've been completely initialized. |
---|
481 | | - * @page_flip_flags: Input flags. |
---|
482 | | - * |
---|
483 | | - * If the STDU uses the same display and content buffers, i.e. a true flip, |
---|
484 | | - * this function will replace the existing display buffer with the new content |
---|
485 | | - * buffer. |
---|
486 | | - * |
---|
487 | | - * If the STDU uses different display and content buffers, i.e. a blit, then |
---|
488 | | - * only the content buffer will be updated. |
---|
489 | | - * |
---|
490 | | - * RETURNS: |
---|
491 | | - * 0 on success, error code on failure |
---|
492 | | - */ |
---|
493 | | -static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, |
---|
494 | | - struct drm_framebuffer *new_fb, |
---|
495 | | - struct drm_pending_vblank_event *event, |
---|
496 | | - uint32_t flags, |
---|
497 | | - struct drm_modeset_acquire_ctx *ctx) |
---|
498 | | - |
---|
499 | | -{ |
---|
500 | | - struct vmw_private *dev_priv = vmw_priv(crtc->dev); |
---|
501 | | - struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc); |
---|
502 | | - int ret; |
---|
503 | | - |
---|
504 | | - if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc)) |
---|
505 | | - return -EINVAL; |
---|
506 | | - |
---|
507 | | - ret = drm_atomic_helper_page_flip(crtc, new_fb, event, flags, ctx); |
---|
508 | | - if (ret) { |
---|
509 | | - DRM_ERROR("Page flip error %d.\n", ret); |
---|
510 | | - return ret; |
---|
511 | | - } |
---|
512 | | - |
---|
513 | | - return 0; |
---|
514 | | -} |
---|
515 | | - |
---|
516 | 445 | |
---|
517 | 446 | /** |
---|
518 | 447 | * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect |
---|
.. | .. |
---|
595 | 524 | |
---|
596 | 525 | vmw_fifo_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); |
---|
597 | 526 | |
---|
| 527 | + stdu->display_srf->res.res_dirty = true; |
---|
598 | 528 | ddirty->left = ddirty->top = S32_MAX; |
---|
599 | 529 | ddirty->right = ddirty->bottom = S32_MIN; |
---|
600 | 530 | } |
---|
.. | .. |
---|
660 | 590 | return; |
---|
661 | 591 | |
---|
662 | 592 | /* Assume we are blitting from Guest (bo) to Host (display_srf) */ |
---|
663 | | - dst_pitch = stdu->display_srf->base_size.width * stdu->cpp; |
---|
| 593 | + dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; |
---|
664 | 594 | dst_bo = &stdu->display_srf->res.backup->base; |
---|
665 | 595 | dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; |
---|
666 | 596 | |
---|
.. | .. |
---|
691 | 621 | region.x2 = diff.rect.x2; |
---|
692 | 622 | region.y1 = diff.rect.y1; |
---|
693 | 623 | region.y2 = diff.rect.y2; |
---|
694 | | - ret = vmw_kms_update_proxy( |
---|
695 | | - (struct vmw_resource *) &stdu->display_srf->res, |
---|
696 | | - (const struct drm_clip_rect *) ®ion, 1, 1); |
---|
| 624 | + ret = vmw_kms_update_proxy(&stdu->display_srf->res, ®ion, |
---|
| 625 | + 1, 1); |
---|
697 | 626 | if (ret) |
---|
698 | 627 | goto out_cleanup; |
---|
699 | 628 | |
---|
700 | 629 | |
---|
701 | 630 | dev_priv = vmw_priv(stdu->base.crtc.dev); |
---|
702 | | - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
---|
703 | | - |
---|
704 | | - if (!cmd) { |
---|
705 | | - DRM_ERROR("Cannot reserve FIFO space to update STDU"); |
---|
| 631 | + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); |
---|
| 632 | + if (!cmd) |
---|
706 | 633 | goto out_cleanup; |
---|
707 | | - } |
---|
708 | 634 | |
---|
709 | 635 | vmw_stdu_populate_update(cmd, stdu->base.unit, |
---|
710 | 636 | region.x1, region.x2, |
---|
.. | .. |
---|
759 | 685 | struct vmw_stdu_dirty ddirty; |
---|
760 | 686 | int ret; |
---|
761 | 687 | bool cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D); |
---|
| 688 | + DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
---|
762 | 689 | |
---|
763 | 690 | /* |
---|
764 | 691 | * VMs without 3D support don't have the surface DMA command and |
---|
765 | 692 | * we'll be using a CPU blit, and the framebuffer should be moved out |
---|
766 | 693 | * of VRAM. |
---|
767 | 694 | */ |
---|
768 | | - ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible, |
---|
769 | | - false, cpu_blit); |
---|
| 695 | + ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit); |
---|
770 | 696 | if (ret) |
---|
771 | 697 | return ret; |
---|
| 698 | + |
---|
| 699 | + ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); |
---|
| 700 | + if (ret) |
---|
| 701 | + goto out_unref; |
---|
772 | 702 | |
---|
773 | 703 | ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : |
---|
774 | 704 | SVGA3D_READ_HOST_VRAM; |
---|
.. | .. |
---|
796 | 726 | |
---|
797 | 727 | ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips, |
---|
798 | 728 | 0, 0, num_clips, increment, &ddirty.base); |
---|
799 | | - vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL, |
---|
800 | | - user_fence_rep); |
---|
801 | 729 | |
---|
| 730 | + vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL, |
---|
| 731 | + user_fence_rep); |
---|
| 732 | + return ret; |
---|
| 733 | + |
---|
| 734 | +out_unref: |
---|
| 735 | + vmw_validation_unref_lists(&val_ctx); |
---|
802 | 736 | return ret; |
---|
803 | 737 | } |
---|
804 | 738 | |
---|
.. | .. |
---|
874 | 808 | cmd->body.dest.sid = stdu->display_srf->res.id; |
---|
875 | 809 | update = (struct vmw_stdu_update *) &blit[dirty->num_hits]; |
---|
876 | 810 | commit_size = sizeof(*cmd) + blit_size + sizeof(*update); |
---|
| 811 | + stdu->display_srf->res.res_dirty = true; |
---|
877 | 812 | } else { |
---|
878 | 813 | update = dirty->cmd; |
---|
879 | 814 | commit_size = sizeof(*update); |
---|
.. | .. |
---|
924 | 859 | struct vmw_framebuffer_surface *vfbs = |
---|
925 | 860 | container_of(framebuffer, typeof(*vfbs), base); |
---|
926 | 861 | struct vmw_stdu_dirty sdirty; |
---|
927 | | - struct vmw_validation_ctx ctx; |
---|
| 862 | + DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
---|
928 | 863 | int ret; |
---|
929 | 864 | |
---|
930 | 865 | if (!srf) |
---|
931 | 866 | srf = &vfbs->surface->res; |
---|
932 | 867 | |
---|
933 | | - ret = vmw_kms_helper_resource_prepare(srf, true, &ctx); |
---|
| 868 | + ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE, |
---|
| 869 | + NULL, NULL); |
---|
934 | 870 | if (ret) |
---|
935 | 871 | return ret; |
---|
| 872 | + |
---|
| 873 | + ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true); |
---|
| 874 | + if (ret) |
---|
| 875 | + goto out_unref; |
---|
936 | 876 | |
---|
937 | 877 | if (vfbs->is_bo_proxy) { |
---|
938 | 878 | ret = vmw_kms_update_proxy(srf, clips, num_clips, inc); |
---|
.. | .. |
---|
954 | 894 | dest_x, dest_y, num_clips, inc, |
---|
955 | 895 | &sdirty.base); |
---|
956 | 896 | out_finish: |
---|
957 | | - vmw_kms_helper_resource_finish(&ctx, out_fence); |
---|
| 897 | + vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence, |
---|
| 898 | + NULL); |
---|
958 | 899 | |
---|
| 900 | + return ret; |
---|
| 901 | + |
---|
| 902 | +out_unref: |
---|
| 903 | + vmw_validation_unref_lists(&val_ctx); |
---|
959 | 904 | return ret; |
---|
960 | 905 | } |
---|
961 | 906 | |
---|
.. | .. |
---|
969 | 914 | .reset = vmw_du_crtc_reset, |
---|
970 | 915 | .atomic_duplicate_state = vmw_du_crtc_duplicate_state, |
---|
971 | 916 | .atomic_destroy_state = vmw_du_crtc_destroy_state, |
---|
972 | | - .set_config = vmw_kms_set_config, |
---|
973 | | - .page_flip = vmw_stdu_crtc_page_flip, |
---|
| 917 | + .set_config = drm_atomic_helper_set_config, |
---|
| 918 | + .page_flip = drm_atomic_helper_page_flip, |
---|
| 919 | + .get_vblank_counter = vmw_get_vblank_counter, |
---|
| 920 | + .enable_vblank = vmw_enable_vblank, |
---|
| 921 | + .disable_vblank = vmw_disable_vblank, |
---|
974 | 922 | }; |
---|
975 | 923 | |
---|
976 | 924 | |
---|
.. | .. |
---|
1025 | 973 | .dpms = vmw_du_connector_dpms, |
---|
1026 | 974 | .detect = vmw_du_connector_detect, |
---|
1027 | 975 | .fill_modes = vmw_du_connector_fill_modes, |
---|
1028 | | - .set_property = vmw_du_connector_set_property, |
---|
1029 | 976 | .destroy = vmw_stdu_connector_destroy, |
---|
1030 | 977 | .reset = vmw_du_connector_reset, |
---|
1031 | 978 | .atomic_duplicate_state = vmw_du_connector_duplicate_state, |
---|
1032 | 979 | .atomic_destroy_state = vmw_du_connector_destroy_state, |
---|
1033 | | - .atomic_set_property = vmw_du_connector_atomic_set_property, |
---|
1034 | | - .atomic_get_property = vmw_du_connector_atomic_get_property, |
---|
1035 | 980 | }; |
---|
1036 | 981 | |
---|
1037 | 982 | |
---|
1038 | 983 | static const struct |
---|
1039 | 984 | drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { |
---|
1040 | | - .best_encoder = drm_atomic_helper_best_encoder, |
---|
1041 | 985 | }; |
---|
1042 | 986 | |
---|
1043 | 987 | |
---|
.. | .. |
---|
1097 | 1041 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); |
---|
1098 | 1042 | enum stdu_content_type new_content_type; |
---|
1099 | 1043 | struct vmw_framebuffer_surface *new_vfbs; |
---|
1100 | | - struct drm_crtc *crtc = new_state->crtc; |
---|
1101 | 1044 | uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h; |
---|
1102 | 1045 | int ret; |
---|
1103 | 1046 | |
---|
.. | .. |
---|
1114 | 1057 | vfb = vmw_framebuffer_to_vfb(new_fb); |
---|
1115 | 1058 | new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb); |
---|
1116 | 1059 | |
---|
1117 | | - if (new_vfbs && new_vfbs->surface->base_size.width == hdisplay && |
---|
1118 | | - new_vfbs->surface->base_size.height == vdisplay) |
---|
| 1060 | + if (new_vfbs && |
---|
| 1061 | + new_vfbs->surface->metadata.base_size.width == hdisplay && |
---|
| 1062 | + new_vfbs->surface->metadata.base_size.height == vdisplay) |
---|
1119 | 1063 | new_content_type = SAME_AS_DISPLAY; |
---|
1120 | 1064 | else if (vfb->bo) |
---|
1121 | 1065 | new_content_type = SEPARATE_BO; |
---|
.. | .. |
---|
1123 | 1067 | new_content_type = SEPARATE_SURFACE; |
---|
1124 | 1068 | |
---|
1125 | 1069 | if (new_content_type != SAME_AS_DISPLAY) { |
---|
1126 | | - struct vmw_surface content_srf; |
---|
1127 | | - struct drm_vmw_size display_base_size = {0}; |
---|
1128 | | - |
---|
1129 | | - display_base_size.width = hdisplay; |
---|
1130 | | - display_base_size.height = vdisplay; |
---|
1131 | | - display_base_size.depth = 1; |
---|
| 1070 | + struct vmw_surface_metadata metadata = {0}; |
---|
1132 | 1071 | |
---|
1133 | 1072 | /* |
---|
1134 | 1073 | * If content buffer is a buffer object, then we have to |
---|
.. | .. |
---|
1138 | 1077 | |
---|
1139 | 1078 | switch (new_fb->format->cpp[0]*8) { |
---|
1140 | 1079 | case 32: |
---|
1141 | | - content_srf.format = SVGA3D_X8R8G8B8; |
---|
| 1080 | + metadata.format = SVGA3D_X8R8G8B8; |
---|
1142 | 1081 | break; |
---|
1143 | 1082 | |
---|
1144 | 1083 | case 16: |
---|
1145 | | - content_srf.format = SVGA3D_R5G6B5; |
---|
| 1084 | + metadata.format = SVGA3D_R5G6B5; |
---|
1146 | 1085 | break; |
---|
1147 | 1086 | |
---|
1148 | 1087 | case 8: |
---|
1149 | | - content_srf.format = SVGA3D_P8; |
---|
| 1088 | + metadata.format = SVGA3D_P8; |
---|
1150 | 1089 | break; |
---|
1151 | 1090 | |
---|
1152 | 1091 | default: |
---|
.. | .. |
---|
1154 | 1093 | return -EINVAL; |
---|
1155 | 1094 | } |
---|
1156 | 1095 | |
---|
1157 | | - content_srf.flags = 0; |
---|
1158 | | - content_srf.mip_levels[0] = 1; |
---|
1159 | | - content_srf.multisample_count = 0; |
---|
1160 | | - content_srf.multisample_pattern = |
---|
1161 | | - SVGA3D_MS_PATTERN_NONE; |
---|
1162 | | - content_srf.quality_level = SVGA3D_MS_QUALITY_NONE; |
---|
| 1096 | + metadata.mip_levels[0] = 1; |
---|
| 1097 | + metadata.num_sizes = 1; |
---|
| 1098 | + metadata.scanout = true; |
---|
1163 | 1099 | } else { |
---|
1164 | | - content_srf = *new_vfbs->surface; |
---|
| 1100 | + metadata = new_vfbs->surface->metadata; |
---|
1165 | 1101 | } |
---|
1166 | 1102 | |
---|
1167 | | - if (vps->surf) { |
---|
1168 | | - struct drm_vmw_size cur_base_size = vps->surf->base_size; |
---|
| 1103 | + metadata.base_size.width = hdisplay; |
---|
| 1104 | + metadata.base_size.height = vdisplay; |
---|
| 1105 | + metadata.base_size.depth = 1; |
---|
1169 | 1106 | |
---|
1170 | | - if (cur_base_size.width != display_base_size.width || |
---|
1171 | | - cur_base_size.height != display_base_size.height || |
---|
1172 | | - vps->surf->format != content_srf.format) { |
---|
| 1107 | + if (vps->surf) { |
---|
| 1108 | + struct drm_vmw_size cur_base_size = |
---|
| 1109 | + vps->surf->metadata.base_size; |
---|
| 1110 | + |
---|
| 1111 | + if (cur_base_size.width != metadata.base_size.width || |
---|
| 1112 | + cur_base_size.height != metadata.base_size.height || |
---|
| 1113 | + vps->surf->metadata.format != metadata.format) { |
---|
1173 | 1114 | WARN_ON(vps->pinned != 0); |
---|
1174 | 1115 | vmw_surface_unreference(&vps->surf); |
---|
1175 | 1116 | } |
---|
.. | .. |
---|
1177 | 1118 | } |
---|
1178 | 1119 | |
---|
1179 | 1120 | if (!vps->surf) { |
---|
1180 | | - ret = vmw_surface_gb_priv_define |
---|
1181 | | - (crtc->dev, |
---|
1182 | | - /* Kernel visible only */ |
---|
1183 | | - 0, |
---|
1184 | | - content_srf.flags, |
---|
1185 | | - content_srf.format, |
---|
1186 | | - true, /* a scanout buffer */ |
---|
1187 | | - content_srf.mip_levels[0], |
---|
1188 | | - content_srf.multisample_count, |
---|
1189 | | - 0, |
---|
1190 | | - display_base_size, |
---|
1191 | | - content_srf.multisample_pattern, |
---|
1192 | | - content_srf.quality_level, |
---|
1193 | | - &vps->surf); |
---|
| 1121 | + ret = vmw_gb_surface_define(dev_priv, 0, &metadata, |
---|
| 1122 | + &vps->surf); |
---|
1194 | 1123 | if (ret != 0) { |
---|
1195 | 1124 | DRM_ERROR("Couldn't allocate STDU surface.\n"); |
---|
1196 | 1125 | return ret; |
---|
.. | .. |
---|
1240 | 1169 | return ret; |
---|
1241 | 1170 | } |
---|
1242 | 1171 | |
---|
| 1172 | +static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update, |
---|
| 1173 | + uint32_t num_hits) |
---|
| 1174 | +{ |
---|
| 1175 | + return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits + |
---|
| 1176 | + sizeof(SVGA3dCmdSurfaceDMASuffix) + |
---|
| 1177 | + sizeof(struct vmw_stdu_update); |
---|
| 1178 | +} |
---|
1243 | 1179 | |
---|
| 1180 | +static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, |
---|
| 1181 | + uint32_t num_hits) |
---|
| 1182 | +{ |
---|
| 1183 | + return sizeof(struct vmw_stdu_update_gb_image) + |
---|
| 1184 | + sizeof(struct vmw_stdu_update); |
---|
| 1185 | +} |
---|
| 1186 | + |
---|
| 1187 | +static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update, |
---|
| 1188 | + void *cmd, uint32_t num_hits) |
---|
| 1189 | +{ |
---|
| 1190 | + struct vmw_screen_target_display_unit *stdu; |
---|
| 1191 | + struct vmw_framebuffer_bo *vfbbo; |
---|
| 1192 | + struct vmw_stdu_dma *cmd_dma = cmd; |
---|
| 1193 | + |
---|
| 1194 | + stdu = container_of(update->du, typeof(*stdu), base); |
---|
| 1195 | + vfbbo = container_of(update->vfb, typeof(*vfbbo), base); |
---|
| 1196 | + |
---|
| 1197 | + cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA; |
---|
| 1198 | + cmd_dma->header.size = sizeof(cmd_dma->body) + |
---|
| 1199 | + sizeof(struct SVGA3dCopyBox) * num_hits + |
---|
| 1200 | + sizeof(SVGA3dCmdSurfaceDMASuffix); |
---|
| 1201 | + vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr); |
---|
| 1202 | + cmd_dma->body.guest.pitch = update->vfb->base.pitches[0]; |
---|
| 1203 | + cmd_dma->body.host.sid = stdu->display_srf->res.id; |
---|
| 1204 | + cmd_dma->body.host.face = 0; |
---|
| 1205 | + cmd_dma->body.host.mipmap = 0; |
---|
| 1206 | + cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM; |
---|
| 1207 | + |
---|
| 1208 | + return sizeof(*cmd_dma); |
---|
| 1209 | +} |
---|
| 1210 | + |
---|
| 1211 | +static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update, |
---|
| 1212 | + void *cmd, struct drm_rect *clip, |
---|
| 1213 | + uint32_t fb_x, uint32_t fb_y) |
---|
| 1214 | +{ |
---|
| 1215 | + struct SVGA3dCopyBox *box = cmd; |
---|
| 1216 | + |
---|
| 1217 | + box->srcx = fb_x; |
---|
| 1218 | + box->srcy = fb_y; |
---|
| 1219 | + box->srcz = 0; |
---|
| 1220 | + box->x = clip->x1; |
---|
| 1221 | + box->y = clip->y1; |
---|
| 1222 | + box->z = 0; |
---|
| 1223 | + box->w = drm_rect_width(clip); |
---|
| 1224 | + box->h = drm_rect_height(clip); |
---|
| 1225 | + box->d = 1; |
---|
| 1226 | + |
---|
| 1227 | + return sizeof(*box); |
---|
| 1228 | +} |
---|
| 1229 | + |
---|
| 1230 | +static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update, |
---|
| 1231 | + void *cmd, struct drm_rect *bb) |
---|
| 1232 | +{ |
---|
| 1233 | + struct vmw_screen_target_display_unit *stdu; |
---|
| 1234 | + struct vmw_framebuffer_bo *vfbbo; |
---|
| 1235 | + SVGA3dCmdSurfaceDMASuffix *suffix = cmd; |
---|
| 1236 | + |
---|
| 1237 | + stdu = container_of(update->du, typeof(*stdu), base); |
---|
| 1238 | + vfbbo = container_of(update->vfb, typeof(*vfbbo), base); |
---|
| 1239 | + |
---|
| 1240 | + suffix->suffixSize = sizeof(*suffix); |
---|
| 1241 | + suffix->maximumOffset = vfbbo->buffer->base.num_pages * PAGE_SIZE; |
---|
| 1242 | + |
---|
| 1243 | + vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2, |
---|
| 1244 | + bb->y1, bb->y2); |
---|
| 1245 | + |
---|
| 1246 | + return sizeof(*suffix) + sizeof(struct vmw_stdu_update); |
---|
| 1247 | +} |
---|
| 1248 | + |
---|
| 1249 | +static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, |
---|
| 1250 | + void *cmd, uint32_t num_hits) |
---|
| 1251 | +{ |
---|
| 1252 | + struct vmw_du_update_plane_buffer *bo_update = |
---|
| 1253 | + container_of(update, typeof(*bo_update), base); |
---|
| 1254 | + |
---|
| 1255 | + bo_update->fb_left = INT_MAX; |
---|
| 1256 | + bo_update->fb_top = INT_MAX; |
---|
| 1257 | + |
---|
| 1258 | + return 0; |
---|
| 1259 | +} |
---|
| 1260 | + |
---|
| 1261 | +static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane *update, |
---|
| 1262 | + void *cmd, struct drm_rect *clip, |
---|
| 1263 | + uint32_t fb_x, uint32_t fb_y) |
---|
| 1264 | +{ |
---|
| 1265 | + struct vmw_du_update_plane_buffer *bo_update = |
---|
| 1266 | + container_of(update, typeof(*bo_update), base); |
---|
| 1267 | + |
---|
| 1268 | + bo_update->fb_left = min_t(int, bo_update->fb_left, fb_x); |
---|
| 1269 | + bo_update->fb_top = min_t(int, bo_update->fb_top, fb_y); |
---|
| 1270 | + |
---|
| 1271 | + return 0; |
---|
| 1272 | +} |
---|
| 1273 | + |
---|
| 1274 | +static uint32_t |
---|
| 1275 | +vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd, |
---|
| 1276 | + struct drm_rect *bb) |
---|
| 1277 | +{ |
---|
| 1278 | + struct vmw_du_update_plane_buffer *bo_update; |
---|
| 1279 | + struct vmw_screen_target_display_unit *stdu; |
---|
| 1280 | + struct vmw_framebuffer_bo *vfbbo; |
---|
| 1281 | + struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0); |
---|
| 1282 | + struct vmw_stdu_update_gb_image *cmd_img = cmd; |
---|
| 1283 | + struct vmw_stdu_update *cmd_update; |
---|
| 1284 | + struct ttm_buffer_object *src_bo, *dst_bo; |
---|
| 1285 | + u32 src_offset, dst_offset; |
---|
| 1286 | + s32 src_pitch, dst_pitch; |
---|
| 1287 | + s32 width, height; |
---|
| 1288 | + |
---|
| 1289 | + bo_update = container_of(update, typeof(*bo_update), base); |
---|
| 1290 | + stdu = container_of(update->du, typeof(*stdu), base); |
---|
| 1291 | + vfbbo = container_of(update->vfb, typeof(*vfbbo), base); |
---|
| 1292 | + |
---|
| 1293 | + width = bb->x2 - bb->x1; |
---|
| 1294 | + height = bb->y2 - bb->y1; |
---|
| 1295 | + |
---|
| 1296 | + diff.cpp = stdu->cpp; |
---|
| 1297 | + |
---|
| 1298 | + dst_bo = &stdu->display_srf->res.backup->base; |
---|
| 1299 | + dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; |
---|
| 1300 | + dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp; |
---|
| 1301 | + |
---|
| 1302 | + src_bo = &vfbbo->buffer->base; |
---|
| 1303 | + src_pitch = update->vfb->base.pitches[0]; |
---|
| 1304 | + src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * |
---|
| 1305 | + stdu->cpp; |
---|
| 1306 | + |
---|
| 1307 | + (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo, |
---|
| 1308 | + src_offset, src_pitch, width * stdu->cpp, height, |
---|
| 1309 | + &diff); |
---|
| 1310 | + |
---|
| 1311 | + if (drm_rect_visible(&diff.rect)) { |
---|
| 1312 | + SVGA3dBox *box = &cmd_img->body.box; |
---|
| 1313 | + |
---|
| 1314 | + cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; |
---|
| 1315 | + cmd_img->header.size = sizeof(cmd_img->body); |
---|
| 1316 | + cmd_img->body.image.sid = stdu->display_srf->res.id; |
---|
| 1317 | + cmd_img->body.image.face = 0; |
---|
| 1318 | + cmd_img->body.image.mipmap = 0; |
---|
| 1319 | + |
---|
| 1320 | + box->x = diff.rect.x1; |
---|
| 1321 | + box->y = diff.rect.y1; |
---|
| 1322 | + box->z = 0; |
---|
| 1323 | + box->w = drm_rect_width(&diff.rect); |
---|
| 1324 | + box->h = drm_rect_height(&diff.rect); |
---|
| 1325 | + box->d = 1; |
---|
| 1326 | + |
---|
| 1327 | + cmd_update = (struct vmw_stdu_update *)&cmd_img[1]; |
---|
| 1328 | + vmw_stdu_populate_update(cmd_update, stdu->base.unit, |
---|
| 1329 | + diff.rect.x1, diff.rect.x2, |
---|
| 1330 | + diff.rect.y1, diff.rect.y2); |
---|
| 1331 | + |
---|
| 1332 | + return sizeof(*cmd_img) + sizeof(*cmd_update); |
---|
| 1333 | + } |
---|
| 1334 | + |
---|
| 1335 | + return 0; |
---|
| 1336 | +} |
---|
| 1337 | + |
---|
| 1338 | +/** |
---|
| 1339 | + * vmw_stdu_plane_update_bo - Update display unit for bo backed fb. |
---|
| 1340 | + * @dev_priv: device private. |
---|
| 1341 | + * @plane: plane state. |
---|
| 1342 | + * @old_state: old plane state. |
---|
| 1343 | + * @vfb: framebuffer which is blitted to display unit. |
---|
| 1344 | + * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. |
---|
| 1345 | + * The returned fence pointer may be NULL in which case the device |
---|
| 1346 | + * has already synchronized. |
---|
| 1347 | + * |
---|
| 1348 | + * Return: 0 on success or a negative error code on failure. |
---|
| 1349 | + */ |
---|
| 1350 | +static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, |
---|
| 1351 | + struct drm_plane *plane, |
---|
| 1352 | + struct drm_plane_state *old_state, |
---|
| 1353 | + struct vmw_framebuffer *vfb, |
---|
| 1354 | + struct vmw_fence_obj **out_fence) |
---|
| 1355 | +{ |
---|
| 1356 | + struct vmw_du_update_plane_buffer bo_update; |
---|
| 1357 | + |
---|
| 1358 | + memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer)); |
---|
| 1359 | + bo_update.base.plane = plane; |
---|
| 1360 | + bo_update.base.old_state = old_state; |
---|
| 1361 | + bo_update.base.dev_priv = dev_priv; |
---|
| 1362 | + bo_update.base.du = vmw_crtc_to_du(plane->state->crtc); |
---|
| 1363 | + bo_update.base.vfb = vfb; |
---|
| 1364 | + bo_update.base.out_fence = out_fence; |
---|
| 1365 | + bo_update.base.mutex = NULL; |
---|
| 1366 | + bo_update.base.cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D); |
---|
| 1367 | + bo_update.base.intr = false; |
---|
| 1368 | + |
---|
| 1369 | + /* |
---|
| 1370 | + * VM without 3D support don't have surface DMA command and framebuffer |
---|
| 1371 | + * should be moved out of VRAM. |
---|
| 1372 | + */ |
---|
| 1373 | + if (bo_update.base.cpu_blit) { |
---|
| 1374 | + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; |
---|
| 1375 | + bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; |
---|
| 1376 | + bo_update.base.clip = vmw_stdu_bo_clip_cpu; |
---|
| 1377 | + bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; |
---|
| 1378 | + } else { |
---|
| 1379 | + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size; |
---|
| 1380 | + bo_update.base.pre_clip = vmw_stdu_bo_populate_dma; |
---|
| 1381 | + bo_update.base.clip = vmw_stdu_bo_populate_clip; |
---|
| 1382 | + bo_update.base.post_clip = vmw_stdu_bo_populate_update; |
---|
| 1383 | + } |
---|
| 1384 | + |
---|
| 1385 | + return vmw_du_helper_plane_update(&bo_update.base); |
---|
| 1386 | +} |
---|
| 1387 | + |
---|
| 1388 | +static uint32_t |
---|
| 1389 | +vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update, |
---|
| 1390 | + uint32_t num_hits) |
---|
| 1391 | +{ |
---|
| 1392 | + struct vmw_framebuffer_surface *vfbs; |
---|
| 1393 | + uint32_t size = 0; |
---|
| 1394 | + |
---|
| 1395 | + vfbs = container_of(update->vfb, typeof(*vfbs), base); |
---|
| 1396 | + |
---|
| 1397 | + if (vfbs->is_bo_proxy) |
---|
| 1398 | + size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; |
---|
| 1399 | + |
---|
| 1400 | + size += sizeof(struct vmw_stdu_update); |
---|
| 1401 | + |
---|
| 1402 | + return size; |
---|
| 1403 | +} |
---|
| 1404 | + |
---|
| 1405 | +static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update, |
---|
| 1406 | + uint32_t num_hits) |
---|
| 1407 | +{ |
---|
| 1408 | + struct vmw_framebuffer_surface *vfbs; |
---|
| 1409 | + uint32_t size = 0; |
---|
| 1410 | + |
---|
| 1411 | + vfbs = container_of(update->vfb, typeof(*vfbs), base); |
---|
| 1412 | + |
---|
| 1413 | + if (vfbs->is_bo_proxy) |
---|
| 1414 | + size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; |
---|
| 1415 | + |
---|
| 1416 | + size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) * |
---|
| 1417 | + num_hits + sizeof(struct vmw_stdu_update); |
---|
| 1418 | + |
---|
| 1419 | + return size; |
---|
| 1420 | +} |
---|
| 1421 | + |
---|
| 1422 | +static uint32_t |
---|
| 1423 | +vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd) |
---|
| 1424 | +{ |
---|
| 1425 | + struct vmw_framebuffer_surface *vfbs; |
---|
| 1426 | + struct drm_plane_state *state = update->plane->state; |
---|
| 1427 | + struct drm_plane_state *old_state = update->old_state; |
---|
| 1428 | + struct vmw_stdu_update_gb_image *cmd_update = cmd; |
---|
| 1429 | + struct drm_atomic_helper_damage_iter iter; |
---|
| 1430 | + struct drm_rect clip; |
---|
| 1431 | + uint32_t copy_size = 0; |
---|
| 1432 | + |
---|
| 1433 | + vfbs = container_of(update->vfb, typeof(*vfbs), base); |
---|
| 1434 | + |
---|
| 1435 | + /* |
---|
| 1436 | + * proxy surface is special where a buffer object type fb is wrapped |
---|
| 1437 | + * in a surface and need an update gb image command to sync with device. |
---|
| 1438 | + */ |
---|
| 1439 | + drm_atomic_helper_damage_iter_init(&iter, old_state, state); |
---|
| 1440 | + drm_atomic_for_each_plane_damage(&iter, &clip) { |
---|
| 1441 | + SVGA3dBox *box = &cmd_update->body.box; |
---|
| 1442 | + |
---|
| 1443 | + cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; |
---|
| 1444 | + cmd_update->header.size = sizeof(cmd_update->body); |
---|
| 1445 | + cmd_update->body.image.sid = vfbs->surface->res.id; |
---|
| 1446 | + cmd_update->body.image.face = 0; |
---|
| 1447 | + cmd_update->body.image.mipmap = 0; |
---|
| 1448 | + |
---|
| 1449 | + box->x = clip.x1; |
---|
| 1450 | + box->y = clip.y1; |
---|
| 1451 | + box->z = 0; |
---|
| 1452 | + box->w = drm_rect_width(&clip); |
---|
| 1453 | + box->h = drm_rect_height(&clip); |
---|
| 1454 | + box->d = 1; |
---|
| 1455 | + |
---|
| 1456 | + copy_size += sizeof(*cmd_update); |
---|
| 1457 | + cmd_update++; |
---|
| 1458 | + } |
---|
| 1459 | + |
---|
| 1460 | + return copy_size; |
---|
| 1461 | +} |
---|
| 1462 | + |
---|
| 1463 | +static uint32_t |
---|
| 1464 | +vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd, |
---|
| 1465 | + uint32_t num_hits) |
---|
| 1466 | +{ |
---|
| 1467 | + struct vmw_screen_target_display_unit *stdu; |
---|
| 1468 | + struct vmw_framebuffer_surface *vfbs; |
---|
| 1469 | + struct vmw_stdu_surface_copy *cmd_copy = cmd; |
---|
| 1470 | + |
---|
| 1471 | + stdu = container_of(update->du, typeof(*stdu), base); |
---|
| 1472 | + vfbs = container_of(update->vfb, typeof(*vfbs), base); |
---|
| 1473 | + |
---|
| 1474 | + cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY; |
---|
| 1475 | + cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) * |
---|
| 1476 | + num_hits; |
---|
| 1477 | + cmd_copy->body.src.sid = vfbs->surface->res.id; |
---|
| 1478 | + cmd_copy->body.dest.sid = stdu->display_srf->res.id; |
---|
| 1479 | + |
---|
| 1480 | + return sizeof(*cmd_copy); |
---|
| 1481 | +} |
---|
| 1482 | + |
---|
| 1483 | +static uint32_t |
---|
| 1484 | +vmw_stdu_surface_populate_clip(struct vmw_du_update_plane *update, void *cmd, |
---|
| 1485 | + struct drm_rect *clip, uint32_t fb_x, |
---|
| 1486 | + uint32_t fb_y) |
---|
| 1487 | +{ |
---|
| 1488 | + struct SVGA3dCopyBox *box = cmd; |
---|
| 1489 | + |
---|
| 1490 | + box->srcx = fb_x; |
---|
| 1491 | + box->srcy = fb_y; |
---|
| 1492 | + box->srcz = 0; |
---|
| 1493 | + box->x = clip->x1; |
---|
| 1494 | + box->y = clip->y1; |
---|
| 1495 | + box->z = 0; |
---|
| 1496 | + box->w = drm_rect_width(clip); |
---|
| 1497 | + box->h = drm_rect_height(clip); |
---|
| 1498 | + box->d = 1; |
---|
| 1499 | + |
---|
| 1500 | + return sizeof(*box); |
---|
| 1501 | +} |
---|
| 1502 | + |
---|
| 1503 | +static uint32_t |
---|
| 1504 | +vmw_stdu_surface_populate_update(struct vmw_du_update_plane *update, void *cmd, |
---|
| 1505 | + struct drm_rect *bb) |
---|
| 1506 | +{ |
---|
| 1507 | + vmw_stdu_populate_update(cmd, update->du->unit, bb->x1, bb->x2, bb->y1, |
---|
| 1508 | + bb->y2); |
---|
| 1509 | + |
---|
| 1510 | + return sizeof(struct vmw_stdu_update); |
---|
| 1511 | +} |
---|
| 1512 | + |
---|
| 1513 | +/** |
---|
| 1514 | + * vmw_stdu_plane_update_surface - Update display unit for surface backed fb |
---|
| 1515 | + * @dev_priv: Device private |
---|
| 1516 | + * @plane: Plane state |
---|
| 1517 | + * @old_state: Old plane state |
---|
| 1518 | + * @vfb: Framebuffer which is blitted to display unit |
---|
| 1519 | + * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. |
---|
| 1520 | + * The returned fence pointer may be NULL in which case the device |
---|
| 1521 | + * has already synchronized. |
---|
| 1522 | + * |
---|
| 1523 | + * Return: 0 on success or a negative error code on failure. |
---|
| 1524 | + */ |
---|
| 1525 | +static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, |
---|
| 1526 | + struct drm_plane *plane, |
---|
| 1527 | + struct drm_plane_state *old_state, |
---|
| 1528 | + struct vmw_framebuffer *vfb, |
---|
| 1529 | + struct vmw_fence_obj **out_fence) |
---|
| 1530 | +{ |
---|
| 1531 | + struct vmw_du_update_plane srf_update; |
---|
| 1532 | + struct vmw_screen_target_display_unit *stdu; |
---|
| 1533 | + struct vmw_framebuffer_surface *vfbs; |
---|
| 1534 | + |
---|
| 1535 | + stdu = vmw_crtc_to_stdu(plane->state->crtc); |
---|
| 1536 | + vfbs = container_of(vfb, typeof(*vfbs), base); |
---|
| 1537 | + |
---|
| 1538 | + memset(&srf_update, 0, sizeof(struct vmw_du_update_plane)); |
---|
| 1539 | + srf_update.plane = plane; |
---|
| 1540 | + srf_update.old_state = old_state; |
---|
| 1541 | + srf_update.dev_priv = dev_priv; |
---|
| 1542 | + srf_update.du = vmw_crtc_to_du(plane->state->crtc); |
---|
| 1543 | + srf_update.vfb = vfb; |
---|
| 1544 | + srf_update.out_fence = out_fence; |
---|
| 1545 | + srf_update.mutex = &dev_priv->cmdbuf_mutex; |
---|
| 1546 | + srf_update.cpu_blit = false; |
---|
| 1547 | + srf_update.intr = true; |
---|
| 1548 | + |
---|
| 1549 | + if (vfbs->is_bo_proxy) |
---|
| 1550 | + srf_update.post_prepare = vmw_stdu_surface_update_proxy; |
---|
| 1551 | + |
---|
| 1552 | + if (vfbs->surface->res.id != stdu->display_srf->res.id) { |
---|
| 1553 | + srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size; |
---|
| 1554 | + srf_update.pre_clip = vmw_stdu_surface_populate_copy; |
---|
| 1555 | + srf_update.clip = vmw_stdu_surface_populate_clip; |
---|
| 1556 | + } else { |
---|
| 1557 | + srf_update.calc_fifo_size = |
---|
| 1558 | + vmw_stdu_surface_fifo_size_same_display; |
---|
| 1559 | + } |
---|
| 1560 | + |
---|
| 1561 | + srf_update.post_clip = vmw_stdu_surface_populate_update; |
---|
| 1562 | + |
---|
| 1563 | + return vmw_du_helper_plane_update(&srf_update); |
---|
| 1564 | +} |
---|
1244 | 1565 | |
---|
1245 | 1566 | /** |
---|
1246 | 1567 | * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane |
---|
1247 | | - * |
---|
1248 | 1568 | * @plane: display plane |
---|
1249 | 1569 | * @old_state: Only used to get crtc info |
---|
1250 | 1570 | * |
---|
.. | .. |
---|
1261 | 1581 | struct drm_crtc *crtc = plane->state->crtc; |
---|
1262 | 1582 | struct vmw_screen_target_display_unit *stdu; |
---|
1263 | 1583 | struct drm_pending_vblank_event *event; |
---|
| 1584 | + struct vmw_fence_obj *fence = NULL; |
---|
1264 | 1585 | struct vmw_private *dev_priv; |
---|
1265 | 1586 | int ret; |
---|
1266 | 1587 | |
---|
1267 | | - /* |
---|
1268 | | - * We cannot really fail this function, so if we do, then output an |
---|
1269 | | - * error and maintain consistent atomic state. |
---|
1270 | | - */ |
---|
| 1588 | + /* If case of device error, maintain consistent atomic state */ |
---|
1271 | 1589 | if (crtc && plane->state->fb) { |
---|
1272 | 1590 | struct vmw_framebuffer *vfb = |
---|
1273 | 1591 | vmw_framebuffer_to_vfb(plane->state->fb); |
---|
1274 | | - struct drm_vmw_rect vclips; |
---|
1275 | 1592 | stdu = vmw_crtc_to_stdu(crtc); |
---|
1276 | 1593 | dev_priv = vmw_priv(crtc->dev); |
---|
1277 | 1594 | |
---|
.. | .. |
---|
1279 | 1596 | stdu->content_fb_type = vps->content_fb_type; |
---|
1280 | 1597 | stdu->cpp = vps->cpp; |
---|
1281 | 1598 | |
---|
1282 | | - vclips.x = crtc->x; |
---|
1283 | | - vclips.y = crtc->y; |
---|
1284 | | - vclips.w = crtc->mode.hdisplay; |
---|
1285 | | - vclips.h = crtc->mode.vdisplay; |
---|
1286 | | - |
---|
1287 | 1599 | ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); |
---|
1288 | 1600 | if (ret) |
---|
1289 | 1601 | DRM_ERROR("Failed to bind surface to STDU.\n"); |
---|
1290 | 1602 | |
---|
1291 | 1603 | if (vfb->bo) |
---|
1292 | | - ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, |
---|
1293 | | - &vclips, 1, 1, true, false, |
---|
1294 | | - crtc); |
---|
| 1604 | + ret = vmw_stdu_plane_update_bo(dev_priv, plane, |
---|
| 1605 | + old_state, vfb, &fence); |
---|
1295 | 1606 | else |
---|
1296 | | - ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, |
---|
1297 | | - &vclips, NULL, 0, 0, |
---|
1298 | | - 1, 1, NULL, crtc); |
---|
| 1607 | + ret = vmw_stdu_plane_update_surface(dev_priv, plane, |
---|
| 1608 | + old_state, vfb, |
---|
| 1609 | + &fence); |
---|
1299 | 1610 | if (ret) |
---|
1300 | 1611 | DRM_ERROR("Failed to update STDU.\n"); |
---|
1301 | 1612 | } else { |
---|
.. | .. |
---|
1303 | 1614 | stdu = vmw_crtc_to_stdu(crtc); |
---|
1304 | 1615 | dev_priv = vmw_priv(crtc->dev); |
---|
1305 | 1616 | |
---|
1306 | | - /* |
---|
1307 | | - * When disabling a plane, CRTC and FB should always be NULL |
---|
1308 | | - * together, otherwise it's an error. |
---|
1309 | | - * Here primary plane is being disable so blank the screen |
---|
1310 | | - * target display unit, if not already done. |
---|
1311 | | - */ |
---|
| 1617 | + /* Blank STDU when fb and crtc are NULL */ |
---|
1312 | 1618 | if (!stdu->defined) |
---|
1313 | 1619 | return; |
---|
1314 | 1620 | |
---|
.. | .. |
---|
1323 | 1629 | return; |
---|
1324 | 1630 | } |
---|
1325 | 1631 | |
---|
| 1632 | + /* In case of error, vblank event is send in vmw_du_crtc_atomic_flush */ |
---|
1326 | 1633 | event = crtc->state->event; |
---|
1327 | | - /* |
---|
1328 | | - * In case of failure and other cases, vblank event will be sent in |
---|
1329 | | - * vmw_du_crtc_atomic_flush. |
---|
1330 | | - */ |
---|
1331 | | - if (event && (ret == 0)) { |
---|
1332 | | - struct vmw_fence_obj *fence = NULL; |
---|
| 1634 | + if (event && fence) { |
---|
1333 | 1635 | struct drm_file *file_priv = event->base.file_priv; |
---|
1334 | 1636 | |
---|
1335 | | - vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); |
---|
1336 | | - |
---|
1337 | | - /* |
---|
1338 | | - * If fence is NULL, then already sync. |
---|
1339 | | - */ |
---|
1340 | | - if (fence) { |
---|
1341 | | - ret = vmw_event_fence_action_queue( |
---|
1342 | | - file_priv, fence, &event->base, |
---|
1343 | | - &event->event.vbl.tv_sec, |
---|
1344 | | - &event->event.vbl.tv_usec, |
---|
1345 | | - true); |
---|
1346 | | - if (ret) |
---|
1347 | | - DRM_ERROR("Failed to queue event on fence.\n"); |
---|
1348 | | - else |
---|
1349 | | - crtc->state->event = NULL; |
---|
1350 | | - |
---|
1351 | | - vmw_fence_obj_unreference(&fence); |
---|
1352 | | - } |
---|
1353 | | - } else { |
---|
1354 | | - (void) vmw_fifo_flush(dev_priv, false); |
---|
| 1637 | + ret = vmw_event_fence_action_queue(file_priv, |
---|
| 1638 | + fence, |
---|
| 1639 | + &event->base, |
---|
| 1640 | + &event->event.vbl.tv_sec, |
---|
| 1641 | + &event->event.vbl.tv_usec, |
---|
| 1642 | + true); |
---|
| 1643 | + if (ret) |
---|
| 1644 | + DRM_ERROR("Failed to queue event on fence.\n"); |
---|
| 1645 | + else |
---|
| 1646 | + crtc->state->event = NULL; |
---|
1355 | 1647 | } |
---|
| 1648 | + |
---|
| 1649 | + if (fence) |
---|
| 1650 | + vmw_fence_obj_unreference(&fence); |
---|
1356 | 1651 | } |
---|
1357 | 1652 | |
---|
1358 | 1653 | |
---|
.. | .. |
---|
1440 | 1735 | stdu->base.pref_active = (unit == 0); |
---|
1441 | 1736 | stdu->base.pref_width = dev_priv->initial_width; |
---|
1442 | 1737 | stdu->base.pref_height = dev_priv->initial_height; |
---|
1443 | | - |
---|
1444 | | - /* |
---|
1445 | | - * Remove this after enabling atomic because property values can |
---|
1446 | | - * only exist in a state object |
---|
1447 | | - */ |
---|
1448 | 1738 | stdu->base.is_implicit = false; |
---|
1449 | 1739 | |
---|
1450 | 1740 | /* Initialize primary plane */ |
---|
1451 | | - vmw_du_plane_reset(primary); |
---|
1452 | | - |
---|
1453 | 1741 | ret = drm_universal_plane_init(dev, primary, |
---|
1454 | 1742 | 0, &vmw_stdu_plane_funcs, |
---|
1455 | 1743 | vmw_primary_plane_formats, |
---|
.. | .. |
---|
1461 | 1749 | } |
---|
1462 | 1750 | |
---|
1463 | 1751 | drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs); |
---|
| 1752 | + drm_plane_enable_fb_damage_clips(primary); |
---|
1464 | 1753 | |
---|
1465 | 1754 | /* Initialize cursor plane */ |
---|
1466 | | - vmw_du_plane_reset(cursor); |
---|
1467 | | - |
---|
1468 | 1755 | ret = drm_universal_plane_init(dev, cursor, |
---|
1469 | 1756 | 0, &vmw_stdu_cursor_funcs, |
---|
1470 | 1757 | vmw_cursor_plane_formats, |
---|
.. | .. |
---|
1478 | 1765 | |
---|
1479 | 1766 | drm_plane_helper_add(cursor, &vmw_stdu_cursor_plane_helper_funcs); |
---|
1480 | 1767 | |
---|
1481 | | - vmw_du_connector_reset(connector); |
---|
1482 | | - |
---|
1483 | 1768 | ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs, |
---|
1484 | 1769 | DRM_MODE_CONNECTOR_VIRTUAL); |
---|
1485 | 1770 | if (ret) { |
---|
.. | .. |
---|
1489 | 1774 | |
---|
1490 | 1775 | drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs); |
---|
1491 | 1776 | connector->status = vmw_du_connector_detect(connector, false); |
---|
1492 | | - vmw_connector_state_to_vcs(connector->state)->is_implicit = false; |
---|
1493 | 1777 | |
---|
1494 | 1778 | ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs, |
---|
1495 | 1779 | DRM_MODE_ENCODER_VIRTUAL, NULL); |
---|
.. | .. |
---|
1508 | 1792 | goto err_free_encoder; |
---|
1509 | 1793 | } |
---|
1510 | 1794 | |
---|
1511 | | - vmw_du_crtc_reset(crtc); |
---|
1512 | 1795 | ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary, |
---|
1513 | 1796 | &stdu->base.cursor, |
---|
1514 | 1797 | &vmw_stdu_crtc_funcs, NULL); |
---|
.. | .. |
---|
1527 | 1810 | dev->mode_config.suggested_x_property, 0); |
---|
1528 | 1811 | drm_object_attach_property(&connector->base, |
---|
1529 | 1812 | dev->mode_config.suggested_y_property, 0); |
---|
1530 | | - if (dev_priv->implicit_placement_property) |
---|
1531 | | - drm_object_attach_property |
---|
1532 | | - (&connector->base, |
---|
1533 | | - dev_priv->implicit_placement_property, |
---|
1534 | | - stdu->base.is_implicit); |
---|
1535 | 1813 | return 0; |
---|
1536 | 1814 | |
---|
1537 | 1815 | err_free_unregister: |
---|
.. | .. |
---|
1588 | 1866 | |
---|
1589 | 1867 | |
---|
1590 | 1868 | /* Do nothing if Screen Target support is turned off */ |
---|
1591 | | - if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE) |
---|
| 1869 | + if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE || !dev_priv->has_mob) |
---|
1592 | 1870 | return -ENOSYS; |
---|
1593 | 1871 | |
---|
1594 | 1872 | if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) |
---|
.. | .. |
---|
1600 | 1878 | |
---|
1601 | 1879 | dev_priv->active_display_unit = vmw_du_screen_target; |
---|
1602 | 1880 | |
---|
1603 | | - vmw_kms_create_implicit_placement_property(dev_priv, false); |
---|
1604 | | - |
---|
1605 | 1881 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) { |
---|
1606 | 1882 | ret = vmw_stdu_init(dev_priv, i); |
---|
1607 | 1883 | |
---|
.. | .. |
---|
1611 | 1887 | } |
---|
1612 | 1888 | } |
---|
1613 | 1889 | |
---|
| 1890 | + drm_mode_config_reset(dev); |
---|
| 1891 | + |
---|
1614 | 1892 | DRM_INFO("Screen Target Display device initialized\n"); |
---|
1615 | 1893 | |
---|
1616 | 1894 | return 0; |
---|