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-uapi/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 "wayland-drm.h"
60 dri_lookup_egl_image(__DRIscreen
*screen
, void *image
, void *data
)
62 struct gbm_dri_device
*dri
= data
;
64 if (dri
->lookup_image
== NULL
)
67 return dri
->lookup_image(screen
, image
, dri
->lookup_user_data
);
71 dri_get_buffers(__DRIdrawable
* driDrawable
,
72 int *width
, int *height
,
73 unsigned int *attachments
, int count
,
74 int *out_count
, void *data
)
76 struct gbm_dri_surface
*surf
= data
;
77 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
79 if (dri
->get_buffers
== NULL
)
82 return dri
->get_buffers(driDrawable
, width
, height
, attachments
,
83 count
, out_count
, surf
->dri_private
);
87 dri_flush_front_buffer(__DRIdrawable
* driDrawable
, void *data
)
89 struct gbm_dri_surface
*surf
= data
;
90 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
92 if (dri
->flush_front_buffer
!= NULL
)
93 dri
->flush_front_buffer(driDrawable
, surf
->dri_private
);
97 dri_get_buffers_with_format(__DRIdrawable
* driDrawable
,
98 int *width
, int *height
,
99 unsigned int *attachments
, int count
,
100 int *out_count
, void *data
)
102 struct gbm_dri_surface
*surf
= data
;
103 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
105 if (dri
->get_buffers_with_format
== NULL
)
109 dri
->get_buffers_with_format(driDrawable
, width
, height
, attachments
,
110 count
, out_count
, surf
->dri_private
);
114 dri_get_capability(void *loaderPrivate
, enum dri_loader_cap cap
)
116 /* Note: loaderPrivate is _EGLDisplay* */
118 case DRI_LOADER_CAP_FP16
:
126 image_get_buffers(__DRIdrawable
*driDrawable
,
130 uint32_t buffer_mask
,
131 struct __DRIimageList
*buffers
)
133 struct gbm_dri_surface
*surf
= loaderPrivate
;
134 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
136 if (dri
->image_get_buffers
== NULL
)
139 return dri
->image_get_buffers(driDrawable
, format
, stamp
,
140 surf
->dri_private
, buffer_mask
, buffers
);
144 swrast_get_drawable_info(__DRIdrawable
*driDrawable
,
151 struct gbm_dri_surface
*surf
= loaderPrivate
;
155 *width
= surf
->base
.width
;
156 *height
= surf
->base
.height
;
160 swrast_put_image2(__DRIdrawable
*driDrawable
,
170 struct gbm_dri_surface
*surf
= loaderPrivate
;
171 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
173 dri
->swrast_put_image2(driDrawable
,
175 width
, height
, stride
,
176 data
, surf
->dri_private
);
180 swrast_put_image(__DRIdrawable
*driDrawable
,
189 swrast_put_image2(driDrawable
, op
, x
, y
, width
, height
,
190 width
* 4, data
, loaderPrivate
);
194 swrast_get_image(__DRIdrawable
*driDrawable
,
202 struct gbm_dri_surface
*surf
= loaderPrivate
;
203 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
205 dri
->swrast_get_image(driDrawable
,
208 data
, surf
->dri_private
);
211 static const __DRIuseInvalidateExtension use_invalidate
= {
212 .base
= { __DRI_USE_INVALIDATE
, 1 }
215 static const __DRIimageLookupExtension image_lookup_extension
= {
216 .base
= { __DRI_IMAGE_LOOKUP
, 1 },
218 .lookupEGLImage
= dri_lookup_egl_image
221 static const __DRIdri2LoaderExtension dri2_loader_extension
= {
222 .base
= { __DRI_DRI2_LOADER
, 4 },
224 .getBuffers
= dri_get_buffers
,
225 .flushFrontBuffer
= dri_flush_front_buffer
,
226 .getBuffersWithFormat
= dri_get_buffers_with_format
,
227 .getCapability
= dri_get_capability
,
230 static const __DRIimageLoaderExtension image_loader_extension
= {
231 .base
= { __DRI_IMAGE_LOADER
, 2 },
233 .getBuffers
= image_get_buffers
,
234 .flushFrontBuffer
= dri_flush_front_buffer
,
235 .getCapability
= dri_get_capability
,
238 static const __DRIswrastLoaderExtension swrast_loader_extension
= {
239 .base
= { __DRI_SWRAST_LOADER
, 2 },
241 .getDrawableInfo
= swrast_get_drawable_info
,
242 .putImage
= swrast_put_image
,
243 .getImage
= swrast_get_image
,
244 .putImage2
= swrast_put_image2
247 static const __DRIextension
*gbm_dri_screen_extensions
[] = {
248 &image_lookup_extension
.base
,
249 &use_invalidate
.base
,
250 &dri2_loader_extension
.base
,
251 &image_loader_extension
.base
,
252 &swrast_loader_extension
.base
,
256 struct dri_extension_match
{
263 static struct dri_extension_match dri_core_extensions
[] = {
264 { __DRI2_FLUSH
, 1, offsetof(struct gbm_dri_device
, flush
), false },
265 { __DRI_IMAGE
, 1, offsetof(struct gbm_dri_device
, image
), false },
266 { __DRI2_FENCE
, 1, offsetof(struct gbm_dri_device
, fence
), true },
269 static struct dri_extension_match gbm_dri_device_extensions
[] = {
270 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
), false },
271 { __DRI_DRI2
, 1, offsetof(struct gbm_dri_device
, dri2
), false },
274 static struct dri_extension_match gbm_swrast_device_extensions
[] = {
275 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
), false },
276 { __DRI_SWRAST
, 1, offsetof(struct gbm_dri_device
, swrast
), false },
280 dri_bind_extensions(struct gbm_dri_device
*dri
,
281 struct dri_extension_match
*matches
, size_t num_matches
,
282 const __DRIextension
**extensions
)
288 for (i
= 0; extensions
[i
]; i
++) {
289 for (j
= 0; j
< num_matches
; j
++) {
290 if (strcmp(extensions
[i
]->name
, matches
[j
].name
) == 0 &&
291 extensions
[i
]->version
>= matches
[j
].version
) {
292 field
= ((char *) dri
+ matches
[j
].offset
);
293 *(const __DRIextension
**) field
= extensions
[i
];
298 for (j
= 0; j
< num_matches
; j
++) {
299 field
= ((char *) dri
+ matches
[j
].offset
);
300 if ((*(const __DRIextension
**) field
== NULL
) && !matches
[j
].optional
) {
308 static const __DRIextension
**
309 dri_open_driver(struct gbm_dri_device
*dri
)
311 /* Temporarily work around dri driver libs that need symbols in libglapi
312 * but don't automatically link it in.
314 /* XXX: Library name differs on per platforms basis. Update this as
315 * osx/cygwin/windows/bsd gets support for GBM..
317 dlopen("libglapi.so.0", RTLD_LAZY
| RTLD_GLOBAL
);
319 static const char *search_path_vars
[] = {
320 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
321 * is recommended over GBM_DRIVERS_PATH.
324 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
325 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
327 "LIBGL_DRIVERS_PATH",
330 return loader_open_driver(dri
->driver_name
, &dri
->driver
, search_path_vars
);
334 dri_load_driver(struct gbm_dri_device
*dri
)
336 const __DRIextension
**extensions
;
338 extensions
= dri_open_driver(dri
);
342 if (!dri_bind_extensions(dri
, gbm_dri_device_extensions
,
343 ARRAY_SIZE(gbm_dri_device_extensions
),
345 dlclose(dri
->driver
);
346 fprintf(stderr
, "failed to bind extensions\n");
350 dri
->driver_extensions
= extensions
;
356 dri_load_driver_swrast(struct gbm_dri_device
*dri
)
358 const __DRIextension
**extensions
;
360 extensions
= dri_open_driver(dri
);
364 if (!dri_bind_extensions(dri
, gbm_swrast_device_extensions
,
365 ARRAY_SIZE(gbm_swrast_device_extensions
),
367 dlclose(dri
->driver
);
368 fprintf(stderr
, "failed to bind extensions\n");
372 dri
->driver_extensions
= extensions
;
378 dri_screen_create_dri2(struct gbm_dri_device
*dri
, char *driver_name
)
380 const __DRIextension
**extensions
;
383 dri
->driver_name
= driver_name
;
384 if (dri
->driver_name
== NULL
)
387 ret
= dri_load_driver(dri
);
389 fprintf(stderr
, "failed to load driver: %s\n", dri
->driver_name
);
393 dri
->loader_extensions
= gbm_dri_screen_extensions
;
395 if (dri
->dri2
== NULL
)
398 if (dri
->dri2
->base
.version
>= 4) {
399 dri
->screen
= dri
->dri2
->createNewScreen2(0, dri
->base
.fd
,
400 dri
->loader_extensions
,
401 dri
->driver_extensions
,
402 &dri
->driver_configs
, dri
);
404 dri
->screen
= dri
->dri2
->createNewScreen(0, dri
->base
.fd
,
405 dri
->loader_extensions
,
406 &dri
->driver_configs
, dri
);
408 if (dri
->screen
== NULL
)
411 extensions
= dri
->core
->getExtensions(dri
->screen
);
412 if (!dri_bind_extensions(dri
, dri_core_extensions
,
413 ARRAY_SIZE(dri_core_extensions
),
419 dri
->lookup_image
= NULL
;
420 dri
->lookup_user_data
= NULL
;
425 dri
->core
->destroyScreen(dri
->screen
);
431 dri_screen_create_swrast(struct gbm_dri_device
*dri
)
435 dri
->driver_name
= strdup("swrast");
436 if (dri
->driver_name
== NULL
)
439 ret
= dri_load_driver_swrast(dri
);
441 fprintf(stderr
, "failed to load swrast driver\n");
445 dri
->loader_extensions
= gbm_dri_screen_extensions
;
447 if (dri
->swrast
== NULL
)
450 if (dri
->swrast
->base
.version
>= 4) {
451 dri
->screen
= dri
->swrast
->createNewScreen2(0, dri
->loader_extensions
,
452 dri
->driver_extensions
,
453 &dri
->driver_configs
, dri
);
455 dri
->screen
= dri
->swrast
->createNewScreen(0, dri
->loader_extensions
,
456 &dri
->driver_configs
, dri
);
458 if (dri
->screen
== NULL
)
461 dri
->lookup_image
= NULL
;
462 dri
->lookup_user_data
= NULL
;
468 dri_screen_create(struct gbm_dri_device
*dri
)
472 driver_name
= loader_get_driver_for_fd(dri
->base
.fd
);
476 return dri_screen_create_dri2(dri
, driver_name
);
480 dri_screen_create_sw(struct gbm_dri_device
*dri
)
485 driver_name
= strdup("kms_swrast");
489 ret
= dri_screen_create_dri2(dri
, driver_name
);
493 return dri_screen_create_swrast(dri
);
496 static const struct gbm_dri_visual gbm_dri_visuals_table
[] = {
498 GBM_FORMAT_R8
, __DRI_IMAGE_FORMAT_R8
,
503 GBM_FORMAT_GR88
, __DRI_IMAGE_FORMAT_GR88
,
508 GBM_FORMAT_ARGB1555
, __DRI_IMAGE_FORMAT_ARGB1555
,
513 GBM_FORMAT_RGB565
, __DRI_IMAGE_FORMAT_RGB565
,
518 GBM_FORMAT_XRGB8888
, __DRI_IMAGE_FORMAT_XRGB8888
,
523 GBM_FORMAT_ARGB8888
, __DRI_IMAGE_FORMAT_ARGB8888
,
528 GBM_FORMAT_XBGR8888
, __DRI_IMAGE_FORMAT_XBGR8888
,
533 GBM_FORMAT_ABGR8888
, __DRI_IMAGE_FORMAT_ABGR8888
,
538 GBM_FORMAT_XRGB2101010
, __DRI_IMAGE_FORMAT_XRGB2101010
,
543 GBM_FORMAT_ARGB2101010
, __DRI_IMAGE_FORMAT_ARGB2101010
,
548 GBM_FORMAT_XBGR2101010
, __DRI_IMAGE_FORMAT_XBGR2101010
,
553 GBM_FORMAT_ABGR2101010
, __DRI_IMAGE_FORMAT_ABGR2101010
,
558 GBM_FORMAT_XBGR16161616F
, __DRI_IMAGE_FORMAT_XBGR16161616F
,
564 GBM_FORMAT_ABGR16161616F
, __DRI_IMAGE_FORMAT_ABGR16161616F
,
572 gbm_format_to_dri_format(uint32_t gbm_format
)
576 gbm_format
= gbm_format_canonicalize(gbm_format
);
577 for (i
= 0; i
< ARRAY_SIZE(gbm_dri_visuals_table
); i
++) {
578 if (gbm_dri_visuals_table
[i
].gbm_format
== gbm_format
)
579 return gbm_dri_visuals_table
[i
].dri_image_format
;
586 gbm_dri_to_gbm_format(int dri_format
)
590 for (i
= 0; i
< ARRAY_SIZE(gbm_dri_visuals_table
); i
++) {
591 if (gbm_dri_visuals_table
[i
].dri_image_format
== dri_format
)
592 return gbm_dri_visuals_table
[i
].gbm_format
;
599 gbm_dri_is_format_supported(struct gbm_device
*gbm
,
603 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
606 if ((usage
& GBM_BO_USE_CURSOR
) && (usage
& GBM_BO_USE_RENDERING
))
609 format
= gbm_format_canonicalize(format
);
610 if (gbm_format_to_dri_format(format
) == 0)
613 /* If there is no query, fall back to the small table which was originally
615 if (dri
->image
->base
.version
<= 15 || !dri
->image
->queryDmaBufModifiers
) {
617 case GBM_FORMAT_XRGB8888
:
618 case GBM_FORMAT_ARGB8888
:
619 case GBM_FORMAT_XBGR8888
:
626 /* Check if the driver returns any modifiers for this format; since linear
627 * is counted as a modifier, we will have at least one modifier for any
628 * supported format. */
629 if (!dri
->image
->queryDmaBufModifiers(dri
->screen
, format
, 0, NULL
, NULL
,
637 gbm_dri_get_format_modifier_plane_count(struct gbm_device
*gbm
,
641 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
642 uint64_t plane_count
;
644 if (dri
->image
->base
.version
< 16 ||
645 !dri
->image
->queryDmaBufFormatModifierAttribs
)
648 format
= gbm_format_canonicalize(format
);
649 if (gbm_format_to_dri_format(format
) == 0)
652 if (!dri
->image
->queryDmaBufFormatModifierAttribs(
653 dri
->screen
, format
, modifier
,
654 __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT
, &plane_count
))
661 gbm_dri_bo_write(struct gbm_bo
*_bo
, const void *buf
, size_t count
)
663 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
665 if (bo
->image
!= NULL
) {
670 memcpy(bo
->map
, buf
, count
);
676 gbm_dri_bo_get_fd(struct gbm_bo
*_bo
)
678 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
679 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
682 if (bo
->image
== NULL
)
685 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_FD
, &fd
))
692 get_number_planes(struct gbm_dri_device
*dri
, __DRIimage
*image
)
696 /* Dumb buffers are single-plane only. */
700 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NUM_PLANES
, &num_planes
);
709 gbm_dri_bo_get_planes(struct gbm_bo
*_bo
)
711 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
712 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
714 return get_number_planes(dri
, bo
->image
);
717 static union gbm_bo_handle
718 gbm_dri_bo_get_handle_for_plane(struct gbm_bo
*_bo
, int plane
)
720 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
721 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
722 union gbm_bo_handle ret
;
725 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
) {
726 /* Preserve legacy behavior if plane is 0 */
728 /* NOTE: return _bo->handle, *NOT* bo->handle which is invalid at this point */
736 if (plane
>= get_number_planes(dri
, bo
->image
)) {
741 /* dumb BOs can only utilize non-planar formats */
744 ret
.s32
= bo
->handle
;
748 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
750 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
751 dri
->image
->destroyImage(image
);
754 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
761 gbm_dri_bo_get_stride(struct gbm_bo
*_bo
, int plane
)
763 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
764 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
768 if (!dri
->image
|| dri
->image
->base
.version
< 11 || !dri
->image
->fromPlanar
) {
769 /* Preserve legacy behavior if plane is 0 */
777 if (plane
>= get_number_planes(dri
, bo
->image
)) {
782 if (bo
->image
== NULL
) {
787 image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
789 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
790 dri
->image
->destroyImage(image
);
793 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
796 return (uint32_t)stride
;
800 gbm_dri_bo_get_offset(struct gbm_bo
*_bo
, int plane
)
802 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
803 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
806 /* These error cases do not actually return an error code, as the user
807 * will also fail to obtain the handle/FD from the BO. In that case, the
808 * offset is irrelevant, as they have no buffer to offset into, so
809 * returning 0 is harmless.
811 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
)
814 if (plane
>= get_number_planes(dri
, bo
->image
))
817 /* Dumb images have no offset */
818 if (bo
->image
== NULL
) {
823 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
825 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_OFFSET
, &offset
);
826 dri
->image
->destroyImage(image
);
829 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_OFFSET
, &offset
);
832 return (uint32_t)offset
;
836 gbm_dri_bo_get_modifier(struct gbm_bo
*_bo
)
838 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
839 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
841 if (!dri
->image
|| dri
->image
->base
.version
< 14) {
843 return DRM_FORMAT_MOD_INVALID
;
846 /* Dumb buffers have no modifiers */
848 return DRM_FORMAT_MOD_LINEAR
;
852 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER
,
854 return DRM_FORMAT_MOD_INVALID
;
856 ret
= (uint64_t)mod
<< 32;
858 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER
,
860 return DRM_FORMAT_MOD_INVALID
;
862 ret
|= (uint64_t)(mod
& 0xffffffff);
868 gbm_dri_bo_destroy(struct gbm_bo
*_bo
)
870 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
871 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
872 struct drm_mode_destroy_dumb arg
;
874 if (bo
->image
!= NULL
) {
875 dri
->image
->destroyImage(bo
->image
);
877 gbm_dri_bo_unmap_dumb(bo
);
878 memset(&arg
, 0, sizeof(arg
));
879 arg
.handle
= bo
->handle
;
880 drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &arg
);
886 static struct gbm_bo
*
887 gbm_dri_bo_import(struct gbm_device
*gbm
,
888 uint32_t type
, void *buffer
, uint32_t usage
)
890 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
891 struct gbm_dri_bo
*bo
;
893 unsigned dri_use
= 0;
896 /* Required for query image WIDTH & HEIGHT */
897 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 4) {
903 #if HAVE_WAYLAND_PLATFORM
904 case GBM_BO_IMPORT_WL_BUFFER
:
906 struct wl_drm_buffer
*wb
;
913 wb
= wayland_drm_buffer_get(dri
->wl_drm
, (struct wl_resource
*) buffer
);
919 image
= dri
->image
->dupImage(wb
->driver_buffer
, NULL
);
921 /* GBM_FORMAT_* is identical to WL_DRM_FORMAT_*, so no conversion
923 gbm_format
= wb
->format
;
928 case GBM_BO_IMPORT_EGL_IMAGE
:
931 if (dri
->lookup_image
== NULL
) {
936 image
= dri
->lookup_image(dri
->screen
, buffer
, dri
->lookup_user_data
);
937 image
= dri
->image
->dupImage(image
, NULL
);
938 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
, &dri_format
);
939 gbm_format
= gbm_dri_to_gbm_format(dri_format
);
940 if (gbm_format
== 0) {
942 dri
->image
->destroyImage(image
);
948 case GBM_BO_IMPORT_FD
:
950 struct gbm_import_fd_data
*fd_data
= buffer
;
951 int stride
= fd_data
->stride
, offset
= 0;
954 /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
955 * tokens accepted by createImageFromFds, except for not supporting
956 * the sARGB format. */
957 fourcc
= gbm_format_canonicalize(fd_data
->format
);
959 image
= dri
->image
->createImageFromFds(dri
->screen
,
970 gbm_format
= fd_data
->format
;
974 case GBM_BO_IMPORT_FD_MODIFIER
:
976 struct gbm_import_fd_modifier_data
*fd_data
= buffer
;
980 /* Import with modifier requires createImageFromDmaBufs2 */
981 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 15 ||
982 dri
->image
->createImageFromDmaBufs2
== NULL
) {
987 /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
988 * tokens accepted by createImageFromDmaBufs2, except for not supporting
989 * the sARGB format. */
990 fourcc
= gbm_format_canonicalize(fd_data
->format
);
992 image
= dri
->image
->createImageFromDmaBufs2(dri
->screen
, fd_data
->width
,
993 fd_data
->height
, fourcc
,
1001 if (image
== NULL
) {
1006 gbm_format
= fourcc
;
1016 bo
= calloc(1, sizeof *bo
);
1018 dri
->image
->destroyImage(image
);
1024 if (usage
& GBM_BO_USE_SCANOUT
)
1025 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1026 if (usage
& GBM_BO_USE_CURSOR
)
1027 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1028 if (dri
->image
->base
.version
>= 2 &&
1029 !dri
->image
->validateUsage(bo
->image
, dri_use
)) {
1031 dri
->image
->destroyImage(bo
->image
);
1037 bo
->base
.format
= gbm_format
;
1039 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_WIDTH
,
1040 (int*)&bo
->base
.width
);
1041 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HEIGHT
,
1042 (int*)&bo
->base
.height
);
1043 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1044 (int*)&bo
->base
.stride
);
1045 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1046 &bo
->base
.handle
.s32
);
1051 static struct gbm_bo
*
1052 create_dumb(struct gbm_device
*gbm
,
1053 uint32_t width
, uint32_t height
,
1054 uint32_t format
, uint32_t usage
)
1056 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1057 struct drm_mode_create_dumb create_arg
;
1058 struct gbm_dri_bo
*bo
;
1059 struct drm_mode_destroy_dumb destroy_arg
;
1061 int is_cursor
, is_scanout
;
1063 is_cursor
= (usage
& GBM_BO_USE_CURSOR
) != 0 &&
1064 format
== GBM_FORMAT_ARGB8888
;
1065 is_scanout
= (usage
& GBM_BO_USE_SCANOUT
) != 0 &&
1066 (format
== GBM_FORMAT_XRGB8888
|| format
== GBM_FORMAT_XBGR8888
);
1067 if (!is_cursor
&& !is_scanout
) {
1072 bo
= calloc(1, sizeof *bo
);
1076 memset(&create_arg
, 0, sizeof(create_arg
));
1077 create_arg
.bpp
= 32;
1078 create_arg
.width
= width
;
1079 create_arg
.height
= height
;
1081 ret
= drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_CREATE_DUMB
, &create_arg
);
1086 bo
->base
.width
= width
;
1087 bo
->base
.height
= height
;
1088 bo
->base
.stride
= create_arg
.pitch
;
1089 bo
->base
.format
= format
;
1090 bo
->base
.handle
.u32
= create_arg
.handle
;
1091 bo
->handle
= create_arg
.handle
;
1092 bo
->size
= create_arg
.size
;
1094 if (gbm_dri_bo_map_dumb(bo
) == NULL
)
1100 memset(&destroy_arg
, 0, sizeof destroy_arg
);
1101 destroy_arg
.handle
= create_arg
.handle
;
1102 drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &destroy_arg
);
1109 static struct gbm_bo
*
1110 gbm_dri_bo_create(struct gbm_device
*gbm
,
1111 uint32_t width
, uint32_t height
,
1112 uint32_t format
, uint32_t usage
,
1113 const uint64_t *modifiers
,
1114 const unsigned int count
)
1116 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1117 struct gbm_dri_bo
*bo
;
1119 unsigned dri_use
= 0;
1121 /* Callers of this may specify a modifier, or a dri usage, but not both. The
1122 * newer modifier interface deprecates the older usage flags.
1124 assert(!(usage
&& count
));
1126 format
= gbm_format_canonicalize(format
);
1128 if (usage
& GBM_BO_USE_WRITE
|| dri
->image
== NULL
)
1129 return create_dumb(gbm
, width
, height
, format
, usage
);
1131 bo
= calloc(1, sizeof *bo
);
1136 bo
->base
.width
= width
;
1137 bo
->base
.height
= height
;
1138 bo
->base
.format
= format
;
1140 dri_format
= gbm_format_to_dri_format(format
);
1141 if (dri_format
== 0) {
1146 if (usage
& GBM_BO_USE_SCANOUT
)
1147 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1148 if (usage
& GBM_BO_USE_CURSOR
)
1149 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1150 if (usage
& GBM_BO_USE_LINEAR
)
1151 dri_use
|= __DRI_IMAGE_USE_LINEAR
;
1153 /* Gallium drivers requires shared in order to get the handle/stride */
1154 dri_use
|= __DRI_IMAGE_USE_SHARE
;
1157 if (!dri
->image
|| dri
->image
->base
.version
< 14 ||
1158 !dri
->image
->createImageWithModifiers
) {
1159 fprintf(stderr
, "Modifiers specified, but DRI is too old\n");
1164 /* It's acceptable to create an image with INVALID modifier in the list,
1165 * but it cannot be on the only modifier (since it will certainly fail
1166 * later). While we could easily catch this after modifier creation, doing
1167 * the check here is a convenient debug check likely pointing at whatever
1168 * interface the client is using to build its modifier list.
1170 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
) {
1171 fprintf(stderr
, "Only invalid modifier specified\n");
1177 dri
->image
->createImageWithModifiers(dri
->screen
,
1184 /* The client passed in a list of invalid modifiers */
1185 assert(gbm_dri_bo_get_modifier(&bo
->base
) != DRM_FORMAT_MOD_INVALID
);
1188 bo
->image
= dri
->image
->createImage(dri
->screen
, width
, height
,
1189 dri_format
, dri_use
, bo
);
1192 if (bo
->image
== NULL
)
1195 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1196 &bo
->base
.handle
.s32
);
1197 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1198 (int *) &bo
->base
.stride
);
1208 gbm_dri_bo_map(struct gbm_bo
*_bo
,
1209 uint32_t x
, uint32_t y
,
1210 uint32_t width
, uint32_t height
,
1211 uint32_t flags
, uint32_t *stride
, void **map_data
)
1213 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1214 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1216 /* If it's a dumb buffer, we already have a mapping */
1218 *map_data
= (char *)bo
->map
+ (bo
->base
.stride
* y
) + (x
* 4);
1219 *stride
= bo
->base
.stride
;
1223 if (!dri
->image
|| dri
->image
->base
.version
< 12 || !dri
->image
->mapImage
) {
1228 mtx_lock(&dri
->mutex
);
1230 dri
->context
= dri
->dri2
->createNewContext(dri
->screen
, NULL
,
1232 assert(dri
->context
);
1233 mtx_unlock(&dri
->mutex
);
1235 /* GBM flags and DRI flags are the same, so just pass them on */
1236 return dri
->image
->mapImage(dri
->context
, bo
->image
, x
, y
,
1237 width
, height
, flags
, (int *)stride
,
1242 gbm_dri_bo_unmap(struct gbm_bo
*_bo
, void *map_data
)
1244 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1245 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1247 /* Check if it's a dumb buffer and check the pointer is in range */
1249 assert(map_data
>= bo
->map
);
1250 assert(map_data
< (bo
->map
+ bo
->size
));
1254 if (!dri
->context
|| !dri
->image
||
1255 dri
->image
->base
.version
< 12 || !dri
->image
->unmapImage
)
1258 dri
->image
->unmapImage(dri
->context
, bo
->image
, map_data
);
1261 * Not all DRI drivers use direct maps. They may queue up DMA operations
1262 * on the mapping context. Since there is no explicit gbm flush
1263 * mechanism, we need to flush here.
1265 if (dri
->flush
->base
.version
>= 4)
1266 dri
->flush
->flush_with_flags(dri
->context
, NULL
, __DRI2_FLUSH_CONTEXT
, 0);
1270 static struct gbm_surface
*
1271 gbm_dri_surface_create(struct gbm_device
*gbm
,
1272 uint32_t width
, uint32_t height
,
1273 uint32_t format
, uint32_t flags
,
1274 const uint64_t *modifiers
, const unsigned count
)
1276 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1277 struct gbm_dri_surface
*surf
;
1280 (!dri
->image
|| dri
->image
->base
.version
< 14 ||
1281 !dri
->image
->createImageWithModifiers
)) {
1289 /* It's acceptable to create an image with INVALID modifier in the list,
1290 * but it cannot be on the only modifier (since it will certainly fail
1291 * later). While we could easily catch this after modifier creation, doing
1292 * the check here is a convenient debug check likely pointing at whatever
1293 * interface the client is using to build its modifier list.
1295 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
) {
1296 fprintf(stderr
, "Only invalid modifier specified\n");
1300 surf
= calloc(1, sizeof *surf
);
1306 surf
->base
.gbm
= gbm
;
1307 surf
->base
.width
= width
;
1308 surf
->base
.height
= height
;
1309 surf
->base
.format
= gbm_format_canonicalize(format
);
1310 surf
->base
.flags
= flags
;
1316 surf
->base
.modifiers
= calloc(count
, sizeof(*modifiers
));
1317 if (count
&& !surf
->base
.modifiers
) {
1323 /* TODO: We are deferring validation of modifiers until the image is actually
1324 * created. This deferred creation can fail due to a modifier-format
1325 * mismatch. The result is the client has a surface but no object to back it.
1327 surf
->base
.count
= count
;
1328 memcpy(surf
->base
.modifiers
, modifiers
, count
* sizeof(*modifiers
));
1334 gbm_dri_surface_destroy(struct gbm_surface
*_surf
)
1336 struct gbm_dri_surface
*surf
= gbm_dri_surface(_surf
);
1338 free(surf
->base
.modifiers
);
1343 dri_destroy(struct gbm_device
*gbm
)
1345 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1349 dri
->core
->destroyContext(dri
->context
);
1351 dri
->core
->destroyScreen(dri
->screen
);
1352 for (i
= 0; dri
->driver_configs
[i
]; i
++)
1353 free((__DRIconfig
*) dri
->driver_configs
[i
]);
1354 free(dri
->driver_configs
);
1355 dlclose(dri
->driver
);
1356 free(dri
->driver_name
);
1361 static struct gbm_device
*
1362 dri_device_create(int fd
)
1364 struct gbm_dri_device
*dri
;
1368 dri
= calloc(1, sizeof *dri
);
1373 dri
->base
.bo_create
= gbm_dri_bo_create
;
1374 dri
->base
.bo_import
= gbm_dri_bo_import
;
1375 dri
->base
.bo_map
= gbm_dri_bo_map
;
1376 dri
->base
.bo_unmap
= gbm_dri_bo_unmap
;
1377 dri
->base
.is_format_supported
= gbm_dri_is_format_supported
;
1378 dri
->base
.get_format_modifier_plane_count
=
1379 gbm_dri_get_format_modifier_plane_count
;
1380 dri
->base
.bo_write
= gbm_dri_bo_write
;
1381 dri
->base
.bo_get_fd
= gbm_dri_bo_get_fd
;
1382 dri
->base
.bo_get_planes
= gbm_dri_bo_get_planes
;
1383 dri
->base
.bo_get_handle
= gbm_dri_bo_get_handle_for_plane
;
1384 dri
->base
.bo_get_stride
= gbm_dri_bo_get_stride
;
1385 dri
->base
.bo_get_offset
= gbm_dri_bo_get_offset
;
1386 dri
->base
.bo_get_modifier
= gbm_dri_bo_get_modifier
;
1387 dri
->base
.bo_destroy
= gbm_dri_bo_destroy
;
1388 dri
->base
.destroy
= dri_destroy
;
1389 dri
->base
.surface_create
= gbm_dri_surface_create
;
1390 dri
->base
.surface_destroy
= gbm_dri_surface_destroy
;
1392 dri
->base
.name
= "drm";
1394 dri
->visual_table
= gbm_dri_visuals_table
;
1395 dri
->num_visuals
= ARRAY_SIZE(gbm_dri_visuals_table
);
1397 mtx_init(&dri
->mutex
, mtx_plain
);
1399 force_sw
= env_var_as_boolean("GBM_ALWAYS_SOFTWARE", false);
1401 ret
= dri_screen_create(dri
);
1403 ret
= dri_screen_create_sw(dri
);
1405 ret
= dri_screen_create_sw(dri
);
1419 struct gbm_backend gbm_dri_backend
= {
1420 .backend_name
= "dri",
1421 .create_device
= dri_device_create
,