| @@ -1,4 +1,4 @@ | |||
| /* $Id: teximage.c,v 1.23 2000/03/21 01:03:40 brianp Exp $ */ | |||
| /* $Id: teximage.c,v 1.24 2000/03/22 17:38:11 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| @@ -50,22 +50,6 @@ | |||
| */ | |||
| /* | |||
| * Default pixel packing of Mesa's internal texture images: | |||
| */ | |||
| static struct gl_pixelstore_attrib DefaultPacking = { | |||
| 1, /* Alignment */ | |||
| 0, /* RowLength */ | |||
| 0, /* SkipPixels */ | |||
| 0, /* SkipRows */ | |||
| 0, /* ImageHeight */ | |||
| 0, /* SkipImages */ | |||
| GL_FALSE, /* SwapBytes */ | |||
| GL_FALSE /* LsbFirst */ | |||
| }; | |||
| /* | |||
| * Compute log base 2 of n. | |||
| * If n isn't an exact power of two return -1. | |||
| @@ -363,16 +347,15 @@ gl_alloc_texture_image( void ) | |||
| /* | |||
| * Return a new gl_texture_image struct with most field initialized. | |||
| * Initialize most fields of a gl_texture_image struct. | |||
| */ | |||
| static struct gl_texture_image * | |||
| new_texture_image( GLsizei width, GLsizei height, GLsizei depth, | |||
| GLint border, GLenum internalFormat ) | |||
| static void | |||
| init_texture_image( struct gl_texture_image *img, | |||
| GLsizei width, GLsizei height, GLsizei depth, | |||
| GLint border, GLenum internalFormat ) | |||
| { | |||
| struct gl_texture_image *img = CALLOC_STRUCT(gl_texture_image); | |||
| if (!img) | |||
| return NULL; | |||
| ASSERT(img); | |||
| ASSERT(!img->Data); | |||
| img->Format = (GLenum) decode_internal_format(internalFormat); | |||
| set_teximage_component_sizes( img ); | |||
| img->IntFormat = (GLenum) internalFormat; | |||
| @@ -393,8 +376,6 @@ new_texture_image( GLsizei width, GLsizei height, GLsizei depth, | |||
| img->Height2 = 1 << img->HeightLog2; | |||
| img->Depth2 = 1 << img->DepthLog2; | |||
| img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); | |||
| return img; | |||
| } | |||
| @@ -1040,7 +1021,8 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, | |||
| if (target==GL_TEXTURE_1D) { | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_image *teximage; | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| if (texture_error_check( ctx, target, level, internalFormat, | |||
| format, type, 1, width, 1, 1, border )) { | |||
| @@ -1048,33 +1030,67 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, | |||
| } | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| /* free current texture image, if any */ | |||
| if (texUnit->CurrentD[1]->Image[level]) { | |||
| gl_free_texture_image( texUnit->CurrentD[1]->Image[level] ); | |||
| texObj = texUnit->CurrentD[1]; | |||
| texImage = texObj->Image[level]; | |||
| if (!texImage) { | |||
| texImage = gl_alloc_texture_image(); | |||
| texObj->Image[level] = texImage; | |||
| if (!texImage) { | |||
| gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); | |||
| return; | |||
| } | |||
| } | |||
| else if (texImage->Data) { | |||
| FREE(texImage->Data); | |||
| texImage->Data = NULL; | |||
| } | |||
| teximage = new_texture_image(width, 1, 1, border, internalFormat); | |||
| /* setup the teximage struct's fields */ | |||
| init_texture_image(texImage, width, 1, 1, border, internalFormat); | |||
| /* make new texture from source image */ | |||
| /* process the texture image */ | |||
| if (pixels) { | |||
| make_texture_image(ctx, teximage, format, type, pixels, &ctx->Unpack); | |||
| GLboolean retain = GL_TRUE; | |||
| GLboolean success = GL_FALSE; | |||
| if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA | |||
| && 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, texImage, 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; | |||
| } | |||
| } | |||
| else { | |||
| make_null_texture(teximage); | |||
| 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); | |||
| } | |||
| } | |||
| /* install new texture image */ | |||
| texUnit->CurrentD[1]->Image[level] = teximage; | |||
| gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); | |||
| /* state update */ | |||
| gl_put_texobj_on_dirty_list( ctx, texObj ); | |||
| ctx->NewState |= NEW_TEXTURING; | |||
| /* tell driver about change */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, | |||
| texUnit->CurrentD[1], | |||
| level, internalFormat, teximage ); | |||
| } | |||
| } | |||
| else if (target==GL_PROXY_TEXTURE_1D) { | |||
| /* Proxy texture: check for errors and update proxy state */ | |||
| @@ -1113,7 +1129,8 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, | |||
| if (target==GL_TEXTURE_2D) { | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_image *teximage; | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| if (texture_error_check( ctx, target, level, internalFormat, | |||
| format, type, 2, width, height, 1, border )) { | |||
| @@ -1121,33 +1138,76 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, | |||
| } | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| /* free current texture image, if any */ | |||
| if (texUnit->CurrentD[2]->Image[level]) { | |||
| gl_free_texture_image( texUnit->CurrentD[2]->Image[level] ); | |||
| texObj = texUnit->CurrentD[2]; | |||
| texImage = texObj->Image[level]; | |||
| if (!texImage) { | |||
| texImage = gl_alloc_texture_image(); | |||
| texObj->Image[level] = texImage; | |||
| if (!texImage) { | |||
| gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); | |||
| return; | |||
| } | |||
| } | |||
| else if (texImage->Data) { | |||
| FREE(texImage->Data); | |||
| texImage->Data = NULL; | |||
| } | |||
| teximage = new_texture_image(width, height, 1, border,internalFormat); | |||
| /* setup the teximage struct's fields */ | |||
| init_texture_image(texImage, width, height, 1, border, internalFormat); | |||
| /* make new texture from source image */ | |||
| /* process the texture image */ | |||
| if (pixels) { | |||
| make_texture_image(ctx, teximage, format, type, pixels, &ctx->Unpack); | |||
| GLboolean retain = GL_TRUE; | |||
| GLboolean success = GL_FALSE; | |||
| if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA | |||
| && 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, texImage, 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; | |||
| } | |||
| } | |||
| else { | |||
| make_null_texture(teximage); | |||
| 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); | |||
| } | |||
| } | |||
| /* install new texture image */ | |||
| texUnit->CurrentD[2]->Image[level] = teximage; | |||
| gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); | |||
| ctx->NewState |= NEW_TEXTURING; | |||
| /* tell driver about change */ | |||
| #define OLD_DD_TEXTURE | |||
| #ifdef OLD_DD_TEXTURE | |||
| /* XXX this will be removed in the future */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, | |||
| texUnit->CurrentD[2], | |||
| level, internalFormat, teximage ); | |||
| (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat, | |||
| texImage ); | |||
| } | |||
| #endif | |||
| /* state update */ | |||
| gl_put_texobj_on_dirty_list( ctx, texObj ); | |||
| ctx->NewState |= NEW_TEXTURING; | |||
| } | |||
| else if (target==GL_PROXY_TEXTURE_2D) { | |||
| /* Proxy texture: check for errors and update proxy state */ | |||
| @@ -1191,7 +1251,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, | |||
| if (target==GL_TEXTURE_3D_EXT) { | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_image *teximage; | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| if (texture_error_check( ctx, target, level, internalFormat, | |||
| format, type, 3, width, height, depth, | |||
| border )) { | |||
| @@ -1199,34 +1260,68 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, | |||
| } | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| /* free current texture image, if any */ | |||
| if (texUnit->CurrentD[3]->Image[level]) { | |||
| gl_free_texture_image( texUnit->CurrentD[3]->Image[level] ); | |||
| texObj = texUnit->CurrentD[3]; | |||
| texImage = texObj->Image[level]; | |||
| if (!texImage) { | |||
| texImage = gl_alloc_texture_image(); | |||
| texObj->Image[level] = texImage; | |||
| if (!texImage) { | |||
| gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); | |||
| return; | |||
| } | |||
| } | |||
| else if (texImage->Data) { | |||
| FREE(texImage->Data); | |||
| texImage->Data = NULL; | |||
| } | |||
| teximage = new_texture_image(width, height, depth, | |||
| border, internalFormat); | |||
| /* setup the teximage struct's fields */ | |||
| init_texture_image(texImage, width, height, depth, | |||
| border, internalFormat); | |||
| /* make new texture from source image */ | |||
| /* process the texture image */ | |||
| if (pixels) { | |||
| make_texture_image(ctx, teximage, format, type, pixels, &ctx->Unpack); | |||
| GLboolean retain = GL_TRUE; | |||
| GLboolean success = GL_FALSE; | |||
| if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA | |||
| && 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, texImage, 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; | |||
| } | |||
| } | |||
| else { | |||
| make_null_texture(teximage); | |||
| 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); | |||
| } | |||
| } | |||
| /* install new texture image */ | |||
| texUnit->CurrentD[3]->Image[level] = teximage; | |||
| gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); | |||
| /* state update */ | |||
| gl_put_texobj_on_dirty_list( ctx, texObj ); | |||
| ctx->NewState |= NEW_TEXTURING; | |||
| /* tell driver about change */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, | |||
| texUnit->CurrentD[3], | |||
| level, internalFormat, teximage ); | |||
| } | |||
| } | |||
| else if (target==GL_PROXY_TEXTURE_3D_EXT) { | |||
| /* Proxy texture: check for errors and update proxy state */ | |||
| @@ -1332,7 +1427,7 @@ get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level, | |||
| for (img = 0; img < depth; img++) { | |||
| for (row = 0; row < height; row++) { | |||
| _mesa_unpack_index_span(ctx, width, dstType, destPtr, | |||
| imgType, srcPtr, &DefaultPacking, GL_FALSE); | |||
| imgType, srcPtr, &_mesa_native_packing, GL_FALSE); | |||
| destPtr += destBytesPerRow; | |||
| srcPtr += srcBytesPerRow; | |||
| } | |||
| @@ -1344,7 +1439,7 @@ get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level, | |||
| for (img = 0; img < depth; img++) { | |||
| for (row = 0; row < height; row++) { | |||
| _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr, | |||
| imgFormat, imgType, srcPtr, &DefaultPacking, GL_FALSE); | |||
| imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE); | |||
| destPtr += destBytesPerRow; | |||
| srcPtr += srcBytesPerRow; | |||
| } | |||
| @@ -1516,64 +1611,78 @@ _mesa_TexSubImage1D( GLenum target, GLint level, | |||
| const GLvoid *pixels ) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| struct gl_texture_image *destTex; | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| GLboolean success = GL_FALSE; | |||
| if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, | |||
| width, 1, 1, format, type)) { | |||
| return; /* error was detected */ | |||
| } | |||
| destTex = texUnit->CurrentD[1]->Image[level]; | |||
| assert(destTex); | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| texObj = texUnit->CurrentD[1]; | |||
| texImage = texObj->Image[level]; | |||
| assert(texImage); | |||
| if (width == 0 || !pixels) | |||
| return; /* no-op, not an error */ | |||
| /* | |||
| * Replace the texture subimage | |||
| */ | |||
| { | |||
| const GLint texComponents = components_in_intformat(destTex->Format); | |||
| const GLenum texFormat = destTex->Format; | |||
| const GLint xoffsetb = xoffset + destTex->Border; | |||
| GLubyte *dst = destTex->Data + xoffsetb * texComponents; | |||
| if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA | |||
| && 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? */ | |||
| const GLint texComponents = components_in_intformat(texImage->Format); | |||
| const GLenum texFormat = texImage->Format; | |||
| const GLint xoffsetb = xoffset + texImage->Border; | |||
| GLboolean retain = GL_TRUE; | |||
| if (!texImage->Data) { | |||
| 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! */ | |||
| } | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, 1, format, type, 0, 0, 0); | |||
| GLubyte *dst = texImage->Data + xoffsetb * texComponents; | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, | |||
| 1, format, type, 0, 0, 0); | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, | |||
| type, src, &ctx->Unpack, GL_TRUE); | |||
| type, src, &ctx->Unpack, GL_TRUE); | |||
| } | |||
| else { | |||
| /* color texture */ | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, 1, format, type, 0, 0, 0); | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, | |||
| format, type, src, &ctx->Unpack, GL_TRUE); | |||
| GLubyte *dst = texImage->Data + xoffsetb * texComponents; | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, | |||
| 1, format, type, 0, 0, 0); | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format, | |||
| type, src, &ctx->Unpack, GL_TRUE); | |||
| } | |||
| } | |||
| gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); | |||
| if (ctx->Driver.TexImage1D) { | |||
| (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, | |||
| GL_UNSIGNED_BYTE, texImage->Data, | |||
| &_mesa_native_packing, texObj, texImage, | |||
| &retain ); | |||
| } | |||
| /* | |||
| * Inform device driver of texture image change. | |||
| */ | |||
| if (ctx->Driver.TexSubImage) { | |||
| (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], | |||
| level, xoffset, 0, width, 1, | |||
| texUnit->CurrentD[1]->Image[level]->IntFormat, | |||
| destTex ); | |||
| } | |||
| else { | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], | |||
| level, | |||
| texUnit->CurrentD[1]->Image[level]->IntFormat, | |||
| destTex ); | |||
| if (!retain && texImage->Data) { | |||
| FREE(texImage->Data); | |||
| texImage->Data = NULL; | |||
| } | |||
| } | |||
| /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/ | |||
| } | |||
| @@ -1585,75 +1694,104 @@ _mesa_TexSubImage2D( GLenum target, GLint level, | |||
| const GLvoid *pixels ) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| struct gl_texture_image *destTex; | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| GLboolean success = GL_FALSE; | |||
| if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, | |||
| width, height, 1, format, type)) { | |||
| return; /* error was detected */ | |||
| } | |||
| destTex = texUnit->CurrentD[2]->Image[level]; | |||
| assert(destTex); | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| texObj = texUnit->CurrentD[2]; | |||
| texImage = texObj->Image[level]; | |||
| assert(texImage); | |||
| if (width == 0 || height == 0 || !pixels) | |||
| return; /* no-op, not an error */ | |||
| if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA | |||
| && 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 texComponents = components_in_intformat(texImage->Format); | |||
| const GLenum texFormat = texImage->Format; | |||
| const GLint xoffsetb = xoffset + texImage->Border; | |||
| const GLint yoffsetb = yoffset + texImage->Border; | |||
| const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width, | |||
| format, type); | |||
| const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte); | |||
| GLboolean retain = GL_TRUE; | |||
| if (!texImage->Data) { | |||
| 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! */ | |||
| } | |||
| /* | |||
| * Replace the texture subimage | |||
| */ | |||
| { | |||
| const GLint texComponents = components_in_intformat(destTex->Format); | |||
| const GLenum texFormat = destTex->Format; | |||
| const GLint xoffsetb = xoffset + destTex->Border; | |||
| const GLint yoffsetb = yoffset + destTex->Border; | |||
| GLubyte *dst = destTex->Data | |||
| + (yoffsetb * destTex->Width + xoffsetb) * texComponents; | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| const GLint stride = destTex->Width * sizeof(GLubyte); | |||
| GLubyte *dst = texImage->Data | |||
| + (yoffsetb * texImage->Width + xoffsetb) * texComponents; | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, 0, 0, 0); | |||
| GLint row; | |||
| for (row = 0; row < height; row++) { | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, 0, row, 0); | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, | |||
| type, src, &ctx->Unpack, GL_TRUE); | |||
| dst += stride; | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type, | |||
| (const GLvoid *) src, &ctx->Unpack, GL_TRUE); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| else { | |||
| /* color texture */ | |||
| const GLint stride = destTex->Width * texComponents * sizeof(GLubyte); | |||
| GLubyte *dst = texImage->Data | |||
| + (yoffsetb * texImage->Width + xoffsetb) * texComponents; | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, 0, 0, 0); | |||
| GLint row; | |||
| for (row = 0; row < height; row++) { | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, 0, row, 0); | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, | |||
| format, type, src, &ctx->Unpack, GL_TRUE); | |||
| dst += stride; | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format, | |||
| type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| } | |||
| gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); | |||
| if (ctx->Driver.TexImage2D) { | |||
| (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format, | |||
| GL_UNSIGNED_BYTE, texImage->Data, | |||
| &_mesa_native_packing, texObj, texImage, | |||
| &retain); | |||
| } | |||
| /* | |||
| * Inform device driver of texture image change. | |||
| */ | |||
| if (ctx->Driver.TexSubImage) { | |||
| (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], | |||
| level, xoffset, yoffset, width, height, | |||
| texUnit->CurrentD[2]->Image[level]->IntFormat, | |||
| destTex ); | |||
| } | |||
| else { | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], | |||
| level, | |||
| texUnit->CurrentD[2]->Image[level]->IntFormat, | |||
| destTex ); | |||
| if (!retain && texImage->Data) { | |||
| FREE(texImage->Data); | |||
| texImage->Data = NULL; | |||
| } | |||
| #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_1D, texObj, | |||
| level, texImage->IntFormat, texImage ); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| @@ -1667,70 +1805,90 @@ _mesa_TexSubImage3D( GLenum target, GLint level, | |||
| const GLvoid *pixels ) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| struct gl_texture_image *destTex; | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| GLboolean success = GL_FALSE; | |||
| if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, | |||
| width, height, depth, format, type)) { | |||
| return; /* error was detected */ | |||
| } | |||
| destTex = texUnit->CurrentD[3]->Image[level]; | |||
| assert(destTex); | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| texObj = texUnit->CurrentD[3]; | |||
| texImage = texObj->Image[level]; | |||
| assert(texImage); | |||
| if (width == 0 || height == 0 || height == 0 || !pixels) | |||
| return; /* no-op, not an error */ | |||
| /* | |||
| * Replace the texture subimage | |||
| */ | |||
| { | |||
| const GLint texComponents = components_in_intformat(destTex->Format); | |||
| const GLenum texFormat = destTex->Format; | |||
| const GLint xoffsetb = xoffset + destTex->Border; | |||
| const GLint yoffsetb = yoffset + destTex->Border; | |||
| const GLint zoffsetb = zoffset + destTex->Border; | |||
| GLint dstRectArea = destTex->Width * destTex->Height; | |||
| GLubyte *dst = destTex->Data | |||
| + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb) | |||
| * texComponents; | |||
| if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA | |||
| && 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 texComponents = components_in_intformat(texImage->Format); | |||
| const GLenum texFormat = texImage->Format; | |||
| const GLint xoffsetb = xoffset + texImage->Border; | |||
| const GLint yoffsetb = yoffset + texImage->Border; | |||
| const GLint zoffsetb = zoffset + texImage->Border; | |||
| const GLint texWidth = texImage->Width; | |||
| const GLint dstRectArea = texWidth * texImage->Height; | |||
| const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, | |||
| width, format, type); | |||
| const GLint dstStride = texWidth * texComponents * sizeof(GLubyte); | |||
| GLboolean retain = GL_TRUE; | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| const GLint stride = destTex->Width * sizeof(GLubyte); | |||
| GLint img, row; | |||
| for (img = 0; img < depth; img++) { | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, img, 0, 0); | |||
| GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea | |||
| + yoffsetb * texWidth + xoffsetb) * texComponents; | |||
| for (row = 0; row < height; row++) { | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, img, row, 0); | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, | |||
| type, src, &ctx->Unpack, GL_TRUE); | |||
| dst += stride; | |||
| type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| } | |||
| else { | |||
| /* color texture */ | |||
| const GLint stride = destTex->Width * texComponents * sizeof(GLubyte); | |||
| GLint img, row; | |||
| for (img = 0; img < depth; img++) { | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, img, 0, 0); | |||
| GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea | |||
| + yoffsetb * texWidth + xoffsetb) * texComponents; | |||
| for (row = 0; row < height; row++) { | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, img, row, 0); | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, | |||
| format, type, src, &ctx->Unpack, GL_TRUE); | |||
| dst += stride; | |||
| format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); | |||
| if (ctx->Driver.TexImage3D) { | |||
| (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format, | |||
| GL_UNSIGNED_BYTE, texImage->Data, | |||
| &_mesa_native_packing, texObj, texImage, | |||
| &retain); | |||
| } | |||
| /* | |||
| * Inform device driver of texture image change. | |||
| */ | |||
| /* XXX todo */ | |||
| if (!retain && texImage->Data) { | |||
| FREE(texImage->Data); | |||
| texImage->Data = NULL; | |||
| } | |||
| } | |||
| } | |||
| @@ -1845,17 +2003,6 @@ copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, | |||
| GLint srcx, GLint srcy, | |||
| GLint dstx, GLint dsty, GLint dstz ) | |||
| { | |||
| static struct gl_pixelstore_attrib packing = { | |||
| 1, /* Alignment */ | |||
| 0, /* RowLength */ | |||
| 0, /* SkipPixels */ | |||
| 0, /* SkipRows */ | |||
| 0, /* ImageHeight */ | |||
| 0, /* SkipImages */ | |||
| GL_FALSE, /* SwapBytes */ | |||
| GL_FALSE /* LsbFirst */ | |||
| }; | |||
| GLint i; | |||
| GLint format, components, rectarea; | |||
| GLint texwidth, texheight, zoffset; | |||
| @@ -1882,7 +2029,7 @@ copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, | |||
| dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components; | |||
| _mesa_unpack_ubyte_color_span(ctx, width, format, dst, | |||
| GL_RGBA, GL_UNSIGNED_BYTE, rgba, | |||
| &packing, GL_TRUE); | |||
| &_mesa_native_packing, GL_TRUE); | |||
| } | |||
| /* Read from draw buffer (the default) */ | |||
| @@ -1916,6 +2063,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, | |||
| if (teximage->Data) { | |||
| copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0); | |||
| /* tell driver about the change */ | |||
| /* XXX call Driver.TexSubImage instead? */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, | |||
| texUnit->CurrentD[1], | |||
| @@ -1952,6 +2100,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, | |||
| copy_tex_sub_image(ctx, teximage, width, height, | |||
| x, y, xoffset, yoffset, 0); | |||
| /* tell driver about the change */ | |||
| /* XXX call Driver.TexSubImage instead? */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, | |||
| texUnit->CurrentD[2], | |||
| @@ -1975,23 +2124,24 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, | |||
| xoffset, yoffset, zoffset, width, height)) | |||
| return; | |||
| if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA | |||
| if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA | |||
| || !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; | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| teximage = texUnit->CurrentD[3]->Image[level]; | |||
| assert(teximage); | |||
| if (teximage->Data) { | |||
| copy_tex_sub_image(ctx, teximage, width, height, | |||
| xoffset, yoffset, zoffset, x, y, width, height )) { | |||
| struct gl_texture_unit *texUnit; | |||
| struct gl_texture_image *teximage; | |||
| texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | |||
| teximage = texUnit->CurrentD[3]->Image[level]; | |||
| assert(teximage); | |||
| if (teximage->Data) { | |||
| copy_tex_sub_image(ctx, teximage, width, height, | |||
| x, y, xoffset, yoffset, zoffset); | |||
| /* tell driver about the change */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D, | |||
| texUnit->CurrentD[3], | |||
| level, teximage->IntFormat, teximage ); | |||
| /* tell driver about the change */ | |||
| /* XXX call Driver.TexSubImage instead? */ | |||
| if (ctx->Driver.TexImage) { | |||
| (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D, | |||
| texUnit->CurrentD[3], | |||
| level, teximage->IntFormat, teximage ); | |||
| } | |||
| } | |||
| } | |||