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>
43 #include <GL/gl.h> /* dri_interface needs GL types */
44 #include <GL/internal/dri_interface.h>
46 #include "gbm_driint.h"
51 /* For importing wl_buffer */
52 #if HAVE_WAYLAND_PLATFORM
53 #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
57 dri_lookup_egl_image(__DRIscreen
*screen
, void *image
, void *data
)
59 struct gbm_dri_device
*dri
= data
;
61 if (dri
->lookup_image
== NULL
)
64 return dri
->lookup_image(screen
, image
, dri
->lookup_user_data
);
68 dri_get_buffers(__DRIdrawable
* driDrawable
,
69 int *width
, int *height
,
70 unsigned int *attachments
, int count
,
71 int *out_count
, void *data
)
73 struct gbm_dri_surface
*surf
= data
;
74 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
76 if (dri
->get_buffers
== NULL
)
79 return dri
->get_buffers(driDrawable
, width
, height
, attachments
,
80 count
, out_count
, surf
->dri_private
);
84 dri_flush_front_buffer(__DRIdrawable
* driDrawable
, void *data
)
86 struct gbm_dri_surface
*surf
= data
;
87 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
89 if (dri
->flush_front_buffer
!= NULL
)
90 dri
->flush_front_buffer(driDrawable
, surf
->dri_private
);
94 dri_get_buffers_with_format(__DRIdrawable
* driDrawable
,
95 int *width
, int *height
,
96 unsigned int *attachments
, int count
,
97 int *out_count
, void *data
)
99 struct gbm_dri_surface
*surf
= data
;
100 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
102 if (dri
->get_buffers_with_format
== NULL
)
106 dri
->get_buffers_with_format(driDrawable
, width
, height
, attachments
,
107 count
, out_count
, surf
->dri_private
);
111 image_get_buffers(__DRIdrawable
*driDrawable
,
115 uint32_t buffer_mask
,
116 struct __DRIimageList
*buffers
)
118 struct gbm_dri_surface
*surf
= loaderPrivate
;
119 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
121 if (dri
->image_get_buffers
== NULL
)
124 return dri
->image_get_buffers(driDrawable
, format
, stamp
,
125 surf
->dri_private
, buffer_mask
, buffers
);
129 swrast_get_drawable_info(__DRIdrawable
*driDrawable
,
136 struct gbm_dri_surface
*surf
= loaderPrivate
;
140 *width
= surf
->base
.width
;
141 *height
= surf
->base
.height
;
145 swrast_put_image2(__DRIdrawable
*driDrawable
,
155 struct gbm_dri_surface
*surf
= loaderPrivate
;
156 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
158 dri
->swrast_put_image2(driDrawable
,
160 width
, height
, stride
,
161 data
, surf
->dri_private
);
165 swrast_put_image(__DRIdrawable
*driDrawable
,
174 return swrast_put_image2(driDrawable
, op
, x
, y
, width
, height
,
175 width
* 4, data
, loaderPrivate
);
179 swrast_get_image(__DRIdrawable
*driDrawable
,
187 struct gbm_dri_surface
*surf
= loaderPrivate
;
188 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
190 dri
->swrast_get_image(driDrawable
,
193 data
, surf
->dri_private
);
196 static const __DRIuseInvalidateExtension use_invalidate
= {
197 .base
= { __DRI_USE_INVALIDATE
, 1 }
200 static const __DRIimageLookupExtension image_lookup_extension
= {
201 .base
= { __DRI_IMAGE_LOOKUP
, 1 },
203 .lookupEGLImage
= dri_lookup_egl_image
206 static const __DRIdri2LoaderExtension dri2_loader_extension
= {
207 .base
= { __DRI_DRI2_LOADER
, 3 },
209 .getBuffers
= dri_get_buffers
,
210 .flushFrontBuffer
= dri_flush_front_buffer
,
211 .getBuffersWithFormat
= dri_get_buffers_with_format
,
214 static const __DRIimageLoaderExtension image_loader_extension
= {
215 .base
= { __DRI_IMAGE_LOADER
, 1 },
217 .getBuffers
= image_get_buffers
,
218 .flushFrontBuffer
= dri_flush_front_buffer
,
221 static const __DRIswrastLoaderExtension swrast_loader_extension
= {
222 .base
= { __DRI_SWRAST_LOADER
, 2 },
224 .getDrawableInfo
= swrast_get_drawable_info
,
225 .putImage
= swrast_put_image
,
226 .getImage
= swrast_get_image
,
227 .putImage2
= swrast_put_image2
230 static const __DRIextension
*gbm_dri_screen_extensions
[] = {
231 &image_lookup_extension
.base
,
232 &use_invalidate
.base
,
233 &dri2_loader_extension
.base
,
234 &image_loader_extension
.base
,
235 &swrast_loader_extension
.base
,
239 struct dri_extension_match
{
246 static struct dri_extension_match dri_core_extensions
[] = {
247 { __DRI2_FLUSH
, 1, offsetof(struct gbm_dri_device
, flush
) },
248 { __DRI_IMAGE
, 1, offsetof(struct gbm_dri_device
, image
) },
249 { __DRI2_FENCE
, 1, offsetof(struct gbm_dri_device
, fence
), 1 },
250 { __DRI2_INTEROP
, 1, offsetof(struct gbm_dri_device
, interop
), 1 },
254 static struct dri_extension_match gbm_dri_device_extensions
[] = {
255 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
) },
256 { __DRI_DRI2
, 1, offsetof(struct gbm_dri_device
, dri2
) },
260 static struct dri_extension_match gbm_swrast_device_extensions
[] = {
261 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
), },
262 { __DRI_SWRAST
, 1, offsetof(struct gbm_dri_device
, swrast
) },
267 dri_bind_extensions(struct gbm_dri_device
*dri
,
268 struct dri_extension_match
*matches
,
269 const __DRIextension
**extensions
)
274 for (i
= 0; extensions
[i
]; i
++) {
275 for (j
= 0; matches
[j
].name
; j
++) {
276 if (strcmp(extensions
[i
]->name
, matches
[j
].name
) == 0 &&
277 extensions
[i
]->version
>= matches
[j
].version
) {
278 field
= ((char *) dri
+ matches
[j
].offset
);
279 *(const __DRIextension
**) field
= extensions
[i
];
284 for (j
= 0; matches
[j
].name
; j
++) {
285 field
= ((char *) dri
+ matches
[j
].offset
);
286 if ((*(const __DRIextension
**) field
== NULL
) && !matches
[j
].optional
) {
294 static const __DRIextension
**
295 dri_open_driver(struct gbm_dri_device
*dri
)
297 const __DRIextension
**extensions
= NULL
;
298 char path
[PATH_MAX
], *search_paths
, *p
, *next
, *end
;
299 char *get_extensions_name
;
302 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */
303 if (geteuid() == getuid()) {
304 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
305 * is recommended over GBM_DRIVERS_PATH.
307 search_paths
= getenv("GBM_DRIVERS_PATH");
309 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
310 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
312 if (search_paths
== NULL
) {
313 search_paths
= getenv("LIBGL_DRIVERS_PATH");
316 if (search_paths
== NULL
)
317 search_paths
= DEFAULT_DRIVER_DIR
;
319 /* Temporarily work around dri driver libs that need symbols in libglapi
320 * but don't automatically link it in.
322 /* XXX: Library name differs on per platforms basis. Update this as
323 * osx/cygwin/windows/bsd gets support for GBM..
325 dlopen("libglapi.so.0", RTLD_LAZY
| RTLD_GLOBAL
);
328 end
= search_paths
+ strlen(search_paths
);
329 for (p
= search_paths
; p
< end
&& dri
->driver
== NULL
; p
= next
+ 1) {
331 next
= strchr(p
, ':');
337 snprintf(path
, sizeof path
,
338 "%.*s/tls/%s_dri.so", len
, p
, dri
->base
.driver_name
);
339 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
341 if (dri
->driver
== NULL
) {
342 snprintf(path
, sizeof path
,
343 "%.*s/%s_dri.so", len
, p
, dri
->base
.driver_name
);
344 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
346 /* not need continue to loop all paths once the driver is found */
347 if (dri
->driver
!= NULL
)
351 snprintf(path
, sizeof path
, "%.*s/gallium_dri.so", len
, p
);
352 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
353 if (dri
->driver
== NULL
)
354 sprintf("failed to open %s: %s\n", path
, dlerror());
360 if (dri
->driver
== NULL
) {
361 fprintf(stderr
, "gbm: failed to open any driver (search paths %s)\n",
363 fprintf(stderr
, "gbm: Last dlopen error: %s\n", dlerror());
367 get_extensions_name
= loader_get_extensions_name(dri
->base
.driver_name
);
368 if (get_extensions_name
) {
369 const __DRIextension
**(*get_extensions
)(void);
371 get_extensions
= dlsym(dri
->driver
, get_extensions_name
);
372 free(get_extensions_name
);
375 extensions
= get_extensions();
379 extensions
= dlsym(dri
->driver
, __DRI_DRIVER_EXTENSIONS
);
380 if (extensions
== NULL
) {
381 fprintf(stderr
, "gbm: driver exports no extensions (%s)", dlerror());
382 dlclose(dri
->driver
);
389 dri_load_driver(struct gbm_dri_device
*dri
)
391 const __DRIextension
**extensions
;
393 extensions
= dri_open_driver(dri
);
397 if (dri_bind_extensions(dri
, gbm_dri_device_extensions
, extensions
) < 0) {
398 dlclose(dri
->driver
);
399 fprintf(stderr
, "failed to bind extensions\n");
403 dri
->driver_extensions
= extensions
;
409 dri_load_driver_swrast(struct gbm_dri_device
*dri
)
411 const __DRIextension
**extensions
;
413 extensions
= dri_open_driver(dri
);
417 if (dri_bind_extensions(dri
, gbm_swrast_device_extensions
, extensions
) < 0) {
418 dlclose(dri
->driver
);
419 fprintf(stderr
, "failed to bind extensions\n");
423 dri
->driver_extensions
= extensions
;
429 dri_screen_create_dri2(struct gbm_dri_device
*dri
, char *driver_name
)
431 const __DRIextension
**extensions
;
434 dri
->base
.driver_name
= driver_name
;
435 if (dri
->base
.driver_name
== NULL
)
438 ret
= dri_load_driver(dri
);
440 fprintf(stderr
, "failed to load driver: %s\n", dri
->base
.driver_name
);
444 dri
->loader_extensions
= gbm_dri_screen_extensions
;
446 if (dri
->dri2
== NULL
)
449 if (dri
->dri2
->base
.version
>= 4) {
450 dri
->screen
= dri
->dri2
->createNewScreen2(0, dri
->base
.base
.fd
,
451 dri
->loader_extensions
,
452 dri
->driver_extensions
,
453 &dri
->driver_configs
, dri
);
455 dri
->screen
= dri
->dri2
->createNewScreen(0, dri
->base
.base
.fd
,
456 dri
->loader_extensions
,
457 &dri
->driver_configs
, dri
);
459 if (dri
->screen
== NULL
)
462 extensions
= dri
->core
->getExtensions(dri
->screen
);
463 if (dri_bind_extensions(dri
, dri_core_extensions
, extensions
) < 0) {
468 dri
->lookup_image
= NULL
;
469 dri
->lookup_user_data
= NULL
;
474 dri
->core
->destroyScreen(dri
->screen
);
480 dri_screen_create_swrast(struct gbm_dri_device
*dri
)
484 dri
->base
.driver_name
= strdup("swrast");
485 if (dri
->base
.driver_name
== NULL
)
488 ret
= dri_load_driver_swrast(dri
);
490 fprintf(stderr
, "failed to load swrast driver\n");
494 dri
->loader_extensions
= gbm_dri_screen_extensions
;
496 if (dri
->swrast
== NULL
)
499 if (dri
->swrast
->base
.version
>= 4) {
500 dri
->screen
= dri
->swrast
->createNewScreen2(0, dri
->loader_extensions
,
501 dri
->driver_extensions
,
502 &dri
->driver_configs
, dri
);
504 dri
->screen
= dri
->swrast
->createNewScreen(0, dri
->loader_extensions
,
505 &dri
->driver_configs
, dri
);
507 if (dri
->screen
== NULL
)
510 dri
->lookup_image
= NULL
;
511 dri
->lookup_user_data
= NULL
;
517 dri_screen_create(struct gbm_dri_device
*dri
)
521 driver_name
= loader_get_driver_for_fd(dri
->base
.base
.fd
);
525 return dri_screen_create_dri2(dri
, driver_name
);
529 dri_screen_create_sw(struct gbm_dri_device
*dri
)
534 driver_name
= strdup("kms_swrast");
538 ret
= dri_screen_create_dri2(dri
, driver_name
);
542 return dri_screen_create_swrast(dri
);
546 gbm_dri_is_format_supported(struct gbm_device
*gbm
,
551 case GBM_BO_FORMAT_XRGB8888
:
552 case GBM_FORMAT_XBGR8888
:
553 case GBM_FORMAT_XRGB8888
:
555 case GBM_BO_FORMAT_ARGB8888
:
556 case GBM_FORMAT_ARGB8888
:
557 if (usage
& GBM_BO_USE_SCANOUT
)
564 if (usage
& GBM_BO_USE_CURSOR
&&
565 usage
& GBM_BO_USE_RENDERING
)
572 gbm_dri_bo_write(struct gbm_bo
*_bo
, const void *buf
, size_t count
)
574 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
576 if (bo
->image
!= NULL
) {
581 memcpy(bo
->map
, buf
, count
);
587 gbm_dri_bo_get_fd(struct gbm_bo
*_bo
)
589 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
590 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
593 if (bo
->image
== NULL
)
596 if (!dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_FD
, &fd
))
603 get_number_planes(struct gbm_dri_device
*dri
, __DRIimage
*image
)
607 /* Dumb buffers are single-plane only. */
611 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NUM_PLANES
, &num_planes
);
620 gbm_dri_bo_get_planes(struct gbm_bo
*_bo
)
622 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
623 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
625 return get_number_planes(dri
, bo
->image
);
628 static union gbm_bo_handle
629 gbm_dri_bo_get_handle_for_plane(struct gbm_bo
*_bo
, int plane
)
631 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
632 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
633 union gbm_bo_handle ret
;
636 if (!dri
->image
|| dri
->image
->base
.version
< 13 || !dri
->image
->fromPlanar
) {
641 if (plane
>= get_number_planes(dri
, bo
->image
)) {
646 /* dumb BOs can only utilize non-planar formats */
649 ret
.s32
= bo
->handle
;
653 __DRIimage
*image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
655 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
656 dri
->image
->destroyImage(image
);
659 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
, &ret
.s32
);
666 gbm_dri_bo_get_stride(struct gbm_bo
*_bo
, int plane
)
668 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
669 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
673 if (!dri
->image
|| dri
->image
->base
.version
< 11 || !dri
->image
->fromPlanar
) {
674 /* Preserve legacy behavior if plane is 0 */
682 if (plane
>= get_number_planes(dri
, bo
->image
)) {
687 if (bo
->image
== NULL
) {
692 image
= dri
->image
->fromPlanar(bo
->image
, plane
, NULL
);
694 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
695 dri
->image
->destroyImage(image
);
698 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
701 return (uint32_t)stride
;
705 gbm_dri_bo_destroy(struct gbm_bo
*_bo
)
707 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
708 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
709 struct drm_mode_destroy_dumb arg
;
711 if (bo
->image
!= NULL
) {
712 dri
->image
->destroyImage(bo
->image
);
714 gbm_dri_bo_unmap_dumb(bo
);
715 memset(&arg
, 0, sizeof(arg
));
716 arg
.handle
= bo
->handle
;
717 drmIoctl(dri
->base
.base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &arg
);
724 gbm_dri_to_gbm_format(uint32_t dri_format
)
728 switch (dri_format
) {
729 case __DRI_IMAGE_FORMAT_RGB565
:
730 ret
= GBM_FORMAT_RGB565
;
732 case __DRI_IMAGE_FORMAT_XRGB8888
:
733 ret
= GBM_FORMAT_XRGB8888
;
735 case __DRI_IMAGE_FORMAT_ARGB8888
:
736 ret
= GBM_FORMAT_ARGB8888
;
738 case __DRI_IMAGE_FORMAT_XBGR8888
:
739 ret
= GBM_FORMAT_XBGR8888
;
741 case __DRI_IMAGE_FORMAT_ABGR8888
:
742 ret
= GBM_FORMAT_ABGR8888
;
752 static struct gbm_bo
*
753 gbm_dri_bo_import(struct gbm_device
*gbm
,
754 uint32_t type
, void *buffer
, uint32_t usage
)
756 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
757 struct gbm_dri_bo
*bo
;
759 unsigned dri_use
= 0;
762 /* Required for query image WIDTH & HEIGHT */
763 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 4) {
769 #if HAVE_WAYLAND_PLATFORM
770 case GBM_BO_IMPORT_WL_BUFFER
:
772 struct wl_drm_buffer
*wb
;
779 wb
= wayland_drm_buffer_get(dri
->wl_drm
, (struct wl_resource
*) buffer
);
785 image
= dri
->image
->dupImage(wb
->driver_buffer
, NULL
);
787 switch (wb
->format
) {
788 case WL_DRM_FORMAT_XRGB8888
:
789 gbm_format
= GBM_FORMAT_XRGB8888
;
791 case WL_DRM_FORMAT_ARGB8888
:
792 gbm_format
= GBM_FORMAT_ARGB8888
;
794 case WL_DRM_FORMAT_RGB565
:
795 gbm_format
= GBM_FORMAT_RGB565
;
797 case WL_DRM_FORMAT_YUYV
:
798 gbm_format
= GBM_FORMAT_YUYV
;
801 dri
->image
->destroyImage(image
);
808 case GBM_BO_IMPORT_EGL_IMAGE
:
811 if (dri
->lookup_image
== NULL
) {
816 image
= dri
->lookup_image(dri
->screen
, buffer
, dri
->lookup_user_data
);
817 image
= dri
->image
->dupImage(image
, NULL
);
818 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
, &dri_format
);
819 gbm_format
= gbm_dri_to_gbm_format(dri_format
);
820 if (gbm_format
== 0) {
822 dri
->image
->destroyImage(image
);
828 case GBM_BO_IMPORT_FD
:
830 struct gbm_import_fd_data
*fd_data
= buffer
;
831 int stride
= fd_data
->stride
, offset
= 0;
834 switch (fd_data
->format
) {
835 case GBM_BO_FORMAT_XRGB8888
:
836 dri_format
= GBM_FORMAT_XRGB8888
;
838 case GBM_BO_FORMAT_ARGB8888
:
839 dri_format
= GBM_FORMAT_ARGB8888
;
842 dri_format
= fd_data
->format
;
845 image
= dri
->image
->createImageFromFds(dri
->screen
,
856 gbm_format
= fd_data
->format
;
866 bo
= calloc(1, sizeof *bo
);
868 dri
->image
->destroyImage(image
);
874 if (usage
& GBM_BO_USE_SCANOUT
)
875 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
876 if (usage
& GBM_BO_USE_CURSOR
)
877 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
878 if (dri
->image
->base
.version
>= 2 &&
879 !dri
->image
->validateUsage(bo
->image
, dri_use
)) {
881 dri
->image
->destroyImage(bo
->image
);
886 bo
->base
.base
.gbm
= gbm
;
887 bo
->base
.base
.format
= gbm_format
;
889 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_WIDTH
,
890 (int*)&bo
->base
.base
.width
);
891 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HEIGHT
,
892 (int*)&bo
->base
.base
.height
);
893 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
894 (int*)&bo
->base
.base
.stride
);
895 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
896 &bo
->base
.base
.handle
.s32
);
898 return &bo
->base
.base
;
902 is_planar_format(uint32_t format
)
905 case GBM_FORMAT_NV12
:
906 case GBM_FORMAT_NV21
:
907 case GBM_FORMAT_NV16
:
908 case GBM_FORMAT_NV61
:
909 case GBM_FORMAT_YUV410
:
910 case GBM_FORMAT_YVU410
:
911 case GBM_FORMAT_YUV411
:
912 case GBM_FORMAT_YVU411
:
913 case GBM_FORMAT_YUV420
:
914 case GBM_FORMAT_YVU420
:
915 case GBM_FORMAT_YUV422
:
916 case GBM_FORMAT_YVU422
:
917 case GBM_FORMAT_YUV444
:
918 case GBM_FORMAT_YVU444
:
926 static struct gbm_bo
*
927 create_dumb(struct gbm_device
*gbm
,
928 uint32_t width
, uint32_t height
,
929 uint32_t format
, uint32_t usage
)
931 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
932 struct drm_mode_create_dumb create_arg
;
933 struct gbm_dri_bo
*bo
;
934 struct drm_mode_destroy_dumb destroy_arg
;
936 int is_cursor
, is_scanout
;
938 is_cursor
= (usage
& GBM_BO_USE_CURSOR
) != 0 &&
939 format
== GBM_FORMAT_ARGB8888
;
940 is_scanout
= (usage
& GBM_BO_USE_SCANOUT
) != 0 &&
941 format
== GBM_FORMAT_XRGB8888
;
942 if (!is_cursor
&& !is_scanout
) {
947 if (is_planar_format(format
)) {
952 bo
= calloc(1, sizeof *bo
);
956 memset(&create_arg
, 0, sizeof(create_arg
));
958 create_arg
.width
= width
;
959 create_arg
.height
= height
;
961 ret
= drmIoctl(dri
->base
.base
.fd
, DRM_IOCTL_MODE_CREATE_DUMB
, &create_arg
);
965 bo
->base
.base
.gbm
= gbm
;
966 bo
->base
.base
.width
= width
;
967 bo
->base
.base
.height
= height
;
968 bo
->base
.base
.stride
= create_arg
.pitch
;
969 bo
->base
.base
.format
= format
;
970 bo
->base
.base
.handle
.u32
= create_arg
.handle
;
971 bo
->handle
= create_arg
.handle
;
972 bo
->size
= create_arg
.size
;
974 if (gbm_dri_bo_map_dumb(bo
) == NULL
)
977 return &bo
->base
.base
;
980 memset(&destroy_arg
, 0, sizeof destroy_arg
);
981 destroy_arg
.handle
= create_arg
.handle
;
982 drmIoctl(dri
->base
.base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &destroy_arg
);
989 static struct gbm_bo
*
990 gbm_dri_bo_create(struct gbm_device
*gbm
,
991 uint32_t width
, uint32_t height
,
992 uint32_t format
, uint32_t usage
)
994 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
995 struct gbm_dri_bo
*bo
;
997 unsigned dri_use
= 0;
999 if (usage
& GBM_BO_USE_WRITE
|| dri
->image
== NULL
)
1000 return create_dumb(gbm
, width
, height
, format
, usage
);
1002 bo
= calloc(1, sizeof *bo
);
1006 bo
->base
.base
.gbm
= gbm
;
1007 bo
->base
.base
.width
= width
;
1008 bo
->base
.base
.height
= height
;
1009 bo
->base
.base
.format
= format
;
1013 dri_format
= __DRI_IMAGE_FORMAT_R8
;
1015 case GBM_FORMAT_GR88
:
1016 dri_format
= __DRI_IMAGE_FORMAT_GR88
;
1018 case GBM_FORMAT_RGB565
:
1019 dri_format
= __DRI_IMAGE_FORMAT_RGB565
;
1021 case GBM_FORMAT_XRGB8888
:
1022 case GBM_BO_FORMAT_XRGB8888
:
1023 dri_format
= __DRI_IMAGE_FORMAT_XRGB8888
;
1025 case GBM_FORMAT_ARGB8888
:
1026 case GBM_BO_FORMAT_ARGB8888
:
1027 dri_format
= __DRI_IMAGE_FORMAT_ARGB8888
;
1029 case GBM_FORMAT_ABGR8888
:
1030 dri_format
= __DRI_IMAGE_FORMAT_ABGR8888
;
1032 case GBM_FORMAT_XBGR8888
:
1033 dri_format
= __DRI_IMAGE_FORMAT_XBGR8888
;
1035 case GBM_FORMAT_ARGB2101010
:
1036 dri_format
= __DRI_IMAGE_FORMAT_ARGB2101010
;
1038 case GBM_FORMAT_XRGB2101010
:
1039 dri_format
= __DRI_IMAGE_FORMAT_XRGB2101010
;
1046 if (usage
& GBM_BO_USE_SCANOUT
)
1047 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
1048 if (usage
& GBM_BO_USE_CURSOR
)
1049 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
1050 if (usage
& GBM_BO_USE_LINEAR
)
1051 dri_use
|= __DRI_IMAGE_USE_LINEAR
;
1053 /* Gallium drivers requires shared in order to get the handle/stride */
1054 dri_use
|= __DRI_IMAGE_USE_SHARE
;
1057 dri
->image
->createImage(dri
->screen
,
1059 dri_format
, dri_use
,
1061 if (bo
->image
== NULL
)
1064 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
1065 &bo
->base
.base
.handle
.s32
);
1066 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
1067 (int *) &bo
->base
.base
.stride
);
1069 return &bo
->base
.base
;
1077 gbm_dri_bo_map(struct gbm_bo
*_bo
,
1078 uint32_t x
, uint32_t y
,
1079 uint32_t width
, uint32_t height
,
1080 uint32_t flags
, uint32_t *stride
, void **map_data
)
1082 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1083 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1085 /* If it's a dumb buffer, we already have a mapping */
1087 *map_data
= (char *)bo
->map
+ (bo
->base
.base
.stride
* y
) + (x
* 4);
1088 *stride
= bo
->base
.base
.stride
;
1092 if (!dri
->image
|| dri
->image
->base
.version
< 12 || !dri
->image
->mapImage
) {
1097 mtx_lock(&dri
->mutex
);
1099 dri
->context
= dri
->dri2
->createNewContext(dri
->screen
, NULL
,
1101 assert(dri
->context
);
1102 mtx_unlock(&dri
->mutex
);
1104 /* GBM flags and DRI flags are the same, so just pass them on */
1105 return dri
->image
->mapImage(dri
->context
, bo
->image
, x
, y
,
1106 width
, height
, flags
, (int *)stride
,
1111 gbm_dri_bo_unmap(struct gbm_bo
*_bo
, void *map_data
)
1113 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
1114 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
1116 /* Check if it's a dumb buffer and check the pointer is in range */
1118 assert(map_data
>= bo
->map
);
1119 assert(map_data
< (bo
->map
+ bo
->size
));
1123 if (!dri
->context
|| !dri
->image
||
1124 dri
->image
->base
.version
< 12 || !dri
->image
->unmapImage
)
1127 dri
->image
->unmapImage(dri
->context
, bo
->image
, map_data
);
1131 static struct gbm_surface
*
1132 gbm_dri_surface_create(struct gbm_device
*gbm
,
1133 uint32_t width
, uint32_t height
,
1134 uint32_t format
, uint32_t flags
)
1136 struct gbm_dri_surface
*surf
;
1138 surf
= calloc(1, sizeof *surf
);
1142 surf
->base
.gbm
= gbm
;
1143 surf
->base
.width
= width
;
1144 surf
->base
.height
= height
;
1145 surf
->base
.format
= format
;
1146 surf
->base
.flags
= flags
;
1152 gbm_dri_surface_destroy(struct gbm_surface
*_surf
)
1154 struct gbm_dri_surface
*surf
= gbm_dri_surface(_surf
);
1160 dri_destroy(struct gbm_device
*gbm
)
1162 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1166 dri
->core
->destroyContext(dri
->context
);
1168 dri
->core
->destroyScreen(dri
->screen
);
1169 for (i
= 0; dri
->driver_configs
[i
]; i
++)
1170 free((__DRIconfig
*) dri
->driver_configs
[i
]);
1171 free(dri
->driver_configs
);
1172 dlclose(dri
->driver
);
1173 free(dri
->base
.driver_name
);
1178 static struct gbm_device
*
1179 dri_device_create(int fd
)
1181 struct gbm_dri_device
*dri
;
1184 dri
= calloc(1, sizeof *dri
);
1188 dri
->base
.base
.fd
= fd
;
1189 dri
->base
.base
.bo_create
= gbm_dri_bo_create
;
1190 dri
->base
.base
.bo_import
= gbm_dri_bo_import
;
1191 dri
->base
.base
.bo_map
= gbm_dri_bo_map
;
1192 dri
->base
.base
.bo_unmap
= gbm_dri_bo_unmap
;
1193 dri
->base
.base
.is_format_supported
= gbm_dri_is_format_supported
;
1194 dri
->base
.base
.bo_write
= gbm_dri_bo_write
;
1195 dri
->base
.base
.bo_get_fd
= gbm_dri_bo_get_fd
;
1196 dri
->base
.base
.bo_get_planes
= gbm_dri_bo_get_planes
;
1197 dri
->base
.base
.bo_get_handle
= gbm_dri_bo_get_handle_for_plane
;
1198 dri
->base
.base
.bo_get_stride
= gbm_dri_bo_get_stride
;
1199 dri
->base
.base
.bo_destroy
= gbm_dri_bo_destroy
;
1200 dri
->base
.base
.destroy
= dri_destroy
;
1201 dri
->base
.base
.surface_create
= gbm_dri_surface_create
;
1202 dri
->base
.base
.surface_destroy
= gbm_dri_surface_destroy
;
1204 dri
->base
.type
= GBM_DRM_DRIVER_TYPE_DRI
;
1205 dri
->base
.base
.name
= "drm";
1207 mtx_init(&dri
->mutex
, mtx_plain
);
1209 force_sw
= getenv("GBM_ALWAYS_SOFTWARE") != NULL
;
1211 ret
= dri_screen_create(dri
);
1213 ret
= dri_screen_create_sw(dri
);
1215 ret
= dri_screen_create_sw(dri
);
1221 return &dri
->base
.base
;
1229 struct gbm_backend gbm_dri_backend
= {
1230 .backend_name
= "dri",
1231 .create_device
= dri_device_create
,