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>
38 #include <sys/types.h>
42 #include <drm_fourcc.h>
44 #include <GL/gl.h> /* dri_interface needs GL types */
45 #include <GL/internal/dri_interface.h>
47 #include "gbm_driint.h"
51 #include "util/debug.h"
52 #include "util/macros.h"
54 /* For importing wl_buffer */
55 #if HAVE_WAYLAND_PLATFORM
56 #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
59 #ifndef DRM_FORMAT_MOD_INVALID
60 #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
63 #ifndef DRM_FORMAT_MOD_LINEAR
64 #define DRM_FORMAT_MOD_LINEAR 0
68 dri_lookup_egl_image(__DRIscreen
*screen
, void *image
, void *data
)
70 struct gbm_dri_device
*dri
= data
;
72 if (dri
->lookup_image
== NULL
)
75 return dri
->lookup_image(screen
, image
, dri
->lookup_user_data
);
79 dri_get_buffers(__DRIdrawable
* driDrawable
,
80 int *width
, int *height
,
81 unsigned int *attachments
, int count
,
82 int *out_count
, void *data
)
84 struct gbm_dri_surface
*surf
= data
;
85 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
87 if (dri
->get_buffers
== NULL
)
90 return dri
->get_buffers(driDrawable
, width
, height
, attachments
,
91 count
, out_count
, surf
->dri_private
);
95 dri_flush_front_buffer(__DRIdrawable
* driDrawable
, void *data
)
97 struct gbm_dri_surface
*surf
= data
;
98 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
100 if (dri
->flush_front_buffer
!= NULL
)
101 dri
->flush_front_buffer(driDrawable
, surf
->dri_private
);
105 dri_get_buffers_with_format(__DRIdrawable
* driDrawable
,
106 int *width
, int *height
,
107 unsigned int *attachments
, int count
,
108 int *out_count
, void *data
)
110 struct gbm_dri_surface
*surf
= data
;
111 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
113 if (dri
->get_buffers_with_format
== NULL
)
117 dri
->get_buffers_with_format(driDrawable
, width
, height
, attachments
,
118 count
, out_count
, surf
->dri_private
);
122 image_get_buffers(__DRIdrawable
*driDrawable
,
126 uint32_t buffer_mask
,
127 struct __DRIimageList
*buffers
)
129 struct gbm_dri_surface
*surf
= loaderPrivate
;
130 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
132 if (dri
->image_get_buffers
== NULL
)
135 return dri
->image_get_buffers(driDrawable
, format
, stamp
,
136 surf
->dri_private
, buffer_mask
, buffers
);
140 swrast_get_drawable_info(__DRIdrawable
*driDrawable
,
147 struct gbm_dri_surface
*surf
= loaderPrivate
;
151 *width
= surf
->base
.width
;
152 *height
= surf
->base
.height
;
156 swrast_put_image2(__DRIdrawable
*driDrawable
,
166 struct gbm_dri_surface
*surf
= loaderPrivate
;
167 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
169 dri
->swrast_put_image2(driDrawable
,
171 width
, height
, stride
,
172 data
, surf
->dri_private
);
176 swrast_put_image(__DRIdrawable
*driDrawable
,
185 return swrast_put_image2(driDrawable
, op
, x
, y
, width
, height
,
186 width
* 4, data
, loaderPrivate
);
190 swrast_get_image(__DRIdrawable
*driDrawable
,
198 struct gbm_dri_surface
*surf
= loaderPrivate
;
199 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
201 dri
->swrast_get_image(driDrawable
,
204 data
, surf
->dri_private
);
207 static const __DRIuseInvalidateExtension use_invalidate
= {
208 .base
= { __DRI_USE_INVALIDATE
, 1 }
211 static const __DRIimageLookupExtension image_lookup_extension
= {
212 .base
= { __DRI_IMAGE_LOOKUP
, 1 },
214 .lookupEGLImage
= dri_lookup_egl_image
217 static const __DRIdri2LoaderExtension dri2_loader_extension
= {
218 .base
= { __DRI_DRI2_LOADER
, 3 },
220 .getBuffers
= dri_get_buffers
,
221 .flushFrontBuffer
= dri_flush_front_buffer
,
222 .getBuffersWithFormat
= dri_get_buffers_with_format
,
225 static const __DRIimageLoaderExtension image_loader_extension
= {
226 .base
= { __DRI_IMAGE_LOADER
, 1 },
228 .getBuffers
= image_get_buffers
,
229 .flushFrontBuffer
= dri_flush_front_buffer
,
232 static const __DRIswrastLoaderExtension swrast_loader_extension
= {
233 .base
= { __DRI_SWRAST_LOADER
, 2 },
235 .getDrawableInfo
= swrast_get_drawable_info
,
236 .putImage
= swrast_put_image
,
237 .getImage
= swrast_get_image
,
238 .putImage2
= swrast_put_image2
241 static const __DRIextension
*gbm_dri_screen_extensions
[] = {
242 &image_lookup_extension
.base
,
243 &use_invalidate
.base
,
244 &dri2_loader_extension
.base
,
245 &image_loader_extension
.base
,
246 &swrast_loader_extension
.base
,
250 struct dri_extension_match
{
257 static struct dri_extension_match dri_core_extensions
[] = {
258 { __DRI2_FLUSH
, 1, offsetof(struct gbm_dri_device
, flush
) },
259 { __DRI_IMAGE
, 1, offsetof(struct gbm_dri_device
, image
) },
260 { __DRI2_FENCE
, 1, offsetof(struct gbm_dri_device
, fence
), 1 },
264 static struct dri_extension_match gbm_dri_device_extensions
[] = {
265 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
) },
266 { __DRI_DRI2
, 1, offsetof(struct gbm_dri_device
, dri2
) },
270 static struct dri_extension_match gbm_swrast_device_extensions
[] = {
271 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
), },
272 { __DRI_SWRAST
, 1, offsetof(struct gbm_dri_device
, swrast
) },
277 dri_bind_extensions(struct gbm_dri_device
*dri
,
278 struct dri_extension_match
*matches
,
279 const __DRIextension
**extensions
)
284 for (i
= 0; extensions
[i
]; i
++) {
285 for (j
= 0; matches
[j
].name
; j
++) {
286 if (strcmp(extensions
[i
]->name
, matches
[j
].name
) == 0 &&
287 extensions
[i
]->version
>= matches
[j
].version
) {
288 field
= ((char *) dri
+ matches
[j
].offset
);
289 *(const __DRIextension
**) field
= extensions
[i
];
294 for (j
= 0; matches
[j
].name
; j
++) {
295 field
= ((char *) dri
+ matches
[j
].offset
);
296 if ((*(const __DRIextension
**) field
== NULL
) && !matches
[j
].optional
) {
304 static const __DRIextension
**
305 dri_open_driver(struct gbm_dri_device
*dri
)
307 const __DRIextension
**extensions
= NULL
;
308 char path
[PATH_MAX
], *search_paths
, *p
, *next
, *end
;
309 char *get_extensions_name
;
312 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */
313 if (geteuid() == getuid()) {
314 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
315 * is recommended over GBM_DRIVERS_PATH.
317 search_paths
= getenv("GBM_DRIVERS_PATH");
319 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
320 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
322 if (search_paths
== NULL
) {
323 search_paths
= getenv("LIBGL_DRIVERS_PATH");
326 if (search_paths
== NULL
)
327 search_paths
= DEFAULT_DRIVER_DIR
;
329 /* Temporarily work around dri driver libs that need symbols in libglapi
330 * but don't automatically link it in.
332 /* XXX: Library name differs on per platforms basis. Update this as
333 * osx/cygwin/windows/bsd gets support for GBM..
335 dlopen("libglapi.so.0", RTLD_LAZY
| RTLD_GLOBAL
);
338 end
= search_paths
+ strlen(search_paths
);
339 for (p
= search_paths
; p
< end
&& dri
->driver
== NULL
; p
= next
+ 1) {
341 next
= strchr(p
, ':');
347 snprintf(path
, sizeof path
,
348 "%.*s/tls/%s_dri.so", len
, p
, dri
->driver_name
);
349 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
351 if (dri
->driver
== NULL
) {
352 snprintf(path
, sizeof path
,
353 "%.*s/%s_dri.so", len
, p
, dri
->driver_name
);
354 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
356 /* not need continue to loop all paths once the driver is found */
357 if (dri
->driver
!= NULL
)
361 if (dri
->driver
== NULL
) {
362 fprintf(stderr
, "gbm: failed to open any driver (search paths %s)\n",
364 fprintf(stderr
, "gbm: Last dlopen error: %s\n", dlerror());
368 get_extensions_name
= loader_get_extensions_name(dri
->driver_name
);
369 if (get_extensions_name
) {
370 const __DRIextension
**(*get_extensions
)(void);
372 get_extensions
= dlsym(dri
->driver
, get_extensions_name
);
373 free(get_extensions_name
);
376 extensions
= get_extensions();
380 extensions
= dlsym(dri
->driver
, __DRI_DRIVER_EXTENSIONS
);
381 if (extensions
== NULL
) {
382 fprintf(stderr
, "gbm: driver exports no extensions (%s)", dlerror());
383 dlclose(dri
->driver
);
390 dri_load_driver(struct gbm_dri_device
*dri
)
392 const __DRIextension
**extensions
;
394 extensions
= dri_open_driver(dri
);
398 if (dri_bind_extensions(dri
, gbm_dri_device_extensions
, extensions
) < 0) {
399 dlclose(dri
->driver
);
400 fprintf(stderr
, "failed to bind extensions\n");
404 dri
->driver_extensions
= extensions
;
410 dri_load_driver_swrast(struct gbm_dri_device
*dri
)
412 const __DRIextension
**extensions
;
414 extensions
= dri_open_driver(dri
);
418 if (dri_bind_extensions(dri
, gbm_swrast_device_extensions
, extensions
) < 0) {
419 dlclose(dri
->driver
);
420 fprintf(stderr
, "failed to bind extensions\n");
424 dri
->driver_extensions
= extensions
;
430 dri_screen_create_dri2(struct gbm_dri_device
*dri
, char *driver_name
)
432 const __DRIextension
**extensions
;
435 dri
->driver_name
= driver_name
;
436 if (dri
->driver_name
== NULL
)
439 ret
= dri_load_driver(dri
);
441 fprintf(stderr
, "failed to load driver: %s\n", dri
->driver_name
);
445 dri
->loader_extensions
= gbm_dri_screen_extensions
;
447 if (dri
->dri2
== NULL
)
450 if (dri
->dri2
->base
.version
>= 4) {
451 dri
->screen
= dri
->dri2
->createNewScreen2(0, dri
->base
.fd
,
452 dri
->loader_extensions
,
453 dri
->driver_extensions
,
454 &dri
->driver_configs
, dri
);
456 dri
->screen
= dri
->dri2
->createNewScreen(0, dri
->base
.fd
,
457 dri
->loader_extensions
,
458 &dri
->driver_configs
, dri
);
460 if (dri
->screen
== NULL
)
463 extensions
= dri
->core
->getExtensions(dri
->screen
);
464 if (dri_bind_extensions(dri
, dri_core_extensions
, extensions
) < 0) {
469 dri
->lookup_image
= NULL
;
470 dri
->lookup_user_data
= NULL
;
475 dri
->core
->destroyScreen(dri
->screen
);
481 dri_screen_create_swrast(struct gbm_dri_device
*dri
)
485 dri
->driver_name
= strdup("swrast");
486 if (dri
->driver_name
== NULL
)
489 ret
= dri_load_driver_swrast(dri
);
491 fprintf(stderr
, "failed to load swrast driver\n");
495 dri
->loader_extensions
= gbm_dri_screen_extensions
;
497 if (dri
->swrast
== NULL
)
500 if (dri
->swrast
->base
.version
>= 4) {
501 dri
->screen
= dri
->swrast
->createNewScreen2(0, dri
->loader_extensions
,
502 dri
->driver_extensions
,
503 &dri
->driver_configs
, dri
);
505 dri
->screen
= dri
->swrast
->createNewScreen(0, dri
->loader_extensions
,
506 &dri
->driver_configs
, dri
);
508 if (dri
->screen
== NULL
)
511 dri
->lookup_image
= NULL
;
512 dri
->lookup_user_data
= NULL
;
518 dri_screen_create(struct gbm_dri_device
*dri
)
522 driver_name
= loader_get_driver_for_fd(dri
->base
.fd
);
526 return dri_screen_create_dri2(dri
, driver_name
);
530 dri_screen_create_sw(struct gbm_dri_device
*dri
)
535 driver_name
= strdup("kms_swrast");
539 ret
= dri_screen_create_dri2(dri
, driver_name
);
543 return dri_screen_create_swrast(dri
);
546 static const struct {
548 int dri_image_format
;
549 } gbm_to_dri_image_formats
[] = {
550 { GBM_FORMAT_R8
, __DRI_IMAGE_FORMAT_R8
},
551 { GBM_FORMAT_GR88
, __DRI_IMAGE_FORMAT_GR88
},
552 { GBM_FORMAT_RGB565
, __DRI_IMAGE_FORMAT_RGB565
},
553 { GBM_FORMAT_XRGB8888
, __DRI_IMAGE_FORMAT_XRGB8888
},
554 { GBM_FORMAT_ARGB8888
, __DRI_IMAGE_FORMAT_ARGB8888
},
555 { GBM_FORMAT_XBGR8888
, __DRI_IMAGE_FORMAT_XBGR8888
},
556 { GBM_FORMAT_ABGR8888
, __DRI_IMAGE_FORMAT_ABGR8888
},
557 { GBM_FORMAT_XRGB2101010
, __DRI_IMAGE_FORMAT_XRGB2101010
},
558 { GBM_FORMAT_ARGB2101010
, __DRI_IMAGE_FORMAT_ARGB2101010
},
561 /* The two GBM_BO_FORMAT_[XA]RGB8888 formats alias the GBM_FORMAT_*
562 * formats of the same name. We want to accept them whenever someone
563 * has a GBM format, but never return them to the user. */
565 gbm_format_canonicalize(uint32_t gbm_format
)
567 switch (gbm_format
) {
568 case GBM_BO_FORMAT_XRGB8888
:
569 return GBM_FORMAT_XRGB8888
;
570 case GBM_BO_FORMAT_ARGB8888
:
571 return GBM_FORMAT_ARGB8888
;
578 gbm_format_to_dri_format(uint32_t gbm_format
)
582 gbm_format
= gbm_format_canonicalize(gbm_format
);
583 for (i
= 0; i
< ARRAY_SIZE(gbm_to_dri_image_formats
); i
++) {
584 if (gbm_to_dri_image_formats
[i
].gbm_format
== gbm_format
)
585 return gbm_to_dri_image_formats
[i
].dri_image_format
;
592 gbm_dri_to_gbm_format(int dri_format
)
596 for (i
= 0; i
< ARRAY_SIZE(gbm_to_dri_image_formats
); i
++) {
597 if (gbm_to_dri_image_formats
[i
].dri_image_format
== dri_format
)
598 return gbm_to_dri_image_formats
[i
].gbm_format
;
605 gbm_dri_is_format_supported(struct gbm_device
*gbm
,
609 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
612 if ((usage
& GBM_BO_USE_CURSOR
) && (usage
& GBM_BO_USE_RENDERING
))
615 format
= gbm_format_canonicalize(format
);
616 if (gbm_format_to_dri_format(format
) == 0)
619 /* If there is no query, fall back to the small table which was originally
621 if (dri
->image
->base
.version
<= 15 || !dri
->image
->queryDmaBufModifiers
) {
623 case GBM_FORMAT_XRGB8888
:
624 case GBM_FORMAT_ARGB8888
:
625 case GBM_FORMAT_XBGR8888
:
632 /* Check if the driver returns any modifiers for this format; since linear
633 * is counted as a modifier, we will have at least one modifier for any
634 * supported format. */
635 if (!dri
->image
->queryDmaBufModifiers(dri
->screen
, format
, 0, NULL
, NULL
,
643 gbm_dri_bo_write(struct gbm_bo
*_bo
, const void *buf
, size_t count
)
645 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
647 if (bo
->image
!= NULL
) {
652 memcpy(bo
->map
, buf
, count
);
658 gbm_dri_bo_get_fd(struct gbm_bo
*_bo
)
660 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
661 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
664 if (bo
->image
== NULL
)
667 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_FD
, &fd
))
674 get_number_planes(struct gbm_dri_device
*dri
, __DRIimage
*image
)
678 /* Dumb buffers are single-plane only. */
682 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NUM_PLANES
, &num_planes
);
691 gbm_dri_bo_get_planes(struct gbm_bo
*_bo
)
693 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
694 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
696 return get_number_planes(dri
, bo
->image
);
699 static union gbm_bo_handle
700 gbm_dri_bo_get_handle_for_plane(struct gbm_bo
*_bo
, int plane
)
702 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
703 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
704 union gbm_bo_handle ret
;
707 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
) {
712 if (plane
>= get_number_planes(dri
, bo
->image
)) {
717 /* dumb BOs can only utilize non-planar formats */
720 ret
.s32
= bo
->handle
;
724 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
726 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
727 dri
->image
->destroyImage(image
);
730 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
737 gbm_dri_bo_get_stride(struct gbm_bo
*_bo
, int plane
)
739 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
740 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
744 if (!dri
->image
|| dri
->image
->base
.version
< 11 || !dri
->image
->fromPlanar
) {
745 /* Preserve legacy behavior if plane is 0 */
753 if (plane
>= get_number_planes(dri
, bo
->image
)) {
758 if (bo
->image
== NULL
) {
763 image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
765 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
766 dri
->image
->destroyImage(image
);
769 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
772 return (uint32_t)stride
;
776 gbm_dri_bo_get_offset(struct gbm_bo
*_bo
, int plane
)
778 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
779 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
782 /* These error cases do not actually return an error code, as the user
783 * will also fail to obtain the handle/FD from the BO. In that case, the
784 * offset is irrelevant, as they have no buffer to offset into, so
785 * returning 0 is harmless.
787 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
)
790 if (plane
>= get_number_planes(dri
, bo
->image
))
793 /* Dumb images have no offset */
794 if (bo
->image
== NULL
) {
799 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
801 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_OFFSET
, &offset
);
802 dri
->image
->destroyImage(image
);
804 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_OFFSET
, &offset
);
807 return (uint32_t)offset
;
811 gbm_dri_bo_get_modifier(struct gbm_bo
*_bo
)
813 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
814 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
816 if (!dri
->image
|| dri
->image
->base
.version
< 14) {
818 return DRM_FORMAT_MOD_INVALID
;
821 /* Dumb buffers have no modifiers */
823 return DRM_FORMAT_MOD_LINEAR
;
827 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER
,
829 return DRM_FORMAT_MOD_INVALID
;
831 ret
= (uint64_t)mod
<< 32;
833 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER
,
835 return DRM_FORMAT_MOD_INVALID
;
837 ret
|= (uint64_t)(mod
& 0xffffffff);
843 gbm_dri_bo_destroy(struct gbm_bo
*_bo
)
845 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
846 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
847 struct drm_mode_destroy_dumb arg
;
849 if (bo
->image
!= NULL
) {
850 dri
->image
->destroyImage(bo
->image
);
852 gbm_dri_bo_unmap_dumb(bo
);
853 memset(&arg
, 0, sizeof(arg
));
854 arg
.handle
= bo
->handle
;
855 drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &arg
);
861 static struct gbm_bo
*
862 gbm_dri_bo_import(struct gbm_device
*gbm
,
863 uint32_t type
, void *buffer
, uint32_t usage
)
865 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
866 struct gbm_dri_bo
*bo
;
868 unsigned dri_use
= 0;
871 /* Required for query image WIDTH & HEIGHT */
872 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 4) {
878 #if HAVE_WAYLAND_PLATFORM
879 case GBM_BO_IMPORT_WL_BUFFER
:
881 struct wl_drm_buffer
*wb
;
888 wb
= wayland_drm_buffer_get(dri
->wl_drm
, (struct wl_resource
*) buffer
);
894 image
= dri
->image
->dupImage(wb
->driver_buffer
, NULL
);
896 /* GBM_FORMAT_* is identical to WL_DRM_FORMAT_*, so no conversion
898 gbm_format
= wb
->format
;
903 case GBM_BO_IMPORT_EGL_IMAGE
:
906 if (dri
->lookup_image
== NULL
) {
911 image
= dri
->lookup_image(dri
->screen
, buffer
, dri
->lookup_user_data
);
912 image
= dri
->image
->dupImage(image
, NULL
);
913 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
, &dri_format
);
914 gbm_format
= gbm_dri_to_gbm_format(dri_format
);
915 if (gbm_format
== 0) {
917 dri
->image
->destroyImage(image
);
923 case GBM_BO_IMPORT_FD
:
925 struct gbm_import_fd_data
*fd_data
= buffer
;
926 int stride
= fd_data
->stride
, offset
= 0;
929 /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
930 * tokens accepted by createImageFromFds, except for not supporting
931 * the sARGB format. */
932 fourcc
= gbm_format_canonicalize(fd_data
->format
);
934 image
= dri
->image
->createImageFromFds(dri
->screen
,
945 gbm_format
= fd_data
->format
;
949 case GBM_BO_IMPORT_FD_MODIFIER
:
951 struct gbm_import_fd_modifier_data
*fd_data
= buffer
;
955 /* Import with modifier requires createImageFromDmaBufs2 */
956 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 15 ||
957 dri
->image
->createImageFromDmaBufs2
== NULL
) {
962 /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
963 * tokens accepted by createImageFromDmaBufs2, except for not supporting
964 * the sARGB format. */
965 fourcc
= gbm_format_canonicalize(fd_data
->format
);
967 image
= dri
->image
->createImageFromDmaBufs2(dri
->screen
, fd_data
->width
,
968 fd_data
->height
, fourcc
,
991 bo
= calloc(1, sizeof *bo
);
993 dri
->image
->destroyImage(image
);
999 if (usage
& GBM_BO_USE_SCANOUT
)
1000 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1001 if (usage
& GBM_BO_USE_CURSOR
)
1002 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1003 if (dri
->image
->base
.version
>= 2 &&
1004 !dri
->image
->validateUsage(bo
->image
, dri_use
)) {
1006 dri
->image
->destroyImage(bo
->image
);
1012 bo
->base
.format
= gbm_format
;
1014 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_WIDTH
,
1015 (int*)&bo
->base
.width
);
1016 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HEIGHT
,
1017 (int*)&bo
->base
.height
);
1018 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1019 (int*)&bo
->base
.stride
);
1020 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1021 &bo
->base
.handle
.s32
);
1026 static struct gbm_bo
*
1027 create_dumb(struct gbm_device
*gbm
,
1028 uint32_t width
, uint32_t height
,
1029 uint32_t format
, uint32_t usage
)
1031 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1032 struct drm_mode_create_dumb create_arg
;
1033 struct gbm_dri_bo
*bo
;
1034 struct drm_mode_destroy_dumb destroy_arg
;
1036 int is_cursor
, is_scanout
;
1038 is_cursor
= (usage
& GBM_BO_USE_CURSOR
) != 0 &&
1039 format
== GBM_FORMAT_ARGB8888
;
1040 is_scanout
= (usage
& GBM_BO_USE_SCANOUT
) != 0 &&
1041 (format
== GBM_FORMAT_XRGB8888
|| format
== GBM_FORMAT_XBGR8888
);
1042 if (!is_cursor
&& !is_scanout
) {
1047 bo
= calloc(1, sizeof *bo
);
1051 memset(&create_arg
, 0, sizeof(create_arg
));
1052 create_arg
.bpp
= 32;
1053 create_arg
.width
= width
;
1054 create_arg
.height
= height
;
1056 ret
= drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_CREATE_DUMB
, &create_arg
);
1061 bo
->base
.width
= width
;
1062 bo
->base
.height
= height
;
1063 bo
->base
.stride
= create_arg
.pitch
;
1064 bo
->base
.format
= format
;
1065 bo
->base
.handle
.u32
= create_arg
.handle
;
1066 bo
->handle
= create_arg
.handle
;
1067 bo
->size
= create_arg
.size
;
1069 if (gbm_dri_bo_map_dumb(bo
) == NULL
)
1075 memset(&destroy_arg
, 0, sizeof destroy_arg
);
1076 destroy_arg
.handle
= create_arg
.handle
;
1077 drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &destroy_arg
);
1084 static struct gbm_bo
*
1085 gbm_dri_bo_create(struct gbm_device
*gbm
,
1086 uint32_t width
, uint32_t height
,
1087 uint32_t format
, uint32_t usage
,
1088 const uint64_t *modifiers
,
1089 const unsigned int count
)
1091 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1092 struct gbm_dri_bo
*bo
;
1094 unsigned dri_use
= 0;
1096 /* Callers of this may specify a modifier, or a dri usage, but not both. The
1097 * newer modifier interface deprecates the older usage flags.
1099 assert(!(usage
&& count
));
1101 format
= gbm_format_canonicalize(format
);
1103 if (usage
& GBM_BO_USE_WRITE
|| dri
->image
== NULL
)
1104 return create_dumb(gbm
, width
, height
, format
, usage
);
1106 bo
= calloc(1, sizeof *bo
);
1111 bo
->base
.width
= width
;
1112 bo
->base
.height
= height
;
1113 bo
->base
.format
= format
;
1115 dri_format
= gbm_format_to_dri_format(format
);
1116 if (dri_format
== 0) {
1121 if (usage
& GBM_BO_USE_SCANOUT
)
1122 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1123 if (usage
& GBM_BO_USE_CURSOR
)
1124 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1125 if (usage
& GBM_BO_USE_LINEAR
)
1126 dri_use
|= __DRI_IMAGE_USE_LINEAR
;
1128 /* Gallium drivers requires shared in order to get the handle/stride */
1129 dri_use
|= __DRI_IMAGE_USE_SHARE
;
1132 if (!dri
->image
|| dri
->image
->base
.version
< 14 ||
1133 !dri
->image
->createImageWithModifiers
) {
1134 fprintf(stderr
, "Modifiers specified, but DRI is too old\n");
1139 /* It's acceptable to create an image with INVALID modifier in the list,
1140 * but it cannot be on the only modifier (since it will certainly fail
1141 * later). While we could easily catch this after modifier creation, doing
1142 * the check here is a convenient debug check likely pointing at whatever
1143 * interface the client is using to build its modifier list.
1145 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
) {
1146 fprintf(stderr
, "Only invalid modifier specified\n");
1152 dri
->image
->createImageWithModifiers(dri
->screen
,
1159 /* The client passed in a list of invalid modifiers */
1160 assert(gbm_dri_bo_get_modifier(&bo
->base
) != DRM_FORMAT_MOD_INVALID
);
1163 bo
->image
= dri
->image
->createImage(dri
->screen
, width
, height
,
1164 dri_format
, dri_use
, bo
);
1167 if (bo
->image
== NULL
)
1170 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1171 &bo
->base
.handle
.s32
);
1172 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1173 (int *) &bo
->base
.stride
);
1183 gbm_dri_bo_map(struct gbm_bo
*_bo
,
1184 uint32_t x
, uint32_t y
,
1185 uint32_t width
, uint32_t height
,
1186 uint32_t flags
, uint32_t *stride
, void **map_data
)
1188 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1189 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1191 /* If it's a dumb buffer, we already have a mapping */
1193 *map_data
= (char *)bo
->map
+ (bo
->base
.stride
* y
) + (x
* 4);
1194 *stride
= bo
->base
.stride
;
1198 if (!dri
->image
|| dri
->image
->base
.version
< 12 || !dri
->image
->mapImage
) {
1203 mtx_lock(&dri
->mutex
);
1205 dri
->context
= dri
->dri2
->createNewContext(dri
->screen
, NULL
,
1207 assert(dri
->context
);
1208 mtx_unlock(&dri
->mutex
);
1210 /* GBM flags and DRI flags are the same, so just pass them on */
1211 return dri
->image
->mapImage(dri
->context
, bo
->image
, x
, y
,
1212 width
, height
, flags
, (int *)stride
,
1217 gbm_dri_bo_unmap(struct gbm_bo
*_bo
, void *map_data
)
1219 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1220 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1222 /* Check if it's a dumb buffer and check the pointer is in range */
1224 assert(map_data
>= bo
->map
);
1225 assert(map_data
< (bo
->map
+ bo
->size
));
1229 if (!dri
->context
|| !dri
->image
||
1230 dri
->image
->base
.version
< 12 || !dri
->image
->unmapImage
)
1233 dri
->image
->unmapImage(dri
->context
, bo
->image
, map_data
);
1236 * Not all DRI drivers use direct maps. They may queue up DMA operations
1237 * on the mapping context. Since there is no explicit gbm flush
1238 * mechanism, we need to flush here.
1240 if (dri
->flush
->base
.version
>= 4)
1241 dri
->flush
->flush_with_flags(dri
->context
, NULL
, __DRI2_FLUSH_CONTEXT
, 0);
1245 static struct gbm_surface
*
1246 gbm_dri_surface_create(struct gbm_device
*gbm
,
1247 uint32_t width
, uint32_t height
,
1248 uint32_t format
, uint32_t flags
,
1249 const uint64_t *modifiers
, const unsigned count
)
1251 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1252 struct gbm_dri_surface
*surf
;
1255 (!dri
->image
|| dri
->image
->base
.version
< 14 ||
1256 !dri
->image
->createImageWithModifiers
)) {
1264 /* It's acceptable to create an image with INVALID modifier in the list,
1265 * but it cannot be on the only modifier (since it will certainly fail
1266 * later). While we could easily catch this after modifier creation, doing
1267 * the check here is a convenient debug check likely pointing at whatever
1268 * interface the client is using to build its modifier list.
1270 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
) {
1271 fprintf(stderr
, "Only invalid modifier specified\n");
1275 surf
= calloc(1, sizeof *surf
);
1281 surf
->base
.gbm
= gbm
;
1282 surf
->base
.width
= width
;
1283 surf
->base
.height
= height
;
1284 surf
->base
.format
= gbm_format_canonicalize(format
);
1285 surf
->base
.flags
= flags
;
1291 surf
->base
.modifiers
= calloc(count
, sizeof(*modifiers
));
1292 if (count
&& !surf
->base
.modifiers
) {
1298 /* TODO: We are deferring validation of modifiers until the image is actually
1299 * created. This deferred creation can fail due to a modifier-format
1300 * mismatch. The result is the client has a surface but no object to back it.
1302 surf
->base
.count
= count
;
1303 memcpy(surf
->base
.modifiers
, modifiers
, count
* sizeof(*modifiers
));
1309 gbm_dri_surface_destroy(struct gbm_surface
*_surf
)
1311 struct gbm_dri_surface
*surf
= gbm_dri_surface(_surf
);
1313 free(surf
->base
.modifiers
);
1318 dri_destroy(struct gbm_device
*gbm
)
1320 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1324 dri
->core
->destroyContext(dri
->context
);
1326 dri
->core
->destroyScreen(dri
->screen
);
1327 for (i
= 0; dri
->driver_configs
[i
]; i
++)
1328 free((__DRIconfig
*) dri
->driver_configs
[i
]);
1329 free(dri
->driver_configs
);
1330 dlclose(dri
->driver
);
1331 free(dri
->driver_name
);
1336 static struct gbm_device
*
1337 dri_device_create(int fd
)
1339 struct gbm_dri_device
*dri
;
1343 dri
= calloc(1, sizeof *dri
);
1348 dri
->base
.bo_create
= gbm_dri_bo_create
;
1349 dri
->base
.bo_import
= gbm_dri_bo_import
;
1350 dri
->base
.bo_map
= gbm_dri_bo_map
;
1351 dri
->base
.bo_unmap
= gbm_dri_bo_unmap
;
1352 dri
->base
.is_format_supported
= gbm_dri_is_format_supported
;
1353 dri
->base
.bo_write
= gbm_dri_bo_write
;
1354 dri
->base
.bo_get_fd
= gbm_dri_bo_get_fd
;
1355 dri
->base
.bo_get_planes
= gbm_dri_bo_get_planes
;
1356 dri
->base
.bo_get_handle
= gbm_dri_bo_get_handle_for_plane
;
1357 dri
->base
.bo_get_stride
= gbm_dri_bo_get_stride
;
1358 dri
->base
.bo_get_offset
= gbm_dri_bo_get_offset
;
1359 dri
->base
.bo_get_modifier
= gbm_dri_bo_get_modifier
;
1360 dri
->base
.bo_destroy
= gbm_dri_bo_destroy
;
1361 dri
->base
.destroy
= dri_destroy
;
1362 dri
->base
.surface_create
= gbm_dri_surface_create
;
1363 dri
->base
.surface_destroy
= gbm_dri_surface_destroy
;
1365 dri
->base
.name
= "drm";
1367 mtx_init(&dri
->mutex
, mtx_plain
);
1369 force_sw
= env_var_as_boolean("GBM_ALWAYS_SOFTWARE", false);
1371 ret
= dri_screen_create(dri
);
1373 ret
= dri_screen_create_sw(dri
);
1375 ret
= dri_screen_create_sw(dri
);
1389 struct gbm_backend gbm_dri_backend
= {
1390 .backend_name
= "dri",
1391 .create_device
= dri_device_create
,