/*
* Mesa 3-D graphics library
- * Version: 6.3
+ * Version: 6.5
*
- * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2005 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 "glheader.h"
-#include "bufferobj.h"
#include "colormac.h"
#include "context.h"
#include "image.h"
#include "histogram.h"
#include "macros.h"
#include "pixel.h"
-#include "mtypes.h"
/** Compute ceiling of integer quotient of A divided by B. */
return sizeof(GLuint);
case GL_UNSIGNED_SHORT_8_8_MESA:
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
- return sizeof(GLushort);
+ return sizeof(GLushort);
+ case GL_UNSIGNED_INT_24_8_EXT:
+ return sizeof(GLuint);
default:
return -1;
}
return 4;
case GL_YCBCR_MESA:
return 2;
+ case GL_DEPTH_STENCIL_EXT:
+ return 2;
default:
return -1;
}
return sizeof(GLushort);
else
return -1;
+ case GL_UNSIGNED_INT_24_8_EXT:
+ if (format == GL_DEPTH_STENCIL_EXT)
+ return sizeof(GLuint);
+ else
+ return -1;
default:
return -1;
}
return GL_TRUE;
else
return GL_FALSE;
+ case GL_DEPTH_STENCIL_EXT:
+ if (ctx->Extensions.EXT_packed_depth_stencil
+ && type == GL_UNSIGNED_INT_24_8_EXT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
default:
; /* fall-through */
}
/**
- * Get the address of a pixel in an image (actually a volume).
+ * Return the address of a specific pixel in an image (1D, 2D or 3D).
*
* 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
+ * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
+ * \param image starting address of image data
+ * \param width the image width
+ * \param height theimage height
+ * \param format the pixel format
+ * \param type the pixel data type
+ * \param packing the pixelstore attributes
+ * \param img which image in the volume (0 for 1D or 2D images)
+ * \param row row of pixel in the image (0 for 1D images)
+ * \param column 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,
- const GLvoid *image, GLsizei width,
- GLsizei height, GLenum format, GLenum type,
+_mesa_image_address( GLuint dimensions,
+ const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
GLint img, GLint row, GLint column )
{
GLint alignment; /* 1, 2 or 4 */
GLint skipimages; /* for 3-D volume images */
GLubyte *pixel_addr;
+ ASSERT(dimensions >= 1 && dimensions <= 3);
+
alignment = packing->Alignment;
if (packing->RowLength > 0) {
pixels_per_row = packing->RowLength;
else {
rows_per_image = height;
}
- skiprows = packing->SkipRows;
+
skippixels = packing->SkipPixels;
- skipimages = packing->SkipImages;
+ /* Note: SKIP_ROWS _is_ used for 1D images */
+ skiprows = packing->SkipRows;
+ /* Note: SKIP_IMAGES is only used for 3D images */
+ skipimages = (dimensions == 3) ? packing->SkipImages : 0;
if (type == GL_BITMAP) {
/* BITMAP data */
}
+GLvoid *
+_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width,
+ GLenum format, GLenum type,
+ GLint column )
+{
+ return _mesa_image_address(1, packing, image, width, 1,
+ format, type, 0, 0, column);
+}
+
+
+GLvoid *
+_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint row, GLint column )
+{
+ return _mesa_image_address(2, packing, image, width, height,
+ format, type, 0, row, column);
+}
+
+
+GLvoid *
+_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint img, GLint row, GLint column )
+{
+ return _mesa_image_address(3, packing, image, width, height,
+ format, type, img, row, column);
+}
+
+
+
/**
* Compute the stride between image rows.
*
dst = buffer;
for (row = 0; row < height; row++) {
const GLubyte *src = (const GLubyte *)
- _mesa_image_address(packing, pixels, width, height,
- GL_COLOR_INDEX, GL_BITMAP, 0, row, 0);
+ _mesa_image_address2d(packing, pixels, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, row, 0);
if (!src) {
FREE(buffer);
return NULL;
width_in_bytes = CEILING( width, 8 );
src = source;
for (row = 0; row < height; row++) {
- GLubyte *dst = (GLubyte *) _mesa_image_address( packing, dest,
- width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
+ GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest,
+ width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
if (!dst)
return;
if (transferOps) {
/* make copy of incoming data */
- DEFMARRAY(GLfloat, rgbaCopy, MAX_WIDTH, 4); /* mac 32k limitation */
- CHECKARRAY(rgbaCopy, return); /* mac 32k limitation */
-
+ GLfloat rgbaCopy[MAX_WIDTH][4];
_mesa_memcpy(rgbaCopy, rgbaIn, n * 4 * sizeof(GLfloat));
_mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgbaCopy);
rgba = (const GLfloat (*)[4]) rgbaCopy;
if ((transferOps & IMAGE_MIN_MAX_BIT) && ctx->MinMax.Sink) {
- UNDEFARRAY(rgbaCopy); /* mac 32k limitation */
return;
}
- UNDEFARRAY(rgbaCopy); /* mac 32k limitation */
}
else {
/* use incoming data, not a copy */
else {
/* general solution */
GLuint i;
- DEFMARRAY(GLfloat, rgba, MAX_WIDTH, 4); /* mac 32k limitation */
- CHECKARRAY(rgba, return); /* mac 32k limitation */
-
+ GLfloat rgba[MAX_WIDTH][4];
assert(n <= MAX_WIDTH);
/* convert color components to floating point */
for (i = 0; i < n; i++) {
_mesa_pack_rgba_span_float(ctx, n, (const GLfloat (*)[4]) rgba,
dstFormat, dstType, dstAddr,
dstPacking, transferOps);
- UNDEFARRAY(rgba); /* mac 32k limitation */
}
}
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_UNSIGNED_INT_24_8_EXT ||
srcType == GL_HALF_FLOAT_ARB ||
srcType == GL_FLOAT);
}
}
break;
+ case GL_UNSIGNED_INT_24_8_EXT:
+ {
+ GLuint i;
+ const GLuint *s = (const GLuint *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLuint value = s[i];
+ SWAP4BYTE(value);
+ indexes[i] = value & 0xff; /* lower 8 bits */
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i] & 0xfff; /* lower 8 bits */
+ }
+ }
+ break;
+
default:
_mesa_problem(NULL, "bad srcType in extract_uint_indexes");
return;
GLint dstComponents;
GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex;
GLint dstLuminanceIndex, dstIntensityIndex;
- DEFMARRAY(GLfloat, rgba, MAX_WIDTH, 4); /* mac 32k limitation */
- CHECKARRAY(rgba, return); /* mac 32k limitation */
+ GLfloat rgba[MAX_WIDTH][4];
dstComponents = _mesa_components_in_format( dstFormat );
/* source & dest image formats should have been error checked by now */
for (i = 0; i < n; i++) {
dest[i] = (GLchan) (indexes[i] & 0xff);
}
- UNDEFARRAY(rgba); /* mac 32k limitation */
return;
}
else {
break;
default:
_mesa_problem(ctx, "bad dstFormat in _mesa_unpack_chan_span()");
- UNDEFARRAY(rgba); /* mac 32k limitation */
return;
}
dst += dstComponents;
}
}
- UNDEFARRAY(rgba); /* mac 32k limitation */
}
}
GLint dstComponents;
GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex;
GLint dstLuminanceIndex, dstIntensityIndex;
- DEFMARRAY(GLfloat, rgba, MAX_WIDTH, 4); /* mac 32k limitation */
- CHECKARRAY(rgba, return); /* mac 32k limitation */
+ GLfloat rgba[MAX_WIDTH][4];
dstComponents = _mesa_components_in_format( dstFormat );
/* source & dest image formats should have been error checked by now */
for (i = 0; i < n; i++) {
dest[i] = (GLchan) (indexes[i] & 0xff);
}
- UNDEFARRAY(rgba); /* mac 32k limitation */
return;
}
else {
break;
default:
_mesa_problem(ctx, "bad dstFormat in _mesa_unpack_color_span_float()");
- UNDEFARRAY(rgba); /* mac 32k limitation */
return;
}
dst += dstComponents;
}
}
- UNDEFARRAY(rgba); /* mac 32k limitation */
}
}
srcType == GL_SHORT ||
srcType == GL_UNSIGNED_INT ||
srcType == GL_INT ||
+ srcType == GL_UNSIGNED_INT_24_8_EXT ||
srcType == GL_HALF_FLOAT_ARB ||
srcType == GL_FLOAT);
void
-_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n, GLfloat *dest,
+_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, GLfloat depthScale,
GLenum srcType, const GLvoid *source,
const struct gl_pixelstore_attrib *srcPacking )
{
+ GLfloat depthTemp[MAX_WIDTH], *depthValues;
+
+ if (dstType == GL_FLOAT) {
+ depthValues = (GLfloat *) dest;
+ }
+ else {
+ depthValues = depthTemp;
+ }
+
(void) srcPacking;
switch (srcType) {
GLuint i;
const GLubyte *src = (const GLubyte *) source;
for (i = 0; i < n; i++) {
- dest[i] = BYTE_TO_FLOAT(src[i]);
+ depthValues[i] = BYTE_TO_FLOAT(src[i]);
}
}
break;
GLuint i;
const GLubyte *src = (const GLubyte *) source;
for (i = 0; i < n; i++) {
- dest[i] = UBYTE_TO_FLOAT(src[i]);
+ depthValues[i] = UBYTE_TO_FLOAT(src[i]);
}
}
break;
GLuint i;
const GLshort *src = (const GLshort *) source;
for (i = 0; i < n; i++) {
- dest[i] = SHORT_TO_FLOAT(src[i]);
+ depthValues[i] = SHORT_TO_FLOAT(src[i]);
}
}
break;
GLuint i;
const GLushort *src = (const GLushort *) source;
for (i = 0; i < n; i++) {
- dest[i] = USHORT_TO_FLOAT(src[i]);
+ depthValues[i] = USHORT_TO_FLOAT(src[i]);
}
}
break;
GLuint i;
const GLint *src = (const GLint *) source;
for (i = 0; i < n; i++) {
- dest[i] = INT_TO_FLOAT(src[i]);
+ depthValues[i] = INT_TO_FLOAT(src[i]);
}
}
break;
GLuint i;
const GLuint *src = (const GLuint *) source;
for (i = 0; i < n; i++) {
- dest[i] = UINT_TO_FLOAT(src[i]);
+ depthValues[i] = UINT_TO_FLOAT(src[i]);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_24_8_EXT: /* GL_EXT_packed_depth_stencil */
+ if (dstType == GL_UNSIGNED_INT && ctx->Pixel.DepthScale == 1.0 &&
+ ctx->Pixel.DepthBias == 0.0 && depthScale == (GLfloat) 0xffffff) {
+ const GLuint *src = (const GLuint *) source;
+ GLuint *zValues = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ zValues[i] = src[i] & 0xffffff00;
+ }
+ return;
+ }
+ else {
+ const GLuint *src = (const GLuint *) source;
+ const GLfloat scale = 1.0f / 0xffffff;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ depthValues[i] = (src[i] >> 8) * scale;
}
}
break;
case GL_FLOAT:
- MEMCPY(dest, source, n * sizeof(GLfloat));
+ MEMCPY(depthValues, source, n * sizeof(GLfloat));
break;
case GL_HALF_FLOAT_ARB:
{
GLuint i;
const GLhalfARB *src = (const GLhalfARB *) source;
for (i = 0; i < n; i++) {
- dest[i] = _mesa_half_to_float(src[i]);
+ depthValues[i] = _mesa_half_to_float(src[i]);
}
}
break;
/* apply depth scale and bias and clamp to [0,1] */
if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) {
+ _mesa_scale_and_bias_depth(ctx, n, depthValues);
+ }
+
+ if (dstType == GL_UNSIGNED_INT) {
+ GLuint *zValues = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ zValues[i] = (GLuint) (depthValues[i] * depthScale);
+ }
+ }
+ else if (dstType == GL_UNSIGNED_SHORT) {
+ GLushort *zValues = (GLushort *) dest;
GLuint i;
for (i = 0; i < n; i++) {
- GLfloat d = dest[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
- dest[i] = CLAMP(d, 0.0F, 1.0F);
+ zValues[i] = (GLushort) (depthValues[i] * depthScale);
}
}
+ else {
+ ASSERT(dstType == GL_FLOAT);
+ ASSERT(depthScale == 1.0F);
+ }
}
const struct gl_pixelstore_attrib *dstPacking )
{
GLfloat depthCopy[MAX_WIDTH];
- const GLboolean bias_or_scale = ctx->Pixel.DepthBias != 0.0 ||
- ctx->Pixel.DepthScale != 1.0;
ASSERT(n <= MAX_WIDTH);
- if (bias_or_scale) {
- GLuint i;
- for (i = 0; i < n; i++) {
- GLfloat d;
- d = depthSpan[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
- depthCopy[i] = CLAMP(d, 0.0F, 1.0F);
- }
+ if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) {
+ _mesa_memcpy(depthCopy, depthSpan, n * sizeof(GLfloat));
+ _mesa_scale_and_bias_depth(ctx, n, depthCopy);
depthSpan = depthCopy;
}
* need a copy of the data in a standard format.
*/
void *
-_mesa_unpack_image( GLsizei width, GLsizei height, GLsizei depth,
+_mesa_unpack_image( GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *unpack )
{
dst = destBuffer;
for (img = 0; img < depth; img++) {
for (row = 0; row < height; row++) {
- const GLvoid *src = _mesa_image_address(unpack, pixels,
+ const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels,
width, height, format, type, img, row, 0);
MEMCPY(dst, src, bytesPerRow);
/* byte flipping/swapping */
/**
* Perform clipping for glDrawPixels. The image's window position
- * and size, and the unpack skipPixels and skipRows are adjusted so
+ * and size, and the unpack SkipPixels and SkipRows are adjusted so
* that the image region is entirely within the window and scissor bounds.
* NOTE: this will only work when glPixelZoom is (1, 1).
*
_mesa_clip_drawpixels(const GLcontext *ctx,
GLint *destX, GLint *destY,
GLsizei *width, GLsizei *height,
- GLint *skipPixels, GLint *skipRows)
+ struct gl_pixelstore_attrib *unpack)
{
const GLframebuffer *buffer = ctx->DrawBuffer;
+ if (unpack->RowLength == 0) {
+ unpack->RowLength = *width;
+ }
+
ASSERT(ctx->Pixel.ZoomX == 1.0F && ctx->Pixel.ZoomY == 1.0F);
/* left clipping */
if (*destX < buffer->_Xmin) {
- *skipPixels += (buffer->_Xmin - *destX);
+ unpack->SkipPixels += (buffer->_Xmin - *destX);
*width -= (buffer->_Xmin - *destX);
*destX = buffer->_Xmin;
}
/* bottom clipping */
if (*destY < buffer->_Ymin) {
- *skipRows += (buffer->_Ymin - *destY);
+ unpack->SkipRows += (buffer->_Ymin - *destY);
*height -= (buffer->_Ymin - *destY);
*destY = buffer->_Ymin;
}
/**
* Perform clipping for glReadPixels. The image's window position
- * and size, and the pack skipPixels and skipRows are adjusted so
- * that the image region is entirely within the window bounds.
+ * and size, and the pack skipPixels, skipRows and rowLength are adjusted
+ * so that the image region is entirely within the window bounds.
* Note: this is different from _mesa_clip_drawpixels() in that the
- * scissor box is ignored, and we use the bounds of the current "read"
- * surface;
+ * scissor box is ignored, and we use the bounds of the current readbuffer
+ * surface.
*
* \return GL_TRUE if image is ready for drawing or
* GL_FALSE if image was completely clipped away (draw nothing)
_mesa_clip_readpixels(const GLcontext *ctx,
GLint *srcX, GLint *srcY,
GLsizei *width, GLsizei *height,
- GLint *skipPixels, GLint *skipRows)
+ struct gl_pixelstore_attrib *pack)
{
const GLframebuffer *buffer = ctx->ReadBuffer;
+ if (pack->RowLength == 0) {
+ pack->RowLength = *width;
+ }
+
/* left clipping */
if (*srcX < 0) {
- *skipPixels += (0 - *srcX);
+ pack->SkipPixels += (0 - *srcX);
*width -= (0 - *srcX);
*srcX = 0;
}
/* right clipping */
- if (*srcX + *width > buffer->Width)
+ if (*srcX + *width > (GLsizei) buffer->Width)
*width -= (*srcX + *width - buffer->Width);
if (*width <= 0)
/* bottom clipping */
if (*srcY < 0) {
- *skipRows += (0 - *srcY);
+ pack->SkipRows += (0 - *srcY);
*height -= (0 - *srcY);
*srcY = 0;
}
/* top clipping */
- if (*srcY + *height > buffer->Height)
+ if (*srcY + *height > (GLsizei) buffer->Height)
*height -= (*srcY + *height - buffer->Height);
if (*height <= 0)