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>
37 #include <sys/types.h>
42 #include <GL/gl.h> /* dri_interface needs GL types */
43 #include <GL/internal/dri_interface.h>
45 #include "gbm_driint.h"
50 /* For importing wl_buffer */
51 #if HAVE_WAYLAND_PLATFORM
52 #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
56 dri_lookup_egl_image(__DRIscreen
*screen
, void *image
, void *data
)
58 struct gbm_dri_device
*dri
= data
;
60 if (dri
->lookup_image
== NULL
)
63 return dri
->lookup_image(screen
, image
, dri
->lookup_user_data
);
67 dri_get_buffers(__DRIdrawable
* driDrawable
,
68 int *width
, int *height
,
69 unsigned int *attachments
, int count
,
70 int *out_count
, void *data
)
72 struct gbm_dri_surface
*surf
= data
;
73 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
75 if (dri
->get_buffers
== NULL
)
78 return dri
->get_buffers(driDrawable
, width
, height
, attachments
,
79 count
, out_count
, surf
->dri_private
);
83 dri_flush_front_buffer(__DRIdrawable
* driDrawable
, void *data
)
85 struct gbm_dri_surface
*surf
= data
;
86 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
88 if (dri
->flush_front_buffer
!= NULL
)
89 dri
->flush_front_buffer(driDrawable
, surf
->dri_private
);
93 dri_get_buffers_with_format(__DRIdrawable
* driDrawable
,
94 int *width
, int *height
,
95 unsigned int *attachments
, int count
,
96 int *out_count
, void *data
)
98 struct gbm_dri_surface
*surf
= data
;
99 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
101 if (dri
->get_buffers_with_format
== NULL
)
105 dri
->get_buffers_with_format(driDrawable
, width
, height
, attachments
,
106 count
, out_count
, surf
->dri_private
);
110 image_get_buffers(__DRIdrawable
*driDrawable
,
114 uint32_t buffer_mask
,
115 struct __DRIimageList
*buffers
)
117 struct gbm_dri_surface
*surf
= loaderPrivate
;
118 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
120 if (dri
->image_get_buffers
== NULL
)
123 return dri
->image_get_buffers(driDrawable
, format
, stamp
,
124 surf
->dri_private
, buffer_mask
, buffers
);
128 swrast_get_drawable_info(__DRIdrawable
*driDrawable
,
135 struct gbm_dri_surface
*surf
= loaderPrivate
;
139 *width
= surf
->base
.width
;
140 *height
= surf
->base
.height
;
144 swrast_put_image2(__DRIdrawable
*driDrawable
,
154 struct gbm_dri_surface
*surf
= loaderPrivate
;
155 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
157 dri
->swrast_put_image2(driDrawable
,
159 width
, height
, stride
,
160 data
, surf
->dri_private
);
164 swrast_put_image(__DRIdrawable
*driDrawable
,
173 return swrast_put_image2(driDrawable
, op
, x
, y
, width
, height
,
174 width
* 4, data
, loaderPrivate
);
178 swrast_get_image(__DRIdrawable
*driDrawable
,
186 struct gbm_dri_surface
*surf
= loaderPrivate
;
187 struct gbm_dri_device
*dri
= gbm_dri_device(surf
->base
.gbm
);
189 dri
->swrast_get_image(driDrawable
,
192 data
, surf
->dri_private
);
195 static const __DRIuseInvalidateExtension use_invalidate
= {
196 .base
= { __DRI_USE_INVALIDATE
, 1 }
199 static const __DRIimageLookupExtension image_lookup_extension
= {
200 .base
= { __DRI_IMAGE_LOOKUP
, 1 },
202 .lookupEGLImage
= dri_lookup_egl_image
205 static const __DRIdri2LoaderExtension dri2_loader_extension
= {
206 .base
= { __DRI_DRI2_LOADER
, 3 },
208 .getBuffers
= dri_get_buffers
,
209 .flushFrontBuffer
= dri_flush_front_buffer
,
210 .getBuffersWithFormat
= dri_get_buffers_with_format
,
213 static const __DRIimageLoaderExtension image_loader_extension
= {
214 .base
= { __DRI_IMAGE_LOADER
, 1 },
216 .getBuffers
= image_get_buffers
,
217 .flushFrontBuffer
= dri_flush_front_buffer
,
220 static const __DRIswrastLoaderExtension swrast_loader_extension
= {
221 .base
= { __DRI_SWRAST_LOADER
, 2 },
223 .getDrawableInfo
= swrast_get_drawable_info
,
224 .putImage
= swrast_put_image
,
225 .getImage
= swrast_get_image
,
226 .putImage2
= swrast_put_image2
229 static const __DRIextension
*gbm_dri_screen_extensions
[] = {
230 &image_lookup_extension
.base
,
231 &use_invalidate
.base
,
232 &dri2_loader_extension
.base
,
233 &image_loader_extension
.base
,
234 &swrast_loader_extension
.base
,
238 struct dri_extension_match
{
245 static struct dri_extension_match dri_core_extensions
[] = {
246 { __DRI2_FLUSH
, 1, offsetof(struct gbm_dri_device
, flush
) },
247 { __DRI_IMAGE
, 1, offsetof(struct gbm_dri_device
, image
) },
248 { __DRI2_FENCE
, 2, offsetof(struct gbm_dri_device
, fence
), 1 },
252 static struct dri_extension_match gbm_dri_device_extensions
[] = {
253 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
) },
254 { __DRI_DRI2
, 1, offsetof(struct gbm_dri_device
, dri2
) },
258 static struct dri_extension_match gbm_swrast_device_extensions
[] = {
259 { __DRI_CORE
, 1, offsetof(struct gbm_dri_device
, core
), },
260 { __DRI_SWRAST
, 1, offsetof(struct gbm_dri_device
, swrast
) },
265 dri_bind_extensions(struct gbm_dri_device
*dri
,
266 struct dri_extension_match
*matches
,
267 const __DRIextension
**extensions
)
272 for (i
= 0; extensions
[i
]; i
++) {
273 for (j
= 0; matches
[j
].name
; j
++) {
274 if (strcmp(extensions
[i
]->name
, matches
[j
].name
) == 0 &&
275 extensions
[i
]->version
>= matches
[j
].version
) {
276 field
= ((char *) dri
+ matches
[j
].offset
);
277 *(const __DRIextension
**) field
= extensions
[i
];
282 for (j
= 0; matches
[j
].name
; j
++) {
283 field
= ((char *) dri
+ matches
[j
].offset
);
284 if ((*(const __DRIextension
**) field
== NULL
) && !matches
[j
].optional
) {
292 static const __DRIextension
**
293 dri_open_driver(struct gbm_dri_device
*dri
)
295 const __DRIextension
**extensions
= NULL
;
296 char path
[PATH_MAX
], *search_paths
, *p
, *next
, *end
;
297 char *get_extensions_name
;
300 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */
301 if (geteuid() == getuid()) {
302 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
303 * is recommended over GBM_DRIVERS_PATH.
305 search_paths
= getenv("GBM_DRIVERS_PATH");
307 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
308 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
310 if (search_paths
== NULL
) {
311 search_paths
= getenv("LIBGL_DRIVERS_PATH");
314 if (search_paths
== NULL
)
315 search_paths
= DEFAULT_DRIVER_DIR
;
317 /* Temporarily work around dri driver libs that need symbols in libglapi
318 * but don't automatically link it in.
320 /* XXX: Library name differs on per platforms basis. Update this as
321 * osx/cygwin/windows/bsd gets support for GBM..
323 dlopen("libglapi.so.0", RTLD_LAZY
| RTLD_GLOBAL
);
326 end
= search_paths
+ strlen(search_paths
);
327 for (p
= search_paths
; p
< end
&& dri
->driver
== NULL
; p
= next
+ 1) {
329 next
= strchr(p
, ':');
335 snprintf(path
, sizeof path
,
336 "%.*s/tls/%s_dri.so", len
, p
, dri
->base
.driver_name
);
337 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
339 if (dri
->driver
== NULL
) {
340 snprintf(path
, sizeof path
,
341 "%.*s/%s_dri.so", len
, p
, dri
->base
.driver_name
);
342 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
344 /* not need continue to loop all paths once the driver is found */
345 if (dri
->driver
!= NULL
)
349 snprintf(path
, sizeof path
, "%.*s/gallium_dri.so", len
, p
);
350 dri
->driver
= dlopen(path
, RTLD_NOW
| RTLD_GLOBAL
);
351 if (dri
->driver
== NULL
)
352 sprintf("failed to open %s: %s\n", path
, dlerror());
358 if (dri
->driver
== NULL
) {
359 fprintf(stderr
, "gbm: failed to open any driver (search paths %s)\n",
361 fprintf(stderr
, "gbm: Last dlopen error: %s\n", dlerror());
365 if (asprintf(&get_extensions_name
, "%s_%s",
366 __DRI_DRIVER_GET_EXTENSIONS
, dri
->base
.driver_name
) != -1) {
367 const __DRIextension
**(*get_extensions
)(void);
369 get_extensions
= dlsym(dri
->driver
, get_extensions_name
);
370 free(get_extensions_name
);
373 extensions
= get_extensions();
377 extensions
= dlsym(dri
->driver
, __DRI_DRIVER_EXTENSIONS
);
378 if (extensions
== NULL
) {
379 fprintf(stderr
, "gbm: driver exports no extensions (%s)", dlerror());
380 dlclose(dri
->driver
);
387 dri_load_driver(struct gbm_dri_device
*dri
)
389 const __DRIextension
**extensions
;
391 extensions
= dri_open_driver(dri
);
395 if (dri_bind_extensions(dri
, gbm_dri_device_extensions
, extensions
) < 0) {
396 dlclose(dri
->driver
);
397 fprintf(stderr
, "failed to bind extensions\n");
401 dri
->driver_extensions
= extensions
;
407 dri_load_driver_swrast(struct gbm_dri_device
*dri
)
409 const __DRIextension
**extensions
;
411 extensions
= dri_open_driver(dri
);
415 if (dri_bind_extensions(dri
, gbm_swrast_device_extensions
, extensions
) < 0) {
416 dlclose(dri
->driver
);
417 fprintf(stderr
, "failed to bind extensions\n");
421 dri
->driver_extensions
= extensions
;
427 dri_screen_create_dri2(struct gbm_dri_device
*dri
, char *driver_name
)
429 const __DRIextension
**extensions
;
432 dri
->base
.driver_name
= driver_name
;
433 if (dri
->base
.driver_name
== NULL
)
436 ret
= dri_load_driver(dri
);
438 fprintf(stderr
, "failed to load driver: %s\n", dri
->base
.driver_name
);
442 dri
->extensions
= gbm_dri_screen_extensions
;
444 if (dri
->dri2
== NULL
)
447 if (dri
->dri2
->base
.version
>= 4) {
448 dri
->screen
= dri
->dri2
->createNewScreen2(0, dri
->base
.base
.fd
,
450 dri
->driver_extensions
,
451 &dri
->driver_configs
, dri
);
453 dri
->screen
= dri
->dri2
->createNewScreen(0, dri
->base
.base
.fd
,
455 &dri
->driver_configs
, dri
);
457 if (dri
->screen
== NULL
)
460 extensions
= dri
->core
->getExtensions(dri
->screen
);
461 if (dri_bind_extensions(dri
, dri_core_extensions
, extensions
) < 0) {
466 dri
->lookup_image
= NULL
;
467 dri
->lookup_user_data
= NULL
;
472 dri
->core
->destroyScreen(dri
->screen
);
478 dri_screen_create_swrast(struct gbm_dri_device
*dri
)
482 dri
->base
.driver_name
= strdup("swrast");
483 if (dri
->base
.driver_name
== NULL
)
486 ret
= dri_load_driver_swrast(dri
);
488 fprintf(stderr
, "failed to load swrast driver\n");
492 dri
->extensions
= gbm_dri_screen_extensions
;
494 if (dri
->swrast
== NULL
)
497 if (dri
->swrast
->base
.version
>= 4) {
498 dri
->screen
= dri
->swrast
->createNewScreen2(0, dri
->extensions
,
499 dri
->driver_extensions
,
500 &dri
->driver_configs
, dri
);
502 dri
->screen
= dri
->swrast
->createNewScreen(0, dri
->extensions
,
503 &dri
->driver_configs
, dri
);
505 if (dri
->screen
== NULL
)
508 dri
->lookup_image
= NULL
;
509 dri
->lookup_user_data
= NULL
;
515 dri_screen_create(struct gbm_dri_device
*dri
)
519 driver_name
= loader_get_driver_for_fd(dri
->base
.base
.fd
, 0);
523 return dri_screen_create_dri2(dri
, driver_name
);
527 dri_screen_create_sw(struct gbm_dri_device
*dri
)
532 driver_name
= strdup("kms_swrast");
536 ret
= dri_screen_create_dri2(dri
, driver_name
);
540 return dri_screen_create_swrast(dri
);
544 gbm_dri_is_format_supported(struct gbm_device
*gbm
,
549 case GBM_BO_FORMAT_XRGB8888
:
550 case GBM_FORMAT_XBGR8888
:
551 case GBM_FORMAT_XRGB8888
:
553 case GBM_BO_FORMAT_ARGB8888
:
554 case GBM_FORMAT_ARGB8888
:
555 if (usage
& GBM_BO_USE_SCANOUT
)
562 if (usage
& GBM_BO_USE_CURSOR
&&
563 usage
& GBM_BO_USE_RENDERING
)
570 gbm_dri_bo_write(struct gbm_bo
*_bo
, const void *buf
, size_t count
)
572 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
574 if (bo
->image
!= NULL
) {
579 memcpy(bo
->map
, buf
, count
);
585 gbm_dri_bo_get_fd(struct gbm_bo
*_bo
)
587 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
588 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
591 if (bo
->image
== NULL
)
594 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_FD
, &fd
);
600 gbm_dri_bo_destroy(struct gbm_bo
*_bo
)
602 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
603 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
604 struct drm_mode_destroy_dumb arg
;
606 if (bo
->image
!= NULL
) {
607 dri
->image
->destroyImage(bo
->image
);
609 gbm_dri_bo_unmap_dumb(bo
);
610 memset(&arg
, 0, sizeof(arg
));
611 arg
.handle
= bo
->handle
;
612 drmIoctl(dri
->base
.base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &arg
);
619 gbm_dri_to_gbm_format(uint32_t dri_format
)
623 switch (dri_format
) {
624 case __DRI_IMAGE_FORMAT_RGB565
:
625 ret
= GBM_FORMAT_RGB565
;
627 case __DRI_IMAGE_FORMAT_XRGB8888
:
628 ret
= GBM_FORMAT_XRGB8888
;
630 case __DRI_IMAGE_FORMAT_ARGB8888
:
631 ret
= GBM_FORMAT_ARGB8888
;
633 case __DRI_IMAGE_FORMAT_XBGR8888
:
634 ret
= GBM_FORMAT_XBGR8888
;
636 case __DRI_IMAGE_FORMAT_ABGR8888
:
637 ret
= GBM_FORMAT_ABGR8888
;
647 static struct gbm_bo
*
648 gbm_dri_bo_import(struct gbm_device
*gbm
,
649 uint32_t type
, void *buffer
, uint32_t usage
)
651 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
652 struct gbm_dri_bo
*bo
;
654 unsigned dri_use
= 0;
657 /* Required for query image WIDTH & HEIGHT */
658 if (dri
->image
== NULL
|| dri
->image
->base
.version
< 4) {
664 #if HAVE_WAYLAND_PLATFORM
665 case GBM_BO_IMPORT_WL_BUFFER
:
667 struct wl_drm_buffer
*wb
;
674 wb
= wayland_drm_buffer_get(dri
->wl_drm
, (struct wl_resource
*) buffer
);
680 image
= dri
->image
->dupImage(wb
->driver_buffer
, NULL
);
682 switch (wb
->format
) {
683 case WL_DRM_FORMAT_XRGB8888
:
684 gbm_format
= GBM_FORMAT_XRGB8888
;
686 case WL_DRM_FORMAT_ARGB8888
:
687 gbm_format
= GBM_FORMAT_ARGB8888
;
689 case WL_DRM_FORMAT_RGB565
:
690 gbm_format
= GBM_FORMAT_RGB565
;
692 case WL_DRM_FORMAT_YUYV
:
693 gbm_format
= GBM_FORMAT_YUYV
;
702 case GBM_BO_IMPORT_EGL_IMAGE
:
705 if (dri
->lookup_image
== NULL
) {
710 image
= dri
->lookup_image(dri
->screen
, buffer
, dri
->lookup_user_data
);
711 image
= dri
->image
->dupImage(image
, NULL
);
712 dri
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
, &dri_format
);
713 gbm_format
= gbm_dri_to_gbm_format(dri_format
);
714 if (gbm_format
== 0) {
721 case GBM_BO_IMPORT_FD
:
723 struct gbm_import_fd_data
*fd_data
= buffer
;
724 int stride
= fd_data
->stride
, offset
= 0;
727 switch (fd_data
->format
) {
728 case GBM_BO_FORMAT_XRGB8888
:
729 dri_format
= GBM_FORMAT_XRGB8888
;
731 case GBM_BO_FORMAT_ARGB8888
:
732 dri_format
= GBM_FORMAT_ARGB8888
;
735 dri_format
= fd_data
->format
;
738 image
= dri
->image
->createImageFromFds(dri
->screen
,
749 gbm_format
= fd_data
->format
;
759 bo
= calloc(1, sizeof *bo
);
765 if (usage
& GBM_BO_USE_SCANOUT
)
766 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
767 if (usage
& GBM_BO_USE_CURSOR
)
768 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
769 if (dri
->image
->base
.version
>= 2 &&
770 !dri
->image
->validateUsage(bo
->image
, dri_use
)) {
776 bo
->base
.base
.gbm
= gbm
;
777 bo
->base
.base
.format
= gbm_format
;
779 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_WIDTH
,
780 (int*)&bo
->base
.base
.width
);
781 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HEIGHT
,
782 (int*)&bo
->base
.base
.height
);
783 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
784 (int*)&bo
->base
.base
.stride
);
785 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
786 &bo
->base
.base
.handle
.s32
);
788 return &bo
->base
.base
;
791 static struct gbm_bo
*
792 create_dumb(struct gbm_device
*gbm
,
793 uint32_t width
, uint32_t height
,
794 uint32_t format
, uint32_t usage
)
796 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
797 struct drm_mode_create_dumb create_arg
;
798 struct gbm_dri_bo
*bo
;
799 struct drm_mode_destroy_dumb destroy_arg
;
801 int is_cursor
, is_scanout
;
803 is_cursor
= (usage
& GBM_BO_USE_CURSOR
) != 0 &&
804 format
== GBM_FORMAT_ARGB8888
;
805 is_scanout
= (usage
& GBM_BO_USE_SCANOUT
) != 0 &&
806 format
== GBM_FORMAT_XRGB8888
;
807 if (!is_cursor
&& !is_scanout
) {
812 bo
= calloc(1, sizeof *bo
);
816 memset(&create_arg
, 0, sizeof(create_arg
));
818 create_arg
.width
= width
;
819 create_arg
.height
= height
;
821 ret
= drmIoctl(dri
->base
.base
.fd
, DRM_IOCTL_MODE_CREATE_DUMB
, &create_arg
);
825 bo
->base
.base
.gbm
= gbm
;
826 bo
->base
.base
.width
= width
;
827 bo
->base
.base
.height
= height
;
828 bo
->base
.base
.stride
= create_arg
.pitch
;
829 bo
->base
.base
.format
= format
;
830 bo
->base
.base
.handle
.u32
= create_arg
.handle
;
831 bo
->handle
= create_arg
.handle
;
832 bo
->size
= create_arg
.size
;
834 if (gbm_dri_bo_map_dumb(bo
) == NULL
)
837 return &bo
->base
.base
;
840 memset(&destroy_arg
, 0, sizeof destroy_arg
);
841 destroy_arg
.handle
= create_arg
.handle
;
842 drmIoctl(dri
->base
.base
.fd
, DRM_IOCTL_MODE_DESTROY_DUMB
, &destroy_arg
);
849 static struct gbm_bo
*
850 gbm_dri_bo_create(struct gbm_device
*gbm
,
851 uint32_t width
, uint32_t height
,
852 uint32_t format
, uint32_t usage
)
854 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
855 struct gbm_dri_bo
*bo
;
857 unsigned dri_use
= 0;
859 if (usage
& GBM_BO_USE_WRITE
|| dri
->image
== NULL
)
860 return create_dumb(gbm
, width
, height
, format
, usage
);
862 bo
= calloc(1, sizeof *bo
);
866 bo
->base
.base
.gbm
= gbm
;
867 bo
->base
.base
.width
= width
;
868 bo
->base
.base
.height
= height
;
869 bo
->base
.base
.format
= format
;
873 dri_format
= __DRI_IMAGE_FORMAT_R8
;
875 case GBM_FORMAT_GR88
:
876 dri_format
= __DRI_IMAGE_FORMAT_GR88
;
878 case GBM_FORMAT_RGB565
:
879 dri_format
= __DRI_IMAGE_FORMAT_RGB565
;
881 case GBM_FORMAT_XRGB8888
:
882 case GBM_BO_FORMAT_XRGB8888
:
883 dri_format
= __DRI_IMAGE_FORMAT_XRGB8888
;
885 case GBM_FORMAT_ARGB8888
:
886 case GBM_BO_FORMAT_ARGB8888
:
887 dri_format
= __DRI_IMAGE_FORMAT_ARGB8888
;
889 case GBM_FORMAT_ABGR8888
:
890 dri_format
= __DRI_IMAGE_FORMAT_ABGR8888
;
892 case GBM_FORMAT_XBGR8888
:
893 dri_format
= __DRI_IMAGE_FORMAT_XBGR8888
;
895 case GBM_FORMAT_ARGB2101010
:
896 dri_format
= __DRI_IMAGE_FORMAT_ARGB2101010
;
898 case GBM_FORMAT_XRGB2101010
:
899 dri_format
= __DRI_IMAGE_FORMAT_XRGB2101010
;
906 if (usage
& GBM_BO_USE_SCANOUT
)
907 dri_use
|= __DRI_IMAGE_USE_SCANOUT
;
908 if (usage
& GBM_BO_USE_CURSOR
)
909 dri_use
|= __DRI_IMAGE_USE_CURSOR
;
910 if (usage
& GBM_BO_USE_LINEAR
)
911 dri_use
|= __DRI_IMAGE_USE_LINEAR
;
913 /* Gallium drivers requires shared in order to get the handle/stride */
914 dri_use
|= __DRI_IMAGE_USE_SHARE
;
917 dri
->image
->createImage(dri
->screen
,
921 if (bo
->image
== NULL
)
924 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_HANDLE
,
925 &bo
->base
.base
.handle
.s32
);
926 dri
->image
->queryImage(bo
->image
, __DRI_IMAGE_ATTRIB_STRIDE
,
927 (int *) &bo
->base
.base
.stride
);
929 return &bo
->base
.base
;
937 gbm_dri_bo_map(struct gbm_bo
*_bo
,
938 uint32_t x
, uint32_t y
,
939 uint32_t width
, uint32_t height
,
940 uint32_t flags
, uint32_t *stride
, void **map_data
)
942 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
943 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
945 /* If it's a dumb buffer, we already have a mapping */
947 *map_data
= (char *)bo
->map
+ (bo
->base
.base
.stride
* y
) + (x
* 4);
948 *stride
= bo
->base
.base
.stride
;
952 if (!dri
->image
|| dri
->image
->base
.version
< 12) {
957 mtx_lock(&dri
->mutex
);
959 dri
->context
= dri
->dri2
->createNewContext(dri
->screen
, NULL
,
961 assert(dri
->context
);
962 mtx_unlock(&dri
->mutex
);
964 /* GBM flags and DRI flags are the same, so just pass them on */
965 return dri
->image
->mapImage(dri
->context
, bo
->image
, x
, y
,
966 width
, height
, flags
, (int *)stride
,
971 gbm_dri_bo_unmap(struct gbm_bo
*_bo
, void *map_data
)
973 struct gbm_dri_device
*dri
= gbm_dri_device(_bo
->gbm
);
974 struct gbm_dri_bo
*bo
= gbm_dri_bo(_bo
);
976 /* Check if it's a dumb buffer and check the pointer is in range */
978 assert(map_data
>= bo
->map
);
979 assert(map_data
< (bo
->map
+ bo
->size
));
983 if (!dri
->context
|| !dri
->image
|| dri
->image
->base
.version
< 12)
986 dri
->image
->unmapImage(dri
->context
, bo
->image
, map_data
);
990 static struct gbm_surface
*
991 gbm_dri_surface_create(struct gbm_device
*gbm
,
992 uint32_t width
, uint32_t height
,
993 uint32_t format
, uint32_t flags
)
995 struct gbm_dri_surface
*surf
;
997 surf
= calloc(1, sizeof *surf
);
1001 surf
->base
.gbm
= gbm
;
1002 surf
->base
.width
= width
;
1003 surf
->base
.height
= height
;
1004 surf
->base
.format
= format
;
1005 surf
->base
.flags
= flags
;
1011 gbm_dri_surface_destroy(struct gbm_surface
*_surf
)
1013 struct gbm_dri_surface
*surf
= gbm_dri_surface(_surf
);
1019 dri_destroy(struct gbm_device
*gbm
)
1021 struct gbm_dri_device
*dri
= gbm_dri_device(gbm
);
1025 dri
->core
->destroyContext(dri
->context
);
1027 dri
->core
->destroyScreen(dri
->screen
);
1028 for (i
= 0; dri
->driver_configs
[i
]; i
++)
1029 free((__DRIconfig
*) dri
->driver_configs
[i
]);
1030 free(dri
->driver_configs
);
1031 dlclose(dri
->driver
);
1032 free(dri
->base
.driver_name
);
1037 static struct gbm_device
*
1038 dri_device_create(int fd
)
1040 struct gbm_dri_device
*dri
;
1043 dri
= calloc(1, sizeof *dri
);
1047 dri
->base
.base
.fd
= fd
;
1048 dri
->base
.base
.bo_create
= gbm_dri_bo_create
;
1049 dri
->base
.base
.bo_import
= gbm_dri_bo_import
;
1050 dri
->base
.base
.bo_map
= gbm_dri_bo_map
;
1051 dri
->base
.base
.bo_unmap
= gbm_dri_bo_unmap
;
1052 dri
->base
.base
.is_format_supported
= gbm_dri_is_format_supported
;
1053 dri
->base
.base
.bo_write
= gbm_dri_bo_write
;
1054 dri
->base
.base
.bo_get_fd
= gbm_dri_bo_get_fd
;
1055 dri
->base
.base
.bo_destroy
= gbm_dri_bo_destroy
;
1056 dri
->base
.base
.destroy
= dri_destroy
;
1057 dri
->base
.base
.surface_create
= gbm_dri_surface_create
;
1058 dri
->base
.base
.surface_destroy
= gbm_dri_surface_destroy
;
1060 dri
->base
.type
= GBM_DRM_DRIVER_TYPE_DRI
;
1061 dri
->base
.base
.name
= "drm";
1063 mtx_init(&dri
->mutex
, mtx_plain
);
1065 force_sw
= getenv("GBM_ALWAYS_SOFTWARE") != NULL
;
1067 ret
= dri_screen_create(dri
);
1069 ret
= dri_screen_create_sw(dri
);
1071 ret
= dri_screen_create_sw(dri
);
1077 return &dri
->base
.base
;
1085 struct gbm_backend gbm_dri_backend
= {
1086 .backend_name
= "dri",
1087 .create_device
= dri_device_create
,