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"
52 /* For importing wl_buffer */
53 #if HAVE_WAYLAND_PLATFORM
54 #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
57 #ifndef DRM_FORMAT_MOD_INVALID
58 #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
61 #ifndef DRM_FORMAT_MOD_LINEAR
62 #define DRM_FORMAT_MOD_LINEAR 0
66 dri_lookup_egl_image(__DRIscreen
*screen
, void *image
, void *data
)
68 struct gbm_dri_device
*dri
= data
;
70 if (dri
->lookup_image
== NULL
)
73 return dri
->lookup_image(screen
, image
, dri
->lookup_user_data
);
77 dri_get_buffers(__DRIdrawable
* driDrawable
,
78 int *width
, int *height
,
79 unsigned int *attachments
, int count
,
80 int *out_count
, void *data
)
82 struct gbm_dri_surface
*surf
= data
;
83 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
85 if (dri
->get_buffers
== NULL
)
88 return dri
->get_buffers(driDrawable
, width
, height
, attachments
,
89 count
, out_count
, surf
->dri_private
);
93 dri_flush_front_buffer(__DRIdrawable
* driDrawable
, void *data
)
95 struct gbm_dri_surface
*surf
= data
;
96 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
98 if (dri
->flush_front_buffer
!= NULL
)
99 dri
->flush_front_buffer(driDrawable
, surf
->dri_private
);
103 dri_get_buffers_with_format(__DRIdrawable
* driDrawable
,
104 int *width
, int *height
,
105 unsigned int *attachments
, int count
,
106 int *out_count
, void *data
)
108 struct gbm_dri_surface
*surf
= data
;
109 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
111 if (dri
->get_buffers_with_format
== NULL
)
115 dri
->get_buffers_with_format(driDrawable
, width
, height
, attachments
,
116 count
, out_count
, surf
->dri_private
);
120 image_get_buffers(__DRIdrawable
*driDrawable
,
124 uint32_t buffer_mask
,
125 struct __DRIimageList
*buffers
)
127 struct gbm_dri_surface
*surf
= loaderPrivate
;
128 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
130 if (dri
->image_get_buffers
== NULL
)
133 return dri
->image_get_buffers(driDrawable
, format
, stamp
,
134 surf
->dri_private
, buffer_mask
, buffers
);
138 swrast_get_drawable_info(__DRIdrawable
*driDrawable
,
145 struct gbm_dri_surface
*surf
= loaderPrivate
;
149 *width
= surf
->base
.width
;
150 *height
= surf
->base
.height
;
154 swrast_put_image2(__DRIdrawable
*driDrawable
,
164 struct gbm_dri_surface
*surf
= loaderPrivate
;
165 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
167 dri
->swrast_put_image2(driDrawable
,
169 width
, height
, stride
,
170 data
, surf
->dri_private
);
174 swrast_put_image(__DRIdrawable
*driDrawable
,
183 return swrast_put_image2(driDrawable
, op
, x
, y
, width
, height
,
184 width
* 4, data
, loaderPrivate
);
188 swrast_get_image(__DRIdrawable
*driDrawable
,
196 struct gbm_dri_surface
*surf
= loaderPrivate
;
197 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
199 dri
->swrast_get_image(driDrawable
,
202 data
, surf
->dri_private
);
205 static const __DRIuseInvalidateExtension use_invalidate
= {
206 .base
= { __DRI_USE_INVALIDATE
, 1 }
209 static const __DRIimageLookupExtension image_lookup_extension
= {
210 .base
= { __DRI_IMAGE_LOOKUP
, 1 },
212 .lookupEGLImage
= dri_lookup_egl_image
215 static const __DRIdri2LoaderExtension dri2_loader_extension
= {
216 .base
= { __DRI_DRI2_LOADER
, 3 },
218 .getBuffers
= dri_get_buffers
,
219 .flushFrontBuffer
= dri_flush_front_buffer
,
220 .getBuffersWithFormat
= dri_get_buffers_with_format
,
223 static const __DRIimageLoaderExtension image_loader_extension
= {
224 .base
= { __DRI_IMAGE_LOADER
, 1 },
226 .getBuffers
= image_get_buffers
,
227 .flushFrontBuffer
= dri_flush_front_buffer
,
230 static const __DRIswrastLoaderExtension swrast_loader_extension
= {
231 .base
= { __DRI_SWRAST_LOADER
, 2 },
233 .getDrawableInfo
= swrast_get_drawable_info
,
234 .putImage
= swrast_put_image
,
235 .getImage
= swrast_get_image
,
236 .putImage2
= swrast_put_image2
239 static const __DRIextension
*gbm_dri_screen_extensions
[] = {
240 &image_lookup_extension
.base
,
241 &use_invalidate
.base
,
242 &dri2_loader_extension
.base
,
243 &image_loader_extension
.base
,
244 &swrast_loader_extension
.base
,
248 struct dri_extension_match
{
255 static struct dri_extension_match dri_core_extensions
[] = {
256 { __DRI2_FLUSH
, 1, offsetof(struct gbm_dri_device
, flush
) },
257 { __DRI_IMAGE
, 1, offsetof(struct gbm_dri_device
, image
) },
258 { __DRI2_FENCE
, 1, offsetof(struct gbm_dri_device
, fence
), 1 },
262 static struct dri_extension_match gbm_dri_device_extensions
[] = {
263 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
) },
264 { __DRI_DRI2
, 1, offsetof(struct gbm_dri_device
, dri2
) },
268 static struct dri_extension_match gbm_swrast_device_extensions
[] = {
269 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
), },
270 { __DRI_SWRAST
, 1, offsetof(struct gbm_dri_device
, swrast
) },
275 dri_bind_extensions(struct gbm_dri_device
*dri
,
276 struct dri_extension_match
*matches
,
277 const __DRIextension
**extensions
)
282 for (i
= 0; extensions
[i
]; i
++) {
283 for (j
= 0; matches
[j
].name
; j
++) {
284 if (strcmp(extensions
[i
]->name
, matches
[j
].name
) == 0 &&
285 extensions
[i
]->version
>= matches
[j
].version
) {
286 field
= ((char *) dri
+ matches
[j
].offset
);
287 *(const __DRIextension
**) field
= extensions
[i
];
292 for (j
= 0; matches
[j
].name
; j
++) {
293 field
= ((char *) dri
+ matches
[j
].offset
);
294 if ((*(const __DRIextension
**) field
== NULL
) && !matches
[j
].optional
) {
302 static const __DRIextension
**
303 dri_open_driver(struct gbm_dri_device
*dri
)
305 const __DRIextension
**extensions
= NULL
;
306 char path
[PATH_MAX
], *search_paths
, *p
, *next
, *end
;
307 char *get_extensions_name
;
310 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */
311 if (geteuid() == getuid()) {
312 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
313 * is recommended over GBM_DRIVERS_PATH.
315 search_paths
= getenv("GBM_DRIVERS_PATH");
317 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
318 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
320 if (search_paths
== NULL
) {
321 search_paths
= getenv("LIBGL_DRIVERS_PATH");
324 if (search_paths
== NULL
)
325 search_paths
= DEFAULT_DRIVER_DIR
;
327 /* Temporarily work around dri driver libs that need symbols in libglapi
328 * but don't automatically link it in.
330 /* XXX: Library name differs on per platforms basis. Update this as
331 * osx/cygwin/windows/bsd gets support for GBM..
333 dlopen("libglapi.so.0", RTLD_LAZY
| RTLD_GLOBAL
);
336 end
= search_paths
+ strlen(search_paths
);
337 for (p
= search_paths
; p
< end
&& dri
->driver
== NULL
; p
= next
+ 1) {
339 next
= strchr(p
, ':');
345 snprintf(path
, sizeof path
,
346 "%.*s/tls/%s_dri.so", len
, p
, dri
->driver_name
);
347 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
349 if (dri
->driver
== NULL
) {
350 snprintf(path
, sizeof path
,
351 "%.*s/%s_dri.so", len
, p
, dri
->driver_name
);
352 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
354 /* not need continue to loop all paths once the driver is found */
355 if (dri
->driver
!= NULL
)
359 snprintf(path
, sizeof path
, "%.*s/gallium_dri.so", len
, p
);
360 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
361 if (dri
->driver
== NULL
)
362 sprintf("failed to open %s: %s\n", path
, dlerror());
368 if (dri
->driver
== NULL
) {
369 fprintf(stderr
, "gbm: failed to open any driver (search paths %s)\n",
371 fprintf(stderr
, "gbm: Last dlopen error: %s\n", dlerror());
375 get_extensions_name
= loader_get_extensions_name(dri
->driver_name
);
376 if (get_extensions_name
) {
377 const __DRIextension
**(*get_extensions
)(void);
379 get_extensions
= dlsym(dri
->driver
, get_extensions_name
);
380 free(get_extensions_name
);
383 extensions
= get_extensions();
387 extensions
= dlsym(dri
->driver
, __DRI_DRIVER_EXTENSIONS
);
388 if (extensions
== NULL
) {
389 fprintf(stderr
, "gbm: driver exports no extensions (%s)", dlerror());
390 dlclose(dri
->driver
);
397 dri_load_driver(struct gbm_dri_device
*dri
)
399 const __DRIextension
**extensions
;
401 extensions
= dri_open_driver(dri
);
405 if (dri_bind_extensions(dri
, gbm_dri_device_extensions
, extensions
) < 0) {
406 dlclose(dri
->driver
);
407 fprintf(stderr
, "failed to bind extensions\n");
411 dri
->driver_extensions
= extensions
;
417 dri_load_driver_swrast(struct gbm_dri_device
*dri
)
419 const __DRIextension
**extensions
;
421 extensions
= dri_open_driver(dri
);
425 if (dri_bind_extensions(dri
, gbm_swrast_device_extensions
, extensions
) < 0) {
426 dlclose(dri
->driver
);
427 fprintf(stderr
, "failed to bind extensions\n");
431 dri
->driver_extensions
= extensions
;
437 dri_screen_create_dri2(struct gbm_dri_device
*dri
, char *driver_name
)
439 const __DRIextension
**extensions
;
442 dri
->driver_name
= driver_name
;
443 if (dri
->driver_name
== NULL
)
446 ret
= dri_load_driver(dri
);
448 fprintf(stderr
, "failed to load driver: %s\n", dri
->driver_name
);
452 dri
->loader_extensions
= gbm_dri_screen_extensions
;
454 if (dri
->dri2
== NULL
)
457 if (dri
->dri2
->base
.version
>= 4) {
458 dri
->screen
= dri
->dri2
->createNewScreen2(0, dri
->base
.fd
,
459 dri
->loader_extensions
,
460 dri
->driver_extensions
,
461 &dri
->driver_configs
, dri
);
463 dri
->screen
= dri
->dri2
->createNewScreen(0, dri
->base
.fd
,
464 dri
->loader_extensions
,
465 &dri
->driver_configs
, dri
);
467 if (dri
->screen
== NULL
)
470 extensions
= dri
->core
->getExtensions(dri
->screen
);
471 if (dri_bind_extensions(dri
, dri_core_extensions
, extensions
) < 0) {
476 dri
->lookup_image
= NULL
;
477 dri
->lookup_user_data
= NULL
;
482 dri
->core
->destroyScreen(dri
->screen
);
488 dri_screen_create_swrast(struct gbm_dri_device
*dri
)
492 dri
->driver_name
= strdup("swrast");
493 if (dri
->driver_name
== NULL
)
496 ret
= dri_load_driver_swrast(dri
);
498 fprintf(stderr
, "failed to load swrast driver\n");
502 dri
->loader_extensions
= gbm_dri_screen_extensions
;
504 if (dri
->swrast
== NULL
)
507 if (dri
->swrast
->base
.version
>= 4) {
508 dri
->screen
= dri
->swrast
->createNewScreen2(0, dri
->loader_extensions
,
509 dri
->driver_extensions
,
510 &dri
->driver_configs
, dri
);
512 dri
->screen
= dri
->swrast
->createNewScreen(0, dri
->loader_extensions
,
513 &dri
->driver_configs
, dri
);
515 if (dri
->screen
== NULL
)
518 dri
->lookup_image
= NULL
;
519 dri
->lookup_user_data
= NULL
;
525 dri_screen_create(struct gbm_dri_device
*dri
)
529 driver_name
= loader_get_driver_for_fd(dri
->base
.fd
);
533 return dri_screen_create_dri2(dri
, driver_name
);
537 dri_screen_create_sw(struct gbm_dri_device
*dri
)
542 driver_name
= strdup("kms_swrast");
546 ret
= dri_screen_create_dri2(dri
, driver_name
);
550 return dri_screen_create_swrast(dri
);
554 gbm_dri_is_format_supported(struct gbm_device
*gbm
,
559 case GBM_BO_FORMAT_XRGB8888
:
560 case GBM_FORMAT_XBGR8888
:
561 case GBM_FORMAT_XRGB8888
:
563 case GBM_BO_FORMAT_ARGB8888
:
564 case GBM_FORMAT_ARGB8888
:
565 if (usage
& GBM_BO_USE_SCANOUT
)
572 if (usage
& GBM_BO_USE_CURSOR
&&
573 usage
& GBM_BO_USE_RENDERING
)
580 gbm_dri_bo_write(struct gbm_bo
*_bo
, const void *buf
, size_t count
)
582 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
584 if (bo
->image
!= NULL
) {
589 memcpy(bo
->map
, buf
, count
);
595 gbm_dri_bo_get_fd(struct gbm_bo
*_bo
)
597 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
598 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
601 if (bo
->image
== NULL
)
604 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_FD
, &fd
))
611 get_number_planes(struct gbm_dri_device
*dri
, __DRIimage
*image
)
615 /* Dumb buffers are single-plane only. */
619 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NUM_PLANES
, &num_planes
);
628 gbm_dri_bo_get_planes(struct gbm_bo
*_bo
)
630 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
631 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
633 return get_number_planes(dri
, bo
->image
);
636 static union gbm_bo_handle
637 gbm_dri_bo_get_handle_for_plane(struct gbm_bo
*_bo
, int plane
)
639 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
640 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
641 union gbm_bo_handle ret
;
644 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
) {
649 if (plane
>= get_number_planes(dri
, bo
->image
)) {
654 /* dumb BOs can only utilize non-planar formats */
657 ret
.s32
= bo
->handle
;
661 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
663 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
664 dri
->image
->destroyImage(image
);
667 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
674 gbm_dri_bo_get_stride(struct gbm_bo
*_bo
, int plane
)
676 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
677 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
681 if (!dri
->image
|| dri
->image
->base
.version
< 11 || !dri
->image
->fromPlanar
) {
682 /* Preserve legacy behavior if plane is 0 */
690 if (plane
>= get_number_planes(dri
, bo
->image
)) {
695 if (bo
->image
== NULL
) {
700 image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
702 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
703 dri
->image
->destroyImage(image
);
706 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
709 return (uint32_t)stride
;
713 gbm_dri_bo_get_offset(struct gbm_bo
*_bo
, int plane
)
715 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
716 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
719 /* These error cases do not actually return an error code, as the user
720 * will also fail to obtain the handle/FD from the BO. In that case, the
721 * offset is irrelevant, as they have no buffer to offset into, so
722 * returning 0 is harmless.
724 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
)
727 if (plane
>= get_number_planes(dri
, bo
->image
))
730 /* Dumb images have no offset */
731 if (bo
->image
== NULL
) {
736 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
738 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_OFFSET
, &offset
);
739 dri
->image
->destroyImage(image
);
741 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_OFFSET
, &offset
);
744 return (uint32_t)offset
;
748 gbm_dri_bo_get_modifier(struct gbm_bo
*_bo
)
750 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
751 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
753 if (!dri
->image
|| dri
->image
->base
.version
< 14) {
755 return DRM_FORMAT_MOD_INVALID
;
758 /* Dumb buffers have no modifiers */
760 return DRM_FORMAT_MOD_LINEAR
;
764 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER
,
766 return DRM_FORMAT_MOD_INVALID
;
768 ret
= (uint64_t)mod
<< 32;
770 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER
,
772 return DRM_FORMAT_MOD_INVALID
;
774 ret
|= (uint64_t)(mod
& 0xffffffff);
780 gbm_dri_bo_destroy(struct gbm_bo
*_bo
)
782 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
783 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
784 struct drm_mode_destroy_dumb arg
;
786 if (bo
->image
!= NULL
) {
787 dri
->image
->destroyImage(bo
->image
);
789 gbm_dri_bo_unmap_dumb(bo
);
790 memset(&arg
, 0, sizeof(arg
));
791 arg
.handle
= bo
->handle
;
792 drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &arg
);
799 gbm_dri_to_gbm_format(uint32_t dri_format
)
803 switch (dri_format
) {
804 case __DRI_IMAGE_FORMAT_RGB565
:
805 ret
= GBM_FORMAT_RGB565
;
807 case __DRI_IMAGE_FORMAT_XRGB8888
:
808 ret
= GBM_FORMAT_XRGB8888
;
810 case __DRI_IMAGE_FORMAT_ARGB8888
:
811 ret
= GBM_FORMAT_ARGB8888
;
813 case __DRI_IMAGE_FORMAT_XBGR8888
:
814 ret
= GBM_FORMAT_XBGR8888
;
816 case __DRI_IMAGE_FORMAT_ABGR8888
:
817 ret
= GBM_FORMAT_ABGR8888
;
827 static struct gbm_bo
*
828 gbm_dri_bo_import(struct gbm_device
*gbm
,
829 uint32_t type
, void *buffer
, uint32_t usage
)
831 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
832 struct gbm_dri_bo
*bo
;
834 unsigned dri_use
= 0;
837 /* Required for query image WIDTH & HEIGHT */
838 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 4) {
844 #if HAVE_WAYLAND_PLATFORM
845 case GBM_BO_IMPORT_WL_BUFFER
:
847 struct wl_drm_buffer
*wb
;
854 wb
= wayland_drm_buffer_get(dri
->wl_drm
, (struct wl_resource
*) buffer
);
860 image
= dri
->image
->dupImage(wb
->driver_buffer
, NULL
);
862 switch (wb
->format
) {
863 case WL_DRM_FORMAT_XRGB8888
:
864 gbm_format
= GBM_FORMAT_XRGB8888
;
866 case WL_DRM_FORMAT_ARGB8888
:
867 gbm_format
= GBM_FORMAT_ARGB8888
;
869 case WL_DRM_FORMAT_RGB565
:
870 gbm_format
= GBM_FORMAT_RGB565
;
872 case WL_DRM_FORMAT_YUYV
:
873 gbm_format
= GBM_FORMAT_YUYV
;
876 dri
->image
->destroyImage(image
);
883 case GBM_BO_IMPORT_EGL_IMAGE
:
886 if (dri
->lookup_image
== NULL
) {
891 image
= dri
->lookup_image(dri
->screen
, buffer
, dri
->lookup_user_data
);
892 image
= dri
->image
->dupImage(image
, NULL
);
893 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
, &dri_format
);
894 gbm_format
= gbm_dri_to_gbm_format(dri_format
);
895 if (gbm_format
== 0) {
897 dri
->image
->destroyImage(image
);
903 case GBM_BO_IMPORT_FD
:
905 struct gbm_import_fd_data
*fd_data
= buffer
;
906 int stride
= fd_data
->stride
, offset
= 0;
909 switch (fd_data
->format
) {
910 case GBM_BO_FORMAT_XRGB8888
:
911 dri_format
= GBM_FORMAT_XRGB8888
;
913 case GBM_BO_FORMAT_ARGB8888
:
914 dri_format
= GBM_FORMAT_ARGB8888
;
917 dri_format
= fd_data
->format
;
920 image
= dri
->image
->createImageFromFds(dri
->screen
,
931 gbm_format
= fd_data
->format
;
935 case GBM_BO_IMPORT_FD_MODIFIER
:
937 struct gbm_import_fd_modifier_data
*fd_data
= buffer
;
941 /* Import with modifier requires createImageFromDmaBufs2 */
942 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 15 ||
943 dri
->image
->createImageFromDmaBufs2
== NULL
) {
948 switch(fd_data
->format
) {
949 case GBM_FORMAT_RGB565
:
950 fourcc
= __DRI_IMAGE_FOURCC_RGB565
;
952 case GBM_FORMAT_ARGB8888
:
953 case GBM_BO_FORMAT_ARGB8888
:
954 fourcc
= __DRI_IMAGE_FOURCC_ARGB8888
;
956 case GBM_FORMAT_XRGB8888
:
957 case GBM_BO_FORMAT_XRGB8888
:
958 fourcc
= __DRI_IMAGE_FOURCC_XRGB8888
;
960 case GBM_FORMAT_ABGR8888
:
961 fourcc
= __DRI_IMAGE_FOURCC_ABGR8888
;
963 case GBM_FORMAT_XBGR8888
:
964 fourcc
= __DRI_IMAGE_FOURCC_XBGR8888
;
971 image
= dri
->image
->createImageFromDmaBufs2(dri
->screen
, fd_data
->width
,
972 fd_data
->height
, fourcc
,
985 gbm_format
= fd_data
->format
;
995 bo
= calloc(1, sizeof *bo
);
997 dri
->image
->destroyImage(image
);
1003 if (usage
& GBM_BO_USE_SCANOUT
)
1004 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1005 if (usage
& GBM_BO_USE_CURSOR
)
1006 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1007 if (dri
->image
->base
.version
>= 2 &&
1008 !dri
->image
->validateUsage(bo
->image
, dri_use
)) {
1010 dri
->image
->destroyImage(bo
->image
);
1016 bo
->base
.format
= gbm_format
;
1018 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_WIDTH
,
1019 (int*)&bo
->base
.width
);
1020 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HEIGHT
,
1021 (int*)&bo
->base
.height
);
1022 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1023 (int*)&bo
->base
.stride
);
1024 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1025 &bo
->base
.handle
.s32
);
1031 is_planar_format(uint32_t format
)
1034 case GBM_FORMAT_NV12
:
1035 case GBM_FORMAT_NV21
:
1036 case GBM_FORMAT_NV16
:
1037 case GBM_FORMAT_NV61
:
1038 case GBM_FORMAT_YUV410
:
1039 case GBM_FORMAT_YVU410
:
1040 case GBM_FORMAT_YUV411
:
1041 case GBM_FORMAT_YVU411
:
1042 case GBM_FORMAT_YUV420
:
1043 case GBM_FORMAT_YVU420
:
1044 case GBM_FORMAT_YUV422
:
1045 case GBM_FORMAT_YVU422
:
1046 case GBM_FORMAT_YUV444
:
1047 case GBM_FORMAT_YVU444
:
1055 static struct gbm_bo
*
1056 create_dumb(struct gbm_device
*gbm
,
1057 uint32_t width
, uint32_t height
,
1058 uint32_t format
, uint32_t usage
)
1060 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1061 struct drm_mode_create_dumb create_arg
;
1062 struct gbm_dri_bo
*bo
;
1063 struct drm_mode_destroy_dumb destroy_arg
;
1065 int is_cursor
, is_scanout
;
1067 is_cursor
= (usage
& GBM_BO_USE_CURSOR
) != 0 &&
1068 format
== GBM_FORMAT_ARGB8888
;
1069 is_scanout
= (usage
& GBM_BO_USE_SCANOUT
) != 0 &&
1070 format
== GBM_FORMAT_XRGB8888
;
1071 if (!is_cursor
&& !is_scanout
) {
1076 if (is_planar_format(format
)) {
1081 bo
= calloc(1, sizeof *bo
);
1085 memset(&create_arg
, 0, sizeof(create_arg
));
1086 create_arg
.bpp
= 32;
1087 create_arg
.width
= width
;
1088 create_arg
.height
= height
;
1090 ret
= drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_CREATE_DUMB
, &create_arg
);
1095 bo
->base
.width
= width
;
1096 bo
->base
.height
= height
;
1097 bo
->base
.stride
= create_arg
.pitch
;
1098 bo
->base
.format
= format
;
1099 bo
->base
.handle
.u32
= create_arg
.handle
;
1100 bo
->handle
= create_arg
.handle
;
1101 bo
->size
= create_arg
.size
;
1103 if (gbm_dri_bo_map_dumb(bo
) == NULL
)
1109 memset(&destroy_arg
, 0, sizeof destroy_arg
);
1110 destroy_arg
.handle
= create_arg
.handle
;
1111 drmIoctl(dri
->base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &destroy_arg
);
1118 static struct gbm_bo
*
1119 gbm_dri_bo_create(struct gbm_device
*gbm
,
1120 uint32_t width
, uint32_t height
,
1121 uint32_t format
, uint32_t usage
,
1122 const uint64_t *modifiers
,
1123 const unsigned int count
)
1125 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1126 struct gbm_dri_bo
*bo
;
1128 unsigned dri_use
= 0;
1130 /* Callers of this may specify a modifier, or a dri usage, but not both. The
1131 * newer modifier interface deprecates the older usage flags.
1133 assert(!(usage
&& count
));
1135 if (usage
& GBM_BO_USE_WRITE
|| dri
->image
== NULL
)
1136 return create_dumb(gbm
, width
, height
, format
, usage
);
1138 bo
= calloc(1, sizeof *bo
);
1143 bo
->base
.width
= width
;
1144 bo
->base
.height
= height
;
1145 bo
->base
.format
= format
;
1149 dri_format
= __DRI_IMAGE_FORMAT_R8
;
1151 case GBM_FORMAT_GR88
:
1152 dri_format
= __DRI_IMAGE_FORMAT_GR88
;
1154 case GBM_FORMAT_RGB565
:
1155 dri_format
= __DRI_IMAGE_FORMAT_RGB565
;
1157 case GBM_FORMAT_XRGB8888
:
1158 case GBM_BO_FORMAT_XRGB8888
:
1159 dri_format
= __DRI_IMAGE_FORMAT_XRGB8888
;
1161 case GBM_FORMAT_ARGB8888
:
1162 case GBM_BO_FORMAT_ARGB8888
:
1163 dri_format
= __DRI_IMAGE_FORMAT_ARGB8888
;
1165 case GBM_FORMAT_ABGR8888
:
1166 dri_format
= __DRI_IMAGE_FORMAT_ABGR8888
;
1168 case GBM_FORMAT_XBGR8888
:
1169 dri_format
= __DRI_IMAGE_FORMAT_XBGR8888
;
1171 case GBM_FORMAT_ARGB2101010
:
1172 dri_format
= __DRI_IMAGE_FORMAT_ARGB2101010
;
1174 case GBM_FORMAT_XRGB2101010
:
1175 dri_format
= __DRI_IMAGE_FORMAT_XRGB2101010
;
1182 if (usage
& GBM_BO_USE_SCANOUT
)
1183 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1184 if (usage
& GBM_BO_USE_CURSOR
)
1185 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1186 if (usage
& GBM_BO_USE_LINEAR
)
1187 dri_use
|= __DRI_IMAGE_USE_LINEAR
;
1189 /* Gallium drivers requires shared in order to get the handle/stride */
1190 dri_use
|= __DRI_IMAGE_USE_SHARE
;
1193 if (!dri
->image
|| dri
->image
->base
.version
< 14 ||
1194 !dri
->image
->createImageWithModifiers
) {
1195 fprintf(stderr
, "Modifiers specified, but DRI is too old\n");
1200 /* It's acceptable to create an image with INVALID modifier in the list,
1201 * but it cannot be on the only modifier (since it will certainly fail
1202 * later). While we could easily catch this after modifier creation, doing
1203 * the check here is a convenient debug check likely pointing at whatever
1204 * interface the client is using to build its modifier list.
1206 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
) {
1207 fprintf(stderr
, "Only invalid modifier specified\n");
1213 dri
->image
->createImageWithModifiers(dri
->screen
,
1220 /* The client passed in a list of invalid modifiers */
1221 assert(gbm_dri_bo_get_modifier(&bo
->base
) != DRM_FORMAT_MOD_INVALID
);
1224 bo
->image
= dri
->image
->createImage(dri
->screen
, width
, height
,
1225 dri_format
, dri_use
, bo
);
1228 if (bo
->image
== NULL
)
1231 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1232 &bo
->base
.handle
.s32
);
1233 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1234 (int *) &bo
->base
.stride
);
1244 gbm_dri_bo_map(struct gbm_bo
*_bo
,
1245 uint32_t x
, uint32_t y
,
1246 uint32_t width
, uint32_t height
,
1247 uint32_t flags
, uint32_t *stride
, void **map_data
)
1249 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1250 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1252 /* If it's a dumb buffer, we already have a mapping */
1254 *map_data
= (char *)bo
->map
+ (bo
->base
.stride
* y
) + (x
* 4);
1255 *stride
= bo
->base
.stride
;
1259 if (!dri
->image
|| dri
->image
->base
.version
< 12 || !dri
->image
->mapImage
) {
1264 mtx_lock(&dri
->mutex
);
1266 dri
->context
= dri
->dri2
->createNewContext(dri
->screen
, NULL
,
1268 assert(dri
->context
);
1269 mtx_unlock(&dri
->mutex
);
1271 /* GBM flags and DRI flags are the same, so just pass them on */
1272 return dri
->image
->mapImage(dri
->context
, bo
->image
, x
, y
,
1273 width
, height
, flags
, (int *)stride
,
1278 gbm_dri_bo_unmap(struct gbm_bo
*_bo
, void *map_data
)
1280 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1281 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1283 /* Check if it's a dumb buffer and check the pointer is in range */
1285 assert(map_data
>= bo
->map
);
1286 assert(map_data
< (bo
->map
+ bo
->size
));
1290 if (!dri
->context
|| !dri
->image
||
1291 dri
->image
->base
.version
< 12 || !dri
->image
->unmapImage
)
1294 dri
->image
->unmapImage(dri
->context
, bo
->image
, map_data
);
1297 * Not all DRI drivers use direct maps. They may queue up DMA operations
1298 * on the mapping context. Since there is no explicit gbm flush
1299 * mechanism, we need to flush here.
1301 if (dri
->flush
->base
.version
>= 4)
1302 dri
->flush
->flush_with_flags(dri
->context
, NULL
, __DRI2_FLUSH_CONTEXT
, 0);
1306 static struct gbm_surface
*
1307 gbm_dri_surface_create(struct gbm_device
*gbm
,
1308 uint32_t width
, uint32_t height
,
1309 uint32_t format
, uint32_t flags
,
1310 const uint64_t *modifiers
, const unsigned count
)
1312 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1313 struct gbm_dri_surface
*surf
;
1316 (!dri
->image
|| dri
->image
->base
.version
< 14 ||
1317 !dri
->image
->createImageWithModifiers
)) {
1325 /* It's acceptable to create an image with INVALID modifier in the list,
1326 * but it cannot be on the only modifier (since it will certainly fail
1327 * later). While we could easily catch this after modifier creation, doing
1328 * the check here is a convenient debug check likely pointing at whatever
1329 * interface the client is using to build its modifier list.
1331 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
) {
1332 fprintf(stderr
, "Only invalid modifier specified\n");
1336 surf
= calloc(1, sizeof *surf
);
1342 surf
->base
.gbm
= gbm
;
1343 surf
->base
.width
= width
;
1344 surf
->base
.height
= height
;
1345 surf
->base
.format
= format
;
1346 surf
->base
.flags
= flags
;
1352 surf
->base
.modifiers
= calloc(count
, sizeof(*modifiers
));
1353 if (count
&& !surf
->base
.modifiers
) {
1359 /* TODO: We are deferring validation of modifiers until the image is actually
1360 * created. This deferred creation can fail due to a modifier-format
1361 * mismatch. The result is the client has a surface but no object to back it.
1363 surf
->base
.count
= count
;
1364 memcpy(surf
->base
.modifiers
, modifiers
, count
* sizeof(*modifiers
));
1370 gbm_dri_surface_destroy(struct gbm_surface
*_surf
)
1372 struct gbm_dri_surface
*surf
= gbm_dri_surface(_surf
);
1374 free(surf
->base
.modifiers
);
1379 dri_destroy(struct gbm_device
*gbm
)
1381 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1385 dri
->core
->destroyContext(dri
->context
);
1387 dri
->core
->destroyScreen(dri
->screen
);
1388 for (i
= 0; dri
->driver_configs
[i
]; i
++)
1389 free((__DRIconfig
*) dri
->driver_configs
[i
]);
1390 free(dri
->driver_configs
);
1391 dlclose(dri
->driver
);
1392 free(dri
->driver_name
);
1397 static struct gbm_device
*
1398 dri_device_create(int fd
)
1400 struct gbm_dri_device
*dri
;
1403 dri
= calloc(1, sizeof *dri
);
1408 dri
->base
.bo_create
= gbm_dri_bo_create
;
1409 dri
->base
.bo_import
= gbm_dri_bo_import
;
1410 dri
->base
.bo_map
= gbm_dri_bo_map
;
1411 dri
->base
.bo_unmap
= gbm_dri_bo_unmap
;
1412 dri
->base
.is_format_supported
= gbm_dri_is_format_supported
;
1413 dri
->base
.bo_write
= gbm_dri_bo_write
;
1414 dri
->base
.bo_get_fd
= gbm_dri_bo_get_fd
;
1415 dri
->base
.bo_get_planes
= gbm_dri_bo_get_planes
;
1416 dri
->base
.bo_get_handle
= gbm_dri_bo_get_handle_for_plane
;
1417 dri
->base
.bo_get_stride
= gbm_dri_bo_get_stride
;
1418 dri
->base
.bo_get_offset
= gbm_dri_bo_get_offset
;
1419 dri
->base
.bo_get_modifier
= gbm_dri_bo_get_modifier
;
1420 dri
->base
.bo_destroy
= gbm_dri_bo_destroy
;
1421 dri
->base
.destroy
= dri_destroy
;
1422 dri
->base
.surface_create
= gbm_dri_surface_create
;
1423 dri
->base
.surface_destroy
= gbm_dri_surface_destroy
;
1425 dri
->base
.name
= "drm";
1427 mtx_init(&dri
->mutex
, mtx_plain
);
1429 force_sw
= getenv("GBM_ALWAYS_SOFTWARE") != NULL
;
1431 ret
= dri_screen_create(dri
);
1433 ret
= dri_screen_create_sw(dri
);
1435 ret
= dri_screen_create_sw(dri
);
1449 struct gbm_backend gbm_dri_backend
= {
1450 .backend_name
= "dri",
1451 .create_device
= dri_device_create
,