ARB_ubo/referenced-by-shader: pass if shader compiler moves UBOs between shaders
[piglit.git] / tests / util / piglit-framework-gl / piglit_drm_dma_buf.c
blob3a31352751875213b8fb6810291e4b4dcc8c9b81
1 /*
2 * Copyright © 2013 Intel Corporation
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:
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.
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.
24 #include "piglit-util-gl.h"
25 #include "piglit_drm_dma_buf.h"
26 #include "drm-uapi/drm_fourcc.h"
27 #ifdef PIGLIT_HAS_GBM_BO_MAP
28 #include <gbm.h>
29 #endif
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <xf86drm.h>
35 #include <stdbool.h>
36 #include <xcb/dri2.h>
37 #include <drm.h>
38 #include <unistd.h>
40 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
42 struct piglit_drm_driver {
43 int fd;
44 char *name;
46 bool
47 (*create)(unsigned w, unsigned h, unsigned cpp,
48 const unsigned char *src_data,
49 struct piglit_dma_buf *buf);
51 bool
52 (*export)(struct piglit_dma_buf *buf);
54 void
55 (*destroy)(struct piglit_dma_buf *buf);
58 static const struct piglit_drm_driver *piglit_drm_get_driver(void);
60 static bool
61 piglit_drm_x11_authenticate(int fd)
63 drm_magic_t magic;
64 xcb_connection_t *conn;
65 int screen;
66 const xcb_setup_t *setup;
67 xcb_screen_iterator_t screen_iter;
68 xcb_dri2_authenticate_cookie_t auth_cookie;
69 xcb_dri2_authenticate_reply_t *auth_reply;
70 int ret = 0;
72 conn = xcb_connect(NULL, &screen);
73 if (!conn) {
74 printf("piglit: failed to connect to X server for DRI2 "
75 "authentication\n");
76 return false;
79 ret = drmGetMagic(fd, &magic);
80 if (ret) {
81 printf("piglit: failed to get DRM magic\n");
82 return false;
85 setup = xcb_get_setup(conn);
86 if (!setup) {
87 printf("piglit: xcb_get_setup() failed\n");
88 return false;
91 screen_iter = xcb_setup_roots_iterator(setup);
92 auth_cookie = xcb_dri2_authenticate_unchecked(conn,
93 screen_iter.data->root,
94 magic);
95 auth_reply = xcb_dri2_authenticate_reply(conn, auth_cookie, NULL);
97 if (auth_reply == NULL || !auth_reply->authenticated) {
98 printf("piglit: failed to authenticate with DRI2\n");
99 return false;
101 free(auth_reply);
103 return true;
106 #ifdef PIGLIT_HAS_GBM_BO_MAP
107 static struct gbm_device *
108 piglit_gbm_get(void)
110 const struct piglit_drm_driver *drv = piglit_drm_get_driver();
111 static struct gbm_device *gbm = NULL;
113 if (gbm)
114 return gbm;
116 gbm = gbm_create_device(drv->fd);
118 return gbm;
121 static bool
122 piglit_gbm_buf_create(unsigned w, unsigned h, unsigned fourcc,
123 const unsigned char *src_data, struct piglit_dma_buf *buf)
125 unsigned i;
126 struct gbm_bo *bo;
127 uint32_t dst_stride;
128 struct gbm_device *gbm = piglit_gbm_get();
129 void *dst_data;
130 void *map_data = NULL;
131 enum gbm_bo_format format;
132 unsigned cpp = 0, src_stride;
133 unsigned buf_w = w;
134 unsigned buf_h = h;
135 unsigned n_planes = 0;
137 if (!gbm || h % 2 || w % 2)
138 return false;
140 switch (fourcc) {
141 case DRM_FORMAT_R8:
142 format = GBM_FORMAT_R8;
143 cpp = 1;
144 src_stride = cpp * w;
145 n_planes = 1;
146 break;
147 case DRM_FORMAT_GR88:
148 case DRM_FORMAT_RG88:
149 case DRM_FORMAT_YUYV:
150 case DRM_FORMAT_YVYU:
151 case DRM_FORMAT_UYVY:
152 case DRM_FORMAT_VYUY:
153 format = GBM_FORMAT_GR88;
154 cpp = 2;
155 src_stride = cpp * w;
156 n_planes = 1;
157 break;
158 case DRM_FORMAT_XRGB8888:
159 case DRM_FORMAT_XBGR8888:
160 case DRM_FORMAT_RGBX8888:
161 case DRM_FORMAT_BGRX8888:
162 case DRM_FORMAT_ARGB8888:
163 case DRM_FORMAT_ABGR8888:
164 case DRM_FORMAT_RGBA8888:
165 case DRM_FORMAT_BGRA8888:
166 case DRM_FORMAT_AYUV:
167 case DRM_FORMAT_XYUV8888:
168 format = GBM_BO_FORMAT_ARGB8888;
169 cpp = 4;
170 src_stride = cpp * w;
171 n_planes = 1;
172 break;
173 case DRM_FORMAT_Y410:
174 format = GBM_FORMAT_ABGR2101010;
175 cpp = 4;
176 src_stride = cpp * w;
177 n_planes = 1;
178 break;
179 case DRM_FORMAT_Y412:
180 case DRM_FORMAT_Y416:
181 format = GBM_BO_FORMAT_ARGB8888;
182 buf_w = w * 2;
183 cpp = 8;
184 src_stride = cpp * w;
185 n_planes = 1;
186 break;
187 case DRM_FORMAT_Y210:
188 case DRM_FORMAT_Y212:
189 case DRM_FORMAT_Y216:
190 format = GBM_BO_FORMAT_ARGB8888;
191 cpp = 4;
192 src_stride = cpp * w;
193 n_planes = 1;
194 break;
196 /* For YUV formats, the U/V planes might have a greater relative
197 * pitch. For example, if the driver needs pitch aligned to 32
198 * pixels, for a 4x4 YUV image, the stride of both the Y and U/V
199 * planes will be 32 bytes. Not 32 for Y and 16 for U/V. To
200 * account for this, use a 2cpp format with half the width. For
201 * hardware that only has stride requirements in bytes (rather
202 * than pixels) this will work out the same. For hardware that
203 * has pitch alignment requirements in pixels, this will give an
204 * overly conservative alignment for Y but a sufficient alignment
205 * for U/V.
207 case DRM_FORMAT_NV12:
208 case DRM_FORMAT_NV21:
209 format = GBM_FORMAT_GR88;
210 buf_w = w / 2;
211 buf_h = h * 3 / 2;
212 src_stride = w;
213 cpp = 1;
214 n_planes = 2;
215 break;
216 case DRM_FORMAT_P010:
217 case DRM_FORMAT_P012:
218 case DRM_FORMAT_P016:
219 format = GBM_FORMAT_GR88;
220 buf_h = h * 3 / 2;
221 cpp = 2;
222 src_stride = cpp * w;
223 n_planes = 2;
224 break;
225 case DRM_FORMAT_YUV420:
226 case DRM_FORMAT_YVU420:
227 format = GBM_FORMAT_GR88;
228 buf_w = w / 2;
229 buf_h = h * 2; /* U/V not interleaved */
230 src_stride = w;
231 cpp = 1;
232 n_planes = 3;
233 break;
234 default:
235 fprintf(stderr, "invalid fourcc: %.4s\n", (char *)&fourcc);
236 return false;
239 bo = gbm_bo_create(gbm, buf_w, buf_h, format,
240 GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
241 if (!bo)
242 return false;
244 dst_data = gbm_bo_map(bo, 0, 0, buf_w, buf_h, GBM_BO_TRANSFER_WRITE,
245 &dst_stride, &map_data);
246 if (!dst_data) {
247 fprintf(stderr, "Failed to map GBM bo\n");
248 gbm_bo_destroy(bo);
249 return NULL;
252 buf->w = w;
253 buf->h = h;
254 buf->n_planes = n_planes;
255 buf->offset[0] = gbm_bo_get_offset(bo, 0);
256 buf->stride[0] = gbm_bo_get_stride_for_plane(bo, 0);
257 buf->fd = -1;
258 buf->priv = bo;
260 for (i = 0; i < h; ++i) {
261 memcpy((char *)dst_data + i * dst_stride,
262 src_data + i * src_stride,
263 w * cpp);
266 switch (fourcc) {
267 case DRM_FORMAT_NV12:
268 case DRM_FORMAT_NV21:
269 case DRM_FORMAT_P010:
270 case DRM_FORMAT_P012:
271 case DRM_FORMAT_P016:
272 for (i = 0; i < h/2; ++i) {
273 memcpy(((char *)dst_data + dst_stride * h) + i * dst_stride,
274 (src_data + (w * h * cpp)) + i * src_stride, w * cpp);
276 buf->offset[1] = buf->stride[0] * h;
277 buf->stride[1] = buf->stride[0];
278 break;
279 case DRM_FORMAT_YUV420:
280 case DRM_FORMAT_YVU420:
281 for (i = 0; i < h/2; ++i) {
282 memcpy(((char *)dst_data + dst_stride * h) + i * dst_stride,
283 (src_data + (w*h)) + i * src_stride / 2, w / 2);
285 unsigned cpu_offset2 = dst_stride * h + dst_stride * h / 2;
286 for (i = 0; i < h/2; ++i) {
287 memcpy(((char *)dst_data + cpu_offset2) + i * dst_stride,
288 (src_data + (w*h) + (w*h/4)) + i * src_stride / 2, w / 2);
290 buf->offset[1] = buf->stride[0] * h;
291 buf->stride[1] = buf->stride[0];
292 buf->offset[2] = buf->stride[0] * h + buf->stride[0] * h / 2;
293 buf->stride[2] = buf->stride[1];
294 break;
295 default:
296 break;
299 gbm_bo_unmap(bo, map_data);
302 return true;
305 static bool
306 piglit_gbm_buf_export(struct piglit_dma_buf *buf)
308 struct gbm_bo *bo = buf->priv;
310 buf->fd = gbm_bo_get_fd(bo);
312 return buf->fd >= 0;
315 static void
316 piglit_gbm_buf_destroy(struct piglit_dma_buf *buf)
318 struct gbm_bo *bo = buf->priv;
320 gbm_bo_destroy(bo);
322 #endif /* PIGLIT_HAS_GBM_BO_MAP */
324 static int
325 piglit_drm_get_user_fd(void)
327 int fd_res = -1;
328 char *nodename = getenv("WAFFLE_GBM_DEVICE");
329 if (nodename && strlen(nodename))
330 fd_res = open(nodename, O_RDWR);
332 return fd_res;
335 static const struct piglit_drm_driver *
336 piglit_drm_get_driver(void)
338 static struct piglit_drm_driver drv = { /* fd */ -1 };
339 drmVersionPtr version = NULL;
341 if (drv.fd != -1)
342 return &drv;
344 drv.fd = piglit_drm_get_user_fd();
345 if (drv.fd == -1) {
346 drv.fd = open("/dev/dri/renderD128", O_RDWR);
348 if (drv.fd == -1) {
349 drv.fd = open("/dev/dri/card0", O_RDWR);
350 if (drv.fd == -1) {
351 fprintf(stderr, "error: failed to open /dev/dri/renderD128 and "
352 "/dev/dri/card0\n");
353 goto fail;
357 if (!piglit_drm_x11_authenticate(drv.fd))
358 goto fail;
361 version = drmGetVersion(drv.fd);
363 if (!version || !version->name) {
364 fprintf(stderr, "error: drmGetVersion() failed\n");
365 goto fail;
366 } else {
367 #if 0
368 fprintf(stderr, "version: %s %d:%d\n",
369 version->name, version->version_major, version->version_minor);
370 #endif
373 drv.name = strdup(version->name);
374 if (!drv.name) {
375 drmFreeVersion(version);
376 fprintf(stderr, "out of memory\n");
377 abort();
380 if (0) {
381 /* empty */
383 #ifdef PIGLIT_HAS_GBM_BO_MAP
384 else if (true) {
385 drv.create = piglit_gbm_buf_create;
386 drv.export = piglit_gbm_buf_export;
387 drv.destroy = piglit_gbm_buf_destroy;
389 #endif
390 else {
391 fprintf(stderr, "error: unrecognized DRM driver name %s\n",
392 version->name);
393 goto fail;
396 drmFreeVersion(version);
397 return &drv;
399 fail:
400 if (drv.fd != -1) {
401 close(drv.fd);
402 drv.fd = -1;
405 if (drv.name) {
406 free(drv.name);
407 drv.name = NULL;
410 drmFreeVersion(version);
411 return NULL;
414 static bool
415 drm_create_dma_buf_modifiers(unsigned w, unsigned h, unsigned fourcc,
416 uint64_t modifier, const unsigned char *src_data,
417 struct piglit_dma_buf *buf)
419 unsigned i;
420 struct gbm_bo *bo;
421 uint32_t dst_stride;
422 struct gbm_device *gbm = piglit_gbm_get();
423 void *dst_data;
424 void *map_data = NULL;
425 unsigned cpp = 0, src_stride;
427 if (!gbm)
428 return false;
430 switch (fourcc) {
431 case DRM_FORMAT_R8:
432 cpp = 1;
433 break;
434 case DRM_FORMAT_R16:
435 cpp = 2;
436 break;
437 case DRM_FORMAT_XBGR8888:
438 case DRM_FORMAT_XRGB8888:
439 case DRM_FORMAT_ABGR8888:
440 case DRM_FORMAT_ARGB8888:
441 cpp = 4;
442 break;
443 default:
444 fprintf(stderr, "invalid fourcc: %.4s\n", (char *)&fourcc);
445 return false;
448 bo = gbm_bo_create_with_modifiers(gbm, w, h, fourcc, &modifier, 1);
449 if (!bo)
450 return false;
452 dst_data = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_WRITE,
453 &dst_stride, &map_data);
454 if (!dst_data) {
455 fprintf(stderr, "Failed to map GBM bo\n");
456 gbm_bo_destroy(bo);
457 return false;
460 src_stride = cpp * w;
462 buf->w = w;
463 buf->h = h;
465 buf->n_planes = gbm_bo_get_plane_count(bo);
466 assert(buf->n_planes <= ARRAY_SIZE(buf->offset));
467 for (int i = 0; i < buf->n_planes; i++) {
468 buf->offset[i] = gbm_bo_get_offset(bo, i);
469 buf->stride[i] = gbm_bo_get_stride_for_plane(bo, i);
472 buf->fd = -1;
473 buf->priv = bo;
475 for (i = 0; i < h; ++i) {
476 memcpy((char *)dst_data + i * dst_stride,
477 src_data + i * src_stride,
478 w * cpp);
481 gbm_bo_unmap(bo, map_data);
484 return true;
486 enum piglit_result
487 piglit_drm_create_dma_buf_modifiers(unsigned w, unsigned h, unsigned fourcc,
488 uint64_t modifier, const void *src_data,
489 struct piglit_dma_buf **buf)
491 struct piglit_dma_buf *drm_buf;
492 const struct piglit_drm_driver *drv = piglit_drm_get_driver();
494 if (!drv)
495 return PIGLIT_SKIP;
497 drm_buf = calloc(sizeof(struct piglit_dma_buf), 1);
498 if (!drm_buf)
499 return PIGLIT_FAIL;
501 if (!drm_create_dma_buf_modifiers(w, h, fourcc, modifier, src_data,
502 drm_buf)) {
503 free(drm_buf);
504 return PIGLIT_FAIL;
507 if (!drv->export(drm_buf)) {
508 free(drm_buf);
509 return PIGLIT_FAIL;
512 *buf = drm_buf;
514 return PIGLIT_PASS;
518 enum piglit_result
519 piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned fourcc,
520 const void *src_data, struct piglit_dma_buf **buf)
522 struct piglit_dma_buf *drm_buf;
523 const struct piglit_drm_driver *drv = piglit_drm_get_driver();
525 if (!drv)
526 return PIGLIT_SKIP;
528 drm_buf = calloc(sizeof(struct piglit_dma_buf), 1);
529 if (!drm_buf)
530 return PIGLIT_FAIL;
532 if (!drv->create(w, h, fourcc, src_data, drm_buf)) {
533 free(drm_buf);
534 return PIGLIT_FAIL;
537 if (!drv->export(drm_buf)) {
538 free(drm_buf);
539 return PIGLIT_FAIL;
542 *buf = drm_buf;
544 return PIGLIT_PASS;
547 void
548 piglit_drm_destroy_dma_buf(struct piglit_dma_buf *buf)
550 const struct piglit_drm_driver *drv;
552 if (!buf)
553 return;
555 drv = piglit_drm_get_driver();
556 if (!drv)
557 return;
559 drv->destroy(buf);
560 free(buf);