X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Ftexstore.c;h=5f30e03d06a7cfc266841c4e78901ac479f2d89b;hb=c1f2f9090bcca309b9aeef7ae57acc280704db81;hp=56a72507f96e5413f790082b6b009693fc928813;hpb=701987c877b5346f39b2258c45cf2b6c989fd9cc;p=mesa.git diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 56a72507f96..5f30e03d06a 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -1,6 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 6.1 + * Version: 6.3 * * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * @@ -65,7 +65,23 @@ #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 @@ -77,8 +93,11 @@ static const GLint ZERO = 1000, ONE = 1001; */ 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: @@ -111,6 +130,13 @@ compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, 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; @@ -134,7 +160,12 @@ compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, _mesa_problem(NULL, "Unexpected logicalBaseFormat"); map[0] = map[1] = 0; } - } + break; + default: + _mesa_problem(NULL, "Unexpected logicalBaseFormat"); + map[0] = map[1] = 0; + break; + } } @@ -227,7 +258,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, /* 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, @@ -299,7 +330,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, 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); @@ -319,7 +350,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, 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 || @@ -449,7 +480,7 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, 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); @@ -473,7 +504,7 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, 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 || @@ -515,6 +546,114 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, } +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. @@ -522,7 +661,8 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, * 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, @@ -535,8 +675,8 @@ memcpy_texture(const struct gl_texture_format *dstFormat, 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; @@ -626,7 +766,8 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, 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); @@ -645,8 +786,8 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, 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++) { @@ -701,6 +842,7 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, GLboolean _mesa_texstore_depth_component_float32(STORE_PARAMS) { + (void) dims; ASSERT(dstFormat == &_mesa_texformat_depth_component_float32); ASSERT(dstFormat->TexelBytes == sizeof(GLfloat)); @@ -710,7 +852,8 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS) 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); @@ -725,7 +868,7 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS) 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); @@ -744,6 +887,7 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS) GLboolean _mesa_texstore_depth_component16(STORE_PARAMS) { + (void) dims; ASSERT(dstFormat == &_mesa_texformat_depth_component16); ASSERT(dstFormat->TexelBytes == sizeof(GLushort)); @@ -753,7 +897,8 @@ _mesa_texstore_depth_component16(STORE_PARAMS) 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); @@ -769,7 +914,7 @@ _mesa_texstore_depth_component16(STORE_PARAMS) 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, @@ -803,7 +948,8 @@ _mesa_texstore_rgb565(STORE_PARAMS) 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); @@ -818,7 +964,7 @@ _mesa_texstore_rgb565(STORE_PARAMS) 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 @@ -896,6 +1042,10 @@ _mesa_texstore_rgb565(STORE_PARAMS) 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); @@ -907,11 +1057,39 @@ _mesa_texstore_rgba8888(STORE_PARAMS) ((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, @@ -979,7 +1157,8 @@ _mesa_texstore_argb8888(STORE_PARAMS) ((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); @@ -992,11 +1171,96 @@ _mesa_texstore_argb8888(STORE_PARAMS) ((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, @@ -1062,7 +1326,8 @@ _mesa_texstore_rgb888(STORE_PARAMS) 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); @@ -1080,8 +1345,8 @@ _mesa_texstore_rgb888(STORE_PARAMS) 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++) { @@ -1103,7 +1368,7 @@ _mesa_texstore_rgb888(STORE_PARAMS) srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); - const GLchan *src = (const GLubyte *) tempImage; + const GLchan *src = (const GLchan *) tempImage; GLubyte *dstImage = (GLubyte *) dstAddr + dstZoffset * dstImageStride + dstYoffset * dstRowStride @@ -1166,7 +1431,8 @@ _mesa_texstore_bgr888(STORE_PARAMS) 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); @@ -1184,8 +1450,8 @@ _mesa_texstore_bgr888(STORE_PARAMS) 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++) { @@ -1207,7 +1473,7 @@ _mesa_texstore_bgr888(STORE_PARAMS) srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); - const GLchan *src = (const GLubyte *) tempImage; + const GLchan *src = (const GLchan *) tempImage; GLubyte *dstImage = (GLubyte *) dstAddr + dstZoffset * dstImageStride + dstYoffset * dstRowStride @@ -1249,7 +1515,8 @@ _mesa_texstore_argb4444(STORE_PARAMS) 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); @@ -1318,7 +1585,8 @@ _mesa_texstore_argb1555(STORE_PARAMS) 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); @@ -1390,7 +1658,8 @@ _mesa_texstore_al88(STORE_PARAMS) 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); @@ -1453,7 +1722,8 @@ _mesa_texstore_rgb332(STORE_PARAMS) 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); @@ -1510,7 +1780,8 @@ _mesa_texstore_a8(STORE_PARAMS) 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); @@ -1553,6 +1824,7 @@ _mesa_texstore_a8(STORE_PARAMS) GLboolean _mesa_texstore_ci8(STORE_PARAMS) { + (void) dims; (void) baseInternalFormat; ASSERT(dstFormat == &_mesa_texformat_ci8); ASSERT(dstFormat->TexelBytes == 1); ASSERT(baseInternalFormat == GL_COLOR_INDEX); @@ -1562,7 +1834,8 @@ _mesa_texstore_ci8(STORE_PARAMS) 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); @@ -1577,7 +1850,7 @@ _mesa_texstore_ci8(STORE_PARAMS) 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, @@ -1599,6 +1872,7 @@ _mesa_texstore_ycbcr(STORE_PARAMS) { const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); + (void) ctx; (void) dims; (void) baseInternalFormat; ASSERT((dstFormat == &_mesa_texformat_ycbcr) || (dstFormat == &_mesa_texformat_ycbcr_rev)); @@ -1610,7 +1884,8 @@ _mesa_texstore_ycbcr(STORE_PARAMS) 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); @@ -1674,7 +1949,8 @@ _mesa_texstore_rgba_float32(STORE_PARAMS) 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); @@ -1741,7 +2017,8 @@ _mesa_texstore_rgba_float16(STORE_PARAMS) 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); @@ -1785,61 +2062,96 @@ _mesa_texstore_rgba_float16(STORE_PARAMS) /** - * Validate acces to a PBO for texture data. - * - * \todo If the PBO is really resident in VRAM, this won't work; the - * device driver should check for that and do the right thing. + * 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 _mesa_unmap_teximage_pbo() too! */ -static const GLvoid * -validate_pbo_teximage( GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *unpack ) +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; + if (unpack->BufferObj->Name == 0) { /* no PBO */ return pixels; } - else if (_mesa_validate_pbo_access(unpack, width, height, depth, format, - type, pixels)) { - return ADD_POINTERS(unpack->BufferObj->Data, 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; } - /* bad access! */ - return NULL; + + 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; + } + + return ADD_POINTERS(buf, pixels); } /** - * Validate that unpacking compressed texture image data from a PBO - * won't go out of bounds. - * - * \todo If the PBO is really resident in VRAM, this won't work; the - * device driver should check for that and do the right thing. + * Check if an unpack PBO is active prior to fetching a compressed texture + * image. + * If so, do bounds checking and map the buffer into main memory. + * Any errors detected will be recorded. + * The caller _must_ call _mesa_unmap_teximage_pbo() too! */ -static const GLvoid * -validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing) +const GLvoid * +_mesa_validate_pbo_compressed_teximage(GLcontext *ctx, + GLsizei imageSize, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + const char *funcName) { + GLubyte *buf; + if (packing->BufferObj->Name == 0) { /* not using a PBO - return pointer unchanged */ return pixels; } - else { - /* using a PBO */ - if ((const GLubyte *) pixels + imageSize > - (const GLubyte *) packing->BufferObj->Size) { - /* out of bounds read! */ - return NULL; - } - /* OK! */ - return ADD_POINTERS(packing->BufferObj->Data, pixels); + if ((const GLubyte *) pixels + imageSize > + (const GLubyte *) packing->BufferObj->Size) { + /* out of bounds read! */ + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); + return NULL; + } + + 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; } + + return ADD_POINTERS(buf, pixels); } +/** + * This function must be called after either of the validate_pbo_*_teximage() + * functions. It unmaps the PBO buffer if it was mapped earlier. + */ +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, + unpack->BufferObj); + } +} + /* * 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, @@ -1852,6 +2164,7 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, { GLint postConvWidth = width; GLint sizeInBytes; + (void) border; if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); @@ -1876,11 +2189,15 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, return; } - pixels = validate_pbo_teximage(width, 1, 1, format, type, pixels, packing); - if (!pixels) + pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels, + packing, "glTexImage1D"); + 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); @@ -1893,7 +2210,6 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); - return; } } @@ -1903,16 +2219,24 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _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, @@ -1925,6 +2249,7 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, { GLint postConvWidth = width, postConvHeight = height; GLint texelBytes, sizeInBytes; + (void) border; if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, @@ -1952,12 +2277,15 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, return; } - pixels = validate_pbo_teximage(width, height, 1, - format, type, pixels, packing); - 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) { @@ -1976,7 +2304,6 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); - return; } } @@ -1986,13 +2313,16 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _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, @@ -2004,6 +2334,7 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { GLint texelBytes, sizeInBytes; + (void) border; /* choose the texture format */ assert(ctx->Driver.ChooseTextureFormat); @@ -2026,13 +2357,15 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, return; } - pixels = validate_pbo_teximage(width, height, depth, - format, type, pixels, packing); - if (!pixels) + pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type, + pixels, packing, "glTexImage3D"); + 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) { @@ -2053,7 +2386,6 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); - return; } } @@ -2063,6 +2395,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2080,8 +2414,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - pixels = validate_pbo_teximage(width, 1, 1, - format, type, pixels, packing); + pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels, + packing, "glTexSubImage1D"); if (!pixels) return; @@ -2098,7 +2432,6 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); - return; } } @@ -2108,6 +2441,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2125,8 +2460,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - pixels = validate_pbo_teximage(width, height, 1, - format, type, pixels, packing); + pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, + pixels, packing, "glTexSubImage2D"); if (!pixels) return; @@ -2150,7 +2485,6 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); - return; } } @@ -2160,6 +2494,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2176,8 +2512,8 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - pixels = validate_pbo_teximage(width, height, depth, - format, type, pixels, packing); + pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type, + pixels, packing, "glTexSubImage3D"); if (!pixels) return; @@ -2203,7 +2539,6 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); - return; } } @@ -2213,6 +2548,8 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2228,6 +2565,13 @@ _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) internalFormat; + (void) width; (void) border; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -2243,6 +2587,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { + (void) width; (void) height; (void) border; + /* This is pretty simple, basically just do a memcpy without worrying * about the usual image unpacking or image transfer operations. */ @@ -2268,7 +2614,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, return; } - data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack); + data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack, + "glCompressedTexImage2D"); if (!data) return; @@ -2282,6 +2629,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); } @@ -2299,6 +2648,14 @@ _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) internalFormat; + (void) width; (void) height; (void) depth; + (void) border; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -2316,6 +2673,13 @@ _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) xoffset; (void) width; + (void) format; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -2336,6 +2700,7 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, GLint i, rows; GLubyte *dest; const GLubyte *src; + (void) format; /* these should have been caught sooner */ ASSERT((width & 3) == 0 || width == 2 || width == 1); @@ -2343,7 +2708,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, ASSERT((xoffset & 3) == 0); ASSERT((yoffset & 3) == 0); - data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack); + data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack, + "glCompressedTexSubImage2D"); if (!data) return; @@ -2372,6 +2738,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); } @@ -2389,6 +2757,14 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) xoffset; (void) yoffset; (void) zoffset; + (void) width; (void) height; (void) depth; + (void) format; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -3376,10 +3752,13 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target, * all aspect ratios). This can be made a lot faster, but I don't * really care enough... */ -void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride, - GLint srcWidth, GLint srcHeight, - GLint dstWidth, GLint dstHeight, - const GLvoid *srcImage, GLvoid *dstImage ) +void +_mesa_rescale_teximage2d (GLuint bytesPerPixel, + GLuint srcStrideInPixels, + GLuint dstRowStride, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage) { GLint row, col; @@ -3388,7 +3767,7 @@ void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride, GLint srcRow = row HOP hScale; \ for ( col = 0 ; col < dstWidth ; col++ ) { \ GLint srcCol = col WOP wScale; \ - dst[col] = src[srcRow * srcWidth + srcCol]; \ + dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ } \ dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ } \ @@ -3398,9 +3777,9 @@ do { \ const TYPE *src = (const TYPE *)srcImage; \ TYPE *dst = (TYPE *)dstImage; \ \ - if ( srcHeight <= dstHeight ) { \ + if ( srcHeight < dstHeight ) { \ const GLint hScale = dstHeight / srcHeight; \ - if ( srcWidth <= dstWidth ) { \ + if ( srcWidth < dstWidth ) { \ const GLint wScale = dstWidth / srcWidth; \ INNER_LOOP( TYPE, /, / ); \ } \ @@ -3411,7 +3790,7 @@ do { \ } \ else { \ const GLint hScale = srcHeight / dstHeight; \ - if ( srcWidth <= dstWidth ) { \ + if ( srcWidth < dstWidth ) { \ const GLint wScale = dstWidth / srcWidth; \ INNER_LOOP( TYPE, *, / ); \ } \ @@ -3472,3 +3851,177 @@ _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight, } } } + + + +/** + * 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); + } +}