-/* $Id: image.c,v 1.65 2002/03/19 16:47:04 brianp Exp $ */
+/**
+ * \file image.c
+ * Image handling.
+ */
/*
* Mesa 3-D graphics library
- * Version: 4.1
+ * Version: 5.1
*
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2003 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"),
*/
-#ifdef PC_HEADER
-#include "all.h"
-#else
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "image.h"
+#include "imports.h"
#include "histogram.h"
#include "macros.h"
-#include "mem.h"
-#include "mmath.h"
#include "pixel.h"
#include "mtypes.h"
-#endif
+/** Compute ceiling of integer quotient of A divided by B. */
+#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
-/*
- * These are the image packing parameters for Mesa's internal images.
- * That is, _mesa_unpack_image() returns image data in this format.
- * When we execute image commands (glDrawPixels, glTexImage, etc)
- * from within display lists we have to be sure to set the current
- * unpacking params to these values!
+
+/**
+ * Image packing parameters for Mesa's internal images.
+ *
+ * _mesa_unpack_image() returns image data in this format. When we execute
+ * image commands (glDrawPixels(), glTexImage(), etc) from within display lists
+ * we have to be sure to set the current unpacking parameters to these values!
*/
const struct gl_pixelstore_attrib _mesa_native_packing = {
1, /* Alignment */
0, /* ImageHeight */
0, /* SkipImages */
GL_FALSE, /* SwapBytes */
- GL_FALSE /* LsbFirst */
+ GL_FALSE, /* LsbFirst */
+ GL_FALSE, /* ClientStorage */
+ GL_FALSE /* Invert */
};
-
-/*
+/**
* Flip the 8 bits in each byte of the given array.
*
- * XXX try this trick to flip bytes someday:
+ * \param p array.
+ * \param n number of bytes.
+ *
+ * \todo try this trick to flip bytes someday:
+ * \code
* v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555);
* v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333);
* v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f);
+ * \endcode
*/
static void
flip_bytes( GLubyte *p, GLuint n )
}
-/*
+/**
* Flip the order of the 2 bytes in each word in the given array.
+ *
+ * \param p array.
+ * \param n number of words.
*/
void
_mesa_swap2( GLushort *p, GLuint n )
}
-
-
-/*
- * Return the size, in bytes, of the given GL datatype.
- * Return 0 if GL_BITMAP.
- * Return -1 if invalid type enum.
+/**
+ * Get the size of a GL data type.
+ *
+ * \param type GL data type.
+ *
+ * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1
+ * if an invalid type enum.
*/
GLint _mesa_sizeof_type( GLenum type )
{
return sizeof(GLint);
case GL_FLOAT:
return sizeof(GLfloat);
+ case GL_HALF_FLOAT_NV:
+ return sizeof(GLhalfNV);
default:
return -1;
}
}
-/*
- * Same as _mesa_sizeof_packed_type() but we also accept the
- * packed pixel format datatypes.
+/**
+ * Same as _mesa_sizeof_type() but also accepting the packed pixel
+ * format data types.
*/
GLint _mesa_sizeof_packed_type( GLenum type )
{
return sizeof(GLuint);
case GL_INT:
return sizeof(GLint);
+ case GL_HALF_FLOAT_NV:
+ return sizeof(GLhalfNV);
case GL_FLOAT:
return sizeof(GLfloat);
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
return sizeof(GLubyte);
case GL_UNSIGNED_SHORT_5_6_5:
- return sizeof(GLshort);
+ return sizeof(GLushort);
case GL_UNSIGNED_SHORT_5_6_5_REV:
- return sizeof(GLshort);
+ return sizeof(GLushort);
case GL_UNSIGNED_SHORT_4_4_4_4:
- return sizeof(GLshort);
+ return sizeof(GLushort);
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return sizeof(GLshort);
+ return sizeof(GLushort);
case GL_UNSIGNED_SHORT_5_5_5_1:
- return sizeof(GLshort);
+ return sizeof(GLushort);
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return sizeof(GLshort);
+ return sizeof(GLushort);
case GL_UNSIGNED_INT_8_8_8_8:
return sizeof(GLuint);
case GL_UNSIGNED_INT_8_8_8_8_REV:
return sizeof(GLuint);
case GL_UNSIGNED_INT_2_10_10_10_REV:
return sizeof(GLuint);
+ case GL_UNSIGNED_SHORT_8_8_MESA:
+ case GL_UNSIGNED_SHORT_8_8_REV_MESA:
+ return sizeof(GLushort);
default:
return -1;
}
}
-
-/*
- * Return the number of components in a GL enum pixel type.
- * Return -1 if bad format.
+/**
+ * Get the number of components in a pixel format.
+ *
+ * \param format pixel format.
+ *
+ * \return the number of components in the given format, or -1 if a bad format.
*/
GLint _mesa_components_in_format( GLenum format )
{
return 4;
case GL_ABGR_EXT:
return 4;
+ case GL_YCBCR_MESA:
+ return 2;
default:
return -1;
}
}
-/*
- * Return bytes per pixel for given format and type
- * Return -1 if bad format or type.
+/**
+ * Get the bytes per pixel of pixel format type pair.
+ *
+ * \param format pixel format.
+ * \param type pixel type.
+ *
+ * \return bytes per pixel, or -1 if a bad format or type was given.
*/
GLint _mesa_bytes_per_pixel( GLenum format, GLenum type )
{
return comps * sizeof(GLint);
case GL_FLOAT:
return comps * sizeof(GLfloat);
+ case GL_HALF_FLOAT_NV:
+ return comps * sizeof(GLhalfNV);
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
if (format == GL_RGB || format == GL_BGR)
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_6_5_REV:
if (format == GL_RGB || format == GL_BGR)
- return sizeof(GLshort);
+ return sizeof(GLushort);
else
return -1; /* error */
case GL_UNSIGNED_SHORT_4_4_4_4:
return sizeof(GLuint);
else
return -1;
+ case GL_UNSIGNED_SHORT_8_8_MESA:
+ case GL_UNSIGNED_SHORT_8_8_REV_MESA:
+ if (format == GL_YCBCR_MESA)
+ return sizeof(GLushort);
+ else
+ return -1;
default:
return -1;
}
}
-/*
- * Test if the given pixel format and type are legal.
- * Return GL_TRUE for legal, GL_FALSE for illegal.
+/**
+ * Test for a legal pixel format and type.
+ *
+ * \param format pixel format.
+ * \param type pixel type.
+ *
+ * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE
+ * otherwise.
*/
GLboolean
_mesa_is_legal_format_and_type( GLenum format, GLenum type )
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
+ case GL_HALF_FLOAT_NV:
return GL_TRUE;
default:
return GL_FALSE;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
+ case GL_HALF_FLOAT_NV:
return GL_TRUE;
default:
return GL_FALSE;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
+ case GL_HALF_FLOAT_NV:
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
case GL_UNSIGNED_SHORT_5_6_5:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
+ case GL_HALF_FLOAT_NV:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL_UNSIGNED_SHORT_5_5_5_1:
default:
return GL_FALSE;
}
+ case GL_YCBCR_MESA:
+ if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
+ type == GL_UNSIGNED_SHORT_8_8_REV_MESA)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
default:
; /* fall-through */
}
}
-
-/*
- * Return the address of a pixel in an image (actually a volume).
- * Pixel unpacking/packing parameters are observed according to 'packing'.
- * Input: image - start of image data
- * width, height - size of image
- * format - image format
- * type - pixel component type
- * packing - the pixelstore attributes
- * img - which image in the volume (0 for 1D or 2D images)
- * row, column - location of pixel in the image
- * Return: address of pixel at (image,row,column) in image or NULL if error.
+/**
+ * Get the address of a pixel in an image (actually a volume).
+ *
+ * Pixel unpacking/packing parameters are observed according to \p packing.
+ *
+ * \param image start of image data.
+ * \param width image width.
+ * \param height image height.
+ * \param format pixel format.
+ * \param type pixel data type.
+ * \param packing the pixelstore attributes
+ * \param img which image in the volume (0 for 1D or 2D images)
+ * \param row of pixel in the image
+ * \param column of pixel in the image
+ *
+ * \return address of pixel on success, or NULL on error.
+ *
+ * According to the \p packing information calculates the number of pixel/bytes
+ * per row/image and refers it.
+ *
+ * \sa gl_pixelstore_attrib.
*/
GLvoid *
_mesa_image_address( const struct gl_pixelstore_attrib *packing,
else {
/* Non-BITMAP data */
GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
+ GLint topOfImage;
bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
bytes_per_image = bytes_per_row * rows_per_image;
+ if (packing->Invert) {
+ /* set pixel_addr to the last row */
+ topOfImage = bytes_per_row * (height - 1);
+ bytes_per_row = -bytes_per_row;
+ }
+ else {
+ topOfImage = 0;
+ }
+
/* compute final pixel address */
pixel_addr = (GLubyte *) image
+ (skipimages + img) * bytes_per_image
+ + topOfImage
+ (skiprows + row) * bytes_per_row
+ (skippixels + column) * bytes_per_pixel;
}
}
-
-/*
- * Compute the stride between image rows (in bytes) for the given
- * pixel packing parameters and image width, format and type.
+/**
+ * Compute the stride between image rows.
+ *
+ * \param packing the pixelstore attributes
+ * \param width image width.
+ * \param format pixel format.
+ * \param type pixel data type.
+ *
+ * \return the stride in bytes for the given parameters.
+ *
+ * Computes the number of bytes per pixel and row and compensates for alignment.
+ *
+ * \sa gl_pixelstore_attrib.
*/
GLint
_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
ASSERT(packing);
if (type == GL_BITMAP) {
/* BITMAP data */
+ GLint bytes;
if (packing->RowLength == 0) {
- GLint bytes = (width + 7) / 8;
- return bytes;
+ bytes = (width + 7) / 8;
}
else {
- GLint bytes = (packing->RowLength + 7) / 8;
- return bytes;
+ bytes = (packing->RowLength + 7) / 8;
+ }
+ if (packing->Invert) {
+ /* negate the bytes per row (negative row stride) */
+ bytes = -bytes;
}
+ return bytes;
}
else {
/* Non-BITMAP data */
remainder = bytesPerRow % packing->Alignment;
if (remainder > 0)
bytesPerRow += (packing->Alignment - remainder);
+ if (packing->Invert)
+ bytesPerRow = -bytesPerRow;
return bytesPerRow;
}
}
+#if _HAVE_FULL_GL
/*
* Compute the stride between images in a 3D texture (in bytes) for the given
}
-
-
/*
* Unpack a 32x32 pixel polygon stipple from user memory using the
* current pixel unpack settings.
}
-
/*
* Pack polygon stipple into user memory given current pixel packing
* settings.
}
-
/*
* Used to pack an array [][4] of RGBA GLchan colors as specified
* by the dstFormat, dstType and dstPacking. Used by glReadPixels,
}
}
break;
+ case GL_HALF_FLOAT_NV:
+ {
+ GLhalfNV *dst = (GLhalfNV *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][ACOMP]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = _mesa_float_to_half(luminance[i]);
+ dst[i*2+1] = _mesa_float_to_half(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*3+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*3+2] = _mesa_float_to_half(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*4+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*4+2] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*4+3] = _mesa_float_to_half(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*3+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*3+2] = _mesa_float_to_half(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*4+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*4+2] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*4+3] = _mesa_float_to_half(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = _mesa_float_to_half(rgba[i][ACOMP]);
+ dst[i*4+1] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*4+2] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n * comps );
+ }
+ }
+ break;
case GL_UNSIGNED_BYTE_3_3_2:
if (dstFormat == GL_RGB) {
GLubyte *dst = (GLubyte *) dstAddr;
}
-
/*
* Pack the given RGBA span into client memory at 'dest' address
* in the given pixel format and type.
* Optionally apply the enabled pixel transfer ops.
* Pack into memory using the given packing params struct.
* This is used by glReadPixels and glGetTexImage?D()
- * Input: ctx - the context
+ * \param ctx - the context
* n - number of pixels in the span
* rgba - the pixels
* format - dest packing format
- * type - dest packing datatype
+ * type - dest packing data type
* destination - destination packing address
* packing - pixel packing parameters
* transferOps - bitmask of IMAGE_*_BIT operations to apply
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_NV ||
srcType == GL_FLOAT);
switch (srcType) {
}
}
break;
+ case GL_HALF_FLOAT_NV:
+ {
+ GLuint i;
+ const GLhalfNV *s = (const GLhalfNV *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLhalfNV value = s[i];
+ SWAP2BYTE(value);
+ indexes[i] = (GLuint) _mesa_half_to_float(value);
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = (GLuint) _mesa_half_to_float(s[i]);
+ }
+ }
+ break;
default:
_mesa_problem(NULL, "bad srcType in extract_uint_indexes");
return;
}
-
/*
* This function extracts floating point RGBA values from arbitrary
* image data. srcFormat and srcType are the format and type parameters
* Args: n - number of pixels
* rgba - output colors
* srcFormat - format of incoming data
- * srcType - datatype of incoming data
+ * srcType - data type of incoming data
* src - source data pointer
* swapBytes - perform byteswapping of incoming data?
*/
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_NV ||
srcType == GL_FLOAT ||
srcType == GL_UNSIGNED_BYTE_3_3_2 ||
srcType == GL_UNSIGNED_BYTE_2_3_3_REV ||
PROCESS(blueIndex, BCOMP, 0.0F, GLfloat, (GLfloat));
PROCESS(alphaIndex, ACOMP, 1.0F, GLfloat, (GLfloat));
break;
+ case GL_HALF_FLOAT_NV:
+ PROCESS(redIndex, RCOMP, 0.0F, GLhalfNV, _mesa_half_to_float);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLhalfNV, _mesa_half_to_float);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLhalfNV, _mesa_half_to_float);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLhalfNV, _mesa_half_to_float);
+ break;
case GL_UNSIGNED_BYTE_3_3_2:
{
const GLubyte *ubsrc = (const GLubyte *) src;
}
-
/*
* Unpack a row of color image data from a client buffer according to
* the pixel unpacking parameters.
* Return GLubyte values in the specified dest image format.
* This is (or will be) used by glDrawPixels and glTexImage?D().
- * Input: ctx - the context
+ * \param ctx - the context
* n - number of pixels in the span
* dstFormat - format of destination color array
* dest - the destination color array
* srcFormat - source image format
- * srcType - source image datatype
+ * srcType - source image data type
* source - source image pointer
* srcPacking - pixel unpacking parameters
* transferOps - bitmask of IMAGE_*_BIT values of operations to apply
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_NV ||
srcType == GL_FLOAT ||
srcType == GL_UNSIGNED_BYTE_3_3_2 ||
srcType == GL_UNSIGNED_BYTE_2_3_3_REV ||
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_NV ||
srcType == GL_FLOAT ||
srcType == GL_UNSIGNED_BYTE_3_3_2 ||
srcType == GL_UNSIGNED_BYTE_2_3_3_REV ||
}
-
-
/*
* Unpack a row of color index data from a client buffer according to
* the pixel unpacking parameters.
*
* Args: ctx - the context
* n - number of pixels
- * dstType - destination datatype
+ * dstType - destination data type
* dest - destination array
* srcType - source pixel type
* source - source data pointer
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_NV ||
srcType == GL_FLOAT);
ASSERT(dstType == GL_UNSIGNED_BYTE ||
}
}
break;
+ case GL_HALF_FLOAT_NV:
+ {
+ GLhalfNV *dst = (GLhalfNV *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = _mesa_float_to_half((GLfloat) source[i]);
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
default:
_mesa_problem(ctx, "bad type in _mesa_pack_index_span");
}
}
-
/*
* Unpack a row of stencil data from a client buffer according to
* the pixel unpacking parameters.
*
* Args: ctx - the context
* n - number of pixels
- * dstType - destination datatype
+ * dstType - destination data type
* dest - destination array
* srcType - source pixel type
* source - source data pointer
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_NV ||
srcType == GL_FLOAT);
ASSERT(dstType == GL_UNSIGNED_BYTE ||
}
}
break;
+ case GL_HALF_FLOAT_NV:
+ {
+ GLhalfNV *dst = (GLhalfNV *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = _mesa_float_to_half( (float) source[i] );
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
case GL_BITMAP:
if (dstPacking->LsbFirst) {
GLubyte *dst = (GLubyte *) dest;
}
-
void
_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n, GLfloat *dest,
GLenum srcType, const GLvoid *source,
case GL_FLOAT:
MEMCPY(dest, source, n * sizeof(GLfloat));
break;
+ case GL_HALF_FLOAT_NV:
+ {
+ GLuint i;
+ const GLhalfNV *src = (const GLhalfNV *) source;
+ for (i = 0; i < n; i++) {
+ dest[i] = _mesa_half_to_float(src[i]);
+ }
+ }
+ break;
default:
_mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()");
return;
}
-
/*
* Pack an array of depth values. The values are floats in [0,1].
*/
}
}
break;
+ case GL_HALF_FLOAT_NV:
+ {
+ GLhalfNV *dst = (GLhalfNV *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = _mesa_float_to_half(depthSpan[i]);
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
default:
_mesa_problem(ctx, "bad type in _mesa_pack_depth_span");
}
}
-
-
/*
* Unpack image data. Apply byteswapping, byte flipping (bitmap).
* Return all image data in a contiguous block.
return destBuffer;
}
}
+
+#endif