* 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:
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:
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:
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:
}
+/*
+ * 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
}
-/*
- * Given a texture unit and a texture target, return the corresponding
- * texture object.
- */
-static struct gl_texture_object *
-select_tex_object(struct gl_texture_unit *unit, GLenum target)
-{
- switch (target) {
- case GL_TEXTURE_1D:
- return unit->CurrentD[1];
- case GL_TEXTURE_2D:
- return unit->CurrentD[2];
- case GL_TEXTURE_3D:
- return unit->CurrentD[3];
- 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 unit->CurrentCubeMap;
- default:
- gl_problem(NULL, "bad target in select_tex_object()");
- return NULL;
- }
-}
-
-
static void
set_tex_image(struct gl_texture_object *tObj,
GLenum target, GLint level,
tObj->Image[level] = texImage;
return;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- tObj->PosX[level] = texImage;
+ tObj->Image[level] = texImage;
return;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
tObj->NegX[level] = texImage;
{
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;
img->Height2 = 1 << img->HeightLog2;
img->Depth2 = 1 << img->DepthLog2;
img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
+ img->IsCompressed = is_compressed_format(internalFormat);
}
+/*
+ * 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.
return ctx->Texture.Proxy3D->Image[level];
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
if (ctx->Extensions.HaveTextureCubeMap)
- return texUnit->CurrentCubeMap->PosX[level];
+ return texUnit->CurrentCubeMap->Image[level];
else
return NULL;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
return NULL;
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
if (ctx->Extensions.HaveTextureCubeMap)
- return ctx->Texture.ProxyCubeMap->PosX[level];
+ return ctx->Texture.ProxyCubeMap->Image[level];
else
return NULL;
default:
}
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;
}
}
}
+ /* 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
return GL_TRUE;
}
- iformat = _mesa_base_tex_format( internalFormat );
+ iformat = _mesa_base_tex_format( ctx, internalFormat );
if (iformat < 0) {
if (!isProxy) {
char message[100];
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 */
}
}
- 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;
}
}
+ /* 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];
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);
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 */
}
}
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 {
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 = select_tex_object(texUnit, target);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (!texImage) {
}
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 {
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 */
}
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 {
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;
}
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- texObj = select_tex_object(texUnit, target);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = texObj->Image[level];
assert(texImage);
(*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
ctx->Pixel.DriverReadBuffer );
+ /* XXX TODO we have to apply pixel transfer ops here! */
+
dst = image;
stride = width * 4 * sizeof(GLubyte);
for (i = 0; i < height; i++) {
|| !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
internalFormat, x, y, width, border))
{
+ struct gl_pixelstore_attrib unpackSave;
+
+ /* get image from framebuffer */
GLubyte *image = read_color_image( ctx, x, y, width, 1 );
if (!image) {
gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
return;
}
+
+ /* call glTexImage1D to redefine the texture */
+ unpackSave = ctx->Unpack;
+ ctx->Unpack = _mesa_native_packing;
(*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
border, GL_RGBA, GL_UNSIGNED_BYTE, image );
+ ctx->Unpack = unpackSave;
+
FREE(image);
}
}
|| !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
internalFormat, x, y, width, height, border))
{
+ struct gl_pixelstore_attrib unpackSave;
+
+ /* get image from framebuffer */
GLubyte *image = read_color_image( ctx, x, y, width, height );
if (!image) {
gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
return;
}
+
+ /* call glTexImage2D to redefine the texture */
+ unpackSave = ctx->Unpack;
+ ctx->Unpack = _mesa_native_packing;
(ctx->Exec->TexImage2D)( target, level, internalFormat, width,
height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
- FREE(image);
- }
-}
-
-
-
-/*
- * Do the work of glCopyTexSubImage[123]D.
- */
-static void
-copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
- GLint width, GLint height,
- GLint srcx, GLint srcy,
- GLint dstx, GLint dsty, GLint dstz )
-{
- GLint i;
- GLint format, components, rectarea;
- GLint texwidth, texheight, zoffset;
-
- /* dst[xyz] may be negative if we have a texture border! */
- dstx += dest->Border;
- dsty += dest->Border;
- dstz += dest->Border;
- texwidth = dest->Width;
- texheight = dest->Height;
- rectarea = texwidth * texheight;
- zoffset = dstz * rectarea;
- format = dest->Format;
- components = components_in_intformat( format );
-
- /* Select buffer to read from */
- (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
- ctx->Pixel.DriverReadBuffer );
+ ctx->Unpack = unpackSave;
- for (i = 0;i < height; i++) {
- GLubyte rgba[MAX_WIDTH][4];
- GLubyte *dst;
- gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
- dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
- _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
- GL_RGBA, GL_UNSIGNED_BYTE, rgba,
- &_mesa_native_packing, GL_TRUE);
+ FREE(image);
}
-
- /* Read from draw buffer (the default) */
- (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
- ctx->Color.DriverDrawBuffer );
}
-
void
_mesa_CopyTexSubImage1D( GLenum target, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width )
xoffset, x, y, width)) {
struct gl_texture_unit *texUnit;
struct gl_texture_image *teximage;
+ struct gl_pixelstore_attrib unpackSave;
+ GLubyte *image;
+
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
teximage = texUnit->CurrentD[1]->Image[level];
assert(teximage);
- if (teximage->Data) {
- copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
- /* tell driver about the change */
- /* XXX this is obsolete */
- if (ctx->Driver.TexImage) {
- (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
- texUnit->CurrentD[1],
- level, teximage->IntFormat, teximage );
- }
+
+ /* get image from frame buffer */
+ image = read_color_image(ctx, x, y, width, 1);
+ if (!image) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
+ return;
}
+
+ /* now call glTexSubImage1D to do the real work */
+ unpackSave = ctx->Unpack;
+ ctx->Unpack = _mesa_native_packing;
+ _mesa_TexSubImage1D(target, level, xoffset, width,
+ GL_RGBA, GL_UNSIGNED_BYTE, image);
+ ctx->Unpack = unpackSave;
+
+ FREE(image);
}
}
xoffset, yoffset, x, y, width, height )) {
struct gl_texture_unit *texUnit;
struct gl_texture_image *teximage;
+ struct gl_pixelstore_attrib unpackSave;
+ GLubyte *image;
+
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
teximage = texUnit->CurrentD[2]->Image[level];
assert(teximage);
- if (teximage->Data) {
- copy_tex_sub_image(ctx, teximage, width, height,
- x, y, xoffset, yoffset, 0);
- /* tell driver about the change */
- /* XXX this is obsolete */
- if (ctx->Driver.TexImage) {
- (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
- texUnit->CurrentD[2],
- level, teximage->IntFormat, teximage );
- }
+
+ /* get image from frame buffer */
+ image = read_color_image(ctx, x, y, width, height);
+ if (!image) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
+ return;
}
+
+ /* now call glTexSubImage2D to do the real work */
+ unpackSave = ctx->Unpack;
+ ctx->Unpack = _mesa_native_packing;
+ _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
+ GL_RGBA, GL_UNSIGNED_BYTE, image);
+ ctx->Unpack = unpackSave;
+
+ FREE(image);
}
}
xoffset, yoffset, zoffset, x, y, width, height )) {
struct gl_texture_unit *texUnit;
struct gl_texture_image *teximage;
+ struct gl_pixelstore_attrib unpackSave;
+ GLubyte *image;
+
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
teximage = texUnit->CurrentD[3]->Image[level];
assert(teximage);
- if (teximage->Data) {
- copy_tex_sub_image(ctx, teximage, width, height,
- x, y, xoffset, yoffset, zoffset);
- /* tell driver about the change */
- /* XXX this is obsolete */
- if (ctx->Driver.TexImage) {
- (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
- texUnit->CurrentD[3],
- level, teximage->IntFormat, teximage );
+
+ /* get image from frame buffer */
+ image = read_color_image(ctx, x, y, width, height);
+ if (!image) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
+ return;
+ }
+
+ /* now call glTexSubImage2D to do the real work */
+ unpackSave = ctx->Unpack;
+ ctx->Unpack = _mesa_native_packing;
+ _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
+ width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
+ ctx->Unpack = unpackSave;
+
+ FREE(image);
+ }
+}
+
+
+
+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");
}
}