Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Test cases for the drm_framebuffer functions
4 */
5
6#include <linux/kernel.h>
7
8#include <drm/drm_device.h>
9#include <drm/drm_mode.h>
10#include <drm/drm_fourcc.h>
11#include <drm/drm_print.h>
12
13#include "../drm_crtc_internal.h"
14
15#include "test-drm_modeset_common.h"
16
17#define MIN_WIDTH 4
18#define MAX_WIDTH 4096
19#define MIN_HEIGHT 4
20#define MAX_HEIGHT 4096
21
22struct drm_framebuffer_test {
23 int buffer_created;
24 struct drm_mode_fb_cmd2 cmd;
25 const char *name;
26};
27
28static struct drm_framebuffer_test createbuffer_tests[] = {
29{ .buffer_created = 1, .name = "ABGR8888 normal sizes",
30 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_ABGR8888,
31 .handles = { 1, 0, 0 }, .pitches = { 4 * 600, 0, 0 },
32 }
33},
34{ .buffer_created = 1, .name = "ABGR8888 max sizes",
35 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
36 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
37 }
38},
39{ .buffer_created = 1, .name = "ABGR8888 pitch greater than min required",
40 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
41 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH + 1, 0, 0 },
42 }
43},
44{ .buffer_created = 0, .name = "ABGR8888 pitch less than min required",
45 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
46 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH - 1, 0, 0 },
47 }
48},
49{ .buffer_created = 0, .name = "ABGR8888 Invalid width",
50 .cmd = { .width = MAX_WIDTH + 1, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
51 .handles = { 1, 0, 0 }, .pitches = { 4 * (MAX_WIDTH + 1), 0, 0 },
52 }
53},
54{ .buffer_created = 0, .name = "ABGR8888 Invalid buffer handle",
55 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
56 .handles = { 0, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
57 }
58},
59{ .buffer_created = 0, .name = "No pixel format",
60 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = 0,
61 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
62 }
63},
64{ .buffer_created = 0, .name = "ABGR8888 Width 0",
65 .cmd = { .width = 0, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
66 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
67 }
68},
69{ .buffer_created = 0, .name = "ABGR8888 Height 0",
70 .cmd = { .width = MAX_WIDTH, .height = 0, .pixel_format = DRM_FORMAT_ABGR8888,
71 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
72 }
73},
74{ .buffer_created = 0, .name = "ABGR8888 Out of bound height * pitch combination",
75 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
76 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
77 }
78},
79{ .buffer_created = 1, .name = "ABGR8888 Large buffer offset",
80 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
81 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
82 }
83},
84{ .buffer_created = 1, .name = "ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers",
85 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
86 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
87 .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
88 }
89},
90{ .buffer_created = 1, .name = "ABGR8888 Valid buffer modifier",
91 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
92 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
93 .flags = DRM_MODE_FB_MODIFIERS, .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 },
94 }
95},
96{ .buffer_created = 0, .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)",
97 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
98 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
99 .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
100 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
101 }
102},
103{ .buffer_created = 1, .name = "ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS",
104 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
105 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
106 .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
107 }
108},
109{ .buffer_created = 0, .name = "ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS",
110 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
111 .handles = { 1, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
112 .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
113 }
114},
115{ .buffer_created = 1, .name = "NV12 Normal sizes",
116 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
117 .handles = { 1, 1, 0 }, .pitches = { 600, 600, 0 },
118 }
119},
120{ .buffer_created = 1, .name = "NV12 Max sizes",
121 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
122 .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
123 }
124},
125{ .buffer_created = 0, .name = "NV12 Invalid pitch",
126 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
127 .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH - 1, 0 },
128 }
129},
130{ .buffer_created = 0, .name = "NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag",
131 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
132 .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
133 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
134 }
135},
136{ .buffer_created = 0, .name = "NV12 different modifier per-plane",
137 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
138 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
139 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
140 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
141 }
142},
143{ .buffer_created = 1, .name = "NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE",
144 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
145 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
146 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
147 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
148 }
149},
150{ .buffer_created = 0, .name = "NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS",
151 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
152 .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
153 DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
154 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
155 }
156},
157{ .buffer_created = 0, .name = "NV12 Modifier for inexistent plane",
158 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
159 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
160 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
161 DRM_FORMAT_MOD_SAMSUNG_64_32_TILE },
162 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
163 }
164},
165{ .buffer_created = 0, .name = "NV12 Handle for inexistent plane",
166 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
167 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
168 }
169},
170{ .buffer_created = 1, .name = "NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS",
171 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
172 .handles = { 1, 1, 1 }, .pitches = { 600, 600, 600 },
173 }
174},
175{ .buffer_created = 1, .name = "YVU420 Normal sizes",
176 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
177 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
178 .pitches = { 600, 300, 300 },
179 }
180},
181{ .buffer_created = 1, .name = "YVU420 DRM_MODE_FB_MODIFIERS set without modifier",
182 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
183 .handles = { 1, 1, 1 }, .pitches = { 600, 300, 300 },
184 }
185},
186{ .buffer_created = 1, .name = "YVU420 Max sizes",
187 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
188 .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2),
189 DIV_ROUND_UP(MAX_WIDTH, 2) },
190 }
191},
192{ .buffer_created = 0, .name = "YVU420 Invalid pitch",
193 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
194 .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) - 1,
195 DIV_ROUND_UP(MAX_WIDTH, 2) },
196 }
197},
198{ .buffer_created = 1, .name = "YVU420 Different pitches",
199 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
200 .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1,
201 DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
202 }
203},
204{ .buffer_created = 1, .name = "YVU420 Different buffer offsets/pitches",
205 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
206 .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH + MAX_WIDTH * MAX_HEIGHT,
207 MAX_WIDTH + 2 * MAX_WIDTH * MAX_HEIGHT },
208 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
209 }
210},
211{ .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS",
212 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
213 .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
214 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
215 }
216},
217{ .buffer_created = 0, .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS",
218 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
219 .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
220 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
221 }
222},
223{ .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS",
224 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
225 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
226 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
227 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
228 }
229},
230{ .buffer_created = 1, .name = "YVU420 Valid modifier",
231 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
232 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
233 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE },
234 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
235 }
236},
237{ .buffer_created = 0, .name = "YVU420 Different modifiers per plane",
238 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
239 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
240 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR,
241 AFBC_FORMAT_MOD_SPARSE },
242 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
243 }
244},
245{ .buffer_created = 0, .name = "YVU420 Modifier for inexistent plane",
246 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
247 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
248 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE,
249 AFBC_FORMAT_MOD_SPARSE },
250 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
251 }
252},
253{ .buffer_created = 1, .name = "X0L2 Normal sizes",
254 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_X0L2,
255 .handles = { 1, 0, 0 }, .pitches = { 1200, 0, 0 }
256 }
257},
258{ .buffer_created = 1, .name = "X0L2 Max sizes",
259 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
260 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH, 0, 0 }
261 }
262},
263{ .buffer_created = 0, .name = "X0L2 Invalid pitch",
264 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
265 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH - 1, 0, 0 }
266 }
267},
268{ .buffer_created = 1, .name = "X0L2 Pitch greater than minimum required",
269 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
270 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
271 }
272},
273{ .buffer_created = 0, .name = "X0L2 Handle for inexistent plane",
274 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
275 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
276 .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
277 }
278},
279{ .buffer_created = 1, .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set",
280 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
281 .handles = { 1, 0, 0 }, .offsets = { 0, 0, 3 },
282 .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
283 }
284},
285{ .buffer_created = 0, .name = "X0L2 Modifier without DRM_MODE_FB_MODIFIERS set",
286 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
287 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
288 .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
289 }
290},
291{ .buffer_created = 1, .name = "X0L2 Valid modifier",
292 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
293 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
294 .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
295 }
296},
297{ .buffer_created = 0, .name = "X0L2 Modifier for inexistent plane",
298 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT,
299 .pixel_format = DRM_FORMAT_X0L2, .handles = { 1, 0, 0 },
300 .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
301 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
302 .flags = DRM_MODE_FB_MODIFIERS,
303 }
304},
305};
306
307static struct drm_framebuffer *fb_create_mock(struct drm_device *dev,
308 struct drm_file *file_priv,
309 const struct drm_mode_fb_cmd2 *mode_cmd)
310{
311 int *buffer_created = dev->dev_private;
312 *buffer_created = 1;
313 return ERR_PTR(-EINVAL);
314}
315
316static struct drm_mode_config_funcs mock_config_funcs = {
317 .fb_create = fb_create_mock,
318};
319
320static struct drm_device mock_drm_device = {
321 .mode_config = {
322 .min_width = MIN_WIDTH,
323 .max_width = MAX_WIDTH,
324 .min_height = MIN_HEIGHT,
325 .max_height = MAX_HEIGHT,
326 .allow_fb_modifiers = true,
327 .funcs = &mock_config_funcs,
328 },
329};
330
331static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r)
332{
333 int buffer_created = 0;
334
335 mock_drm_device.dev_private = &buffer_created;
336 drm_internal_framebuffer_create(&mock_drm_device, r, NULL);
337 return buffer_created;
338}
339
340int igt_check_drm_framebuffer_create(void *ignored)
341{
342 int i = 0;
343
344 for (i = 0; i < ARRAY_SIZE(createbuffer_tests); i++) {
345 FAIL(createbuffer_tests[i].buffer_created !=
346 execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd),
347 "Test %d: \"%s\" failed\n", i, createbuffer_tests[i].name);
348 }
349
350 return 0;
351}