From 6a7dea93fa70d670a5954e47a47075a2703209d4 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 31 Aug 2012 19:48:26 +0200 Subject: dri: Rework planar image interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As discussed with Kristian on #wayland. Pushes the decision of components into the dri driver giving it greater freedom to allow t to implement YUV samplers in hardware, and which mode to use. This interface will also allow drivers like SVGA to implement YUV surfaces without the need to sub-allocate and instead send 3 seperate buffers for each channel, currently not implemented. I have tested these changes on Gallium Svga. Scott tested them on both intel and Gallium Radeon. Kristan and Pekka tested them on intel. v2: Fix typo in dri2_from_planar. v3: Merge in intel changes. Tested-by: Scott Moreau Tested-by: Pekka Paalanen Tested-by: Kristian Høgsberg Reviewed-by: Kristian Høgsberg Signed-off-by: Jakob Bornecrantz --- src/mesa/drivers/dri/intel/intel_regions.h | 26 ++++++ src/mesa/drivers/dri/intel/intel_screen.c | 135 +++++++++++++++++++++++++++-- 2 files changed, 153 insertions(+), 8 deletions(-) (limited to 'src/mesa/drivers/dri/intel') diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h index 4ff0efed72a..7480853d360 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.h +++ b/src/mesa/drivers/dri/intel/intel_regions.h @@ -141,12 +141,38 @@ uint32_t intel_region_get_aligned_offset(struct intel_region *region, uint32_t x, uint32_t y); +/** + * Used with images created with image_from_names + * to help support planar images. + */ +struct intel_image_format { + int fourcc; + int components; + int nplanes; + struct { + int buffer_index; + int width_shift; + int height_shift; + uint32_t dri_format; + int cpp; + } planes[3]; +}; + struct __DRIimageRec { struct intel_region *region; GLenum internal_format; uint32_t dri_format; GLuint format; uint32_t offset; + + /* + * Need to save these here between calls to + * image_from_names and calls to image_from_planar. + */ + uint32_t strides[3]; + uint32_t offsets[3]; + struct intel_image_format *planar_format; + void *data; }; diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 55cebaca013..7476ca00414 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -190,6 +190,59 @@ static const struct __DRI2flushExtensionRec intelFlushExtension = { dri2InvalidateDrawable, }; +struct intel_image_format intel_image_formats[] = { + { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, + + { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, + + { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, + + { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, + + /* For YUYV buffers, we set up two overlapping DRI images and treat + * them as planar buffers in the compositors. Plane 0 is GR88 and + * samples YU or YV pairs and places Y into the R component, while + * plane 1 is ARGB and samples YUYV clusters and places pairs and + * places U into the G component and V into A. This lets the + * texture sampler interpolate the Y components correctly when + * sampling from plane 0, and interpolate U and V correctly when + * sampling from plane 1. */ + { __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, + { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } } +}; + static __DRIimage * intel_allocate_image(int dri_format, void *loaderPrivate) { @@ -249,7 +302,7 @@ intel_create_image_from_name(__DRIscreen *screen, image = intel_allocate_image(format, loaderPrivate); if (image->format == MESA_FORMAT_NONE) - cpp = 0; + cpp = 1; else cpp = _mesa_get_format_bytes(image->format); image->region = intel_region_alloc_for_handle(intelScreen, @@ -372,6 +425,11 @@ intel_query_image(__DRIimage *image, int attrib, int *value) case __DRI_IMAGE_ATTRIB_HEIGHT: *value = image->region->height; return true; + case __DRI_IMAGE_ATTRIB_COMPONENTS: + if (image->planar_format == NULL) + return false; + *value = image->planar_format->components; + return true; default: return false; } @@ -393,11 +451,15 @@ intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) } image->internal_format = orig_image->internal_format; + image->planar_format = orig_image->planar_format; image->dri_format = orig_image->dri_format; image->format = orig_image->format; image->offset = orig_image->offset; image->data = loaderPrivate; - + + memcpy(image->strides, orig_image->strides, sizeof(image->strides)); + memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets)); + return image; } @@ -413,16 +475,72 @@ intel_validate_usage(__DRIimage *image, unsigned int use) } static __DRIimage * -intel_create_sub_image(__DRIimage *parent, - int width, int height, int dri_format, - int offset, int pitch, void *loaderPrivate) +intel_create_image_from_names(__DRIscreen *screen, + int width, int height, int fourcc, + int *names, int num_names, + int *strides, int *offsets, + void *loaderPrivate) { + struct intel_image_format *f = NULL; __DRIimage *image; - int cpp; + int i, index; + + if (screen == NULL || names == NULL || num_names != 1) + return NULL; + + for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) { + if (intel_image_formats[i].fourcc == fourcc) { + f = &intel_image_formats[i]; + } + } + + if (f == NULL) + return NULL; + + image = intel_create_image_from_name(screen, width, height, + __DRI_IMAGE_FORMAT_NONE, + names[0], strides[0], + loaderPrivate); + + if (image == NULL) + return NULL; + + image->planar_format = f; + for (i = 0; i < f->nplanes; i++) { + index = f->planes[i].buffer_index; + image->offsets[index] = offsets[index]; + image->strides[index] = strides[index]; + } + + return image; +} + +static __DRIimage * +intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate) +{ + int width, height, offset, stride, dri_format, cpp, index, pitch; + struct intel_image_format *f; uint32_t mask_x, mask_y; + __DRIimage *image; + + if (parent == NULL || parent->planar_format == NULL) + return NULL; + + f = parent->planar_format; + + if (plane >= f->nplanes) + return NULL; + + width = parent->region->width >> f->planes[plane].width_shift; + height = parent->region->height >> f->planes[plane].height_shift; + dri_format = f->planes[plane].dri_format; + index = f->planes[plane].buffer_index; + offset = parent->offsets[index]; + stride = parent->strides[index]; image = intel_allocate_image(dri_format, loaderPrivate); - cpp = _mesa_get_format_bytes(image->format); + cpp = _mesa_get_format_bytes(image->format); /* safe since no none format */ + pitch = stride / cpp; if (offset + height * cpp * pitch > parent->region->bo->size) { _mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds"); FREE(image); @@ -463,7 +581,8 @@ static struct __DRIimageExtensionRec intelImageExtension = { intel_query_image, intel_dup_image, intel_validate_usage, - intel_create_sub_image + intel_create_image_from_names, + intel_from_planar }; static const __DRIextension *intelScreenExtensions[] = { -- cgit v1.2.3