From: Brian Paul Date: Tue, 6 Jun 2000 17:03:38 +0000 (+0000) Subject: more work on GL_ARB_texture_compression X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9540a1dbcf213645b23c6cd9284e92a1152cca05;p=mesa.git more work on GL_ARB_texture_compression --- diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 106d99d780f..ad389df4a5d 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -667,6 +667,47 @@ struct dd_function_table { * should do the job. */ + GLboolean (*CompressedTexSubImage1D)( GLcontext *ctx, GLenum target, + GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + GLboolean (*CompressedTexSubImage2D)( GLcontext *ctx, GLenum target, + GLint level, GLint xoffset, + GLint yoffset, GLsizei width, + GLint height, GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + GLboolean (*CompressedTexSubImage3D)( GLcontext *ctx, GLenum target, + GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, + GLsizei width, GLint height, + GLint depth, GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + /* Called by glCompressedTexSubImage1/2/3D. + * Arguments: + * , , , , , , + * , and are user specified. + * is the target texture object. + * is the target texture image. It will have the texture + * width, height, depth, border and internalFormat information. + * Return GL_TRUE if operation completed, return GL_FALSE if core Mesa + * should do the job. + */ + + void (*GetCompressedTexImage)( GLcontext *ctx, GLenum target, + GLint lod, void *image, + const struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + /* Called by glGetCompressedTexImageARB. + * , , are specified by user. + * is the source texture object. + * is the source texture image. + */ void (*TexEnv)( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ); diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 2f291a6bdee..637aecff5e6 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -1,4 +1,4 @@ -/* $Id: dlist.c,v 1.41 2000/05/24 15:04:45 brianp Exp $ */ +/* $Id: dlist.c,v 1.42 2000/06/06 17:03:38 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -245,6 +245,13 @@ typedef enum { /* GL_SGIX/SGIS_pixel_texture */ OPCODE_PIXEL_TEXGEN_SGIX, OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS, + /* GL_ARB_texture_compression */ + OPCODE_COMPRESSED_TEX_IMAGE_1D, + OPCODE_COMPRESSED_TEX_IMAGE_2D, + OPCODE_COMPRESSED_TEX_IMAGE_3D, + OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, + OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, + OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, /* The following three are meta instructions */ OPCODE_ERROR, /* raise compiled-in error */ OPCODE_VERTEX_CASSETTE, /* render prebuilt vertex buffer */ @@ -420,6 +427,30 @@ void gl_destroy_list( GLcontext *ctx, GLuint list ) FREE(n[11].data); n += InstSize[n[0].opcode]; break; + case OPCODE_COMPRESSED_TEX_IMAGE_1D: + FREE(n[7].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_IMAGE_2D: + FREE(n[8].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_IMAGE_3D: + FREE(n[9].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: + FREE(n[7].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: + FREE(n[9].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: + FREE(n[11].data); + n += InstSize[n[0].opcode]; + break; case OPCODE_CONTINUE: n = (Node *) n[1].next; FREE( block ); @@ -628,7 +659,14 @@ void gl_init_lists( void ) InstSize[OPCODE_END_OF_LIST] = 1; /* GL_SGIX/SGIS_pixel_texture */ InstSize[OPCODE_PIXEL_TEXGEN_SGIX] = 2; - InstSize[OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS] = 3, + InstSize[OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS] = 3; + /* GL_ARB_texture_compression */ + InstSize[OPCODE_COMPRESSED_TEX_IMAGE_1D] = 8; + InstSize[OPCODE_COMPRESSED_TEX_IMAGE_2D] = 9; + InstSize[OPCODE_COMPRESSED_TEX_IMAGE_3D] = 10; + InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D] = 8; + InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D] = 10; + InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D] = 12; /* GL_ARB_multitexture */ InstSize[OPCODE_ACTIVE_TEXTURE] = 2; InstSize[OPCODE_CLIENT_ACTIVE_TEXTURE] = 2; @@ -3611,28 +3649,136 @@ static void save_PixelTexGenSGIX(GLenum mode) /* GL_ARB_texture_compression */ static void save_CompressedTexImage1DARB(GLenum target, GLint level, - GLenum internalformat, GLsizei width, + GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) { + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_1D) { + /* don't compile, execute immediately */ + (*ctx->Exec->CompressedTexImage1DARB)(target, level, internalFormat, + width, border, imageSize, data); + } + else { + Node *n; + GLvoid *image; + FLUSH_VB(ctx, "dlist"); + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalFormat; + n[4].i = (GLint) width; + n[5].i = border; + n[6].i = imageSize; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec->CompressedTexImage1DARB)(target, level, internalFormat, + width, border, imageSize, data); + } + } } static void save_CompressedTexImage2DARB(GLenum target, GLint level, - GLenum internalformat, GLsizei width, + GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) { + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_2D) { + /* don't compile, execute immediately */ + (*ctx->Exec->CompressedTexImage2DARB)(target, level, internalFormat, + width, height, border, imageSize, data); + } + else { + Node *n; + GLvoid *image; + FLUSH_VB(ctx, "dlist"); + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalFormat; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = border; + n[7].i = imageSize; + n[8].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec->CompressedTexImage2DARB)(target, level, internalFormat, + width, height, border, imageSize, data); + } + } } static void save_CompressedTexImage3DARB(GLenum target, GLint level, - GLenum internalformat, GLsizei width, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) { + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_3D) { + /* don't compile, execute immediately */ + (*ctx->Exec->CompressedTexImage3DARB)(target, level, internalFormat, + width, height, depth, border, imageSize, data); + } + else { + Node *n; + GLvoid *image; + FLUSH_VB(ctx, "dlist"); + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D, 10 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalFormat; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = (GLint) depth; + n[7].i = border; + n[8].i = imageSize; + n[9].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec->CompressedTexImage3DARB)(target, level, internalFormat, + width, height, depth, border, imageSize, data); + } + } } @@ -3641,6 +3787,36 @@ save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) { + Node *n; + GLvoid *image; + + GET_CURRENT_CONTEXT(ctx); + FLUSH_VB(ctx, "dlist"); + + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage1DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = (GLint) width; + n[5].e = format; + n[6].i = imageSize; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec->CompressedTexSubImage1DARB)(target, level, xoffset, + width, format, imageSize, data); + } } @@ -3650,6 +3826,38 @@ save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, GLenum format, GLsizei imageSize, const GLvoid *data) { + Node *n; + GLvoid *image; + + GET_CURRENT_CONTEXT(ctx); + FLUSH_VB(ctx, "dlist"); + + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, 10 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = (GLint) width; + n[6].i = (GLint) height; + n[7].e = format; + n[8].i = imageSize; + n[9].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec->CompressedTexSubImage2DARB)(target, level, xoffset, yoffset, + width, height, format, imageSize, data); + } } @@ -3659,6 +3867,40 @@ save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) { + Node *n; + GLvoid *image; + + GET_CURRENT_CONTEXT(ctx); + FLUSH_VB(ctx, "dlist"); + + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, 12 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = zoffset; + n[6].i = (GLint) width; + n[7].i = (GLint) height; + n[8].i = (GLint) depth; + n[9].e = format; + n[10].i = imageSize; + n[11].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec->CompressedTexSubImage3DARB)(target, level, xoffset, yoffset, + zoffset, width, height, depth, format, imageSize, data); + } } @@ -4433,6 +4675,31 @@ static void execute_list( GLcontext *ctx, GLuint list ) case OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS: /* GL_SGIS_pixel_texture */ (*ctx->Exec->PixelTexGenParameteriSGIS)( n[1].e, n[2].i ); break; + case OPCODE_COMPRESSED_TEX_IMAGE_1D: /* GL_ARB_texture_compression */ + (*ctx->Exec->CompressedTexImage1DARB)(n[1].e, n[2].i, n[3].e, + n[4].i, n[5].i, n[6].i, n[7].data); + break; + case OPCODE_COMPRESSED_TEX_IMAGE_2D: /* GL_ARB_texture_compression */ + (*ctx->Exec->CompressedTexImage2DARB)(n[1].e, n[2].i, n[3].e, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].data); + break; + case OPCODE_COMPRESSED_TEX_IMAGE_3D: /* GL_ARB_texture_compression */ + (*ctx->Exec->CompressedTexImage3DARB)(n[1].e, n[2].i, n[3].e, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, n[9].data); + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: /* GL_ARB_texture_compress */ + (*ctx->Exec->CompressedTexSubImage1DARB)(n[1].e, n[2].i, n[3].i, + n[4].i, n[5].e, n[6].i, n[7].data); + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: /* GL_ARB_texture_compress */ + (*ctx->Exec->CompressedTexSubImage2DARB)(n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].e, n[8].i, n[9].data); + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: /* GL_ARB_texture_compress */ + (*ctx->Exec->CompressedTexSubImage3DARB)(n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, + n[9].e, n[10].i, n[11].data); + break; case OPCODE_CONTINUE: n = (Node *) n[1].next; break; diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index d94b65fb3a7..0d25df6d81e 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -1125,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; @@ -1810,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; @@ -2581,7 +2609,10 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB"); - 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; @@ -2678,7 +2709,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB"); - if (target == GL_TEXTURE_1D) { + if (target == GL_TEXTURE_3D) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; @@ -2771,6 +2802,35 @@ _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; + } + } @@ -2780,6 +2840,35 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 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; + } } @@ -2789,10 +2878,113 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 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 lod, GLvoid *img) +_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"); + } }