0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) "drm_plane_helper: " fmt
0007
0008 #include <drm/drm_atomic_helper.h>
0009 #include <drm/drm_framebuffer.h>
0010 #include <drm/drm_plane_helper.h>
0011 #include <drm/drm_modes.h>
0012
0013 #include "test-drm_modeset_common.h"
0014
0015 static void set_src(struct drm_plane_state *plane_state,
0016 unsigned src_x, unsigned src_y,
0017 unsigned src_w, unsigned src_h)
0018 {
0019 plane_state->src_x = src_x;
0020 plane_state->src_y = src_y;
0021 plane_state->src_w = src_w;
0022 plane_state->src_h = src_h;
0023 }
0024
0025 static bool check_src_eq(struct drm_plane_state *plane_state,
0026 unsigned src_x, unsigned src_y,
0027 unsigned src_w, unsigned src_h)
0028 {
0029 if (plane_state->src.x1 < 0) {
0030 pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
0031 drm_rect_debug_print("src: ", &plane_state->src, true);
0032 return false;
0033 }
0034 if (plane_state->src.y1 < 0) {
0035 pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
0036 drm_rect_debug_print("src: ", &plane_state->src, true);
0037 return false;
0038 }
0039
0040 if (plane_state->src.x1 != src_x ||
0041 plane_state->src.y1 != src_y ||
0042 drm_rect_width(&plane_state->src) != src_w ||
0043 drm_rect_height(&plane_state->src) != src_h) {
0044 drm_rect_debug_print("src: ", &plane_state->src, true);
0045 return false;
0046 }
0047
0048 return true;
0049 }
0050
0051 static void set_crtc(struct drm_plane_state *plane_state,
0052 int crtc_x, int crtc_y,
0053 unsigned crtc_w, unsigned crtc_h)
0054 {
0055 plane_state->crtc_x = crtc_x;
0056 plane_state->crtc_y = crtc_y;
0057 plane_state->crtc_w = crtc_w;
0058 plane_state->crtc_h = crtc_h;
0059 }
0060
0061 static bool check_crtc_eq(struct drm_plane_state *plane_state,
0062 int crtc_x, int crtc_y,
0063 unsigned crtc_w, unsigned crtc_h)
0064 {
0065 if (plane_state->dst.x1 != crtc_x ||
0066 plane_state->dst.y1 != crtc_y ||
0067 drm_rect_width(&plane_state->dst) != crtc_w ||
0068 drm_rect_height(&plane_state->dst) != crtc_h) {
0069 drm_rect_debug_print("dst: ", &plane_state->dst, false);
0070
0071 return false;
0072 }
0073
0074 return true;
0075 }
0076
0077 int igt_check_plane_state(void *ignored)
0078 {
0079 int ret;
0080
0081 static const struct drm_crtc_state crtc_state = {
0082 .crtc = ZERO_SIZE_PTR,
0083 .enable = true,
0084 .active = true,
0085 .mode = {
0086 DRM_MODE("1024x768", 0, 65000, 1024, 1048,
0087 1184, 1344, 0, 768, 771, 777, 806, 0,
0088 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
0089 },
0090 };
0091 static struct drm_plane plane = {
0092 .dev = NULL
0093 };
0094 static struct drm_framebuffer fb = {
0095 .width = 2048,
0096 .height = 2048
0097 };
0098 static struct drm_plane_state plane_state = {
0099 .plane = &plane,
0100 .crtc = ZERO_SIZE_PTR,
0101 .fb = &fb,
0102 .rotation = DRM_MODE_ROTATE_0
0103 };
0104
0105
0106 set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
0107 set_crtc(&plane_state, 0, 0, fb.width, fb.height);
0108 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0109 DRM_PLANE_HELPER_NO_SCALING,
0110 DRM_PLANE_HELPER_NO_SCALING,
0111 false, false);
0112 FAIL(ret < 0, "Simple clipping check should pass\n");
0113 FAIL_ON(!plane_state.visible);
0114 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
0115 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
0116
0117
0118 plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
0119 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0120 DRM_PLANE_HELPER_NO_SCALING,
0121 DRM_PLANE_HELPER_NO_SCALING,
0122 false, false);
0123 FAIL(ret < 0, "Rotated clipping check should pass\n");
0124 FAIL_ON(!plane_state.visible);
0125 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
0126 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
0127 plane_state.rotation = DRM_MODE_ROTATE_0;
0128
0129
0130 set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
0131 set_crtc(&plane_state, 0, 0, 1023, 767);
0132 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0133 DRM_PLANE_HELPER_NO_SCALING,
0134 DRM_PLANE_HELPER_NO_SCALING,
0135 false, false);
0136 FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n");
0137
0138 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0139 DRM_PLANE_HELPER_NO_SCALING,
0140 DRM_PLANE_HELPER_NO_SCALING,
0141 true, false);
0142 FAIL(ret < 0, "Simple positioning should work\n");
0143 FAIL_ON(!plane_state.visible);
0144 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
0145 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767));
0146
0147
0148 set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
0149 set_crtc(&plane_state, 0, 0, 1024, 768);
0150 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0151 0x8001,
0152 DRM_PLANE_HELPER_NO_SCALING,
0153 false, false);
0154 FAIL(!ret, "Upscaling out of range should fail.\n");
0155 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0156 0x8000,
0157 DRM_PLANE_HELPER_NO_SCALING,
0158 false, false);
0159 FAIL(ret < 0, "Upscaling exactly 2x should work\n");
0160 FAIL_ON(!plane_state.visible);
0161 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
0162 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
0163
0164 set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
0165 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0166 DRM_PLANE_HELPER_NO_SCALING,
0167 0x1ffff, false, false);
0168 FAIL(!ret, "Downscaling out of range should fail.\n");
0169 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0170 DRM_PLANE_HELPER_NO_SCALING,
0171 0x20000, false, false);
0172 FAIL(ret < 0, "Should succeed with exact scaling limit\n");
0173 FAIL_ON(!plane_state.visible);
0174 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
0175 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
0176
0177
0178 set_src(&plane_state, 0, 0, 0x40001, 0x40001);
0179 set_crtc(&plane_state, 1022, 766, 4, 4);
0180 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0181 DRM_PLANE_HELPER_NO_SCALING,
0182 0x10001,
0183 true, false);
0184 FAIL(ret < 0, "Should succeed by clipping to exact multiple");
0185 FAIL_ON(!plane_state.visible);
0186 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
0187 FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
0188
0189 set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
0190 set_crtc(&plane_state, -2, -2, 1028, 772);
0191 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0192 DRM_PLANE_HELPER_NO_SCALING,
0193 0x10001,
0194 false, false);
0195 FAIL(ret < 0, "Should succeed by clipping to exact multiple");
0196 FAIL_ON(!plane_state.visible);
0197 FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16));
0198 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
0199
0200 set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
0201 set_crtc(&plane_state, 1022, 766, 4, 4);
0202 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0203 0xffff,
0204 DRM_PLANE_HELPER_NO_SCALING,
0205 true, false);
0206 FAIL(ret < 0, "Should succeed by clipping to exact multiple");
0207 FAIL_ON(!plane_state.visible);
0208
0209 FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
0210 FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
0211
0212 set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
0213 set_crtc(&plane_state, -2, -2, 1028, 772);
0214 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
0215 0xffff,
0216 DRM_PLANE_HELPER_NO_SCALING,
0217 false, false);
0218 FAIL(ret < 0, "Should succeed by clipping to exact multiple");
0219 FAIL_ON(!plane_state.visible);
0220 FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16));
0221 FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
0222
0223 return 0;
0224 }