diff --git a/src/egl/drivers/wgl/egl_wgl.c b/src/egl/drivers/wgl/egl_wgl.c index 8459f6ed041..9eb5e781a2d 100644 --- a/src/egl/drivers/wgl/egl_wgl.c +++ b/src/egl/drivers/wgl/egl_wgl.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -242,21 +243,12 @@ wgl_initialize_impl(_EGLDisplay *disp, HDC hdc) disp->Extensions.KHR_gl_colorspace = EGL_TRUE; disp->Extensions.KHR_create_context = EGL_TRUE; - disp->Extensions.KHR_reusable_sync = EGL_TRUE; -#if 0 disp->Extensions.KHR_image_base = EGL_TRUE; disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; - if (wgl_dpy->image->base.version >= 5 && - wgl_dpy->image->createImageFromTexture) { - disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; - disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; - - if (wgl_renderer_query_integer(wgl_dpy, - __wgl_RENDERER_HAS_TEXTURE_3D)) - disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE; - } -#endif + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE; if (!wgl_add_configs(disp)) { err = "wgl: failed to add configs"; @@ -841,6 +833,161 @@ wgl_wait_native(EGLint engine) return EGL_TRUE; } +static EGLint +egl_error_from_stw_image_error(enum stw_image_error err) +{ + switch (err) { + case STW_IMAGE_ERROR_SUCCESS: + return EGL_SUCCESS; + case STW_IMAGE_ERROR_BAD_ALLOC: + return EGL_BAD_ALLOC; + case STW_IMAGE_ERROR_BAD_MATCH: + return EGL_BAD_MATCH; + case STW_IMAGE_ERROR_BAD_PARAMETER: + return EGL_BAD_PARAMETER; + case STW_IMAGE_ERROR_BAD_ACCESS: + return EGL_BAD_ACCESS; + default: + assert(!"unknown stw_image_error code"); + return EGL_BAD_ALLOC; + } +} + +static _EGLImage * +wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attr_list) +{ + struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx); + struct wgl_egl_image *wgl_img; + GLuint texture = (GLuint) (uintptr_t) buffer; + _EGLImageAttribs attrs; + GLuint depth; + GLenum gl_target; + enum stw_image_error error; + + if (texture == 0) { + _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + if (!_eglParseImageAttribList(&attrs, disp, attr_list)) + 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: + unreachable("Unexpected target in wgl_create_image_khr_texture()"); + return EGL_NO_IMAGE_KHR; + } + + wgl_img = malloc(sizeof *wgl_img); + if (!wgl_img) { + _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + _eglInitImage(&wgl_img->base, disp); + + wgl_img->img = stw_create_image_from_texture(wgl_ctx->ctx, + gl_target, + texture, + depth, + attrs.GLTextureLevel, + &error); + assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS)); + + if (!wgl_img->img) { + free(wgl_img); + _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + return &wgl_img->base; +} + +static _EGLImage * +wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, + const EGLint *attr_list) +{ + struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx); + struct wgl_egl_image *wgl_img; + GLuint renderbuffer = (GLuint) (uintptr_t) buffer; + enum stw_image_error error; + + if (renderbuffer == 0) { + _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + wgl_img = malloc(sizeof(*wgl_img)); + if (!wgl_img) { + _eglError(EGL_BAD_ALLOC, "wgl_create_image"); + return NULL; + } + + _eglInitImage(&wgl_img->base, disp); + + wgl_img->img = stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error); + assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS)); + + if (!wgl_img->img) { + free(wgl_img); + _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + return &wgl_img->base; +} + +static _EGLImage * +wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + 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: + case EGL_GL_TEXTURE_3D_KHR: + return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list); + case EGL_GL_RENDERBUFFER_KHR: + return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); + default: + _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } +} + +static EGLBoolean +wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img) +{ + struct wgl_egl_image *wgl_img = wgl_egl_image(img); + stw_destroy_image(wgl_img->img); + free(wgl_img); + return EGL_TRUE; +} + struct _egl_driver _eglDriver = { .Initialize = wgl_initialize, .Terminate = wgl_terminate, @@ -858,5 +1005,7 @@ struct _egl_driver _eglDriver = { .SwapBuffers = wgl_swap_buffers, .WaitClient = wgl_wait_client, .WaitNative = wgl_wait_native, + .CreateImageKHR = wgl_create_image_khr, + .DestroyImageKHR = wgl_destroy_image_khr, }; diff --git a/src/egl/drivers/wgl/egl_wgl.h b/src/egl/drivers/wgl/egl_wgl.h index d7bb68daf64..7fd5408d1b3 100644 --- a/src/egl/drivers/wgl/egl_wgl.h +++ b/src/egl/drivers/wgl/egl_wgl.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -54,4 +55,11 @@ struct wgl_egl_surface struct stw_framebuffer *fb; }; +struct wgl_egl_image +{ + _EGLImage base; + struct stw_image *img; +}; + _EGL_DRIVER_STANDARD_TYPECASTS(wgl_egl) +_EGL_DRIVER_TYPECAST(wgl_egl_image, _EGLImage, obj) diff --git a/src/gallium/frontends/wgl/meson.build b/src/gallium/frontends/wgl/meson.build index 0e75e510f73..340e9cf0dd9 100644 --- a/src/gallium/frontends/wgl/meson.build +++ b/src/gallium/frontends/wgl/meson.build @@ -38,6 +38,7 @@ libwgl = static_library( 'stw_ext_swapinterval.c', 'stw_framebuffer.c', 'stw_getprocaddress.c', + 'stw_image.c', 'stw_nopfuncs.c', 'stw_nopfuncs.h', 'stw_pixelformat.c', diff --git a/src/gallium/frontends/wgl/stw_context.h b/src/gallium/frontends/wgl/stw_context.h index caf3efa4ffa..170cd7def19 100644 --- a/src/gallium/frontends/wgl/stw_context.h +++ b/src/gallium/frontends/wgl/stw_context.h @@ -29,6 +29,8 @@ #define STW_CONTEXT_H #include +#include +#include struct hud_context; struct stw_framebuffer; diff --git a/src/gallium/frontends/wgl/stw_image.c b/src/gallium/frontends/wgl/stw_image.c new file mode 100644 index 00000000000..cedd8d25c29 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_image.c @@ -0,0 +1,135 @@ +/* + * Copyright © Microsoft Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "stw_image.h" +#include +#include +#include + +#include
+#include
+#include +#include + +struct stw_image * +stw_create_image_from_texture(struct stw_context *ctx, GLenum gl_target, GLuint texture, + GLuint depth, GLint level, enum stw_image_error *error) +{ + struct st_context *st_ctx = (struct st_context *)ctx->st; + struct gl_context *gl_ctx = st_ctx->ctx; + struct gl_texture_object *obj; + struct pipe_resource *tex; + GLuint face = 0; + + obj = _mesa_lookup_texture(gl_ctx, texture); + if (!obj || obj->Target != gl_target) { + *error = STW_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + tex = st_get_texobj_resource(obj); + if (!tex) { + *error = STW_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + if (gl_target == GL_TEXTURE_CUBE_MAP) + face = depth; + + _mesa_test_texobj_completeness(gl_ctx, obj); + if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { + *error = STW_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + if (level < obj->Attrib.BaseLevel || level > obj->_MaxLevel) { + *error = STW_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + if (gl_target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { + *error = STW_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + struct stw_image *ret = calloc(1, sizeof(struct stw_image)); + pipe_resource_reference(&ret->pres, tex); + ret->level = level; + ret->layer = depth; + ret->format = tex->format; + + gl_ctx->Shared->HasExternallySharedImages = true; + *error = STW_IMAGE_ERROR_SUCCESS; + return ret; +} + +struct stw_image * +stw_create_image_from_renderbuffer(struct stw_context *ctx, GLuint renderbuffer, + enum stw_image_error *error) +{ + struct st_context *st_ctx = (struct st_context *)ctx->st; + struct gl_context *gl_ctx = st_ctx->ctx; + struct gl_renderbuffer *rb; + struct pipe_resource *tex; + + /* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5 + * specification says: + * + * "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a + * renderbuffer object, or if buffer is the name of a multisampled + * renderbuffer object, the error EGL_BAD_PARAMETER is generated." + * + * "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*, + * EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the + * default GL texture object (0) for the corresponding GL target, the + * error EGL_BAD_PARAMETER is generated." + * (rely on _mesa_lookup_renderbuffer returning NULL in this case) + */ + rb = _mesa_lookup_renderbuffer(gl_ctx, renderbuffer); + if (!rb || rb->NumSamples > 0) { + *error = STW_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + tex = rb->texture; + if (!tex) { + *error = STW_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + struct stw_image *ret = calloc(1, sizeof(struct stw_image)); + pipe_resource_reference(&ret->pres, tex); + ret->format = tex->format; + + gl_ctx->Shared->HasExternallySharedImages = true; + *error = STW_IMAGE_ERROR_SUCCESS; + return ret; +} + +void +stw_destroy_image(struct stw_image *img) +{ + pipe_resource_reference(&img->pres, NULL); + free(img); +} + diff --git a/src/gallium/frontends/wgl/stw_image.h b/src/gallium/frontends/wgl/stw_image.h new file mode 100644 index 00000000000..2a1e04bcd16 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_image.h @@ -0,0 +1,57 @@ +/* + * Copyright © Microsoft Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#pragma once + +#include +#include "stw_context.h" + +#include + +enum stw_image_error +{ + STW_IMAGE_ERROR_SUCCESS, + STW_IMAGE_ERROR_BAD_ALLOC, + STW_IMAGE_ERROR_BAD_PARAMETER, + STW_IMAGE_ERROR_BAD_MATCH, + STW_IMAGE_ERROR_BAD_ACCESS, +}; + +struct stw_image +{ + struct pipe_resource *pres; + unsigned level; + unsigned layer; + enum pipe_format format; +}; + +struct stw_image * +stw_create_image_from_texture(struct stw_context *ctx, GLenum gl_target, GLuint texture, + GLuint depth, GLint level, enum stw_image_error *error); + +struct stw_image * +stw_create_image_from_renderbuffer(struct stw_context *ctx, GLuint renderbuffer, + enum stw_image_error *error); + +void +stw_destroy_image(struct stw_image *img); diff --git a/src/gallium/targets/wgl/gallium_wgl.def.in b/src/gallium/targets/wgl/gallium_wgl.def.in index 49e0963f727..76b93264382 100644 --- a/src/gallium/targets/wgl/gallium_wgl.def.in +++ b/src/gallium/targets/wgl/gallium_wgl.def.in @@ -39,3 +39,6 @@ stw_framebuffer_unlock stw_framebuffer_swap_locked stw_get_framebuffer_resource stw_pbuffer_create +stw_create_image_from_texture +stw_create_image_from_renderbuffer +stw_destroy_image