[Mesa-dev] [PATCH 1/4] st/dri: move image extension into the common file
gurchetansingh at chromium.org
gurchetansingh at chromium.org
Fri Jun 9 00:26:36 UTC 2017
From: Gurchetan Singh <gurchetansingh at chromium.org>
This image extension is is needed by the Android studio emulator
when using the host's GLES implementation.
This patch moves the extension code from dri2.c to dri_extensions.c.
Since some functions in this extension are initialized at runtime by
dri2.c, we need to expose them in dri_extensions.h.
---
src/gallium/state_trackers/dri/dri2.c | 756 -----------------------
src/gallium/state_trackers/dri/dri_extensions.c | 770 +++++++++++++++++++++++-
src/gallium/state_trackers/dri/dri_extensions.h | 17 +
3 files changed, 784 insertions(+), 759 deletions(-)
diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index 625678f257..b68d93bdaa 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -35,7 +35,6 @@
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_debug.h"
-#include "state_tracker/drm_driver.h"
#include "state_tracker/st_cb_bufferobjects.h"
#include "state_tracker/st_cb_fbo.h"
#include "state_tracker/st_cb_texture.h"
@@ -52,126 +51,6 @@
#include "dri_query_renderer.h"
#include "dri2_buffer.h"
-static int convert_fourcc(int format, int *dri_components_p)
-{
- int dri_components;
- switch(format) {
- 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;
- case __DRI_IMAGE_FOURCC_R8:
- format = __DRI_IMAGE_FORMAT_R8;
- dri_components = __DRI_IMAGE_COMPONENTS_R;
- break;
- case __DRI_IMAGE_FOURCC_GR88:
- format = __DRI_IMAGE_FORMAT_GR88;
- dri_components = __DRI_IMAGE_COMPONENTS_RG;
- break;
- /*
- * For multi-planar YUV formats, we return the format of the first
- * plane only. Since there is only one caller which supports multi-
- * planar YUV it gets to figure out the remaining planes on it's
- * own.
- */
- case __DRI_IMAGE_FOURCC_YUV420:
- case __DRI_IMAGE_FOURCC_YVU420:
- format = __DRI_IMAGE_FORMAT_R8;
- dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
- break;
- case __DRI_IMAGE_FOURCC_NV12:
- format = __DRI_IMAGE_FORMAT_R8;
- dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
- break;
- default:
- return -1;
- }
- *dri_components_p = dri_components;
- return format;
-}
-
-/* NOTE this probably isn't going to do the right thing for YUV images
- * (but I think the same can be said for intel_query_image()). I think
- * only needed for exporting dmabuf's, so I think I won't loose much
- * sleep over it.
- */
-static int convert_to_fourcc(int format)
-{
- switch(format) {
- case __DRI_IMAGE_FORMAT_RGB565:
- format = __DRI_IMAGE_FOURCC_RGB565;
- break;
- case __DRI_IMAGE_FORMAT_ARGB8888:
- format = __DRI_IMAGE_FOURCC_ARGB8888;
- break;
- case __DRI_IMAGE_FORMAT_XRGB8888:
- format = __DRI_IMAGE_FOURCC_XRGB8888;
- break;
- case __DRI_IMAGE_FORMAT_ABGR8888:
- format = __DRI_IMAGE_FOURCC_ABGR8888;
- break;
- case __DRI_IMAGE_FORMAT_XBGR8888:
- format = __DRI_IMAGE_FOURCC_XBGR8888;
- break;
- case __DRI_IMAGE_FORMAT_R8:
- format = __DRI_IMAGE_FOURCC_R8;
- break;
- case __DRI_IMAGE_FORMAT_GR88:
- format = __DRI_IMAGE_FOURCC_GR88;
- break;
- default:
- return -1;
- }
- return format;
-}
-
-static enum pipe_format dri2_format_to_pipe_format (int format)
-{
- enum pipe_format pf;
-
- switch (format) {
- case __DRI_IMAGE_FORMAT_RGB565:
- pf = PIPE_FORMAT_B5G6R5_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_XRGB8888:
- pf = PIPE_FORMAT_BGRX8888_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_ARGB8888:
- pf = PIPE_FORMAT_BGRA8888_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_ABGR8888:
- pf = PIPE_FORMAT_RGBA8888_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_R8:
- pf = PIPE_FORMAT_R8_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_GR88:
- pf = PIPE_FORMAT_RG88_UNORM;
- break;
- default:
- pf = PIPE_FORMAT_NONE;
- break;
- }
-
- return pf;
-}
-
/**
* DRI2 flush extension.
*/
@@ -780,641 +659,6 @@ dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
return img;
}
-static __DRIimage *
-dri2_create_image_from_winsys(__DRIscreen *_screen,
- int width, int height, int format,
- int num_handles, struct winsys_handle *whandle,
- void *loaderPrivate)
-{
- struct dri_screen *screen = dri_screen(_screen);
- struct pipe_screen *pscreen = screen->base.screen;
- __DRIimage *img;
- struct pipe_resource templ;
- unsigned tex_usage;
- enum pipe_format pf;
- int i;
-
- tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
-
- pf = dri2_format_to_pipe_format (format);
- if (pf == PIPE_FORMAT_NONE)
- return NULL;
-
- img = CALLOC_STRUCT(__DRIimageRec);
- if (!img)
- return NULL;
-
- memset(&templ, 0, sizeof(templ));
- templ.bind = tex_usage;
- templ.target = screen->target;
- templ.last_level = 0;
- templ.depth0 = 1;
- templ.array_size = 1;
-
- for (i = num_handles - 1; i >= 0; i--) {
- struct pipe_resource *tex;
-
- /* TODO: something a lot less ugly */
- switch (i) {
- case 0:
- templ.width0 = width;
- templ.height0 = height;
- templ.format = pf;
- break;
- case 1:
- templ.width0 = width / 2;
- templ.height0 = height / 2;
- templ.format = (num_handles == 2) ?
- PIPE_FORMAT_RG88_UNORM : /* NV12, etc */
- PIPE_FORMAT_R8_UNORM; /* I420, etc */
- break;
- case 2:
- templ.width0 = width / 2;
- templ.height0 = height / 2;
- templ.format = PIPE_FORMAT_R8_UNORM;
- break;
- default:
- unreachable("too many planes!");
- }
-
- tex = pscreen->resource_from_handle(pscreen,
- &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
- if (!tex) {
- pipe_resource_reference(&img->texture, NULL);
- FREE(img);
- return NULL;
- }
-
- tex->next = img->texture;
- img->texture = tex;
- }
-
- img->level = 0;
- img->layer = 0;
- img->dri_format = format;
- img->use = 0;
- img->loader_private = loaderPrivate;
-
- return img;
-}
-
-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;
- enum pipe_format pf;
-
- memset(&whandle, 0, sizeof(whandle));
- whandle.type = DRM_API_HANDLE_TYPE_SHARED;
- whandle.handle = name;
-
- pf = dri2_format_to_pipe_format (format);
- if (pf == PIPE_FORMAT_NONE)
- return NULL;
-
- whandle.stride = pitch * util_format_get_blocksize(pf);
-
- return dri2_create_image_from_winsys(_screen, width, height, format,
- 1, &whandle, loaderPrivate);
-}
-
-static __DRIimage *
-dri2_create_image_from_fd(__DRIscreen *_screen,
- int width, int height, int fourcc,
- int *fds, int num_fds, int *strides,
- int *offsets, unsigned *error,
- int *dri_components, void *loaderPrivate)
-{
- struct winsys_handle whandles[3];
- int format;
- __DRIimage *img = NULL;
- unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
- int expected_num_fds, i;
-
- switch (fourcc) {
- case __DRI_IMAGE_FOURCC_YUV420:
- case __DRI_IMAGE_FOURCC_YVU420:
- expected_num_fds = 3;
- break;
- case __DRI_IMAGE_FOURCC_NV12:
- expected_num_fds = 2;
- break;
- default:
- expected_num_fds = 1;
- break;
- }
-
- if (num_fds != expected_num_fds) {
- err = __DRI_IMAGE_ERROR_BAD_MATCH;
- goto exit;
- }
-
- format = convert_fourcc(fourcc, dri_components);
- if (format == -1) {
- err = __DRI_IMAGE_ERROR_BAD_MATCH;
- goto exit;
- }
-
- memset(whandles, 0, sizeof(whandles));
-
- for (i = 0; i < num_fds; i++) {
- if (fds[i] < 0) {
- err = __DRI_IMAGE_ERROR_BAD_ALLOC;
- goto exit;
- }
-
- whandles[i].type = DRM_API_HANDLE_TYPE_FD;
- whandles[i].handle = (unsigned)fds[i];
- whandles[i].stride = (unsigned)strides[i];
- whandles[i].offset = (unsigned)offsets[i];
- }
-
- if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
- /* convert to YUV420 by swapping 2nd and 3rd planes: */
- struct winsys_handle tmp = whandles[1];
- whandles[1] = whandles[2];
- whandles[2] = tmp;
- fourcc = __DRI_IMAGE_FOURCC_YUV420;
- }
-
- img = dri2_create_image_from_winsys(_screen, width, height, format,
- num_fds, whandles, loaderPrivate);
- if(img == NULL)
- err = __DRI_IMAGE_ERROR_BAD_ALLOC;
-
-exit:
- if (error)
- *error = err;
-
- return img;
-}
-
-static __DRIimage *
-dri2_create_image_from_renderbuffer(__DRIcontext *context,
- int renderbuffer, void *loaderPrivate)
-{
- struct dri_context *ctx = dri_context(context);
-
- if (!ctx->st->get_resource_for_egl_image)
- return NULL;
-
- /* TODO */
- return NULL;
-}
-
-static __DRIimage *
-dri2_create_image(__DRIscreen *_screen,
- int width, int height, int format,
- unsigned int use, void *loaderPrivate)
-{
- struct dri_screen *screen = dri_screen(_screen);
- __DRIimage *img;
- struct pipe_resource templ;
- unsigned tex_usage;
- enum pipe_format pf;
-
- tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
- if (use & __DRI_IMAGE_USE_SCANOUT)
- tex_usage |= PIPE_BIND_SCANOUT;
- if (use & __DRI_IMAGE_USE_SHARE)
- tex_usage |= PIPE_BIND_SHARED;
- if (use & __DRI_IMAGE_USE_LINEAR)
- tex_usage |= PIPE_BIND_LINEAR;
- if (use & __DRI_IMAGE_USE_CURSOR) {
- if (width != 64 || height != 64)
- return NULL;
- tex_usage |= PIPE_BIND_CURSOR;
- }
-
- pf = dri2_format_to_pipe_format (format);
- if (pf == PIPE_FORMAT_NONE)
- return NULL;
-
- img = CALLOC_STRUCT(__DRIimageRec);
- if (!img)
- return NULL;
-
- memset(&templ, 0, sizeof(templ));
- templ.bind = tex_usage;
- templ.format = pf;
- templ.target = PIPE_TEXTURE_2D;
- templ.last_level = 0;
- templ.width0 = width;
- templ.height0 = height;
- templ.depth0 = 1;
- templ.array_size = 1;
-
- img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
- if (!img->texture) {
- FREE(img);
- return NULL;
- }
-
- img->level = 0;
- img->layer = 0;
- img->dri_format = format;
- img->dri_components = 0;
- img->use = use;
-
- img->loader_private = loaderPrivate;
- return img;
-}
-
-static GLboolean
-dri2_query_image(__DRIimage *image, int attrib, int *value)
-{
- struct winsys_handle whandle;
- unsigned usage;
-
- if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
- usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
- else
- usage = PIPE_HANDLE_USAGE_READ_WRITE;
-
- memset(&whandle, 0, sizeof(whandle));
-
- switch (attrib) {
- case __DRI_IMAGE_ATTRIB_STRIDE:
- whandle.type = DRM_API_HANDLE_TYPE_KMS;
- image->texture->screen->resource_get_handle(image->texture->screen,
- NULL, image->texture, &whandle, usage);
- *value = whandle.stride;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_HANDLE:
- whandle.type = DRM_API_HANDLE_TYPE_KMS;
- image->texture->screen->resource_get_handle(image->texture->screen,
- NULL, image->texture, &whandle, usage);
- *value = whandle.handle;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_NAME:
- whandle.type = DRM_API_HANDLE_TYPE_SHARED;
- image->texture->screen->resource_get_handle(image->texture->screen,
- NULL, image->texture, &whandle, usage);
- *value = whandle.handle;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_FD:
- whandle.type= DRM_API_HANDLE_TYPE_FD;
- if (!image->texture->screen->resource_get_handle(image->texture->screen,
- NULL, image->texture, &whandle, usage))
- return GL_FALSE;
-
- *value = whandle.handle;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_FORMAT:
- *value = image->dri_format;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_WIDTH:
- *value = image->texture->width0;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_HEIGHT:
- *value = image->texture->height0;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_COMPONENTS:
- if (image->dri_components == 0)
- return GL_FALSE;
- *value = image->dri_components;
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_FOURCC:
- *value = convert_to_fourcc(image->dri_format);
- return GL_TRUE;
- case __DRI_IMAGE_ATTRIB_NUM_PLANES:
- *value = 1;
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-static __DRIimage *
-dri2_dup_image(__DRIimage *image, void *loaderPrivate)
-{
- __DRIimage *img;
-
- img = CALLOC_STRUCT(__DRIimageRec);
- if (!img)
- return NULL;
-
- img->texture = NULL;
- pipe_resource_reference(&img->texture, image->texture);
- img->level = image->level;
- img->layer = image->layer;
- img->dri_format = image->dri_format;
- /* This should be 0 for sub images, but dup is also used for base images. */
- img->dri_components = image->dri_components;
- img->loader_private = loaderPrivate;
-
- return img;
-}
-
-static GLboolean
-dri2_validate_usage(__DRIimage *image, unsigned int use)
-{
- /*
- * Gallium drivers are bad at adding usages to the resources
- * once opened again in another process, which is the main use
- * case for this, so we have to lie.
- */
- if (image != NULL)
- return GL_TRUE;
- else
- return GL_FALSE;
-}
-
-static __DRIimage *
-dri2_from_names(__DRIscreen *screen, int width, int height, int format,
- int *names, int num_names, int *strides, int *offsets,
- void *loaderPrivate)
-{
- __DRIimage *img;
- int dri_components;
- struct winsys_handle whandle;
-
- if (num_names != 1)
- return NULL;
-
- format = convert_fourcc(format, &dri_components);
- if (format == -1)
- return NULL;
-
- memset(&whandle, 0, sizeof(whandle));
- whandle.type = DRM_API_HANDLE_TYPE_SHARED;
- whandle.handle = names[0];
- whandle.stride = strides[0];
- whandle.offset = offsets[0];
-
- img = dri2_create_image_from_winsys(screen, width, height, format,
- 1, &whandle, loaderPrivate);
- if (img == NULL)
- return NULL;
-
- img->dri_components = dri_components;
- return img;
-}
-
-static __DRIimage *
-dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
-{
- __DRIimage *img;
-
- if (plane != 0)
- return NULL;
-
- if (image->dri_components == 0)
- return NULL;
-
- img = dri2_dup_image(image, loaderPrivate);
- if (img == NULL)
- return NULL;
-
- if (img->texture->screen->resource_changed)
- img->texture->screen->resource_changed(img->texture->screen,
- img->texture);
-
- /* set this to 0 for sub images. */
- img->dri_components = 0;
- return img;
-}
-
-static __DRIimage *
-dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
- int depth, int level, unsigned *error,
- void *loaderPrivate)
-{
- __DRIimage *img;
- struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
- struct gl_texture_object *obj;
- struct pipe_resource *tex;
- GLuint face = 0;
-
- obj = _mesa_lookup_texture(ctx, texture);
- if (!obj || obj->Target != target) {
- *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
- return NULL;
- }
-
- tex = st_get_texobj_resource(obj);
- if (!tex) {
- *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
- return NULL;
- }
-
- if (target == GL_TEXTURE_CUBE_MAP)
- face = depth;
-
- _mesa_test_texobj_completeness(ctx, obj);
- if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
- *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
- return NULL;
- }
-
- if (level < obj->BaseLevel || level > obj->_MaxLevel) {
- *error = __DRI_IMAGE_ERROR_BAD_MATCH;
- return NULL;
- }
-
- if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
- *error = __DRI_IMAGE_ERROR_BAD_MATCH;
- return NULL;
- }
-
- img = CALLOC_STRUCT(__DRIimageRec);
- if (!img) {
- *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
- return NULL;
- }
-
- img->level = level;
- img->layer = depth;
- img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
-
- img->loader_private = loaderPrivate;
-
- if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
- *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
- free(img);
- return NULL;
- }
-
- pipe_resource_reference(&img->texture, tex);
-
- *error = __DRI_IMAGE_ERROR_SUCCESS;
- return img;
-}
-
-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 dri_components;
-
- img = dri2_create_image_from_fd(screen, width, height, fourcc,
- fds, num_fds, strides, offsets, NULL,
- &dri_components, loaderPrivate);
- if (img == NULL)
- return NULL;
-
- img->dri_components = dri_components;
- return img;
-}
-
-static __DRIimage *
-dri2_from_dma_bufs(__DRIscreen *screen,
- int width, int height, int fourcc,
- int *fds, int num_fds,
- int *strides, int *offsets,
- enum __DRIYUVColorSpace yuv_color_space,
- enum __DRISampleRange sample_range,
- enum __DRIChromaSiting horizontal_siting,
- enum __DRIChromaSiting vertical_siting,
- unsigned *error,
- void *loaderPrivate)
-{
- __DRIimage *img;
- int dri_components;
-
- img = dri2_create_image_from_fd(screen, width, height, fourcc,
- fds, num_fds, strides, offsets, error,
- &dri_components, loaderPrivate);
- if (img == NULL)
- return NULL;
-
- img->yuv_color_space = yuv_color_space;
- img->sample_range = sample_range;
- img->horizontal_siting = horizontal_siting;
- img->vertical_siting = vertical_siting;
- img->dri_components = dri_components;
-
- *error = __DRI_IMAGE_ERROR_SUCCESS;
- return img;
-}
-
-static void
-dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
- int dstx0, int dsty0, int dstwidth, int dstheight,
- int srcx0, int srcy0, int srcwidth, int srcheight,
- int flush_flag)
-{
- struct dri_context *ctx = dri_context(context);
- struct pipe_context *pipe = ctx->st->pipe;
- struct pipe_screen *screen;
- struct pipe_fence_handle *fence;
- struct pipe_blit_info blit;
-
- if (!dst || !src)
- return;
-
- memset(&blit, 0, sizeof(blit));
- blit.dst.resource = dst->texture;
- blit.dst.box.x = dstx0;
- blit.dst.box.y = dsty0;
- blit.dst.box.width = dstwidth;
- blit.dst.box.height = dstheight;
- blit.dst.box.depth = 1;
- blit.dst.format = dst->texture->format;
- blit.src.resource = src->texture;
- blit.src.box.x = srcx0;
- blit.src.box.y = srcy0;
- blit.src.box.width = srcwidth;
- blit.src.box.height = srcheight;
- blit.src.box.depth = 1;
- blit.src.format = src->texture->format;
- blit.mask = PIPE_MASK_RGBA;
- blit.filter = PIPE_TEX_FILTER_NEAREST;
-
- pipe->blit(pipe, &blit);
-
- if (flush_flag == __BLIT_FLAG_FLUSH) {
- pipe->flush_resource(pipe, dst->texture);
- ctx->st->flush(ctx->st, 0, NULL);
- } else if (flush_flag == __BLIT_FLAG_FINISH) {
- screen = dri_screen(ctx->sPriv)->base.screen;
- pipe->flush_resource(pipe, dst->texture);
- ctx->st->flush(ctx->st, 0, &fence);
- (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
- screen->fence_reference(screen, &fence, NULL);
- }
-}
-
-static void *
-dri2_map_image(__DRIcontext *context, __DRIimage *image,
- int x0, int y0, int width, int height,
- unsigned int flags, int *stride, void **data)
-{
- struct dri_context *ctx = dri_context(context);
- struct pipe_context *pipe = ctx->st->pipe;
- enum pipe_transfer_usage pipe_access = 0;
- struct pipe_transfer *trans;
- void *map;
-
- if (!image || !data || *data)
- return NULL;
-
- if (flags & __DRI_IMAGE_TRANSFER_READ)
- pipe_access |= PIPE_TRANSFER_READ;
- if (flags & __DRI_IMAGE_TRANSFER_WRITE)
- pipe_access |= PIPE_TRANSFER_WRITE;
-
- map = pipe_transfer_map(pipe, image->texture,
- 0, 0, pipe_access, x0, y0, width, height,
- &trans);
- if (map) {
- *data = trans;
- *stride = trans->stride;
- }
-
- return map;
-}
-
-static void
-dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
-{
- struct dri_context *ctx = dri_context(context);
- struct pipe_context *pipe = ctx->st->pipe;
-
- pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
-}
-
-static void
-dri2_destroy_image(__DRIimage *img)
-{
- pipe_resource_reference(&img->texture, NULL);
- FREE(img);
-}
-
-static int
-dri2_get_capabilities(__DRIscreen *_screen)
-{
- struct dri_screen *screen = dri_screen(_screen);
-
- return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
-}
-
-/* The extension is modified during runtime if DRI_PRIME is detected */
-static __DRIimageExtension dri2ImageExtension = {
- .base = { __DRI_IMAGE, 12 },
-
- .createImageFromName = dri2_create_image_from_name,
- .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
- .destroyImage = dri2_destroy_image,
- .createImage = dri2_create_image,
- .queryImage = dri2_query_image,
- .dupImage = dri2_dup_image,
- .validateUsage = dri2_validate_usage,
- .createImageFromNames = dri2_from_names,
- .fromPlanar = dri2_from_planar,
- .createImageFromTexture = dri2_create_from_texture,
- .createImageFromFds = NULL,
- .createImageFromDmaBufs = NULL,
- .blitImage = dri2_blit_image,
- .getCapabilities = dri2_get_capabilities,
- .mapImage = dri2_map_image,
- .unmapImage = dri2_unmap_image,
-};
-
static const __DRIrobustnessExtension dri2Robustness = {
.base = { __DRI2_ROBUSTNESS, 1 }
};
diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c
index b3a2cb78f9..c3daca1762 100644
--- a/src/gallium/state_trackers/dri/dri_extensions.c
+++ b/src/gallium/state_trackers/dri/dri_extensions.c
@@ -21,10 +21,139 @@
*/
#include <dlfcn.h>
-#include "dri_context.h"
-#include "dri_screen.h"
-#include "pipe/p_screen.h"
#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "state_tracker/st_texture.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/drm_driver.h"
+#include "pipe/p_screen.h"
+#include "main/texobj.h"
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_extensions.h"
+
+static int convert_fourcc(int format, int *dri_components_p)
+{
+ int dri_components;
+ switch(format) {
+ 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;
+ case __DRI_IMAGE_FOURCC_R8:
+ format = __DRI_IMAGE_FORMAT_R8;
+ dri_components = __DRI_IMAGE_COMPONENTS_R;
+ break;
+ case __DRI_IMAGE_FOURCC_GR88:
+ format = __DRI_IMAGE_FORMAT_GR88;
+ dri_components = __DRI_IMAGE_COMPONENTS_RG;
+ break;
+ /*
+ * For multi-planar YUV formats, we return the format of the first
+ * plane only. Since there is only one caller which supports multi-
+ * planar YUV it gets to figure out the remaining planes on it's
+ * own.
+ */
+ case __DRI_IMAGE_FOURCC_YUV420:
+ case __DRI_IMAGE_FOURCC_YVU420:
+ format = __DRI_IMAGE_FORMAT_R8;
+ dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
+ break;
+ case __DRI_IMAGE_FOURCC_NV12:
+ format = __DRI_IMAGE_FORMAT_R8;
+ dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
+ break;
+ default:
+ return -1;
+ }
+ *dri_components_p = dri_components;
+ return format;
+}
+
+/* NOTE this probably isn't going to do the right thing for YUV images
+ * (but I think the same can be said for intel_query_image()). I think
+ * only needed for exporting dmabuf's, so I think I won't loose much
+ * sleep over it.
+ */
+static int convert_to_fourcc(int format)
+{
+ switch(format) {
+ case __DRI_IMAGE_FORMAT_RGB565:
+ format = __DRI_IMAGE_FOURCC_RGB565;
+ break;
+ case __DRI_IMAGE_FORMAT_ARGB8888:
+ format = __DRI_IMAGE_FOURCC_ARGB8888;
+ break;
+ case __DRI_IMAGE_FORMAT_XRGB8888:
+ format = __DRI_IMAGE_FOURCC_XRGB8888;
+ break;
+ case __DRI_IMAGE_FORMAT_ABGR8888:
+ format = __DRI_IMAGE_FOURCC_ABGR8888;
+ break;
+ case __DRI_IMAGE_FORMAT_XBGR8888:
+ format = __DRI_IMAGE_FOURCC_XBGR8888;
+ break;
+ case __DRI_IMAGE_FORMAT_R8:
+ format = __DRI_IMAGE_FOURCC_R8;
+ break;
+ case __DRI_IMAGE_FORMAT_GR88:
+ format = __DRI_IMAGE_FOURCC_GR88;
+ break;
+ default:
+ return -1;
+ }
+ return format;
+}
+
+static enum pipe_format dri2_format_to_pipe_format (int format)
+{
+ enum pipe_format pf;
+
+ switch (format) {
+ case __DRI_IMAGE_FORMAT_RGB565:
+ pf = PIPE_FORMAT_B5G6R5_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_XRGB8888:
+ pf = PIPE_FORMAT_BGRX8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_ARGB8888:
+ pf = PIPE_FORMAT_BGRA8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_ABGR8888:
+ pf = PIPE_FORMAT_RGBA8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_R8:
+ pf = PIPE_FORMAT_R8_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_GR88:
+ pf = PIPE_FORMAT_RG88_UNORM;
+ break;
+ default:
+ pf = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return pf;
+}
+
static bool
dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
@@ -227,4 +356,639 @@ const __DRI2fenceExtension dri2FenceExtension = {
.get_fence_fd = dri2_get_fence_fd,
};
+static __DRIimage *
+dri2_create_image_from_winsys(__DRIscreen *_screen,
+ int width, int height, int format,
+ int num_handles, struct winsys_handle *whandle,
+ void *loaderPrivate)
+{
+ struct dri_screen *screen = dri_screen(_screen);
+ struct pipe_screen *pscreen = screen->base.screen;
+ __DRIimage *img;
+ struct pipe_resource templ;
+ unsigned tex_usage;
+ enum pipe_format pf;
+ int i;
+
+ tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+
+ pf = dri2_format_to_pipe_format (format);
+ if (pf == PIPE_FORMAT_NONE)
+ return NULL;
+
+ img = CALLOC_STRUCT(__DRIimageRec);
+ if (!img)
+ return NULL;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.bind = tex_usage;
+ templ.target = screen->target;
+ templ.last_level = 0;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+
+ for (i = num_handles - 1; i >= 0; i--) {
+ struct pipe_resource *tex;
+
+ /* TODO: something a lot less ugly */
+ switch (i) {
+ case 0:
+ templ.width0 = width;
+ templ.height0 = height;
+ templ.format = pf;
+ break;
+ case 1:
+ templ.width0 = width / 2;
+ templ.height0 = height / 2;
+ templ.format = (num_handles == 2) ?
+ PIPE_FORMAT_RG88_UNORM : /* NV12, etc */
+ PIPE_FORMAT_R8_UNORM; /* I420, etc */
+ break;
+ case 2:
+ templ.width0 = width / 2;
+ templ.height0 = height / 2;
+ templ.format = PIPE_FORMAT_R8_UNORM;
+ break;
+ default:
+ unreachable("too many planes!");
+ }
+
+ tex = pscreen->resource_from_handle(pscreen,
+ &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
+ if (!tex) {
+ pipe_resource_reference(&img->texture, NULL);
+ FREE(img);
+ return NULL;
+ }
+
+ tex->next = img->texture;
+ img->texture = tex;
+ }
+
+ img->level = 0;
+ img->layer = 0;
+ img->dri_format = format;
+ img->use = 0;
+ img->loader_private = loaderPrivate;
+
+ return img;
+}
+
+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;
+ enum pipe_format pf;
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+ whandle.handle = name;
+
+ pf = dri2_format_to_pipe_format (format);
+ if (pf == PIPE_FORMAT_NONE)
+ return NULL;
+
+ whandle.stride = pitch * util_format_get_blocksize(pf);
+
+ return dri2_create_image_from_winsys(_screen, width, height, format,
+ 1, &whandle, loaderPrivate);
+}
+
+static __DRIimage *
+dri2_create_image_from_fd(__DRIscreen *_screen,
+ int width, int height, int fourcc,
+ int *fds, int num_fds, int *strides,
+ int *offsets, unsigned *error,
+ int *dri_components, void *loaderPrivate)
+{
+ struct winsys_handle whandles[3];
+ int format;
+ __DRIimage *img = NULL;
+ unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
+ int expected_num_fds, i;
+
+ switch (fourcc) {
+ case __DRI_IMAGE_FOURCC_YUV420:
+ case __DRI_IMAGE_FOURCC_YVU420:
+ expected_num_fds = 3;
+ break;
+ case __DRI_IMAGE_FOURCC_NV12:
+ expected_num_fds = 2;
+ break;
+ default:
+ expected_num_fds = 1;
+ break;
+ }
+
+ if (num_fds != expected_num_fds) {
+ err = __DRI_IMAGE_ERROR_BAD_MATCH;
+ goto exit;
+ }
+
+ format = convert_fourcc(fourcc, dri_components);
+ if (format == -1) {
+ err = __DRI_IMAGE_ERROR_BAD_MATCH;
+ goto exit;
+ }
+
+ memset(whandles, 0, sizeof(whandles));
+
+ for (i = 0; i < num_fds; i++) {
+ if (fds[i] < 0) {
+ err = __DRI_IMAGE_ERROR_BAD_ALLOC;
+ goto exit;
+ }
+
+ whandles[i].type = DRM_API_HANDLE_TYPE_FD;
+ whandles[i].handle = (unsigned)fds[i];
+ whandles[i].stride = (unsigned)strides[i];
+ whandles[i].offset = (unsigned)offsets[i];
+ }
+
+ if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
+ /* convert to YUV420 by swapping 2nd and 3rd planes: */
+ struct winsys_handle tmp = whandles[1];
+ whandles[1] = whandles[2];
+ whandles[2] = tmp;
+ fourcc = __DRI_IMAGE_FOURCC_YUV420;
+ }
+
+ img = dri2_create_image_from_winsys(_screen, width, height, format,
+ num_fds, whandles, loaderPrivate);
+ if(img == NULL)
+ err = __DRI_IMAGE_ERROR_BAD_ALLOC;
+
+exit:
+ if (error)
+ *error = err;
+
+ return img;
+}
+
+static __DRIimage *
+dri2_create_image_from_renderbuffer(__DRIcontext *context,
+ int renderbuffer, void *loaderPrivate)
+{
+ struct dri_context *ctx = dri_context(context);
+
+ if (!ctx->st->get_resource_for_egl_image)
+ return NULL;
+
+ /* TODO */
+ return NULL;
+}
+
+static __DRIimage *
+dri2_create_image(__DRIscreen *_screen,
+ int width, int height, int format,
+ unsigned int use, void *loaderPrivate)
+{
+ struct dri_screen *screen = dri_screen(_screen);
+ __DRIimage *img;
+ struct pipe_resource templ;
+ unsigned tex_usage;
+ enum pipe_format pf;
+
+ tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+ if (use & __DRI_IMAGE_USE_SCANOUT)
+ tex_usage |= PIPE_BIND_SCANOUT;
+ if (use & __DRI_IMAGE_USE_SHARE)
+ tex_usage |= PIPE_BIND_SHARED;
+ if (use & __DRI_IMAGE_USE_LINEAR)
+ tex_usage |= PIPE_BIND_LINEAR;
+ if (use & __DRI_IMAGE_USE_CURSOR) {
+ if (width != 64 || height != 64)
+ return NULL;
+ tex_usage |= PIPE_BIND_CURSOR;
+ }
+
+ pf = dri2_format_to_pipe_format (format);
+ if (pf == PIPE_FORMAT_NONE)
+ return NULL;
+
+ img = CALLOC_STRUCT(__DRIimageRec);
+ if (!img)
+ return NULL;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.bind = tex_usage;
+ templ.format = pf;
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = width;
+ templ.height0 = height;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+
+ img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
+ if (!img->texture) {
+ FREE(img);
+ return NULL;
+ }
+
+ img->level = 0;
+ img->layer = 0;
+ img->dri_format = format;
+ img->dri_components = 0;
+ img->use = use;
+
+ img->loader_private = loaderPrivate;
+ return img;
+}
+
+static GLboolean
+dri2_query_image(__DRIimage *image, int attrib, int *value)
+{
+ struct winsys_handle whandle;
+ unsigned usage;
+
+ if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
+ usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
+ else
+ usage = PIPE_HANDLE_USAGE_READ_WRITE;
+
+ memset(&whandle, 0, sizeof(whandle));
+
+ switch (attrib) {
+ case __DRI_IMAGE_ATTRIB_STRIDE:
+ whandle.type = DRM_API_HANDLE_TYPE_KMS;
+ image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage);
+ *value = whandle.stride;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_HANDLE:
+ whandle.type = DRM_API_HANDLE_TYPE_KMS;
+ image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage);
+ *value = whandle.handle;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_NAME:
+ whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+ image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage);
+ *value = whandle.handle;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_FD:
+ whandle.type= DRM_API_HANDLE_TYPE_FD;
+ if (!image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage))
+ return GL_FALSE;
+
+ *value = whandle.handle;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_FORMAT:
+ *value = image->dri_format;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_WIDTH:
+ *value = image->texture->width0;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_HEIGHT:
+ *value = image->texture->height0;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_COMPONENTS:
+ if (image->dri_components == 0)
+ return GL_FALSE;
+ *value = image->dri_components;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_FOURCC:
+ *value = convert_to_fourcc(image->dri_format);
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_NUM_PLANES:
+ *value = 1;
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+static __DRIimage *
+dri2_dup_image(__DRIimage *image, void *loaderPrivate)
+{
+ __DRIimage *img;
+
+ img = CALLOC_STRUCT(__DRIimageRec);
+ if (!img)
+ return NULL;
+
+ img->texture = NULL;
+ pipe_resource_reference(&img->texture, image->texture);
+ img->level = image->level;
+ img->layer = image->layer;
+ img->dri_format = image->dri_format;
+ /* This should be 0 for sub images, but dup is also used for base images. */
+ img->dri_components = image->dri_components;
+ img->loader_private = loaderPrivate;
+
+ return img;
+}
+
+static GLboolean
+dri2_validate_usage(__DRIimage *image, unsigned int use)
+{
+ /*
+ * Gallium drivers are bad at adding usages to the resources
+ * once opened again in another process, which is the main use
+ * case for this, so we have to lie.
+ */
+ if (image != NULL)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+static __DRIimage *
+dri2_from_names(__DRIscreen *screen, int width, int height, int format,
+ int *names, int num_names, int *strides, int *offsets,
+ void *loaderPrivate)
+{
+ __DRIimage *img;
+ int dri_components;
+ struct winsys_handle whandle;
+
+ if (num_names != 1)
+ return NULL;
+
+ format = convert_fourcc(format, &dri_components);
+ if (format == -1)
+ return NULL;
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+ whandle.handle = names[0];
+ whandle.stride = strides[0];
+ whandle.offset = offsets[0];
+
+ img = dri2_create_image_from_winsys(screen, width, height, format,
+ 1, &whandle, loaderPrivate);
+ if (img == NULL)
+ return NULL;
+
+ img->dri_components = dri_components;
+ return img;
+}
+
+static __DRIimage *
+dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
+{
+ __DRIimage *img;
+
+ if (plane != 0)
+ return NULL;
+
+ if (image->dri_components == 0)
+ return NULL;
+
+ img = dri2_dup_image(image, loaderPrivate);
+ if (img == NULL)
+ return NULL;
+
+ if (img->texture->screen->resource_changed)
+ img->texture->screen->resource_changed(img->texture->screen,
+ img->texture);
+
+ /* set this to 0 for sub images. */
+ img->dri_components = 0;
+ return img;
+}
+
+static __DRIimage *
+dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
+ int depth, int level, unsigned *error,
+ void *loaderPrivate)
+{
+ __DRIimage *img;
+ struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
+ struct gl_texture_object *obj;
+ struct pipe_resource *tex;
+ GLuint face = 0;
+
+ obj = _mesa_lookup_texture(ctx, texture);
+ if (!obj || obj->Target != target) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ return NULL;
+ }
+
+ tex = st_get_texobj_resource(obj);
+ if (!tex) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ return NULL;
+ }
+
+ if (target == GL_TEXTURE_CUBE_MAP)
+ face = depth;
+
+ _mesa_test_texobj_completeness(ctx, obj);
+ if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ return NULL;
+ }
+
+ if (level < obj->BaseLevel || level > obj->_MaxLevel) {
+ *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+ return NULL;
+ }
+
+ if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
+ *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+ return NULL;
+ }
+
+ img = CALLOC_STRUCT(__DRIimageRec);
+ if (!img) {
+ *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+ return NULL;
+ }
+
+ img->level = level;
+ img->layer = depth;
+ img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
+
+ img->loader_private = loaderPrivate;
+
+ if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ free(img);
+ return NULL;
+ }
+
+ pipe_resource_reference(&img->texture, tex);
+
+ *error = __DRI_IMAGE_ERROR_SUCCESS;
+ return img;
+}
+
+__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 dri_components;
+
+ img = dri2_create_image_from_fd(screen, width, height, fourcc,
+ fds, num_fds, strides, offsets, NULL,
+ &dri_components, loaderPrivate);
+ if (img == NULL)
+ return NULL;
+
+ img->dri_components = dri_components;
+ return img;
+}
+
+__DRIimage *
+dri2_from_dma_bufs(__DRIscreen *screen,
+ int width, int height, int fourcc,
+ int *fds, int num_fds,
+ int *strides, int *offsets,
+ enum __DRIYUVColorSpace yuv_color_space,
+ enum __DRISampleRange sample_range,
+ enum __DRIChromaSiting horizontal_siting,
+ enum __DRIChromaSiting vertical_siting,
+ unsigned *error,
+ void *loaderPrivate)
+{
+ __DRIimage *img;
+ int dri_components;
+
+ img = dri2_create_image_from_fd(screen, width, height, fourcc,
+ fds, num_fds, strides, offsets, error,
+ &dri_components, loaderPrivate);
+ if (img == NULL)
+ return NULL;
+
+ img->yuv_color_space = yuv_color_space;
+ img->sample_range = sample_range;
+ img->horizontal_siting = horizontal_siting;
+ img->vertical_siting = vertical_siting;
+ img->dri_components = dri_components;
+
+ *error = __DRI_IMAGE_ERROR_SUCCESS;
+ return img;
+}
+
+static void
+dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
+ int dstx0, int dsty0, int dstwidth, int dstheight,
+ int srcx0, int srcy0, int srcwidth, int srcheight,
+ int flush_flag)
+{
+ struct dri_context *ctx = dri_context(context);
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen;
+ struct pipe_fence_handle *fence;
+ struct pipe_blit_info blit;
+
+ if (!dst || !src)
+ return;
+
+ memset(&blit, 0, sizeof(blit));
+ blit.dst.resource = dst->texture;
+ blit.dst.box.x = dstx0;
+ blit.dst.box.y = dsty0;
+ blit.dst.box.width = dstwidth;
+ blit.dst.box.height = dstheight;
+ blit.dst.box.depth = 1;
+ blit.dst.format = dst->texture->format;
+ blit.src.resource = src->texture;
+ blit.src.box.x = srcx0;
+ blit.src.box.y = srcy0;
+ blit.src.box.width = srcwidth;
+ blit.src.box.height = srcheight;
+ blit.src.box.depth = 1;
+ blit.src.format = src->texture->format;
+ blit.mask = PIPE_MASK_RGBA;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+ pipe->blit(pipe, &blit);
+
+ if (flush_flag == __BLIT_FLAG_FLUSH) {
+ pipe->flush_resource(pipe, dst->texture);
+ ctx->st->flush(ctx->st, 0, NULL);
+ } else if (flush_flag == __BLIT_FLAG_FINISH) {
+ screen = dri_screen(ctx->sPriv)->base.screen;
+ pipe->flush_resource(pipe, dst->texture);
+ ctx->st->flush(ctx->st, 0, &fence);
+ (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
+ screen->fence_reference(screen, &fence, NULL);
+ }
+}
+
+static void *
+dri2_map_image(__DRIcontext *context, __DRIimage *image,
+ int x0, int y0, int width, int height,
+ unsigned int flags, int *stride, void **data)
+{
+ struct dri_context *ctx = dri_context(context);
+ struct pipe_context *pipe = ctx->st->pipe;
+ enum pipe_transfer_usage pipe_access = 0;
+ struct pipe_transfer *trans;
+ void *map;
+
+ if (!image || !data || *data)
+ return NULL;
+
+ if (flags & __DRI_IMAGE_TRANSFER_READ)
+ pipe_access |= PIPE_TRANSFER_READ;
+ if (flags & __DRI_IMAGE_TRANSFER_WRITE)
+ pipe_access |= PIPE_TRANSFER_WRITE;
+
+ map = pipe_transfer_map(pipe, image->texture,
+ 0, 0, pipe_access, x0, y0, width, height,
+ &trans);
+ if (map) {
+ *data = trans;
+ *stride = trans->stride;
+ }
+
+ return map;
+}
+
+static void
+dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
+{
+ struct dri_context *ctx = dri_context(context);
+ struct pipe_context *pipe = ctx->st->pipe;
+
+ pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
+}
+
+static void
+dri2_destroy_image(__DRIimage *img)
+{
+ pipe_resource_reference(&img->texture, NULL);
+ FREE(img);
+}
+
+static int
+dri2_get_capabilities(__DRIscreen *_screen)
+{
+ struct dri_screen *screen = dri_screen(_screen);
+
+ return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
+}
+
+/* The extension is modified during runtime if DRI_PRIME is detected */
+__DRIimageExtension dri2ImageExtension = {
+ .base = { __DRI_IMAGE, 12 },
+
+ .createImageFromName = dri2_create_image_from_name,
+ .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
+ .destroyImage = dri2_destroy_image,
+ .createImage = dri2_create_image,
+ .queryImage = dri2_query_image,
+ .dupImage = dri2_dup_image,
+ .validateUsage = dri2_validate_usage,
+ .createImageFromNames = dri2_from_names,
+ .fromPlanar = dri2_from_planar,
+ .createImageFromTexture = dri2_create_from_texture,
+ .createImageFromFds = NULL,
+ .createImageFromDmaBufs = NULL,
+ .blitImage = dri2_blit_image,
+ .getCapabilities = dri2_get_capabilities,
+ .mapImage = dri2_map_image,
+ .unmapImage = dri2_unmap_image,
+};
+
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_extensions.h b/src/gallium/state_trackers/dri/dri_extensions.h
index 89b01cd3ed..6c19ccac75 100644
--- a/src/gallium/state_trackers/dri/dri_extensions.h
+++ b/src/gallium/state_trackers/dri/dri_extensions.h
@@ -24,7 +24,24 @@
#define DRI_EXTENSIONS_H
extern const __DRI2fenceExtension dri2FenceExtension;
+extern __DRIimageExtension dri2ImageExtension;
+__DRIimage *
+dri2_from_dma_bufs(__DRIscreen *screen,
+ int width, int height, int fourcc,
+ int *fds, int num_fds,
+ int *strides, int *offsets,
+ enum __DRIYUVColorSpace yuv_color_space,
+ enum __DRISampleRange sample_range,
+ enum __DRIChromaSiting horizontal_siting,
+ enum __DRIChromaSiting vertical_siting,
+ unsigned *error,
+ void *loaderPrivate);
+
+__DRIimage *
+dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
+ int *fds, int num_fds, int *strides, int *offsets,
+ void *loaderPrivate);
#endif
/* vim: set sw=3 ts=8 sts=3 expandtab: */
--
2.12.2
More information about the mesa-dev
mailing list