-/* $Id: texutil.c,v 1.15 2001/03/18 08:53:50 gareth Exp $ */
+/* $Id: texutil.c,v 1.26 2002/02/21 15:12:31 brianp Exp $ */
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 4.0.2
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2002 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"),
#include "texutil.h"
#endif
-#define DBG 0
+#define DEBUG_TEXUTIL 0
struct gl_texture_convert {
GLint xoffset, yoffset, zoffset; /* Subimage offset */
GLint width, height, depth; /* Subimage region */
- GLint imageWidth, imageHeight; /* Full image dimensions */
- GLenum format, type;
+ GLint dstImageWidth, dstImageHeight; /* Dest image size */
+ /* Needed for subimage replacement */
+ GLenum format, type; /* Source (user) format and type */
- const struct gl_pixelstore_attrib *packing;
+ const struct gl_pixelstore_attrib *unpacking;
const GLvoid *srcImage;
GLvoid *dstImage;
typedef GLboolean (*convert_func)( struct gl_texture_convert *convert );
#define CONVERT_STRIDE_BIT 0x1
-#define CONVERT_PACKING_BIT 0x2
+#define CONVERT_UNPACKING_BIT 0x2
-/* ================================================================
+/* =============================================================
* RGBA8888 textures:
*/
#define DST_TYPE GLuint
#define DST_TEXELS_PER_DWORD 1
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_8888( src[3], src[2], src[1], src[0] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_8888( src[3], src[2], src[1], src[0] )
#define CONVERT_DIRECT
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_8888( src[0], src[1], src[2], src[3] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_8888( src[0], src[1], src[2], src[3] )
-#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
+#define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
#define SRC_TEXEL_BYTES 4
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_8888( src[0], src[1], src[2], 0xff )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_8888( src[0], src[1], src[2], 0xff )
-#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
+#define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
#define SRC_TEXEL_BYTES 3
-/* ================================================================
+/* =============================================================
* ARGB8888 textures:
*/
#define DST_TYPE GLuint
#define DST_TEXELS_PER_DWORD 1
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_8888( src[3], src[2], src[1], src[0] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_8888( src[3], src[2], src[1], src[0] )
#define CONVERT_DIRECT
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_8888( src[3], src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_8888( src[3], src[0], src[1], src[2] )
-#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
+#define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
#define SRC_TEXEL_BYTES 4
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_8888( 0xff, src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_8888( 0xff, src[0], src[1], src[2] )
-#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
+#define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
#define SRC_TEXEL_BYTES 3
-/* ================================================================
+/* =============================================================
* RGB888 textures:
*/
-/* ================================================================
+/* =============================================================
* RGB565 textures:
*/
#define DST_TYPE GLushort
#define DST_TEXELS_PER_DWORD 2
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_565( src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_565( src[0], src[1], src[2] )
#define CONVERT_DIRECT
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_565( src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_565( src[0], src[1], src[2] )
-#define CONVERT_TEXEL_DWORD( src ) \
- ((PACK_COLOR_565( src[0], src[1], src[2] )) | \
- (PACK_COLOR_565( src[3], src[4], src[5] ) << 16))
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_565( src[0], src[1], src[2] )) | \
+ (PACK_COLOR_565( src[3], src[4], src[5] ) << 16))
#define SRC_TEXEL_BYTES 3
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_565( src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_565( src[0], src[1], src[2] )
-#define CONVERT_TEXEL_DWORD( src ) \
- ((PACK_COLOR_565( src[0], src[1], src[2] )) | \
- (PACK_COLOR_565( src[4], src[5], src[6] ) << 16))
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_565( src[0], src[1], src[2] )) | \
+ (PACK_COLOR_565( src[4], src[5], src[6] ) << 16))
#define SRC_TEXEL_BYTES 4
-/* ================================================================
+/* =============================================================
* ARGB4444 textures:
*/
#define DST_TYPE GLushort
#define DST_TEXELS_PER_DWORD 2
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_4444( src[3], src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_4444( src[3], src[0], src[1], src[2] )
#define CONVERT_DIRECT
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_4444( src[3], src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_4444( src[3], src[0], src[1], src[2] )
-#define CONVERT_TEXEL_DWORD( src ) \
- ((PACK_COLOR_4444( src[3], src[0], src[1], src[2] )) | \
- (PACK_COLOR_4444( src[7], src[4], src[5], src[6] ) << 16))
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_4444( src[3], src[0], src[1], src[2] )) | \
+ (PACK_COLOR_4444( src[7], src[4], src[5], src[6] ) << 16))
#define SRC_TEXEL_BYTES 4
-#define TAG(x) x##_rgba8888_to_argb4444
+#define TAG(x) x##_abgr8888_to_argb4444
#include "texutil_tmp.h"
else if ( convert->format == GL_RGBA && \
convert->type == GL_UNSIGNED_BYTE ) \
{ \
- tab = name##_tab_rgba8888_to_argb4444; \
+ tab = name##_tab_abgr8888_to_argb4444; \
} \
else \
{ \
-/* ================================================================
+/* =============================================================
* ARGB1555 textures:
*/
#define DST_TYPE GLushort
#define DST_TEXELS_PER_DWORD 2
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_1555( src[3], src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_1555( src[3], src[0], src[1], src[2] )
#define CONVERT_DIRECT
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_1555( src[3], src[0], src[1], src[2] )
+#define CONVERT_TEXEL( dst, src ) \
+ { const GLushort s = *(GLushort *)src; \
+ dst = (s >> 1) | ((s & 1) << 15); }
-#define CONVERT_TEXEL_DWORD( src ) \
- ((PACK_COLOR_1555( src[3], src[0], src[1], src[2] )) | \
- (PACK_COLOR_1555( src[7], src[4], src[5], src[6] ) << 16))
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ { const GLuint s = ((fi_type *)src)->i; \
+ dst = (((s & 0xfffefffe) >> 1) | \
+ ((s & 0x00010001) << 15)); }
+
+#define SRC_TEXEL_BYTES 2
+
+#define TAG(x) x##_rgba5551_to_argb1555
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_1555( src[3], src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_1555( src[3], src[0], src[1], src[2] )) | \
+ (PACK_COLOR_1555( src[7], src[4], src[5], src[6] ) << 16))
#define SRC_TEXEL_BYTES 4
-#define TAG(x) x##_rgba8888_to_argb1555
+#define TAG(x) x##_abgr8888_to_argb1555
#include "texutil_tmp.h"
{ \
tab = name##_tab_argb1555_direct; \
} \
+ else if ( convert->format == GL_RGBA && \
+ convert->type == GL_UNSIGNED_SHORT_5_5_5_1 ) \
+ { \
+ tab = name##_tab_rgba5551_to_argb1555; \
+ } \
else if ( convert->format == GL_RGBA && \
convert->type == GL_UNSIGNED_BYTE ) \
{ \
- tab = name##_tab_rgba8888_to_argb1555; \
+ tab = name##_tab_abgr8888_to_argb1555; \
} \
else \
{ \
-/* ================================================================
+/* =============================================================
* AL88 textures:
*/
#define DST_TYPE GLushort
#define DST_TEXELS_PER_DWORD 2
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_88( src[0], src[1] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_88( src[0], src[1] )
#define CONVERT_DIRECT
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_88( src[0], 0x00 )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_88( src[0], 0x00 )
-#define CONVERT_TEXEL_DWORD( src ) \
- ((PACK_COLOR_88( src[0], 0x00 )) | \
- (PACK_COLOR_88( src[1], 0x00 ) << 16))
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_88( src[0], 0x00 )) | \
+ (PACK_COLOR_88( src[1], 0x00 ) << 16))
#define SRC_TEXEL_BYTES 1
#include "texutil_tmp.h"
-#define CONVERT_TEXEL( src ) \
- PACK_COLOR_88( 0xff, src[0] )
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_88( 0xff, src[0] )
-#define CONVERT_TEXEL_DWORD( src ) \
- ((PACK_COLOR_88( 0xff, src[0] )) | \
- (PACK_COLOR_88( 0xff, src[1] ) << 16))
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_88( 0xff, src[0] )) | \
+ (PACK_COLOR_88( 0xff, src[1] ) << 16))
#define SRC_TEXEL_BYTES 1
#define TAG(x) x##_l8_to_al88
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src ) \
+ dst = PACK_COLOR_88( src[3], src[0] )
+
+#define CONVERT_TEXEL_DWORD( dst, src ) \
+ dst = ((PACK_COLOR_88( src[3], src[0] )) | \
+ (PACK_COLOR_88( src[7], src[1] ) << 16))
+
+#define SRC_TEXEL_BYTES 4
+
+#define TAG(x) x##_abgr8888_to_al88
#include "texutil_tmp.h"
{ \
tab = name##_tab_l8_to_al88; \
} \
+ else if ( convert->format == GL_RGBA && \
+ convert->type == GL_UNSIGNED_BYTE ) \
+ { \
+ tab = name##_tab_abgr8888_to_al88; \
+ } \
else \
{ \
/* Can't handle this source format/type combination */ \
-/* ================================================================
+/* =============================================================
* RGB332 textures:
*/
-/* ================================================================
+/* =============================================================
* CI8 (and all other single-byte texel) textures:
*/
#define DST_TYPE GLubyte
#define DST_TEXELS_PER_DWORD 4
-#define CONVERT_TEXEL( src ) src[0]
+#define CONVERT_TEXEL( dst, src ) dst = src[0]
#define CONVERT_DIRECT
-/* ================================================================
+/* =============================================================
* Global entry points
*/
/* See if we need to care about the pixel store attributes when we're
* converting the texture image. This should be stored as
- * packing->_SomeBoolean and updated when the values change, to avoid
+ * unpacking->_SomeBoolean and updated when the values change, to avoid
* testing every time...
*/
static INLINE GLboolean
-convert_needs_packing( const struct gl_pixelstore_attrib *packing,
+convert_needs_unpacking( const struct gl_pixelstore_attrib *unpacking,
GLenum format, GLenum type )
{
- if ( ( packing->Alignment == 1 ||
- ( packing->Alignment == 4 && /* Pick up the common Q3A case... */
+ if ( ( unpacking->Alignment == 1 ||
+ ( unpacking->Alignment == 4 && /* Pick up the common Q3A case... */
format == GL_RGBA && type == GL_UNSIGNED_BYTE ) ) &&
- packing->RowLength == 0 &&
- packing->SkipPixels == 0 &&
- packing->SkipRows == 0 &&
- packing->ImageHeight == 0 &&
- packing->SkipImages == 0 &&
- packing->SwapBytes == GL_FALSE &&
- packing->LsbFirst == GL_FALSE ) {
+ unpacking->RowLength == 0 &&
+ unpacking->SkipPixels == 0 &&
+ unpacking->SkipRows == 0 &&
+ unpacking->ImageHeight == 0 &&
+ unpacking->SkipImages == 0 &&
+ unpacking->SwapBytes == GL_FALSE &&
+ unpacking->LsbFirst == GL_FALSE ) {
return GL_FALSE;
} else {
return GL_TRUE;
GLint xoffset,
GLint width,
GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *packing,
+ const struct gl_pixelstore_attrib *unpacking,
const GLvoid *srcImage, GLvoid *dstImage )
{
struct gl_texture_convert convert;
- ASSERT( packing );
+ ASSERT( unpacking );
ASSERT( srcImage );
ASSERT( dstImage );
convert.height = 1;
convert.format = format;
convert.type = type;
- convert.packing = packing;
+ convert.unpacking = unpacking;
convert.srcImage = srcImage;
convert.dstImage = dstImage;
convert.index = 0;
- if ( convert_needs_packing( packing, format, type ) )
- convert.index |= CONVERT_PACKING_BIT;
+ if ( convert_needs_unpacking( unpacking, format, type ) )
+ convert.index |= CONVERT_UNPACKING_BIT;
return gl_convert_texsubimage2d_tab[mesaFormat]( &convert );
}
+
+/* Convert a user's 2D image into a texture image. This basically
+ * repacks pixel data into the special texture formats used by core Mesa
+ * and the DRI drivers. This function can do full images or subimages.
+ *
+ * We return a boolean because this function may not accept some kinds
+ * of source image formats and/or types. For example, if the incoming
+ * format/type = GL_BGR, GL_UNSIGNED_INT this function probably won't
+ * be able to do the conversion.
+ *
+ * In that case, the incoming image should first be simplified to one of
+ * the "canonical" formats (GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA,
+ * GL_INTENSITY, GL_RGB, GL_RGBA) and types (GL_CHAN). We can do that
+ * with the _mesa_transfer_teximage() function. That function will also
+ * do image transfer operations such as scale/bias and convolution.
+ *
+ * Input:
+ * mesaFormat - one of the MESA_FORMAT_* values from texformat.h
+ * xoffset, yoffset - position in dest image to put data
+ * width, height - incoming image size, also size of dest region.
+ * dstImageWidth - width (row stride) of dest image in pixels
+ * format, type - incoming image format and type
+ * unpacking - describes incoming image unpacking
+ * srcImage - pointer to source image
+ * destImage - pointer to dest image
+ */
GLboolean
_mesa_convert_texsubimage2d( GLint mesaFormat,
GLint xoffset, GLint yoffset,
GLint width, GLint height,
- GLint imageWidth,
+ GLint destImageWidth,
GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *packing,
+ const struct gl_pixelstore_attrib *unpacking,
const GLvoid *srcImage, GLvoid *dstImage )
{
struct gl_texture_convert convert;
- ASSERT( packing );
+ ASSERT( unpacking );
ASSERT( srcImage );
ASSERT( dstImage );
convert.yoffset = yoffset;
convert.width = width;
convert.height = height;
- convert.imageWidth = imageWidth;
+ convert.dstImageWidth = destImageWidth;
convert.format = format;
convert.type = type;
- convert.packing = packing;
+ convert.unpacking = unpacking;
convert.srcImage = srcImage;
convert.dstImage = dstImage;
convert.index = 0;
- if ( convert_needs_packing( packing, format, type ) )
- convert.index |= CONVERT_PACKING_BIT;
+ if ( convert_needs_unpacking( unpacking, format, type ) )
+ convert.index |= CONVERT_UNPACKING_BIT;
- if ( width != imageWidth )
+ if ( width != destImageWidth )
convert.index |= CONVERT_STRIDE_BIT;
return gl_convert_texsubimage2d_tab[mesaFormat]( &convert );
_mesa_convert_texsubimage3d( GLint mesaFormat,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
- GLint imageWidth, GLint imageHeight,
+ GLint dstImageWidth, GLint dstImageHeight,
GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *packing,
+ const struct gl_pixelstore_attrib *unpacking,
const GLvoid *srcImage, GLvoid *dstImage )
{
struct gl_texture_convert convert;
- ASSERT( packing );
+ ASSERT( unpacking );
ASSERT( srcImage );
ASSERT( dstImage );
convert.width = width;
convert.height = height;
convert.depth = depth;
- convert.imageWidth = imageWidth;
- convert.imageHeight = imageHeight;
+ convert.dstImageWidth = dstImageWidth;
+ convert.dstImageHeight = dstImageHeight;
convert.format = format;
convert.type = type;
- convert.packing = packing;
+ convert.unpacking = unpacking;
convert.srcImage = srcImage;
convert.dstImage = dstImage;
convert.index = 0;
- if ( convert_needs_packing( packing, format, type ) )
- convert.index |= CONVERT_PACKING_BIT;
+ if ( convert_needs_unpacking( unpacking, format, type ) )
+ convert.index |= CONVERT_UNPACKING_BIT;
- if ( width != imageWidth || height != imageHeight )
+ if ( width != dstImageWidth || height != dstImageHeight )
convert.index |= CONVERT_STRIDE_BIT;
return gl_convert_texsubimage3d_tab[mesaFormat]( &convert );
* all aspect ratios). This can be made a lot faster, but I don't
* really care enough...
*/
-void _mesa_rescale_teximage2d( const struct gl_texture_format *texFormat,
+void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
GLint srcWidth, GLint srcHeight,
GLint dstWidth, GLint dstHeight,
const GLvoid *srcImage, GLvoid *dstImage )
{
GLint row, col;
-#define INNER_LOOP( HOP, WOP ) \
+#define INNER_LOOP( TYPE, HOP, WOP ) \
for ( row = 0 ; row < dstHeight ; row++ ) { \
GLint srcRow = row HOP hScale; \
for ( col = 0 ; col < dstWidth ; col++ ) { \
GLint srcCol = col WOP wScale; \
- *dst++ = src[srcRow * srcWidth + srcCol]; \
+ dst[col] = src[srcRow * srcWidth + srcCol]; \
} \
+ dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
} \
#define RESCALE_IMAGE( TYPE ) \
const GLint hScale = dstHeight / srcHeight; \
if ( srcWidth <= dstWidth ) { \
const GLint wScale = dstWidth / srcWidth; \
- INNER_LOOP( /, / ); \
+ INNER_LOOP( TYPE, /, / ); \
} \
else { \
const GLint wScale = srcWidth / dstWidth; \
- INNER_LOOP( /, * ); \
+ INNER_LOOP( TYPE, /, * ); \
} \
} \
else { \
const GLint hScale = srcHeight / dstHeight; \
if ( srcWidth <= dstWidth ) { \
const GLint wScale = dstWidth / srcWidth; \
- INNER_LOOP( *, / ); \
+ INNER_LOOP( TYPE, *, / ); \
} \
else { \
const GLint wScale = srcWidth / dstWidth; \
- INNER_LOOP( *, * ); \
+ INNER_LOOP( TYPE, *, * ); \
} \
} \
} while (0)
- switch ( texFormat->TexelBytes ) {
+ switch ( bytesPerPixel ) {
case 4:
RESCALE_IMAGE( GLuint );
break;
case 1:
RESCALE_IMAGE( GLubyte );
break;
+ default:
+ _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
}
}