2 * Copyright © 2011 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,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Benjamin Franzke <benjaminfranzke@googlemail.com>
35 #include <sys/types.h>
39 #include <GL/gl.h> /* dri_interface needs GL types */
40 #include <GL/internal/dri_interface.h>
42 #include "gbm_driint.h"
47 dri_lookup_egl_image(__DRIscreen
*screen
, void *image
, void *data
)
49 struct gbm_dri_device
*dri
= data
;
51 if (dri
->lookup_image
== NULL
)
54 return dri
->lookup_image(screen
, image
, dri
->lookup_user_data
);
57 static const __DRIuseInvalidateExtension use_invalidate
= {
58 { __DRI_USE_INVALIDATE
, 1 }
61 static const __DRIimageLookupExtension image_lookup_extension
= {
62 { __DRI_IMAGE_LOOKUP
, 1 },
66 struct dri_extension_match
{
72 static struct dri_extension_match dri_core_extensions
[] = {
73 { __DRI2_FLUSH
, 1, offsetof(struct gbm_dri_device
, flush
) },
74 { __DRI_IMAGE
, 1, offsetof(struct gbm_dri_device
, image
) },
78 static struct dri_extension_match gbm_dri_device_extensions
[] = {
79 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
) },
80 { __DRI_DRI2
, 1, offsetof(struct gbm_dri_device
, dri2
) },
85 dri_bind_extensions(struct gbm_dri_device
*dri
,
86 struct dri_extension_match
*matches
,
87 const __DRIextension
**extensions
)
92 for (i
= 0; extensions
[i
]; i
++) {
93 for (j
= 0; matches
[j
].name
; j
++) {
94 if (strcmp(extensions
[i
]->name
, matches
[j
].name
) == 0 &&
95 extensions
[i
]->version
>= matches
[j
].version
) {
96 field
= ((char *) dri
+ matches
[j
].offset
);
97 *(const __DRIextension
**) field
= extensions
[i
];
102 for (j
= 0; matches
[j
].name
; j
++) {
103 field
= ((char *) dri
+ matches
[j
].offset
);
104 if (*(const __DRIextension
**) field
== NULL
) {
113 dri_load_driver(struct gbm_dri_device
*dri
)
115 const __DRIextension
**extensions
;
116 char path
[PATH_MAX
], *search_paths
, *p
, *next
, *end
;
119 if (geteuid() == getuid()) {
120 /* don't allow setuid apps to use GBM_DRIVERS_PATH */
121 search_paths
= getenv("GBM_DRIVERS_PATH");
123 if (search_paths
== NULL
)
124 search_paths
= DEFAULT_DRIVER_DIR
;
127 end
= search_paths
+ strlen(search_paths
);
128 for (p
= search_paths
; p
< end
&& dri
->driver
== NULL
; p
= next
+ 1) {
130 next
= strchr(p
, ':');
136 snprintf(path
, sizeof path
,
137 "%.*s/tls/%s_dri.so", len
, p
, dri
->base
.driver_name
);
138 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
140 if (dri
->driver
== NULL
) {
141 snprintf(path
, sizeof path
,
142 "%.*s/%s_dri.so", len
, p
, dri
->base
.driver_name
);
143 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
144 if (dri
->driver
== NULL
)
145 fprintf(stderr
, "failed to open %s: %s\n", path
, dlerror());
149 if (dri
->driver
== NULL
) {
150 fprintf(stderr
, "gbm: failed to open any driver (search paths %s)",
155 extensions
= dlsym(dri
->driver
, __DRI_DRIVER_EXTENSIONS
);
156 if (extensions
== NULL
) {
157 fprintf(stderr
, "gbm: driver exports no extensions (%s)", dlerror());
158 dlclose(dri
->driver
);
163 if (dri_bind_extensions(dri
, gbm_dri_device_extensions
, extensions
) < 0) {
164 dlclose(dri
->driver
);
165 fprintf(stderr
, "failed to bind extensions\n");
173 dri_screen_create(struct gbm_dri_device
*dri
)
175 const __DRIextension
**extensions
;
178 dri
->base
.driver_name
= dri_fd_get_driver_name(dri
->base
.base
.fd
);
179 if (dri
->base
.driver_name
== NULL
)
182 ret
= dri_load_driver(dri
);
184 fprintf(stderr
, "failed to load driver: %s\n", dri
->base
.driver_name
);
188 dri
->extensions
[0] = &image_lookup_extension
.base
;
189 dri
->extensions
[1] = &use_invalidate
.base
;
190 dri
->extensions
[2] = NULL
;
192 if (dri
->dri2
== NULL
)
195 dri
->screen
= dri
->dri2
->createNewScreen(0, dri
->base
.base
.fd
,
197 &dri
->driver_configs
, dri
);
198 if (dri
->screen
== NULL
)
201 extensions
= dri
->core
->getExtensions(dri
->screen
);
202 if (dri_bind_extensions(dri
, dri_core_extensions
, extensions
) < 0) {
207 dri
->lookup_image
= NULL
;
208 dri
->lookup_user_data
= NULL
;
213 dri
->core
->destroyScreen(dri
->screen
);
219 gbm_dri_is_format_supported(struct gbm_device
*gbm
,
224 case GBM_BO_FORMAT_XRGB8888
:
225 case GBM_FORMAT_XRGB8888
:
227 case GBM_BO_FORMAT_ARGB8888
:
228 case GBM_FORMAT_ARGB8888
:
229 if (usage
& GBM_BO_USE_SCANOUT
)
236 if (usage
& GBM_BO_USE_CURSOR_64X64
&&
237 usage
& GBM_BO_USE_RENDERING
)
244 gbm_dri_bo_destroy(struct gbm_bo
*_bo
)
246 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
247 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
249 dri
->image
->destroyImage(bo
->image
);
254 gbm_dri_to_gbm_format(uint32_t dri_format
)
258 switch (dri_format
) {
259 case __DRI_IMAGE_FORMAT_RGB565
:
260 ret
= GBM_FORMAT_RGB565
;
262 case __DRI_IMAGE_FORMAT_XRGB8888
:
263 ret
= GBM_FORMAT_XRGB8888
;
265 case __DRI_IMAGE_FORMAT_ARGB8888
:
266 ret
= GBM_FORMAT_ARGB8888
;
268 case __DRI_IMAGE_FORMAT_ABGR8888
:
269 ret
= GBM_FORMAT_ABGR8888
;
279 static struct gbm_bo
*
280 gbm_dri_bo_create_from_egl_image(struct gbm_device
*gbm
,
281 void *egl_dpy
, void *egl_img
,
282 uint32_t width
, uint32_t height
,
285 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
286 struct gbm_dri_bo
*bo
;
288 unsigned dri_use
= 0;
292 if (dri
->lookup_image
== NULL
)
295 bo
= calloc(1, sizeof *bo
);
299 bo
->base
.base
.gbm
= gbm
;
300 bo
->base
.base
.width
= width
;
301 bo
->base
.base
.height
= height
;
303 __DRIimage
*tmp
= dri
->lookup_image(dri
->screen
, egl_img
,
304 dri
->lookup_user_data
);
306 bo
->image
= dri
->image
->dupImage(tmp
, bo
);
307 if (bo
->image
== NULL
)
310 if (usage
& GBM_BO_USE_SCANOUT
)
311 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
312 if (usage
& GBM_BO_USE_CURSOR_64X64
)
313 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
314 if (dri
->image
->base
.version
>= 2 &&
315 !dri
->image
->validateUsage(bo
->image
, dri_use
)) {
320 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
321 &bo
->base
.base
.handle
.s32
);
322 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
323 (int *) &bo
->base
.base
.pitch
);
324 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_FORMAT
,
327 bo
->base
.base
.format
= gbm_dri_to_gbm_format(dri_format
);
329 return &bo
->base
.base
;
332 static struct gbm_bo
*
333 gbm_dri_bo_create(struct gbm_device
*gbm
,
334 uint32_t width
, uint32_t height
,
335 uint32_t format
, uint32_t usage
)
337 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
338 struct gbm_dri_bo
*bo
;
340 unsigned dri_use
= 0;
342 bo
= calloc(1, sizeof *bo
);
346 bo
->base
.base
.gbm
= gbm
;
347 bo
->base
.base
.width
= width
;
348 bo
->base
.base
.height
= height
;
351 case GBM_FORMAT_RGB565
:
352 dri_format
=__DRI_IMAGE_FORMAT_RGB565
;
354 case GBM_FORMAT_XRGB8888
:
355 case GBM_BO_FORMAT_XRGB8888
:
356 dri_format
= __DRI_IMAGE_FORMAT_XRGB8888
;
358 case GBM_FORMAT_ARGB8888
:
359 case GBM_BO_FORMAT_ARGB8888
:
360 dri_format
= __DRI_IMAGE_FORMAT_ARGB8888
;
362 case GBM_FORMAT_ABGR8888
:
363 dri_format
= __DRI_IMAGE_FORMAT_ABGR8888
;
369 if (usage
& GBM_BO_USE_SCANOUT
)
370 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
371 if (usage
& GBM_BO_USE_CURSOR_64X64
)
372 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
375 dri
->image
->createImage(dri
->screen
,
379 if (bo
->image
== NULL
)
382 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
383 &bo
->base
.base
.handle
.s32
);
384 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
385 (int *) &bo
->base
.base
.pitch
);
387 return &bo
->base
.base
;
390 static struct gbm_surface
*
391 gbm_dri_surface_create(struct gbm_device
*gbm
,
392 uint32_t width
, uint32_t height
,
393 uint32_t format
, uint32_t flags
)
395 struct gbm_dri_surface
*surf
;
397 surf
= calloc(1, sizeof *surf
);
401 surf
->base
.gbm
= gbm
;
402 surf
->base
.width
= width
;
403 surf
->base
.height
= height
;
404 surf
->base
.format
= format
;
405 surf
->base
.flags
= flags
;
411 gbm_dri_surface_destroy(struct gbm_surface
*_surf
)
413 struct gbm_dri_surface
*surf
= gbm_dri_surface(_surf
);
419 dri_destroy(struct gbm_device
*gbm
)
421 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
423 dri
->core
->destroyScreen(dri
->screen
);
424 free(dri
->driver_configs
);
425 dlclose(dri
->driver
);
426 free(dri
->base
.driver_name
);
431 static struct gbm_device
*
432 dri_device_create(int fd
)
434 struct gbm_dri_device
*dri
;
437 dri
= calloc(1, sizeof *dri
);
439 dri
->base
.base
.fd
= fd
;
440 dri
->base
.base
.bo_create
= gbm_dri_bo_create
;
441 dri
->base
.base
.bo_create_from_egl_image
= gbm_dri_bo_create_from_egl_image
;
442 dri
->base
.base
.is_format_supported
= gbm_dri_is_format_supported
;
443 dri
->base
.base
.bo_destroy
= gbm_dri_bo_destroy
;
444 dri
->base
.base
.destroy
= dri_destroy
;
445 dri
->base
.base
.surface_create
= gbm_dri_surface_create
;
446 dri
->base
.base
.surface_destroy
= gbm_dri_surface_destroy
;
448 dri
->base
.type
= GBM_DRM_DRIVER_TYPE_DRI
;
449 dri
->base
.base
.name
= "drm";
451 ret
= dri_screen_create(dri
);
457 return &dri
->base
.base
;
460 struct gbm_backend gbm_dri_backend
= {
461 .backend_name
= "dri",
462 .create_device
= dri_device_create
,