dri2: Create image from texture

Add create image from texture extension and bump version.

v8: - Add appropriate image errors codes in DRI interface so we don't
      have to use internal EGL functions in driver. Suggested by Chad Versace.

Reviewed-by: Eric Anholt <eric@anholt.net> (v6)
Reviewed-by: Chad Versace <chad.versace@linux.intel.com> (v8)
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
This commit is contained in:
Abdiel Janulgue 2012-11-27 15:19:54 +02:00 committed by Chad Versace
parent a8a5055f2d
commit 7b7af48e01
2 changed files with 153 additions and 1 deletions

View File

@ -938,7 +938,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_*
@ -1022,6 +1022,23 @@ struct __DRIdri2ExtensionRec {
#define __DRI_IMAGE_ATTRIB_HEIGHT 0x2005
#define __DRI_IMAGE_ATTRIB_COMPONENTS 0x2006 /* available in versions 5+ */
/**
* \name Reasons that __DRIimageExtensionRec::createImageFromTexture might fail
*/
/*@{*/
/** Success! */
#define __DRI_IMAGE_ERROR_SUCCESS 0
/** Memory allocation failure */
#define __DRI_IMAGE_ERROR_BAD_ALLOC 1
/** Client requested an invalid attribute for a texture object */
#define __DRI_IMAGE_ERROR_BAD_MATCH 2
/** Client requested an invalid texture object */
#define __DRI_IMAGE_ERROR_BAD_PARAMETER 3
/*@}*/
typedef struct __DRIimageRec __DRIimage;
typedef struct __DRIimageExtensionRec __DRIimageExtension;
struct __DRIimageExtensionRec {
@ -1087,6 +1104,19 @@ struct __DRIimageExtensionRec {
*/
__DRIimage *(*fromPlanar)(__DRIimage *image, int plane,
void *loaderPrivate);
/**
* Create image from texture.
*
* \since 6
*/
__DRIimage *(*createImageFromTexture)(__DRIcontext *context,
int target,
unsigned texture,
int depth,
int level,
unsigned *error,
void *loaderPrivate);
};

View File

@ -495,6 +495,11 @@ dri2_setup_screen(_EGLDisplay *disp)
disp->Extensions.MESA_drm_image = EGL_TRUE;
disp->Extensions.KHR_image_base = EGL_TRUE;
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
if (dri2_dpy->image->base.version >= 5 &&
dri2_dpy->image->createImageFromTexture) {
disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
}
}
}
@ -1217,6 +1222,115 @@ dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
}
#endif
/**
* Set the error code after a call to
* dri2_egl_image::dri_image::createImageFromTexture.
*/
static void
dri2_create_image_khr_texture_error(int dri_error)
{
EGLint egl_error;
switch (dri_error) {
case __DRI_IMAGE_ERROR_SUCCESS:
return;
case __DRI_IMAGE_ERROR_BAD_ALLOC:
egl_error = EGL_BAD_ALLOC;
break;
case __DRI_IMAGE_ERROR_BAD_MATCH:
egl_error = EGL_BAD_MATCH;
break;
case __DRI_IMAGE_ERROR_BAD_PARAMETER:
egl_error = EGL_BAD_PARAMETER;
break;
default:
assert(0);
egl_error = EGL_BAD_MATCH;
break;
}
_eglError(egl_error, "dri2_create_image_khr_texture");
}
static _EGLImage *
dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
EGLenum target,
EGLClientBuffer buffer,
const EGLint *attr_list)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
struct dri2_egl_image *dri2_img;
GLuint texture = (GLuint) (uintptr_t) buffer;
_EGLImageAttribs attrs;
GLuint depth;
GLenum gl_target;
unsigned error;
if (texture == 0) {
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
return EGL_NO_IMAGE_KHR;
}
if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
return EGL_NO_IMAGE_KHR;
switch (target) {
case EGL_GL_TEXTURE_2D_KHR:
depth = 0;
gl_target = GL_TEXTURE_2D;
break;
case EGL_GL_TEXTURE_3D_KHR:
depth = attrs.GLTextureZOffset;
gl_target = GL_TEXTURE_3D;
break;
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
gl_target = GL_TEXTURE_CUBE_MAP;
break;
default:
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
return EGL_NO_IMAGE_KHR;
}
dri2_img = malloc(sizeof *dri2_img);
if (!dri2_img) {
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
return EGL_NO_IMAGE_KHR;
}
if (!_eglInitImage(&dri2_img->base, disp)) {
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
free(dri2_img);
return EGL_NO_IMAGE_KHR;
}
dri2_img->dri_image =
dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
gl_target,
texture,
depth,
attrs.GLTextureLevel,
&error,
dri2_img);
dri2_create_image_khr_texture_error(error);
if (!dri2_img->dri_image) {
free(dri2_img);
return EGL_NO_IMAGE_KHR;
}
return &dri2_img->base;
}
_EGLImage *
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
_EGLContext *ctx, EGLenum target,
@ -1225,6 +1339,14 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
(void) drv;
switch (target) {
case EGL_GL_TEXTURE_2D_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
case EGL_GL_RENDERBUFFER_KHR:
return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
case EGL_DRM_BUFFER_MESA: