-/* $Id: texformat.c,v 1.7 2001/03/30 14:44:43 gareth Exp $ */
+/* $Id: texformat.c,v 1.8 2001/04/04 21:54:21 brianp Exp $ */
/*
* Mesa 3-D graphics library
+GLboolean
+_mesa_is_hardware_tex_format( const struct gl_texture_format *format )
+{
+ return (format->MesaFormat < MESA_FORMAT_RGBA);
+}
+
+
/* Given an internal texture format or 1, 2, 3, 4 initialize the texture
* image structure's default format and type information. Drivers will
* initialize these fields accordingly if they override the default
* storage format.
*/
-void _mesa_init_tex_format( GLcontext *ctx, GLenum internalFormat,
- struct gl_texture_image *texImage )
+const struct gl_texture_format *
+_mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
{
- const struct gl_texture_format *texFormat;
-
- /* Ask the driver for the base format, if it doesn't know, it will
- * return -1;
- */
- if ( ctx->Driver.BaseCompressedTexFormat ) {
- GLint format = 0; /* Silence compiler warning */
- format = (*ctx->Driver.BaseCompressedTexFormat)( ctx, format );
- if ( format >= 0 ) {
- internalFormat = format;
- }
- }
+ (void) format;
+ (void) type;
switch ( internalFormat ) {
/* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has
*/
case 4: /* Quake3 uses this... */
case GL_RGBA:
- texFormat = &_mesa_texformat_rgba;
- break;
+ return &_mesa_texformat_rgba;
case 3: /* ... and this. */
case GL_RGB:
- texFormat = &_mesa_texformat_rgb;
- break;
+ return &_mesa_texformat_rgb;
/* GH: Okay, keep checking as normal. Still test for GL_RGB,
* GL_RGBA formats first.
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
- texFormat = &_mesa_texformat_rgba;
- break;
+ return &_mesa_texformat_rgba;
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
- texFormat = &_mesa_texformat_rgb;
- break;
+ return &_mesa_texformat_rgb;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
- texFormat = &_mesa_texformat_alpha;
- break;
+ return &_mesa_texformat_alpha;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
- texFormat = &_mesa_texformat_luminance;
- break;
+ return &_mesa_texformat_luminance;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
- texFormat = &_mesa_texformat_luminance_alpha;
- break;
+ return &_mesa_texformat_luminance_alpha;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
- texFormat = &_mesa_texformat_intensity;
- break;
+ return &_mesa_texformat_intensity;
case GL_COLOR_INDEX:
case GL_COLOR_INDEX1_EXT:
case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX12_EXT:
case GL_COLOR_INDEX16_EXT:
- texFormat = &_mesa_texformat_color_index;
- break;
+ return &_mesa_texformat_color_index;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_SGIX:
case GL_DEPTH_COMPONENT32_SGIX:
if ( !ctx->Extensions.SGIX_depth_texture )
_mesa_problem( ctx, "depth format without GL_SGIX_depth_texture" );
- texFormat = &_mesa_texformat_depth_component;
- break;
+ return &_mesa_texformat_depth_component;
default:
- _mesa_problem( ctx, "unexpected format in _mesa_init_tex_format" );
- return;
+ _mesa_problem( ctx, "unexpected format in _mesa_choose_tex_format()" );
+ printf("intformat = %d %x\n", internalFormat, internalFormat );
+ return NULL;
}
-
- texImage->TexFormat = texFormat;
}
-/* $Id: texstore.c,v 1.21 2001/03/28 20:40:51 gareth Exp $ */
+/* $Id: texstore.c,v 1.22 2001/04/04 21:54:21 brianp Exp $ */
/*
* Mesa 3-D graphics library
#include "texformat.h"
#include "teximage.h"
#include "texstore.h"
+#include "texutil.h"
/*
* srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
* srcPacking - describes packing of incoming image.
*/
-void
-_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
- GLenum texDestFormat, GLvoid *texDestAddr,
- 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)
+static void
+transfer_teximage(GLcontext *ctx, GLuint dimensions,
+ GLenum texDestFormat, GLvoid *texDestAddr,
+ 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;
+/*
+ * Transfer a texture image from user space to <destAddr> applying all
+ * needed image transfer operations and storing the result in the format
+ * specified by <dstFormat>. <dstFormat> may be any format from texformat.h.
+ * Input:
+ * dstRowStride - stride between dest rows in bytes
+ * dstImagetride - stride between dest images in bytes
+ *
+ * XXX this function is a bit more complicated than it should be. If
+ * _mesa_convert_texsubimage[123]d could handle any dest/source formats
+ * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
+ * could simplify things here.
+ */
+void
+_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
+ const struct gl_texture_format *dstFormat,
+ GLvoid *dstAddr,
+ 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)
+{
+ const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
+ const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
+ GLboolean makeTemp;
+
+ /* First, determine if need to make a temporary, intermediate image */
+ if (_mesa_is_hardware_tex_format(dstFormat)) {
+ if (ctx->_ImageTransferState) {
+ makeTemp = GL_TRUE;
+ }
+ else {
+ if (dimensions == 1) {
+ makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
+ dstXoffset,
+ srcWidth,
+ srcFormat, srcType,
+ srcPacking, srcAddr,
+ dstAddr);
+ }
+ else if (dimensions == 2) {
+ makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
+ dstXoffset, dstYoffset,
+ srcWidth, srcHeight,
+ dstRowStridePixels,
+ srcFormat, srcType,
+ srcPacking, srcAddr,
+ dstAddr);
+ }
+ else {
+ assert(dimensions == 3);
+ makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
+ dstXoffset, dstYoffset, dstZoffset,
+ srcWidth, srcHeight, srcDepth,
+ dstRowStridePixels, dstImageStridePixels,
+ srcFormat, srcType,
+ srcPacking, srcAddr, dstAddr);
+ }
+ if (!makeTemp) {
+ /* all done! */
+ return;
+ }
+ }
+ }
+ else {
+ /* software texture format */
+ makeTemp = GL_FALSE;
+ }
+
+
+ if (makeTemp) {
+ GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
+ GLenum tmpFormat;
+ GLuint tmpComps, tmpTexelSize;
+ GLint tmpRowStride, tmpImageStride;
+ GLubyte *tmpImage;
+
+ if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+ _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
+ &postConvHeight);
+ }
+
+ tmpFormat = _mesa_base_tex_format(ctx, dstFormat->IntFormat);
+ tmpComps = _mesa_components_in_format(tmpFormat);
+ tmpTexelSize = tmpComps * sizeof(CHAN_TYPE);
+ tmpRowStride = postConvWidth * tmpTexelSize;
+ tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
+ tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
+ srcDepth * tmpTexelSize);
+ if (!tmpImage)
+ return;
+
+ transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
+ srcWidth, srcHeight, srcDepth,
+ 0, 0, 0, /* x/y/zoffset */
+ tmpRowStride, tmpImageStride,
+ srcFormat, srcType, srcAddr, srcPacking);
+
+ /* the temp image is our new source image */
+ srcWidth = postConvWidth;
+ srcHeight = postConvHeight;
+ srcFormat = tmpFormat;
+ srcType = CHAN_TYPE;
+ srcAddr = tmpImage;
+ srcPacking = &_mesa_native_packing;
+ }
+
+ if (_mesa_is_hardware_tex_format(dstFormat)) {
+ assert(makeTemp);
+ if (dimensions == 1) {
+ GLboolean b;
+ b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
+ dstXoffset,
+ srcWidth,
+ srcFormat, srcType,
+ srcPacking, srcAddr,
+ dstAddr);
+ assert(b);
+ }
+ else if (dimensions == 2) {
+ GLboolean b;
+ b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
+ dstXoffset, dstYoffset,
+ srcWidth, srcHeight,
+ dstRowStridePixels,
+ srcFormat, srcType,
+ srcPacking, srcAddr,
+ dstAddr);
+ assert(b);
+ }
+ else {
+ GLboolean b;
+ b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
+ dstXoffset, dstYoffset, dstZoffset,
+ srcWidth, srcHeight, srcDepth,
+ dstRowStridePixels, dstImageStridePixels,
+ srcFormat, srcType,
+ 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,
+ srcWidth, srcHeight, srcDepth,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageStride,
+ srcFormat, srcType, srcAddr, srcPacking);
+ }
+}
+
+
/*
* This is the software fallback for Driver.TexImage1D().
* The texture image type will be GLchan.
_mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
}
- /* setup the teximage struct's fields */
- _mesa_init_tex_format( ctx, internalFormat, texImage );
+ /* choose the texture format */
+ assert(ctx->Driver.ChooseTextureFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ assert(texImage->TexFormat);
texelBytes = texImage->TexFormat->TexelBytes;
/* allocate memory */
- texImage->Data = (GLchan *) MALLOC(postConvWidth * texelBytes);
- if (!texImage->Data)
- return; /* out of memory */
+ texImage->Data = MALLOC(postConvWidth * texelBytes);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ return;
+ }
/* unpack image, apply transfer ops and store in texImage->Data */
- _mesa_transfer_teximage(ctx, 1, texImage->Format, texImage->Data,
+ _mesa_transfer_teximage(ctx, 1, texImage->TexFormat, texImage->Data,
width, 1, 1, 0, 0, 0,
0, /* dstRowStride */
0, /* dstImageStride */
&postConvHeight);
}
- /* setup the teximage struct's fields */
- _mesa_init_tex_format( ctx, internalFormat, texImage );
+ /* choose the texture format */
+ assert(ctx->Driver.ChooseTextureFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ assert(texImage->TexFormat);
texelBytes = texImage->TexFormat->TexelBytes;
/* allocate memory */
- texImage->Data = (GLchan *) MALLOC(postConvWidth * postConvHeight *
- texelBytes);
- if (!texImage->Data)
- return; /* out of memory */
+ texImage->Data = MALLOC(postConvWidth * postConvHeight * texelBytes);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
/* unpack image, apply transfer ops and store in texImage->Data */
- _mesa_transfer_teximage(ctx, 2, texImage->Format, texImage->Data,
+ _mesa_transfer_teximage(ctx, 2, texImage->TexFormat, texImage->Data,
width, height, 1, 0, 0, 0,
texImage->Width * texelBytes,
0, /* dstImageStride */
{
GLint texelBytes;
- /* setup the teximage struct's fields */
- _mesa_init_tex_format( ctx, internalFormat, texImage );
+ /* choose the texture format */
+ assert(ctx->Driver.ChooseTextureFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ assert(texImage->TexFormat);
texelBytes = texImage->TexFormat->TexelBytes;
/* allocate memory */
- texImage->Data = (GLchan *) MALLOC(width * height * depth * texelBytes);
- if (!texImage->Data)
- return; /* out of memory */
+ texImage->Data = MALLOC(width * height * depth * texelBytes);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+ return;
+ }
/* unpack image, apply transfer ops and store in texImage->Data */
- _mesa_transfer_teximage(ctx, 3, texImage->Format, texImage->Data,
+ _mesa_transfer_teximage(ctx, 3, texImage->TexFormat, texImage->Data,
width, height, depth, 0, 0, 0,
texImage->Width * texelBytes,
texImage->Width * texImage->Height * texelBytes,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- _mesa_transfer_teximage(ctx, 1, texImage->Format, texImage->Data,
+ _mesa_transfer_teximage(ctx, 1, texImage->TexFormat, texImage->Data,
width, 1, 1, /* src size */
xoffset, 0, 0, /* dest offsets */
0, /* dstRowStride */
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- _mesa_transfer_teximage(ctx, 2, texImage->Format, texImage->Data,
+ _mesa_transfer_teximage(ctx, 2, texImage->TexFormat, texImage->Data,
width, height, 1, /* src size */
xoffset, yoffset, 0, /* dest offsets */
texImage->Width * texImage->TexFormat->TexelBytes,
struct gl_texture_image *texImage)
{
const GLint texelBytes = texImage->TexFormat->TexelBytes;
- _mesa_transfer_teximage(ctx, 3, texImage->Format, texImage->Data,
+ _mesa_transfer_teximage(ctx, 3, texImage->TexFormat, texImage->Data,
width, height, depth, /* src size */
xoffset, yoffset, xoffset, /* dest offsets */
texImage->Width * texelBytes,
-
-
-
/*
* This is the fallback for Driver.TestProxyTexImage().
*/
* Drivers may have more stringent texture limits to enforce and will
* have to override this function.
*/
- /* setup the teximage struct's fields */
- _mesa_init_tex_format( ctx, internalFormat, texImage );
+ /* choose the texture format */
+ assert(ctx->Driver.ChooseTextureFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ assert(texImage->TexFormat);
return GL_TRUE;
}