summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/texstore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/texstore.c')
-rw-r--r--src/mesa/main/texstore.c134
1 files changed, 101 insertions, 33 deletions
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
index ef4a75916bb..bfa23018cf7 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -1,4 +1,4 @@
-/* $Id: texstore.c,v 1.23 2001/04/04 22:41:23 brianp Exp $ */
+/* $Id: texstore.c,v 1.24 2001/04/20 16:46:04 brianp Exp $ */
/*
* Mesa 3-D graphics library
@@ -29,15 +29,6 @@
* Brian Paul
*/
-
-/*
- * The functions in this file are mostly related to software texture fallbacks.
- * This includes texture image transfer/packing and texel fetching.
- * Hardware drivers will likely override most of this.
- */
-
-
-
#include "colormac.h"
#include "context.h"
#include "convolve.h"
@@ -154,6 +145,7 @@ components_in_intformat( GLint format )
* srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
* srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
* srcPacking - describes packing of incoming image.
+ * transferOps - mask of pixel transfer operations
*/
static void
transfer_teximage(GLcontext *ctx, GLuint dimensions,
@@ -163,7 +155,8 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
GLint dstRowStride, GLint dstImageStride,
GLenum srcFormat, GLenum srcType,
const GLvoid *srcAddr,
- const struct gl_pixelstore_attrib *srcPacking)
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLuint transferOps)
{
GLint texComponents;
@@ -184,7 +177,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
texComponents = components_in_intformat(texDestFormat);
/* try common 2D texture cases first */
- if (!ctx->_ImageTransferState && dimensions == 2 && srcType == CHAN_TYPE) {
+ if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
if (srcFormat == texDestFormat) {
/* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
@@ -253,8 +246,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
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);
+ srcType, src, srcPacking, transferOps);
destRow += dstRowStride;
}
dest += dstImageStride;
@@ -314,7 +306,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
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,
+ transferOps & IMAGE_PRE_CONVOLUTION_BITS,
GL_TRUE);
dstf += srcWidth * 4;
}
@@ -345,7 +337,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
(const GLfloat (*)[4]) srcf,
texDestFormat, CHAN_TYPE,
dest, &_mesa_native_packing,
- ctx->_ImageTransferState
+ transferOps
& IMAGE_POST_CONVOLUTION_BITS);
srcf += convWidth * 4;
dest += dstRowStride;
@@ -371,7 +363,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
srcFormat, srcType, img, row, 0);
_mesa_unpack_chan_color_span(ctx, srcWidth, texDestFormat,
destRow, srcFormat, srcType, srcRow,
- srcPacking, ctx->_ImageTransferState);
+ srcPacking, transferOps);
destRow += dstRowStride;
}
dest += dstImageStride;
@@ -387,8 +379,18 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
* needed image transfer operations and storing the result in the format
* specified by <dstFormat>. <dstFormat> may be any format from texformat.h.
* Input:
+ * dimensions - 1, 2 or 3
+ * baseInternalFormat - base format of the internal texture format
+ * specified by the user. This is very important, see below.
+ * dstFormat - destination image format
+ * dstAddr - destination address
+ * srcWidth, srcHeight, srcDepth - size of source iamge
+ * dstX/Y/Zoffset - as specified by glTexSubImage
* dstRowStride - stride between dest rows in bytes
* dstImagetride - stride between dest images in bytes
+ * srcFormat, srcType - incoming image format and datatype
+ * srcAddr - source image address
+ * srcPacking - packing params of source image
*
* XXX this function is a bit more complicated than it should be. If
* _mesa_convert_texsubimage[123]d could handle any dest/source formats
@@ -397,6 +399,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
*/
void
_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
+ GLenum baseInternalFormat,
const struct gl_texture_format *dstFormat,
GLvoid *dstAddr,
GLint srcWidth, GLint srcHeight, GLint srcDepth,
@@ -409,10 +412,56 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
GLboolean makeTemp;
+ GLuint transferOps = ctx->_ImageTransferState;
+ GLboolean freeSourceData = GL_FALSE;
+ GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
+
+ if (transferOps & IMAGE_CONVOLUTION_BIT) {
+ _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
+ &postConvHeight);
+ }
+
+ /*
+ * Consider this scenario: The user's source image is GL_RGB and the
+ * requested internal format is GL_LUMINANCE. Now suppose the device
+ * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
+ * texture format. In that case we still need to do an intermediate
+ * conversion to luminance format so that the incoming red channel gets
+ * replicated into the dest red, green and blue channels. The following
+ * code takes care of that.
+ */
+ if (dstFormat->BaseFormat != baseInternalFormat) {
+ /* Allocate storage for temporary image in the baseInternalFormat */
+ const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
+ * sizeof(GLchan);
+ const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
+ const GLint tmpRowStride = texelSize * postConvWidth;
+ const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
+ GLvoid *tmpImage = MALLOC(bytes);
+ if (!tmpImage)
+ return;
+ transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
+ srcWidth, srcHeight, srcDepth,
+ 0, 0, 0, /* x/y/zoffset */
+ tmpRowStride, tmpImgStride,
+ srcFormat, srcType, srcAddr, srcPacking, transferOps);
+
+ /* this is our new source image */
+ srcWidth = postConvWidth;
+ srcHeight = postConvHeight;
+ srcFormat = baseInternalFormat;
+ srcType = CHAN_TYPE;
+ srcAddr = tmpImage;
+ srcPacking = &_mesa_native_packing;
+ freeSourceData = GL_TRUE;
+ transferOps = 0; /* image transfer ops were completed */
+ }
- /* First, determine if need to make a temporary, intermediate image */
+ /* Let the optimized tex conversion functions take a crack at the
+ * image conversion if the dest format is a h/w format.
+ */
if (_mesa_is_hardware_tex_format(dstFormat)) {
- if (ctx->_ImageTransferState) {
+ if (transferOps) {
makeTemp = GL_TRUE;
}
else {
@@ -444,6 +493,8 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
}
if (!makeTemp) {
/* all done! */
+ if (freeSourceData)
+ FREE((void *) srcAddr);
return;
}
}
@@ -460,26 +511,32 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
GLint tmpRowStride, tmpImageStride;
GLubyte *tmpImage;
- if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+ if (transferOps & IMAGE_CONVOLUTION_BIT) {
_mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
&postConvHeight);
}
- tmpFormat = _mesa_base_tex_format(ctx, dstFormat->IntFormat);
+ tmpFormat = dstFormat->BaseFormat;
tmpComps = _mesa_components_in_format(tmpFormat);
tmpTexelSize = tmpComps * sizeof(GLchan);
tmpRowStride = postConvWidth * tmpTexelSize;
tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
srcDepth * tmpTexelSize);
- if (!tmpImage)
+ if (!tmpImage) {
+ if (freeSourceData)
+ FREE((void *) srcAddr);
return;
+ }
transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
srcWidth, srcHeight, srcDepth,
0, 0, 0, /* x/y/zoffset */
tmpRowStride, tmpImageStride,
- srcFormat, srcType, srcAddr, srcPacking);
+ srcFormat, srcType, srcAddr, srcPacking, transferOps);
+
+ if (freeSourceData)
+ FREE((void *) srcAddr);
/* the temp image is our new source image */
srcWidth = postConvWidth;
@@ -488,6 +545,7 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
srcType = CHAN_TYPE;
srcAddr = tmpImage;
srcPacking = &_mesa_native_packing;
+ freeSourceData = GL_TRUE;
}
if (_mesa_is_hardware_tex_format(dstFormat)) {
@@ -523,18 +581,19 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
srcPacking, srcAddr, dstAddr);
assert(b);
}
- FREE((void *) srcAddr); /* the temp image */
}
else {
/* software format */
- GLenum dstBaseFormat = _mesa_base_tex_format(ctx, dstFormat->IntFormat);
assert(!makeTemp);
- transfer_teximage(ctx, dimensions, dstBaseFormat, dstAddr,
+ transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
srcWidth, srcHeight, srcDepth,
dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
- srcFormat, srcType, srcAddr, srcPacking);
+ srcFormat, srcType, srcAddr, srcPacking, transferOps);
}
+
+ if (freeSourceData)
+ FREE((void *) srcAddr); /* the temp image */
}
@@ -577,7 +636,8 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
}
/* unpack image, apply transfer ops and store in texImage->Data */
- _mesa_transfer_teximage(ctx, 1, texImage->TexFormat, texImage->Data,
+ _mesa_transfer_teximage(ctx, 1, _mesa_base_tex_format(ctx, internalFormat),
+ texImage->TexFormat, texImage->Data,
width, 1, 1, 0, 0, 0,
0, /* dstRowStride */
0, /* dstImageStride */
@@ -625,7 +685,8 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
}
/* unpack image, apply transfer ops and store in texImage->Data */
- _mesa_transfer_teximage(ctx, 2, texImage->TexFormat, texImage->Data,
+ _mesa_transfer_teximage(ctx, 2, _mesa_base_tex_format(ctx, internalFormat),
+ texImage->TexFormat, texImage->Data,
width, height, 1, 0, 0, 0,
texImage->Width * texelBytes,
0, /* dstImageStride */
@@ -668,7 +729,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
}
/* unpack image, apply transfer ops and store in texImage->Data */
- _mesa_transfer_teximage(ctx, 3, texImage->TexFormat, texImage->Data,
+ _mesa_transfer_teximage(ctx, 3, _mesa_base_tex_format(ctx, internalFormat),
+ texImage->TexFormat, texImage->Data,
width, height, depth, 0, 0, 0,
texImage->Width * texelBytes,
texImage->Width * texImage->Height * texelBytes,
@@ -689,7 +751,9 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- _mesa_transfer_teximage(ctx, 1, texImage->TexFormat, texImage->Data,
+ _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 */
@@ -710,7 +774,9 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- _mesa_transfer_teximage(ctx, 2, texImage->TexFormat, texImage->Data,
+ _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,
@@ -732,7 +798,9 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_image *texImage)
{
const GLint texelBytes = texImage->TexFormat->TexelBytes;
- _mesa_transfer_teximage(ctx, 3, texImage->TexFormat, texImage->Data,
+ _mesa_transfer_teximage(ctx, 3,
+ _mesa_base_tex_format(ctx, texImage->IntFormat),
+ texImage->TexFormat, texImage->Data,
width, height, depth, /* src size */
xoffset, yoffset, xoffset, /* dest offsets */
texImage->Width * texelBytes,