[Mesa-dev] EGL_KHR_*_image extension implemention
Chia-I Wu
olvaffe at gmail.com
Sun Sep 12 20:52:51 PDT 2010
On Mon, Sep 13, 2010 at 2:53 AM, Gregory Prisament
<greg at lycheesoftware.com> wrote:
> Hi,
>
> Attached is a patch that implements the following EGL extensions:
>
> EGL_KHR_gl_texture_2d_image
> EGL_KHR_gl_texture_3d_image
> EGL_KHR_gl_renderbuffer_image
> EGL_KHR_vg_parent_image
>
> Please review and, if you find it acceptable, someone can go ahead and apply
> it.
>
> This is my first contribution so please let me know if I should do things
> differently (either code-wise or process-wise).
Great work! I have a few comments below. It would also be good to
split the patch into implement the get_resource hook for OpenGL, for
OpenVG, and implement the EGL extensions.
> Thanks!
> -Greg, Lychee Software
> From c834c77d9f1b9512fde7ed7e36cdb36452286e1e Mon Sep 17 00:00:00 2001
> From: Gregory Prisament <greg at lycheesoftware.com>
> Date: Sun, 12 Sep 2010 11:26:38 -0700
> Subject: [PATCH 1/2] Implement additional EGL image extension.
>
> Implements:
> - EGL_KHR_gl_texture_2d_image
> - EGL_KHR_gl_texture_3d_image
> - EGL_KHR_gl_cubemap_image
> - EGL_KHR_gl_renderbuffer_image
> - EGL_KHR_vg_parent_image
> ---
> src/gallium/include/state_tracker/st_api.h | 6 +-
> src/gallium/state_trackers/egl/common/egl_g3d.c | 6 +
> .../state_trackers/egl/common/egl_g3d_image.c | 128 ++++++++++++++++++--
> src/gallium/state_trackers/vega/vg_manager.c | 29 +++++
> src/mesa/state_tracker/st_manager.c | 61 +++++++++
> 5 files changed, 219 insertions(+), 11 deletions(-)
>
> diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
> index 8ea1554..d265d69 100644
> --- a/src/gallium/include/state_tracker/st_api.h
> +++ b/src/gallium/include/state_tracker/st_api.h
> @@ -117,7 +117,11 @@ enum st_context_resource_type {
> ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z,
> ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
> ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER,
> - ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE
> + ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE,
> +
> + ST_CONTEXT_RESOURCE_COUNT,
> + ST_CONTEXT_RESOURCE_INVALID = -1
> +
> };
>
> /**
> diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
> index 33a838f..d955ab4 100644
> --- a/src/gallium/state_trackers/egl/common/egl_g3d.c
> +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
> @@ -530,6 +530,12 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
> if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
> dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
>
> + dpy->Extensions.KHR_vg_parent_image = EGL_TRUE;
> + dpy->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
> + dpy->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
> + dpy->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
> + dpy->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
> +
> dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
> dpy->Extensions.KHR_fence_sync = EGL_TRUE;
>
> diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
> index 558638e..6bf7f7c 100644
> --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
> +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
> @@ -230,6 +230,37 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
>
> #endif /* EGL_MESA_drm_image */
>
> +/* Map <target> param of eglCreateImageKHR to st_context_resource_type enum. */
> +static enum st_context_resource_type
> +egl_g3d_target_to_resource_type(EGLenum target)
> +{
> + switch (target) {
> + case EGL_GL_TEXTURE_2D_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D;
> + case EGL_GL_TEXTURE_3D_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D;
> + case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X;
> + case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X;
> + case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y;
> + case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
> + case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z;
> + case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
> + case EGL_GL_RENDERBUFFER_KHR:
> + return ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER;
> + case EGL_VG_PARENT_IMAGE_KHR:
> + return ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE;
> + default:
> + return ST_CONTEXT_RESOURCE_INVALID;
> + }
> +}
> +
> +
> _EGLImage *
> egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
> EGLenum target, EGLClientBuffer buffer,
> @@ -237,6 +268,7 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
> {
> struct pipe_resource *ptex;
> struct egl_g3d_image *gimg;
> + struct egl_g3d_context *gctx;
> unsigned face = 0, level = 0, zslice = 0;
>
> gimg = CALLOC_STRUCT(egl_g3d_image);
> @@ -250,11 +282,76 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
> return NULL;
> }
>
> + gctx = egl_g3d_context(ctx);
> + if (!gctx) {
> + _eglError(EGL_BAD_CONTEXT, "eglCreateImageKHR");
> + FREE(gimg);
> + return NULL;
> + }
> +
> + /* Parse attributes */
> + while (*attribs != EGL_NONE)
> + {
> + EGLint attr_val = attribs[1];
> + switch (*attribs) {
> + case EGL_GL_TEXTURE_LEVEL_KHR:
> + level = attr_val;
> + break;
> + case EGL_GL_TEXTURE_ZOFFSET_KHR:
> + if (target != EGL_GL_TEXTURE_3D_KHR) {
> + goto handle_bad_parameter;
> + }
> + zslice = attr_val;
> + break;
> + default:
> + /* unsupported attribute */
> + goto handle_bad_parameter;
> + }
> + attribs += 2;
> + }
_eglInitImage parses these attributes. You can use
gimg->base.{GLTextureLevel,GLTextureZOffset}. The spec states that
unrecognized attributes should be ignored IIRC.
> + /* Lookup client-API resource */
> switch (target) {
> case EGL_NATIVE_PIXMAP_KHR:
> ptex = egl_g3d_reference_native_pixmap(dpy,
> (EGLNativePixmapType) buffer);
> 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:
> + face = (unsigned int)target -
> + (unsigned int)EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
> + /* Intentional fall-through: */
> + case EGL_GL_TEXTURE_2D_KHR:
> + case EGL_GL_TEXTURE_3D_KHR:
> + case EGL_GL_RENDERBUFFER_KHR:
> + case EGL_VG_PARENT_IMAGE_KHR:
> + {
> + boolean result;
> + struct st_context_resource stres;
> +
> + stres.type = egl_g3d_target_to_resource_type(target);
> + assert(stres.type != ST_CONTEXT_RESOURCE_INVALID);
> +
> + stres.resource = (void *)buffer;
> +
> + if (!gctx->stctxi->get_resource_for_egl_image) {
> + goto handle_bad_parameter;
> + }
> +
> + result =
> + gctx->stctxi->get_resource_for_egl_image(gctx->stctxi, &stres);
> + if (!result) {
> + goto handle_bad_parameter;
> + }
> +
> + ptex = stres.texture;
> + break;
> + }
> +
> #ifdef EGL_MESA_drm_image
> case EGL_DRM_BUFFER_MESA:
> ptex = egl_g3d_reference_drm_buffer(dpy, (EGLint) buffer, attribs);
> @@ -266,21 +363,14 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
> }
>
> if (!ptex) {
> - FREE(gimg);
> - return NULL;
> + goto handle_bad_parameter;
> }
>
> if (level > ptex->last_level) {
> - _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR");
> - pipe_resource_reference(&gimg->texture, NULL);
> - FREE(gimg);
> - return NULL;
> + goto handle_bad_parameter;
> }
> if (zslice > ptex->depth0) {
> - _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
> - pipe_resource_reference(&gimg->texture, NULL);
> - FREE(gimg);
> - return NULL;
> + goto handle_bad_parameter;
> }
>
> /* transfer the ownership to the image */
> @@ -290,6 +380,24 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
> gimg->zslice = zslice;
>
> return &gimg->base;
> +
> + /* error handling */
> +handle_bad_parameter:
> + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
> + goto handle_error;
> +
> +handle_bad_match:
> + _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR");
> + goto handle_error;
> +
> +handle_error:
> + if (gimg && gimg->texture)
> + pipe_resource_reference(&gimg->texture, NULL);
> +
> + if (gimg)
> + FREE(gimg);
> +
> + return NULL;
> }
>
> EGLBoolean
> diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c
> index e799674..86221e2 100644
> --- a/src/gallium/state_trackers/vega/vg_manager.c
> +++ b/src/gallium/state_trackers/vega/vg_manager.c
> @@ -332,6 +332,32 @@ vg_context_flush(struct st_context_iface *stctxi, unsigned flags,
> vg_manager_flush_frontbuffer(ctx);
> }
>
> +static boolean
> +vg_context_get_resource_for_egl_image(struct st_context_iface *stctxi,
> + struct st_context_resource *stres)
> +{
> + struct vg_context *ctx;
> + struct vg_image *img;
> + struct pipe_sampler_view *sampler_view;
> +
> + ctx = (struct vg_context *) stctxi;
> + if (!ctx)
> + return FALSE;
This check could be replaced by an assertion. Calling stctxi's method
without passing stctxi is a bug elsewhere.
> +
> + img = (struct vg_image *)stres->resource;
A check on stres->type and res->resource (!= VG_INVALID_HANDLE) would
be good before the assignment.
> + if (!img)
> + return FALSE;
> +
> + sampler_view = img->sampler_view;
> + if (!sampler_view)
> + return FALSE;
> +
> + stres->texture = sampler_view->texture;
It should be
stres->texture = NULL;
pipe_resource_reference(&stres->texture, sampler_view->texture);
stres->texture is caller owned.
> +
> + return TRUE;
> +}
> +
> +
> static void
> vg_context_destroy(struct st_context_iface *stctxi)
> {
> @@ -373,6 +399,9 @@ vg_api_create_context(struct st_api *stapi, struct st_manager *smapi,
> ctx->iface.teximage = NULL;
> ctx->iface.copy = NULL;
>
> + ctx->iface.get_resource_for_egl_image =
> + vg_context_get_resource_for_egl_image;
> +
> ctx->iface.st_context_private = (void *) smapi;
>
> return &ctx->iface;
> diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
> index 450b045..f8f4223 100644
> --- a/src/mesa/state_tracker/st_manager.c
> +++ b/src/mesa/state_tracker/st_manager.c
> @@ -601,6 +601,66 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target
> return TRUE;
> }
>
> +static boolean
> +st_context_get_resource_for_egl_image(struct st_context_iface *stctxi,
> + struct st_context_resource *stres)
> +{
> + struct st_context *st = (struct st_context *) stctxi;
> +
> + switch (stres->type) {
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z:
> + case ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
> + {
> + GLuint texID;
> + struct gl_texture_object *texObj;
> + struct pipe_resource *resource;
> +
> + texID = (GLuint)stres->resource;
> +
> + texObj = _mesa_lookup_texture(st->ctx, texID);
> + if (!texObj)
> + return FALSE;
> +
Should texObj be _mesa_lock_texture here? It seems so to me, but I am
not entirely sure.
> + resource = st_get_texobj_resource(texObj);
> + if (!resource)
> + return FALSE;
> +
> + stres->texture = resource;
stres->texture is caller owned.
> + return TRUE;
> + }
> + case ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER:
> + {
> + GLuint rbID;
> + struct gl_renderbuffer *rbObj;
> + struct st_renderbuffer *stRb;
> +
> + rbID = (GLuint)stres->resource;
> +
> + rbObj = _mesa_lookup_renderbuffer(st->ctx, rbID);
> + if (!rbObj)
> + return FALSE;
> +
> + stRb = st_renderbuffer(rbObj);
> + if (!stRb)
> + return FALSE;
> +
> + stres->texture = stRb->texture;
Likewise.
> + return TRUE;
> + }
> + default:
> + return FALSE;
> + }
> +
> + return FALSE;
> +}
> +
> +
> static void
> st_context_destroy(struct st_context_iface *stctxi)
> {
> @@ -669,6 +729,7 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
> st->iface.flush = st_context_flush;
> st->iface.teximage = st_context_teximage;
> st->iface.copy = NULL;
> + st->iface.get_resource_for_egl_image = st_context_get_resource_for_egl_image;
> st->iface.st_context_private = (void *) smapi;
>
> return &st->iface;
> --
> 1.6.3.3
>
I got some trailing space complaints when git am. Please fix them.
The rest of the patch looks good to me.
--
olv at LunarG.com
More information about the mesa-dev
mailing list