Linux-libre 5.3.12-gnu
[librecmc/linux-libre.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         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 }