Linux Audio

Check our new training course

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}