From 68c43ae8b2026acca482639292b3a673fb06ef6f Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 18 Jul 2017 10:53:14 +0200 Subject: [PATCH] mesa: add texture_view() helper Signed-off-by: Samuel Pitoiset Reviewed-by: Timothy Arceri --- src/mesa/main/textureview.c | 336 +++++++++++++++++++----------------- 1 file changed, 175 insertions(+), 161 deletions(-) diff --git a/src/mesa/main/textureview.c b/src/mesa/main/textureview.c index cef9caff41c..165af3c7469 100644 --- a/src/mesa/main/textureview.c +++ b/src/mesa/main/textureview.c @@ -518,119 +518,19 @@ _mesa_set_texture_view_state(struct gl_context *ctx, * If an error is found, record it with _mesa_error() * \return none. */ -void GLAPIENTRY -_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, - GLenum internalformat, - GLuint minlevel, GLuint numlevels, - GLuint minlayer, GLuint numlayers) +static ALWAYS_INLINE void +texture_view(struct gl_context *ctx, struct gl_texture_object *origTexObj, + struct gl_texture_object *texObj, GLenum target, + GLenum internalformat, GLuint minlevel, GLuint numlevels, + GLuint minlayer, GLuint numlayers, bool no_error) { - struct gl_texture_object *texObj; - struct gl_texture_object *origTexObj; struct gl_texture_image *origTexImage; - GLuint newViewMinLevel, newViewMinLayer; GLuint newViewNumLevels, newViewNumLayers; GLsizei width, height, depth; mesa_format texFormat; GLboolean sizeOK, dimensionsOK; GLenum faceTarget; - GET_CURRENT_CONTEXT(ctx); - - if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", - texture, _mesa_enum_to_string(target), origtexture, - _mesa_enum_to_string(internalformat), - minlevel, numlevels, minlayer, numlayers); - - if (origtexture == 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", - origtexture); - return; - } - - /* Need original texture information to validate arguments */ - origTexObj = _mesa_lookup_texture(ctx, origtexture); - - /* If is not the name of a texture, INVALID_VALUE - * is generated. - */ - if (!origTexObj) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", - origtexture); - return; - } - - /* If 's TEXTURE_IMMUTABLE_FORMAT value is not TRUE, - * INVALID_OPERATION is generated. - */ - if (!origTexObj->Immutable) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(origtexture not immutable)"); - return; - } - - /* If is 0, INVALID_VALUE is generated. */ - if (texture == 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); - return; - } - - /* If is not a valid name returned by GenTextures, - * the error INVALID_OPERATION is generated. - */ - texObj = _mesa_lookup_texture(ctx, texture); - if (texObj == NULL) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(texture = %u non-gen name)", texture); - return; - } - - /* If has already been bound and given a target, then - * the error INVALID_OPERATION is generated. - */ - if (texObj->Target) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(texture = %u already bound)", texture); - return; - } - - /* Check for compatible target */ - if (!target_valid(ctx, origTexObj->Target, target)) { - return; /* error was recorded */ - } - - /* minlevel and minlayer are relative to the view of origtexture. - * If minlevel or minlayer is greater than level or layer, respectively, - * return INVALID_VALUE. - */ - newViewMinLevel = origTexObj->MinLevel + minlevel; - newViewMinLayer = origTexObj->MinLayer + minlayer; - if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTextureView(new minlevel (%d) > orig minlevel (%d)" - " + orig numlevels (%d))", - newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); - return; - } - - if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTextureView(new minlayer (%d) > orig minlayer (%d)" - " + orig numlayers (%d))", - newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); - return; - } - - if (!_mesa_texture_view_compatible_format(ctx, - origTexObj->Image[0][0]->InternalFormat, - internalformat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(internalformat %s not compatible with origtexture %s)", - _mesa_enum_to_string(internalformat), - _mesa_enum_to_string(origTexObj->Image[0][0]->InternalFormat)); - return; - } - texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, internalformat, GL_NONE, GL_NONE); if (texFormat == MESA_FORMAT_NONE) return; @@ -668,7 +568,7 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped * must be equal to 6. */ - if (newViewNumLayers != 6) { + if (!no_error && newViewNumLayers != 6) { _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(clamped numlayers %d != 6)", newViewNumLayers); @@ -687,7 +587,7 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, * and the clamped must be a multiple of 6. * Otherwise, the error INVALID_VALUE is generated. */ - if ((newViewNumLayers % 6) != 0) { + if (!no_error && (newViewNumLayers % 6) != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(clamped numlayers %d is not" " a multiple of 6)", @@ -698,62 +598,65 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, break; } - /* If the dimensions of the original texture are larger than the maximum - * supported dimensions of the new target, the error INVALID_OPERATION is - * generated. For example, if the original texture has a TEXTURE_2D_ARRAY - * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an error - * will be generated if TextureView is called to create a TEXTURE_CUBE_MAP - * view. - */ - dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, - width, height, depth, 0); - if (!dimensionsOK) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(invalid width or height or depth)"); - return; - } - - sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 1, 0, texFormat, - origTexImage->NumSamples, - width, height, depth); - if (!sizeOK) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(invalid texture size)"); - return; - } + if (!no_error) { + /* If the dimensions of the original texture are larger than the maximum + * supported dimensions of the new target, the error INVALID_OPERATION is + * generated. For example, if the original texture has a TEXTURE_2D_ARRAY + * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an + * error will be generated if TextureView is called to create a + * TEXTURE_CUBE_MAP view. + */ + dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, + width, height, depth, 0); + if (!dimensionsOK) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(invalid width or height or depth)"); + return; + } - /* If is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, - * or TEXTURE_2D_MULTISAMPLE and does not equal 1, the error - * INVALID_VALUE is generated. - */ - switch (target) { - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_RECTANGLE: - case GL_TEXTURE_2D_MULTISAMPLE: - if (numlayers != 1) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", - numlayers); + sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 1, 0, texFormat, + origTexImage->NumSamples, + width, height, depth); + if (!sizeOK) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(invalid texture size)"); return; } - break; - case GL_TEXTURE_CUBE_MAP: - break; - case GL_TEXTURE_CUBE_MAP_ARRAY: - break; - } - /* If the new texture's target is TEXTURE_CUBE_MAP or - * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's - * levels must be equal otherwise the error INVALID_OPERATION is generated. - */ - if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) && - (origTexImage->Width != origTexImage->Height)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(origtexture width (%d) != height (%d))", - origTexImage->Width, origTexImage->Height); - return; + /* If is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, + * or TEXTURE_2D_MULTISAMPLE and does not equal 1, the error + * INVALID_VALUE is generated. + */ + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + if (numlayers != 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", + numlayers); + return; + } + break; + case GL_TEXTURE_CUBE_MAP: + break; + case GL_TEXTURE_CUBE_MAP_ARRAY: + break; + } + + /* If the new texture's target is TEXTURE_CUBE_MAP or + * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's + * levels must be equal otherwise the error INVALID_OPERATION is + * generated. + */ + if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) + && (origTexImage->Width != origTexImage->Height)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(origtexture width (%d) != height (%d))", + origTexImage->Width, origTexImage->Height); + return; + } } /* When the original texture's target is TEXTURE_CUBE_MAP, the layer @@ -777,8 +680,8 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, return; /* Already recorded error */ } - texObj->MinLevel = newViewMinLevel; - texObj->MinLayer = newViewMinLayer; + texObj->MinLevel = origTexObj->MinLevel + minlevel; + texObj->MinLayer = origTexObj->MinLayer + minlayer; texObj->NumLevels = newViewNumLevels; texObj->NumLayers = newViewNumLayers; texObj->Immutable = GL_TRUE; @@ -792,3 +695,114 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, return; /* driver recorded error */ } } + +void GLAPIENTRY +_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, + GLenum internalformat, + GLuint minlevel, GLuint numlevels, + GLuint minlayer, GLuint numlayers) +{ + struct gl_texture_object *texObj; + struct gl_texture_object *origTexObj; + GLuint newViewMinLevel, newViewMinLayer; + + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", + texture, _mesa_enum_to_string(target), origtexture, + _mesa_enum_to_string(internalformat), + minlevel, numlevels, minlayer, numlayers); + + if (origtexture == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", + origtexture); + return; + } + + /* Need original texture information to validate arguments */ + origTexObj = _mesa_lookup_texture(ctx, origtexture); + + /* If is not the name of a texture, INVALID_VALUE + * is generated. + */ + if (!origTexObj) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", + origtexture); + return; + } + + /* If 's TEXTURE_IMMUTABLE_FORMAT value is not TRUE, + * INVALID_OPERATION is generated. + */ + if (!origTexObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(origtexture not immutable)"); + return; + } + + /* If is 0, INVALID_VALUE is generated. */ + if (texture == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); + return; + } + + /* If is not a valid name returned by GenTextures, + * the error INVALID_OPERATION is generated. + */ + texObj = _mesa_lookup_texture(ctx, texture); + if (texObj == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(texture = %u non-gen name)", texture); + return; + } + + /* If has already been bound and given a target, then + * the error INVALID_OPERATION is generated. + */ + if (texObj->Target) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(texture = %u already bound)", texture); + return; + } + + /* Check for compatible target */ + if (!target_valid(ctx, origTexObj->Target, target)) { + return; /* error was recorded */ + } + + /* minlevel and minlayer are relative to the view of origtexture. + * If minlevel or minlayer is greater than level or layer, respectively, + * return INVALID_VALUE. + */ + newViewMinLevel = origTexObj->MinLevel + minlevel; + newViewMinLayer = origTexObj->MinLayer + minlayer; + if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTextureView(new minlevel (%d) > orig minlevel (%d)" + " + orig numlevels (%d))", + newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); + return; + } + + if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTextureView(new minlayer (%d) > orig minlayer (%d)" + " + orig numlayers (%d))", + newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); + return; + } + + if (!_mesa_texture_view_compatible_format(ctx, + origTexObj->Image[0][0]->InternalFormat, + internalformat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(internalformat %s not compatible with origtexture %s)", + _mesa_enum_to_string(internalformat), + _mesa_enum_to_string(origTexObj->Image[0][0]->InternalFormat)); + return; + } + + texture_view(ctx, origTexObj, texObj, target, internalformat, minlevel, + numlevels, minlayer, numlayers, false); +} -- 2.30.2