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