[Mesa-dev] [PATCH 09/10] egl/drm: Add support for native gbm backends
Ander Conselvan de Oliveira
conselvan2 at gmail.com
Fri Apr 4 01:36:27 PDT 2014
From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
---
src/egl/drivers/dri2/egl_dri2.c | 9 +-
src/egl/drivers/dri2/egl_dri2.h | 3 +-
src/egl/drivers/dri2/platform_drm.c | 217 ++++++++++++++++++++++++++++++------
src/gbm/main/common_drm.h | 6 +
4 files changed, 200 insertions(+), 35 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index a5ba048..d4f3c8c 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -686,7 +686,7 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
#ifdef HAVE_DRM_PLATFORM
case _EGL_PLATFORM_DRM:
if (dri2_dpy->own_device) {
- gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
+ gbm_device_destroy(&dri2_dpy->gbm_drm->base);
}
break;
#endif
@@ -2018,8 +2018,11 @@ dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
#ifdef HAVE_DRM_PLATFORM
/* We have to share the wl_drm instance with gbm, so gbm can convert
* wl_buffers to gbm bos. */
- if (dri2_dpy->gbm_dri)
- dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
+ if (dri2_dpy->gbm_drm &&
+ dri2_dpy->gbm_drm->type == GBM_DRM_DRIVER_TYPE_DRI) {
+ struct gbm_dri_device *gbm_dri = gbm_dri_device(&dri2_dpy->gbm_drm->base);
+ gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
+ }
#endif
return EGL_TRUE;
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 7c19f5e..bad5fb0 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -44,6 +44,7 @@
#include <GL/internal/dri_interface.h>
#ifdef HAVE_DRM_PLATFORM
+#include <common_drm.h>
#include <gbm_driint.h>
#endif
@@ -167,7 +168,7 @@ struct dri2_egl_display
int max_swap_interval;
int default_swap_interval;
#ifdef HAVE_DRM_PLATFORM
- struct gbm_dri_device *gbm_dri;
+ struct gbm_drm_device *gbm_drm;
#endif
char *device_name;
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 0c3ffd2..d7c3f3f 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -39,6 +39,10 @@
#include "egl_dri2_fallbacks.h"
#include "loader.h"
+static __DRIimage *
+bo_to_dri_image(struct gbm_bo *bo, struct dri2_egl_display *dri2_dpy,
+ void *loaderPrivate);
+
static struct gbm_bo *
lock_front_buffer(struct gbm_surface *surf)
{
@@ -92,6 +96,7 @@ dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
struct dri2_egl_surface *dri2_surf;
struct gbm_surface *surf = native_window;
+ void *loaderPrivate;
(void) drv;
@@ -117,10 +122,15 @@ dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
goto cleanup_surf;
}
+ if (dri2_dpy->gbm_drm->type == GBM_DRM_DRIVER_TYPE_DRI)
+ loaderPrivate = dri2_surf->gbm_surface;
+ else
+ loaderPrivate = dri2_surf;
+
dri2_surf->dri_drawable =
(*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
dri2_conf->dri_double_config,
- dri2_surf->gbm_surface);
+ loaderPrivate);
if (dri2_surf->dri_drawable == NULL) {
_eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
@@ -207,7 +217,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
if (dri2_surf->back == NULL)
return -1;
if (dri2_surf->back->bo == NULL)
- dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
+ dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_drm->base,
surf->width, surf->height,
surf->format, surf->flags);
if (dri2_surf->back->bo == NULL)
@@ -343,14 +353,14 @@ dri2_drm_image_get_buffers(__DRIdrawable *driDrawable,
struct __DRIimageList *buffers)
{
struct dri2_egl_surface *dri2_surf = loaderPrivate;
- struct gbm_dri_bo *bo;
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
if (get_back_bo(dri2_surf) < 0)
return 0;
- bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
- buffers->back = bo->image;
+ buffers->back = bo_to_dri_image(dri2_surf->back->bo, dri2_dpy, NULL);
return 1;
}
@@ -362,6 +372,13 @@ dri2_drm_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
(void) loaderPrivate;
}
+static const __DRIimageLoaderExtension image_loader_extension = {
+ .base = { __DRI_IMAGE_LOADER, 1 },
+
+ .getBuffers = dri2_drm_image_get_buffers,
+ .flushFrontBuffer = dri2_drm_flush_front_buffer,
+};
+
static EGLBoolean
dri2_drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
{
@@ -400,12 +417,78 @@ dri2_drm_query_buffer_age(_EGLDriver *drv,
return dri2_surf->back->age;
}
+static __DRIimage *
+native_gbm_bo_to_dri_image(struct gbm_bo *bo,
+ struct dri2_egl_display *dri2_dpy,
+ void *loaderPrivate)
+{
+ __DRIimage *image;
+ struct gbm_drm_bo *drm_bo;
+ int width, height, pitch, format, cpp;
+
+ width = gbm_bo_get_width(bo);
+ height = gbm_bo_get_height(bo);
+
+ switch (gbm_bo_get_format(bo)) {
+ case GBM_FORMAT_RGB565:
+ cpp = 2;
+ format = __DRI_IMAGE_FORMAT_RGB565;
+ break;
+ case GBM_FORMAT_XRGB8888:
+ case GBM_BO_FORMAT_XRGB8888:
+ cpp = 4;
+ format = __DRI_IMAGE_FORMAT_XRGB8888;
+ break;
+ case GBM_BO_FORMAT_ARGB8888:
+ case GBM_FORMAT_ARGB8888:
+ cpp = 4;
+ format = __DRI_IMAGE_FORMAT_ARGB8888;
+ break;
+ default:
+ return NULL;
+ }
+
+ pitch = gbm_bo_get_stride(bo) / cpp;
+
+ drm_bo = (struct gbm_drm_bo *) bo;
+
+ image =
+ dri2_dpy->image->createImageFromHandle(dri2_dpy->dri_screen,
+ width, height, format,
+ drm_bo->bo, pitch, loaderPrivate);
+
+ return image;
+}
+
+static __DRIimage *
+dri_gbm_bo_to_dri_image(struct gbm_bo *bo, struct dri2_egl_display *dri2_dpy,
+ void *loaderPrivate)
+{
+ struct gbm_dri_bo *dri_bo = gbm_dri_bo(bo);
+
+ return dri2_dpy->image->dupImage(dri_bo->image, loaderPrivate);
+}
+
+static __DRIimage *
+bo_to_dri_image(struct gbm_bo *bo, struct dri2_egl_display *dri2_dpy,
+ void *loaderPrivate)
+{
+ switch (dri2_dpy->gbm_drm->type) {
+ case GBM_DRM_DRIVER_TYPE_DRI:
+ return dri_gbm_bo_to_dri_image(bo, dri2_dpy, loaderPrivate);
+ case GBM_DRM_DRIVER_TYPE_NATIVE:
+ return native_gbm_bo_to_dri_image(bo, dri2_dpy, loaderPrivate);
+ default:
+ return NULL;
+ }
+}
+
static _EGLImage *
dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
EGLClientBuffer buffer, const EGLint *attr_list)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
+ struct gbm_bo *bo = (struct gbm_bo *) buffer;
struct dri2_egl_image *dri2_img;
dri2_img = malloc(sizeof *dri2_img);
@@ -419,7 +502,7 @@ dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
return NULL;
}
- dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
+ dri2_img->dri_image = bo_to_dri_image(bo, dri2_dpy, dri2_img);
if (dri2_img->dri_image == NULL) {
free(dri2_img);
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
@@ -469,11 +552,90 @@ static struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
.create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
};
+static EGLBoolean
+dri2_initialize_gbm_dri(_EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy = disp->DriverData;
+ struct gbm_dri_device *gbm_dri;
+
+ _eglLog(_EGL_DEBUG, "DRM: GBM is using DRI backend");
+
+ gbm_dri = gbm_dri_device(&dri2_dpy->gbm_drm->base);
+
+ dri2_dpy->driver_name = gbm_dri->base.driver_name;
+
+ dri2_dpy->dri_screen = gbm_dri->screen;
+ dri2_dpy->core = gbm_dri->core;
+ dri2_dpy->dri2 = gbm_dri->dri2;
+ dri2_dpy->image = gbm_dri->image;
+ dri2_dpy->flush = gbm_dri->flush;
+ dri2_dpy->driver_configs = gbm_dri->driver_configs;
+
+ gbm_dri->lookup_image = dri2_lookup_egl_image;
+ gbm_dri->lookup_user_data = disp;
+
+ gbm_dri->get_buffers = dri2_drm_get_buffers;
+ gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
+ gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;
+ gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
+
+ dri2_setup_screen(disp);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_initialize_gbm_native(_EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy = disp->DriverData;
+
+ _eglLog(_EGL_DEBUG, "DRM: GBM is using native backend");
+
+ if (!dri2_dpy->gbm_drm->bufmgr)
+ return EGL_FALSE;
+
+ dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
+ if (!dri2_dpy->driver_name)
+ return EGL_FALSE;
+
+ if (!dri2_load_driver(disp))
+ goto cleanup_driver_name;
+
+ dri2_dpy->shared_bufmgr_extension.base.name = __DRI_SHARED_BUFMGR;
+ dri2_dpy->shared_bufmgr_extension.base.version = 1;
+ dri2_dpy->shared_bufmgr_extension.bufmgr = dri2_dpy->gbm_drm->bufmgr;
+ dri2_dpy->extensions[0] = &image_loader_extension.base;
+ dri2_dpy->extensions[1] = &image_lookup_extension.base;
+ dri2_dpy->extensions[2] = &use_invalidate.base;
+ dri2_dpy->extensions[3] = &dri2_dpy->shared_bufmgr_extension.base;
+ dri2_dpy->extensions[4] = NULL;
+
+ if (!dri2_create_screen(disp))
+ goto cleanup_driver;
+
+ if (dri2_dpy->image->base.version < 9 ||
+ dri2_dpy->image->createImageFromHandle == NULL)
+ goto cleanup_screen;
+
+ return EGL_TRUE;
+
+cleanup_screen:
+ _eglCleanupDisplay(disp);
+ dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
+cleanup_driver:
+ dlclose(dri2_dpy->driver);
+cleanup_driver_name:
+ free(dri2_dpy->driver_name);
+
+ return EGL_FALSE;
+}
+
EGLBoolean
dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy;
struct gbm_device *gbm;
+ EGLBoolean ret;
int fd = -1;
int i;
@@ -499,11 +661,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
return EGL_FALSE;
}
- dri2_dpy->gbm_dri = gbm_dri_device(gbm);
- if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
- free(dri2_dpy);
- return EGL_FALSE;
- }
+ dri2_dpy->gbm_drm = gbm_drm_device(gbm);
if (fd < 0) {
fd = dup(gbm_device_get_fd(gbm));
@@ -515,28 +673,25 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
dri2_dpy->fd = fd;
dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
- dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
-
- dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
- dri2_dpy->core = dri2_dpy->gbm_dri->core;
- dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
- dri2_dpy->image = dri2_dpy->gbm_dri->image;
- dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
- dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
- dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
- dri2_dpy->gbm_dri->lookup_user_data = disp;
-
- dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers;
- dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
- dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;
- dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
+ if (dri2_dpy->gbm_drm->type == GBM_DRM_DRIVER_TYPE_DRI) {
+ ret = dri2_initialize_gbm_dri(disp);
+ } else if (dri2_dpy->gbm_drm->type == GBM_DRM_DRIVER_TYPE_NATIVE) {
+ ret = dri2_initialize_gbm_native(disp);
+ } else {
+ _eglLog(_EGL_FATAL, "Unsupported GBM backend type");
+ ret = EGL_FALSE;
+ }
- dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
- dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
- dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
+ if (ret == EGL_FALSE) {
+ free(dri2_dpy);
+ close(fd);
+ return EGL_FALSE;
+ }
- dri2_setup_screen(disp);
+ gbm->surface_lock_front_buffer = lock_front_buffer;
+ gbm->surface_release_buffer = release_buffer;
+ gbm->surface_has_free_buffers = has_free_buffers;
for (i = 0; dri2_dpy->driver_configs[i]; i++) {
EGLint format, attr_list[3];
diff --git a/src/gbm/main/common_drm.h b/src/gbm/main/common_drm.h
index c49a6f9..30d8ec2 100644
--- a/src/gbm/main/common_drm.h
+++ b/src/gbm/main/common_drm.h
@@ -52,4 +52,10 @@ struct gbm_drm_bo {
void *bo;
};
+static inline struct gbm_drm_device *
+gbm_drm_device(struct gbm_device *gbm)
+{
+ return (struct gbm_drm_device *) gbm;
+}
+
#endif
--
1.8.3.2
More information about the mesa-dev
mailing list