From: Christopher James Halse Rogers <r...@ubuntu.com> Enabled based on kernel drm support for dma-buf.
v2: Detect dma-buf support from st/dri rather than adding a PIPE_CAP_PRIME --- src/gallium/drivers/freedreno/freedreno_screen.c | 5 + src/gallium/drivers/nouveau/nouveau_screen.c | 6 + src/gallium/include/state_tracker/drm_driver.h | 9 +- src/gallium/state_trackers/dri/drm/dri2.c | 125 +++++++++++++++++++-- .../state_trackers/egl/common/native_helper.c | 1 + src/gallium/state_trackers/egl/x11/native_dri2.c | 1 + src/gallium/winsys/i915/drm/i915_drm_buffer.c | 5 + src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 6 + 8 files changed, 147 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index b4fc20e..708baaf 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -431,6 +431,11 @@ fd_screen_bo_from_handle(struct pipe_screen *pscreen, struct fd_screen *screen = fd_screen(pscreen); struct fd_bo *bo; + if (whandle->type != DRM_API_HANDLE_TYPE_SHARED) { + DBG("Attempt to import unsupported handle type: %d", whandle->type); + return NULL; + } + bo = fd_bo_from_name(screen->dev, whandle->handle); if (!bo) { DBG("ref name 0x%08x failed", whandle->handle); diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index d129a55..e1d4ca5 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -86,6 +86,12 @@ nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, struct nouveau_bo *bo = 0; int ret; + if (whandle->type != DRM_API_HANDLE_TYPE_SHARED) { + debug_printf("%s: attempt to import unsupported handle type %d\n", + __FUNCTION__, whandle->type); + return NULL; + } + ret = nouveau_bo_name_ref(dev, whandle->handle, &bo); if (ret) { debug_printf("%s: ref name 0x%08x failed with %d\n", diff --git a/src/gallium/include/state_tracker/drm_driver.h b/src/gallium/include/state_tracker/drm_driver.h index f9bd222..5b76d87 100644 --- a/src/gallium/include/state_tracker/drm_driver.h +++ b/src/gallium/include/state_tracker/drm_driver.h @@ -10,6 +10,8 @@ struct pipe_resource; #define DRM_API_HANDLE_TYPE_SHARED 0 #define DRM_API_HANDLE_TYPE_KMS 1 +#define DRM_API_HANDLE_TYPE_FD 2 + /** * For use with pipe_screen::{texture_from_handle|texture_get_handle}. @@ -17,9 +19,10 @@ struct pipe_resource; struct winsys_handle { /** - * Unused for texture_from_handle, always - * DRM_API_HANDLE_TYPE_SHARED. Input to texture_get_handle, - * use TEXTURE_USAGE to select handle for kms or ipc. + * Input for texture_from_handle, valid values are + * DRM_API_HANDLE_TYPE_SHARED or DRM_API_HANDLE_TYPE_FD. + * Input to texture_get_handle, + * to select handle for kms, flink, or prime. */ unsigned type; /** diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index 1750ff0..f554f98 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -40,6 +40,8 @@ #include "dri_drawable.h" #include "dri2_buffer.h" +#include <xf86drm.h> + /** * DRI2 flush extension. */ @@ -231,6 +233,7 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable, templ.format = format; templ.bind = bind; + whandle.type = DRM_API_HANDLE_TYPE_SHARED; whandle.handle = buf->name; whandle.stride = buf->pitch; @@ -452,14 +455,14 @@ dri2_lookup_egl_image(struct dri_screen *screen, void *handle) } static __DRIimage * -dri2_create_image_from_name(__DRIscreen *_screen, - int width, int height, int format, - int name, int pitch, void *loaderPrivate) +dri2_create_image_from_winsys(__DRIscreen *_screen, + int width, int height, int format, + struct winsys_handle *whandle, int pitch, + void *loaderPrivate) { struct dri_screen *screen = dri_screen(_screen); __DRIimage *img; struct pipe_resource templ; - struct winsys_handle whandle; unsigned tex_usage; enum pipe_format pf; @@ -499,12 +502,10 @@ dri2_create_image_from_name(__DRIscreen *_screen, templ.depth0 = 1; templ.array_size = 1; - memset(&whandle, 0, sizeof(whandle)); - whandle.handle = name; - whandle.stride = pitch * util_format_get_blocksize(pf); + whandle->stride = pitch * util_format_get_blocksize(pf); img->texture = screen->base.screen->resource_from_handle(screen->base.screen, - &templ, &whandle); + &templ, whandle); if (!img->texture) { FREE(img); return NULL; @@ -519,6 +520,39 @@ dri2_create_image_from_name(__DRIscreen *_screen, } static __DRIimage * +dri2_create_image_from_name(__DRIscreen *_screen, + int width, int height, int format, + int name, int pitch, void *loaderPrivate) +{ + struct winsys_handle whandle; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + whandle.handle = name; + + return dri2_create_image_from_winsys(_screen, width, height, format, + &whandle, pitch, loaderPrivate); +} + +static __DRIimage * +dri2_create_image_from_fd(__DRIscreen *_screen, + int width, int height, int format, + int fd, int pitch, void *loaderPrivate) +{ + struct winsys_handle whandle; + + if (fd < 0) + return NULL; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_FD; + whandle.handle = (unsigned)fd; + + return dri2_create_image_from_winsys(_screen, width, height, format, + &whandle, pitch, loaderPrivate); +} + +static __DRIimage * dri2_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { @@ -626,6 +660,12 @@ dri2_query_image(__DRIimage *image, int attrib, int *value) image->texture, &whandle); *value = whandle.handle; return GL_TRUE; + case __DRI_IMAGE_ATTRIB_FD: + whandle.type= DRM_API_HANDLE_TYPE_FD; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.handle; + return GL_TRUE; case __DRI_IMAGE_ATTRIB_FORMAT: *value = image->dri_format; return GL_TRUE; @@ -749,6 +789,67 @@ dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) return img; } +static __DRIimage * +dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, + int depth, int level, unsigned *error, + void *loaderPrivate) +{ + /* Bad parameter seems like the least-incorrect error */ + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; +} + +static __DRIimage * +dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, + int *fds, int num_fds, int *strides, int *offsets, + void *loaderPrivate) +{ + __DRIimage *img; + int format, stride, dri_components; + + if (num_fds != 1) + return NULL; + if (offsets[0] != 0) + return NULL; + + switch(fourcc) { + case __DRI_IMAGE_FOURCC_RGB565: + format = __DRI_IMAGE_FORMAT_RGB565; + dri_components = __DRI_IMAGE_COMPONENTS_RGB; + break; + case __DRI_IMAGE_FOURCC_ARGB8888: + format = __DRI_IMAGE_FORMAT_ARGB8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGBA; + break; + case __DRI_IMAGE_FOURCC_XRGB8888: + format = __DRI_IMAGE_FORMAT_XRGB8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGB; + break; + case __DRI_IMAGE_FOURCC_ABGR8888: + format = __DRI_IMAGE_FORMAT_ABGR8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGBA; + break; + case __DRI_IMAGE_FOURCC_XBGR8888: + format = __DRI_IMAGE_FORMAT_XBGR8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGB; + break; + default: + return NULL; + } + + /* Strides are in bytes not pixels. */ + stride = strides[0] /4; + + img = dri2_create_image_from_fd(screen, width, height, format, + fds[0], stride, loaderPrivate); + if (img == NULL) + return NULL; + + img->dri_components = dri_components; + return img; +} + + static void dri2_destroy_image(__DRIimage *img) { @@ -794,6 +895,7 @@ dri2_init_screen(__DRIscreen * sPriv) struct dri_screen *screen; struct pipe_screen *pscreen; const struct drm_conf_ret *throttle_ret = NULL; + uint64_t prime_caps; screen = CALLOC_STRUCT(dri_screen); if (!screen) @@ -813,6 +915,13 @@ dri2_init_screen(__DRIscreen * sPriv) screen->default_throttle_frames = throttle_ret->val.val_int; } + drmGetCap(screen->fd, DRM_CAP_PRIME, &prime_caps); + if (prime_caps & (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT)) { + dri2ImageExtension.base.version = 7; + dri2ImageExtension.createImageFromTexture = dri2_create_from_texture; + dri2ImageExtension.createImageFromFds = dri2_from_fds; + } + sPriv->extensions = dri_screen_extensions; /* dri_init_screen_helper checks pscreen for us */ diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index 99259b8..eda6668 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.c +++ b/src/gallium/state_trackers/egl/common/native_helper.c @@ -428,6 +428,7 @@ drm_display_import_native_buffer(struct native_display *ndpy, memset(&wsh, 0, sizeof(wsh)); wsh.handle = nbuf->u.drm.name; + wsh.type = DRM_API_HANDLE_TYPE_SHARED; wsh.stride = nbuf->u.drm.stride; res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh); diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index fc18a4c..673e3d7 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -177,6 +177,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, } memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; whandle.stride = xbuf->pitch; whandle.handle = xbuf->name; dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( diff --git a/src/gallium/winsys/i915/drm/i915_drm_buffer.c b/src/gallium/winsys/i915/drm/i915_drm_buffer.c index ac66af3..1f84cc6 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_buffer.c +++ b/src/gallium/winsys/i915/drm/i915_drm_buffer.c @@ -101,6 +101,11 @@ i915_drm_buffer_from_handle(struct i915_winsys *iws, if (!buf) return NULL; + if (whandle->type != DRM_API_HANDLE_TYPE_SHARED) { + assert(!"Unsupported handle type"); + return NULL; + } + buf->magic = 0xDEAD1337; buf->bo = drm_intel_bo_gem_create_from_name(idws->gem_manager, "gallium3d_from_handle", whandle->handle); buf->flinked = TRUE; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index 6ec1713..6fd1fdc 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -873,6 +873,12 @@ static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws, struct drm_gem_open open_arg = {}; int r; + if (whandle->type != DRM_API_HANDLE_TYPE_SHARED) { + fprintf(stderr, "Attempted to import unsupported handle type %d\n", + whandle->type); + return NULL; + } + memset(&open_arg, 0, sizeof(open_arg)); /* We must maintain a list of pairs <handle, bo>, so that we always return -- 1.8.1.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev