X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fteximage.c;h=ffddeffbabc79da27eb186557ab4a49772b6a0f2;hb=f431a3fb4dc1bf860203d79e54657e3a62bc50df;hp=24244674c5fe9bd1d9d0e4377da7c69e423385c1;hpb=9c27278acfb786c8f2fc591eef9ed0c25135bcf0;p=mesa.git diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 24244674c5f..ffddeffbabc 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -1,21 +1,21 @@ -/* $Id: teximage.c,v 1.47 2000/09/05 22:04:30 brianp Exp $ */ +/* $Id: teximage.c,v 1.100 2001/07/13 20:07:37 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 3.5 - * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -32,20 +32,23 @@ #include "context.h" #include "convolve.h" #include "image.h" +#include "macros.h" #include "mem.h" #include "mmath.h" -#include "span.h" #include "state.h" +#include "texformat.h" #include "teximage.h" #include "texstate.h" -#include "types.h" +#include "texstore.h" +#include "mtypes.h" +#include "swrast/s_span.h" /* XXX SWRAST hack */ #endif /* * NOTES: * - * Mesa's native texture datatype is GLubyte. Native formats are + * Mesa's native texture datatype is GLchan. Native formats are * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, * and GL_COLOR_INDEX. * Device drivers are free to implement any internal format they want. @@ -55,50 +58,53 @@ #ifdef DEBUG static void PrintTexture(const struct gl_texture_image *img) { - int i, j, c; - GLubyte *data = img->Data; - - if (!data) { - printf("No texture data\n"); - return; - } - - switch (img->Format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_INTENSITY: - case GL_COLOR_INDEX: - c = 1; - break; - case GL_LUMINANCE_ALPHA: - c = 2; - break; - case GL_RGB: - c = 3; - break; - case GL_RGBA: - c = 4; - break; - default: - gl_problem(NULL, "error in PrintTexture\n"); - return; - } - - - for (i = 0; i < img->Height; i++) { - for (j = 0; j < img->Width; j++) { - if (c==1) - printf("%02x ", data[0]); - else if (c==2) - printf("%02x%02x ", data[0], data[1]); - else if (c==3) - printf("%02x%02x%02x ", data[0], data[1], data[2]); - else if (c==4) - printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); - data += c; - } - printf("\n"); - } +#if CHAN_TYPE == GL_FLOAT + _mesa_problem(NULL, "PrintTexture doesn't support float channels"); +#else + GLuint i, j, c; + const GLchan *data = (const GLchan *) img->Data; + + if (!data) { + printf("No texture data\n"); + return; + } + + switch (img->Format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_COLOR_INDEX: + c = 1; + break; + case GL_LUMINANCE_ALPHA: + c = 2; + break; + case GL_RGB: + c = 3; + break; + case GL_RGBA: + c = 4; + break; + default: + _mesa_problem(NULL, "error in PrintTexture\n"); + return; + } + + for (i = 0; i < img->Height; i++) { + for (j = 0; j < img->Width; j++) { + if (c==1) + printf("%02x ", data[0]); + else if (c==2) + printf("%02x%02x ", data[0], data[1]); + else if (c==3) + printf("%02x%02x%02x ", data[0], data[1], data[2]); + else if (c==4) + printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); + data += c; + } + printf("\n"); + } +#endif } #endif @@ -107,7 +113,7 @@ static void PrintTexture(const struct gl_texture_image *img) /* * Compute log base 2 of n. * If n isn't an exact power of two return -1. - * If n<0 return -1. + * If n < 0 return -1. */ static int logbase2( int n ) @@ -115,7 +121,7 @@ logbase2( int n ) GLint i = 1; GLint log2 = 0; - if (n<0) { + if (n < 0) { return -1; } @@ -142,10 +148,10 @@ logbase2( int n ) GLint _mesa_base_tex_format( GLcontext *ctx, GLint format ) { - /* - * Ask the driver for the base format, if it doesn't - * know, it will return -1; - */ + /* + * Ask the driver for the base format, if it doesn't + * know, it will return -1; + */ if (ctx->Driver.BaseCompressedTexFormat) { GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format); if (ifmt >= 0) { @@ -209,21 +215,26 @@ _mesa_base_tex_format( GLcontext *ctx, GLint format ) case GL_COLOR_INDEX12_EXT: case GL_COLOR_INDEX16_EXT: return GL_COLOR_INDEX; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16_SGIX: + case GL_DEPTH_COMPONENT24_SGIX: + case GL_DEPTH_COMPONENT32_SGIX: + if (ctx->Extensions.SGIX_depth_texture) + return GL_DEPTH_COMPONENT; + else + return -1; default: return -1; /* error */ } } - /* - * Given an internal texture format enum or 1, 2, 3, 4 return the - * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, - * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the - * number of components for the format. Return -1 if invalid enum. + * Test if the given image format is a color/rgba format. That is, + * not color index, depth, stencil, etc. */ -static GLint -components_in_intformat( GLint format ) +static GLboolean +is_color_format(GLenum format) { switch (format) { case GL_ALPHA: @@ -231,14 +242,12 @@ components_in_intformat( GLint format ) case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: - return 1; case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: - return 1; case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: @@ -247,13 +256,11 @@ components_in_intformat( GLint format ) case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: - return 2; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: - return 1; case 3: case GL_RGB: case GL_R3_G3_B2: @@ -263,7 +270,6 @@ components_in_intformat( GLint format ) case GL_RGB10: case GL_RGB12: case GL_RGB16: - return 3; case 4: case GL_RGBA: case GL_RGBA2: @@ -273,7 +279,17 @@ components_in_intformat( GLint format ) case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: - return 4; + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +static GLboolean +is_index_format(GLenum format) +{ + switch (format) { case GL_COLOR_INDEX: case GL_COLOR_INDEX1_EXT: case GL_COLOR_INDEX2_EXT: @@ -281,9 +297,9 @@ components_in_intformat( GLint format ) case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX12_EXT: case GL_COLOR_INDEX16_EXT: - return 1; + return GL_TRUE; default: - return -1; /* error */ + return GL_FALSE; } } @@ -295,132 +311,34 @@ components_in_intformat( GLint format ) static GLboolean is_compressed_format(GLcontext *ctx, GLenum internalFormat) { - if (ctx->Driver.IsCompressedFormat) { - return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat); - } - return GL_FALSE; + if (ctx->Driver.BaseCompressedTexFormat) { + GLint b = (*ctx->Driver.BaseCompressedTexFormat)(ctx, internalFormat); + if (b > 0) + return GL_TRUE; + else + return GL_FALSE; + } + return GL_FALSE; } /* - * Examine the texImage->Format field and set the Red, Green, Blue, etc - * texel component sizes to default values. - * These fields are set only here by core Mesa but device drivers may - * overwritting these fields to indicate true texel resolution. + * Store a gl_texture_image pointer in a gl_texture_object structure + * according to the target and level parameters. + * This was basically prompted by the introduction of cube maps. */ -static void -set_teximage_component_sizes( struct gl_texture_image *texImage ) -{ - switch (texImage->Format) { - case GL_ALPHA: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 8; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_LUMINANCE: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 8; - texImage->IndexBits = 0; - break; - case GL_LUMINANCE_ALPHA: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 8; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 8; - texImage->IndexBits = 0; - break; - case GL_INTENSITY: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 8; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_RED: - texImage->RedBits = 8; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_GREEN: - texImage->RedBits = 0; - texImage->GreenBits = 8; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_BLUE: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 8; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_RGB: - case GL_BGR: - texImage->RedBits = 8; - texImage->GreenBits = 8; - texImage->BlueBits = 8; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - texImage->RedBits = 8; - texImage->GreenBits = 8; - texImage->BlueBits = 8; - texImage->AlphaBits = 8; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_COLOR_INDEX: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 8; - break; - default: - gl_problem(NULL, "unexpected format in set_teximage_component_sizes"); - } -} - - -static void -set_tex_image(struct gl_texture_object *tObj, - GLenum target, GLint level, - struct gl_texture_image *texImage) +void +_mesa_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_1D: case GL_TEXTURE_2D: + case GL_TEXTURE_3D: tObj->Image[level] = texImage; return; case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: @@ -442,12 +360,13 @@ set_tex_image(struct gl_texture_object *tObj, tObj->NegZ[level] = texImage; return; default: - gl_problem(NULL, "bad target in set_tex_image()"); + _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); return; } } + /* * Return new gl_texture_image struct with all fields initialized to zero. */ @@ -459,42 +378,6 @@ _mesa_alloc_texture_image( void ) -/* - * Initialize most fields of a gl_texture_image struct. - */ -static void -init_texture_image( GLcontext *ctx, - struct gl_texture_image *img, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum internalFormat ) -{ - ASSERT(img); - ASSERT(!img->Data); - img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat); - set_teximage_component_sizes( img ); - img->IntFormat = (GLenum) internalFormat; - img->Border = border; - img->Width = width; - img->Height = height; - img->Depth = depth; - img->WidthLog2 = logbase2(width - 2 * border); - if (height == 1) /* 1-D texture */ - img->HeightLog2 = 0; - else - img->HeightLog2 = logbase2(height - 2 * border); - if (depth == 1) /* 2-D texture */ - img->DepthLog2 = 0; - else - img->DepthLog2 = logbase2(depth - 2 * border); - img->Width2 = 1 << img->WidthLog2; - img->Height2 = 1 << img->HeightLog2; - img->Depth2 = 1 << img->DepthLog2; - img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); - img->IsCompressed = is_compressed_format(ctx, internalFormat); -} - - - void _mesa_free_texture_image( struct gl_texture_image *teximage ) { @@ -506,33 +389,19 @@ _mesa_free_texture_image( struct gl_texture_image *teximage ) } - /* - * Return number of bytes of storage needed to store a compressed texture - * image. Only the driver knows for sure. If the driver can't help us, - * we must return 0. + * Return GL_TRUE if the target is a proxy target. */ -GLuint -_mesa_compressed_image_size(GLcontext *ctx, - GLenum internalFormat, - GLint numDimensions, - GLint width, - GLint height, - GLint depth) +static GLboolean +is_proxy_target(GLenum target) { - if (ctx->Driver.CompressedImageSize) { - return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat, - numDimensions, - width, height, depth); - } - else { - /* Shouldn't this be an internal error of some sort? */ - return 0; - } + return (target == GL_PROXY_TEXTURE_1D || + target == GL_PROXY_TEXTURE_2D || + target == GL_PROXY_TEXTURE_3D || + target == GL_PROXY_TEXTURE_CUBE_MAP_ARB); } - /* * Given a texture unit and a texture target, return the corresponding * texture object. @@ -543,15 +412,15 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, { switch (target) { case GL_TEXTURE_1D: - return texUnit->CurrentD[1]; + return texUnit->Current1D; case GL_PROXY_TEXTURE_1D: return ctx->Texture.Proxy1D; case GL_TEXTURE_2D: - return texUnit->CurrentD[2]; + return texUnit->Current2D; case GL_PROXY_TEXTURE_2D: return ctx->Texture.Proxy2D; case GL_TEXTURE_3D: - return texUnit->CurrentD[3]; + return texUnit->Current3D; case GL_PROXY_TEXTURE_3D: return ctx->Texture.Proxy3D; case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: @@ -560,13 +429,14 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 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 + case GL_TEXTURE_CUBE_MAP_ARB: + return ctx->Extensions.ARB_texture_cube_map ? texUnit->CurrentCubeMap : NULL; case GL_PROXY_TEXTURE_CUBE_MAP_ARB: - return ctx->Extensions.HaveTextureCubeMap + return ctx->Extensions.ARB_texture_cube_map ? ctx->Texture.ProxyCubeMap : NULL; default: - gl_problem(NULL, "bad target in _mesa_select_tex_object()"); + _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); return NULL; } } @@ -581,396 +451,81 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, GLenum target, GLint level) { ASSERT(texUnit); + ASSERT(level < MAX_TEXTURE_LEVELS); switch (target) { case GL_TEXTURE_1D: - return texUnit->CurrentD[1]->Image[level]; + return texUnit->Current1D->Image[level]; case GL_PROXY_TEXTURE_1D: return ctx->Texture.Proxy1D->Image[level]; case GL_TEXTURE_2D: - return texUnit->CurrentD[2]->Image[level]; + return texUnit->Current2D->Image[level]; case GL_PROXY_TEXTURE_2D: return ctx->Texture.Proxy2D->Image[level]; case GL_TEXTURE_3D: - return texUnit->CurrentD[3]->Image[level]; + return texUnit->Current3D->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) + if (ctx->Extensions.ARB_texture_cube_map) return texUnit->CurrentCubeMap->Image[level]; else return NULL; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - if (ctx->Extensions.HaveTextureCubeMap) + if (ctx->Extensions.ARB_texture_cube_map) return texUnit->CurrentCubeMap->NegX[level]; else return NULL; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - if (ctx->Extensions.HaveTextureCubeMap) + if (ctx->Extensions.ARB_texture_cube_map) return texUnit->CurrentCubeMap->PosY[level]; else return NULL; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - if (ctx->Extensions.HaveTextureCubeMap) + if (ctx->Extensions.ARB_texture_cube_map) return texUnit->CurrentCubeMap->NegY[level]; else return NULL; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - if (ctx->Extensions.HaveTextureCubeMap) + if (ctx->Extensions.ARB_texture_cube_map) return texUnit->CurrentCubeMap->PosZ[level]; else return NULL; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - if (ctx->Extensions.HaveTextureCubeMap) + if (ctx->Extensions.ARB_texture_cube_map) return texUnit->CurrentCubeMap->NegZ[level]; else return NULL; case GL_PROXY_TEXTURE_CUBE_MAP_ARB: - if (ctx->Extensions.HaveTextureCubeMap) + if (ctx->Extensions.ARB_texture_cube_map) return ctx->Texture.ProxyCubeMap->Image[level]; else return NULL; default: - gl_problem(ctx, "bad target in _mesa_select_tex_image()"); + _mesa_problem(ctx, "bad target in _mesa_select_tex_image()"); return NULL; } } -/* - * Calling glTexImage and related functions when convolution is enabled - * with GL_REDUCE border mode causes some complications. - * The incoming image must be extra large so that the post-convolution - * image size is reduced to a power of two size (plus 2 * border). - * This function adjusts a texture width and height accordingly if - * convolution with GL_REDUCE is enabled. - */ -static void -adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions, - GLsizei *width, GLsizei *height) -{ - if (ctx->Pixel.Convolution1DEnabled - && dimensions == 1 - && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) { - *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1); - } - else if (ctx->Pixel.Convolution2DEnabled - && dimensions > 1 - && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) { - *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1); - *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1); - } - else if (ctx->Pixel.Separable2DEnabled - && dimensions > 1 - && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) { - *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1); - *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1); - } -} - - - -/* - * This function is used to move user image data into a texture image. - * We handle full texture images and subtexture images. We also take - * care of all image transfer operations here, including convolution. - * Input: - * dstXoffset, dstYoffset, dstZoffset - offsets in pixels - * dstRowStride, dstImageStride - strides in bytes - */ -static void -fill_texture_image( GLcontext *ctx, GLuint dimensions, - GLenum texFormat, GLubyte *texAddr, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking) -{ - GLint texComponents; - - ASSERT(ctx); - ASSERT(dimensions >= 1 && dimensions <= 3); - ASSERT(texAddr); - ASSERT(srcWidth >= 1); - ASSERT(srcHeight >= 1); - ASSERT(srcDepth >= 1); - ASSERT(dstXoffset >= 0); - ASSERT(dstYoffset >= 0); - ASSERT(dstZoffset >= 0); - ASSERT(dstRowStride >= 0); - ASSERT(dstImageStride >= 0); - ASSERT(srcAddr); - ASSERT(srcPacking); - - texComponents = components_in_intformat(texFormat); - - /* try common 2D texture cases first */ - if (!ctx->ImageTransferState && dimensions == 2 - && srcType == GL_UNSIGNED_BYTE) { - - if (srcFormat == texFormat) { - /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA, - * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy(). - */ - const GLubyte *src = (const GLubyte *) _mesa_image_address( - srcPacking, srcAddr, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcRowStride = _mesa_image_row_stride(srcPacking, - srcWidth, srcFormat, srcType); - const GLint widthInBytes = srcWidth * texComponents; - GLubyte *dst = texAddr + dstYoffset * dstRowStride - + dstXoffset * texComponents * sizeof(GLubyte); - if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) { - MEMCPY(dst, src, srcHeight * widthInBytes); - } - else { - GLint i; - for (i = 0; i < srcHeight; i++) { - MEMCPY(dst, src, widthInBytes); - src += srcRowStride; - dst += dstRowStride; - } - } - return; /* all done */ - } - else if (srcFormat == GL_RGBA && texFormat == GL_RGB) { - /* commonly used by Quake */ - const GLubyte *src = (const GLubyte *) _mesa_image_address( - srcPacking, srcAddr, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcRowStride = _mesa_image_row_stride(srcPacking, - srcWidth, srcFormat, srcType); - GLubyte *dst = texAddr + dstYoffset * dstRowStride - + dstXoffset * texComponents * sizeof(GLubyte); - GLint i, j; - for (i = 0; i < srcHeight; i++) { - const GLubyte *s = src; - GLubyte *d = dst; - for (j = 0; j < srcWidth; j++) { - *d++ = *s++; /*red*/ - *d++ = *s++; /*green*/ - *d++ = *s++; /*blue*/ - s++; /*alpha*/ - } - src += srcRowStride; - dst += dstRowStride; - } - return; /* all done */ - } - } - - /* - * General case solutions - */ - if (texFormat == GL_COLOR_INDEX) { - /* color index texture */ - const GLenum texType = GL_UNSIGNED_BYTE; - GLint img, row; - GLubyte *dest = texAddr + dstZoffset * dstImageStride - + dstYoffset * dstRowStride - + dstXoffset * texComponents * sizeof(GLubyte); - for (img = 0; img < srcDepth; img++) { - GLubyte *destRow = dest; - for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); - _mesa_unpack_index_span(ctx, srcWidth, texType, destRow, - srcType, src, srcPacking, - ctx->ImageTransferState); - destRow += dstRowStride; - } - dest += dstImageStride; - } - } - else { - /* regular, color texture */ - if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) || - (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) || - (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) { - /* - * Fill texture image with convolution - */ - GLint img, row; - GLint convWidth = srcWidth, convHeight = srcHeight; - GLfloat *tmpImage, *convImage; - tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); - if (!tmpImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); - return; - } - convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); - if (!convImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); - FREE(tmpImage); - return; - } - - for (img = 0; img < srcDepth; img++) { - const GLfloat *srcf; - GLfloat *dstf = tmpImage; - GLubyte *dest; - - /* unpack and do transfer ops up to convolution */ - for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, - srcFormat, srcType, img, row, 0); - _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf, - srcFormat, srcType, src, srcPacking, - ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS, - GL_TRUE); - dstf += srcWidth * 4; - } - - /* convolve */ - if (dimensions == 1) { - ASSERT(ctx->Pixel.Convolution1DEnabled); - _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage); - } - else { - if (ctx->Pixel.Convolution2DEnabled) { - _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, - tmpImage, convImage); - } - else { - ASSERT(ctx->Pixel.Separable2DEnabled); - _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, - tmpImage, convImage); - } - } - - /* packing and transfer ops after convolution */ - srcf = convImage; - dest = texAddr + (dstZoffset + img) * dstImageStride - + dstYoffset * dstRowStride; - for (row = 0; row < convHeight; row++) { - _mesa_pack_float_rgba_span(ctx, convWidth, - (const GLfloat (*)[4]) srcf, - texFormat, GL_UNSIGNED_BYTE, - dest, &_mesa_native_packing, - ctx->ImageTransferState - & IMAGE_POST_CONVOLUTION_BITS); - srcf += convWidth * 4; - dest += dstRowStride; - } - } - - FREE(convImage); - FREE(tmpImage); - } - else { - /* - * no convolution - */ - GLint img, row; - GLubyte *dest = texAddr + dstZoffset * dstImageStride - + dstYoffset * dstRowStride - + dstXoffset * texComponents * sizeof(GLubyte); - for (img = 0; img < srcDepth; img++) { - GLubyte *destRow = dest; - for (row = 0; row < srcHeight; row++) { - const GLvoid *srcRow = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, - srcFormat, srcType, img, row, 0); - _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow, - srcFormat, srcType, srcRow, srcPacking, - ctx->ImageTransferState); - destRow += dstRowStride; - } - dest += dstImageStride; - } - } - } -} - - - -/* Need this to prevent an out-of-bounds memory access when using - * X86 optimized code. - */ -#ifdef USE_X86_ASM -# define EXTRA_BYTE 1 -#else -# define EXTRA_BYTE 0 -#endif - - - -/* - * Called by glTexImage[123]D. Fill in a texture image with data given - * by the client. All pixel transfer and unpack modes are handled here. - * Input: dimensions (1, 2, or 3) - * texImage - destination texture image (we'll malloc the memory) - * width, height, depth - size of source image - * srcFormat, srcType - source image format and type - * pixels - source image data - * srcPacking - source image packing parameters - * - * NOTE: All texture image parameters should have already been error checked. - * - * NOTE: the texImage dimensions and source image dimensions must be correct - * with respect to convolution with border mode = reduce. - */ -static void -make_texture_image( GLcontext *ctx, GLuint dimensions, - struct gl_texture_image *texImage, - GLint width, GLint height, GLint depth, - GLenum srcFormat, GLenum srcType, const GLvoid *pixels, - const struct gl_pixelstore_attrib *srcPacking) -{ - const GLint internalFormat = texImage->IntFormat; - const GLint components = components_in_intformat(internalFormat); - GLint convWidth = width, convHeight = height; - - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) { - _mesa_update_image_transfer_state(ctx); - } - - if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) { - adjust_texture_size_for_convolution(ctx, dimensions, - &convWidth, &convHeight); - } - - texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth - * components + EXTRA_BYTE); - if (!texImage->Data) - return; /* out of memory */ - - fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data, - width, height, depth, 0, 0, 0, - convWidth * components * sizeof(GLubyte), - convWidth * convHeight * components * sizeof(GLubyte), - srcFormat, srcType, pixels, srcPacking); -} - - - /* * glTexImage[123]D can accept a NULL image pointer. In this case we * create a texture image with unspecified image contents per the OpenGL - * spec. This function creates an empty image for the given texture image. + * spec. */ -static void -make_null_texture( struct gl_texture_image *texImage ) +static GLubyte * +make_null_texture(GLint width, GLint height, GLint depth, GLenum format) { - GLint components; - GLint numPixels; - - ASSERT(texImage); - ASSERT(!texImage->Data); - - components = components_in_intformat(texImage->IntFormat); - numPixels = texImage->Width * texImage->Height * texImage->Depth; - - texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE ); + const GLint components = _mesa_components_in_format(format); + const GLint numPixels = width * height * depth; + GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); /* * Let's see if anyone finds this. If glTexImage2D() is called with * a NULL image pointer then load the texture image with something * interesting instead of leaving it indeterminate. */ - if (texImage->Data) { + if (data) { static const char message[8][32] = { " X X XXXXX XXX X ", " XX XX X X X X X ", @@ -982,40 +537,41 @@ make_null_texture( struct gl_texture_image *texImage ) " " }; - GLubyte *imgPtr = texImage->Data; - GLint i, j, k; - for (i = 0; i < texImage->Height; i++) { - GLint srcRow = 7 - i % 8; - for (j = 0; j < texImage->Width; j++) { - GLint srcCol = j % 32; - GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70; - for (k=0;kFormat = 0; img->IntFormat = 0; - img->RedBits = 0; - img->GreenBits = 0; - img->BlueBits = 0; - img->AlphaBits = 0; - img->IntensityBits = 0; - img->LuminanceBits = 0; - img->IndexBits = 0; img->Border = 0; img->Width = 0; img->Height = 0; @@ -1027,11 +583,47 @@ clear_proxy_teximage(struct gl_texture_image *img) img->HeightLog2 = 0; img->DepthLog2 = 0; img->Data = NULL; + img->TexFormat = &_mesa_null_texformat; + img->FetchTexel = NULL; img->IsCompressed = 0; img->CompressedSize = 0; } +/* + * Initialize basic fields of the gl_texture_image struct. + */ +void +_mesa_init_teximage_fields(GLcontext *ctx, + struct gl_texture_image *img, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum internalFormat) +{ + ASSERT(img); + img->Format = _mesa_base_tex_format( ctx, internalFormat ); + ASSERT(img->Format > 0); + img->IntFormat = internalFormat; + img->Border = border; + img->Width = width; + img->Height = height; + img->Depth = depth; + img->WidthLog2 = logbase2(width - 2 * border); + if (height == 1) /* 1-D texture */ + img->HeightLog2 = 0; + else + img->HeightLog2 = logbase2(height - 2 * border); + if (depth == 1) /* 2-D texture */ + img->DepthLog2 = 0; + else + img->DepthLog2 = logbase2(depth - 2 * border); + img->Width2 = 1 << img->WidthLog2; + img->Height2 = 1 << img->HeightLog2; + img->Depth2 = 1 << img->DepthLog2; + img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); + img->IsCompressed = is_compressed_format(ctx, internalFormat); +} + + /* * Test glTexImage[123]D() parameters for errors. @@ -1049,65 +641,76 @@ texture_error_check( GLcontext *ctx, GLenum target, { GLboolean isProxy; GLint iformat; + GLint maxLevels = 0, maxTextureSize; if (dimensions == 1) { isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D); if (target != GL_TEXTURE_1D && !isProxy) { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { - isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D); + isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D || + target == GL_PROXY_TEXTURE_CUBE_MAP_ARB); if (target != GL_TEXTURE_2D && !isProxy && - !(ctx->Extensions.HaveTextureCubeMap && + !(ctx->Extensions.ARB_texture_cube_map && target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); return GL_TRUE; } + if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) + maxLevels = ctx->Const.MaxTextureLevels; + else + maxLevels = ctx->Const.MaxCubeTextureLevels; } else if (dimensions == 3) { isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D); if (target != GL_TEXTURE_3D && !isProxy) { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.Max3DTextureLevels; } else { - gl_problem( ctx, "bad dims in texture_error_check" ); + _mesa_problem( ctx, "bad dims in texture_error_check" ); return GL_TRUE; } + ASSERT(maxLevels > 0); + maxTextureSize = 1 << (maxLevels - 1); + /* Border */ if (border != 0 && border != 1) { if (!isProxy) { char message[100]; - sprintf(message, "glTexImage%dD(border)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexImage%dD(border=%d)", dimensions, border); + _mesa_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } /* Width */ - if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize + if (width < 2 * border || width > 2 + maxTextureSize || logbase2( width - 2 * border ) < 0) { if (!isProxy) { char message[100]; - sprintf(message, "glTexImage%dD(width)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexImage%dD(width=%d)", dimensions, width); + _mesa_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } /* Height */ if (dimensions >= 2) { - if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize + if (height < 2 * border || height > 2 + maxTextureSize || logbase2( height - 2 * border ) < 0) { if (!isProxy) { char message[100]; - sprintf(message, "glTexImage%dD(height)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexImage%dD(height=%d)", dimensions, height); + _mesa_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } @@ -1118,7 +721,7 @@ texture_error_check( GLcontext *ctx, GLenum target, target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { if (width != height) { if (!isProxy) { - gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); } return GL_TRUE; } @@ -1126,47 +729,60 @@ texture_error_check( GLcontext *ctx, GLenum target, /* Depth */ if (dimensions >= 3) { - if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize + if (depth < 2 * border || depth > 2 + maxTextureSize || logbase2( depth - 2 * border ) < 0) { if (!isProxy) { - gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" ); + char message[100]; + sprintf(message, "glTexImage3D(depth=%d)", depth ); + _mesa_error( ctx, GL_INVALID_VALUE, message ); } return GL_TRUE; } } /* Level */ - if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + if (level < 0 || level >= maxLevels) { if (!isProxy) { char message[100]; - sprintf(message, "glTexImage%dD(level)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexImage%dD(level=%d)", dimensions, level); + _mesa_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } + /* For cube map, width must equal height */ + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (width != height) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); + return GL_TRUE; + } + } + iformat = _mesa_base_tex_format( ctx, internalFormat ); if (iformat < 0) { if (!isProxy) { char message[100]; - sprintf(message, "glTexImage%dD(internalFormat)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions, + internalFormat); + _mesa_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } - if (!is_compressed_format(ctx, 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; + ASSERT(iformat > 0); + + if (!is_compressed_format( ctx, internalFormat ) && + !_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); + _mesa_error(ctx, GL_INVALID_OPERATION, message); } + return GL_TRUE; } /* if we get here, the parameters are OK */ @@ -1190,102 +806,133 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions, { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *destTex; + GLint maxLevels = 0; + GLboolean compressed; if (dimensions == 1) { if (target != GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { - if (ctx->Extensions.HaveTextureCubeMap) { + if (ctx->Extensions.ARB_texture_cube_map) { 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)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); return GL_TRUE; } } else if (target != GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); return GL_TRUE; } + if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) + maxLevels = ctx->Const.MaxTextureLevels; + else + maxLevels = ctx->Const.MaxCubeTextureLevels; } else if (dimensions == 3) { if (target != GL_TEXTURE_3D) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.Max3DTextureLevels; } else { - gl_problem( ctx, "bad dims in texture_error_check" ); + _mesa_problem( ctx, "bad dims in texture_error_check" ); return GL_TRUE; } - if (level < 0 || level >= ctx->Const.MaxTextureLevels) { - gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)"); + ASSERT(maxLevels > 0); + + if (level < 0 || level >= maxLevels) { + char message[100]; + sprintf(message, "glTexSubImage2D(level=%d)", level); + _mesa_error(ctx, GL_INVALID_ENUM, message); return GL_TRUE; } if (width < 0) { char message[100]; - sprintf(message, "glTexSubImage%dD(width)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } if (height < 0 && dimensions > 1) { char message[100]; - sprintf(message, "glTexSubImage%dD(height)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } if (depth < 0 && dimensions > 2) { char message[100]; - sprintf(message, "glTexSubImage%dD(depth)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } - destTex = texUnit->CurrentD[2]->Image[level]; + destTex = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!destTex) { - gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); return GL_TRUE; } if (xoffset < -((GLint)destTex->Border)) { - gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); return GL_TRUE; } if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { - gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); return GL_TRUE; } if (dimensions > 1) { if (yoffset < -((GLint)destTex->Border)) { - gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); return GL_TRUE; } if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { - gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); return GL_TRUE; } } if (dimensions > 2) { if (zoffset < -((GLint)destTex->Border)) { - gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); return GL_TRUE; } - if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { - gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); + if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); return GL_TRUE; } } - if (!is_compressed_format(ctx, 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); + compressed = is_compressed_format(ctx, destTex->IntFormat); + + if (!compressed && !_mesa_is_legal_format_and_type(format, type)) { + char message[100]; + sprintf(message, "glTexSubImage%dD(format or type)", dimensions); + _mesa_error(ctx, GL_INVALID_ENUM, message); + return GL_TRUE; + } + + if (compressed) { + if (xoffset != -destTex->Border) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage1/2/3D(xoffset != -border"); + return GL_TRUE; + } + if (dimensions > 1 && yoffset != -destTex->Border) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage2/3D(yoffset != -border"); + return GL_TRUE; + } + if (dimensions > 2 && zoffset != -destTex->Border) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage3D(zoffset != -border"); return GL_TRUE; } } @@ -1305,52 +952,61 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, GLint width, GLint height, GLint border ) { GLint iformat; + GLint maxLevels = 0, maxTextureSize; if (dimensions == 1) { if (target != GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { - if (ctx->Extensions.HaveTextureCubeMap) { + if (ctx->Extensions.ARB_texture_cube_map) { 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)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); return GL_TRUE; } } else if (target != GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); return GL_TRUE; } + if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) + maxLevels = ctx->Const.MaxTextureLevels; + else + maxLevels = ctx->Const.MaxCubeTextureLevels; } + ASSERT(maxLevels > 0); + maxTextureSize = 1 << (maxLevels - 1); + /* Border */ - if (border!=0 && border!=1) { + if (border != 0 && border != 1) { char message[100]; sprintf(message, "glCopyTexImage%dD(border)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } /* Width */ - if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize + if (width < 2 * border || width > 2 + maxTextureSize || logbase2( width - 2 * border ) < 0) { char message[100]; - sprintf(message, "glCopyTexImage%dD(width)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } /* Height */ if (dimensions >= 2) { - if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize + if (height < 2 * border || height > 2 + maxTextureSize || logbase2( height - 2 * border ) < 0) { char message[100]; - sprintf(message, "glCopyTexImage%dD(height)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } } @@ -1359,24 +1015,24 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, 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)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)"); return GL_TRUE; } } /* Level */ - if (level<0 || level>=ctx->Const.MaxTextureLevels) { + if (level < 0 || level >= maxLevels) { char message[100]; - sprintf(message, "glCopyTexImage%dD(level)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } - iformat = _mesa_base_tex_format( ctx, internalFormat ); + iformat = _mesa_base_tex_format(ctx, internalFormat); if (iformat < 0) { char message[100]; sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } @@ -1393,86 +1049,96 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *teximage; + GLint maxLevels = 0; + GLboolean compressed; if (dimensions == 1) { if (target != GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.MaxTextureLevels; } else if (dimensions == 2) { - if (ctx->Extensions.HaveTextureCubeMap) { + if (ctx->Extensions.ARB_texture_cube_map) { 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)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); return GL_TRUE; } } else if (target != GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); return GL_TRUE; } + if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) + maxLevels = ctx->Const.MaxTextureLevels; + else + maxLevels = ctx->Const.MaxCubeTextureLevels; } else if (dimensions == 3) { if (target != GL_TEXTURE_3D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); return GL_TRUE; } + maxLevels = ctx->Const.Max3DTextureLevels; } - if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + ASSERT(maxLevels > 0); + + if (level < 0 || level >= maxLevels) { char message[100]; - sprintf(message, "glCopyTexSubImage%dD(level)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } if (width < 0) { char message[100]; - sprintf(message, "glCopyTexSubImage%dD(width)", dimensions ); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } if (dimensions > 1 && height < 0) { char message[100]; - sprintf(message, "glCopyTexSubImage%dD(height)", dimensions ); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } - teximage = texUnit->CurrentD[dimensions]->Image[level]; + teximage = _mesa_select_tex_image(ctx, texUnit, target, level); if (!teximage) { char message[100]; sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions); - gl_error(ctx, GL_INVALID_OPERATION, message); + _mesa_error(ctx, GL_INVALID_OPERATION, message); return GL_TRUE; } if (xoffset < -((GLint)teximage->Border)) { char message[100]; - sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } - if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { + if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { char message[100]; sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } if (dimensions > 1) { if (yoffset < -((GLint)teximage->Border)) { char message[100]; - sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } /* NOTE: we're adding the border here, not subtracting! */ - if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { + if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { char message[100]; sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } } @@ -1481,13 +1147,32 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, if (zoffset < -((GLint)teximage->Border)) { char message[100]; sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + _mesa_error(ctx, GL_INVALID_VALUE, message); return GL_TRUE; } - if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { + if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { char message[100]; sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions); - gl_error(ctx, GL_INVALID_VALUE, message); + _mesa_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + } + + compressed = is_compressed_format(ctx, teximage->IntFormat); + if (compressed) { + if (xoffset != -teximage->Border) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexSubImage1/2/3D(xoffset != -border"); + return GL_TRUE; + } + if (dimensions > 1 && yoffset != -teximage->Border) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexSubImage2/3D(yoffset != -border"); + return GL_TRUE; + } + if (dimensions > 2 && zoffset != -teximage->Border) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexSubImage3D(zoffset != -border"); return GL_TRUE; } } @@ -1498,102 +1183,125 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, - -/* - * Turn generic compressed formats into specific compressed format. - * Some of the compressed formats we don't support, so we - * fall back to the uncompressed format. (See issue 15 of - * the GL_ARB_texture_compression specification.) - */ -static GLint -get_specific_compressed_tex_format(GLcontext *ctx, - GLint ifmt, GLint numDimensions) +void +_mesa_GetTexImage( GLenum target, GLint level, GLenum format, + GLenum type, GLvoid *pixels ) { - char message[100]; - GLint internalFormat = ifmt; + const struct gl_texture_unit *texUnit; + const struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLint maxLevels = 0; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (ctx->Extensions.HaveTextureCompression - && ctx->Driver.SpecificCompressedTexFormat) { - /* - * First, ask the driver for the specific format. - */ - 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: - internalFormat = (*ctx->Driver.SpecificCompressedTexFormat) - (ctx, internalFormat, numDimensions); - /* XXX shouldn't we return now? */ - break; - default: - /* silence compiler warnings */ - ; - } + texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); + texObj = _mesa_select_tex_object(ctx, texUnit, target); + if (!texObj || is_proxy_target(target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); + return; } - /* - * Now, convert any generic format left to an uncompressed - * specific format. If the driver does not support compression - * of the format, we must drop back to the uncompressed format. - * See issue 15 of the GL_ARB_texture_compression specification. - */ - switch (internalFormat) { - case GL_COMPRESSED_ALPHA_ARB: - if (ctx && !ctx->Extensions.HaveTextureCompression) { - sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); - gl_error(ctx, GL_INVALID_VALUE, message); - return -1; - } - internalFormat = GL_ALPHA; - break; - case GL_COMPRESSED_LUMINANCE_ARB: - if (ctx && !ctx->Extensions.HaveTextureCompression) { - sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); - gl_error(ctx, GL_INVALID_VALUE, message); - return -1; - } - internalFormat = GL_LUMINANCE; - break; - case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: - if (ctx && !ctx->Extensions.HaveTextureCompression) { - sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); - gl_error(ctx, GL_INVALID_VALUE, message); - return -1; - } - internalFormat = GL_LUMINANCE_ALPHA; - break; - case GL_COMPRESSED_INTENSITY_ARB: - if (ctx && !ctx->Extensions.HaveTextureCompression) { - sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); - gl_error(ctx, GL_INVALID_VALUE, message); - return -1; - } - internalFormat = GL_INTENSITY; - break; - case GL_COMPRESSED_RGB_ARB: - if (ctx && !ctx->Extensions.HaveTextureCompression) { - sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); - gl_error(ctx, GL_INVALID_VALUE, message); - return -1; - } - internalFormat = GL_RGB; - break; - case GL_COMPRESSED_RGBA_ARB: - if (ctx && !ctx->Extensions.HaveTextureCompression) { - sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); - gl_error(ctx, GL_INVALID_VALUE, message); - return -1; - } - internalFormat = GL_RGBA; - break; - default: - /* silence compiler warning */ - ; + if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) { + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (target == GL_TEXTURE_3D) { + maxLevels = ctx->Const.Max3DTextureLevels; + } + else { + maxLevels = ctx->Const.MaxCubeTextureLevels; + } + + ASSERT(maxLevels > 0); + + if (level < 0 || level >= maxLevels) { + _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); + return; + } + + if (_mesa_sizeof_type(type) <= 0) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); + return; + } + + if (_mesa_components_in_format(format) <= 0 || + format == GL_STENCIL_INDEX) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); + return; + } + + if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + } + + if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + } + + /* XXX what if format/type doesn't match texture format/type? */ + + if (!pixels) + return; + + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!texImage) { + /* invalid mipmap level, not an error */ + return; + } + + if (!texImage->Data) { + /* no image data, not an error */ + return; + } + + { + const GLint width = texImage->Width; + const GLint height = texImage->Height; + const GLint depth = texImage->Depth; + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + /* compute destination address in client memory */ + GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels, + width, height, format, type, + img, row, 0); + assert(dest); + + if (format == GL_COLOR_INDEX) { + GLuint indexRow[MAX_WIDTH]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexel)(texImage, col, row, img, + (GLvoid *) &indexRow[col]); + } + _mesa_pack_index_span(ctx, width, type, dest, + indexRow, &ctx->Pack, + 0 /* no image transfer */); + } + else if (format == GL_DEPTH_COMPONENT) { + GLfloat depthRow[MAX_WIDTH]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexel)(texImage, col, row, img, + (GLvoid *) &depthRow[col]); + } + _mesa_pack_depth_span(ctx, width, dest, type, + depthRow, &ctx->Pack); + } + else { + /* general case: convert row to RGBA format */ + GLchan rgba[MAX_WIDTH][4]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexel)(texImage, col, row, img, + (GLvoid *) rgba[col]); + } + _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba, + format, type, dest, &ctx->Pack, + 0 /* no image transfer */); + } /* format */ + } /* row */ + } /* img */ } - return internalFormat; } @@ -1606,118 +1314,106 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) { - GLsizei postConvWidth; + GLsizei postConvWidth = width; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - postConvWidth = width; - adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL); + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } - if (target==GL_TEXTURE_1D) { + if (target == GL_TEXTURE_1D) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLint ifmt; - - ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1); - if (ifmt < 0) { - /* - * The error here is that we were sent a generic compressed - * format, but the extension is not supported. - */ - return; - } - else { - internalFormat = ifmt; - } if (texture_error_check(ctx, target, level, internalFormat, format, type, 1, postConvWidth, 1, 1, border)) { - return; /* error in texture image was detected */ + return; /* error was recorded */ } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[1]; - 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; if (!texImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); return; } } else if (texImage->Data) { + /* free the old texture data */ FREE(texImage->Data); texImage->Data = NULL; } + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1, + border, internalFormat); - /* setup the teximage struct's fields */ - init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat); - - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - /* process the texture image */ + ASSERT(ctx->Driver.TexImage1D); if (pixels) { - GLboolean retain = GL_TRUE; - GLboolean success = GL_FALSE; - if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) { - /* let device driver try to use raw image */ - success = (*ctx->Driver.TexImage1D)( ctx, target, level, format, - type, pixels, &ctx->Unpack, - texObj, texImage, &retain); - } - if (retain || !success) { - /* make internal copy of the texture image */ - make_texture_image(ctx, 1, texImage, width, 1, 1, - format, type, pixels, &ctx->Unpack); - if (!success && ctx->Driver.TexImage1D) { - /* let device driver try to use unpacked image */ - (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, - texObj, texImage, &retain); - } - } - if (!retain && texImage->Data) { - FREE(texImage->Data); - texImage->Data = NULL; - } + (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, + width, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); } else { - make_null_texture(texImage); - if (ctx->Driver.TexImage1D) { - GLboolean retain; - (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, - texObj, texImage, &retain); + GLubyte *dummy = make_null_texture(width, 1, 1, format); + if (dummy) { + (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, + width, border, + format, GL_UNSIGNED_BYTE, dummy, + &_mesa_native_packing, texObj, texImage); + FREE(dummy); } } + ASSERT(texImage->TexFormat); + if (!texImage->FetchTexel) { + /* If driver didn't explicitly set this, use the default */ + texImage->FetchTexel = texImage->TexFormat->FetchTexel1D; + } + ASSERT(texImage->FetchTexel); + + if (texImage->IsCompressed) { + ASSERT(texImage->CompressedSize > 0); + } + /* state update */ - gl_put_texobj_on_dirty_list( ctx, texObj ); - ctx->NewState |= NEW_TEXTURING; + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } - else if (target==GL_PROXY_TEXTURE_1D) { + 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, postConvWidth, 1, 1, border)) { + GLenum error = texture_error_check(ctx, target, level, internalFormat, + format, type, 1, + postConvWidth, 1, 1, border); + if (!error) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1, + border, internalFormat); + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, format, type, + postConvWidth, 1, 1, border); + } + if (error) { /* if error, clear all proxy texture image parameters */ - if (level>=0 && levelConst.MaxTextureLevels) { - clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]); + if (level >= 0 && level < ctx->Const.MaxTextureLevels) { + clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]); } } - else { - /* if no error, update proxy texture image parameters */ - init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level], - width, 1, 1, border, internalFormat); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); return; } } @@ -1729,39 +1425,28 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, GLenum format, GLenum type, const GLvoid *pixels ) { - GLsizei postConvWidth, postConvHeight; + GLsizei postConvWidth = width, postConvHeight = height; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - postConvWidth = width; - postConvHeight = height; - adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight); + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } - if (target==GL_TEXTURE_2D || - (ctx->Extensions.HaveTextureCubeMap && + if (target == GL_TEXTURE_2D || + (ctx->Extensions.ARB_texture_cube_map && target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { + /* non-proxy target */ struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLint ifmt; - - ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2); - if (ifmt < 0) { - /* - * The error here is that we were sent a generic compressed - * format, but the extension is not supported. - */ - return; - } - else { - internalFormat = ifmt; - } if (texture_error_check(ctx, target, level, internalFormat, format, type, 2, postConvWidth, postConvHeight, 1, border)) { - return; /* error in texture image was detected */ + return; /* error was recorded */ } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; @@ -1770,145 +1455,121 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, if (!texImage) { texImage = _mesa_alloc_texture_image(); - set_tex_image(texObj, target, level, texImage); - /*texObj->Image[level] = texImage;*/ + _mesa_set_tex_image(texObj, target, level, texImage); if (!texImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } } else if (texImage->Data) { + /* free the old texture data */ FREE(texImage->Data); texImage->Data = NULL; } + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, + 1, border, internalFormat); - /* setup the teximage struct's fields */ - init_texture_image(ctx, texImage, postConvWidth, postConvHeight, - 1, border, internalFormat); - - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - /* process the texture image */ + ASSERT(ctx->Driver.TexImage2D); if (pixels) { - GLboolean retain = GL_TRUE; - GLboolean success = GL_FALSE; - if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) { - /* let device driver try to use raw image */ - success = (*ctx->Driver.TexImage2D)( ctx, target, level, format, - type, pixels, &ctx->Unpack, - texObj, texImage, &retain); - } - if (retain || !success) { - /* make internal copy of the texture image */ - make_texture_image(ctx, 2, texImage, width, height, 1, - format, type, pixels, &ctx->Unpack); - if (!success && ctx->Driver.TexImage2D) { - /* let device driver try to use unpacked image */ - (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, - texObj, texImage, &retain); - } - } - if (!retain && texImage->Data) { - FREE(texImage->Data); - texImage->Data = NULL; - } + (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, + width, height, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); } else { - make_null_texture(texImage); - if (ctx->Driver.TexImage2D) { - GLboolean retain; - (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, - texObj, texImage, &retain); + GLubyte *dummy = make_null_texture(width, height, 1, format); + if (dummy) { + (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, + width, height, border, + format, GL_UNSIGNED_BYTE, dummy, + &_mesa_native_packing, texObj, texImage); + FREE(dummy); } } -#define OLD_DD_TEXTURE -#ifdef OLD_DD_TEXTURE - /* XXX this will be removed in the future */ - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat, - texImage ); + ASSERT(texImage->TexFormat); + if (!texImage->FetchTexel) { + /* If driver didn't explicitly set this, use the default */ + texImage->FetchTexel = texImage->TexFormat->FetchTexel2D; + } + ASSERT(texImage->FetchTexel); + + if (texImage->IsCompressed) { + ASSERT(texImage->CompressedSize > 0); } -#endif /* state update */ - gl_put_texobj_on_dirty_list( ctx, texObj ); - ctx->NewState |= NEW_TEXTURING; + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } - else if (target==GL_PROXY_TEXTURE_2D) { + 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, postConvWidth, height, 1, border)) { + GLenum error = texture_error_check(ctx, target, level, internalFormat, + format, type, 2, + postConvWidth, postConvHeight, 1, border); + if (!error) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, texImage, postConvWidth, + postConvHeight, 1, border, internalFormat); + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, format, type, + postConvWidth, postConvHeight, 1, border); + } + if (error) { /* if error, clear all proxy texture image parameters */ - if (level>=0 && levelConst.MaxTextureLevels) { - clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]); + const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ? + ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels; + if (level >= 0 && level < maxLevels) { + clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); } } - else { - /* if no error, update proxy texture image parameters */ - init_texture_image(ctx, - ctx->Texture.Proxy2D->Image[level], - width, height, 1, border, internalFormat); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); return; } } - /* * Called by the API or display list executor. * Note that width and height include the border. */ void -_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, +_mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (target==GL_TEXTURE_3D_EXT) { + if (target == GL_TEXTURE_3D) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLint ifmt; - - ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3); - if (ifmt < 0) { - /* - * The error here is that we were sent a generic compressed - * format, but the extension is not supported. - */ - return; - } - else { - internalFormat = ifmt; - } - if (texture_error_check(ctx, target, level, internalFormat, + if (texture_error_check(ctx, target, level, (GLint) internalFormat, format, type, 3, width, height, depth, border)) { - return; /* error in texture image was detected */ + return; /* error was recorded */ } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[3]; - 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; if (!texImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); return; } } @@ -1916,73 +1577,72 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, FREE(texImage->Data); texImage->Data = NULL; } + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border, + internalFormat); - /* setup the teximage struct's fields */ - init_texture_image(ctx, texImage, width, height, depth, - border, internalFormat); + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); - - /* process the texture image */ + ASSERT(ctx->Driver.TexImage3D); if (pixels) { - GLboolean retain = GL_TRUE; - GLboolean success = GL_FALSE; - if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) { - /* let device driver try to use raw image */ - success = (*ctx->Driver.TexImage3D)( ctx, target, level, format, - type, pixels, &ctx->Unpack, - texObj, texImage, &retain); - } - if (retain || !success) { - /* make internal copy of the texture image */ - make_texture_image(ctx, 3, texImage, width, height, depth, - format, type, pixels, &ctx->Unpack); - if (!success && ctx->Driver.TexImage3D) { - /* let device driver try to use unpacked image */ - (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, - texObj, texImage, &retain); - } - } - if (!retain && texImage->Data) { - FREE(texImage->Data); - texImage->Data = NULL; - } + (*ctx->Driver.TexImage3D)(ctx, target, level, (GLint) internalFormat, + width, height, depth, border, + format, type, pixels, + &ctx->Unpack, texObj, texImage); } else { - make_null_texture(texImage); - if (ctx->Driver.TexImage3D) { - GLboolean retain; - (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, - texObj, texImage, &retain); + GLubyte *dummy = make_null_texture(width, height, depth, format); + if (dummy) { + (*ctx->Driver.TexImage3D)(ctx, target, level, + (GLint) internalFormat, + width, height, depth, border, + format, GL_UNSIGNED_BYTE, dummy, + &_mesa_native_packing, texObj, texImage); + FREE(dummy); } } + ASSERT(texImage->TexFormat); + if (!texImage->FetchTexel) { + /* If driver didn't explicitly set this, use the default */ + texImage->FetchTexel = texImage->TexFormat->FetchTexel3D; + } + ASSERT(texImage->FetchTexel); + + if (texImage->IsCompressed) { + ASSERT(texImage->CompressedSize > 0); + } + /* state update */ - gl_put_texobj_on_dirty_list( ctx, texObj ); - ctx->NewState |= NEW_TEXTURING; + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } - else if (target==GL_PROXY_TEXTURE_3D) { + 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)) { + GLenum error = texture_error_check(ctx, target, level, internalFormat, + format, type, 3, width, height, depth, border); + if (!error) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, texImage, width, height, 1, + border, internalFormat); + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, format, type, + width, height, depth, border); + } + if (error) { /* if error, clear all proxy texture image parameters */ - if (level>=0 && levelConst.MaxTextureLevels) { - clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]); + if (level >= 0 && level < ctx->Const.Max3DTextureLevels) { + clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]); } } - else { - /* if no error, update proxy texture image parameters */ - init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level], - width, height, depth, border, internalFormat); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); return; } } @@ -1994,253 +1654,11 @@ _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) { - _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, + _mesa_TexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels); } -/* - * Fetch a texture image from the device driver. - * Store the results in the given texture object at the given mipmap level. - */ -void -_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level, - const struct gl_texture_object *texObj ) -{ - GLvoid *image; - GLenum imgFormat, imgType; - GLboolean freeImage; - struct gl_texture_image *texImage; - GLint destComponents, numPixels, srcBytesPerTexel; - - if (!ctx->Driver.GetTexImage) - return; - - image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj, - &imgFormat, &imgType, &freeImage); - if (!image) - return; - - texImage = texObj->Image[level]; - ASSERT(texImage); - if (!texImage) - return; - - destComponents = components_in_intformat(texImage->Format); - assert(destComponents > 0); - numPixels = texImage->Width * texImage->Height * texImage->Depth; - assert(numPixels > 0); - srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType); - assert(srcBytesPerTexel > 0); - - if (!texImage->Data) { - /* Allocate memory for the texture image data */ - texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE); - } - - if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) { - /* We got lucky! The driver's format and type match Mesa's format. */ - if (texImage->Data) { - MEMCPY(texImage->Data, image, numPixels * destComponents); - } - } - else { - /* Convert the texture image from the driver's format to Mesa's - * internal format. - */ - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; - const GLint destBytesPerRow = width * destComponents * sizeof(GLchan); - const GLint srcBytesPerRow = width * srcBytesPerTexel; - const GLenum dstType = GL_UNSIGNED_BYTE; - const GLenum dstFormat = texImage->Format; - const GLubyte *srcPtr = (const GLubyte *) image; - GLubyte *destPtr = texImage->Data; - - if (texImage->Format == GL_COLOR_INDEX) { - /* color index texture */ - GLint img, row; - assert(imgFormat == GL_COLOR_INDEX); - for (img = 0; img < depth; img++) { - for (row = 0; row < height; row++) { - _mesa_unpack_index_span(ctx, width, dstType, destPtr, - imgType, srcPtr, &_mesa_native_packing, GL_FALSE); - destPtr += destBytesPerRow; - srcPtr += srcBytesPerRow; - } - } - } - else { - /* color texture */ - GLint img, row; - for (img = 0; img < depth; img++) { - for (row = 0; row < height; row++) { - _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr, - imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE); - destPtr += destBytesPerRow; - srcPtr += srcBytesPerRow; - } - } - } - } - - if (freeImage) - FREE(image); -} - - -void -_mesa_GetTexImage( GLenum target, GLint level, GLenum format, - GLenum type, GLvoid *pixels ) -{ - GET_CURRENT_CONTEXT(ctx); - const struct gl_texture_unit *texUnit; - const struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLboolean discardImage; - - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage"); - - if (level < 0 || level >= ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); - return; - } - - if (_mesa_sizeof_type(type) <= 0) { - gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); - return; - } - - if (_mesa_components_in_format(format) <= 0) { - gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); - return; - } - - if (!pixels) - return; - - texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = _mesa_select_tex_image(ctx, texUnit, target, level); - if (!texObj || !texImage) { - gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); - return; - } - - if (!texImage) { - /* invalid mipmap level */ - return; - } - - if (!texImage->Data) { - /* try to get the texture image from the device driver */ - _mesa_get_teximage_from_driver(ctx, target, level, texObj); - discardImage = GL_TRUE; - } - else { - discardImage = GL_FALSE; - } - - if (texImage->Data) { - GLint width = texImage->Width; - GLint height = texImage->Height; - GLint row; - - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); - - for (row = 0; row < height; row++) { - /* compute destination address in client memory */ - GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels, - width, height, - format, type, 0, row, 0); - - assert(dest); - if (texImage->Format == GL_RGBA) { - const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte); - /* XXX convolution */ - _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src, - format, type, dest, &ctx->Pack, - ctx->ImageTransferState ); - } - else { - /* fetch RGBA row from texture image then pack it in client mem */ - GLubyte rgba[MAX_WIDTH][4]; - GLint i; - const GLubyte *src; - switch (texImage->Format) { - case GL_ALPHA: - src = texImage->Data + row * width * sizeof(GLubyte); - for (i = 0; i < width; i++) { - rgba[i][RCOMP] = 255; - rgba[i][GCOMP] = 255; - rgba[i][BCOMP] = 255; - rgba[i][ACOMP] = src[i]; - } - break; - case GL_LUMINANCE: - src = texImage->Data + row * width * sizeof(GLubyte); - for (i = 0; i < width; i++) { - rgba[i][RCOMP] = src[i]; - rgba[i][GCOMP] = src[i]; - rgba[i][BCOMP] = src[i]; - rgba[i][ACOMP] = 255; - } - break; - case GL_LUMINANCE_ALPHA: - src = texImage->Data + row * 2 * width * sizeof(GLubyte); - for (i = 0; i < width; i++) { - rgba[i][RCOMP] = src[i*2+0]; - rgba[i][GCOMP] = src[i*2+0]; - rgba[i][BCOMP] = src[i*2+0]; - rgba[i][ACOMP] = src[i*2+1]; - } - break; - case GL_INTENSITY: - src = texImage->Data + row * width * sizeof(GLubyte); - for (i = 0; i < width; i++) { - rgba[i][RCOMP] = src[i]; - rgba[i][GCOMP] = src[i]; - rgba[i][BCOMP] = src[i]; - rgba[i][ACOMP] = 255; - } - break; - case GL_RGB: - src = texImage->Data + row * 3 * width * sizeof(GLubyte); - for (i = 0; i < width; i++) { - rgba[i][RCOMP] = src[i*3+0]; - rgba[i][GCOMP] = src[i*3+1]; - rgba[i][BCOMP] = src[i*3+2]; - rgba[i][ACOMP] = 255; - } - break; - case GL_RGBA: - /* this special case should have been handled above! */ - gl_problem( ctx, "error 1 in gl_GetTexImage" ); - break; - case GL_COLOR_INDEX: - gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" ); - break; - default: - gl_problem( ctx, "bad format in gl_GetTexImage" ); - } - /* XXX convolution */ - _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba, - format, type, dest, &ctx->Pack, - ctx->ImageTransferState ); - } - } - - /* if we got the teximage from the device driver we'll discard it now */ - if (discardImage) { - FREE(texImage->Data); - texImage->Data = NULL; - } - } -} - - void _mesa_TexSubImage1D( GLenum target, GLint level, @@ -2248,15 +1666,20 @@ _mesa_TexSubImage1D( GLenum target, GLint level, GLenum format, GLenum type, const GLvoid *pixels ) { - GET_CURRENT_CONTEXT(ctx); + GLsizei postConvWidth = width; struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLboolean success = GL_FALSE; - GLsizei postConvWidth; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - postConvWidth = width; - adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL); + /* XXX should test internal format */ + if (is_color_format(format)) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, postConvWidth, 1, 1, format, type)) { @@ -2264,50 +1687,21 @@ _mesa_TexSubImage1D( GLenum target, GLint level, } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[1]; - texImage = texObj->Image[level]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); assert(texImage); if (width == 0 || !pixels) return; /* no-op, not an error */ - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); - - if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) { - success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset, - width, format, type, pixels, - &ctx->Unpack, texObj, texImage ); - } - if (!success) { - /* XXX if Driver.TexSubImage1D, unpack image and try again? */ - GLboolean retain = GL_TRUE; - if (!texImage->Data) { - _mesa_get_teximage_from_driver( ctx, target, level, texObj ); - if (!texImage->Data) { - make_null_texture(texImage); - } - if (!texImage->Data) - return; /* we're really out of luck! */ - } - - fill_texture_image(ctx, 1, texImage->Format, texImage->Data, - width, 1, 1, xoffset, 0, 0, /* size and offsets */ - 0, 0, /* strides */ - format, type, pixels, &ctx->Unpack); + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; - if (ctx->Driver.TexImage1D) { - (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, texObj, texImage, - &retain ); - } - - if (!retain && texImage->Data) { - FREE(texImage->Data); - texImage->Data = NULL; - } - } + ASSERT(ctx->Driver.TexSubImage1D); + (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, + format, type, pixels, &ctx->Unpack, + texObj, texImage); + ctx->NewState |= _NEW_TEXTURE; } @@ -2318,16 +1712,21 @@ _mesa_TexSubImage2D( GLenum target, GLint level, GLenum format, GLenum type, const GLvoid *pixels ) { - GET_CURRENT_CONTEXT(ctx); + GLsizei postConvWidth = width, postConvHeight = height; struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLboolean success = GL_FALSE; - GLsizei postConvWidth, postConvHeight; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - postConvWidth = width; - postConvHeight = height; - adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight); + /* XXX should test internal format */ + if (is_color_format(format)) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, postConvWidth, postConvHeight, 1, format, type)) { @@ -2336,65 +1735,21 @@ _mesa_TexSubImage2D( GLenum target, GLint level, texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = texObj->Image[level]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); assert(texImage); if (width == 0 || height == 0 || !pixels) return; /* no-op, not an error */ - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); - - if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) { - success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset, - yoffset, width, height, format, type, - pixels, &ctx->Unpack, texObj, texImage ); - } - if (!success) { - /* XXX if Driver.TexSubImage2D, unpack image and try again? */ - const GLint texComps = components_in_intformat(texImage->Format); - const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte); - GLboolean retain = GL_TRUE; - - if (!texImage->Data) { - _mesa_get_teximage_from_driver( ctx, target, level, texObj ); - if (!texImage->Data) { - make_null_texture(texImage); - } - if (!texImage->Data) - return; /* we're really out of luck! */ - } - - fill_texture_image(ctx, 2, texImage->Format, texImage->Data, - width, height, 1, xoffset, yoffset, 0, - texRowStride, 0, - format, type, pixels, &ctx->Unpack); - - if (ctx->Driver.TexImage2D) { - (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, texObj, texImage, - &retain); - } - - if (!retain && texImage->Data) { - FREE(texImage->Data); - texImage->Data = NULL; - } + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; -#ifdef OLD_DD_TEXTURE - /* XXX this will be removed in the future */ - if (ctx->Driver.TexSubImage) { - (*ctx->Driver.TexSubImage)(ctx, target, texObj, level, - xoffset, yoffset, width, height, - texImage->IntFormat, texImage); - } - else if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj, - level, texImage->IntFormat, texImage ); - } -#endif - } + ASSERT(ctx->Driver.TexSubImage2D); + (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, + width, height, format, type, pixels, + &ctx->Unpack, texObj, texImage); + ctx->NewState |= _NEW_TEXTURE; } @@ -2406,11 +1761,14 @@ _mesa_TexSubImage3D( GLenum target, GLint level, GLenum format, GLenum type, const GLvoid *pixels ) { - GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLboolean success = GL_FALSE; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type)) { @@ -2418,94 +1776,25 @@ _mesa_TexSubImage3D( GLenum target, GLint level, } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[3]; - texImage = texObj->Image[level]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); assert(texImage); if (width == 0 || height == 0 || height == 0 || !pixels) return; /* no-op, not an error */ - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); - - if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) { - success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset, - yoffset, zoffset, width, height, depth, format, - type, pixels, &ctx->Unpack, texObj, texImage ); - } - if (!success) { - /* XXX if Driver.TexSubImage3D, unpack image and try again? */ - const GLint texComps = components_in_intformat(texImage->Format); - const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte); - const GLint texImgStride = texRowStride * texImage->Height; - GLboolean retain = GL_TRUE; - - if (!texImage->Data) { - _mesa_get_teximage_from_driver( ctx, target, level, texObj ); - if (!texImage->Data) { - make_null_texture(texImage); - } - if (!texImage->Data) - return; /* we're really out of luck! */ - } - - fill_texture_image(ctx, 3, texImage->Format, texImage->Data, - width, height, depth, xoffset, yoffset, zoffset, - texRowStride, texImgStride, - format, type, pixels, &ctx->Unpack); - - if (ctx->Driver.TexImage3D) { - (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format, - GL_UNSIGNED_BYTE, texImage->Data, - &_mesa_native_packing, texObj, texImage, - &retain); - } - - if (!retain && texImage->Data) { - FREE(texImage->Data); - texImage->Data = NULL; - } - } -} - - - -/* - * Read an RGBA image from the frame buffer. - * This is used by glCopyTex[Sub]Image[12]D(). - * Input: ctx - the context - * x, y - lower left corner - * width, height - size of region to read - * Return: pointer to block of GL_RGBA, GLubyte data. - */ -static GLubyte * -read_color_image( GLcontext *ctx, GLint x, GLint y, - GLsizei width, GLsizei height ) -{ - GLint stride, i; - GLubyte *image, *dst; - - image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte)); - if (!image) - return NULL; - - /* Select buffer to read from */ - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - - dst = image; - stride = width * 4 * sizeof(GLubyte); - for (i = 0; i < height; i++) { - gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i, - (GLubyte (*)[4]) dst ); - dst += stride; - } - - /* Read from draw buffer (the default) */ - (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - - return image; + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + zoffset += texImage->Border; + + ASSERT(ctx->Driver.TexSubImage3D); + (*ctx->Driver.TexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, + &ctx->Unpack, texObj, texImage ); + ctx->NewState |= _NEW_TEXTURE; } @@ -2516,37 +1805,60 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLint border ) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (copytexture_error_check(ctx, 1, target, level, internalFormat, - width, 1, border)) - return; + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } - if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D - || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level, - internalFormat, x, y, width, border)) { - struct gl_pixelstore_attrib unpackSave; + if (copytexture_error_check(ctx, 1, target, level, internalFormat, + postConvWidth, 1, border)) + return; - /* get image from framebuffer */ - GLubyte *image = read_color_image( ctx, x, y, width, 1 ); - if (!image) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!texImage) { + texImage = _mesa_alloc_texture_image(); + _mesa_set_tex_image(texObj, target, level, texImage); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); return; } + } + else if (texImage->Data) { + /* free the old texture data */ + FREE(texImage->Data); + texImage->Data = NULL; + } - /* 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; + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1, + border, internalFormat); - FREE(image); + + ASSERT(ctx->Driver.CopyTexImage1D); + (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, + x, y, width, border); + + ASSERT(texImage->TexFormat); + if (!texImage->FetchTexel) { + /* If driver didn't explicitly set this, use the default */ + texImage->FetchTexel = texImage->TexFormat->FetchTexel1D; } + ASSERT(texImage->FetchTexel); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } @@ -2556,37 +1868,60 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width, postConvHeight = height; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (copytexture_error_check(ctx, 2, target, level, internalFormat, - width, height, border)) - return; + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } - if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D - || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level, - internalFormat, x, y, width, height, border)) { - struct gl_pixelstore_attrib unpackSave; + if (copytexture_error_check(ctx, 2, target, level, internalFormat, + postConvWidth, postConvHeight, border)) + return; - /* get image from framebuffer */ - GLubyte *image = read_color_image( ctx, x, y, width, height ); - if (!image) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!texImage) { + texImage = _mesa_alloc_texture_image(); + _mesa_set_tex_image(texObj, target, level, texImage); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); return; } + } + else if (texImage->Data) { + /* free the old texture data */ + FREE(texImage->Data); + texImage->Data = NULL; + } + + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1, + border, internalFormat); - /* 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 ); - ctx->Unpack = unpackSave; + ASSERT(ctx->Driver.CopyTexImage2D); + (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, + x, y, width, height, border); - FREE(image); + ASSERT(texImage->TexFormat); + if (!texImage->FetchTexel) { + /* If driver didn't explicitly set this, use the default */ + texImage->FetchTexel = texImage->TexFormat->FetchTexel2D; } + ASSERT(texImage->FetchTexel); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } @@ -2595,44 +1930,33 @@ void _mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (copytexsubimage_error_check(ctx, 1, target, level, - xoffset, 0, 0, width, 1)) - return; + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + /* XXX should test internal format */ + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); - if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D - || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, - xoffset, x, y, width)) { - struct gl_texture_unit *texUnit; - struct gl_texture_image *teximage; - struct gl_pixelstore_attrib unpackSave; - GLubyte *image; + if (copytexsubimage_error_check(ctx, 1, target, level, + xoffset, 0, 0, postConvWidth, 1)) + return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - teximage = texUnit->CurrentD[1]->Image[level]; - assert(teximage); + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); - /* 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; + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; - FREE(image); - } + ASSERT(ctx->Driver.CopyTexSubImage1D); + (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width); + ctx->NewState |= _NEW_TEXTURE; } @@ -2642,44 +1966,35 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width, postConvHeight = height; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (copytexsubimage_error_check(ctx, 2, target, level, - xoffset, yoffset, 0, width, height)) - return; + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + /* XXX should test internal format */ + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); - if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D - || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, - xoffset, yoffset, x, y, width, height )) { - struct gl_texture_unit *texUnit; - struct gl_texture_image *teximage; - struct gl_pixelstore_attrib unpackSave; - GLubyte *image; + if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0, + postConvWidth, postConvHeight)) + return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - teximage = texUnit->CurrentD[2]->Image[level]; - assert(teximage); + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); - /* 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; - } + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; - /* 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); - } + ASSERT(ctx->Driver.CopyTexSubImage2D); + (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, + xoffset, yoffset, x, y, width, height); + ctx->NewState |= _NEW_TEXTURE; } @@ -2689,44 +2004,37 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width, postConvHeight = height; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (copytexsubimage_error_check(ctx, 3, target, level, - xoffset, yoffset, zoffset, width, height)) - return; + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); - if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) - _mesa_update_image_transfer_state(ctx); + /* XXX should test internal format */ + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); - if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D - || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, - xoffset, yoffset, zoffset, x, y, width, height )) { - struct gl_texture_unit *texUnit; - struct gl_texture_image *teximage; - struct gl_pixelstore_attrib unpackSave; - GLubyte *image; + if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset, + zoffset, postConvWidth, postConvHeight)) + return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - teximage = texUnit->CurrentD[3]->Image[level]; - assert(teximage); + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); - /* 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; - } + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + zoffset += texImage->Border; - /* 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); - } + ASSERT(ctx->Driver.CopyTexSubImage3D); + (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, + x, y, width, height); + ctx->NewState |= _NEW_TEXTURE; } @@ -2738,7 +2046,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, const GLvoid *data) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); switch (internalFormat) { case GL_COMPRESSED_ALPHA_ARB: @@ -2747,7 +2055,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, case GL_COMPRESSED_INTENSITY_ARB: case GL_COMPRESSED_RGB_ARB: case GL_COMPRESSED_RGBA_ARB: - gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB"); + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB"); return; default: /* silence compiler warning */ @@ -2758,7 +2066,6 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLsizei computedImageSize; if (texture_error_check(ctx, target, level, internalFormat, GL_NONE, GL_NONE, 1, width, 1, 1, border)) { @@ -2766,14 +2073,14 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[1]; - 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; if (!texImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); return; } } @@ -2782,71 +2089,47 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, texImage->Data = NULL; } - /* setup the teximage struct's fields */ - init_texture_image(ctx, texImage, width, 1, 1, - border, internalFormat); + _mesa_init_teximage_fields(ctx, 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, - imageSize, data, texObj, texImage, &retain); - } - if (retain || !success) { - /* make internal copy of the texture image */ - computedImageSize = _mesa_compressed_image_size(ctx, - internalFormat, - 1, /* num dims */ - width, - 1, /* height */ - 1); /* depth */ - if (computedImageSize != imageSize) { - gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)"); - return; - } - texImage->Data = MALLOC(computedImageSize); - if (texImage->Data) { - MEMCPY(texImage->Data, data, computedImageSize); - } - } - 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, 0, - texImage->Data, texObj, - texImage, &retain); - } + if (ctx->Extensions.ARB_texture_compression) { + ASSERT(ctx->Driver.CompressedTexImage1D); + (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, + internalFormat, width, border, + imageSize, data, + texObj, texImage); + ASSERT(texImage->CompressedSize > 0); /* sanity */ } /* state update */ - gl_put_texobj_on_dirty_list( ctx, texObj ); - ctx->NewState |= NEW_TEXTURING; + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } 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)) { + GLenum error = texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, 1, 1, border); + if (!error) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, texImage, width, 1, 1, + border, internalFormat); + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, GL_NONE, GL_NONE, + width, 1, 1, border); + } + if (error) { /* if error, clear all proxy texture image parameters */ - if (level>=0 && levelConst.MaxTextureLevels) { - clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]); + if (level >= 0 && level < ctx->Const.MaxTextureLevels) { + clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]); } } - else { - /* if no error, update proxy texture image parameters */ - init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level], - width, 1, 1, border, internalFormat); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" ); + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)"); return; } } @@ -2859,7 +2142,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, const GLvoid *data) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); switch (internalFormat) { case GL_COMPRESSED_ALPHA_ARB: @@ -2868,21 +2151,20 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, case GL_COMPRESSED_INTENSITY_ARB: case GL_COMPRESSED_RGB_ARB: case GL_COMPRESSED_RGBA_ARB: - gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB"); + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB"); return; default: /* silence compiler warning */ ; } - if (target==GL_TEXTURE_2D || - (ctx->Extensions.HaveTextureCubeMap && + if (target == GL_TEXTURE_2D || + (ctx->Extensions.ARB_texture_cube_map && target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLsizei computedImageSize; if (texture_error_check(ctx, target, level, internalFormat, GL_NONE, GL_NONE, 1, width, height, 1, border)) { @@ -2890,14 +2172,14 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, } 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; if (!texImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); return; } } @@ -2906,76 +2188,49 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, texImage->Data = NULL; } - /* setup the teximage struct's fields */ - init_texture_image(ctx, 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, - imageSize, - data, - texObj, - texImage, - &retain); - } - if (retain || !success) { - /* make internal copy of the texture image */ - computedImageSize = _mesa_compressed_image_size(ctx, - internalFormat, - 2, /* num dims */ - width, - height, - 1); /* depth */ - if (computedImageSize != imageSize) { - gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)"); - return; - } - texImage->Data = MALLOC(computedImageSize); - if (texImage->Data) { - MEMCPY(texImage->Data, data, computedImageSize); - } - } - 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, 0, - texImage->Data, texObj, - texImage, &retain); - } + _mesa_init_teximage_fields(ctx, texImage, width, height, 1, border, + internalFormat); + + if (ctx->Extensions.ARB_texture_compression) { + ASSERT(ctx->Driver.CompressedTexImage2D); + (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, + internalFormat, width, height, + border, imageSize, data, + texObj, texImage); + ASSERT(texImage->CompressedSize > 0); /* sanity */ } /* state update */ - gl_put_texobj_on_dirty_list( ctx, texObj ); - ctx->NewState |= NEW_TEXTURING; + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } 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)) { + GLenum error = texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 2, width, height, 1, border); + if (!error) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, texImage, width, height, 1, + border, internalFormat); + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, GL_NONE, GL_NONE, + width, height, 1, border); + } + if (error) { /* if error, clear all proxy texture image parameters */ - if (level>=0 && levelConst.MaxTextureLevels) { - clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]); + const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ? + ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels; + if (level >= 0 && level < maxLevels) { + clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); } } - else { - /* if no error, update proxy texture image parameters */ - init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level], - width, 1, 1, border, internalFormat); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" ); + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)"); return; } } @@ -2988,7 +2243,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, GLsizei imageSize, const GLvoid *data) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); switch (internalFormat) { case GL_COMPRESSED_ALPHA_ARB: @@ -2997,7 +2252,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, case GL_COMPRESSED_INTENSITY_ARB: case GL_COMPRESSED_RGB_ARB: case GL_COMPRESSED_RGBA_ARB: - gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB"); + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB"); return; default: /* silence compiler warning */ @@ -3008,7 +2263,6 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLsizei computedImageSize; if (texture_error_check(ctx, target, level, internalFormat, GL_NONE, GL_NONE, 1, width, height, depth, border)) { @@ -3016,14 +2270,14 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - texObj = texUnit->CurrentD[3]; - 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; if (!texImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); return; } } @@ -3032,73 +2286,48 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, texImage->Data = NULL; } - /* setup the teximage struct's fields */ - init_texture_image(ctx, texImage, width, height, depth, - border, internalFormat); + _mesa_init_teximage_fields(ctx, 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, - imageSize, data, - texObj, texImage, - &retain); - } - if (retain || !success) { - /* make internal copy of the texture image */ - computedImageSize = _mesa_compressed_image_size(ctx, - internalFormat, - 3, /* num dims */ - width, - height, - depth); - if (computedImageSize != imageSize) { - gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)"); - return; - } - texImage->Data = MALLOC(computedImageSize); - if (texImage->Data) { - MEMCPY(texImage->Data, data, computedImageSize); - } - } - 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, 0, - texImage->Data, texObj, - texImage, &retain); - } + if (ctx->Extensions.ARB_texture_compression) { + ASSERT(ctx->Driver.CompressedTexImage3D); + (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, + internalFormat, + width, height, depth, + border, imageSize, data, + texObj, texImage); + ASSERT(texImage->CompressedSize > 0); /* sanity */ } /* state update */ - gl_put_texobj_on_dirty_list( ctx, texObj ); - ctx->NewState |= NEW_TEXTURING; + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; } 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)) { + GLenum error = texture_error_check(ctx, target, level, internalFormat, + GL_NONE, GL_NONE, 1, width, height, depth, border); + if (!error) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, texImage, width, height, depth, + border, internalFormat); + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, GL_NONE, GL_NONE, + width, height, depth, border); + } + if (error) { /* if error, clear all proxy texture image parameters */ - if (level>=0 && levelConst.MaxTextureLevels) { - clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]); + if (level >= 0 && level < ctx->Const.Max3DTextureLevels) { + clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]); } } - else { - /* if no error, update proxy texture image parameters */ - init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level], - width, 1, 1, border, internalFormat); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" ); + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)"); return; } } @@ -3109,11 +2338,11 @@ _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; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, format, GL_NONE)) { @@ -3122,21 +2351,19 @@ _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = texObj->Image[level]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, 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; + (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, + xoffset, width, + format, imageSize, data, + texObj, texImage); } + ctx->NewState |= _NEW_TEXTURE; } @@ -3146,11 +2373,11 @@ _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; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1, format, GL_NONE)) { @@ -3159,22 +2386,19 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = texObj->Image[level]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, 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; + (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, + xoffset, yoffset, width, height, + format, imageSize, data, + texObj, texImage); } + ctx->NewState |= _NEW_TEXTURE; } @@ -3184,11 +2408,11 @@ _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; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, format, GL_NONE)) { @@ -3197,100 +2421,80 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = texObj->Image[level]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, 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; + (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data, + texObj, texImage); } + ctx->NewState |= _NEW_TEXTURE; } void _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) { - GET_CURRENT_CONTEXT(ctx); + const struct gl_texture_unit *texUnit; const struct gl_texture_object *texObj; struct gl_texture_image *texImage; + GLint maxLevels; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); + return; + } - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB"); + if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) { + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (target == GL_TEXTURE_3D) { + maxLevels = ctx->Const.Max3DTextureLevels; + } + else { + maxLevels = ctx->Const.MaxCubeTextureLevels; + } - if (level < 0 || level >= ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" ); + ASSERT(maxLevels > 0); + + if (level < 0 || level >= maxLevels) { + _mesa_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 (is_proxy_target(target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); + return; } + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); if (!texImage) { - /* invalid mipmap level */ - gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); + /* probably invalid mipmap level */ + _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); return; } if (!texImage->IsCompressed) { - gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); return; } if (!img) return; - if (ctx->Driver.GetCompressedTexImage) { + if (ctx->Extensions.ARB_texture_compression) { + ASSERT(ctx->Driver.GetCompressedTexImage); (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj, texImage); } - else { - gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage"); - } }