summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2016-05-01 09:35:28 +0100
committerEmil Velikov <emil.l.velikov@gmail.com>2016-05-01 12:31:29 +0100
commit34ddef39cefc15ac6c82815c6339f5b666bb08d4 (patch)
tree46ddc34f20270d5a52b0be3387c9599c2e7895a2
parent81a6fff4c5246c0604b065a6b34145cdad9be423 (diff)
egl: android: add dma-buf fd support
Add support for creating images from Android native buffers with dma-buf fd. As dma-buf support also requires DRI image loader extension, add that as well. This is based on several originally patches written by Varad Gautam. I've collapsed them into logical changes and done a bit of reformatting. Using dma-bufs vs. GEM handles is now a runtime decision similar to the wayland EGL instead of being compile time selection. The dma-buf support is also re-written to use common dri2_create_image_dma_buf function in egl_dri2.c. Cc: Varad Gautam <varadgautam@gmail.com> Cc: Rob Clark <robdclark@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
-rw-r--r--src/egl/drivers/dri2/platform_android.c124
1 files changed, 117 insertions, 7 deletions
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index ea05818bc29..43ca45e3b39 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -65,6 +65,19 @@ get_format_bpp(int native)
return bpp;
}
+/* createImageFromFds requires fourcc format */
+static int get_fourcc(int format)
+{
+ switch(format) {
+ case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
+ case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
+ case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
+ case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
+ case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
+ }
+ return -1;
+}
+
static int get_format(int format)
{
switch (format) {
@@ -80,6 +93,18 @@ static int get_format(int format)
return -1;
}
static int
+get_native_buffer_fd(struct ANativeWindowBuffer *buf)
+{
+ native_handle_t *handle = (native_handle_t *)buf->handle;
+ /*
+ * Various gralloc implementations exist, but the dma-buf fd tends
+ * to be first. Access it directly to avoid a dependency on specific
+ * gralloc versions.
+ */
+ return (handle && handle->numFds) ? handle->data[0] : -1;
+}
+
+static int
get_native_buffer_name(struct ANativeWindowBuffer *buf)
{
return gralloc_drm_get_gem_handle(buf->handle);
@@ -333,6 +358,66 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
return 0;
}
+static int
+get_back_bo(struct dri2_egl_surface *dri2_surf)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ int format, stride;
+ int offset = 0, fd;
+
+ if (!dri2_surf->buffer)
+ return -1;
+
+ fd = get_native_buffer_fd(dri2_surf->buffer);
+ if (fd < 0)
+ return -1;
+
+ format = get_format(dri2_surf->buffer->format);
+
+ stride = dri2_surf->buffer->stride *
+ get_format_bpp(dri2_surf->buffer->format);
+
+ dri2_surf->dri_image =
+ dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ get_fourcc(format),
+ &fd,
+ 1,
+ &stride,
+ &offset,
+ dri2_surf);
+ if (!dri2_surf->dri_image)
+ return -1;
+
+ return 0;
+}
+
+static int
+droid_image_get_buffers(__DRIdrawable *driDrawable,
+ unsigned int format,
+ uint32_t *stamp,
+ void *loaderPrivate,
+ uint32_t buffer_mask,
+ struct __DRIimageList *images)
+{
+ struct dri2_egl_surface *dri2_surf = loaderPrivate;
+
+ if (update_buffers(dri2_surf) < 0)
+ return 0;
+
+ if (get_back_bo(dri2_surf) < 0) {
+ _eglError(EGL_BAD_PARAMETER, "get_back_bo");
+ return 0;
+ }
+
+ images->image_mask = __DRI_IMAGE_BUFFER_BACK;
+ images->back = dri2_surf->dri_image;
+
+ return 1;
+}
+
static EGLBoolean
droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
{
@@ -361,12 +446,13 @@ droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
}
static _EGLImage *
-dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+dri2_create_image_android_native_buffer(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLContext *ctx,
struct ANativeWindowBuffer *buf)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_image *dri2_img;
- int name;
+ int name, fd;
if (ctx != NULL) {
/* From the EGL_ANDROID_image_native_buffer spec:
@@ -386,6 +472,22 @@ dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
return NULL;
}
+ fd = get_native_buffer_fd(buf);
+ if (fd >= 0) {
+ const EGLint attr_list[14] = {
+ EGL_WIDTH, buf->width,
+ EGL_HEIGHT, buf->height,
+ EGL_LINUX_DRM_FOURCC_EXT, get_fourcc(get_format(buf->format)),
+ EGL_DMA_BUF_PLANE0_FD_EXT, fd,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, buf->stride * get_format_bpp(buf->format),
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
+ EGL_NONE, 0
+ };
+
+ return dri2_create_image_khr(drv, disp, ctx, EGL_LINUX_DMA_BUF_EXT,
+ NULL, attr_list);
+ }
+
name = get_native_buffer_name(buf);
if (!name) {
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
@@ -427,7 +529,7 @@ droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
{
switch (target) {
case EGL_NATIVE_BUFFER_ANDROID:
- return dri2_create_image_android_native_buffer(disp, ctx,
+ return dri2_create_image_android_native_buffer(drv, disp, ctx,
(struct ANativeWindowBuffer *) buffer);
default:
return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
@@ -663,6 +765,13 @@ static struct dri2_egl_display_vtbl droid_display_vtbl = {
.get_dri_drawable = dri2_surface_get_dri_drawable,
};
+static const __DRIimageLoaderExtension droid_image_loader_extension = {
+ .base = { __DRI_IMAGE_LOADER, 1 },
+
+ .getBuffers = droid_image_get_buffers,
+ .flushFrontBuffer = droid_flush_front_buffer,
+};
+
EGLBoolean
dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
{
@@ -698,8 +807,9 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
- dri2_dpy->extensions[0] = &image_lookup_extension.base;
+ dri2_dpy->extensions[0] = &droid_image_loader_extension.base;
dri2_dpy->extensions[1] = &use_invalidate.base;
+ dri2_dpy->extensions[2] = &image_lookup_extension.base;
/* render nodes cannot use Gem names, and thus do not support
* the __DRI_DRI2_LOADER extension */
@@ -710,10 +820,10 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
dri2_dpy->dri2_loader_extension.flushFrontBuffer = droid_flush_front_buffer;
dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
droid_get_buffers_with_format;
- dri2_dpy->extensions[2] = &dri2_dpy->dri2_loader_extension.base;
- dri2_dpy->extensions[3] = NULL;
+ dri2_dpy->extensions[3] = &dri2_dpy->dri2_loader_extension.base;
+ dri2_dpy->extensions[4] = NULL;
} else
- dri2_dpy->extensions[2] = NULL;
+ dri2_dpy->extensions[3] = NULL;
if (!dri2_create_screen(dpy)) {