diff options
Diffstat (limited to 'xc/extras/Mesa/src/teximage.c')
-rw-r--r-- | xc/extras/Mesa/src/teximage.c | 955 |
1 files changed, 873 insertions, 82 deletions
diff --git a/xc/extras/Mesa/src/teximage.c b/xc/extras/Mesa/src/teximage.c index ae50558bf..0d25df6d8 100644 --- a/xc/extras/Mesa/src/teximage.c +++ b/xc/extras/Mesa/src/teximage.c @@ -137,15 +137,23 @@ logbase2( int n ) * Return -1 if invalid enum. */ GLint -_mesa_base_tex_format( GLint format ) +_mesa_base_tex_format( GLcontext *ctx, GLint format ) { switch (format) { + case GL_COMPRESSED_ALPHA_ARB: + if (ctx && !ctx->Extensions.HaveTextureCompression) + return -1; + /* fall-through */ case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: return GL_ALPHA; + case GL_COMPRESSED_LUMINANCE_ARB: + if (ctx && !ctx->Extensions.HaveTextureCompression) + return -1; + /* fall-through */ case 1: case GL_LUMINANCE: case GL_LUMINANCE4: @@ -153,6 +161,10 @@ _mesa_base_tex_format( GLint format ) case GL_LUMINANCE12: case GL_LUMINANCE16: return GL_LUMINANCE; + case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: + if (ctx && !ctx->Extensions.HaveTextureCompression) + return -1; + /* fall-through */ case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: @@ -162,12 +174,31 @@ _mesa_base_tex_format( GLint format ) case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: return GL_LUMINANCE_ALPHA; + case GL_COMPRESSED_INTENSITY_ARB: + if (ctx && !ctx->Extensions.HaveTextureCompression) + return -1; + /* fall-through */ case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: return GL_INTENSITY; + case GL_COMPRESSED_RGB_ARB: + if (ctx && ctx->Extensions.HaveTextureCompression) + return GL_RGB; + else + return -1; + case GL_COMPRESSED_RGB_FXT1_3DFX: + if (ctx && ctx->Extensions.HaveTextureCompressionFXT1) + return GL_RGB; + else + return -1; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + if (ctx && ctx->Extensions.HaveTextureCompressionS3TC) + return GL_RGB; + else + return -1; case 3: case GL_RGB: case GL_R3_G3_B2: @@ -178,6 +209,23 @@ _mesa_base_tex_format( GLint format ) case GL_RGB12: case GL_RGB16: return GL_RGB; + case GL_COMPRESSED_RGBA_ARB: + if (ctx && ctx->Extensions.HaveTextureCompression) + return GL_RGBA; + else + return -1; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + if (ctx && ctx->Extensions.HaveTextureCompressionFXT1) + return GL_RGBA; + else + return -1; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + if (ctx && ctx->Extensions.HaveTextureCompressionS3TC) + return GL_RGBA; + else + return -1; case 4: case GL_RGBA: case GL_RGBA2: @@ -275,6 +323,33 @@ components_in_intformat( GLint format ) } +/* + * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE + * otherwise. + */ +static GLboolean +is_compressed_format(GLenum internalFormat) +{ + switch (internalFormat) { + case GL_COMPRESSED_ALPHA_ARB: + case GL_COMPRESSED_LUMINANCE_ARB: + case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: + case GL_COMPRESSED_INTENSITY_ARB: + case GL_COMPRESSED_RGB_ARB: + case GL_COMPRESSED_RGBA_ARB: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + /* * Examine the texImage->Format field and set the Red, Green, Blue, etc @@ -385,6 +460,41 @@ set_teximage_component_sizes( struct gl_texture_image *texImage ) } +static void +set_tex_image(struct gl_texture_object *tObj, + GLenum target, GLint level, + struct gl_texture_image *texImage) +{ + ASSERT(tObj); + ASSERT(texImage); + switch (target) { + case GL_TEXTURE_2D: + tObj->Image[level] = texImage; + return; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + tObj->Image[level] = texImage; + return; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + tObj->NegX[level] = texImage; + return; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + tObj->PosY[level] = texImage; + return; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + tObj->NegY[level] = texImage; + return; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + tObj->PosZ[level] = texImage; + return; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + tObj->NegZ[level] = texImage; + return; + default: + gl_problem(NULL, "bad target in set_tex_image()"); + return; + } +} + /* * Return new gl_texture_image struct with all fields initialized to zero. @@ -407,7 +517,7 @@ init_texture_image( struct gl_texture_image *img, { ASSERT(img); ASSERT(!img->Data); - img->Format = (GLenum) _mesa_base_tex_format(internalFormat); + img->Format = (GLenum) _mesa_base_tex_format(NULL, internalFormat); set_teximage_component_sizes( img ); img->IntFormat = (GLenum) internalFormat; img->Border = border; @@ -427,6 +537,7 @@ init_texture_image( struct gl_texture_image *img, img->Height2 = 1 << img->HeightLog2; img->Depth2 = 1 << img->DepthLog2; img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); + img->IsCompressed = is_compressed_format(internalFormat); } @@ -443,6 +554,123 @@ _mesa_free_texture_image( struct gl_texture_image *teximage ) +/* + * Return number of bytes of storage needed to store a compressed texture + * image. + */ +GLuint +_mesa_compressed_image_size(GLenum internalFormat, + GLint width, GLint height, GLint depth) +{ + return 0; +} + + + +/* + * Given a texture unit and a texture target, return the corresponding + * texture object. + */ +struct gl_texture_object * +_mesa_select_tex_object(GLcontext *ctx, struct gl_texture_unit *texUnit, + GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + return texUnit->CurrentD[1]; + case GL_PROXY_TEXTURE_1D: + return ctx->Texture.Proxy1D; + case GL_TEXTURE_2D: + return texUnit->CurrentD[2]; + case GL_PROXY_TEXTURE_2D: + return ctx->Texture.Proxy2D; + case GL_TEXTURE_3D: + return texUnit->CurrentD[3]; + case GL_PROXY_TEXTURE_3D: + return ctx->Texture.Proxy3D; + 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: + return ctx->Extensions.HaveTextureCubeMap + ? texUnit->CurrentCubeMap : NULL; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + return ctx->Extensions.HaveTextureCubeMap + ? ctx->Texture.ProxyCubeMap : NULL; + default: + gl_problem(NULL, "bad target in _mesa_select_tex_object()"); + return NULL; + } +} + + +/* + * Return the texture image struct which corresponds to target and level + * for the given texture unit. + */ +struct gl_texture_image * +_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target, GLint level) +{ + ASSERT(texUnit); + switch (target) { + case GL_TEXTURE_1D: + return texUnit->CurrentD[1]->Image[level]; + case GL_PROXY_TEXTURE_1D: + return ctx->Texture.Proxy1D->Image[level]; + case GL_TEXTURE_2D: + return texUnit->CurrentD[2]->Image[level]; + case GL_PROXY_TEXTURE_2D: + return ctx->Texture.Proxy2D->Image[level]; + case GL_TEXTURE_3D: + return texUnit->CurrentD[3]->Image[level]; + case GL_PROXY_TEXTURE_3D: + return ctx->Texture.Proxy3D->Image[level]; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return texUnit->CurrentCubeMap->Image[level]; + else + return NULL; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return texUnit->CurrentCubeMap->NegX[level]; + else + return NULL; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return texUnit->CurrentCubeMap->PosY[level]; + else + return NULL; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return texUnit->CurrentCubeMap->NegY[level]; + else + return NULL; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return texUnit->CurrentCubeMap->PosZ[level]; + else + return NULL; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return texUnit->CurrentCubeMap->NegZ[level]; + else + return NULL; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + if (ctx->Extensions.HaveTextureCubeMap) + return ctx->Texture.ProxyCubeMap->Image[level]; + else + return NULL; + default: + gl_problem(ctx, "bad target in _mesa_select_tex_image()"); + return NULL; + } +} + + + /* Need this to prevent an out-of-bounds memory access when using * X86 optimized code. */ @@ -675,7 +903,10 @@ texture_error_check( GLcontext *ctx, GLenum target, } else if (dimensions == 2) { isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D); - if (target != GL_TEXTURE_2D && !isProxy) { + if (target != GL_TEXTURE_2D && !isProxy && + !(ctx->Extensions.HaveTextureCubeMap && + target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); return GL_TRUE; } @@ -726,6 +957,17 @@ texture_error_check( GLcontext *ctx, GLenum target, } } + /* 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) { + gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); + } + return GL_TRUE; + } + } + /* Depth */ if (dimensions >= 3) { if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize @@ -747,7 +989,7 @@ texture_error_check( GLcontext *ctx, GLenum target, return GL_TRUE; } - iformat = _mesa_base_tex_format( internalFormat ); + iformat = _mesa_base_tex_format( ctx, internalFormat ); if (iformat < 0) { if (!isProxy) { char message[100]; @@ -757,16 +999,18 @@ texture_error_check( GLcontext *ctx, GLenum target, return GL_TRUE; } - 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. - */ - if (!isProxy) { - char message[100]; - sprintf(message, "glTexImage%dD(format or type)", dimensions); - gl_error(ctx, GL_INVALID_OPERATION, message); + if (!is_compressed_format(internalFormat)) { + 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. + */ + if (!isProxy) { + char message[100]; + sprintf(message, "glTexImage%dD(format or type)", dimensions); + gl_error(ctx, GL_INVALID_OPERATION, message); + } + return GL_TRUE; } - return GL_TRUE; } /* if we get here, the parameters are OK */ @@ -798,7 +1042,15 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions, } } else if (dimensions == 2) { - if (target != GL_TEXTURE_2D) { + if (ctx->Extensions.HaveTextureCubeMap) { + if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || + target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && + target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (target != GL_TEXTURE_2D) { gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); return GL_TRUE; } @@ -873,11 +1125,13 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions, } } - if (!_mesa_is_legal_format_and_type(format, type)) { - char message[100]; - sprintf(message, "glTexSubImage%dD(format or type)", dimensions); - gl_error(ctx, GL_INVALID_ENUM, message); - return GL_TRUE; + if (!is_compressed_format(destTex->IntFormat)) { + if (!_mesa_is_legal_format_and_type(format, type)) { + char message[100]; + sprintf(message, "glTexSubImage%dD(format or type)", dimensions); + gl_error(ctx, GL_INVALID_ENUM, message); + return GL_TRUE; + } } return GL_FALSE; @@ -896,18 +1150,25 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, { GLint iformat; - if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" ); - return GL_TRUE; - } - - if (dimensions == 1 && target != GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); - return GL_TRUE; + if (dimensions == 1) { + if (target != GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); + return GL_TRUE; + } } - else if (dimensions == 2 && target != GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); - return GL_TRUE; + else if (dimensions == 2) { + if (ctx->Extensions.HaveTextureCubeMap) { + if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || + target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && + target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return GL_TRUE; + } + } + else if (target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return GL_TRUE; + } } /* Border */ @@ -938,6 +1199,15 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, } } + /* 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) { + gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)"); + return GL_TRUE; + } + } + /* Level */ if (level<0 || level>=ctx->Const.MaxTextureLevels) { char message[100]; @@ -946,7 +1216,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, return GL_TRUE; } - iformat = _mesa_base_tex_format( internalFormat ); + iformat = _mesa_base_tex_format( ctx, internalFormat ); if (iformat < 0) { char message[100]; sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions); @@ -968,17 +1238,31 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *teximage; - if (dimensions == 1 && target != GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); - return GL_TRUE; + if (dimensions == 1) { + if (target != GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); + return GL_TRUE; + } } - else if (dimensions == 2 && target != GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); - return GL_TRUE; + else if (dimensions == 2) { + if (ctx->Extensions.HaveTextureCubeMap) { + if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || + target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && + target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return GL_TRUE; + } } - else if (dimensions == 3 && target != GL_TEXTURE_3D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); - return GL_TRUE; + else if (dimensions == 3) { + if (target != GL_TEXTURE_3D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); + return GL_TRUE; + } } if (level < 0 || level >= ctx->Const.MaxTextureLevels) { @@ -1075,8 +1359,8 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, struct gl_texture_object *texObj; struct gl_texture_image *texImage; - if (texture_error_check( ctx, target, level, internalFormat, - format, type, 1, width, 1, 1, border )) { + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 1, width, 1, 1, border)) { return; /* error in texture image was detected */ } @@ -1145,21 +1429,18 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, } else if (target==GL_PROXY_TEXTURE_1D) { /* Proxy texture: check for errors and update proxy state */ - if (texture_error_check( ctx, target, level, internalFormat, - format, type, 1, width, 1, 1, border )) { + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 1, width, 1, 1, border)) { + /* if error, clear all proxy texture image parameters */ if (level>=0 && level<ctx->Const.MaxTextureLevels) { MEMSET( ctx->Texture.Proxy1D->Image[level], 0, sizeof(struct gl_texture_image) ); } } else { - ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format; - set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] ); - ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat; - ctx->Texture.Proxy1D->Image[level]->Border = border; - ctx->Texture.Proxy1D->Image[level]->Width = width; - ctx->Texture.Proxy1D->Image[level]->Height = 1; - ctx->Texture.Proxy1D->Image[level]->Depth = 1; + /* if no error, update proxy texture image parameters */ + init_texture_image(ctx->Texture.Proxy1D->Image[level], + width, 1, 1, border, internalFormat); } } else { @@ -1178,23 +1459,27 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); - if (target==GL_TEXTURE_2D) { + if (target==GL_TEXTURE_2D || + (ctx->Extensions.HaveTextureCubeMap && + target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - if (texture_error_check( ctx, target, level, internalFormat, - format, type, 2, width, height, 1, border )) { + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 2, width, height, 1, border)) { return; /* error in texture image was detected */ } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[2]; - texImage = texObj->Image[level]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); if (!texImage) { texImage = _mesa_alloc_texture_image(); - texObj->Image[level] = texImage; + set_tex_image(texObj, target, level, texImage); + /*texObj->Image[level] = texImage;*/ if (!texImage) { gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; @@ -1262,21 +1547,18 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, } else if (target==GL_PROXY_TEXTURE_2D) { /* Proxy texture: check for errors and update proxy state */ - if (texture_error_check( ctx, target, level, internalFormat, - format, type, 2, width, height, 1, border )) { + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 2, width, height, 1, border)) { + /* if error, clear all proxy texture image parameters */ if (level>=0 && level<ctx->Const.MaxTextureLevels) { MEMSET( ctx->Texture.Proxy2D->Image[level], 0, sizeof(struct gl_texture_image) ); } } else { - ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format; - set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] ); - ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat; - ctx->Texture.Proxy2D->Image[level]->Border = border; - ctx->Texture.Proxy2D->Image[level]->Width = width; - ctx->Texture.Proxy2D->Image[level]->Height = height; - ctx->Texture.Proxy2D->Image[level]->Depth = 1; + /* if no error, update proxy texture image parameters */ + init_texture_image(ctx->Texture.Proxy1D->Image[level], + width, height, 1, border, internalFormat); } } else { @@ -1304,9 +1586,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - if (texture_error_check( ctx, target, level, internalFormat, - format, type, 3, width, height, depth, - border )) { + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 3, width, height, depth, border)) { return; /* error in texture image was detected */ } @@ -1374,24 +1655,20 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, gl_put_texobj_on_dirty_list( ctx, texObj ); ctx->NewState |= NEW_TEXTURING; } - else if (target==GL_PROXY_TEXTURE_3D_EXT) { + else if (target==GL_PROXY_TEXTURE_3D) { /* Proxy texture: check for errors and update proxy state */ - if (texture_error_check( ctx, target, level, internalFormat, - format, type, 3, width, height, depth, - border )) { + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 3, width, height, depth, border)) { + /* if error, clear all proxy texture image parameters */ if (level>=0 && level<ctx->Const.MaxTextureLevels) { MEMSET( ctx->Texture.Proxy3D->Image[level], 0, sizeof(struct gl_texture_image) ); } } else { - ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format; - set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] ); - ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat; - ctx->Texture.Proxy3D->Image[level]->Border = border; - ctx->Texture.Proxy3D->Image[level]->Width = width; - ctx->Texture.Proxy3D->Image[level]->Height = height; - ctx->Texture.Proxy3D->Image[level]->Depth = depth; + /* if no error, update proxy texture image parameters */ + init_texture_image(ctx->Texture.Proxy1D->Image[level], + width, height, depth, border, internalFormat); } } else { @@ -1535,19 +1812,45 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format, switch (target) { case GL_TEXTURE_1D: texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1]; + texImage = texObj->Image[level]; break; case GL_TEXTURE_2D: texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2]; + texImage = texObj->Image[level]; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->Image[level]; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->NegX[level]; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->PosY[level]; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->NegY[level]; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->PosZ[level]; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->NegZ[level]; break; case GL_TEXTURE_3D: texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3]; + texImage = texObj->Image[level]; break; default: gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" ); return; } - texImage = texObj->Image[level]; if (!texImage) { /* invalid mipmap level */ return; @@ -1756,7 +2059,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level, } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[2]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); texImage = texObj->Image[level]; assert(texImage); @@ -2197,3 +2500,491 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, } } } + + + +void +_mesa_CompressedTexImage1DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLint border, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB"); + + if (target == GL_TEXTURE_1D) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + + if (texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, 1, 1, border)) { + return; /* error in texture image was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = texUnit->CurrentD[1]; + texImage = texObj->Image[level]; + + if (!texImage) { + texImage = _mesa_alloc_texture_image(); + texObj->Image[level] = texImage; + if (!texImage) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); + return; + } + } + else if (texImage->Data) { + FREE(texImage->Data); + texImage->Data = NULL; + } + + /* setup the teximage struct's fields */ + init_texture_image(texImage, width, 1, 1, border, internalFormat); + + /* process the texture image */ + if (data) { + GLboolean retain = GL_TRUE; + GLboolean success = GL_FALSE; + if (ctx->Driver.CompressedTexImage1D) { + success = (*ctx->Driver.CompressedTexImage1D)( ctx, target, level, + data, texObj, texImage, &retain); + } + if (retain || !success) { + /* make internal copy of the texture image */ + GLuint imageSize = _mesa_compressed_image_size(internalFormat, + width, 1, 1); + texImage->Data = MALLOC(imageSize); + if (texImage->Data) { + MEMCPY(texImage->Data, data, imageSize); + } + } + if (!retain && texImage->Data) { + FREE(texImage->Data); + texImage->Data = NULL; + } + } + else { + make_null_texture(texImage); + if (ctx->Driver.CompressedTexImage1D) { + GLboolean retain; + (*ctx->Driver.CompressedTexImage1D)( ctx, target, level, + texImage->Data, texObj, texImage, &retain); + } + } + + /* state update */ + gl_put_texobj_on_dirty_list( ctx, texObj ); + ctx->NewState |= NEW_TEXTURING; + } + else if (target == GL_PROXY_TEXTURE_1D) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, 1, 1, border)) { + /* if error, clear all proxy texture image parameters */ + if (level>=0 && level<ctx->Const.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy1D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + /* if no error, update proxy texture image parameters */ + init_texture_image(ctx->Texture.Proxy1D->Image[level], + width, 1, 1, border, internalFormat); + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" ); + return; + } +} + + +void +_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, "glCompressedTexImage2DARB"); + + if (target==GL_TEXTURE_2D || + (ctx->Extensions.HaveTextureCubeMap && + target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + + if (texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, height, 1, border)) { + return; /* error in texture image was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = texUnit->CurrentD[2]; + texImage = texObj->Image[level]; + + if (!texImage) { + texImage = _mesa_alloc_texture_image(); + texObj->Image[level] = texImage; + if (!texImage) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); + return; + } + } + else if (texImage->Data) { + FREE(texImage->Data); + texImage->Data = NULL; + } + + /* setup the teximage struct's fields */ + init_texture_image(texImage, width, height, 1, border, internalFormat); + + /* process the texture image */ + if (data) { + GLboolean retain = GL_TRUE; + GLboolean success = GL_FALSE; + if (ctx->Driver.CompressedTexImage2D) { + success = (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, + data, texObj, texImage, &retain); + } + if (retain || !success) { + /* make internal copy of the texture image */ + GLuint imageSize = _mesa_compressed_image_size(internalFormat, + width, height, 1); + texImage->Data = MALLOC(imageSize); + if (texImage->Data) { + MEMCPY(texImage->Data, data, imageSize); + } + } + if (!retain && texImage->Data) { + FREE(texImage->Data); + texImage->Data = NULL; + } + } + else { + make_null_texture(texImage); + if (ctx->Driver.CompressedTexImage2D) { + GLboolean retain; + (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, + texImage->Data, texObj, texImage, &retain); + } + } + + /* state update */ + gl_put_texobj_on_dirty_list( ctx, texObj ); + ctx->NewState |= NEW_TEXTURING; + } + else if (target == GL_PROXY_TEXTURE_2D) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, 1, 1, border)) { + /* if error, clear all proxy texture image parameters */ + if (level>=0 && level<ctx->Const.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy2D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + /* if no error, update proxy texture image parameters */ + init_texture_image(ctx->Texture.Proxy2D->Image[level], + width, 1, 1, border, internalFormat); + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" ); + return; + } +} + + +void +_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); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB"); + + if (target == GL_TEXTURE_3D) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + + if (texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, height, depth, border)) { + return; /* error in texture image was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = texUnit->CurrentD[3]; + texImage = texObj->Image[level]; + + if (!texImage) { + texImage = _mesa_alloc_texture_image(); + texObj->Image[level] = texImage; + if (!texImage) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); + return; + } + } + else if (texImage->Data) { + FREE(texImage->Data); + texImage->Data = NULL; + } + + /* setup the teximage struct's fields */ + init_texture_image(texImage, width, height, depth, border, internalFormat); + + /* process the texture image */ + if (data) { + GLboolean retain = GL_TRUE; + GLboolean success = GL_FALSE; + if (ctx->Driver.CompressedTexImage3D) { + success = (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, + data, texObj, texImage, &retain); + } + if (retain || !success) { + /* make internal copy of the texture image */ + GLuint imageSize = _mesa_compressed_image_size(internalFormat, + width, height, depth); + texImage->Data = MALLOC(imageSize); + if (texImage->Data) { + MEMCPY(texImage->Data, data, imageSize); + } + } + if (!retain && texImage->Data) { + FREE(texImage->Data); + texImage->Data = NULL; + } + } + else { + make_null_texture(texImage); + if (ctx->Driver.CompressedTexImage3D) { + GLboolean retain; + (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, + texImage->Data, texObj, texImage, &retain); + } + } + + /* state update */ + gl_put_texobj_on_dirty_list( ctx, texObj ); + ctx->NewState |= NEW_TEXTURING; + } + else if (target == GL_PROXY_TEXTURE_3D) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, height, depth, border)) { + /* if error, clear all proxy texture image parameters */ + if (level>=0 && level<ctx->Const.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy3D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + /* if no error, update proxy texture image parameters */ + init_texture_image(ctx->Texture.Proxy3D->Image[level], + width, 1, 1, border, internalFormat); + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" ); + return; + } +} + + +void +_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLboolean success = GL_FALSE; + + if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, + width, 1, 1, format, GL_NONE)) { + return; /* error was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = texObj->Image[level]; + assert(texImage); + + if (width == 0 || !data) + return; /* no-op, not an error */ + + if (ctx->Driver.CompressedTexSubImage1D) { + success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, + xoffset, width, format, imageSize, data, texObj, texImage); + } + if (!success) { + /* XXX what else can we do? */ + gl_problem(ctx, "glCompressedTexSubImage1DARB failed!"); + return; + } + +} + + +void +_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLboolean success = GL_FALSE; + + if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, + width, height, 1, format, GL_NONE)) { + return; /* error was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = texObj->Image[level]; + assert(texImage); + + if (width == 0 || height == 0 || !data) + return; /* no-op, not an error */ + + if (ctx->Driver.CompressedTexSubImage2D) { + success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, + xoffset, yoffset, width, height, format, + imageSize, data, texObj, texImage); + } + if (!success) { + /* XXX what else can we do? */ + gl_problem(ctx, "glCompressedTexSubImage2DARB failed!"); + return; + } +} + + +void +_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLboolean success = GL_FALSE; + + if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, GL_NONE)) { + return; /* error was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = texObj->Image[level]; + assert(texImage); + + if (width == 0 || height == 0 || depth == 0 || !data) + return; /* no-op, not an error */ + + if (ctx->Driver.CompressedTexSubImage3D) { + success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data, texObj, texImage); + } + if (!success) { + /* XXX what else can we do? */ + gl_problem(ctx, "glCompressedTexSubImage3DARB failed!"); + return; + } +} + + +void +_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB"); + + if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" ); + return; + } + + switch (target) { + case GL_TEXTURE_1D: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1]; + texImage = texObj->Image[level]; + break; + case GL_TEXTURE_2D: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2]; + texImage = texObj->Image[level]; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->Image[level]; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->NegX[level]; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->PosY[level]; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->NegY[level]; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->PosZ[level]; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; + texImage = texObj->NegZ[level]; + break; + case GL_TEXTURE_3D: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3]; + texImage = texObj->Image[level]; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); + return; + } + + if (!texImage) { + /* invalid mipmap level */ + gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); + return; + } + + if (!texImage->IsCompressed) { + gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); + return; + } + + if (!img) + return; + + if (ctx->Driver.GetCompressedTexImage) { + (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj, + texImage); + } + else { + gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage"); + } +} |