diff options
Diffstat (limited to 'src/mesa/main/teximage.c')
-rw-r--r-- | src/mesa/main/teximage.c | 2101 |
1 files changed, 857 insertions, 1244 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index b65a2de046e..1e8626c7346 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -40,6 +40,7 @@ #include "image.h" #include "imports.h" #include "macros.h" +#include "mfeatures.h" #include "state.h" #include "texcompress.h" #include "texfetch.h" @@ -340,11 +341,11 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) return GL_RGBA; case GL_SLUMINANCE_ALPHA_EXT: case GL_SLUMINANCE8_ALPHA8_EXT: - case GL_COMPRESSED_SLUMINANCE_EXT: case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: return GL_LUMINANCE_ALPHA; case GL_SLUMINANCE_EXT: case GL_SLUMINANCE8_EXT: + case GL_COMPRESSED_SLUMINANCE_EXT: return GL_LUMINANCE; default: ; /* fallthrough */ @@ -596,7 +597,8 @@ _mesa_free_texture_image_data(struct gl_context *ctx, * Free the texture image structure and the associated image data. */ void -_mesa_delete_texture_image( struct gl_context *ctx, struct gl_texture_image *texImage ) +_mesa_delete_texture_image(struct gl_context *ctx, + struct gl_texture_image *texImage) { /* Free texImage->Data and/or any other driver-specific texture * image storage. @@ -635,7 +637,49 @@ _mesa_is_proxy_texture(GLenum target) /** - * Get the texture object that corresponds to the target of the given texture unit. + * Return the proxy target which corresponds to the given texture target + */ +static GLenum +get_proxy_target(GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + return GL_PROXY_TEXTURE_1D; + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + return GL_PROXY_TEXTURE_2D; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + return GL_PROXY_TEXTURE_3D; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + return GL_PROXY_TEXTURE_CUBE_MAP_ARB; + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + return GL_PROXY_TEXTURE_RECTANGLE_NV; + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_PROXY_TEXTURE_1D_ARRAY_EXT: + return GL_PROXY_TEXTURE_1D_ARRAY_EXT; + case GL_TEXTURE_2D_ARRAY_EXT: + case GL_PROXY_TEXTURE_2D_ARRAY_EXT: + return GL_PROXY_TEXTURE_2D_ARRAY_EXT; + default: + _mesa_problem(NULL, "unexpected target in get_proxy_target()"); + return 0; + } +} + + +/** + * Get the texture object that corresponds to the target of the given + * texture unit. * * \param ctx GL context. * \param texUnit texture unit. @@ -646,7 +690,8 @@ _mesa_is_proxy_texture(GLenum target) * \sa gl_texture_unit. */ struct gl_texture_object * -_mesa_select_tex_object(struct gl_context *ctx, const struct gl_texture_unit *texUnit, +_mesa_select_tex_object(struct gl_context *ctx, + const struct gl_texture_unit *texUnit, GLenum target) { switch (target) { @@ -723,7 +768,8 @@ _mesa_get_current_tex_object(struct gl_context *ctx, GLenum target) * \return pointer to the texture image structure, or NULL on failure. */ struct gl_texture_image * -_mesa_select_tex_image(struct gl_context *ctx, const struct gl_texture_object *texObj, +_mesa_select_tex_image(struct gl_context *ctx, + const struct gl_texture_object *texObj, GLenum target, GLint level) { const GLuint face = _mesa_tex_target_to_face(target); @@ -883,6 +929,45 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) } +/** + * Return number of dimensions per mipmap level for the given texture target. + */ +static GLint +get_texture_dimensions(GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + return 1; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_CUBE_MAP: + case GL_PROXY_TEXTURE_2D: + case GL_PROXY_TEXTURE_RECTANGLE: + case GL_PROXY_TEXTURE_CUBE_MAP: + 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: + case GL_TEXTURE_1D_ARRAY: + case GL_PROXY_TEXTURE_1D_ARRAY: + return 2; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + case GL_PROXY_TEXTURE_2D_ARRAY: + return 3; + default: + _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()", + target); + return 2; + } +} + + + #if 000 /* not used anymore */ /* @@ -988,6 +1073,7 @@ clear_teximage_fields(struct gl_texture_image *img) * \param depth image depth. * \param border image border. * \param internalFormat internal format. + * \param format the actual hardware format (one of MESA_FORMAT_*) * * Fills in the fields of \p img with the given information. * Note: width, height and depth include the border. @@ -996,9 +1082,10 @@ void _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, struct gl_texture_image *img, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum internalFormat) + GLint border, GLenum internalFormat, + gl_format format) { - GLint i; + GLint i, dims; ASSERT(img); ASSERT(width >= 0); @@ -1069,8 +1156,11 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, img->DepthScale = (GLfloat) img->Depth; } - img->FetchTexelc = NULL; - img->FetchTexelf = NULL; + img->TexFormat = format; + + dims = get_texture_dimensions(target); + + _mesa_set_fetch_functions(img, dims); } @@ -1084,7 +1174,8 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, * fields are cleared so that its parent object will test incomplete. */ void -_mesa_clear_texture_image(struct gl_context *ctx, struct gl_texture_image *texImage) +_mesa_clear_texture_image(struct gl_context *ctx, + struct gl_texture_image *texImage) { ctx->Driver.FreeTexImageData(ctx, texImage); clear_teximage_fields(texImage); @@ -1129,94 +1220,110 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, switch (target) { case GL_PROXY_TEXTURE_1D: maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); - if (width < 2 * border || width > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - width >0 && !_mesa_is_pow_two(width - 2 * border)) || - level >= ctx->Const.MaxTextureLevels) { - /* bad width or level */ + if (width < 2 * border || width > 2 + maxSize) return GL_FALSE; + if (level >= ctx->Const.MaxTextureLevels) + return GL_FALSE; + if (!ctx->Extensions.ARB_texture_non_power_of_two) { + if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) + return GL_FALSE; } return GL_TRUE; + case GL_PROXY_TEXTURE_2D: maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); - if (width < 2 * border || width > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - width > 0 && !_mesa_is_pow_two(width - 2 * border)) || - height < 2 * border || height > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - height > 0 && !_mesa_is_pow_two(height - 2 * border)) || - level >= ctx->Const.MaxTextureLevels) { - /* bad width or height or level */ + if (width < 2 * border || width > 2 + maxSize) return GL_FALSE; + if (height < 2 * border || height > 2 + maxSize) + return GL_FALSE; + if (level >= ctx->Const.MaxTextureLevels) + return GL_FALSE; + if (!ctx->Extensions.ARB_texture_non_power_of_two) { + if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) + return GL_FALSE; + if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) + return GL_FALSE; } return GL_TRUE; + case GL_PROXY_TEXTURE_3D: maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); - if (width < 2 * border || width > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - width > 0 && !_mesa_is_pow_two(width - 2 * border)) || - height < 2 * border || height > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - height > 0 && !_mesa_is_pow_two(height - 2 * border)) || - depth < 2 * border || depth > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) || - level >= ctx->Const.Max3DTextureLevels) { - /* bad width or height or depth or level */ + if (width < 2 * border || width > 2 + maxSize) + return GL_FALSE; + if (height < 2 * border || height > 2 + maxSize) + return GL_FALSE; + if (depth < 2 * border || depth > 2 + maxSize) + return GL_FALSE; + if (level >= ctx->Const.Max3DTextureLevels) return GL_FALSE; + if (!ctx->Extensions.ARB_texture_non_power_of_two) { + if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) + return GL_FALSE; + if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) + return GL_FALSE; + if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) + return GL_FALSE; } return GL_TRUE; + case GL_PROXY_TEXTURE_RECTANGLE_NV: - if (width < 0 || width > ctx->Const.MaxTextureRectSize || - height < 0 || height > ctx->Const.MaxTextureRectSize || - level != 0) { - /* bad width or height or level */ + maxSize = ctx->Const.MaxTextureRectSize; + if (width < 0 || width > maxSize) + return GL_FALSE; + if (height < 0 || height > maxSize) + return GL_FALSE; + if (level != 0) 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 || - (!ctx->Extensions.ARB_texture_non_power_of_two && - width > 0 && !_mesa_is_pow_two(width - 2 * border)) || - height < 2 * border || height > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - height > 0 && !_mesa_is_pow_two(height - 2 * border)) || - level >= ctx->Const.MaxCubeTextureLevels) { - /* bad width or height */ + if (width < 2 * border || width > 2 + maxSize) + return GL_FALSE; + if (height < 2 * border || height > 2 + maxSize) + return GL_FALSE; + if (level >= ctx->Const.MaxCubeTextureLevels) return GL_FALSE; + if (!ctx->Extensions.ARB_texture_non_power_of_two) { + if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) + return GL_FALSE; + if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) + return GL_FALSE; } return GL_TRUE; + case GL_PROXY_TEXTURE_1D_ARRAY_EXT: maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); - if (width < 2 * border || width > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - width > 0 && !_mesa_is_pow_two(width - 2 * border)) || - level >= ctx->Const.MaxTextureLevels) { - /* bad width or level */ + if (width < 2 * border || width > 2 + maxSize) return GL_FALSE; - } - - if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) { + if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) + return GL_FALSE; + if (level >= ctx->Const.MaxTextureLevels) return GL_FALSE; + if (!ctx->Extensions.ARB_texture_non_power_of_two) { + if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) + return GL_FALSE; } return GL_TRUE; + case GL_PROXY_TEXTURE_2D_ARRAY_EXT: maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); - if (width < 2 * border || width > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - width > 0 && !_mesa_is_pow_two(width - 2 * border)) || - height < 2 * border || height > 2 + maxSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && - height > 0 && !_mesa_is_pow_two(height - 2 * border)) || - level >= ctx->Const.MaxTextureLevels) { - /* bad width or height or level */ + if (width < 2 * border || width > 2 + maxSize) return GL_FALSE; - } - if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) { + if (height < 2 * border || height > 2 + maxSize) + return GL_FALSE; + if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) return GL_FALSE; + if (level >= ctx->Const.MaxTextureLevels) + return GL_FALSE; + if (!ctx->Extensions.ARB_texture_non_power_of_two) { + if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) + return GL_FALSE; + if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) + return GL_FALSE; } return GL_TRUE; + default: _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); return GL_FALSE; @@ -1225,15 +1332,37 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, /** - * Helper function to determine whether a target supports compressed textures + * Check if the memory used by the texture would exceed the driver's limit. + * This lets us support a max 3D texture size of 8K (for example) but + * prevents allocating a full 8K x 8K x 8K texture. + * XXX this could be rolled into the proxy texture size test (above) but + * we don't have the actual texture internal format at that point. */ static GLboolean -target_can_be_compressed(struct gl_context *ctx, GLenum target) +legal_texture_size(struct gl_context *ctx, gl_format format, + GLint width, GLint height, GLint depth) { + uint64_t bytes = _mesa_format_image_size64(format, width, height, depth); + uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */ + return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes; +} + + + +/** + * Helper function to determine whether a target and specific compression + * format are supported. + */ +static GLboolean +target_can_be_compressed(const struct gl_context *ctx, GLenum target, + GLenum intFormat) +{ + (void) intFormat; /* not used yet */ + switch (target) { case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: - return GL_TRUE; + return GL_TRUE; /* true for any compressed format so far */ case GL_PROXY_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: @@ -1252,15 +1381,118 @@ target_can_be_compressed(struct gl_context *ctx, GLenum target) /** + * Check if the given texture target value is legal for a + * glTexImage1/2/3D call. + */ +static GLboolean +legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) +{ + switch (dims) { + case 1: + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + return GL_TRUE; + default: + return GL_FALSE; + } + case 2: + switch (target) { + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + return GL_TRUE; + case GL_PROXY_TEXTURE_CUBE_MAP: + 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: + return ctx->Extensions.ARB_texture_cube_map; + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + return ctx->Extensions.NV_texture_rectangle; + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_PROXY_TEXTURE_1D_ARRAY_EXT: + return ctx->Extensions.MESA_texture_array; + default: + return GL_FALSE; + } + case 3: + switch (target) { + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + return GL_TRUE; + case GL_TEXTURE_2D_ARRAY_EXT: + case GL_PROXY_TEXTURE_2D_ARRAY_EXT: + return ctx->Extensions.MESA_texture_array; + default: + return GL_FALSE; + } + default: + _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims); + return GL_FALSE; + } +} + + +/** + * Check if the given texture target value is legal for a + * glTexSubImage, glCopyTexSubImage or glCopyTexImage call. + * The difference compared to legal_teximage_target() above is that + * proxy targets are not supported. + */ +static GLboolean +legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) +{ + switch (dims) { + case 1: + return target == GL_TEXTURE_1D; + case 2: + switch (target) { + case GL_TEXTURE_2D: + return GL_TRUE; + 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: + return ctx->Extensions.ARB_texture_cube_map; + case GL_TEXTURE_RECTANGLE_NV: + return ctx->Extensions.NV_texture_rectangle; + case GL_TEXTURE_1D_ARRAY_EXT: + return ctx->Extensions.MESA_texture_array; + default: + return GL_FALSE; + } + case 3: + switch (target) { + case GL_TEXTURE_3D: + return GL_TRUE; + case GL_TEXTURE_2D_ARRAY_EXT: + return ctx->Extensions.MESA_texture_array; + default: + return GL_FALSE; + } + default: + _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()", + dims); + return GL_FALSE; + } +} + + +/** * Test the glTexImage[123]D() parameters for errors. * * \param ctx GL context. + * \param dimensions texture image dimensions (must be 1, 2 or 3). * \param target texture target given by the user. * \param level image level given by the user. * \param internalFormat internal format given by the user. * \param format pixel data format given by the user. * \param type pixel data type given by the user. - * \param dimensions texture image dimensions (must be 1, 2 or 3). * \param width image width given by the user. * \param height image height given by the user. * \param depth image depth given by the user. @@ -1269,21 +1501,21 @@ target_can_be_compressed(struct gl_context *ctx, GLenum target) * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. * * Verifies each of the parameters against the constants specified in - * __struct gl_contextRec::Const and the supported extensions, and according to the - * OpenGL specification. + * __struct gl_contextRec::Const and the supported extensions, and according + * to the OpenGL specification. */ static GLboolean -texture_error_check( struct gl_context *ctx, GLenum target, +texture_error_check( struct gl_context *ctx, + GLuint dimensions, GLenum target, GLint level, GLint internalFormat, GLenum format, GLenum type, - GLuint dimensions, GLint width, GLint height, GLint depth, GLint border ) { - const GLboolean isProxy = _mesa_is_proxy_texture(target); + const GLenum proxyTarget = get_proxy_target(target); + const GLboolean isProxy = target == proxyTarget; GLboolean sizeOK = GL_TRUE; GLboolean colorFormat, indexFormat; - GLenum proxy_target; /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ if (level < 0 || level >= MAX_TEXTURE_LEVELS) { @@ -1313,71 +1545,16 @@ texture_error_check( struct gl_context *ctx, GLenum target, 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) { - proxy_target = GL_PROXY_TEXTURE_1D; - height = 1; - depth = 1; - } - else { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); - return GL_TRUE; - } - } - else if (dimensions == 2) { - depth = 1; - if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { - proxy_target = GL_PROXY_TEXTURE_2D; - } - 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; - } - proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; - sizeOK = (width == height); - } - 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; - } - proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; - } - else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || - target == GL_TEXTURE_1D_ARRAY_EXT) { - proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); - return GL_TRUE; - } - } - else if (dimensions == 3) { - if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { - proxy_target = GL_PROXY_TEXTURE_3D; - } - else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT || - target == GL_TEXTURE_2D_ARRAY_EXT) { - proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; - } - else { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); - return GL_TRUE; - } - } - else { - _mesa_problem( ctx, "bad dims in texture_error_check" ); - return GL_TRUE; + /* Do this simple check before calling the TestProxyTexImage() function */ + if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { + sizeOK = (width == height); } - sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, + /* + * Use the proxy texture driver hook to see if the size/level/etc are + * legal. + */ + sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, internalFormat, format, type, width, height, depth, border); @@ -1482,9 +1659,10 @@ texture_error_check( struct gl_context *ctx, GLenum target, /* additional checks for compressed textures */ if (_mesa_is_compressed_format(ctx, internalFormat)) { - if (!target_can_be_compressed(ctx, target) && !isProxy) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexImage%dD(target)", dimensions); + if (!target_can_be_compressed(ctx, target, internalFormat)) { + if (!isProxy) + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexImage%dD(target)", dimensions); return GL_TRUE; } if (border != 0) { @@ -1532,8 +1710,8 @@ texture_error_check( struct gl_context *ctx, GLenum target, * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. * * Verifies each of the parameters against the constants specified in - * __struct gl_contextRec::Const and the supported extensions, and according to the - * OpenGL specification. + * __struct gl_contextRec::Const and the supported extensions, and according + * to the OpenGL specification. */ static GLboolean subtexture_error_check( struct gl_context *ctx, GLuint dimensions, @@ -1542,61 +1720,13 @@ subtexture_error_check( struct gl_context *ctx, GLuint dimensions, GLint width, GLint height, GLint depth, GLenum format, GLenum type ) { - /* Check target */ - if (dimensions == 1) { - if (target != GL_TEXTURE_1D) { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); - return GL_TRUE; - } - } - else if (dimensions == 2) { - 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, "glTexSubImage2D(target)" ); - return GL_TRUE; - } - } - else if (target == GL_TEXTURE_RECTANGLE_NV) { - if (!ctx->Extensions.NV_texture_rectangle) { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); - return GL_TRUE; - } - } - else if (target == GL_TEXTURE_1D_ARRAY_EXT) { - if (!ctx->Extensions.MESA_texture_array) { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); - return GL_TRUE; - } - } - 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_2D_ARRAY_EXT) { - if (!ctx->Extensions.MESA_texture_array) { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); - return GL_TRUE; - } - } - else if (target != GL_TEXTURE_3D) { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); - return GL_TRUE; - } - } - else { - _mesa_problem( ctx, "invalid dims in texture_error_check" ); - return GL_TRUE; - } - /* Basic level check */ if (level < 0 || level >= MAX_TEXTURE_LEVELS) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); return GL_TRUE; } + /* Check for negative sizes */ if (width < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(width=%d)", dimensions, width); @@ -1683,13 +1813,6 @@ subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, if (_mesa_is_format_compressed(destTex->TexFormat)) { GLuint bw, bh; - if (!target_can_be_compressed(ctx, target)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexSubImage%dD(target=%s)", dimensions, - _mesa_lookup_enum_by_nr(target)); - return GL_TRUE; - } - /* do tests which depend on compression block size */ _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); @@ -1732,18 +1855,26 @@ subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. * * Verifies each of the parameters against the constants specified in - * __struct gl_contextRec::Const and the supported extensions, and according to the - * OpenGL specification. + * __struct gl_contextRec::Const and the supported extensions, and according + * to the OpenGL specification. */ static GLboolean copytexture_error_check( struct gl_context *ctx, GLuint dimensions, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border ) { - GLenum type; + const GLenum proxyTarget = get_proxy_target(target); + const GLenum type = GL_FLOAT; GLboolean sizeOK; GLint format; + /* check target */ + if (!legal_texsubimage_target(ctx, dimensions, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)", + dimensions, _mesa_lookup_enum_by_nr(target)); + return GL_TRUE; + } + /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ if (level < 0 || level >= MAX_TEXTURE_LEVELS) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1781,75 +1912,14 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - /* NOTE: the format and type aren't really significant for - * TestProxyTexImage(). Only the internalformat really matters. - */ - type = GL_FLOAT; + /* Do size, level checking */ + sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) + ? (width == height) : 1; - /* Check target and call ctx->Driver.TestProxyTexImage() to check the - * level, width, height and depth. - */ - if (dimensions == 1) { - 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; - } - } - else if (dimensions == 2) { - 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_1D_ARRAY_EXT) { - if (!ctx->Extensions.MESA_texture_array) { - _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)"); - return GL_TRUE; - } - sizeOK = ctx->Driver.TestProxyTexImage(ctx, - GL_PROXY_TEXTURE_1D_ARRAY_EXT, - level, internalFormat, - format, type, - width, height, 1, border); - } - else { - _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); - return GL_TRUE; - } - } - else { - _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); - return GL_TRUE; - } + sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, + internalFormat, format, + type, width, height, + 1, border); if (!sizeOK) { if (dimensions == 1) { @@ -1865,7 +1935,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_compressed_format(ctx, internalFormat)) { - if (!target_can_be_compressed(ctx, target)) { + if (!target_can_be_compressed(ctx, target, internalFormat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%dD(target)", dimensions); return GL_TRUE; @@ -1924,45 +1994,11 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, } } - /* Check target */ - if (dimensions == 1) { - if (target != GL_TEXTURE_1D) { - _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); - return GL_TRUE; - } - } - else if (dimensions == 2) { - 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, "glCopyTexSubImage2D(target)" ); - return GL_TRUE; - } - } - else if (target == GL_TEXTURE_RECTANGLE_NV) { - if (!ctx->Extensions.NV_texture_rectangle) { - _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); - return GL_TRUE; - } - } - else if (target == GL_TEXTURE_1D_ARRAY_EXT) { - if (!ctx->Extensions.MESA_texture_array) { - _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); - return GL_TRUE; - } - } - else if (target != GL_TEXTURE_2D) { - _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); - return GL_TRUE; - } - } - else if (dimensions == 3) { - if (((target != GL_TEXTURE_2D_ARRAY_EXT) || - (!ctx->Extensions.MESA_texture_array)) - && (target != GL_TEXTURE_3D)) { - _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); - return GL_TRUE; - } + /* check target (proxies not allowed) */ + if (!legal_texsubimage_target(ctx, dimensions, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%uD(target=%s)", + dimensions, _mesa_lookup_enum_by_nr(target)); + return GL_TRUE; } /* Check level */ @@ -2051,11 +2087,6 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(teximage->TexFormat)) { - if (!target_can_be_compressed(ctx, target)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTexSubImage%dD(target)", dimensions); - return GL_TRUE; - } /* offset must be multiple of 4 */ if ((xoffset & 3) || (yoffset & 3)) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -2107,9 +2138,9 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, /* If copying into an integer texture, the source buffer must also be * integer-valued. */ - if (_mesa_is_format_integer(teximage->TexFormat)) { + if (_mesa_is_format_integer_color(teximage->TexFormat)) { struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; - if (!_mesa_is_format_integer(rb->Format)) { + if (!_mesa_is_format_integer_color(rb->Format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage%dD(source buffer is not integer format)", dimensions); @@ -2257,13 +2288,14 @@ override_internal_format(GLenum internalFormat, GLint width, GLint height) * for efficient texture memory layout/allocation. In particular, this * comes up during automatic mipmap generation. */ -void +gl_format _mesa_choose_texture_format(struct gl_context *ctx, struct gl_texture_object *texObj, - struct gl_texture_image *texImage, GLenum target, GLint level, GLenum internalFormat, GLenum format, GLenum type) { + gl_format f; + /* see if we've already chosen a format for the previous level */ if (level > 0) { struct gl_texture_image *prevImage = @@ -2275,102 +2307,60 @@ _mesa_choose_texture_format(struct gl_context *ctx, prevImage->Width > 0 && prevImage->InternalFormat == internalFormat) { /* use the same format */ - texImage->TexFormat = prevImage->TexFormat; - return; + ASSERT(prevImage->TexFormat != MESA_FORMAT_NONE); + return prevImage->TexFormat; } } /* choose format from scratch */ - texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, - format, type); - ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); + f = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); + ASSERT(f != MESA_FORMAT_NONE); + return f; } - -/* - * Called from the API. Note that width includes the border. +/** + * Common code to implement all the glTexImage1D/2D/3D functions. */ -void GLAPIENTRY -_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLint border, GLenum format, - GLenum type, const GLvoid *pixels ) +static void +teximage(struct gl_context *ctx, GLuint dims, + GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels) { - GET_CURRENT_CONTEXT(ctx); + GLboolean error; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n", + _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n", + dims, _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), width, border, + _mesa_lookup_enum_by_nr(internalFormat), + width, height, depth, border, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type), pixels); - internalFormat = override_internal_format(internalFormat, width, 1); - - if (target == GL_TEXTURE_1D) { - /* non-proxy target */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - const GLuint face = _mesa_tex_target_to_face(target); - - if (texture_error_check(ctx, target, level, internalFormat, - format, type, 1, width, 1, 1, border)) { - return; /* error was recorded */ - } - - if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) - _mesa_update_state(ctx); - - texObj = _mesa_get_current_tex_object(ctx, target); - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_get_tex_image(ctx, texObj, target, level); - if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); - } - else { - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - - ASSERT(texImage->Data == NULL); - - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - width, 1, 1, - border, internalFormat); - - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, format, type); - - /* Give the texture to the driver. <pixels> may be null. */ - ASSERT(ctx->Driver.TexImage1D); - ctx->Driver.TexImage1D(ctx, target, level, internalFormat, - width, border, format, type, pixels, - &ctx->Unpack, texObj, texImage); - - ASSERT(texImage->TexFormat); + internalFormat = override_internal_format(internalFormat, width, height); - _mesa_set_fetch_functions(texImage, 1); + /* target error checking */ + if (!legal_teximage_target(ctx, dims, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)", + dims, _mesa_lookup_enum_by_nr(target)); + return; + } - check_gen_mipmap(ctx, target, texObj, level); + /* general error checking */ + error = texture_error_check(ctx, dims, target, level, internalFormat, + format, type, width, height, depth, border); - update_fbo_texture(ctx, texObj, face, level); + if (_mesa_is_proxy_texture(target)) { + /* Proxy texture: just clear or set state depending on error checking */ + struct gl_texture_image *texImage = + _mesa_get_proxy_tex_image(ctx, target, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - } - _mesa_unlock_texture(ctx, texObj); - } - else if (target == GL_PROXY_TEXTURE_1D) { - /* Proxy texture: check for errors and update proxy state */ - 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, width, 1, 1, border)) { + if (error) { /* when error, clear all proxy texture image parameters */ if (texImage) clear_teximage_fields(texImage); @@ -2379,54 +2369,28 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, /* no error, set the tex image parameters */ struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); - ASSERT(texImage); - _mesa_init_teximage_fields(ctx, target, texImage, - width, 1, 1, - border, internalFormat); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, format, type); + gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, + target, level, + internalFormat, + format, type); + + if (legal_texture_size(ctx, texFormat, width, height, depth)) { + _mesa_init_teximage_fields(ctx, target, texImage, width, height, + depth, border, internalFormat, + texFormat); + } + else if (texImage) { + clear_teximage_fields(texImage); + } } } else { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); - return; - } -} - - -void GLAPIENTRY -_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, - const GLvoid *pixels ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n", - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), width, height, - border, _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); - - internalFormat = override_internal_format(internalFormat, width, height); - - if (target == GL_TEXTURE_2D || - (ctx->Extensions.ARB_texture_cube_map && - target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || - (ctx->Extensions.NV_texture_rectangle && - target == GL_TEXTURE_RECTANGLE_NV) || - (ctx->Extensions.MESA_texture_array && - target == GL_TEXTURE_1D_ARRAY_EXT)) { /* non-proxy target */ + const GLuint face = _mesa_tex_target_to_face(target); struct gl_texture_object *texObj; struct gl_texture_image *texImage; - const GLuint face = _mesa_tex_target_to_face(target); - if (texture_error_check(ctx, target, level, internalFormat, - format, type, 2, width, height, 1, border)) { + if (error) { return; /* error was recorded */ } @@ -2434,78 +2398,97 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, _mesa_update_state(ctx); texObj = _mesa_get_current_tex_object(ctx, target); + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); + if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); } else { + gl_format texFormat; + if (texImage->Data) { ctx->Driver.FreeTexImageData( ctx, texImage ); } ASSERT(texImage->Data == NULL); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - width, height, 1, - border, internalFormat); - - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, format, type); - - /* Give the texture to the driver. <pixels> may be null. */ - ASSERT(ctx->Driver.TexImage2D); - ctx->Driver.TexImage2D(ctx, target, level, internalFormat, - width, height, border, format, type, - pixels, &ctx->Unpack, texObj, texImage); - - ASSERT(texImage->TexFormat); - - _mesa_set_fetch_functions(texImage, 2); + texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, + internalFormat, format, + type); + + if (legal_texture_size(ctx, texFormat, width, height, depth)) { + _mesa_init_teximage_fields(ctx, target, texImage, + width, height, depth, + border, internalFormat, texFormat); + + /* Give the texture to the driver. <pixels> may be null. */ + ASSERT(ctx->Driver.TexImage3D); + switch (dims) { + case 1: + ctx->Driver.TexImage1D(ctx, target, level, internalFormat, + width, border, format, + type, pixels, &ctx->Unpack, texObj, + texImage); + break; + case 2: + ctx->Driver.TexImage2D(ctx, target, level, internalFormat, + width, height, border, format, + type, pixels, &ctx->Unpack, texObj, + texImage); + break; + case 3: + ctx->Driver.TexImage3D(ctx, target, level, internalFormat, + width, height, depth, border, format, + type, pixels, &ctx->Unpack, texObj, + texImage); + break; + default: + _mesa_problem(ctx, "invalid dims=%u in teximage()", dims); + } - check_gen_mipmap(ctx, target, texObj, level); + check_gen_mipmap(ctx, target, texObj, level); - update_fbo_texture(ctx, texObj, face, level); + update_fbo_texture(ctx, texObj, face, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); + } } } _mesa_unlock_texture(ctx, texObj); } - else if (target == GL_PROXY_TEXTURE_2D || - (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && - ctx->Extensions.ARB_texture_cube_map) || - (target == GL_PROXY_TEXTURE_RECTANGLE_NV && - ctx->Extensions.NV_texture_rectangle) || - (ctx->Extensions.MESA_texture_array && - target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { - /* Proxy texture: check for errors and update proxy state */ - 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, width, height, 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_object *texObj = - _mesa_get_current_tex_object(ctx, target); - _mesa_init_teximage_fields(ctx, target, texImage, - width, height, 1, - border, internalFormat); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, format, type); - } - } - else { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); - return; - } +} + + +/* + * Called from the API. Note that width includes the border. + */ +void GLAPIENTRY +_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLint border, GLenum format, + GLenum type, const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + teximage(ctx, 1, target, level, internalFormat, width, 1, 1, + border, format, type, pixels); +} + + +void GLAPIENTRY +_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + teximage(ctx, 2, target, level, internalFormat, width, height, 1, + border, format, type, pixels); } @@ -2520,101 +2503,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, const GLvoid *pixels ) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n", - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), width, height, - depth, border, _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); - - internalFormat = override_internal_format(internalFormat, width, height); - - if (target == GL_TEXTURE_3D || - (ctx->Extensions.MESA_texture_array && - target == GL_TEXTURE_2D_ARRAY_EXT)) { - /* non-proxy target */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - const GLuint face = _mesa_tex_target_to_face(target); - - if (texture_error_check(ctx, target, level, (GLint) internalFormat, - format, type, 3, width, height, depth, border)) { - return; /* error was recorded */ - } - - if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) - _mesa_update_state(ctx); - - texObj = _mesa_get_current_tex_object(ctx, target); - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_get_tex_image(ctx, texObj, target, level); - if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); - } - else { - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - - ASSERT(texImage->Data == NULL); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - width, height, depth, - border, internalFormat); - - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, format, type); - - /* Give the texture to the driver. <pixels> may be null. */ - ASSERT(ctx->Driver.TexImage3D); - ctx->Driver.TexImage3D(ctx, target, level, internalFormat, - width, height, depth, border, format, type, - pixels, &ctx->Unpack, texObj, texImage); - - ASSERT(texImage->TexFormat); - - _mesa_set_fetch_functions(texImage, 3); - - check_gen_mipmap(ctx, target, texObj, level); - - update_fbo_texture(ctx, texObj, face, level); - - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - } - _mesa_unlock_texture(ctx, texObj); - } - else if (target == GL_PROXY_TEXTURE_3D || - (ctx->Extensions.MESA_texture_array && - target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { - /* Proxy texture: check for errors and update proxy state */ - 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_object *texObj = - _mesa_get_current_tex_object(ctx, target); - _mesa_init_teximage_fields(ctx, target, texImage, width, height, - depth, border, internalFormat); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, format, type); - } - } - else { - _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); - return; - } + teximage(ctx, 3, target, level, internalFormat, width, height, depth, + border, format, type, pixels); } @@ -2677,51 +2567,92 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) #endif -void GLAPIENTRY -_mesa_TexSubImage1D( GLenum target, GLint level, - GLint xoffset, GLsizei width, - GLenum format, GLenum type, - const GLvoid *pixels ) + +/** + * Implement all the glTexSubImage1/2/3D() functions. + */ +static void +texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n", + _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n", + dims, _mesa_lookup_enum_by_nr(target), level, - xoffset, width, _mesa_lookup_enum_by_nr(format), + xoffset, yoffset, zoffset, width, height, depth, + _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type), pixels); + /* check target (proxies not allowed) */ + if (!legal_texsubimage_target(ctx, dims, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", + dims, _mesa_lookup_enum_by_nr(target)); + return; + } + if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, - width, 1, 1, format, type)) { + if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, type)) { return; /* error was detected */ } - texObj = _mesa_get_current_tex_object(ctx, target); - assert(texObj); _mesa_lock_texture(ctx, texObj); { texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, - width, 1, 1, format, type, texImage)) { + if (subtexture_error_check2(ctx, dims, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, texImage)) { /* error was recorded */ } - else if (width > 0) { - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; + else if (width > 0 && height > 0 && height > 0) { + /* If we have a border, offset=-1 is legal. Bias by border width. */ + switch (dims) { + case 3: + zoffset += texImage->Border; + /* fall-through */ + case 2: + yoffset += texImage->Border; + /* fall-through */ + case 1: + xoffset += texImage->Border; + } - ASSERT(ctx->Driver.TexSubImage1D); - ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width, - format, type, pixels, &ctx->Unpack, - texObj, texImage); + switch (dims) { + case 1: + ctx->Driver.TexSubImage1D(ctx, target, level, + xoffset, width, + format, type, pixels, + &ctx->Unpack, texObj, texImage ); + break; + case 2: + ctx->Driver.TexSubImage2D(ctx, target, level, + xoffset, yoffset, width, height, + format, type, pixels, + &ctx->Unpack, texObj, texImage ); + break; + case 3: + ctx->Driver.TexSubImage3D(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, + &ctx->Unpack, texObj, texImage ); + break; + default: + _mesa_problem(ctx, "unexpected dims in subteximage()"); + } check_gen_mipmap(ctx, target, texObj, level); @@ -2733,58 +2664,31 @@ _mesa_TexSubImage1D( GLenum target, GLint level, void GLAPIENTRY +_mesa_TexSubImage1D( GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + texsubimage(ctx, 1, target, level, + xoffset, 0, 0, + width, 1, 1, + format, type, pixels); +} + + +void GLAPIENTRY _mesa_TexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n", - _mesa_lookup_enum_by_nr(target), level, - xoffset, yoffset, width, height, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); - - if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) - _mesa_update_state(ctx); - - if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, - width, height, 1, format, type)) { - return; /* error was detected */ - } - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - - if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, - width, height, 1, format, type, texImage)) { - /* error was recorded */ - } - else if (width > 0 && height >= 0) { - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - - ASSERT(ctx->Driver.TexSubImage2D); - ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset, - width, height, format, type, pixels, - &ctx->Unpack, texObj, texImage); - - check_gen_mipmap(ctx, target, texObj, level); - - ctx->NewState |= _NEW_TEXTURE; - } - } - _mesa_unlock_texture(ctx, texObj); + texsubimage(ctx, 2, target, level, + xoffset, yoffset, 0, + width, height, 1, + format, type, pixels); } @@ -2796,84 +2700,41 @@ _mesa_TexSubImage3D( GLenum target, GLint level, GLenum format, GLenum type, const GLvoid *pixels ) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n", - _mesa_lookup_enum_by_nr(target), level, - xoffset, yoffset, zoffset, width, height, depth, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), pixels); - - if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) - _mesa_update_state(ctx); - - if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type)) { - return; /* error was detected */ - } - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - - if (subtexture_error_check2(ctx, 3, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, texImage)) { - /* error was recorded */ - } - else if (width > 0 && height > 0 && height > 0) { - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - zoffset += texImage->Border; - - ASSERT(ctx->Driver.TexSubImage3D); - ctx->Driver.TexSubImage3D(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, - &ctx->Unpack, texObj, texImage ); - - check_gen_mipmap(ctx, target, texObj, level); - - ctx->NewState |= _NEW_TEXTURE; - } - } - _mesa_unlock_texture(ctx, texObj); + texsubimage(ctx, 3, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels); } -void GLAPIENTRY -_mesa_CopyTexImage1D( GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, - GLsizei width, GLint border ) +/** + * Implement the glCopyTexImage1/2D() functions. + */ +static void +copyteximage(struct gl_context *ctx, GLuint dims, + GLenum target, GLint level, GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint face = _mesa_tex_target_to_face(target); - GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n", + _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n", + dims, _mesa_lookup_enum_by_nr(target), level, _mesa_lookup_enum_by_nr(internalFormat), - x, y, width, border); + x, y, width, height, border); if (ctx->NewState & NEW_COPY_TEX_STATE) _mesa_update_state(ctx); - if (copytexture_error_check(ctx, 1, target, level, internalFormat, - width, 1, border)) + if (copytexture_error_check(ctx, dims, target, level, internalFormat, + width, height, border)) return; texObj = _mesa_get_current_tex_object(ctx, target); @@ -2881,38 +2742,46 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); + if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); } else { + gl_format texFormat; + if (texImage->Data) { ctx->Driver.FreeTexImageData( ctx, texImage ); } ASSERT(texImage->Data == NULL); - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, - border, internalFormat); + texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, + internalFormat, GL_NONE, + GL_NONE); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); - - ASSERT(ctx->Driver.CopyTexImage1D); - ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, - x, y, width, border); - - ASSERT(texImage->TexFormat); + if (legal_texture_size(ctx, texFormat, width, height, 1)) { + _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, + border, internalFormat, texFormat); - _mesa_set_fetch_functions(texImage, 1); + ASSERT(ctx->Driver.CopyTexImage2D); + if (dims == 1) + ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, + x, y, width, border); + else + ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, + x, y, width, height, border); - check_gen_mipmap(ctx, target, texObj, level); + check_gen_mipmap(ctx, target, texObj, level); - update_fbo_texture(ctx, texObj, face, level); + update_fbo_texture(ctx, texObj, face, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); + } } } _mesa_unlock_texture(ctx, texObj); @@ -2921,95 +2790,52 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, void GLAPIENTRY -_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border ) +_mesa_CopyTexImage1D( GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLint border ) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - const GLuint face = _mesa_tex_target_to_face(target); GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n", - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), - x, y, width, height, border); - - if (ctx->NewState & NEW_COPY_TEX_STATE) - _mesa_update_state(ctx); - - if (copytexture_error_check(ctx, 2, target, level, internalFormat, - width, height, border)) - return; - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_get_tex_image(ctx, texObj, target, level); - - if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); - } - else { - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - - ASSERT(texImage->Data == NULL); - - clear_teximage_fields(texImage); /* not really needed, but helpful */ - _mesa_init_teximage_fields(ctx, target, texImage, - width, height, 1, - border, internalFormat); - - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); - - ASSERT(ctx->Driver.CopyTexImage2D); - ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, - x, y, width, height, border); - - ASSERT(texImage->TexFormat); - - _mesa_set_fetch_functions(texImage, 2); + copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border); +} - check_gen_mipmap(ctx, target, texObj, level); - update_fbo_texture(ctx, texObj, face, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - } - _mesa_unlock_texture(ctx, texObj); +void GLAPIENTRY +_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border ) +{ + GET_CURRENT_CONTEXT(ctx); + copyteximage(ctx, 2, target, level, internalFormat, + x, y, width, height, border); } -void GLAPIENTRY -_mesa_CopyTexSubImage1D( GLenum target, GLint level, - GLint xoffset, GLint x, GLint y, GLsizei width ) + +/** + * Implementation for glCopyTexSubImage1/2/3D() functions. + */ +static void +copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLint yoffset = 0; - GLsizei height = 1; - GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n", + _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n", + dims, _mesa_lookup_enum_by_nr(target), - level, xoffset, x, y, width); + level, xoffset, yoffset, zoffset, x, y, width, height); if (ctx->NewState & NEW_COPY_TEX_STATE) _mesa_update_state(ctx); - if (copytexsubimage_error_check1(ctx, 1, target, level)) + if (copytexsubimage_error_check1(ctx, dims, target, level)) return; texObj = _mesa_get_current_tex_object(ctx, target); @@ -3018,19 +2844,43 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, { texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (copytexsubimage_error_check2(ctx, 1, target, level, - xoffset, 0, 0, width, 1, texImage)) { - /* error was recorded */ + if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset, + zoffset, width, height, texImage)) { + /* error was recored */ } else { - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; + /* If we have a border, offset=-1 is legal. Bias by border width. */ + switch (dims) { + case 3: + zoffset += texImage->Border; + /* fall-through */ + case 2: + yoffset += texImage->Border; + /* fall-through */ + case 1: + xoffset += texImage->Border; + } if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, &width, &height)) { - ASSERT(ctx->Driver.CopyTexSubImage1D); - ctx->Driver.CopyTexSubImage1D(ctx, target, level, - xoffset, x, y, width); + switch (dims) { + case 1: + ctx->Driver.CopyTexSubImage1D(ctx, target, level, + xoffset, x, y, width); + break; + case 2: + ctx->Driver.CopyTexSubImage2D(ctx, target, level, + xoffset, yoffset, + x, y, width, height); + break; + case 3: + ctx->Driver.CopyTexSubImage3D(ctx, target, level, + xoffset, yoffset, zoffset, + x, y, width, height); + break; + default: + _mesa_problem(ctx, "bad dims in copytexsubimage()"); + } check_gen_mipmap(ctx, target, texObj, level); @@ -3042,57 +2892,24 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, } +void GLAPIENTRY +_mesa_CopyTexSubImage1D( GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + GET_CURRENT_CONTEXT(ctx); + copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1); +} + + void GLAPIENTRY _mesa_CopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n", - _mesa_lookup_enum_by_nr(target), - level, xoffset, yoffset, x, y, width, height); - - if (ctx->NewState & NEW_COPY_TEX_STATE) - _mesa_update_state(ctx); - - if (copytexsubimage_error_check1(ctx, 2, target, level)) - return; - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - - if (copytexsubimage_error_check2(ctx, 2, target, level, - xoffset, yoffset, 0, - width, height, texImage)) { - /* error was recorded */ - } - else { - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - - if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, - &width, &height)) { - ASSERT(ctx->Driver.CopyTexSubImage2D); - ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, - x, y, width, height); - - check_gen_mipmap(ctx, target, texObj, level); - - ctx->NewState |= _NEW_TEXTURE; - } - } - } - _mesa_unlock_texture(ctx, texObj); + copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y, + width, height); } @@ -3102,52 +2919,9 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n", - _mesa_lookup_enum_by_nr(target), - level, xoffset, yoffset, zoffset, x, y, width, height); - - if (ctx->NewState & NEW_COPY_TEX_STATE) - _mesa_update_state(ctx); - - if (copytexsubimage_error_check1(ctx, 3, target, level)) - return; - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - - if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, - zoffset, width, height, texImage)) { - /* error was recored */ - } - else { - /* If we have a border, xoffset=-1 is legal. Bias by border width */ - xoffset += texImage->Border; - yoffset += texImage->Border; - zoffset += texImage->Border; - - if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, - &width, &height)) { - ASSERT(ctx->Driver.CopyTexSubImage3D); - ctx->Driver.CopyTexSubImage3D(ctx, target, level, - xoffset, yoffset, zoffset, - x, y, width, height); - - check_gen_mipmap(ctx, target, texObj, level); - - ctx->NewState |= _NEW_TEXTURE; - } - } - } - _mesa_unlock_texture(ctx, texObj); + copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, + x, y, width, height); } @@ -3192,45 +2966,18 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize) { - GLint expectedSize, maxLevels = 0, maxTextureSize; + const GLenum proxyTarget = get_proxy_target(target); + const GLint maxLevels = _mesa_max_texture_levels(ctx, target); + GLint expectedSize; - if (dimensions == 1) { - /* 1D compressed textures not allowed */ - return GL_INVALID_ENUM; - } - else if (dimensions == 2) { - if (target == GL_PROXY_TEXTURE_2D) { - maxLevels = ctx->Const.MaxTextureLevels; - } - else if (target == GL_TEXTURE_2D) { - maxLevels = ctx->Const.MaxTextureLevels; - } - else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { - if (!ctx->Extensions.ARB_texture_cube_map) - return GL_INVALID_ENUM; /*target*/ - maxLevels = ctx->Const.MaxCubeTextureLevels; - } - 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) - return GL_INVALID_ENUM; /*target*/ - maxLevels = ctx->Const.MaxCubeTextureLevels; - } - else { - return GL_INVALID_ENUM; /*target*/ - } - } - else if (dimensions == 3) { - /* 3D compressed textures not allowed */ - return GL_INVALID_ENUM; - } - else { - assert(0); + /* check level */ + if (level < 0 || level >= maxLevels) + return GL_INVALID_VALUE; + + if (!target_can_be_compressed(ctx, target, internalFormat)) { return GL_INVALID_ENUM; } - maxTextureSize = 1 << (maxLevels - 1); - /* This will detect any invalid internalFormat value */ if (!_mesa_is_compressed_format(ctx, internalFormat)) return GL_INVALID_ENUM; @@ -3239,47 +2986,51 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, if (_mesa_base_tex_format(ctx, internalFormat) < 0) return GL_INVALID_ENUM; + /* No compressed formats support borders at this time */ if (border != 0) return GL_INVALID_VALUE; - /* - * XXX We should probably use the proxy texture error check function here. - */ - if (width < 1 || width > maxTextureSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) - return GL_INVALID_VALUE; - - if ((height < 1 || height > maxTextureSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) - && dimensions > 1) - return GL_INVALID_VALUE; - - if ((depth < 1 || depth > maxTextureSize || - (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) - && dimensions > 2) - return GL_INVALID_VALUE; - /* For cube map, width must equal height */ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) return GL_INVALID_VALUE; - if (level < 0 || level >= maxLevels) - return GL_INVALID_VALUE; + /* check image size against compression block size */ + { + gl_format texFormat = + ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); + GLuint bw, bh; - expectedSize = compressed_tex_size(width, height, depth, internalFormat); - if (expectedSize != imageSize) - return GL_INVALID_VALUE; + _mesa_get_format_block_size(texFormat, &bw, &bh); + if ((width > bw && width % bw > 0) || + (height > bh && height % bh > 0)) { + /* + * Per GL_ARB_texture_compression: GL_INVALID_OPERATION is + * generated [...] if any parameter combinations are not + * supported by the specific compressed internal format. + */ + return GL_INVALID_OPERATION; + } + } -#if FEATURE_EXT_texture_sRGB - if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || - internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || - internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || - internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) - && border != 0) { + /* check image sizes */ + if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, + internalFormat, GL_NONE, GL_NONE, + width, height, depth, border)) { + /* See error comment above */ return GL_INVALID_OPERATION; } -#endif + + /* check image size in bytes */ + expectedSize = compressed_tex_size(width, height, depth, internalFormat); + if (expectedSize != imageSize) { + /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] + * if <imageSize> is not consistent with the format, dimensions, and + * contents of the specified image. + */ + return GL_INVALID_VALUE; + } return GL_NO_ERROR; } @@ -3421,156 +3172,101 @@ compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, } - -void GLAPIENTRY -_mesa_CompressedTexImage1DARB(GLenum target, GLint level, - GLenum internalFormat, GLsizei width, - GLint border, GLsizei imageSize, - const GLvoid *data) +/** + * Implementation of the glCompressedTexImage1/2/3D() functions. + */ +static void +compressedteximage(struct gl_context *ctx, GLuint dims, + GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid *data) { - GET_CURRENT_CONTEXT(ctx); + GLenum error; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n", + _mesa_debug(ctx, + "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n", + dims, _mesa_lookup_enum_by_nr(target), level, _mesa_lookup_enum_by_nr(internalFormat), - width, border, imageSize, data); - - if (target == GL_TEXTURE_1D) { - /* non-proxy target */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLenum error = compressed_texture_error_check(ctx, 1, target, level, - internalFormat, width, 1, 1, border, imageSize); - if (error) { - _mesa_error(ctx, error, "glCompressedTexImage1D"); - return; - } - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_get_tex_image(ctx, texObj, target, level); - if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); - } - else { - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - ASSERT(texImage->Data == NULL); - - _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, - border, internalFormat); - - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); + width, height, depth, border, imageSize, data); - ASSERT(ctx->Driver.CompressedTexImage1D); - ctx->Driver.CompressedTexImage1D(ctx, target, level, - internalFormat, width, border, - imageSize, data, - texObj, texImage); + /* check target */ + if (!legal_teximage_target(ctx, dims, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)", + dims, _mesa_lookup_enum_by_nr(target)); + return; + } - _mesa_set_fetch_functions(texImage, 1); + error = compressed_texture_error_check(ctx, dims, target, level, + internalFormat, width, height, depth, + border, imageSize); - check_gen_mipmap(ctx, target, texObj, level); +#if FEATURE_ES + /* XXX this is kind of a hack */ + if (error) { + _mesa_error(ctx, error, "glTexImage2D"); + return; + } - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } + if (dims == 2) { + switch (internalFormat) { + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + _mesa_cpal_compressed_teximage2d(target, level, internalFormat, + width, height, imageSize, data); + return; } - _mesa_unlock_texture(ctx, texObj); } - else if (target == GL_PROXY_TEXTURE_1D) { - /* Proxy texture: check for errors and update proxy state */ - GLenum error = compressed_texture_error_check(ctx, 1, target, level, - internalFormat, width, 1, 1, border, imageSize); +#endif + + if (_mesa_is_proxy_texture(target)) { + /* Proxy texture: just check for errors and update proxy state */ + struct gl_texture_image *texImage; + if (!error) { - ASSERT(ctx->Driver.TestProxyTexImage); - error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, - internalFormat, GL_NONE, GL_NONE, - width, 1, 1, border); + struct gl_texture_object *texObj = + _mesa_get_current_tex_object(ctx, target); + gl_format texFormat = + _mesa_choose_texture_format(ctx, texObj, target, level, + internalFormat, GL_NONE, GL_NONE); + if (!legal_texture_size(ctx, texFormat, width, height, depth)) { + error = GL_OUT_OF_MEMORY; + } } - if (error) { - /* if error, clear all proxy texture image parameters */ - struct gl_texture_image *texImage; - texImage = _mesa_get_proxy_tex_image(ctx, target, level); - if (texImage) + + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texImage) { + if (error) { + /* if error, clear all proxy texture image parameters */ clear_teximage_fields(texImage); - } - else { - /* store the teximage parameters */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, - border, internalFormat); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); - } - _mesa_unlock_texture(ctx, texObj); + } + else { + /* no error: store the teximage parameters */ + _mesa_init_teximage_fields(ctx, target, texImage, width, height, + depth, border, internalFormat, + MESA_FORMAT_NONE); + } } } else { - _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); - return; - } -} - -void GLAPIENTRY -_mesa_CompressedTexImage2DARB(GLenum target, GLint level, - GLenum internalFormat, GLsizei width, - GLsizei height, GLint border, GLsizei imageSize, - const GLvoid *data) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n", - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), - width, height, border, imageSize, data); - -#if FEATURE_ES - switch (internalFormat) { - case GL_PALETTE4_RGB8_OES: - case GL_PALETTE4_RGBA8_OES: - case GL_PALETTE4_R5_G6_B5_OES: - case GL_PALETTE4_RGBA4_OES: - case GL_PALETTE4_RGB5_A1_OES: - case GL_PALETTE8_RGB8_OES: - case GL_PALETTE8_RGBA8_OES: - case GL_PALETTE8_R5_G6_B5_OES: - case GL_PALETTE8_RGBA4_OES: - case GL_PALETTE8_RGB5_A1_OES: - _mesa_cpal_compressed_teximage2d(target, level, internalFormat, - width, height, imageSize, data); - return; - } -#endif - - if (target == GL_TEXTURE_2D || - (ctx->Extensions.ARB_texture_cube_map && - target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { /* non-proxy target */ struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLenum error = compressed_texture_error_check(ctx, 2, target, level, - internalFormat, width, height, 1, border, imageSize); if (error) { - _mesa_error(ctx, error, "glCompressedTexImage2D"); + _mesa_error(ctx, error, "glCompressedTexImage%uD", dims); return; } @@ -3580,186 +3276,105 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, { texImage = _mesa_get_tex_image(ctx, texObj, target, level); if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glCompressedTexImage%uD", dims); } else { + gl_format texFormat; + if (texImage->Data) { ctx->Driver.FreeTexImageData( ctx, texImage ); } ASSERT(texImage->Data == NULL); - _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, - border, internalFormat); - - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); - - ASSERT(ctx->Driver.CompressedTexImage2D); - ctx->Driver.CompressedTexImage2D(ctx, target, level, - internalFormat, width, height, - border, imageSize, data, - texObj, texImage); - - _mesa_set_fetch_functions(texImage, 2); + texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, + internalFormat, GL_NONE, + GL_NONE); + + if (legal_texture_size(ctx, texFormat, width, height, depth)) { + _mesa_init_teximage_fields(ctx, target, texImage, + width, height, depth, + border, internalFormat, texFormat); + + switch (dims) { + case 1: + ASSERT(ctx->Driver.CompressedTexImage1D); + ctx->Driver.CompressedTexImage1D(ctx, target, level, + internalFormat, + width, + border, imageSize, data, + texObj, texImage); + break; + case 2: + ASSERT(ctx->Driver.CompressedTexImage2D); + ctx->Driver.CompressedTexImage2D(ctx, target, level, + internalFormat, + width, height, + border, imageSize, data, + texObj, texImage); + break; + case 3: + ASSERT(ctx->Driver.CompressedTexImage3D); + ctx->Driver.CompressedTexImage3D(ctx, target, level, + internalFormat, + width, height, depth, + border, imageSize, data, + texObj, texImage); + break; + default: + _mesa_problem(ctx, "bad dims in compressedteximage"); + } - check_gen_mipmap(ctx, target, texObj, level); + check_gen_mipmap(ctx, target, texObj, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + /* state update */ + texObj->_Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glCompressedTexImage%uD", dims); + } } } _mesa_unlock_texture(ctx, texObj); } - else if (target == GL_PROXY_TEXTURE_2D || - (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && - ctx->Extensions.ARB_texture_cube_map)) { - /* Proxy texture: check for errors and update proxy state */ - GLenum error = compressed_texture_error_check(ctx, 2, target, level, - internalFormat, width, height, 1, border, imageSize); - if (!error) { - ASSERT(ctx->Driver.TestProxyTexImage); - error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, - internalFormat, GL_NONE, GL_NONE, - width, height, 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); - if (texImage) - clear_teximage_fields(texImage); - } - else { - /* store the teximage parameters */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, - border, internalFormat); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); - } - _mesa_unlock_texture(ctx, texObj); - } - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); - return; - } } void GLAPIENTRY -_mesa_CompressedTexImage3DARB(GLenum target, GLint level, +_mesa_CompressedTexImage1DARB(GLenum target, GLint level, GLenum internalFormat, GLsizei width, - GLsizei height, GLsizei depth, GLint border, - GLsizei imageSize, const GLvoid *data) + GLint border, GLsizei imageSize, + const GLvoid *data) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n", - _mesa_lookup_enum_by_nr(target), level, - _mesa_lookup_enum_by_nr(internalFormat), - width, height, depth, border, imageSize, data); - - if (target == GL_TEXTURE_3D) { - /* non-proxy target */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLenum error = compressed_texture_error_check(ctx, 3, target, level, - internalFormat, width, height, depth, border, imageSize); - if (error) { - _mesa_error(ctx, error, "glCompressedTexImage3D"); - return; - } - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_get_tex_image(ctx, texObj, target, level); - if (!texImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); - } - else { - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - ASSERT(texImage->Data == NULL); - - _mesa_init_teximage_fields(ctx, target, texImage, - width, height, depth, - border, internalFormat); - - /* Choose actual texture format */ - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); + compressedteximage(ctx, 1, target, level, internalFormat, + width, 1, 1, border, imageSize, data); +} - ASSERT(ctx->Driver.CompressedTexImage3D); - ctx->Driver.CompressedTexImage3D(ctx, target, level, - internalFormat, - width, height, depth, - border, imageSize, data, - texObj, texImage); - _mesa_set_fetch_functions(texImage, 3); +void GLAPIENTRY +_mesa_CompressedTexImage2DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + compressedteximage(ctx, 2, target, level, internalFormat, + width, height, 1, border, imageSize, data); +} - check_gen_mipmap(ctx, target, texObj, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; - } - } - _mesa_unlock_texture(ctx, texObj); - } - else if (target == GL_PROXY_TEXTURE_3D) { - /* Proxy texture: check for errors and update proxy state */ - GLenum error = compressed_texture_error_check(ctx, 3, target, level, - internalFormat, width, height, depth, border, imageSize); - if (!error) { - ASSERT(ctx->Driver.TestProxyTexImage); - error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, - internalFormat, GL_NONE, GL_NONE, - 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); - if (texImage) - clear_teximage_fields(texImage); - } - else { - /* store the teximage parameters */ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - - texObj = _mesa_get_current_tex_object(ctx, target); - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - _mesa_init_teximage_fields(ctx, target, texImage, width, height, - depth, border, internalFormat); - _mesa_choose_texture_format(ctx, texObj, texImage, target, level, - internalFormat, GL_NONE, GL_NONE); - } - _mesa_unlock_texture(ctx, texObj); - } - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); - return; - } +void GLAPIENTRY +_mesa_CompressedTexImage3DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + compressedteximage(ctx, 3, target, level, internalFormat, + width, height, depth, border, imageSize, data); } @@ -3869,5 +3484,3 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); } - - |