diff options
Diffstat (limited to 'xc/extras/Mesa/src/texstore.c')
-rw-r--r-- | xc/extras/Mesa/src/texstore.c | 783 |
1 files changed, 566 insertions, 217 deletions
diff --git a/xc/extras/Mesa/src/texstore.c b/xc/extras/Mesa/src/texstore.c index 2285c4663..62768c598 100644 --- a/xc/extras/Mesa/src/texstore.c +++ b/xc/extras/Mesa/src/texstore.c @@ -1,8 +1,7 @@ -/* $Id: texstore.c,v 1.1.1.1 2002/10/22 13:05:22 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.4 + * Version: 5.0.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -29,12 +28,38 @@ * Brian Paul */ +/* + * The GL texture image functions in teximage.c basically just do + * error checking and data structure allocation. They in turn call + * device driver functions which actually copy/convert/store the user's + * texture image data. + * + * However, most device drivers will be able to use the fallback functions + * in this file. That is, most drivers will have the following bit of + * code: + * ctx->Driver.TexImage1D = _mesa_store_teximage1d; + * ctx->Driver.TexImage2D = _mesa_store_teximage2d; + * ctx->Driver.TexImage3D = _mesa_store_teximage3d; + * etc... + * + * Texture image processing is actually kind of complicated. We have to do: + * Format/type conversions + * pixel unpacking + * pixel transfer (scale, bais, lookup, convolution!, etc) + * + * These functions can handle most everything, including processing full + * images and sub-images. + */ + + +#include "glheader.h" #include "colormac.h" #include "context.h" #include "convolve.h" #include "image.h" #include "macros.h" -#include "mem.h" +#include "imports.h" +#include "texcompress.h" #include "texformat.h" #include "teximage.h" #include "texstore.h" @@ -46,9 +71,6 @@ * 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. - * - * GH: Do we really need this? We have the number of bytes per texel - * in the texture format structures, so why don't we just use that? */ static GLint components_in_intformat( GLint format ) @@ -115,6 +137,8 @@ components_in_intformat( GLint format ) case GL_DEPTH_COMPONENT24_SGIX: case GL_DEPTH_COMPONENT32_SGIX: return 1; + case GL_YCBCR_MESA: + return 2; /* Y + (Cb or Cr) */ default: return -1; /* error */ } @@ -127,7 +151,8 @@ components_in_intformat( GLint format ) * We also take care of all image transfer operations here, including * convolution, scale/bias, colortables, etc. * - * The destination texel channel type is always GLchan. + * The destination texel type is always GLchan. + * The destination texel format is one of the 6 basic types. * * A hardware driver may use this as a helper routine to unpack and * apply pixel transfer ops into a temporary image buffer. Then, @@ -135,8 +160,8 @@ components_in_intformat( GLint format ) * * Input: * dimensions - 1, 2, or 3 - * texFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA, - * GL_RGB or GL_RGBA + * texDestFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA, + * GL_RGB or GL_RGBA (the destination format) * texDestAddr - destination image address * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images * dstXoffset, dstYoffset, dstZoffset - position to store the image within @@ -162,6 +187,12 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions, ASSERT(ctx); ASSERT(dimensions >= 1 && dimensions <= 3); + ASSERT(texDestFormat == GL_LUMINANCE || + texDestFormat == GL_INTENSITY || + texDestFormat == GL_LUMINANCE_ALPHA || + texDestFormat == GL_ALPHA || + texDestFormat == GL_RGB || + texDestFormat == GL_RGBA); ASSERT(texDestAddr); ASSERT(srcWidth >= 1); ASSERT(srcHeight >= 1); @@ -255,6 +286,26 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions, dest += dstImageStride; } } + else if (texDestFormat == GL_YCBCR_MESA) { + /* YCbCr texture */ + GLint img, row; + GLushort *dest = (GLushort *) texDestAddr + + dstZoffset * (dstImageStride / sizeof(GLushort)) + + dstYoffset * (dstRowStride / sizeof(GLushort)) + + dstXoffset * texComponents; + ASSERT(ctx->Extensions.MESA_ycbcr_texture); + for (img = 0; img < srcDepth; img++) { + GLushort *destRow = dest; + for (row = 0; row < srcHeight; row++) { + const GLvoid *srcRow = _mesa_image_address(srcPacking, + srcAddr, srcWidth, srcHeight, + srcFormat, srcType, img, row, 0); + MEMCPY(destRow, srcRow, srcWidth * sizeof(GLushort)); + destRow += (dstRowStride / sizeof(GLushort)); + } + dest += dstImageStride / sizeof(GLushort); + } + } else if (texDestFormat == GL_DEPTH_COMPONENT) { /* Depth texture (shadow maps) */ GLint img, row; @@ -422,6 +473,12 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions, GLint postConvWidth = srcWidth, postConvHeight = srcHeight; assert(baseInternalFormat > 0); + ASSERT(baseInternalFormat == GL_LUMINANCE || + baseInternalFormat == GL_INTENSITY || + baseInternalFormat == GL_LUMINANCE_ALPHA || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_RGBA); if (transferOps & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth, @@ -604,12 +661,86 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions, } + +/** + * Given a user's uncompressed texture image, this function takes care of + * pixel unpacking, pixel transfer, format conversion and compression. + */ +static void +transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum srcFormat, GLenum srcType, + const struct gl_pixelstore_attrib *unpacking, + const GLvoid *source, + const struct gl_texture_format *dstFormat, + GLubyte *dest, + GLint dstRowStride) +{ + GLchan *tempImage = NULL; + GLint srcRowStride; + GLenum baseFormat; + + ASSERT(dimensions == 2); + /* TexelBytes is zero if and only if it's a compressed format */ + ASSERT(dstFormat->TexelBytes == 0); + + baseFormat = dstFormat->BaseFormat; + + if (srcFormat != baseFormat || srcType != CHAN_TYPE || + ctx->_ImageTransferState != 0 || unpacking->SwapBytes) { + /* need to convert user's image to texImage->Format, GLchan */ + GLint comps = components_in_intformat(baseFormat); + GLint postConvWidth = width, postConvHeight = height; + + /* XXX convolution untested */ + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { + _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth, + &postConvHeight); + } + + tempImage = (GLchan*) MALLOC(width * height * comps * sizeof(GLchan)); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + return; + } + transfer_teximage(ctx, dimensions, + baseFormat, /* dest format */ + tempImage, /* dst address */ + width, height, depth, /* src size */ + 0, 0, 0, /* x/y/zoffset */ + comps * width, /* dst row stride */ + comps * width * height, /* dst image stride */ + srcFormat, srcType, /* src format, type */ + source, unpacking, /* src and src packing */ + ctx->_ImageTransferState); + source = tempImage; + width = postConvWidth; + height = postConvHeight; + srcRowStride = width; + } + else { + if (unpacking->RowLength) + srcRowStride = unpacking->RowLength; + else + srcRowStride = width; + } + + _mesa_compress_teximage(ctx, width, height, baseFormat, + (const GLchan *) source, srcRowStride, + dstFormat, dest, dstRowStride); + if (tempImage) { + FREE(tempImage); + } +} + + + /* - * This is the software fallback for Driver.TexImage1D(). + * This is the software fallback for Driver.TexImage1D() + * and Driver.CopyTexImage2D(). * The texture image type will be GLchan. * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY, * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA. - * */ void _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, @@ -636,52 +767,55 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, texelBytes = texImage->TexFormat->TexelBytes; - /* Compute image size, in bytes */ - if (texImage->IsCompressed) { - assert(ctx->Driver.CompressedTextureSize); - sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage); - assert(sizeInBytes > 0); - texImage->CompressedSize = sizeInBytes; - } - else { - sizeInBytes = postConvWidth * texelBytes; - } - /* allocate memory */ + if (texImage->IsCompressed) + sizeInBytes = texImage->CompressedSize; + else + sizeInBytes = postConvWidth * texelBytes; texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); return; } - if (pixels) { - /* unpack image, apply transfer ops and store in texImage->Data */ + if (!pixels) + return; + + /* unpack image, apply transfer ops and store in texImage->Data */ + if (texImage->IsCompressed) { + GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + width); + transfer_compressed_teximage(ctx, 1, width, 1, 1, + format, type, packing, + pixels, texImage->TexFormat, + (GLubyte *) texImage->Data, dstRowStride); + } + else { _mesa_transfer_teximage(ctx, 1, - _mesa_base_tex_format(ctx, internalFormat), + texImage->Format, /* base format */ texImage->TexFormat, texImage->Data, - width, 1, 1, 0, 0, 0, + width, 1, 1, /* src size */ + 0, 0, 0, /* dstX/Y/Zoffset */ 0, /* dstRowStride */ 0, /* dstImageStride */ format, type, pixels, packing); + } - /* GL_SGIS_generate_mipmap */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); } } /* - * This is the software fallback for Driver.TexImage2D(). + * This is the software fallback for Driver.TexImage2D() + * and Driver.CopyTexImage2D(). * The texture image type will be GLchan. * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY, * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA. - * - * NOTE: if real texture compression is supported, this whole function - * will need to be overridden. */ void _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, @@ -709,51 +843,56 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, texelBytes = texImage->TexFormat->TexelBytes; - /* Compute image size, in bytes */ - if (texImage->IsCompressed) { - assert(ctx->Driver.CompressedTextureSize); - sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage); - assert(sizeInBytes > 0); - texImage->CompressedSize = sizeInBytes; - } - else { - sizeInBytes = postConvWidth * postConvHeight * texelBytes; - } - /* allocate memory */ + if (texImage->IsCompressed) + sizeInBytes = texImage->CompressedSize; + else + sizeInBytes = postConvWidth * postConvHeight * texelBytes; texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } - if (pixels) { - /* unpack image, apply transfer ops and store in texImage->Data */ + if (!pixels) + return; + + /* unpack image, apply transfer ops and store in texImage->Data */ + if (texImage->IsCompressed) { + GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + width); + transfer_compressed_teximage(ctx, 2, width, height, 1, + format, type, packing, + pixels, texImage->TexFormat, + (GLubyte *) texImage->Data, dstRowStride); + } + else { _mesa_transfer_teximage(ctx, 2, - _mesa_base_tex_format(ctx, internalFormat), + texImage->Format, texImage->TexFormat, texImage->Data, - width, height, 1, 0, 0, 0, - texImage->Width * texelBytes, + width, height, 1, /* src size */ + 0, 0, 0, /* dstX/Y/Zoffset */ + texImage->Width * texelBytes, /* dstRowStride */ 0, /* dstImageStride */ format, type, pixels, packing); + } - /* GL_SGIS_generate_mipmap */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); } } /* - * This is the software fallback for Driver.TexImage3D(). + * This is the software fallback for Driver.TexImage3D() + * and Driver.CopyTexImage3D(). * The texture image type will be GLchan. * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY, * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA. - * */ void _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, @@ -775,40 +914,45 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, texelBytes = texImage->TexFormat->TexelBytes; - /* Compute image size, in bytes */ - if (texImage->IsCompressed) { - assert(ctx->Driver.CompressedTextureSize); - sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage); - assert(sizeInBytes > 0); - texImage->CompressedSize = sizeInBytes; - } - else { - sizeInBytes = width * height * depth * texelBytes; - } - /* allocate memory */ + if (texImage->IsCompressed) + sizeInBytes = texImage->CompressedSize; + else + sizeInBytes = width * height * depth * texelBytes; texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); return; } - if (pixels) { - /* unpack image, apply transfer ops and store in texImage->Data */ + if (!pixels) + return; + + /* unpack image, apply transfer ops and store in texImage->Data */ + if (texImage->IsCompressed) { + GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + width); + transfer_compressed_teximage(ctx, 3, width, height, depth, + format, type, packing, + pixels, texImage->TexFormat, + (GLubyte *) texImage->Data, dstRowStride); + } + else { _mesa_transfer_teximage(ctx, 3, - _mesa_base_tex_format(ctx, internalFormat), + texImage->Format, texImage->TexFormat, texImage->Data, - width, height, depth, 0, 0, 0, - texImage->Width * texelBytes, + width, height, depth, /* src size */ + 0, 0, 0, /* dstX/Y/Zoffset */ + texImage->Width * texelBytes, /* dstRowStride */ texImage->Width * texImage->Height * texelBytes, format, type, pixels, packing); + } - /* GL_SGIS_generate_mipmap */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); } } @@ -816,7 +960,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, /* - * This is the software fallback for Driver.TexSubImage1D(). + * This is the software fallback for Driver.TexSubImage1D() + * and Driver.CopyTexSubImage1D(). */ void _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, @@ -826,25 +971,45 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - _mesa_transfer_teximage(ctx, 1, - _mesa_base_tex_format(ctx, texImage->IntFormat), - texImage->TexFormat, texImage->Data, - width, 1, 1, /* src size */ - xoffset, 0, 0, /* dest offsets */ - 0, /* dstRowStride */ - 0, /* dstImageStride */ - format, type, pixels, packing); + if (texImage->IsCompressed) { + GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + GLubyte *dest = _mesa_compressed_image_address(xoffset, 0, 0, + texImage->IntFormat, + texImage->Width, + texImage->Data); + transfer_compressed_teximage(ctx, 1, /* dimensions */ + width, 1, 1, /* size to replace */ + format, type, /* source format/type */ + packing, /* source packing */ + pixels, /* source data */ + texImage->TexFormat,/* dest format */ + dest, dstRowStride); + } + else { + _mesa_transfer_teximage(ctx, 1, + texImage->Format, + texImage->TexFormat, texImage->Data, + width, 1, 1, /* src size */ + xoffset, 0, 0, /* dest offsets */ + 0, /* dstRowStride */ + 0, /* dstImageStride */ + format, type, pixels, packing); + } /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } } + /* - * This is the software fallback for Driver.TexSubImage2D(). + * This is the software fallback for Driver.TexSubImage2D() + * and Driver.CopyTexSubImage2D(). */ void _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, @@ -855,18 +1020,36 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - _mesa_transfer_teximage(ctx, 2, - _mesa_base_tex_format(ctx, texImage->IntFormat), - texImage->TexFormat, texImage->Data, - width, height, 1, /* src size */ - xoffset, yoffset, 0, /* dest offsets */ - texImage->Width * texImage->TexFormat->TexelBytes, - 0, /* dstImageStride */ - format, type, pixels, packing); + if (texImage->IsCompressed) { + GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, 0, + texImage->IntFormat, + texImage->Width, + texImage->Data); + transfer_compressed_teximage(ctx, 2, /* dimensions */ + width, height, 1, /* size to replace */ + format, type, /* source format/type */ + packing, /* source packing */ + pixels, /* source data */ + texImage->TexFormat,/* dest format */ + dest, dstRowStride); + } + else { + _mesa_transfer_teximage(ctx, 2, + texImage->Format, + texImage->TexFormat, texImage->Data, + width, height, 1, /* src size */ + xoffset, yoffset, 0, /* dest offsets */ + texImage->Width *texImage->TexFormat->TexelBytes, + 0, /* dstImageStride */ + format, type, pixels, packing); + } /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } } @@ -874,6 +1057,7 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, /* * This is the software fallback for Driver.TexSubImage3D(). + * and Driver.CopyTexSubImage3D(). */ void _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, @@ -884,18 +1068,37 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLint texelBytes = texImage->TexFormat->TexelBytes; - _mesa_transfer_teximage(ctx, 3, - _mesa_base_tex_format(ctx, texImage->IntFormat), + if (texImage->IsCompressed) { + GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, zoffset, + texImage->IntFormat, + texImage->Width, + texImage->Data); + transfer_compressed_teximage(ctx, 3, /* dimensions */ + width, height, depth,/* size to replace */ + format, type, /* source format/type */ + packing, /* source packing */ + pixels, /* source data */ + texImage->TexFormat,/* dest format */ + dest, dstRowStride); + } + else { + const GLint texelBytes = texImage->TexFormat->TexelBytes; + _mesa_transfer_teximage(ctx, 3, + texImage->Format, texImage->TexFormat, texImage->Data, width, height, depth, /* src size */ xoffset, yoffset, xoffset, /* dest offsets */ - texImage->Width * texelBytes, + texImage->Width * texelBytes, /* dst row stride */ texImage->Width * texImage->Height * texelBytes, format, type, pixels, packing); + } + /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } } @@ -914,9 +1117,7 @@ _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - /* Nothing here. - * The device driver has to do it all. - */ + /* this space intentionally left blank */ } @@ -932,9 +1133,33 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - /* Nothing here. - * The device driver has to do it all. + /* This is pretty simple, basically just do a memcpy without worrying + * about the usual image unpacking or image transfer operations. */ + ASSERT(texObj); + ASSERT(texImage); + ASSERT(texImage->Width > 0); + ASSERT(texImage->Height > 0); + ASSERT(texImage->Depth == 1); + ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */ + + /* choose the texture format */ + assert(ctx->Driver.ChooseTextureFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, 0, 0); + assert(texImage->TexFormat); + texImage->FetchTexel = texImage->TexFormat->FetchTexel2D; + + /* allocate storage */ + texImage->Data = MESA_PBUFFER_ALLOC(imageSize); + if (!texImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); + return; + } + + /* copy the data */ + ASSERT(texImage->CompressedSize == imageSize); + MEMCPY(texImage->Data, data, imageSize); } @@ -951,31 +1176,90 @@ _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - /* Nothing here. - * The device driver has to do it all. - */ + /* this space intentionally left blank */ } -/* - * Fallback for Driver.GetCompressedTexImage3D() - * This will probably work find for hardware drivers. That is, hardware - * drivers won't have to override this function, unless the compressed - * texture must first be fetched from the TRAM. +/** + * Fallback for Driver.CompressedTexSubImage1D() */ void -_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, - GLint level, void *image, - const struct gl_texture_object *texObj, - struct gl_texture_image *texImage) +_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLsizei width, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) { - assert(texImage->IsCompressed); - assert(texImage->CompressedSize > 0); - MEMCPY(image, texImage->Data, texImage->CompressedSize); + /* this space intentionally left blank */ } +/** + * Fallback for Driver.CompressedTexSubImage2D() + */ +void +_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + GLint bytesPerRow, destRowStride, srcRowStride; + GLint i, rows; + GLubyte *dest; + const GLubyte *src; + + /* these should have been caught sooner */ + ASSERT((width & 3) == 0 || width == 2 || width == 1); + ASSERT((height & 3) == 0 || height == 2 || height == 1); + ASSERT((xoffset & 3) == 0); + ASSERT((yoffset & 3) == 0); + + srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width); + src = (const GLubyte *) data; + + destRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + dest = _mesa_compressed_image_address(xoffset, yoffset, 0, + texImage->IntFormat, + texImage->Width, texImage->Data); + + bytesPerRow = srcRowStride; + rows = height / 4; + + for (i = 0; i < rows; i++) { + MEMCPY(dest, src, bytesPerRow); + dest += destRowStride; + src += srcRowStride; + } +} + + +/** + * Fallback for Driver.CompressedTexSubImage3D() + */ +void +_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + /* this space intentionally left blank */ +} + + + + /* * This is the fallback for Driver.TestProxyTexImage(). @@ -1470,7 +1754,7 @@ make_3d_mipmap(const struct gl_texture_format *format, GLint border, */ /* - printf("mip3d %d x %d x %d -> %d x %d x %d\n", + _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n", srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); */ @@ -1603,53 +1887,74 @@ make_3d_mipmap(const struct gl_texture_format *format, GLint border, * Stop at texObj's MaxLevel or when we get to the 1x1 texture. */ void -_mesa_generate_mipmap(GLcontext *ctx, +_mesa_generate_mipmap(GLcontext *ctx, GLenum target, const struct gl_texture_unit *texUnit, struct gl_texture_object *texObj) { - const GLenum targets1D[] = { GL_TEXTURE_1D, 0 }; - const GLenum targets2D[] = { GL_TEXTURE_2D, 0 }; - const GLenum targets3D[] = { GL_TEXTURE_3D, 0 }; - const GLenum targetsCube[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, - 0 }; - const GLenum targetsRect[] = { GL_TEXTURE_RECTANGLE_NV, 0 }; - const GLenum *targets; - GLint level; - GLint maxLevels = 0; + const struct gl_texture_image *srcImage; + const struct gl_texture_format *convertFormat; + const GLubyte *srcData; + GLubyte *dstData; + GLint level, maxLevels; ASSERT(texObj); - ASSERT(texObj->Image[texObj->BaseLevel]); - - switch (texObj->Target) { - case GL_TEXTURE_1D: - targets = targets1D; - maxLevels = ctx->Const.MaxTextureLevels; - break; - case GL_TEXTURE_2D: - targets = targets2D; - maxLevels = ctx->Const.MaxTextureLevels; - break; - case GL_TEXTURE_3D: - targets = targets3D; - maxLevels = ctx->Const.Max3DTextureLevels; - break; - case GL_TEXTURE_CUBE_MAP_ARB: - targets = targetsCube; - maxLevels = ctx->Const.MaxCubeTextureLevels; - break; - case GL_TEXTURE_RECTANGLE_NV: - targets = targetsRect; - maxLevels = 1; - break; - default: - _mesa_problem(ctx, - "Bad texture object dimension in _mesa_generate_mipmaps"); - return; + srcImage = texObj->Image[texObj->BaseLevel]; + ASSERT(srcImage); + + maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); + ASSERT(maxLevels > 0); /* bad target */ + + /* Find convertFormat - the format that do_row() will process */ + if (srcImage->IsCompressed) { + /* setup for compressed textures */ + GLuint row; + GLint components, size; + GLchan *dst; + + assert(texObj->Target == GL_TEXTURE_2D); + + if (srcImage->Format == GL_RGB) { + convertFormat = &_mesa_texformat_rgb; + components = 3; + } + else if (srcImage->Format == GL_RGBA) { + convertFormat = &_mesa_texformat_rgba; + components = 4; + } + else { + _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps"); + return; + } + + /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ + size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE) + * srcImage->Width * srcImage->Height * srcImage->Depth + 20; + /* 20 extra bytes, just be safe when calling last FetchTexel */ + srcData = MALLOC(size); + if (!srcData) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + return; + } + dstData = MALLOC(size / 2); /* 1/4 would probably be OK */ + if (!dstData) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + FREE((void *) srcData); + return; + } + + /* decompress base image here */ + dst = (GLchan *) srcData; + for (row = 0; row < srcImage->Height; row++) { + GLuint col; + for (col = 0; col < srcImage->Width; col++) { + (*srcImage->FetchTexel)(srcImage, col, row, 0, (GLvoid *) dst); + dst += components; + } + } + } + else { + /* uncompressed */ + convertFormat = srcImage->TexFormat; } for (level = texObj->BaseLevel; level < texObj->MaxLevel @@ -1660,15 +1965,14 @@ _mesa_generate_mipmap(GLcontext *ctx, GLint srcWidth, srcHeight, srcDepth; GLint dstWidth, dstHeight, dstDepth; GLint border, bytesPerTexel; - GLint t; - srcImage = texObj->Image[level]; + /* get src image parameters */ + srcImage = _mesa_select_tex_image(ctx, texUnit, target, level); ASSERT(srcImage); srcWidth = srcImage->Width; srcHeight = srcImage->Height; srcDepth = srcImage->Depth; border = srcImage->Border; - bytesPerTexel = srcImage->TexFormat->TexelBytes; /* compute next (level+1) image size */ if (srcWidth - 2 * border > 1) { @@ -1694,65 +1998,88 @@ _mesa_generate_mipmap(GLcontext *ctx, dstHeight == srcHeight && dstDepth == srcDepth) { /* all done */ + if (srcImage->IsCompressed) { + FREE((void *) srcData); + FREE(dstData); + } return; } - /* Need this loop just because of cubemaps */ - for (t = 0; targets[t]; t++) { - ASSERT(t < 6); - - dstImage = _mesa_select_tex_image(ctx, texUnit, targets[t], level+1); + /* get dest gl_texture_image */ + dstImage = _mesa_select_tex_image(ctx, texUnit, target, level+1); + if (!dstImage) { + dstImage = _mesa_alloc_texture_image(); if (!dstImage) { - dstImage = _mesa_alloc_texture_image(); - if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - _mesa_set_tex_image(texObj, targets[t], level + 1, dstImage); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; } + _mesa_set_tex_image(texObj, target, level + 1, dstImage); + } - /* Free old image data */ - if (dstImage->Data) - MESA_PBUFFER_FREE(dstImage->Data); - - /* initialize new image */ - _mesa_init_teximage_fields(ctx, t, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->Format); - dstImage->DriverData = NULL; - dstImage->TexFormat = srcImage->TexFormat; - dstImage->FetchTexel = srcImage->FetchTexel; - ASSERT(dstImage->TexFormat); - ASSERT(dstImage->FetchTexel); - + /* Free old image data */ + if (dstImage->Data) + MESA_PBUFFER_FREE(dstImage->Data); + + /* initialize new image */ + _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, + dstDepth, border, srcImage->IntFormat); + dstImage->DriverData = NULL; + dstImage->TexFormat = srcImage->TexFormat; + dstImage->FetchTexel = srcImage->FetchTexel; + ASSERT(dstImage->TexFormat); + ASSERT(dstImage->FetchTexel); + + /* Alloc new teximage data buffer. + * Setup src and dest data pointers. + */ + if (dstImage->IsCompressed) { + ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/ + dstImage->Data = MESA_PBUFFER_ALLOC(dstImage->CompressedSize); + if (!dstImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + /* srcData and dstData are already set */ + ASSERT(srcData); + ASSERT(dstData); + } + else { + bytesPerTexel = srcImage->TexFormat->TexelBytes; ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0); - - /* alloc new image buffer */ dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth - * bytesPerTexel); + * bytesPerTexel); if (!dstImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); return; } + srcData = (const GLubyte *) srcImage->Data; + dstData = (GLubyte *) dstImage->Data; + } - /* - * We use simple 2x2 averaging to compute the next mipmap level. - */ - switch (texObj->Target) { + /* + * We use simple 2x2 averaging to compute the next mipmap level. + */ + switch (target) { case GL_TEXTURE_1D: - make_1d_mipmap(srcImage->TexFormat, border, - srcWidth, (const GLubyte *) srcImage->Data, - dstWidth, (GLubyte *) dstImage->Data); + make_1d_mipmap(convertFormat, border, + srcWidth, srcData, + dstWidth, dstData); break; case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP_ARB: - make_2d_mipmap(srcImage->TexFormat, border, - srcWidth, srcHeight, (const GLubyte *) srcImage->Data, - dstWidth, dstHeight, (GLubyte *) dstImage->Data); + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + make_2d_mipmap(convertFormat, border, + srcWidth, srcHeight, srcData, + dstWidth, dstHeight, dstData); break; case GL_TEXTURE_3D: - make_3d_mipmap(srcImage->TexFormat, border, - srcWidth, srcHeight, srcDepth, (const GLubyte *) srcImage->Data, - dstWidth, dstHeight, dstDepth, (GLubyte *) dstImage->Data); + make_3d_mipmap(convertFormat, border, + srcWidth, srcHeight, srcDepth, srcData, + dstWidth, dstHeight, dstDepth, dstData); break; case GL_TEXTURE_RECTANGLE_NV: /* no mipmaps, do nothing */ @@ -1760,7 +2087,29 @@ _mesa_generate_mipmap(GLcontext *ctx, default: _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps"); return; - } - } /* loop over tex image targets */ - } /* loop over tex levels */ + } + + if (dstImage->IsCompressed) { + GLubyte *temp; + /* compress image from dstData into dstImage->Data */ + const GLenum srcFormat = convertFormat->BaseFormat; + GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat, + dstWidth); + ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); + _mesa_compress_teximage(ctx, + dstWidth, dstHeight, /* size */ + srcFormat, /* source format */ + dstData, /* source buffer */ + dstWidth, /* source row stride */ + dstImage->TexFormat, /* dest format */ + dstImage->Data, /* dest buffer */ + dstRowStride ); /* dest row stride */ + + /* swap src and dest pointers */ + temp = (GLubyte *) srcData; + srcData = dstData; + dstData = temp; + } + + } /* loop over mipmap levels */ } |