diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 144 |
1 files changed, 35 insertions, 109 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index e17c26a1cff1..344228b640b9 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -935,21 +935,11 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
935 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 935 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
936 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | 936 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
937 | struct drm_framebuffer *fb = state->base.fb; | 937 | struct drm_framebuffer *fb = state->base.fb; |
938 | int crtc_x, crtc_y; | ||
939 | unsigned int crtc_w, crtc_h; | ||
940 | uint32_t src_x, src_y, src_w, src_h; | ||
941 | struct drm_rect *src = &state->base.src; | ||
942 | struct drm_rect *dst = &state->base.dst; | ||
943 | struct drm_rect clip = {}; | ||
944 | int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384; | 938 | int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384; |
945 | int hscale, vscale; | ||
946 | int max_scale, min_scale; | 939 | int max_scale, min_scale; |
947 | bool can_scale; | 940 | bool can_scale; |
948 | int ret; | 941 | int ret; |
949 | 942 | ||
950 | *src = drm_plane_state_src(&state->base); | ||
951 | *dst = drm_plane_state_dest(&state->base); | ||
952 | |||
953 | if (!fb) { | 943 | if (!fb) { |
954 | state->base.visible = false; | 944 | state->base.visible = false; |
955 | return 0; | 945 | return 0; |
@@ -985,64 +975,19 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
985 | min_scale = plane->can_scale ? 1 : (1 << 16); | 975 | min_scale = plane->can_scale ? 1 : (1 << 16); |
986 | } | 976 | } |
987 | 977 | ||
988 | /* | 978 | ret = drm_atomic_helper_check_plane_state(&state->base, |
989 | * FIXME the following code does a bunch of fuzzy adjustments to the | 979 | &crtc_state->base, |
990 | * coordinates and sizes. We probably need some way to decide whether | 980 | min_scale, max_scale, |
991 | * more strict checking should be done instead. | 981 | true, true); |
992 | */ | 982 | if (ret) |
993 | drm_rect_rotate(src, fb->width << 16, fb->height << 16, | 983 | return ret; |
994 | state->base.rotation); | ||
995 | |||
996 | hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale); | ||
997 | BUG_ON(hscale < 0); | ||
998 | |||
999 | vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale); | ||
1000 | BUG_ON(vscale < 0); | ||
1001 | |||
1002 | if (crtc_state->base.enable) | ||
1003 | drm_mode_get_hv_timing(&crtc_state->base.mode, | ||
1004 | &clip.x2, &clip.y2); | ||
1005 | |||
1006 | state->base.visible = drm_rect_clip_scaled(src, dst, &clip); | ||
1007 | |||
1008 | crtc_x = dst->x1; | ||
1009 | crtc_y = dst->y1; | ||
1010 | crtc_w = drm_rect_width(dst); | ||
1011 | crtc_h = drm_rect_height(dst); | ||
1012 | 984 | ||
1013 | if (state->base.visible) { | 985 | if (state->base.visible) { |
1014 | /* check again in case clipping clamped the results */ | 986 | struct drm_rect *src = &state->base.src; |
1015 | hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); | 987 | struct drm_rect *dst = &state->base.dst; |
1016 | if (hscale < 0) { | 988 | unsigned int crtc_w = drm_rect_width(dst); |
1017 | DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); | 989 | unsigned int crtc_h = drm_rect_height(dst); |
1018 | drm_rect_debug_print("src: ", src, true); | 990 | uint32_t src_x, src_y, src_w, src_h; |
1019 | drm_rect_debug_print("dst: ", dst, false); | ||
1020 | |||
1021 | return hscale; | ||
1022 | } | ||
1023 | |||
1024 | vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); | ||
1025 | if (vscale < 0) { | ||
1026 | DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); | ||
1027 | drm_rect_debug_print("src: ", src, true); | ||
1028 | drm_rect_debug_print("dst: ", dst, false); | ||
1029 | |||
1030 | return vscale; | ||
1031 | } | ||
1032 | |||
1033 | /* Make the source viewport size an exact multiple of the scaling factors. */ | ||
1034 | drm_rect_adjust_size(src, | ||
1035 | drm_rect_width(dst) * hscale - drm_rect_width(src), | ||
1036 | drm_rect_height(dst) * vscale - drm_rect_height(src)); | ||
1037 | |||
1038 | drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, | ||
1039 | state->base.rotation); | ||
1040 | |||
1041 | /* sanity check to make sure the src viewport wasn't enlarged */ | ||
1042 | WARN_ON(src->x1 < (int) state->base.src_x || | ||
1043 | src->y1 < (int) state->base.src_y || | ||
1044 | src->x2 > (int) state->base.src_x + state->base.src_w || | ||
1045 | src->y2 > (int) state->base.src_y + state->base.src_h); | ||
1046 | 991 | ||
1047 | /* | 992 | /* |
1048 | * Hardware doesn't handle subpixel coordinates. | 993 | * Hardware doesn't handle subpixel coordinates. |
@@ -1055,58 +1000,39 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
1055 | src_y = src->y1 >> 16; | 1000 | src_y = src->y1 >> 16; |
1056 | src_h = drm_rect_height(src) >> 16; | 1001 | src_h = drm_rect_height(src) >> 16; |
1057 | 1002 | ||
1058 | if (intel_format_is_yuv(fb->format->format)) { | 1003 | src->x1 = src_x << 16; |
1059 | src_x &= ~1; | 1004 | src->x2 = (src_x + src_w) << 16; |
1060 | src_w &= ~1; | 1005 | src->y1 = src_y << 16; |
1061 | 1006 | src->y2 = (src_y + src_h) << 16; | |
1062 | /* | ||
1063 | * Must keep src and dst the | ||
1064 | * same if we can't scale. | ||
1065 | */ | ||
1066 | if (!can_scale) | ||
1067 | crtc_w &= ~1; | ||
1068 | 1007 | ||
1069 | if (crtc_w == 0) | 1008 | if (intel_format_is_yuv(fb->format->format) && |
1070 | state->base.visible = false; | 1009 | (src_x % 2 || src_w % 2)) { |
1010 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", | ||
1011 | src_x, src_w); | ||
1012 | return -EINVAL; | ||
1071 | } | 1013 | } |
1072 | } | ||
1073 | 1014 | ||
1074 | /* Check size restrictions when scaling */ | 1015 | /* Check size restrictions when scaling */ |
1075 | if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) { | 1016 | if (src_w != crtc_w || src_h != crtc_h) { |
1076 | unsigned int width_bytes; | 1017 | unsigned int width_bytes; |
1077 | int cpp = fb->format->cpp[0]; | 1018 | int cpp = fb->format->cpp[0]; |
1078 | 1019 | ||
1079 | WARN_ON(!can_scale); | 1020 | WARN_ON(!can_scale); |
1080 | 1021 | ||
1081 | /* FIXME interlacing min height is 6 */ | 1022 | width_bytes = ((src_x * cpp) & 63) + src_w * cpp; |
1082 | 1023 | ||
1083 | if (crtc_w < 3 || crtc_h < 3) | 1024 | /* FIXME interlacing min height is 6 */ |
1084 | state->base.visible = false; | 1025 | if (INTEL_GEN(dev_priv) < 9 && ( |
1085 | 1026 | src_w < 3 || src_h < 3 || | |
1086 | if (src_w < 3 || src_h < 3) | 1027 | src_w > 2048 || src_h > 2048 || |
1087 | state->base.visible = false; | 1028 | crtc_w < 3 || crtc_h < 3 || |
1088 | 1029 | width_bytes > 4096 || fb->pitches[0] > 4096)) { | |
1089 | width_bytes = ((src_x * cpp) & 63) + src_w * cpp; | 1030 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); |
1090 | 1031 | return -EINVAL; | |
1091 | if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 || | 1032 | } |
1092 | width_bytes > 4096 || fb->pitches[0] > 4096)) { | ||
1093 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); | ||
1094 | return -EINVAL; | ||
1095 | } | 1033 | } |
1096 | } | 1034 | } |
1097 | 1035 | ||
1098 | if (state->base.visible) { | ||
1099 | src->x1 = src_x << 16; | ||
1100 | src->x2 = (src_x + src_w) << 16; | ||
1101 | src->y1 = src_y << 16; | ||
1102 | src->y2 = (src_y + src_h) << 16; | ||
1103 | } | ||
1104 | |||
1105 | dst->x1 = crtc_x; | ||
1106 | dst->x2 = crtc_x + crtc_w; | ||
1107 | dst->y1 = crtc_y; | ||
1108 | dst->y2 = crtc_y + crtc_h; | ||
1109 | |||
1110 | if (INTEL_GEN(dev_priv) >= 9) { | 1036 | if (INTEL_GEN(dev_priv) >= 9) { |
1111 | ret = skl_check_plane_surface(crtc_state, state); | 1037 | ret = skl_check_plane_surface(crtc_state, state); |
1112 | if (ret) | 1038 | if (ret) |