#include "texstore.h"
-static const GLint ZERO = 1000, ONE = 1001;
+static const GLint ZERO = 4, ONE = 5;
+
+static GLboolean can_swizzle(GLenum logicalBaseFormat)
+{
+ switch (logicalBaseFormat) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
/**
* When promoting texture formats (see below) we need to compute the
*/
static void
compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
- GLint map[4])
+ GLubyte map[6])
{
+ map[ZERO] = ZERO;
+ map[ONE] = ONE;
+
/* compute mapping from dest components back to src components */
switch (textureBaseFormat) {
case GL_RGB:
map[2] = 2;
map[3] = ONE;
break;
+ case GL_RGBA:
+ ASSERT(textureBaseFormat == GL_RGBA);
+ map[0] = 0;
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+ break;
default:
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
map[0] = map[1] = map[2] = map[3] = 0;
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
map[0] = map[1] = 0;
}
- }
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected logicalBaseFormat");
+ map[0] = map[1] = 0;
+ break;
+ }
}
/* unpack and do transfer ops up to convolution */
for (row = 0; row < srcHeight; row++) {
- const GLvoid *src = _mesa_image_address(srcPacking,
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
srcAddr, srcWidth, srcHeight,
srcFormat, srcType, img, row, 0);
_mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
dst = tempImage;
for (img = 0; img < srcDepth; img++) {
const GLubyte *src
- = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr,
+ = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
srcWidth, srcHeight,
srcFormat, srcType,
img, 0, 0);
GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
GLfloat *newImage;
GLint i, n;
- GLint map[4];
+ GLubyte map[6];
/* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
srcWidth, srcFormat,
srcType);
const GLubyte *src
- = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr,
+ = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
srcWidth, srcHeight,
srcFormat, srcType,
img, 0, 0);
GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
GLchan *newImage;
GLint i, n;
- GLint map[4];
+ GLubyte map[6];
/* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
}
+static void swizzle_copy(GLubyte *dst,
+ GLuint dstComponents,
+ const GLubyte *src,
+ GLuint srcComponents,
+ GLubyte *map,
+ GLuint count)
+{
+ GLubyte tmp[8];
+ GLint i;
+
+ tmp[ZERO] = 0x0;
+ tmp[ONE] = 0xff;
+
+ switch (dstComponents) {
+ case 4:
+ for (i = 0; i < count; i++) {
+ COPY_4UBV(tmp, src);
+ src += srcComponents;
+ dst[0] = tmp[map[0]];
+ dst[1] = tmp[map[1]];
+ dst[2] = tmp[map[2]];
+ dst[3] = tmp[map[3]];
+ dst += 4;
+ }
+ break;
+ case 3:
+ for (i = 0; i < count; i++) {
+ COPY_4UBV(tmp, src);
+ src += srcComponents;
+ dst[0] = tmp[map[0]];
+ dst[1] = tmp[map[1]];
+ dst[2] = tmp[map[2]];
+ dst += 3;
+ }
+ break;
+ case 2:
+ for (i = 0; i < count; i++) {
+ COPY_4UBV(tmp, src);
+ src += srcComponents;
+ dst[0] = tmp[map[0]];
+ dst[1] = tmp[map[1]];
+ dst += 2;
+ }
+ break;
+ }
+}
+
+
+static void
+_mesa_swizzle_ubyte_image(GLcontext *ctx,
+ GLuint dimensions,
+ GLenum srcFormat,
+ const GLubyte *dstmap, GLint dstComponents,
+
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride, GLint dstImageStride,
+
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking )
+{
+ GLint srcComponents = _mesa_components_in_format(srcFormat);
+ GLubyte srcmap[6], map[4];
+ GLint i;
+
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, GL_UNSIGNED_BYTE);
+ const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
+ srcWidth, srcHeight, srcFormat, GL_UNSIGNED_BYTE);
+ const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
+ srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, GL_UNSIGNED_BYTE, 0, 0, 0);
+
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstZoffset * dstImageStride
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstComponents;
+
+ compute_component_mapping(srcFormat, GL_RGBA, srcmap);
+
+ for (i = 0; i < 4; i++)
+ map[i] = srcmap[dstmap[i]];
+
+ if (srcRowStride == srcWidth * srcComponents &&
+ (srcImageStride == srcWidth * srcHeight * srcComponents ||
+ srcDepth == 1)) {
+ swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
+ srcWidth * srcHeight * srcDepth);
+ }
+ else {
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ const GLubyte *srcRow = srcImage;
+ GLubyte *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ srcImage += srcImageStride;
+ dstImage += dstImageStride;
+ }
+ }
+}
+
+
+
+
/**
* Teximage storage routine for when a simple memcpy will do.
* 1D, 2D and 3D images supported.
*/
static void
-memcpy_texture(const struct gl_texture_format *dstFormat,
+memcpy_texture(GLuint dimensions,
+ const struct gl_texture_format *dstFormat,
GLvoid *dstAddr,
GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
GLint dstRowStride, GLint dstImageStride,
srcFormat, srcType);
const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
srcWidth, srcHeight, srcFormat, srcType);
- const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(srcPacking,
- srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
+ const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
+ srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
const GLint bytesPerImage = srcHeight * bytesPerRow;
const GLint bytesPerTexture = srcDepth * bytesPerImage;
baseInternalFormat == srcFormat &&
srcType == CHAN_TYPE) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
for (img = 0; img < srcDepth; img++) {
const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
srcWidth, srcFormat, srcType);
- GLchan *srcRow = (GLchan *) _mesa_image_address(srcPacking, srcAddr,
- srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
GLchan *dstRow = dstImage;
for (row = 0; row < srcHeight; row++) {
for (col = 0; col < srcWidth; col++) {
srcFormat == GL_DEPTH_COMPONENT &&
srcType == GL_FLOAT) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
for (img = 0; img < srcDepth; img++) {
GLubyte *dstRow = dstImage;
for (row = 0; row < srcHeight; row++) {
- const GLvoid *src = _mesa_image_address(srcPacking,
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
_mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) dstRow,
srcType, src, srcPacking);
srcFormat == GL_DEPTH_COMPONENT &&
srcType == GL_UNSIGNED_SHORT) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
GLubyte *dstRow = dstImage;
for (row = 0; row < srcHeight; row++) {
GLfloat depthTemp[MAX_WIDTH];
- const GLvoid *src = _mesa_image_address(srcPacking,
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
GLushort *dst16 = (GLushort *) dstRow;
_mesa_unpack_depth_span(ctx, srcWidth, depthTemp,
srcFormat == GL_RGB &&
srcType == GL_UNSIGNED_SHORT_5_6_5) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
srcFormat, srcType);
const GLubyte *src = (const GLubyte *)
- _mesa_image_address(srcPacking, srcAddr, srcWidth, srcHeight,
+ _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
srcFormat, srcType, 0, 0, 0);
GLubyte *dst = (GLubyte *) dstAddr
+ dstZoffset * dstImageStride
GLboolean
_mesa_texstore_rgba8888(STORE_PARAMS)
{
+ const GLuint ui = 1;
+ const GLubyte littleEndian = *((const GLubyte *) &ui);
+
+ (void)littleEndian;
ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
dstFormat == &_mesa_texformat_rgba8888_rev);
ASSERT(dstFormat->TexelBytes == 4);
((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
}
+#if 0
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcType == GL_UNSIGNED_BYTE &&
+ dstFormat == &_mesa_texformat_rgba8888 &&
+ littleEndian &&
+ can_swizzle(srcFormat)) {
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from GL_RGBA to dst format:
+ *
+ * FIXME - add !litteEndian and _rev varients:
+ */
+ dstmap[3] = 0;
+ dstmap[2] = 1;
+ dstmap[1] = 2;
+ dstmap[0] = 3;
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageStride,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+#endif
else {
/* general path */
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
/* simple memcpy path (little endian) */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
srcType == GL_UNSIGNED_INT_8_8_8_8)) {
/* simple memcpy path (big endian) */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
}
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_BYTE) {
+
+ int img, row, col;
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstZoffset * dstImageStride
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP];
+ dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP];
+ dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP];
+ dstRow[col * 4 + 3] = 0xff;
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ dstImage += dstImageStride;
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+
+ int img, row, col;
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstZoffset * dstImageStride
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP];
+ dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP];
+ dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP];
+ dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP];
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ dstImage += dstImageStride;
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from GL_RGBA to dst format:
+ */
+ dstmap[3] = 3; /* alpha */
+ dstmap[2] = 0; /* red */
+ dstmap[1] = 1; /* green */
+ dstmap[0] = 2; /* blue */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageStride,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
else {
/* general path */
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
srcType == GL_UNSIGNED_BYTE &&
littleEndian) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
for (img = 0; img < srcDepth; img++) {
const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
srcWidth, srcFormat, srcType);
- GLubyte *srcRow = (GLubyte *) _mesa_image_address(srcPacking, srcAddr,
- srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
GLubyte *dstRow = dstImage;
for (row = 0; row < srcHeight; row++) {
for (col = 0; col < srcWidth; col++) {
srcType == GL_UNSIGNED_BYTE &&
littleEndian) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
for (img = 0; img < srcDepth; img++) {
const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
srcWidth, srcFormat, srcType);
- GLubyte *srcRow = (GLubyte *) _mesa_image_address(srcPacking, srcAddr,
- srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
GLubyte *dstRow = dstImage;
for (row = 0; row < srcHeight; row++) {
for (col = 0; col < srcWidth; col++) {
srcFormat == GL_BGRA &&
srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
srcFormat == GL_BGRA &&
srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
srcType == GL_UNSIGNED_BYTE &&
littleEndian) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
baseInternalFormat == GL_RGB &&
srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
baseInternalFormat == srcFormat &&
srcType == GL_UNSIGNED_BYTE) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
srcFormat == GL_COLOR_INDEX &&
srcType == GL_UNSIGNED_BYTE) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
for (img = 0; img < srcDepth; img++) {
GLubyte *dstRow = dstImage;
for (row = 0; row < srcHeight; row++) {
- const GLvoid *src = _mesa_image_address(srcPacking,
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
_mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
srcType, src, srcPacking,
ASSERT(baseInternalFormat == GL_YCBCR_MESA);
/* always just memcpy since no pixel transfer ops apply */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
baseInternalFormat == srcFormat &&
srcType == GL_FLOAT) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
baseInternalFormat == srcFormat &&
srcType == GL_HALF_FLOAT_ARB) {
/* simple memcpy path */
- memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ memcpy_texture(dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
dstRowStride, dstImageStride,
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
srcAddr, srcPacking);
* Check if an unpack PBO is active prior to fetching a texture image.
* If so, do bounds checking and map the buffer into main memory.
* Any errors detected will be recorded.
- * The caller _must_ call unmap_teximage_pbo() too!
+ * The caller _must_ call _mesa_unmap_teximage_pbo() too!
*/
-static const GLvoid *
-validate_pbo_teximage(GLcontext *ctx,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *unpack,
- const char *funcName)
+const GLvoid *
+_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ const char *funcName)
{
GLubyte *buf;
/* no PBO */
return pixels;
}
- if (!_mesa_validate_pbo_access(unpack, width, height, depth, format,
- type, pixels)) {
+ if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+ format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
return NULL;
}
- buf = ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB, unpack->BufferObj);
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, unpack->BufferObj);
if (!buf) {
_mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
return NULL;
* image.
* If so, do bounds checking and map the buffer into main memory.
* Any errors detected will be recorded.
- * The caller _must_ call unmap_teximage_pbo() too!
+ * The caller _must_ call _mesa_unmap_teximage_pbo() too!
*/
-static const GLvoid *
-validate_pbo_compressed_teximage(GLcontext *ctx,
+const GLvoid *
+_mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
GLsizei imageSize, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
const char *funcName)
return NULL;
}
- buf = ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB, packing->BufferObj);
+ buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, packing->BufferObj);
if (!buf) {
_mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
return NULL;
* This function must be called after either of the validate_pbo_*_teximage()
* functions. It unmaps the PBO buffer if it was mapped earlier.
*/
-static void
-unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack)
+void
+_mesa_unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack)
{
if (unpack->BufferObj->Name) {
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
/*
* This is the software fallback for Driver.TexImage1D()
* and Driver.CopyTexImage1D().
+ * \sa _mesa_store_teximage2d()
*/
void
_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
return;
}
- pixels = validate_pbo_teximage(ctx, width, 1, 1, format, type, pixels,
+ pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels,
packing, "glTexImage1D");
- if (!pixels)
+ if (!pixels) {
+ /* Note: we check for a NULL image pointer here, _after_ we allocated
+ * memory for the texture. That's what the GL spec calls for.
+ */
return;
-
- {
+ }
+ else {
const GLint dstRowStride = 0, dstImageStride = 0;
GLboolean success;
ASSERT(texImage->TexFormat->StoreImage);
texObj);
}
- unmap_teximage_pbo(ctx, packing);
+ _mesa_unmap_teximage_pbo(ctx, packing);
}
-/*
+/**
* This is the software fallback for Driver.TexImage2D()
* and Driver.CopyTexImage2D().
+ * We store the image in heap memory. We know nothing about on-board
+ * VRAM here. But since most DRI drivers rely on keeping a copy of all
+ * textures in main memory, this routine will typically be used by
+ * hardware drivers too.
+ *
* Reasons why a driver might override this function:
- * - Special memory allocation needs
- * - Unusual row/image strides
+ * - Special memory allocation needs (VRAM, AGP, etc)
+ * - Unusual row/image strides or padding
* - Special housekeeping
+ * - Using VRAM-based Pixel Buffer Objects
*/
void
_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
return;
}
- pixels = validate_pbo_teximage(ctx, width, height, 1, format, type, pixels,
- packing, "glTexImage2D");
- if (!pixels)
+ pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
+ pixels, packing, "glTexImage2D");
+ if (!pixels) {
+ /* Note: we check for a NULL image pointer here, _after_ we allocated
+ * memory for the texture. That's what the GL spec calls for.
+ */
return;
-
- {
+ }
+ else {
GLint dstRowStride, dstImageStride = 0;
GLboolean success;
if (texImage->IsCompressed) {
texObj);
}
- unmap_teximage_pbo(ctx, packing);
+ _mesa_unmap_teximage_pbo(ctx, packing);
}
-/*
+/**
* This is the software fallback for Driver.TexImage3D()
* and Driver.CopyTexImage3D().
+ * \sa _mesa_store_teximage2d()
*/
void
_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
return;
}
- pixels = validate_pbo_teximage(ctx, width, height, depth, format, type,
+ pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type,
pixels, packing, "glTexImage3D");
- if (!pixels)
+ if (!pixels) {
+ /* Note: we check for a NULL image pointer here, _after_ we allocated
+ * memory for the texture. That's what the GL spec calls for.
+ */
return;
-
- /* unpack image, apply transfer ops and store in texImage->Data */
- {
+ }
+ else {
GLint dstRowStride, dstImageStride;
GLboolean success;
if (texImage->IsCompressed) {
texObj);
}
- unmap_teximage_pbo(ctx, packing);
+ _mesa_unmap_teximage_pbo(ctx, packing);
}
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- pixels = validate_pbo_teximage(ctx, width, 1, 1, format, type, pixels,
+ pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels,
packing, "glTexSubImage1D");
if (!pixels)
return;
texObj);
}
- unmap_teximage_pbo(ctx, packing);
+ _mesa_unmap_teximage_pbo(ctx, packing);
}
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- pixels = validate_pbo_teximage(ctx, width, height, 1, format, type, pixels,
- packing, "glTexSubImage2D");
+ pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
+ pixels, packing, "glTexSubImage2D");
if (!pixels)
return;
texObj);
}
- unmap_teximage_pbo(ctx, packing);
+ _mesa_unmap_teximage_pbo(ctx, packing);
}
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- pixels = validate_pbo_teximage(ctx, width, height, depth, format, type,
+ pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type,
pixels, packing, "glTexSubImage3D");
if (!pixels)
return;
texObj);
}
- unmap_teximage_pbo(ctx, packing);
+ _mesa_unmap_teximage_pbo(ctx, packing);
}
return;
}
- data = validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+ data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
"glCompressedTexImage2D");
if (!data)
return;
texObj);
}
- unmap_teximage_pbo(ctx, &ctx->Unpack);
+ _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
}
ASSERT((xoffset & 3) == 0);
ASSERT((yoffset & 3) == 0);
- data = validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+ data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
"glCompressedTexSubImage2D");
if (!data)
return;
texObj);
}
- unmap_teximage_pbo(ctx, &ctx->Unpack);
+ _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
}
}
}
}
+
+
+
+/**
+ * This is the software fallback for Driver.GetTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_texture_object *texObj,
+ const struct gl_texture_image *texImage)
+{
+ GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+
+ if (ctx->Pack.BufferObj->Name) {
+ /* pack texture image into a PBO */
+ GLubyte *buf;
+ if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+ texImage->Height, texImage->Depth,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexImage(invalid PBO access)");
+ return;
+ }
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
+ return;
+ }
+ pixels = ADD_POINTERS(buf, pixels);
+ }
+ else if (!pixels) {
+ /* not an error */
+ return;
+ }
+
+ {
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ GLint img, row;
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ /* compute destination address in client memory */
+ GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ assert(dest);
+
+ if (format == GL_COLOR_INDEX) {
+ GLuint indexRow[MAX_WIDTH];
+ GLint col;
+ /* Can't use FetchTexel here because that returns RGBA */
+ if (texImage->TexFormat->IndexBits == 8) {
+ const GLubyte *src = (const GLubyte *) texImage->Data;
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[texImage->Width *
+ (img * texImage->Height + row) + col];
+ }
+ }
+ else if (texImage->TexFormat->IndexBits == 16) {
+ const GLushort *src = (const GLushort *) texImage->Data;
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[texImage->Width *
+ (img * texImage->Height + row) + col];
+ }
+ }
+ else {
+ _mesa_problem(ctx,
+ "Color index problem in _mesa_GetTexImage");
+ }
+ _mesa_pack_index_span(ctx, width, type, dest,
+ indexRow, &ctx->Pack,
+ 0 /* no image transfer */);
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ GLfloat depthRow[MAX_WIDTH];
+ GLint col;
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img,
+ depthRow + col);
+ }
+ _mesa_pack_depth_span(ctx, width, dest, type,
+ depthRow, &ctx->Pack);
+ }
+ else if (format == GL_YCBCR_MESA) {
+ /* No pixel transfer */
+ const GLint rowstride = texImage->RowStride;
+ MEMCPY(dest,
+ (const GLushort *) texImage->Data + row * rowstride,
+ width * sizeof(GLushort));
+ /* check for byte swapping */
+ if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
+ && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
+ (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
+ && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
+ if (!ctx->Pack.SwapBytes)
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ else if (ctx->Pack.SwapBytes) {
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ }
+ else {
+ /* general case: convert row to RGBA format */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLint col;
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
+ }
+ _mesa_pack_rgba_span_float(ctx, width,
+ (const GLfloat (*)[4]) rgba,
+ format, type, dest, &ctx->Pack,
+ 0 /* no image transfer */);
+ } /* format */
+ } /* row */
+ } /* img */
+ }
+
+ if (ctx->Pack.BufferObj->Name) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.GetCompressedTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ const struct gl_texture_object *texObj,
+ const struct gl_texture_image *texImage)
+{
+ if (ctx->Pack.BufferObj->Name) {
+ /* pack texture image into a PBO */
+ GLubyte *buf;
+ if ((const GLubyte *) img + texImage->CompressedSize >
+ (const GLubyte *) ctx->Pack.BufferObj->Size) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(invalid PBO access)");
+ return;
+ }
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(PBO is mapped)");
+ return;
+ }
+ img = ADD_POINTERS(buf, img);
+ }
+ else if (!img) {
+ /* not an error */
+ return;
+ }
+
+ /* just memcpy, no pixelstore or pixel transfer */
+ MEMCPY(img, texImage->Data, texImage->CompressedSize);
+
+ if (ctx->Pack.BufferObj->Name) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}