+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Store an rgb565 or rgb565_rev texture image.
+ */
+GLboolean
+_mesa_texstore_rgb565(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
+ dstFormat == &_mesa_texformat_rgb565_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgb565 &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_SHORT_5_6_5) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_BYTE &&
+ dims == 2) {
+ /* do optimized tex store */
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, srcType);
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
+ srcFormat, srcType, 0, 0, 0);
+ GLubyte *dst = (GLubyte *) dstAddr
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ GLint row, col;
+ for (row = 0; row < srcHeight; row++) {
+ const GLubyte *srcUB = (const GLubyte *) src;
+ GLushort *dstUS = (GLushort *) dst;
+ /* check for byteswapped format */
+ if (dstFormat == &_mesa_texformat_rgb565) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
+ srcUB += 3;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
+ srcUB += 3;
+ }
+ }
+ dst += dstRowStride;
+ src += srcRowStride;
+ }
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ /* check for byteswapped format */
+ if (dstFormat == &_mesa_texformat_rgb565) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 3;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 3;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
+ */
+GLboolean
+_mesa_texstore_rgba8888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
+ dstFormat == &_mesa_texformat_rgba8888_rev);
+ ASSERT(dstFormat->TexelBytes == 4);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgba8888 &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgba8888_rev &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
+ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ (srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_rgba8888) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_rgba8888_rev)) {
+ dstmap[3] = 0;
+ dstmap[2] = 1;
+ dstmap[1] = 2;
+ dstmap[0] = 3;
+ }
+ else {
+ dstmap[3] = 3;
+ dstmap[2] = 2;
+ dstmap[1] = 1;
+ dstmap[0] = 0;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ if (dstFormat == &_mesa_texformat_rgba8888) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]),
+ CHAN_TO_UBYTE(src[ACOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]),
+ CHAN_TO_UBYTE(src[ACOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_argb8888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
+ dstFormat == &_mesa_texformat_argb8888_rev);
+ ASSERT(dstFormat->TexelBytes == 4);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
+ /* simple memcpy path (little endian) */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888_rev &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8)) {
+ /* simple memcpy path (big endian) */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGB &&
+ (baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB) &&
+ srcType == GL_UNSIGNED_BYTE) {
+
+ int img, row, col;
+ 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 = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ 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;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGBA &&
+ baseInternalFormat == GL_RGBA &&
+ (srcType == GL_UNSIGNED_BYTE && littleEndian)) {
+ GLint img, row, col;
+ /* For some reason, streaming copies to write-combined regions
+ * are extremely sensitive to the characteristics of how the
+ * source data is retrieved. By reordering the source reads to
+ * be in-order, the speed of this operation increases by half.
+ * Strangely the same isn't required for the RGB path, above.
+ */
+ 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 = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ *(GLuint *)(dstRow + col * 4) = (srcRow[col * 4 + RCOMP] << 16 |
+ srcRow[col * 4 + GCOMP] << 8 |
+ srcRow[col * 4 + BCOMP] << 0 |
+ srcRow[col * 4 + ACOMP] << 24);
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGBA &&
+ baseInternalFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+
+ GLint img, row, col;
+ 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 = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ 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;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ (srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) {
+ dstmap[3] = 3; /* alpha */
+ dstmap[2] = 0; /* red */
+ dstmap[1] = 1; /* green */
+ dstmap[0] = 2; /* blue */
+ }
+ else {
+ assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_argb8888));
+ dstmap[3] = 2;
+ dstmap[2] = 1;
+ dstmap[1] = 0;
+ dstmap[0] = 3;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+
+ baseInternalFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ if (dstFormat == &_mesa_texformat_argb8888) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_rgb888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_rgb888);
+ ASSERT(dstFormat->TexelBytes == 3);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_BGR &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* extract RGB from RGBA */
+ GLint img, row, col;
+ 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 = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
+ dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
+ dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ dstmap[0] = 2;
+ dstmap[1] = 1;
+ dstmap[2] = 0;
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 3,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = (const GLchan *) tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+#if 0
+ if (littleEndian) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
+ dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
+ dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
+ srcUB += 3;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = srcUB[BCOMP];
+ dstRow[col * 3 + 1] = srcUB[GCOMP];
+ dstRow[col * 3 + 2] = srcUB[RCOMP];
+ srcUB += 3;
+ }
+ }
+#else
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
+ dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
+ dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
+ src += 3;
+ }
+#endif
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_bgr888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_bgr888);
+ ASSERT(dstFormat->TexelBytes == 3);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* extract BGR from RGBA */
+ int img, row, col;
+ 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 = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
+ dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
+ dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ dstmap[0] = 0;
+ dstmap[1] = 1;
+ dstmap[2] = 2;
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 3,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = (const GLchan *) tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
+ dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
+ dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
+ src += 3;
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_argb4444(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
+ dstFormat == &_mesa_texformat_argb4444_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb4444 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ if (dstFormat == &_mesa_texformat_argb4444) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+
+GLboolean
+_mesa_texstore_argb1555(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
+ dstFormat == &_mesa_texformat_argb1555_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb1555 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src =tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ if (dstFormat == &_mesa_texformat_argb1555) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_al88(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_al88 ||
+ dstFormat == &_mesa_texformat_al88_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_al88 &&
+ baseInternalFormat == GL_LUMINANCE_ALPHA &&
+ srcFormat == GL_LUMINANCE_ALPHA &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ littleEndian &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_al88) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) {
+ dstmap[0] = 0;
+ dstmap[1] = 3;
+ }
+ else {
+ dstmap[0] = 3;
+ dstmap[1] = 0;
+ }
+ dstmap[2] = ZERO; /* ? */
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 2,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ if (dstFormat == &_mesa_texformat_al88) {
+ for (col = 0; col < srcWidth; col++) {
+ /* src[0] is luminance, src[1] is alpha */
+ dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
+ CHAN_TO_UBYTE(src[0]) );
+ src += 2;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ /* src[0] is luminance, src[1] is alpha */
+ dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
+ CHAN_TO_UBYTE(src[0]) );
+ src += 2;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_rgb332(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_rgb332);
+ ASSERT(dstFormat->TexelBytes == 1);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 3;
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
+ */
+GLboolean
+_mesa_texstore_a8(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_a8 ||
+ dstFormat == &_mesa_texformat_l8 ||
+ dstFormat == &_mesa_texformat_i8);
+ ASSERT(dstFormat->TexelBytes == 1);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if (dstFormat == &_mesa_texformat_a8) {
+ dstmap[0] = 3;
+ }
+ else {
+ dstmap[0] = 0;
+ }
+ dstmap[1] = ZERO; /* ? */
+ dstmap[2] = ZERO; /* ? */
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 1,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col] = CHAN_TO_UBYTE(src[col]);
+ }
+ dstRow += dstRowStride;
+ src += srcWidth;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+
+GLboolean
+_mesa_texstore_ci8(TEXSTORE_PARAMS)
+{
+ (void) dims; (void) baseInternalFormat;
+ ASSERT(dstFormat == &_mesa_texformat_ci8);
+ ASSERT(dstFormat->TexelBytes == 1);
+ ASSERT(baseInternalFormat == GL_COLOR_INDEX);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcFormat == GL_COLOR_INDEX &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ 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,
+ ctx->_ImageTransferState);
+ dstRow += dstRowStride;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
+ */
+GLboolean
+_mesa_texstore_ycbcr(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+ (void) ctx; (void) dims; (void) baseInternalFormat;
+
+ ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
+ (dstFormat == &_mesa_texformat_ycbcr_rev));
+ ASSERT(dstFormat->TexelBytes == 2);
+ ASSERT(ctx->Extensions.MESA_ycbcr_texture);
+ ASSERT(srcFormat == GL_YCBCR_MESA);
+ ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
+ (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
+ ASSERT(baseInternalFormat == GL_YCBCR_MESA);
+
+ /* always just memcpy since no pixel transfer ops apply */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+
+ /* Check if we need byte swapping */
+ /* XXX the logic here _might_ be wrong */
+ if (srcPacking->SwapBytes ^
+ (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
+ (dstFormat == &_mesa_texformat_ycbcr_rev) ^
+ !littleEndian) {
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_swap2((GLushort *) dstRow, srcWidth);
+ dstRow += dstRowStride;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Store a combined depth/stencil texture image.
+ */
+GLboolean
+_mesa_texstore_z24_s8(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_z24_s8);
+ ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
+ ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes) {
+ /* simple path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLint srcRowStride
+ = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
+ / sizeof(GLuint);
+ GLint img, row;
+
+ for (img = 0; img < srcDepth; img++) {
+ GLuint *dstRow = (GLuint *) dstAddr
+ + dstImageOffsets[dstZoffset + img]
+ + dstYoffset * dstRowStride / sizeof(GLuint)
+ + dstXoffset;
+ const GLuint *src
+ = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ GLubyte stencil[MAX_WIDTH];
+ GLint i;
+ /* the 24 depth bits will be in the high position: */
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT, /* dst type */
+ dstRow, /* dst addr */
+ (GLfloat) 0xffffff, /* depthScale */
+ srcType, src, srcPacking);
+ /* get the 8-bit stencil values */
+ _mesa_unpack_stencil_span(ctx, srcWidth,
+ GL_UNSIGNED_BYTE, /* dst type */
+ stencil, /* dst addr */
+ srcType, src, srcPacking,
+ ctx->_ImageTransferState);
+ /* merge stencil values into depth values */
+ for (i = 0; i < srcWidth; i++)
+ dstRow[i] |= stencil[i];
+
+ src += srcRowStride;
+ dstRow += dstRowStride / sizeof(GLuint);
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Store an image in any of the formats:
+ * _mesa_texformat_rgba_float32
+ * _mesa_texformat_rgb_float32
+ * _mesa_texformat_alpha_float32
+ * _mesa_texformat_luminance_float32
+ * _mesa_texformat_luminance_alpha_float32
+ * _mesa_texformat_intensity_float32
+ */
+GLboolean
+_mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
+{
+ const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
+ dstFormat == &_mesa_texformat_rgb_float32 ||
+ dstFormat == &_mesa_texformat_alpha_float32 ||
+ dstFormat == &_mesa_texformat_luminance_float32 ||
+ dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
+ dstFormat == &_mesa_texformat_intensity_float32);
+ ASSERT(baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB ||
+ baseInternalFormat == GL_ALPHA ||
+ baseInternalFormat == GL_LUMINANCE ||
+ baseInternalFormat == GL_LUMINANCE_ALPHA ||
+ baseInternalFormat == GL_INTENSITY);
+ ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == GL_FLOAT) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLfloat *srcRow = tempImage;
+ GLint bytesPerRow;
+ GLint img, row;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ bytesPerRow = srcWidth * components * sizeof(GLfloat);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_memcpy(dstRow, srcRow, bytesPerRow);
+ dstRow += dstRowStride;
+ srcRow += srcWidth * components;
+ }
+ }
+
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * As above, but store 16-bit floats.
+ */
+GLboolean
+_mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
+{
+ const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
+ dstFormat == &_mesa_texformat_rgb_float16 ||
+ dstFormat == &_mesa_texformat_alpha_float16 ||
+ dstFormat == &_mesa_texformat_luminance_float16 ||
+ dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
+ dstFormat == &_mesa_texformat_intensity_float16);
+ ASSERT(baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB ||
+ baseInternalFormat == GL_ALPHA ||
+ baseInternalFormat == GL_LUMINANCE ||
+ baseInternalFormat == GL_LUMINANCE_ALPHA ||
+ baseInternalFormat == GL_INTENSITY);
+ ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == GL_HALF_FLOAT_ARB) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLfloat *src = tempImage;
+ GLint img, row;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
+ GLint i;
+ for (i = 0; i < srcWidth * components; i++) {
+ dstTexel[i] = _mesa_float_to_half(src[i]);
+ }
+ dstRow += dstRowStride;
+ src += srcWidth * components;
+ }
+ }
+
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+#if FEATURE_EXT_texture_sRGB
+GLboolean
+_mesa_texstore_srgb8(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+ const struct gl_texture_format *newDstFormat;
+ StoreTexImageFunc store;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_srgb8);
+
+ /* reuse normal rgb texstore code */
+ if (littleEndian) {
+ newDstFormat = &_mesa_texformat_bgr888;
+ store = _mesa_texstore_bgr888;
+ }
+ else {
+ newDstFormat = &_mesa_texformat_rgb888;
+ store = _mesa_texstore_rgb888;
+ }
+
+ k = store(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_srgba8(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_srgba8);
+
+ /* reuse normal rgba texstore code */
+ if (littleEndian)
+ newDstFormat = &_mesa_texformat_rgba8888_rev;
+ else
+ newDstFormat = &_mesa_texformat_rgba8888;
+
+ k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_sl8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sl8);
+
+ newDstFormat = &_mesa_texformat_l8;
+
+ /* _mesa_textore_a8 handles luminance8 too */
+ k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_sla8(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sla8);
+
+ /* reuse normal luminance/alpha texstore code */
+ if (littleEndian)
+ newDstFormat = &_mesa_texformat_al88;
+ else
+ newDstFormat = &_mesa_texformat_al88_rev;
+
+ k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/**
+ * 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!
+ */
+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;
+ }
+ 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 = (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);
+}
+
+
+/**
+ * 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!
+ */
+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;
+ }
+ if ((const GLubyte *) pixels + imageSize >
+ ((const GLubyte *) 0) + 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);
+ }
+}
+
+
+
+/**
+ * Adaptor for fetching a GLchan texel from a float-valued texture.
+ */
+static void
+fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texelOut)
+{
+ GLfloat temp[4];
+ ASSERT(texImage->FetchTexelf);
+ texImage->FetchTexelf(texImage, i, j, k, temp);
+ if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
+ texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* just one channel */
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
+ }
+ else {
+ /* four channels */
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
+ }
+}
+
+
+/**
+ * Adaptor for fetching a float texel from a GLchan-valued texture.
+ */
+static void
+fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texelOut)
+{
+ GLchan temp[4];
+ ASSERT(texImage->FetchTexelc);
+ texImage->FetchTexelc(texImage, i, j, k, temp);
+ if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
+ texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* just one channel */
+ texelOut[0] = CHAN_TO_FLOAT(temp[0]);
+ }
+ else {
+ /* four channels */
+ texelOut[0] = CHAN_TO_FLOAT(temp[0]);
+ texelOut[1] = CHAN_TO_FLOAT(temp[1]);
+ texelOut[2] = CHAN_TO_FLOAT(temp[2]);
+ texelOut[3] = CHAN_TO_FLOAT(temp[3]);
+ }
+}
+
+
+/**
+ * Initialize the texture image's FetchTexelc and FetchTexelf methods.
+ */
+static void
+set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
+{
+ ASSERT(dims == 1 || dims == 2 || dims == 3);
+ ASSERT(texImage->TexFormat);
+
+ switch (dims) {
+ case 1:
+ texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
+ texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
+ break;
+ case 2:
+ texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
+ texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
+ break;
+ case 3:
+ texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
+ texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
+ break;
+ default:
+ ;
+ }