egl,wgl: Support eglCreateImageKHR

Acked-by: Daniel Stone <daniels@collabora.com>
Acked-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Acked-by: Sidney Just <justsid@x-plane.com>
Acked-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Tested-by: Yonggang Luo <luoyonggang@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12964>
This commit is contained in:
Jesse Natalie 2021-09-20 15:24:19 -07:00 committed by Marge Bot
parent 76756ea4c6
commit d57a4abcf8
7 changed files with 367 additions and 12 deletions

View file

@ -33,6 +33,7 @@
#include <stw_pixelformat.h>
#include <stw_context.h>
#include <stw_framebuffer.h>
#include <stw_image.h>
#include <GL/wglext.h>
@ -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,
};

View file

@ -26,6 +26,7 @@
#include <egldriver.h>
#include <egldisplay.h>
#include <eglconfig.h>
#include <eglimage.h>
#include <stw_pixelformat.h>
#include <windows.h>
@ -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)

View file

@ -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',

View file

@ -29,6 +29,8 @@
#define STW_CONTEXT_H
#include <windows.h>
#include <GL/gl.h>
#include <gldrv.h>
struct hud_context;
struct stw_framebuffer;

View file

@ -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 <pipe/p_state.h>
#include <util/u_inlines.h>
#include <frontend/api.h>
#include <main/mtypes.h>
#include <main/texobj.h>
#include <state_tracker/st_context.h>
#include <state_tracker/st_texture.h>
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);
}

View file

@ -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 <pipe/p_state.h>
#include "stw_context.h"
#include <GL/gl.h>
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);

View file

@ -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