• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test cases for the drm_plane_helper functions
4  */
5 
6 #define pr_fmt(fmt) "drm_plane_helper: " fmt
7 
8 #include <drm/drm_atomic_helper.h>
9 #include <drm/drm_plane_helper.h>
10 #include <drm/drm_modes.h>
11 
12 #include "test-drm_modeset_common.h"
13 
set_src(struct drm_plane_state * plane_state,unsigned src_x,unsigned src_y,unsigned src_w,unsigned src_h)14 static void set_src(struct drm_plane_state *plane_state,
15 		    unsigned src_x, unsigned src_y,
16 		    unsigned src_w, unsigned src_h)
17 {
18 	plane_state->src_x = src_x;
19 	plane_state->src_y = src_y;
20 	plane_state->src_w = src_w;
21 	plane_state->src_h = src_h;
22 }
23 
check_src_eq(struct drm_plane_state * plane_state,unsigned src_x,unsigned src_y,unsigned src_w,unsigned src_h)24 static bool check_src_eq(struct drm_plane_state *plane_state,
25 			 unsigned src_x, unsigned src_y,
26 			 unsigned src_w, unsigned src_h)
27 {
28 	if (plane_state->src.x1 < 0) {
29 		pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
30 		drm_rect_debug_print("src: ", &plane_state->src, true);
31 		return false;
32 	}
33 	if (plane_state->src.y1 < 0) {
34 		pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
35 		drm_rect_debug_print("src: ", &plane_state->src, true);
36 		return false;
37 	}
38 
39 	if (plane_state->src.x1 != src_x ||
40 	    plane_state->src.y1 != src_y ||
41 	    drm_rect_width(&plane_state->src) != src_w ||
42 	    drm_rect_height(&plane_state->src) != src_h) {
43 		drm_rect_debug_print("src: ", &plane_state->src, true);
44 		return false;
45 	}
46 
47 	return true;
48 }
49 
set_crtc(struct drm_plane_state * plane_state,int crtc_x,int crtc_y,unsigned crtc_w,unsigned crtc_h)50 static void set_crtc(struct drm_plane_state *plane_state,
51 		     int crtc_x, int crtc_y,
52 		     unsigned crtc_w, unsigned crtc_h)
53 {
54 	plane_state->crtc_x = crtc_x;
55 	plane_state->crtc_y = crtc_y;
56 	plane_state->crtc_w = crtc_w;
57 	plane_state->crtc_h = crtc_h;
58 }
59 
check_crtc_eq(struct drm_plane_state * plane_state,int crtc_x,int crtc_y,unsigned crtc_w,unsigned crtc_h)60 static bool check_crtc_eq(struct drm_plane_state *plane_state,
61 			  int crtc_x, int crtc_y,
62 			  unsigned crtc_w, unsigned crtc_h)
63 {
64 	if (plane_state->dst.x1 != crtc_x ||
65 	    plane_state->dst.y1 != crtc_y ||
66 	    drm_rect_width(&plane_state->dst) != crtc_w ||
67 	    drm_rect_height(&plane_state->dst) != crtc_h) {
68 		drm_rect_debug_print("dst: ", &plane_state->dst, false);
69 
70 		return false;
71 	}
72 
73 	return true;
74 }
75 
igt_check_plane_state(void * ignored)76 int igt_check_plane_state(void *ignored)
77 {
78 	int ret;
79 
80 	const struct drm_crtc_state crtc_state = {
81 		.crtc = ZERO_SIZE_PTR,
82 		.enable = true,
83 		.active = true,
84 		.mode = {
85 			DRM_MODE("1024x768", 0, 65000, 1024, 1048,
86 				1184, 1344, 0, 768, 771, 777, 806, 0,
87 				DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
88 		},
89 	};
90 	struct drm_framebuffer fb = {
91 		.width = 2048,
92 		.height = 2048
93 	};
94 	struct drm_plane_state plane_state = {
95 		.crtc = ZERO_SIZE_PTR,
96 		.fb = &fb,
97 		.rotation = DRM_MODE_ROTATE_0
98 	};
99 
100 	/* Simple clipping, no scaling. */
101 	set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
102 	set_crtc(&plane_state, 0, 0, fb.width, fb.height);
103 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
104 						  DRM_PLANE_HELPER_NO_SCALING,
105 						  DRM_PLANE_HELPER_NO_SCALING,
106 						  false, false);
107 	FAIL(ret < 0, "Simple clipping check should pass\n");
108 	FAIL_ON(!plane_state.visible);
109 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
110 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
111 
112 	/* Rotated clipping + reflection, no scaling. */
113 	plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
114 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
115 						  DRM_PLANE_HELPER_NO_SCALING,
116 						  DRM_PLANE_HELPER_NO_SCALING,
117 						  false, false);
118 	FAIL(ret < 0, "Rotated clipping check should pass\n");
119 	FAIL_ON(!plane_state.visible);
120 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
121 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
122 	plane_state.rotation = DRM_MODE_ROTATE_0;
123 
124 	/* Check whether positioning works correctly. */
125 	set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
126 	set_crtc(&plane_state, 0, 0, 1023, 767);
127 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
128 						  DRM_PLANE_HELPER_NO_SCALING,
129 						  DRM_PLANE_HELPER_NO_SCALING,
130 						  false, false);
131 	FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n");
132 
133 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
134 						  DRM_PLANE_HELPER_NO_SCALING,
135 						  DRM_PLANE_HELPER_NO_SCALING,
136 						  true, false);
137 	FAIL(ret < 0, "Simple positioning should work\n");
138 	FAIL_ON(!plane_state.visible);
139 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
140 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767));
141 
142 	/* Simple scaling tests. */
143 	set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
144 	set_crtc(&plane_state, 0, 0, 1024, 768);
145 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
146 						  0x8001,
147 						  DRM_PLANE_HELPER_NO_SCALING,
148 						  false, false);
149 	FAIL(!ret, "Upscaling out of range should fail.\n");
150 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
151 						  0x8000,
152 						  DRM_PLANE_HELPER_NO_SCALING,
153 						  false, false);
154 	FAIL(ret < 0, "Upscaling exactly 2x should work\n");
155 	FAIL_ON(!plane_state.visible);
156 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
157 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
158 
159 	set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
160 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
161 						  DRM_PLANE_HELPER_NO_SCALING,
162 						  0x1ffff, false, false);
163 	FAIL(!ret, "Downscaling out of range should fail.\n");
164 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
165 						  DRM_PLANE_HELPER_NO_SCALING,
166 						  0x20000, false, false);
167 	FAIL(ret < 0, "Should succeed with exact scaling limit\n");
168 	FAIL_ON(!plane_state.visible);
169 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
170 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
171 
172 	/* Testing rounding errors. */
173 	set_src(&plane_state, 0, 0, 0x40001, 0x40001);
174 	set_crtc(&plane_state, 1022, 766, 4, 4);
175 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
176 						  DRM_PLANE_HELPER_NO_SCALING,
177 						  0x10001,
178 						  true, false);
179 	FAIL(ret < 0, "Should succeed by clipping to exact multiple");
180 	FAIL_ON(!plane_state.visible);
181 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
182 	FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
183 
184 	set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
185 	set_crtc(&plane_state, -2, -2, 1028, 772);
186 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
187 						  DRM_PLANE_HELPER_NO_SCALING,
188 						  0x10001,
189 						  false, false);
190 	FAIL(ret < 0, "Should succeed by clipping to exact multiple");
191 	FAIL_ON(!plane_state.visible);
192 	FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16));
193 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
194 
195 	set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
196 	set_crtc(&plane_state, 1022, 766, 4, 4);
197 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
198 						  0xffff,
199 						  DRM_PLANE_HELPER_NO_SCALING,
200 						  true, false);
201 	FAIL(ret < 0, "Should succeed by clipping to exact multiple");
202 	FAIL_ON(!plane_state.visible);
203 	/* Should not be rounded to 0x20001, which would be upscaling. */
204 	FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
205 	FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
206 
207 	set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
208 	set_crtc(&plane_state, -2, -2, 1028, 772);
209 	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
210 						  0xffff,
211 						  DRM_PLANE_HELPER_NO_SCALING,
212 						  false, false);
213 	FAIL(ret < 0, "Should succeed by clipping to exact multiple");
214 	FAIL_ON(!plane_state.visible);
215 	FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16));
216 	FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
217 
218 	return 0;
219 }
220