1 /*
2  * Copyright © 2015 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 /* This program tests whether the igt_draw library actually works. */
26 
27 #include "igt.h"
28 
29 #define MAX_CONNECTORS 32
30 
31 struct modeset_params {
32 	uint32_t crtc_id;
33 	uint32_t connector_id;
34 	drmModeModeInfoPtr mode;
35 };
36 
37 int drm_fd;
38 drmModeResPtr drm_res;
39 drmModeConnectorPtr drm_connectors[MAX_CONNECTORS];
40 drm_intel_bufmgr *bufmgr;
41 igt_pipe_crc_t *pipe_crc;
42 
43 #define N_FORMATS 3
44 static const uint32_t formats[N_FORMATS] = {
45 	DRM_FORMAT_XRGB8888,
46 	DRM_FORMAT_RGB565,
47 	DRM_FORMAT_XRGB2101010,
48 };
49 
50 #define N_TILING_METHODS 3
51 static const uint64_t tilings[N_TILING_METHODS] = {
52 	LOCAL_DRM_FORMAT_MOD_NONE,
53 	LOCAL_I915_FORMAT_MOD_X_TILED,
54 	LOCAL_I915_FORMAT_MOD_Y_TILED,
55 };
56 
57 struct base_crc {
58 	bool set;
59 	igt_crc_t crc;
60 };
61 struct base_crc base_crcs[N_FORMATS];
62 
63 struct modeset_params ms;
64 
find_modeset_params(void)65 static void find_modeset_params(void)
66 {
67 	int i;
68 	uint32_t crtc_id;
69 	drmModeConnectorPtr connector = NULL;
70 	drmModeModeInfoPtr mode = NULL;
71 
72 	for (i = 0; i < drm_res->count_connectors; i++) {
73 		drmModeConnectorPtr c = drm_connectors[i];
74 
75 		if (c->count_modes) {
76 			connector = c;
77 			mode = &c->modes[0];
78 			break;
79 		}
80 	}
81 	igt_require(connector);
82 
83 	crtc_id = kmstest_find_crtc_for_connector(drm_fd, drm_res, connector,
84 						  0);
85 	igt_assert(mode);
86 
87 	ms.connector_id = connector->connector_id;
88 	ms.crtc_id = crtc_id;
89 	ms.mode = mode;
90 
91 }
92 
get_color(uint32_t drm_format,bool r,bool g,bool b)93 static uint32_t get_color(uint32_t drm_format, bool r, bool g, bool b)
94 {
95 	uint32_t color = 0;
96 
97 	switch (drm_format) {
98 	case DRM_FORMAT_RGB565:
99 		color |= r ? 0x1F << 11 : 0;
100 		color |= g ? 0x3F << 5 : 0;
101 		color |= b ? 0x1F : 0;
102 		break;
103 	case DRM_FORMAT_XRGB8888:
104 		color |= r ? 0xFF << 16 : 0;
105 		color |= g ? 0xFF << 8 : 0;
106 		color |= b ? 0xFF : 0;
107 		break;
108 	case DRM_FORMAT_XRGB2101010:
109 		color |= r ? 0x3FF << 20 : 0;
110 		color |= g ? 0x3FF << 10 : 0;
111 		color |= b ? 0x3FF : 0;
112 		break;
113 	default:
114 		igt_assert(false);
115 	}
116 
117 	return color;
118 }
119 
get_method_crc(enum igt_draw_method method,uint32_t drm_format,uint64_t tiling,igt_crc_t * crc)120 static void get_method_crc(enum igt_draw_method method, uint32_t drm_format,
121 			   uint64_t tiling, igt_crc_t *crc)
122 {
123 	struct igt_fb fb;
124 	int rc;
125 
126 	igt_create_fb(drm_fd, ms.mode->hdisplay, ms.mode->vdisplay,
127 		      drm_format, tiling, &fb);
128 	igt_draw_rect_fb(drm_fd, bufmgr, NULL, &fb, method,
129 			 0, 0, fb.width, fb.height,
130 			 get_color(drm_format, 0, 0, 1));
131 
132 	igt_draw_rect_fb(drm_fd, bufmgr, NULL, &fb, method,
133 			 fb.width / 4, fb.height / 4,
134 			 fb.width / 2, fb.height / 2,
135 			 get_color(drm_format, 0, 1, 0));
136 	igt_draw_rect_fb(drm_fd, bufmgr, NULL, &fb, method,
137 			 fb.width / 8, fb.height / 8,
138 			 fb.width / 4, fb.height / 4,
139 			 get_color(drm_format, 1, 0, 0));
140 	igt_draw_rect_fb(drm_fd, bufmgr, NULL, &fb, method,
141 			 fb.width / 2, fb.height / 2,
142 			 fb.width / 3, fb.height / 3,
143 			 get_color(drm_format, 1, 0, 1));
144 	igt_draw_rect_fb(drm_fd, bufmgr, NULL, &fb, method, 1, 1, 15, 15,
145 			 get_color(drm_format, 0, 1, 1));
146 
147 	rc = drmModeSetCrtc(drm_fd, ms.crtc_id, fb.fb_id, 0, 0,
148 			    &ms.connector_id, 1, ms.mode);
149 	igt_assert_eq(rc, 0);
150 
151 	igt_pipe_crc_collect_crc(pipe_crc, crc);
152 
153 	igt_remove_fb(drm_fd, &fb);
154 }
155 
format_is_supported(uint32_t format,uint64_t modifier)156 static bool format_is_supported(uint32_t format, uint64_t modifier)
157 {
158 	uint32_t gem_handle, fb_id;
159 	unsigned int offsets[4] = {};
160 	unsigned int strides[4] = {};
161 	int ret;
162 
163 	gem_handle = igt_create_bo_with_dimensions(drm_fd, 64, 64,
164 						   format, modifier,
165 						   0, NULL, &strides[0], NULL);
166 	ret =  __kms_addfb(drm_fd, gem_handle, 64, 64,
167 			   format, modifier, strides, offsets, 1,
168 			   LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id);
169 	drmModeRmFB(drm_fd, fb_id);
170 	gem_close(drm_fd, gem_handle);
171 
172 	return ret == 0;
173 }
174 
draw_method_subtest(enum igt_draw_method method,uint32_t format_index,uint64_t tiling)175 static void draw_method_subtest(enum igt_draw_method method,
176 				uint32_t format_index, uint64_t tiling)
177 {
178 	igt_crc_t crc;
179 
180 	igt_skip_on(method == IGT_DRAW_MMAP_WC && !gem_mmap__has_wc(drm_fd));
181 
182 	igt_require(format_is_supported(formats[format_index], tiling));
183 
184 	/* Use IGT_DRAW_MMAP_GTT on an untiled buffer as the parameter for
185 	 * comparison. Cache the value so we don't recompute it for every single
186 	 * subtest. */
187 	if (!base_crcs[format_index].set) {
188 		get_method_crc(IGT_DRAW_MMAP_GTT, formats[format_index],
189 			       LOCAL_DRM_FORMAT_MOD_NONE,
190 			       &base_crcs[format_index].crc);
191 		base_crcs[format_index].set = true;
192 	}
193 
194 	get_method_crc(method, formats[format_index], tiling, &crc);
195 	igt_assert_crc_equal(&crc, &base_crcs[format_index].crc);
196 }
197 
get_fill_crc(uint64_t tiling,igt_crc_t * crc)198 static void get_fill_crc(uint64_t tiling, igt_crc_t *crc)
199 {
200 	struct igt_fb fb;
201 	int rc;
202 
203 	igt_create_fb(drm_fd, ms.mode->hdisplay, ms.mode->vdisplay,
204 		      DRM_FORMAT_XRGB8888, tiling, &fb);
205 
206 	igt_draw_fill_fb(drm_fd, &fb, 0xFF);
207 
208 	rc = drmModeSetCrtc(drm_fd, ms.crtc_id, fb.fb_id, 0, 0,
209 			    &ms.connector_id, 1, ms.mode);
210 	igt_assert_eq(rc, 0);
211 
212 	igt_pipe_crc_collect_crc(pipe_crc, crc);
213 
214 	igt_remove_fb(drm_fd, &fb);
215 }
216 
fill_fb_subtest(void)217 static void fill_fb_subtest(void)
218 {
219 	int rc;
220 	struct igt_fb fb;
221 	igt_crc_t base_crc, crc;
222 
223 	igt_create_fb(drm_fd, ms.mode->hdisplay, ms.mode->vdisplay,
224 		      DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, &fb);
225 
226 	igt_draw_rect_fb(drm_fd, bufmgr, NULL, &fb, IGT_DRAW_MMAP_GTT,
227 			 0, 0, fb.width, fb.height, 0xFF);
228 
229 	rc = drmModeSetCrtc(drm_fd, ms.crtc_id, fb.fb_id, 0, 0,
230 			    &ms.connector_id, 1, ms.mode);
231 	igt_assert_eq(rc, 0);
232 
233 	igt_pipe_crc_collect_crc(pipe_crc, &base_crc);
234 
235 	get_fill_crc(LOCAL_DRM_FORMAT_MOD_NONE, &crc);
236 	igt_assert_crc_equal(&crc, &base_crc);
237 
238 	get_fill_crc(LOCAL_I915_FORMAT_MOD_X_TILED, &crc);
239 	igt_assert_crc_equal(&crc, &base_crc);
240 
241 	if (intel_gen(intel_get_drm_devid(drm_fd)) >= 9) {
242 		get_fill_crc(LOCAL_I915_FORMAT_MOD_Y_TILED, &crc);
243 		igt_assert_crc_equal(&crc, &base_crc);
244 	}
245 
246 	igt_remove_fb(drm_fd, &fb);
247 }
248 
setup_environment(void)249 static void setup_environment(void)
250 {
251 	int i;
252 
253 	drm_fd = drm_open_driver_master(DRIVER_INTEL);
254 	igt_require(drm_fd >= 0);
255 
256 	drm_res = drmModeGetResources(drm_fd);
257 	igt_require(drm_res);
258 	igt_assert(drm_res->count_connectors <= MAX_CONNECTORS);
259 
260 	for (i = 0; i < drm_res->count_connectors; i++)
261 		drm_connectors[i] = drmModeGetConnectorCurrent(drm_fd,
262 							       drm_res->connectors[i]);
263 
264 	kmstest_set_vt_graphics_mode();
265 
266 	bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
267 	igt_assert(bufmgr);
268 	drm_intel_bufmgr_gem_enable_reuse(bufmgr);
269 
270 	find_modeset_params();
271 	pipe_crc = igt_pipe_crc_new(drm_fd, kmstest_get_crtc_idx(drm_res, ms.crtc_id),
272 				    INTEL_PIPE_CRC_SOURCE_AUTO);
273 }
274 
teardown_environment(void)275 static void teardown_environment(void)
276 {
277 	int i;
278 
279 	igt_pipe_crc_free(pipe_crc);
280 
281 	drm_intel_bufmgr_destroy(bufmgr);
282 
283 	for (i = 0; i < drm_res->count_connectors; i++)
284 		drmModeFreeConnector(drm_connectors[i]);
285 
286 	drmModeFreeResources(drm_res);
287 	close(drm_fd);
288 }
289 
format_str(int format_index)290 static const char *format_str(int format_index)
291 {
292 	switch (formats[format_index]) {
293 	case DRM_FORMAT_RGB565:
294 		return "rgb565";
295 	case DRM_FORMAT_XRGB8888:
296 		return "xrgb8888";
297 	case DRM_FORMAT_XRGB2101010:
298 		return "xrgb2101010";
299 	default:
300 		igt_assert(false);
301 	}
302 }
303 
tiling_str(int tiling_index)304 static const char *tiling_str(int tiling_index)
305 {
306 	switch (tilings[tiling_index]) {
307 	case LOCAL_DRM_FORMAT_MOD_NONE:
308 		return "untiled";
309 	case LOCAL_I915_FORMAT_MOD_X_TILED:
310 		return "xtiled";
311 	case LOCAL_I915_FORMAT_MOD_Y_TILED:
312 		return "ytiled";
313 	default:
314 		igt_assert(false);
315 	}
316 }
317 
318 igt_main
319 {
320 	enum igt_draw_method method;
321 	int format_idx, tiling_idx;
322 
323 	igt_fixture
324 		setup_environment();
325 
326 	for (format_idx = 0; format_idx < N_FORMATS; format_idx++) {
327 	for (method = 0; method < IGT_DRAW_METHOD_COUNT; method++) {
328 	for (tiling_idx = 0; tiling_idx < N_TILING_METHODS; tiling_idx++) {
329 		igt_subtest_f("draw-method-%s-%s-%s",
330 			      format_str(format_idx),
331 			      igt_draw_get_method_name(method),
332 			      tiling_str(tiling_idx))
333 			draw_method_subtest(method, format_idx,
334 					    tilings[tiling_idx]);
335 	} } }
336 
337 	igt_subtest("fill-fb")
338 		fill_fb_subtest();
339 
340 	igt_fixture
341 		teardown_environment();
342 }
343