From 738318bb75dea8dac4465f53850987f6062a732d Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 4 Apr 2003 17:17:50 +0000 Subject: Rework gl[Copy]Tex[Sub]Image() error checking so that all level, width, height and depth checks are done via ctx->Driver.TestProxyTexImage(). This allows more flexiblity, like supporting larger, non-cubic 3D textures. --- src/mesa/drivers/osmesa/osmesa.c | 3 +- src/mesa/drivers/x11/xm_dd.c | 38 ++- src/mesa/main/config.h | 4 +- src/mesa/main/teximage.c | 558 +++++++++++++++++++-------------------- src/mesa/main/teximage.h | 11 +- src/mesa/main/texstore.c | 36 --- src/mesa/main/texstore.h | 12 +- 7 files changed, 316 insertions(+), 346 deletions(-) diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index 286662b628..195b432885 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -1,5 +1,3 @@ -/* $Id: osmesa.c,v 1.103 2003/04/01 17:28:55 brianp Exp $ */ - /* * Mesa 3-D graphics library * Version: 5.1 @@ -48,6 +46,7 @@ #include "mtypes.h" #include "texformat.h" #include "texobj.h" +#include "teximage.h" #include "texstore.h" #include "array_cache/acache.h" #include "swrast/swrast.h" diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index eec0d8ad32..30a8b51723 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -1,5 +1,3 @@ -/* $Id: xm_dd.c,v 1.47 2003/04/01 17:28:11 brianp Exp $ */ - /* * Mesa 3-D graphics library * Version: 5.1 @@ -36,6 +34,7 @@ #include "mtypes.h" #include "state.h" #include "texobj.h" +#include "teximage.h" #include "texstore.h" #include "texformat.h" #include "xmesaP.h" @@ -924,6 +923,39 @@ void xmesa_update_state( GLcontext *ctx, GLuint new_state ) +/** + * Called via ctx->Driver.TestProxyTeximage(). Normally, we'd just use + * the _mesa_test_proxy_teximage() fallback function, but we're going to + * special-case the 3D texture case to allow textures up to 512x512x32 + * texels. + */ +static GLboolean +test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border) +{ + if (target == GL_PROXY_TEXTURE_3D) { + /* special case for 3D textures */ + if (width * height * depth > 512 * 512 * 64 || + width < 2 * border || _mesa_bitcount(width - 2 * border) != 1 || + height < 2 * border || _mesa_bitcount(height - 2 * border) != 1 || + depth < 2 * border || _mesa_bitcount(depth - 2 * border) != 1) { + /* Bad size, or too many texels */ + return GL_FALSE; + } + return GL_TRUE; + } + else { + /* use the fallback routine for 1D, 2D, cube and rect targets */ + return _mesa_test_proxy_teximage(ctx, target, level, internalFormat, + format, type, width, height, depth, + border); + } +} + + + + /* Setup pointers and other driver state that is constant for the life * of a context. */ @@ -957,7 +989,7 @@ void xmesa_init_pointers( GLcontext *ctx ) ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; - ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + ctx->Driver.TestProxyTexImage = test_proxy_teximage; ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index 264b57c279..85acb0f292 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -1,5 +1,3 @@ -/* $Id: config.h,v 1.45 2003/03/29 17:01:03 brianp Exp $ */ - /* * Mesa 3-D graphics library * Version: 5.1 @@ -107,7 +105,7 @@ #define MAX_TEXTURE_LEVELS 12 /* Number of 3D texture mipmap levels */ -#define MAX_3D_TEXTURE_LEVELS 8 +#define MAX_3D_TEXTURE_LEVELS 9 /* Number of cube texture mipmap levels - GL_ARB_texture_cube_map */ #define MAX_CUBE_TEXTURE_LEVELS 12 diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 11247b5002..1c10aaea01 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -785,7 +785,7 @@ make_null_texture(GLint width, GLint height, GLint depth, GLenum format) -/* +/** * Reset the fields of a gl_texture_image struct to zero. * This is called when a proxy texture test fails, we set all the * image members (except DriverData) to zero. @@ -871,12 +871,103 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, } +/** + * This is the fallback for Driver.TestProxyTexImage(). Test the texture + * level, width, height and depth against the ctx->Const limits for textures. + * + * A hardware driver might override this function if, for example, the + * max 3D texture size is 512x512x64 (i.e. not a cube). + * + * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, + * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, + * GL_PROXY_TEXTURE_CUBE_MAP_ARB. + * \param level as passed to glTexImage + * \param internalFormat as passed to glTexImage + * \param format as passed to glTexImage + * \param type as passed to glTexImage + * \param width as passed to glTexImage + * \param height as passed to glTexImage + * \param depth as passed to glTexImage + * \param border as passed to glTexImage + * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. + */ +GLboolean +_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border) +{ + GLint maxSize; -/* + (void) internalFormat; + (void) format; + (void) type; + + switch (target) { + case GL_PROXY_TEXTURE_1D: + maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + _mesa_bitcount(width - 2 * border) != 1 || + level >= ctx->Const.MaxTextureLevels) { + /* bad width or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_2D: + maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + _mesa_bitcount(width - 2 * border) != 1 || + height < 2 * border || height > 2 + maxSize || + _mesa_bitcount(height - 2 * border) != 1 || + level >= ctx->Const.MaxTextureLevels) { + /* bad width or height or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_3D: + maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + _mesa_bitcount(width - 2 * border) != 1 || + height < 2 * border || height > 2 + maxSize || + _mesa_bitcount(height - 2 * border) != 1 || + depth < 2 * border || depth > 2 + maxSize || + _mesa_bitcount(depth - 2 * border) != 1 || + level >= ctx->Const.Max3DTextureLevels) { + /* bad width or height or depth or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_RECTANGLE_NV: + if (width < 1 || width > ctx->Const.MaxTextureRectSize || + height < 1 || height > ctx->Const.MaxTextureRectSize || + level != 0) { + /* bad width or height or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + _mesa_bitcount(width - 2 * border) != 1 || + height < 2 * border || height > 2 + maxSize || + _mesa_bitcount(height - 2 * border) != 1 || + level >= ctx->Const.MaxCubeTextureLevels) { + /* bad width or height */ + return GL_FALSE; + } + return GL_TRUE; + default: + _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); + return GL_FALSE; + } +} + + +/** * Test glTexImage[123]D() parameters for errors. - * Input: - * dimensions - must be 1 or 2 or 3 - * Return: GL_TRUE = an error was detected, GL_FALSE = no errors + * This function calls the ctx->Driver.TestProxyTexImage() function to + * check the level and size. + * \param dimensions must be 1 or 2 or 3 + * \return GL_TRUE if an error was detected or GL_FALSE if no errors */ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, @@ -886,63 +977,74 @@ texture_error_check( GLcontext *ctx, GLenum target, GLint width, GLint height, GLint depth, GLint border ) { - GLboolean isProxy; - GLint maxLevels = 0, maxTextureSize; + const GLboolean isProxy = is_proxy_target(target); + GLboolean sizeOK; - if (dimensions == 1) { - if (target == GL_PROXY_TEXTURE_1D) { - isProxy = GL_TRUE; + /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(level=%d)", dimensions, level); } - else if (target == GL_TEXTURE_1D) { - isProxy = GL_FALSE; + return GL_TRUE; + } + + /* Check border */ + if (border < 0 || border > 1 || + ((target == GL_TEXTURE_RECTANGLE_NV || + target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(border=%d)", dimensions, border); + } + return GL_TRUE; + } + + /* Check target and call ctx->Driver.TestProxyTexImage() to check the + * level, width, height and depth. + */ + if (dimensions == 1) { + if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, + level, internalFormat, + format, type, + width, 1, 1, border); } else { _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); return GL_TRUE; } - maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { - if (target == GL_PROXY_TEXTURE_2D) { - isProxy = GL_TRUE; - maxLevels = ctx->Const.MaxTextureLevels; - } - else if (target == GL_TEXTURE_2D) { - isProxy = GL_FALSE; - maxLevels = ctx->Const.MaxTextureLevels; - } - else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { + if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, + level, internalFormat, + format, type, + width, height, 1, border); + } + else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || + (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { if (!ctx->Extensions.ARB_texture_cube_map) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); return GL_TRUE; } - isProxy = GL_TRUE; - maxLevels = ctx->Const.MaxCubeTextureLevels; + sizeOK = (width == height) && + ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, + level, internalFormat, format, type, + width, height, 1, border); } - else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { - if (!ctx->Extensions.ARB_texture_cube_map) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); - return GL_TRUE; - } - isProxy = GL_FALSE; - maxLevels = ctx->Const.MaxCubeTextureLevels; - } - else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV) { - if (!ctx->Extensions.NV_texture_rectangle) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); - return GL_TRUE; - } - isProxy = GL_TRUE; - maxLevels = 1; - } - else if (target == GL_TEXTURE_RECTANGLE_NV) { + else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || + target == GL_TEXTURE_RECTANGLE_NV) { if (!ctx->Extensions.NV_texture_rectangle) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); return GL_TRUE; } - isProxy = GL_FALSE; - maxLevels = 1; + sizeOK = ctx->Driver.TestProxyTexImage(ctx, + GL_PROXY_TEXTURE_RECTANGLE_NV, + level, internalFormat, + format, type, + width, height, 1, border); } else { _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); @@ -950,132 +1052,32 @@ texture_error_check( GLcontext *ctx, GLenum target, } } else if (dimensions == 3) { - if (target == GL_PROXY_TEXTURE_3D) { - isProxy = GL_TRUE; - } - else if (target == GL_TEXTURE_3D) { - isProxy = GL_FALSE; + if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_3D, + level, internalFormat, + format, type, + width, height, depth, border); } else { _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); return GL_TRUE; } - maxLevels = ctx->Const.Max3DTextureLevels; } else { _mesa_problem( ctx, "bad dims in texture_error_check" ); return GL_TRUE; } - ASSERT(maxLevels > 0); - maxTextureSize = 1 << (maxLevels - 1); - - /* Border */ - if (border != 0 && border != 1) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(border=%d)", dimensions, border); - } - return GL_TRUE; - } - if ((target == GL_TEXTURE_RECTANGLE_NV || - target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0) { - return GL_TRUE; - } - - /* Width */ - if (target == GL_TEXTURE_RECTANGLE_NV || - target == GL_PROXY_TEXTURE_RECTANGLE_NV) { - if (width < 1 || width > ctx->Const.MaxTextureRectSize) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(width=%d)", dimensions, width); - } - return GL_TRUE; - } - } - else if (width < 2 * border || width > 2 + maxTextureSize - || logbase2( width - 2 * border ) < 0) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(width=%d)", dimensions, width); - } - return GL_TRUE; - } - - /* Height */ - if (target == GL_TEXTURE_RECTANGLE_NV || - target == GL_PROXY_TEXTURE_RECTANGLE_NV) { - if (height < 1 || height > ctx->Const.MaxTextureRectSize) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(height=%d)", dimensions, height); - } - return GL_TRUE; - } - } - else if (dimensions >= 2) { - if (height < 2 * border || height > 2 + maxTextureSize - || logbase2( height - 2 * border ) < 0) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(height=%d)", dimensions, height); - } - return GL_TRUE; - } - } - - /* For cube map, width must equal height */ - if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { - if (width != height) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); - } - return GL_TRUE; - } - } - - /* Depth */ - if (dimensions >= 3) { - if (depth < 2 * border || depth > 2 + maxTextureSize - || logbase2( depth - 2 * border ) < 0) { - if (!isProxy) { - _mesa_error( ctx, GL_INVALID_VALUE, - "glTexImage3D(depth=%d)", depth ); - } - return GL_TRUE; - } - } - - /* Level */ - if (target == GL_TEXTURE_RECTANGLE_NV || - target == GL_PROXY_TEXTURE_RECTANGLE_NV) { - if (level != 0) { - if (!isProxy) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage2D(level=%d)", level); - } - return GL_TRUE; - } - } - else if (level < 0 || level >= maxLevels) { + if (!sizeOK) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%dD(level=%d)", dimensions, level); + "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", + dimensions, level, width, height, depth); } return GL_TRUE; } - /* For cube map, width must equal height */ - if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { - if (width != height) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); - return GL_TRUE; - } - } - + /* Check internalFormat */ if (_mesa_base_tex_format(ctx, internalFormat) < 0) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1085,6 +1087,7 @@ texture_error_check( GLcontext *ctx, GLenum target, return GL_TRUE; } + /* Check incoming image format and type */ if (!_mesa_is_legal_format_and_type(format, type)) { /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. @@ -1176,52 +1179,47 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions, { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *destTex; - GLint maxLevels = 0; + /* Check target */ if (dimensions == 1) { - if (target == GL_TEXTURE_1D) { - maxLevels = ctx->Const.MaxTextureLevels; - } - else { + if (target != GL_TEXTURE_1D) { _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); return GL_TRUE; } } else if (dimensions == 2) { - if (ctx->Extensions.ARB_texture_cube_map && - target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && target <=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { - maxLevels = ctx->Const.MaxCubeTextureLevels; + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; + } } else if (ctx->Extensions.NV_texture_rectangle && target == GL_TEXTURE_RECTANGLE_NV) { - maxLevels = 1; - } - else if (target == GL_TEXTURE_2D) { - maxLevels = ctx->Const.MaxTextureLevels; + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; + } } - else { + else if (target != GL_TEXTURE_2D) { _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); return GL_TRUE; } } else if (dimensions == 3) { - if (target == GL_TEXTURE_3D) { - maxLevels = ctx->Const.Max3DTextureLevels; - } - else { + if (target != GL_TEXTURE_3D) { _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); return GL_TRUE; } } else { - _mesa_problem( ctx, "bad dims in texture_error_check" ); + _mesa_problem( ctx, "invalid dims in texture_error_check" ); return GL_TRUE; } - ASSERT(maxLevels > 0); - - if (level < 0 || level >= maxLevels) { + /* Basic level check */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); return GL_TRUE; } @@ -1237,32 +1235,38 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions, return GL_TRUE; } if (depth < 0 && dimensions > 2) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(depth=%d)", dimensions, depth); + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexSubImage%dD(depth=%d)", dimensions, depth); return GL_TRUE; } destTex = _mesa_select_tex_image(ctx, texUnit, target, level); if (!destTex) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); + /* undefined image level */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); return GL_TRUE; } if (xoffset < -((GLint)destTex->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", + dimensions); return GL_TRUE; } if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", + dimensions); return GL_TRUE; } if (dimensions > 1) { if (yoffset < -((GLint)destTex->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", + dimensions); return GL_TRUE; } if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", + dimensions); return GL_TRUE; } } @@ -1336,82 +1340,93 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border ) { - GLint maxLevels = 0, maxTextureSize; + GLenum format, type; + GLboolean sizeOK; + /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexImage%dD(level=%d)", dimensions, level); + return GL_TRUE; + } + + /* Check border */ + if (border < 0 || border > 1 || + ((target == GL_TEXTURE_RECTANGLE_NV || + target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { + return GL_TRUE; + } + + /* The format and type aren't really significant here, but we need to pass + * something to TestProxyTexImage(). + */ + format = _mesa_base_tex_format(ctx, internalFormat); + type = GL_FLOAT; + + /* Check target and call ctx->Driver.TestProxyTexImage() to check the + * level, width, height and depth. + */ if (dimensions == 1) { - if (target != GL_TEXTURE_1D) { + if (target == GL_TEXTURE_1D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, + level, internalFormat, + format, type, + width, 1, 1, border); + } + else { _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); return GL_TRUE; } - maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { - if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (target == GL_TEXTURE_2D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, + level, internalFormat, + format, type, + width, height, 1, border); + } + else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { if (!ctx->Extensions.ARB_texture_cube_map) { _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); return GL_TRUE; } + sizeOK = (width == height) && + ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, + level, internalFormat, format, type, + width, height, 1, border); } else if (target == GL_TEXTURE_RECTANGLE_NV) { if (!ctx->Extensions.NV_texture_rectangle) { _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); return GL_TRUE; } + sizeOK = ctx->Driver.TestProxyTexImage(ctx, + GL_PROXY_TEXTURE_RECTANGLE_NV, + level, internalFormat, + format, type, + width, height, 1, border); } - else if (target != GL_TEXTURE_2D) { + else { _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); return GL_TRUE; } - if (target == GL_TEXTURE_2D) - maxLevels = ctx->Const.MaxTextureLevels; - else if (target == GL_TEXTURE_RECTANGLE_NV) - maxLevels = 1; - else - maxLevels = ctx->Const.MaxCubeTextureLevels; - } - - ASSERT(maxLevels > 0); - maxTextureSize = 1 << (maxLevels - 1); - - /* Border */ - if (border != 0 && border != 1) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(border)", dimensions); - return GL_TRUE; } - - /* Width */ - if (width < 2 * border || width > 2 + maxTextureSize - || logbase2( width - 2 * border ) < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(width=%d)", dimensions, width); + else { + _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); return GL_TRUE; } - /* Height */ - if (dimensions >= 2) { - if (height < 2 * border || height > 2 + maxTextureSize - || logbase2( height - 2 * border ) < 0) { + if (!sizeOK) { + if (dimensions == 1) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(height=%d)", dimensions, height); - return GL_TRUE; + "glCopyTexImage1D(width=%d)", width); } - } - - /* For cube map, width must equal height */ - if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { - if (width != height) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)"); - return GL_TRUE; + else { + ASSERT(dimensions == 2); + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexImage2D(width=%d, height=%d)", width, height); } - } - - /* Level */ - if (level < 0 || level >= maxLevels) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(level=%d)", dimensions, level); return GL_TRUE; } @@ -1447,14 +1462,13 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *teximage; - GLint maxLevels = 0; + /* Check target */ if (dimensions == 1) { if (target != GL_TEXTURE_1D) { _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); return GL_TRUE; } - maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && @@ -1474,29 +1488,22 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); return GL_TRUE; } - if (target == GL_TEXTURE_2D) - maxLevels = ctx->Const.MaxTextureLevels; - else if (target == GL_TEXTURE_RECTANGLE_NV) - maxLevels = 1; - else - maxLevels = ctx->Const.MaxCubeTextureLevels; } else if (dimensions == 3) { if (target != GL_TEXTURE_3D) { _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); return GL_TRUE; } - maxLevels = ctx->Const.Max3DTextureLevels; } - ASSERT(maxLevels > 0); - - if (level < 0 || level >= maxLevels) { + /* Check level */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexSubImage%dD(level=%d)", dimensions, level); return GL_TRUE; } + /* Check size */ if (width < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexSubImage%dD(width=%d)", dimensions, width); @@ -1792,30 +1799,22 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, } else if (target == GL_PROXY_TEXTURE_1D) { /* Proxy texture: check for errors and update proxy state */ - GLboolean error = texture_error_check(ctx, target, level, internalFormat, - format, type, 1, postConvWidth, 1, 1, border); - if (!error) { - ASSERT(ctx->Driver.TestProxyTexImage); - error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, - internalFormat, format, type, - postConvWidth, 1, 1, border); - } - if (error) { - /* if error, clear all proxy texture image parameters */ - struct gl_texture_image *texImage; - texImage = _mesa_get_proxy_tex_image(ctx, target, level); + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 1, postConvWidth, 1, 1, border)) { + /* when error, clear all proxy texture image parameters */ if (texImage) clear_teximage_fields(texImage); } else { /* no error, set the tex image parameters */ - struct gl_texture_unit *texUnit; - struct gl_texture_image *texImage; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + ASSERT(texImage); _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, border, internalFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); } } else { @@ -1901,30 +1900,22 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, (target == GL_PROXY_TEXTURE_RECTANGLE_NV && ctx->Extensions.NV_texture_rectangle)) { /* Proxy texture: check for errors and update proxy state */ - GLboolean error = texture_error_check(ctx, target, level, internalFormat, - format, type, 2, postConvWidth, postConvHeight, 1, border); - if (!error) { - ASSERT(ctx->Driver.TestProxyTexImage); - error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, - internalFormat, format, type, - postConvWidth, postConvHeight, 1, border); - } - if (error) { - /* if error, clear all proxy texture image parameters */ - struct gl_texture_image *texImage; - texImage = _mesa_get_proxy_tex_image(ctx, target, level); + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 2, postConvWidth, postConvHeight, + 1, border)) { + /* when error, clear all proxy texture image parameters */ if (texImage) clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); } else { /* no error, set the tex image parameters */ - struct gl_texture_unit *texUnit; - struct gl_texture_image *texImage; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texImage = _mesa_select_tex_image(ctx, texUnit, target, level); _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, postConvHeight, 1, border, internalFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); } } else { @@ -1996,29 +1987,20 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, } else if (target == GL_PROXY_TEXTURE_3D) { /* Proxy texture: check for errors and update proxy state */ - GLboolean error = texture_error_check(ctx, target, level, internalFormat, - format, type, 3, width, height, depth, border); - if (!error) { - ASSERT(ctx->Driver.TestProxyTexImage); - error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, - internalFormat, format, type, - width, height, depth, border); - } - if (error) { - /* if error, clear all proxy texture image parameters */ - struct gl_texture_image *texImage; - texImage = _mesa_get_proxy_tex_image(ctx, target, level); + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 3, width, height, depth, border)) { + /* when error, clear all proxy texture image parameters */ if (texImage) clear_teximage_fields(texImage); } else { /* no error, set the tex image parameters */ - struct gl_texture_unit *texUnit; - struct gl_texture_image *texImage; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texImage = _mesa_select_tex_image(ctx, texUnit, target, level); _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, border, internalFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); } } else { diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index 7ab6810209..ed0008e37f 100644 --- a/src/mesa/main/teximage.h +++ b/src/mesa/main/teximage.h @@ -1,10 +1,8 @@ -/* $Id: teximage.h,v 1.23 2003/04/01 16:41:54 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 5.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -83,6 +81,11 @@ extern GLint _mesa_max_texture_levels(GLcontext *ctx, GLenum target); +extern GLboolean +_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border); + /*** API entry point functions ***/ diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 08e625bc0d..f9afbb6b87 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -1,5 +1,3 @@ -/* $Id: texstore.c,v 1.55 2003/04/01 16:41:55 brianp Exp $ */ - /* * Mesa 3-D graphics library * Version: 5.1 @@ -1264,40 +1262,6 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, } - - - -/* - * This is the fallback for Driver.TestProxyTexImage(). - */ -GLboolean -_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, GLenum format, GLenum type, - GLint width, GLint height, GLint depth, GLint border) -{ - struct gl_texture_image *texImage; - - (void) format; - (void) type; - - texImage = _mesa_get_proxy_tex_image(ctx, target, level); - - /* We always pass. - * The core Mesa code will have already tested the image size, etc. - * If a driver has more stringent texture limits to enforce it will - * have to override this function. - */ - /* choose the texture format */ - assert(ctx->Driver.ChooseTextureFormat); - texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, - internalFormat, format, type); - assert(texImage->TexFormat); - - return GL_TRUE; -} - - - /* * Average together two rows of a source image to produce a single new * row in the dest image. It's legal for the two source rows to point diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h index 8d1e149102..6d3a4397b2 100644 --- a/src/mesa/main/texstore.h +++ b/src/mesa/main/texstore.h @@ -1,10 +1,8 @@ -/* $Id: texstore.h,v 1.11 2002/09/27 02:45:38 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 4.1 + * Version: 5.1 * - * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -165,12 +163,6 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, struct gl_texture_image *texImage); -extern GLboolean -_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, GLenum format, GLenum type, - GLint width, GLint height, GLint depth, GLint border); - - extern void _mesa_generate_mipmap(GLcontext *ctx, GLenum target, const struct gl_texture_unit *texUnit, -- cgit v1.2.3