GNU Linux-libre 5.19-rc6-gnu
[releases.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 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
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
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
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
76 int igt_check_plane_state(void *ignored)
77 {
78         int ret;
79
80         static 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         static struct drm_plane plane = {
91                 .dev = NULL
92         };
93         static struct drm_framebuffer fb = {
94                 .width = 2048,
95                 .height = 2048
96         };
97         static struct drm_plane_state plane_state = {
98                 .plane = &plane,
99                 .crtc = ZERO_SIZE_PTR,
100                 .fb = &fb,
101                 .rotation = DRM_MODE_ROTATE_0
102         };
103
104         /* Simple clipping, no scaling. */
105         set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
106         set_crtc(&plane_state, 0, 0, fb.width, fb.height);
107         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
108                                                   DRM_PLANE_HELPER_NO_SCALING,
109                                                   DRM_PLANE_HELPER_NO_SCALING,
110                                                   false, false);
111         FAIL(ret < 0, "Simple clipping check should pass\n");
112         FAIL_ON(!plane_state.visible);
113         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
114         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
115
116         /* Rotated clipping + reflection, no scaling. */
117         plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
118         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
119                                                   DRM_PLANE_HELPER_NO_SCALING,
120                                                   DRM_PLANE_HELPER_NO_SCALING,
121                                                   false, false);
122         FAIL(ret < 0, "Rotated clipping check should pass\n");
123         FAIL_ON(!plane_state.visible);
124         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
125         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
126         plane_state.rotation = DRM_MODE_ROTATE_0;
127
128         /* Check whether positioning works correctly. */
129         set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
130         set_crtc(&plane_state, 0, 0, 1023, 767);
131         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
132                                                   DRM_PLANE_HELPER_NO_SCALING,
133                                                   DRM_PLANE_HELPER_NO_SCALING,
134                                                   false, false);
135         FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n");
136
137         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
138                                                   DRM_PLANE_HELPER_NO_SCALING,
139                                                   DRM_PLANE_HELPER_NO_SCALING,
140                                                   true, false);
141         FAIL(ret < 0, "Simple positioning should work\n");
142         FAIL_ON(!plane_state.visible);
143         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
144         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767));
145
146         /* Simple scaling tests. */
147         set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
148         set_crtc(&plane_state, 0, 0, 1024, 768);
149         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
150                                                   0x8001,
151                                                   DRM_PLANE_HELPER_NO_SCALING,
152                                                   false, false);
153         FAIL(!ret, "Upscaling out of range should fail.\n");
154         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
155                                                   0x8000,
156                                                   DRM_PLANE_HELPER_NO_SCALING,
157                                                   false, false);
158         FAIL(ret < 0, "Upscaling exactly 2x should work\n");
159         FAIL_ON(!plane_state.visible);
160         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
161         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
162
163         set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
164         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
165                                                   DRM_PLANE_HELPER_NO_SCALING,
166                                                   0x1ffff, false, false);
167         FAIL(!ret, "Downscaling out of range should fail.\n");
168         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
169                                                   DRM_PLANE_HELPER_NO_SCALING,
170                                                   0x20000, false, false);
171         FAIL(ret < 0, "Should succeed with exact scaling limit\n");
172         FAIL_ON(!plane_state.visible);
173         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
174         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
175
176         /* Testing rounding errors. */
177         set_src(&plane_state, 0, 0, 0x40001, 0x40001);
178         set_crtc(&plane_state, 1022, 766, 4, 4);
179         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
180                                                   DRM_PLANE_HELPER_NO_SCALING,
181                                                   0x10001,
182                                                   true, false);
183         FAIL(ret < 0, "Should succeed by clipping to exact multiple");
184         FAIL_ON(!plane_state.visible);
185         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
186         FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
187
188         set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
189         set_crtc(&plane_state, -2, -2, 1028, 772);
190         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
191                                                   DRM_PLANE_HELPER_NO_SCALING,
192                                                   0x10001,
193                                                   false, false);
194         FAIL(ret < 0, "Should succeed by clipping to exact multiple");
195         FAIL_ON(!plane_state.visible);
196         FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16));
197         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
198
199         set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
200         set_crtc(&plane_state, 1022, 766, 4, 4);
201         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
202                                                   0xffff,
203                                                   DRM_PLANE_HELPER_NO_SCALING,
204                                                   true, false);
205         FAIL(ret < 0, "Should succeed by clipping to exact multiple");
206         FAIL_ON(!plane_state.visible);
207         /* Should not be rounded to 0x20001, which would be upscaling. */
208         FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
209         FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
210
211         set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
212         set_crtc(&plane_state, -2, -2, 1028, 772);
213         ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
214                                                   0xffff,
215                                                   DRM_PLANE_HELPER_NO_SCALING,
216                                                   false, false);
217         FAIL(ret < 0, "Should succeed by clipping to exact multiple");
218         FAIL_ON(!plane_state.visible);
219         FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16));
220         FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
221
222         return 0;
223 }