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
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
24 #include "piglit-util-gl.h"
25 #include "piglit_drm_dma_buf.h"
26 #include "drm_fourcc.h"
27 #ifdef PIGLIT_HAS_GBM_BO_MAP
30 #include <sys/types.h>
40 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
42 struct piglit_drm_driver
{
47 (*create
)(unsigned w
, unsigned h
, unsigned cpp
,
48 const unsigned char *src_data
,
49 struct piglit_dma_buf
*buf
);
52 (*export
)(struct piglit_dma_buf
*buf
);
55 (*destroy
)(struct piglit_dma_buf
*buf
);
58 static const struct piglit_drm_driver
*piglit_drm_get_driver(void);
61 piglit_drm_x11_authenticate(int fd
)
64 xcb_connection_t
*conn
;
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
;
72 conn
= xcb_connect(NULL
, &screen
);
74 printf("piglit: failed to connect to X server for DRI2 "
79 ret
= drmGetMagic(fd
, &magic
);
81 printf("piglit: failed to get DRM magic\n");
85 setup
= xcb_get_setup(conn
);
87 printf("piglit: xcb_get_setup() failed\n");
91 screen_iter
= xcb_setup_roots_iterator(setup
);
92 auth_cookie
= xcb_dri2_authenticate_unchecked(conn
,
93 screen_iter
.data
->root
,
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");
106 #ifdef PIGLIT_HAS_GBM_BO_MAP
107 static struct gbm_device
*
110 const struct piglit_drm_driver
*drv
= piglit_drm_get_driver();
111 static struct gbm_device
*gbm
= NULL
;
116 gbm
= gbm_create_device(drv
->fd
);
122 piglit_gbm_buf_create(unsigned w
, unsigned h
, unsigned fourcc
,
123 const unsigned char *src_data
, struct piglit_dma_buf
*buf
)
128 struct gbm_device
*gbm
= piglit_gbm_get();
130 void *map_data
= NULL
;
131 enum gbm_bo_format format
;
132 unsigned cpp
= 0, src_stride
;
136 if (!gbm
|| h
% 2 || w
% 2)
141 format
= GBM_FORMAT_R8
;
143 src_stride
= cpp
* w
;
145 case DRM_FORMAT_GR88
:
146 case DRM_FORMAT_RG88
:
147 case DRM_FORMAT_YUYV
:
148 case DRM_FORMAT_UYVY
:
149 format
= GBM_FORMAT_GR88
;
151 src_stride
= cpp
* w
;
153 case DRM_FORMAT_XRGB8888
:
154 case DRM_FORMAT_XBGR8888
:
155 case DRM_FORMAT_RGBX8888
:
156 case DRM_FORMAT_BGRX8888
:
157 case DRM_FORMAT_ARGB8888
:
158 case DRM_FORMAT_ABGR8888
:
159 case DRM_FORMAT_RGBA8888
:
160 case DRM_FORMAT_BGRA8888
:
161 case DRM_FORMAT_AYUV
:
162 case DRM_FORMAT_XYUV8888
:
163 format
= GBM_BO_FORMAT_ARGB8888
;
165 src_stride
= cpp
* w
;
167 case DRM_FORMAT_Y410
:
168 format
= GBM_FORMAT_ABGR2101010
;
170 src_stride
= cpp
* w
;
172 case DRM_FORMAT_Y412
:
173 case DRM_FORMAT_Y416
:
174 format
= GBM_BO_FORMAT_ARGB8888
;
177 src_stride
= cpp
* w
;
179 case DRM_FORMAT_Y210
:
180 case DRM_FORMAT_Y212
:
181 case DRM_FORMAT_Y216
:
182 format
= GBM_BO_FORMAT_ARGB8888
;
184 src_stride
= cpp
* w
;
187 /* For YUV formats, the U/V planes might have a greater relative
188 * pitch. For example, if the driver needs pitch aligned to 32
189 * pixels, for a 4x4 YUV image, the stride of both the Y and U/V
190 * planes will be 32 bytes. Not 32 for Y and 16 for U/V. To
191 * account for this, use a 2cpp format with half the width. For
192 * hardware that only has stride requirements in bytes (rather
193 * than pixels) this will work out the same. For hardware that
194 * has pitch alignment requirements in pixels, this will give an
195 * overly conservative alignment for Y but a sufficient alignment
198 case DRM_FORMAT_NV12
:
199 format
= GBM_FORMAT_GR88
;
205 case DRM_FORMAT_P010
:
206 case DRM_FORMAT_P012
:
207 case DRM_FORMAT_P016
:
208 format
= GBM_FORMAT_GR88
;
211 src_stride
= cpp
* w
;
213 case DRM_FORMAT_YUV420
:
214 case DRM_FORMAT_YVU420
:
215 format
= GBM_FORMAT_GR88
;
217 buf_h
= h
* 2; /* U/V not interleaved */
222 fprintf(stderr
, "invalid fourcc: %.4s\n", (char *)&fourcc
);
226 bo
= gbm_bo_create(gbm
, buf_w
, buf_h
, format
,
227 GBM_BO_USE_RENDERING
| GBM_BO_USE_LINEAR
);
231 dst_data
= gbm_bo_map(bo
, 0, 0, buf_w
, buf_h
, GBM_BO_TRANSFER_WRITE
,
232 &dst_stride
, &map_data
);
234 fprintf(stderr
, "Failed to map GBM bo\n");
241 buf
->offset
[0] = gbm_bo_get_offset(bo
, 0);
242 buf
->stride
[0] = gbm_bo_get_stride_for_plane(bo
, 0);
246 for (i
= 0; i
< h
; ++i
) {
247 memcpy((char *)dst_data
+ i
* dst_stride
,
248 src_data
+ i
* src_stride
,
253 case DRM_FORMAT_NV12
:
254 case DRM_FORMAT_P010
:
255 case DRM_FORMAT_P012
:
256 case DRM_FORMAT_P016
:
257 for (i
= 0; i
< h
/2; ++i
) {
258 memcpy(((char *)dst_data
+ dst_stride
* h
) + i
* dst_stride
,
259 (src_data
+ (w
* h
* cpp
)) + i
* src_stride
, w
* cpp
);
261 buf
->offset
[1] = buf
->stride
[0] * h
;
262 buf
->stride
[1] = buf
->stride
[0];
264 case DRM_FORMAT_YUV420
:
265 case DRM_FORMAT_YVU420
:
266 for (i
= 0; i
< h
/2; ++i
) {
267 memcpy(((char *)dst_data
+ dst_stride
* h
) + i
* dst_stride
,
268 (src_data
+ (w
*h
)) + i
* src_stride
/ 2, w
/ 2);
270 unsigned cpu_offset2
= dst_stride
* h
+ dst_stride
* h
/ 2;
271 for (i
= 0; i
< h
/2; ++i
) {
272 memcpy(((char *)dst_data
+ cpu_offset2
) + i
* dst_stride
,
273 (src_data
+ (w
*h
) + (w
*h
/4)) + i
* src_stride
/ 2, w
/ 2);
275 buf
->offset
[1] = buf
->stride
[0] * h
;
276 buf
->stride
[1] = buf
->stride
[0];
277 buf
->offset
[2] = buf
->stride
[0] * h
+ buf
->stride
[0] * h
/ 2;
278 buf
->stride
[2] = buf
->stride
[1];
284 gbm_bo_unmap(bo
, map_data
);
291 piglit_gbm_buf_export(struct piglit_dma_buf
*buf
)
293 struct gbm_bo
*bo
= buf
->priv
;
295 buf
->fd
= gbm_bo_get_fd(bo
);
301 piglit_gbm_buf_destroy(struct piglit_dma_buf
*buf
)
303 struct gbm_bo
*bo
= buf
->priv
;
307 #endif /* PIGLIT_HAS_GBM_BO_MAP */
310 piglit_drm_get_user_fd(void)
313 char *nodename
= getenv("WAFFLE_GBM_DEVICE");
314 if (nodename
&& strlen(nodename
))
315 fd_res
= open(nodename
, O_RDWR
);
320 static const struct piglit_drm_driver
*
321 piglit_drm_get_driver(void)
323 static struct piglit_drm_driver drv
= { /* fd */ -1 };
324 drmVersionPtr version
= NULL
;
329 drv
.fd
= piglit_drm_get_user_fd();
331 drv
.fd
= open("/dev/dri/renderD128", O_RDWR
);
334 drv
.fd
= open("/dev/dri/card0", O_RDWR
);
336 fprintf(stderr
, "error: failed to open /dev/dri/renderD128 and "
342 if (!piglit_drm_x11_authenticate(drv
.fd
))
346 version
= drmGetVersion(drv
.fd
);
348 if (!version
|| !version
->name
) {
349 fprintf(stderr
, "error: drmGetVersion() failed\n");
353 fprintf(stderr
, "version: %s %d:%d\n",
354 version
->name
, version
->version_major
, version
->version_minor
);
358 drv
.name
= strdup(version
->name
);
360 drmFreeVersion(version
);
361 fprintf(stderr
, "out of memory\n");
368 #ifdef PIGLIT_HAS_GBM_BO_MAP
370 drv
.create
= piglit_gbm_buf_create
;
371 drv
.export
= piglit_gbm_buf_export
;
372 drv
.destroy
= piglit_gbm_buf_destroy
;
376 fprintf(stderr
, "error: unrecognized DRM driver name %s\n",
381 drmFreeVersion(version
);
395 drmFreeVersion(version
);
400 piglit_drm_create_dma_buf(unsigned w
, unsigned h
, unsigned fourcc
,
401 const void *src_data
, struct piglit_dma_buf
**buf
)
403 struct piglit_dma_buf
*drm_buf
;
404 const struct piglit_drm_driver
*drv
= piglit_drm_get_driver();
409 drm_buf
= calloc(sizeof(struct piglit_dma_buf
), 1);
413 if (!drv
->create(w
, h
, fourcc
, src_data
, drm_buf
)) {
418 if (!drv
->export(drm_buf
)) {
429 piglit_drm_destroy_dma_buf(struct piglit_dma_buf
*buf
)
431 const struct piglit_drm_driver
*drv
;
436 drv
= piglit_drm_get_driver();