diff options
author | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2012-09-14 14:33:10 +0200 |
---|---|---|
committer | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2012-09-14 14:33:10 +0200 |
commit | ef33894a6061f130a6a28bdde2af5661da146632 (patch) | |
tree | 82009e9a06a72f3a41886e5373b5682ac577f8b1 | |
parent | d00d24ddc44fb511fc49c765659ac96d0f165a19 (diff) |
egl: make VA/EGL buffer support driver specific.21.VA_pixel_buffer-r221.VA_pixel_buffer
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
-rw-r--r-- | include/GL/internal/dri_interface.h | 30 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 120 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 5 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_screen.c | 135 |
4 files changed, 167 insertions, 123 deletions
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 1e0f1d07b3..1a6cf0a568 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -912,7 +912,7 @@ struct __DRIdri2ExtensionRec { * extensions. */ #define __DRI_IMAGE "DRI_IMAGE" -#define __DRI_IMAGE_VERSION 5 +#define __DRI_IMAGE_VERSION 6 /** * These formats correspond to the similarly named MESA_FORMAT_* @@ -1061,6 +1061,34 @@ struct __DRIimageExtensionRec { */ __DRIimage *(*fromPlanar)(__DRIimage *image, int plane, void *loaderPrivate); + + /** + * Create an image out of a VA/EGL buffer. This entry-point lets us create + * individual __DRIimages for different planes in a planar buffer, similar + * to fromPlanar(), but with a VA/EGL buffer as source. + * + * Buffer structure, if non-zero, specifies the desired sampling from the + * client application. e.g. if a YUV surface was provided but + * @buffer_structure is VA_EGL_BUFFER_STRUCTURE_RGBA, this means the user + * would like to get RGBA samples from the YUV surface, i.e. color space + * conversion is to be performed by the underlying hardware without shader + * code. If the hardware does not support this capability, the function + * shall return NULL, thus indicating to client application that a planar + * format should be tried instead and suitable shader code provided. + * + * Picture structure represents the full frame (default, if zero), the top + * or the bottom field for interlaced surfaces. Note that for those two + * modes, this basically actually means whether to render every other line + * or not. If not proper hardware function supports that capability, or + * that using double stride and half height doesn't work, then this + * entry-point shall return NULL. + * + * \since 6 + */ + __DRIimage *(*createImageFromVABuffer)(__DRIscreen *screen, void *buffer, + int buffer_structure, int plane, + int picture_structure, + void *loaderPrivate); }; diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index de4506cbbb..47d5e9b5cf 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -1146,97 +1146,15 @@ dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, #endif #ifdef HAVE_VA_EGL_INTEROP -static const struct va_dri_image_descriptor { - uint32_t format; - uint32_t dri_fourcc; - int nplanes; -} va_dri_image_descriptors[] = { - { VA_EGL_PIXEL_FORMAT_ARGB8888, __DRI_IMAGE_FOURCC_ARGB8888, 1 }, - { VA_EGL_PIXEL_FORMAT_XRGB8888, __DRI_IMAGE_FOURCC_XRGB8888, 1 }, - { VA_EGL_PIXEL_FORMAT_ABGR8888, __DRI_IMAGE_FOURCC_ABGR8888, 1 }, - { VA_EGL_PIXEL_FORMAT_NV12, __DRI_IMAGE_FOURCC_NV12, 2 }, - { VA_EGL_PIXEL_FORMAT_YUV410P, __DRI_IMAGE_FOURCC_YUV410, 3 }, - { VA_EGL_PIXEL_FORMAT_YUV411P, __DRI_IMAGE_FOURCC_YUV411, 3 }, - { VA_EGL_PIXEL_FORMAT_YUV420P, __DRI_IMAGE_FOURCC_YUV420, 3 }, - { VA_EGL_PIXEL_FORMAT_YUV422P, __DRI_IMAGE_FOURCC_YUV422, 3 }, - { VA_EGL_PIXEL_FORMAT_YUV444P, __DRI_IMAGE_FOURCC_YUV444, 3 }, -}; - -struct va_dri_image { - __DRIimage *image; - void (*destroy_func)(__DRIimage *image); - const struct va_dri_image_descriptor *desc; -}; - -static void -dri2_va_destroy_image(struct va_dri_image *img) -{ - if (img) - return; - if (img->destroy_func) - img->destroy_func(img->image); - free(img); -} - -static struct va_dri_image * -dri2_va_create_image(_EGLDisplay *disp, struct va_egl_client_buffer *buffer) -{ - struct dri2_egl_display * const dri2_dpy = dri2_egl_display(disp); - struct va_dri_image *img; - int i, handle, pitches[3], offsets[3]; - - for (i = 0; i < ARRAY_SIZE(va_dri_image_descriptors); i++) { - if (va_dri_image_descriptors[i].format == buffer->format) - break; - } - if (i == ARRAY_SIZE(va_dri_image_descriptors)) { - _eglLog(_EGL_DEBUG, "DRI2-VA: failed to validate pixel format %d", - buffer->format); - return NULL; - } - - img = malloc(sizeof(*img)); - if (!img) - return NULL; - img->destroy_func = dri2_dpy->image->destroyImage; - img->desc = &va_dri_image_descriptors[i]; - - handle = buffer->handle; - for (i = 0; i < buffer->num_planes; i++) { - pitches[i] = buffer->pitches[i]; - offsets[i] = buffer->offsets[i]; - } - for (; i < ARRAY_SIZE(pitches); i++) { - pitches[i] = 0; - offsets[i] = 0; - } - img->image = dri2_dpy->image->createImageFromNames( - dri2_dpy->dri_screen, buffer->width, buffer->height, - img->desc->dri_fourcc, &handle, 1, pitches, offsets, - NULL); - if (img->image) - return img; - - free(img); - return NULL; -} - static _EGLImage * dri2_create_image_va_pixel_buffer(_EGLDisplay *disp, _EGLContext *ctx, - EGLClientBuffer _buffer, + EGLClientBuffer buffer, const EGLint *attr_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct va_egl_client_buffer *buffer = _buffer; - struct va_dri_image *img; __DRIimage *dri_image; _EGLImageAttribs attrs; - EGLint plane, structure, err; - - if (!buffer || buffer->version != VA_EGL_CLIENT_BUFFER_VERSION) { - _eglError(EGL_BAD_PARAMETER, "DRI2-VA: unsupported EGLClientBuffer"); - return NULL; - } + EGLint plane, err; err = _eglParseImageAttribList(&attrs, disp, attr_list); if (err != EGL_SUCCESS) { @@ -1251,37 +1169,9 @@ dri2_create_image_va_pixel_buffer(_EGLDisplay *disp, _EGLContext *ctx, return NULL; } - structure = attrs.VABufferStructureINTEL; - if (structure && structure != buffer->structure) { - _eglError(EGL_BAD_PARAMETER, - "DRI2-VA: buffer structure coercition is not supported yet"); - return NULL; - } - - structure = attrs.VAPictureStructureINTEL; - if (structure != VA_EGL_PICTURE_STRUCTURE_FRAME) { - _eglError(EGL_BAD_PARAMETER, - "DRI2-VA: interlaced picture structure is not supported yet"); - return NULL; - } - - img = buffer->private_data; - if (!img) { - img = dri2_va_create_image(disp, buffer); - if (!img) { - _eglError(EGL_BAD_ALLOC, "DRI2-VA: could not reference VA buffer"); - return NULL; - } - buffer->private_data = img; - buffer->destroy_private_data = (void (*)(void *))dri2_va_destroy_image; - } - - if (plane >= img->desc->nplanes) { - _eglError(EGL_BAD_PARAMETER, "DRI2-VA: invalid plane index"); - return NULL; - } - - dri_image = dri2_dpy->image->fromPlanar(img->image, plane, NULL); + dri_image = dri2_dpy->image->createImageFromVABuffer(dri2_dpy->dri_screen, + buffer, attrs.VABufferStructureINTEL, plane, + attrs.VAPictureStructureINTEL, NULL); if (!dri_image) { _eglError(EGL_BAD_ALLOC, "DRI2-VA: could not create sub-buffer"); return NULL; diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 6ad78bddbd..81c1354b79 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -44,11 +44,6 @@ #include <GL/gl.h> #include <GL/internal/dri_interface.h> -#ifdef HAVE_VA_EGL_INTEROP -# include <va/va_egl.h> -# include <va/va_backend_egl.h> -#endif - #ifdef HAVE_DRM_PLATFORM #include <gbm_driint.h> #endif diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index e3a442c2a2..835f9158e9 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -36,6 +36,11 @@ #include "main/version.h" #include "swrast/s_renderbuffer.h" +#ifdef HAVE_VA_EGL_INTEROP +# include <va/va_egl.h> +# include <va/va_backend_egl.h> +#endif + #include "utils.h" #include "xmlpool.h" @@ -572,8 +577,133 @@ intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate) return image; } +#ifdef HAVE_VA_EGL_INTEROP +static const struct va_dri_image_descriptor { + uint32_t format; + uint32_t dri_fourcc; + int nplanes; +} va_dri_image_descriptors[] = { + { VA_EGL_PIXEL_FORMAT_ARGB8888, __DRI_IMAGE_FOURCC_ARGB8888, 1 }, + { VA_EGL_PIXEL_FORMAT_XRGB8888, __DRI_IMAGE_FOURCC_XRGB8888, 1 }, + { VA_EGL_PIXEL_FORMAT_ABGR8888, __DRI_IMAGE_FOURCC_ABGR8888, 1 }, + { VA_EGL_PIXEL_FORMAT_NV12, __DRI_IMAGE_FOURCC_NV12, 2 }, + { VA_EGL_PIXEL_FORMAT_YUV410P, __DRI_IMAGE_FOURCC_YUV410, 3 }, + { VA_EGL_PIXEL_FORMAT_YUV411P, __DRI_IMAGE_FOURCC_YUV411, 3 }, + { VA_EGL_PIXEL_FORMAT_YUV420P, __DRI_IMAGE_FOURCC_YUV420, 3 }, + { VA_EGL_PIXEL_FORMAT_YUV422P, __DRI_IMAGE_FOURCC_YUV422, 3 }, + { VA_EGL_PIXEL_FORMAT_YUV444P, __DRI_IMAGE_FOURCC_YUV444, 3 }, +}; + +struct va_dri_image { + __DRIimage *image; + const struct va_dri_image_descriptor *desc; +}; + +static void +intel_destroy_va_image(struct va_dri_image *img) +{ + if (!img) + return; + if (img->image) + intel_destroy_image(img->image); + free(img); +} + +static struct va_dri_image * +intel_create_va_image(__DRIscreen *screen, struct va_egl_client_buffer *buffer) +{ + struct va_dri_image *img = NULL; + int i, handle, pitches[3], offsets[3]; + + for (i = 0; i < ARRAY_SIZE(va_dri_image_descriptors); i++) { + if (va_dri_image_descriptors[i].format == buffer->format) + break; + } + if (i == ARRAY_SIZE(va_dri_image_descriptors)) { + _mesa_error(NULL, GL_INVALID_OPERATION, + "DRI2-VA: failed to validate pixel format %d", + buffer->format); + goto error; + } + + img = malloc(sizeof(*img)); + if (!img) { + _mesa_error(NULL, GL_OUT_OF_MEMORY, "DRI2-VA: failed to create VA image"); + goto error; + } + img->desc = &va_dri_image_descriptors[i]; + + handle = buffer->handle; + for (i = 0; i < buffer->num_planes; i++) { + pitches[i] = buffer->pitches[i]; + offsets[i] = buffer->offsets[i]; + } + for (; i < ARRAY_SIZE(pitches); i++) { + pitches[i] = 0; + offsets[i] = 0; + } + img->image = intel_create_image_from_names( + screen, buffer->width, buffer->height, + img->desc->dri_fourcc, &handle, 1, pitches, offsets, + NULL); + if (!img->image) + goto error; + + buffer->private_data = img; + buffer->destroy_private_data = (void (*)(void *))intel_destroy_va_image; + return img; + +error: + free(img); + return NULL; +} +#endif + +static __DRIimage * +intel_create_image_from_va_buffer(__DRIscreen *screen, void *_buffer, + int buffer_structure, int plane, + int picture_structure, void *loaderPrivate) +{ +#ifdef HAVE_VA_EGL_INTEROP + struct va_egl_client_buffer * const buffer = _buffer; + struct va_dri_image *img; + + if (!buffer || buffer->version != VA_EGL_CLIENT_BUFFER_VERSION) { + _mesa_error(NULL, GL_INVALID_VALUE, + "DRI2-VA: unsupported EGLClientBuffer"); + return NULL; + } + + if (buffer_structure && buffer_structure != buffer->structure) { + _mesa_error(NULL, GL_INVALID_VALUE, + "DRI2-VA: buffer structure coercition is not supported yet"); + return NULL; + } + + if (picture_structure != VA_EGL_PICTURE_STRUCTURE_FRAME) { + _mesa_error(NULL, GL_INVALID_VALUE, + "DRI2-VA: interlaced picture structure is not supported yet"); + return NULL; + } + + img = buffer->private_data; + if (!img) { + img = intel_create_va_image(screen, buffer); + if (!img) + return NULL; + } + + if (plane >= img->desc->nplanes) { + _mesa_error(NULL, GL_INVALID_VALUE, "DRI2-VA: invalid plane index"); + return NULL; + } + return intel_from_planar(img->image, plane, loaderPrivate); +#endif + return NULL; +} + static struct __DRIimageExtensionRec intelImageExtension = { - { __DRI_IMAGE, 5 }, + { __DRI_IMAGE, 6 }, intel_create_image_from_name, intel_create_image_from_renderbuffer, intel_destroy_image, @@ -582,7 +712,8 @@ static struct __DRIimageExtensionRec intelImageExtension = { intel_dup_image, intel_validate_usage, intel_create_image_from_names, - intel_from_planar + intel_from_planar, + intel_create_image_from_va_buffer }; static const __DRIextension *intelScreenExtensions[] = { |