This splits off the (still) rather large chunk that is get_texture_for_framebuffer into lots of smaller functions specialized to service the wide variety of unique needs of *FramebufferTexture* entry points. The result is much cleaner because, rather than having a pile of branches and confusing conditions (like the boolean layered), the uniqueness is baked into the entry points. The entry points know whether or not they are layered or use a textarget. --- src/mesa/main/fbobject.c | 457 +++++++++++++++++++++++++---------------------- src/mesa/main/fbobject.h | 2 +- 2 files changed, 247 insertions(+), 212 deletions(-)
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f634aed..4df0b6b 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -2415,14 +2415,7 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, /** * Common code called by gl*FramebufferTexture*() to retrieve the correct - * texture object pointer and check for associated errors. - * - * \param textarget is the textarget that was passed to the - * glFramebufferTexture...() function, or 0 if the corresponding function - * doesn't have a textarget parameter. - * - * \param layered is true if this function was called from - * gl*FramebufferTexture(), false otherwise. + * texture object pointer. * * \param texObj where the pointer to the texture object is returned. Note * that a successful call may return texObj = NULL. @@ -2430,20 +2423,12 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, * \return true if no errors, false if errors */ static bool -get_texture_for_framebuffer(struct gl_context *ctx, - GLuint texture, GLenum textarget, - GLint level, GLuint zoffset, GLboolean *layered, - const char *caller, +get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture, + bool layered, const char *caller, struct gl_texture_object **texObj) { - GLenum maxLevelsTarget; - GLboolean err = GL_TRUE; - *texObj = NULL; /* This will get returned if texture = 0. */ - /* The textarget, level, and zoffset parameters are only validated if - * texture is non-zero. - */ if (!texture) return true; @@ -2458,27 +2443,40 @@ get_texture_for_framebuffer(struct gl_context *ctx, * value, while the other commands throw invalid operation (where * *layered = GL_FALSE). */ - GLenum no_texobj_err = *layered ? GL_INVALID_VALUE : + GLenum no_texobj_err = layered ? GL_INVALID_VALUE : GL_INVALID_OPERATION; _mesa_error(ctx, no_texobj_err, "%s(non-generated texture %u)", caller, texture); return false; } - if (textarget == 0) { - if (*layered) { - /* We're being called by gl*FramebufferTexture() and textarget - * is not used. - */ - switch ((*texObj)->Target) { + return true; +} + +/** + * Common code called by gl*FramebufferTexture() to verify the texture target + * and decide whether or not the attachment should truly be considered + * layered. + * + * \param layered true if attachment should be considered layered, false if + * not + * + * \return true if no errors, false if errors + */ +static bool +check_layered_texture_target(struct gl_context *ctx, GLenum target, + const char *caller, bool *layered) +{ + *layered = true; + + switch (target) { case GL_TEXTURE_3D: case GL_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - err = false; - break; + return true; case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_RECTANGLE: @@ -2486,41 +2484,139 @@ get_texture_for_framebuffer(struct gl_context *ctx, /* These texture types are valid to pass to * glFramebufferTexture(), but since they aren't layered, it * is equivalent to calling glFramebufferTexture{1D,2D}(). + * + * textarget can remain 0 since CUBE MAP is not valid here. */ - err = false; *layered = false; - textarget = (*texObj)->Target; - break; - default: - err = true; - break; + return true; } - } else { + + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return false; +} + +/** + * Common code called by gl*FramebufferTextureLayer() to verify the texture + * target. + * + * \return true if no errors, false if errors + */ +static bool +check_texture_target(struct gl_context *ctx, GLenum target, + const char *caller) +{ /* We're being called by glFramebufferTextureLayer() and * textarget is not used. The only legal texture types for * that function are 3D and 1D/2D arrays textures. */ - err = ((*texObj)->Target != GL_TEXTURE_3D) && - ((*texObj)->Target != GL_TEXTURE_1D_ARRAY_EXT) && - ((*texObj)->Target != GL_TEXTURE_2D_ARRAY_EXT) && - ((*texObj)->Target != GL_TEXTURE_CUBE_MAP_ARRAY) && - ((*texObj)->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY); + switch (target) { + case GL_TEXTURE_3D: + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return true; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return false; +} + +/** + * Common code called by glFramebufferTexture*D() to verify the texture + * target. + * + * \return true if no errors, false if errors + */ +static bool +check_textarget(struct gl_context *ctx, int dims, GLenum target, + GLenum textarget, const char *caller) +{ + bool err = false; + + switch (dims) { + case 1: + switch (textarget) { + case GL_TEXTURE_1D: + break; + case GL_TEXTURE_1D_ARRAY: + err = !ctx->Extensions.EXT_texture_array; + break; + default: + err = true; } + break; + case 2: + switch (textarget) { + case GL_TEXTURE_2D: + break; + case GL_TEXTURE_RECTANGLE: + err = _mesa_is_gles(ctx) + || !ctx->Extensions.NV_texture_rectangle; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + err = !ctx->Extensions.ARB_texture_cube_map; + break; + case GL_TEXTURE_2D_ARRAY: + err = (_mesa_is_gles(ctx) && ctx->Version < 30) + || !ctx->Extensions.EXT_texture_array; + break; + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + err = _mesa_is_gles(ctx) + || !ctx->Extensions.ARB_texture_multisample; + break; + default: + err = true; + } + break; + case 3: + if (textarget != GL_TEXTURE_3D) + err = true; + break; + default: + err = true; } - else { - /* Make sure textarget is consistent with the texture's type */ - err = ((*texObj)->Target == GL_TEXTURE_CUBE_MAP) - ? !_mesa_is_cube_face(textarget) - : ((*texObj)->Target != textarget); + + if (err) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target)", caller); + return false; } + /* Make sure textarget is consistent with the texture's type */ + err = (target == GL_TEXTURE_CUBE_MAP) ? + !_mesa_is_cube_face(textarget): (target != textarget); + if (err) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(invalid or mismatched texture target)", caller); + "%s(mismatched texture target)", caller); return false; } - if ((*texObj)->Target == GL_TEXTURE_3D) { + return true; +} + +/** + * Common code called by gl*FramebufferTextureLayer() and + * glFramebufferTexture3D() to verify the zoffset. + * + * \return true if no errors, false if errors + */ +static bool +check_zoffset(struct gl_context *ctx, GLenum target, GLuint zoffset, + const char *caller) +{ + if (target == GL_TEXTURE_3D) { const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); if (zoffset >= maxSize) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -2528,10 +2624,10 @@ get_texture_for_framebuffer(struct gl_context *ctx, return false; } } - else if (((*texObj)->Target == GL_TEXTURE_1D_ARRAY_EXT) || - ((*texObj)->Target == GL_TEXTURE_2D_ARRAY_EXT) || - ((*texObj)->Target == GL_TEXTURE_CUBE_MAP_ARRAY) || - ((*texObj)->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { + else if ((target == GL_TEXTURE_1D_ARRAY_EXT) || + (target == GL_TEXTURE_2D_ARRAY_EXT) || + (target == GL_TEXTURE_CUBE_MAP_ARRAY) || + (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { if (zoffset >= ctx->Const.MaxArrayTextureLayers) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid layer %u)", caller, zoffset); @@ -2539,9 +2635,21 @@ get_texture_for_framebuffer(struct gl_context *ctx, } } - maxLevelsTarget = textarget ? textarget : (*texObj)->Target; + return true; +} + +/** + * Common code called by all gl*FramebufferTexture*() entry points to verify + * the level. + * + * \return true if no errors, false if errors + */ +static bool +check_level(struct gl_context *ctx, GLenum target, GLint level, + const char *caller) +{ if ((level < 0) || - (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) { + (level >= _mesa_max_texture_levels(ctx, target))) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid level %d)", caller, level); return false; @@ -2554,7 +2662,7 @@ void _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, GLenum attachment, struct gl_texture_object *texObj, GLenum textarget, - GLint level, GLuint zoffset, GLboolean layered, + GLint level, GLuint zoffset, bool layered, const char *caller) { struct gl_renderbuffer_attachment *att; @@ -2639,127 +2747,58 @@ _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, } -void GLAPIENTRY -_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) +static void +framebuffer_texture_with_dims(int dims, GLenum target, + GLenum attachment, GLenum textarget, + GLuint texture, GLint level, GLint zoffset, + const char *caller) { GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered = GL_FALSE; - - if (texture != 0) { - GLboolean error; - - switch (textarget) { - case GL_TEXTURE_1D: - error = GL_FALSE; - break; - case GL_TEXTURE_1D_ARRAY: - error = !ctx->Extensions.EXT_texture_array; - break; - default: - error = GL_TRUE; - } - - if (error) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture1D(invalid texture target %s)", - _mesa_lookup_enum_by_nr(textarget)); - return; - } - } /* Get the framebuffer object */ fb = get_framebuffer_target(ctx, target); if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture1D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, _mesa_lookup_enum_by_nr(target)); return; } /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, textarget, level, 0, - &layered, "glFramebufferTexture1D", - &texObj)) { - /* Error already recorded */ + if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj)) return; + + if (texObj) { + if (!check_textarget(ctx, dims, texObj->Target, textarget, caller)) + return; + + if ((dims == 3) && !check_zoffset(ctx, texObj->Target, zoffset, caller)) + return; + } + if (!check_level(ctx, textarget, level, caller)) + return; _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, - 0, layered, "glFramebufferTexture1D"); + zoffset, false, caller); } - void GLAPIENTRY -_mesa_FramebufferTexture2D(GLenum target, GLenum attachment, +_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - GET_CURRENT_CONTEXT(ctx); - struct gl_framebuffer *fb; - struct gl_texture_object *texObj; - GLboolean layered = GL_FALSE; - - if (texture != 0) { - GLboolean error; - - switch (textarget) { - case GL_TEXTURE_2D: - error = GL_FALSE; - break; - case GL_TEXTURE_RECTANGLE: - error = _mesa_is_gles(ctx) - || !ctx->Extensions.NV_texture_rectangle; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - error = !ctx->Extensions.ARB_texture_cube_map; - break; - case GL_TEXTURE_2D_ARRAY: - error = (_mesa_is_gles(ctx) && ctx->Version < 30) - || !ctx->Extensions.EXT_texture_array; - break; - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - error = _mesa_is_gles(ctx) - || !ctx->Extensions.ARB_texture_multisample; - break; - default: - error = GL_TRUE; - } - - if (error) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture2D(invalid texture target %s)", - _mesa_lookup_enum_by_nr(textarget)); - return; - } - } + framebuffer_texture_with_dims(1, target, attachment, textarget, texture, + level, 0, "glFramebufferTexture1D"); +} - /* Get the framebuffer object */ - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture2D(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); - return; - } - /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, textarget, level, 0, - &layered, "glFramebufferTexture2D", - &texObj)) { - /* Error already recorded */ - return; - } - - _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, - 0, layered, "glFramebufferTexture2D"); +void GLAPIENTRY +_mesa_FramebufferTexture2D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + framebuffer_texture_with_dims(2, target, attachment, textarget, texture, + level, 0, "glFramebufferTexture2D"); } @@ -2768,37 +2807,8 @@ _mesa_FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { - GET_CURRENT_CONTEXT(ctx); - struct gl_framebuffer *fb; - struct gl_texture_object *texObj; - GLboolean layered = GL_FALSE; - - if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture3D(invalid texture target %s)", - _mesa_lookup_enum_by_nr(textarget)); - return; - } - - /* Get the framebuffer object */ - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture3D(invalid target %s)", - _mesa_lookup_enum_by_nr(target)); - return; - } - - /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, textarget, level, zoffset, - &layered, "glFramebufferTexture3D", - &texObj)) { - /* Error already recorded */ - return; - } - - _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, - zoffset, layered, "glFramebufferTexture3D"); + framebuffer_texture_with_dims(3, target, attachment, textarget, texture, + level, zoffset, "glFramebufferTexture3D"); } @@ -2809,7 +2819,8 @@ _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered = GL_FALSE; + + const char *func = "glFramebufferTextureLayer"; /* Get the framebuffer object */ fb = get_framebuffer_target(ctx, target); @@ -2821,15 +2832,22 @@ _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, } /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, 0, level, layer, - &layered, "glFramebufferTextureLayer", - &texObj)) { - /* Error already recorded */ + if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj)) return; + + if (texObj) { + if (!check_texture_target(ctx, texObj->Target, func)) + return; + + if (!check_zoffset(ctx, texObj->Target, layer, func)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; } _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, - layer, layered, "glFramebufferTextureLayer"); + layer, false, func); } void GLAPIENTRY @@ -2839,26 +2857,31 @@ _mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment, GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered = GL_FALSE; + + const char *func = "glNamedFramebufferTextureLayer"; /* Get the framebuffer object */ - fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, - "glNamedFramebufferTextureLayer"); + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func); if (!fb) return; /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, 0, level, layer, - &layered, - "glNamedFramebufferTextureLayer", - &texObj)) { - /* Error already recorded */ + if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj)) return; + + if (texObj) { + if (!check_texture_target(ctx, texObj->Target, func)) + return; + + if (!check_zoffset(ctx, texObj->Target, layer, func)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; } _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, - layer, layered, - "glNamedFramebufferTextureLayer"); + layer, false, func); } @@ -2869,7 +2892,9 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered = GL_TRUE; + bool layered; + + const char *func = "FramebufferTexture"; if (!_mesa_has_geometry_shaders(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -2887,15 +2912,19 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, } /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, 0, level, 0, - &layered, "glFramebufferTexture", - &texObj)) { - /* Error already recorded */ + if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj)) return; + + if (texObj) { + if (!check_layered_texture_target(ctx, texObj->Target, func, &layered)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; } _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, - 0, layered, "glFramebufferTexture"); + 0, layered, func); } void GLAPIENTRY @@ -2905,7 +2934,9 @@ _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, GET_CURRENT_CONTEXT(ctx); struct gl_framebuffer *fb; struct gl_texture_object *texObj; - GLboolean layered = GL_TRUE; + bool layered; + + const char *func = "glNamedFramebufferTexture"; if (!_mesa_has_geometry_shaders(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -2914,21 +2945,25 @@ _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, } /* Get the framebuffer object */ - fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, - "glNamedFramebufferTexture"); + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func); if (!fb) return; /* Get the texture object */ - if (!get_texture_for_framebuffer(ctx, texture, 0, level, 0, - &layered, "glNamedFramebufferTexture", - &texObj)) { - /* Error already recorded */ + if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj)) return; + + if (texObj) { + if (!check_layered_texture_target(ctx, texObj->Target, func, + &layered)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; } _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, - 0, layered, "glNamedFramebufferTexture"); + 0, layered, func); } diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index 7487f02..96d39a7 100644 --- a/src/mesa/main/fbobject.h +++ b/src/mesa/main/fbobject.h @@ -119,7 +119,7 @@ extern void _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, GLenum attachment, struct gl_texture_object *texObj, GLenum textarget, - GLint level, GLuint zoffset, GLboolean layered, + GLint level, GLuint zoffset, bool layered, const char *caller); -- 2.1.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev