2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
65 #include "texcompress.h"
66 #include "texformat.h"
79 * Return GL_TRUE if the given image format is one that be converted
80 * to another format by swizzling.
83 can_swizzle(GLenum logicalBaseFormat)
85 switch (logicalBaseFormat) {
88 case GL_LUMINANCE_ALPHA:
122 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
123 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
124 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
125 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
128 static const struct {
131 GLubyte from_rgba[6];
132 } mappings[MAX_IDX] =
142 MAP4(ZERO, ZERO, ZERO, 0),
173 MAP4(0, ZERO, ZERO, ONE),
179 MAP4(ZERO, 0, ZERO, ONE),
185 MAP4(ZERO, ZERO, 0, ONE),
211 * Convert a GL image format enum to an IDX_* value (see above).
214 get_map_idx(GLenum value)
217 case GL_LUMINANCE: return IDX_LUMINANCE;
218 case GL_ALPHA: return IDX_ALPHA;
219 case GL_INTENSITY: return IDX_INTENSITY;
220 case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA;
221 case GL_RGB: return IDX_RGB;
222 case GL_RGBA: return IDX_RGBA;
223 case GL_RED: return IDX_RED;
224 case GL_GREEN: return IDX_GREEN;
225 case GL_BLUE: return IDX_BLUE;
226 case GL_BGR: return IDX_BGR;
227 case GL_BGRA: return IDX_BGRA;
228 case GL_ABGR_EXT: return IDX_ABGR;
230 _mesa_problem(NULL, "Unexpected inFormat");
237 * When promoting texture formats (see below) we need to compute the
238 * mapping of dest components back to source components.
239 * This function does that.
240 * \param inFormat the incoming format of the texture
241 * \param outFormat the final texture format
242 * \return map[6] a full 6-component map
245 compute_component_mapping(GLenum inFormat, GLenum outFormat,
248 const int inFmt = get_map_idx(inFormat);
249 const int outFmt = get_map_idx(outFormat);
250 const GLubyte *in2rgba = mappings[inFmt].to_rgba;
251 const GLubyte *rgba2out = mappings[outFmt].from_rgba;
254 for (i = 0; i < 4; i++)
255 map[i] = in2rgba[rgba2out[i]];
261 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
262 inFormat, _mesa_lookup_enum_by_nr(inFormat),
263 outFormat, _mesa_lookup_enum_by_nr(outFormat),
274 #if !FEATURE_convolve
276 _mesa_adjust_image_for_convolution(GLcontext *ctx, GLuint dims,
277 GLsizei *srcWidth, GLsizei *srcHeight)
285 * Make a temporary (color) texture image with GLfloat components.
286 * Apply all needed pixel unpacking and pixel transfer operations.
287 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
288 * Suppose the user specifies GL_LUMINANCE as the internal texture format
289 * but the graphics hardware doesn't support luminance textures. So, might
290 * use an RGB hardware format instead.
291 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
293 * \param ctx the rendering context
294 * \param dims image dimensions: 1, 2 or 3
295 * \param logicalBaseFormat basic texture derived from the user's
296 * internal texture format value
297 * \param textureBaseFormat the actual basic format of the texture
298 * \param srcWidth source image width
299 * \param srcHeight source image height
300 * \param srcDepth source image depth
301 * \param srcFormat source image format
302 * \param srcType source image type
303 * \param srcAddr source image address
304 * \param srcPacking source image pixel packing
305 * \return resulting image with format = textureBaseFormat and type = GLfloat.
308 make_temp_float_image(GLcontext *ctx, GLuint dims,
309 GLenum logicalBaseFormat,
310 GLenum textureBaseFormat,
311 GLint srcWidth, GLint srcHeight, GLint srcDepth,
312 GLenum srcFormat, GLenum srcType,
313 const GLvoid *srcAddr,
314 const struct gl_pixelstore_attrib *srcPacking)
316 GLuint transferOps = ctx->_ImageTransferState;
319 ASSERT(dims >= 1 && dims <= 3);
321 ASSERT(logicalBaseFormat == GL_RGBA ||
322 logicalBaseFormat == GL_RGB ||
323 logicalBaseFormat == GL_LUMINANCE_ALPHA ||
324 logicalBaseFormat == GL_LUMINANCE ||
325 logicalBaseFormat == GL_ALPHA ||
326 logicalBaseFormat == GL_INTENSITY ||
327 logicalBaseFormat == GL_COLOR_INDEX ||
328 logicalBaseFormat == GL_DEPTH_COMPONENT);
330 ASSERT(textureBaseFormat == GL_RGBA ||
331 textureBaseFormat == GL_RGB ||
332 textureBaseFormat == GL_LUMINANCE_ALPHA ||
333 textureBaseFormat == GL_LUMINANCE ||
334 textureBaseFormat == GL_ALPHA ||
335 textureBaseFormat == GL_INTENSITY ||
336 textureBaseFormat == GL_COLOR_INDEX ||
337 textureBaseFormat == GL_DEPTH_COMPONENT);
339 /* conventional color image */
341 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
342 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
343 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
344 /* need image convolution */
345 const GLuint preConvTransferOps
346 = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
347 const GLuint postConvTransferOps
348 = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
350 GLint convWidth, convHeight;
353 /* pre-convolution image buffer (3D) */
354 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
355 * 4 * sizeof(GLfloat));
359 /* post-convolution image buffer (2D) */
360 convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight
361 * 4 * sizeof(GLfloat));
363 _mesa_free(tempImage);
367 /* loop over 3D image slices */
368 for (img = 0; img < srcDepth; img++) {
369 GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4);
371 /* unpack and do transfer ops up to convolution */
372 for (row = 0; row < srcHeight; row++) {
373 const GLvoid *src = _mesa_image_address(dims, srcPacking,
374 srcAddr, srcWidth, srcHeight,
375 srcFormat, srcType, img, row, 0);
376 _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
377 srcFormat, srcType, src,
383 /* size after optional convolution */
384 convWidth = srcWidth;
385 convHeight = srcHeight;
390 GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
392 ASSERT(ctx->Pixel.Convolution1DEnabled);
393 _mesa_convolve_1d_image(ctx, &convWidth, src, convImage);
396 if (ctx->Pixel.Convolution2DEnabled) {
397 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
401 ASSERT(ctx->Pixel.Separable2DEnabled);
402 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
408 /* do post-convolution transfer and pack into tempImage */
410 const GLint logComponents
411 = _mesa_components_in_format(logicalBaseFormat);
412 const GLfloat *src = convImage;
413 GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
414 for (row = 0; row < convHeight; row++) {
415 _mesa_pack_rgba_span_float(ctx, convWidth,
416 (GLfloat (*)[4]) src,
417 logicalBaseFormat, GL_FLOAT,
418 dst, &ctx->DefaultPacking,
419 postConvTransferOps);
420 src += convWidth * 4;
421 dst += convWidth * logComponents;
424 } /* loop over 3D image slices */
426 _mesa_free(convImage);
428 /* might need these below */
429 srcWidth = convWidth;
430 srcHeight = convHeight;
434 const GLint components = _mesa_components_in_format(logicalBaseFormat);
435 const GLint srcStride = _mesa_image_row_stride(srcPacking,
436 srcWidth, srcFormat, srcType);
440 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
441 * components * sizeof(GLfloat));
446 for (img = 0; img < srcDepth; img++) {
448 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
452 for (row = 0; row < srcHeight; row++) {
453 _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
454 dst, srcFormat, srcType, src,
455 srcPacking, transferOps);
456 dst += srcWidth * components;
462 if (logicalBaseFormat != textureBaseFormat) {
464 GLint texComponents = _mesa_components_in_format(textureBaseFormat);
465 GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
470 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
471 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
472 textureBaseFormat == GL_LUMINANCE_ALPHA);
474 /* The actual texture format should have at least as many components
475 * as the logical texture format.
477 ASSERT(texComponents >= logComponents);
479 newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
480 * texComponents * sizeof(GLfloat));
482 _mesa_free(tempImage);
486 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
488 n = srcWidth * srcHeight * srcDepth;
489 for (i = 0; i < n; i++) {
491 for (k = 0; k < texComponents; k++) {
494 newImage[i * texComponents + k] = 0.0F;
496 newImage[i * texComponents + k] = 1.0F;
498 newImage[i * texComponents + k] = tempImage[i * logComponents + j];
502 _mesa_free(tempImage);
503 tempImage = newImage;
511 * Make a temporary (color) texture image with GLchan components.
512 * Apply all needed pixel unpacking and pixel transfer operations.
513 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
514 * Suppose the user specifies GL_LUMINANCE as the internal texture format
515 * but the graphics hardware doesn't support luminance textures. So, might
516 * use an RGB hardware format instead.
517 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
519 * \param ctx the rendering context
520 * \param dims image dimensions: 1, 2 or 3
521 * \param logicalBaseFormat basic texture derived from the user's
522 * internal texture format value
523 * \param textureBaseFormat the actual basic format of the texture
524 * \param srcWidth source image width
525 * \param srcHeight source image height
526 * \param srcDepth source image depth
527 * \param srcFormat source image format
528 * \param srcType source image type
529 * \param srcAddr source image address
530 * \param srcPacking source image pixel packing
531 * \return resulting image with format = textureBaseFormat and type = GLchan.
534 _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
535 GLenum logicalBaseFormat,
536 GLenum textureBaseFormat,
537 GLint srcWidth, GLint srcHeight, GLint srcDepth,
538 GLenum srcFormat, GLenum srcType,
539 const GLvoid *srcAddr,
540 const struct gl_pixelstore_attrib *srcPacking)
542 GLuint transferOps = ctx->_ImageTransferState;
543 const GLint components = _mesa_components_in_format(logicalBaseFormat);
544 GLboolean freeSrcImage = GL_FALSE;
546 GLchan *tempImage, *dst;
548 ASSERT(dims >= 1 && dims <= 3);
550 ASSERT(logicalBaseFormat == GL_RGBA ||
551 logicalBaseFormat == GL_RGB ||
552 logicalBaseFormat == GL_LUMINANCE_ALPHA ||
553 logicalBaseFormat == GL_LUMINANCE ||
554 logicalBaseFormat == GL_ALPHA ||
555 logicalBaseFormat == GL_INTENSITY);
557 ASSERT(textureBaseFormat == GL_RGBA ||
558 textureBaseFormat == GL_RGB ||
559 textureBaseFormat == GL_LUMINANCE_ALPHA ||
560 textureBaseFormat == GL_LUMINANCE ||
561 textureBaseFormat == GL_ALPHA ||
562 textureBaseFormat == GL_INTENSITY);
565 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
566 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
567 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
568 /* get convolved image */
569 GLfloat *convImage = make_temp_float_image(ctx, dims,
572 srcWidth, srcHeight, srcDepth,
574 srcAddr, srcPacking);
577 /* the convolved image is our new source image */
579 srcFormat = logicalBaseFormat;
581 srcPacking = &ctx->DefaultPacking;
582 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
584 freeSrcImage = GL_TRUE;
588 /* unpack and transfer the source image */
589 tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
590 * components * sizeof(GLchan));
595 for (img = 0; img < srcDepth; img++) {
596 const GLint srcStride = _mesa_image_row_stride(srcPacking,
600 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
604 for (row = 0; row < srcHeight; row++) {
605 _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
606 srcFormat, srcType, src, srcPacking,
608 dst += srcWidth * components;
613 /* If we made a temporary image for convolution, free it here */
615 _mesa_free((void *) srcAddr);
618 if (logicalBaseFormat != textureBaseFormat) {
619 /* one more conversion step */
620 GLint texComponents = _mesa_components_in_format(textureBaseFormat);
621 GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
626 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
627 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
628 textureBaseFormat == GL_LUMINANCE_ALPHA);
630 /* The actual texture format should have at least as many components
631 * as the logical texture format.
633 ASSERT(texComponents >= logComponents);
635 newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
636 * texComponents * sizeof(GLchan));
638 _mesa_free(tempImage);
642 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
644 n = srcWidth * srcHeight * srcDepth;
645 for (i = 0; i < n; i++) {
647 for (k = 0; k < texComponents; k++) {
650 newImage[i * texComponents + k] = 0;
652 newImage[i * texComponents + k] = CHAN_MAX;
654 newImage[i * texComponents + k] = tempImage[i * logComponents + j];
658 _mesa_free(tempImage);
659 tempImage = newImage;
667 * Copy GLubyte pixels from <src> to <dst> with swizzling.
668 * \param dst destination pixels
669 * \param dstComponents number of color components in destination pixels
670 * \param src source pixels
671 * \param srcComponents number of color components in source pixels
672 * \param map the swizzle mapping. map[X] says where to find the X component
673 * in the source image's pixels. For example, if the source image
674 * is GL_BGRA and X = red, map[0] yields 2.
675 * \param count number of pixels to copy/swizzle.
678 swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
679 GLuint srcComponents, const GLubyte *map, GLuint count)
681 #define SWZ_CPY(dst, src, count, dstComps, srcComps) \
684 for (i = 0; i < count; i++) { \
686 if (srcComps == 4) { \
687 COPY_4UBV(tmp, src); \
690 for (j = 0; j < srcComps; j++) { \
695 for (j = 0; j < dstComps; j++) { \
696 dst[j] = tmp[map[j]]; \
707 ASSERT(srcComponents <= 4);
708 ASSERT(dstComponents <= 4);
710 switch (dstComponents) {
712 switch (srcComponents) {
714 SWZ_CPY(dst, src, count, 4, 4);
717 SWZ_CPY(dst, src, count, 4, 3);
720 SWZ_CPY(dst, src, count, 4, 2);
723 SWZ_CPY(dst, src, count, 4, 1);
730 switch (srcComponents) {
732 SWZ_CPY(dst, src, count, 3, 4);
735 SWZ_CPY(dst, src, count, 3, 3);
738 SWZ_CPY(dst, src, count, 3, 2);
741 SWZ_CPY(dst, src, count, 3, 1);
748 switch (srcComponents) {
750 SWZ_CPY(dst, src, count, 2, 4);
753 SWZ_CPY(dst, src, count, 2, 3);
756 SWZ_CPY(dst, src, count, 2, 2);
759 SWZ_CPY(dst, src, count, 2, 1);
766 switch (srcComponents) {
768 SWZ_CPY(dst, src, count, 1, 4);
771 SWZ_CPY(dst, src, count, 1, 3);
774 SWZ_CPY(dst, src, count, 1, 2);
777 SWZ_CPY(dst, src, count, 1, 1);
791 static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE };
792 static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE };
794 /* Deal with the _REV input types:
796 static const GLubyte *
797 type_mapping( GLenum srcType )
800 case GL_UNSIGNED_BYTE:
802 case GL_UNSIGNED_INT_8_8_8_8:
803 return _mesa_little_endian() ? map_3210 : map_identity;
804 case GL_UNSIGNED_INT_8_8_8_8_REV:
805 return _mesa_little_endian() ? map_identity : map_3210;
811 /* Mapping required if input type is
813 static const GLubyte *
814 byteswap_mapping( GLboolean swapBytes,
821 case GL_UNSIGNED_BYTE:
823 case GL_UNSIGNED_INT_8_8_8_8:
824 case GL_UNSIGNED_INT_8_8_8_8_REV:
834 * Transfer a GLubyte texture image with component swizzling.
837 _mesa_swizzle_ubyte_image(GLcontext *ctx,
842 GLenum baseInternalFormat,
844 const GLubyte *rgba2dst,
845 GLuint dstComponents,
848 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
850 const GLuint *dstImageOffsets,
852 GLint srcWidth, GLint srcHeight, GLint srcDepth,
853 const GLvoid *srcAddr,
854 const struct gl_pixelstore_attrib *srcPacking )
856 GLint srcComponents = _mesa_components_in_format(srcFormat);
857 const GLubyte *srctype2ubyte, *swap;
858 GLubyte map[4], src2base[6], base2rgba[6];
860 const GLint srcRowStride =
861 _mesa_image_row_stride(srcPacking, srcWidth,
862 srcFormat, GL_UNSIGNED_BYTE);
863 const GLint srcImageStride
864 = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat,
866 const GLubyte *srcImage
867 = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr,
868 srcWidth, srcHeight, srcFormat,
869 GL_UNSIGNED_BYTE, 0, 0, 0);
873 /* Translate from src->baseInternal->GL_RGBA->dst. This will
874 * correctly deal with RGBA->RGB->RGBA conversions where the final
875 * A value must be 0xff regardless of the incoming alpha values.
877 compute_component_mapping(srcFormat, baseInternalFormat, src2base);
878 compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba);
879 swap = byteswap_mapping(srcPacking->SwapBytes, srcType);
880 srctype2ubyte = type_mapping(srcType);
883 for (i = 0; i < 4; i++)
884 map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]];
886 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
888 if (srcRowStride == dstRowStride &&
889 srcComponents == dstComponents &&
890 srcRowStride == srcWidth * srcComponents &&
892 /* 1 and 2D images only */
893 GLubyte *dstImage = (GLubyte *) dstAddr
894 + dstYoffset * dstRowStride
895 + dstXoffset * dstComponents;
896 swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
897 srcWidth * srcHeight);
901 for (img = 0; img < srcDepth; img++) {
902 const GLubyte *srcRow = srcImage;
903 GLubyte *dstRow = (GLubyte *) dstAddr
904 + dstImageOffsets[dstZoffset + img] * dstComponents
905 + dstYoffset * dstRowStride
906 + dstXoffset * dstComponents;
907 for (row = 0; row < srcHeight; row++) {
908 swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
909 dstRow += dstRowStride;
910 srcRow += srcRowStride;
912 srcImage += srcImageStride;
919 * Teximage storage routine for when a simple memcpy will do.
920 * No pixel transfer operations or special texel encodings allowed.
921 * 1D, 2D and 3D images supported.
924 memcpy_texture(GLcontext *ctx,
926 const struct gl_texture_format *dstFormat,
928 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
930 const GLuint *dstImageOffsets,
931 GLint srcWidth, GLint srcHeight, GLint srcDepth,
932 GLenum srcFormat, GLenum srcType,
933 const GLvoid *srcAddr,
934 const struct gl_pixelstore_attrib *srcPacking)
936 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
938 const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
939 srcWidth, srcHeight, srcFormat, srcType);
940 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
941 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
942 const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
945 /* XXX update/re-enable for dstImageOffsets array */
946 const GLint bytesPerImage = srcHeight * bytesPerRow;
947 const GLint bytesPerTexture = srcDepth * bytesPerImage;
948 GLubyte *dstImage = (GLubyte *) dstAddr
949 + dstZoffset * dstImageStride
950 + dstYoffset * dstRowStride
951 + dstXoffset * dstFormat->TexelBytes;
953 if (dstRowStride == srcRowStride &&
954 dstRowStride == bytesPerRow &&
955 ((dstImageStride == srcImageStride &&
956 dstImageStride == bytesPerImage) ||
959 ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
964 for (img = 0; img < srcDepth; img++) {
965 const GLubyte *srcRow = srcImage;
966 GLubyte *dstRow = dstImage;
967 for (row = 0; row < srcHeight; row++) {
968 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
969 dstRow += dstRowStride;
970 srcRow += srcRowStride;
972 srcImage += srcImageStride;
973 dstImage += dstImageStride;
979 for (img = 0; img < srcDepth; img++) {
980 const GLubyte *srcRow = srcImage;
981 GLubyte *dstRow = (GLubyte *) dstAddr
982 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
983 + dstYoffset * dstRowStride
984 + dstXoffset * dstFormat->TexelBytes;
985 for (row = 0; row < srcHeight; row++) {
986 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
987 dstRow += dstRowStride;
988 srcRow += srcRowStride;
990 srcImage += srcImageStride;
997 * Store an image in any of the formats:
998 * _mesa_texformat_rgba
999 * _mesa_texformat_rgb
1000 * _mesa_texformat_alpha
1001 * _mesa_texformat_luminance
1002 * _mesa_texformat_luminance_alpha
1003 * _mesa_texformat_intensity
1007 _mesa_texstore_rgba(TEXSTORE_PARAMS)
1009 const GLint components = _mesa_components_in_format(baseInternalFormat);
1011 ASSERT(dstFormat == &_mesa_texformat_rgba ||
1012 dstFormat == &_mesa_texformat_rgb ||
1013 dstFormat == &_mesa_texformat_alpha ||
1014 dstFormat == &_mesa_texformat_luminance ||
1015 dstFormat == &_mesa_texformat_luminance_alpha ||
1016 dstFormat == &_mesa_texformat_intensity);
1017 ASSERT(baseInternalFormat == GL_RGBA ||
1018 baseInternalFormat == GL_RGB ||
1019 baseInternalFormat == GL_ALPHA ||
1020 baseInternalFormat == GL_LUMINANCE ||
1021 baseInternalFormat == GL_LUMINANCE_ALPHA ||
1022 baseInternalFormat == GL_INTENSITY);
1023 ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan));
1025 if (!ctx->_ImageTransferState &&
1026 !srcPacking->SwapBytes &&
1027 baseInternalFormat == srcFormat &&
1028 srcType == CHAN_TYPE) {
1029 /* simple memcpy path */
1030 memcpy_texture(ctx, dims,
1031 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1034 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1035 srcAddr, srcPacking);
1037 else if (!ctx->_ImageTransferState &&
1038 !srcPacking->SwapBytes &&
1039 dstFormat == &_mesa_texformat_rgb &&
1040 srcFormat == GL_RGBA &&
1041 srcType == CHAN_TYPE) {
1042 /* extract RGB from RGBA */
1043 GLint img, row, col;
1044 for (img = 0; img < srcDepth; img++) {
1045 GLchan *dstImage = (GLchan *)
1046 ((GLubyte *) dstAddr
1047 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1048 + dstYoffset * dstRowStride
1049 + dstXoffset * dstFormat->TexelBytes);
1051 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1052 srcWidth, srcFormat, srcType);
1053 GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
1054 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1055 GLchan *dstRow = dstImage;
1056 for (row = 0; row < srcHeight; row++) {
1057 for (col = 0; col < srcWidth; col++) {
1058 dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
1059 dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
1060 dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
1062 dstRow += dstRowStride / sizeof(GLchan);
1063 srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
1067 else if (!ctx->_ImageTransferState &&
1068 CHAN_TYPE == GL_UNSIGNED_BYTE &&
1069 (srcType == GL_UNSIGNED_BYTE ||
1070 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1071 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1072 can_swizzle(baseInternalFormat) &&
1073 can_swizzle(srcFormat)) {
1075 const GLubyte *dstmap;
1078 /* dstmap - how to swizzle from RGBA to dst format:
1080 if (dstFormat == &_mesa_texformat_rgba) {
1081 dstmap = mappings[IDX_RGBA].from_rgba;
1084 else if (dstFormat == &_mesa_texformat_rgb) {
1085 dstmap = mappings[IDX_RGB].from_rgba;
1088 else if (dstFormat == &_mesa_texformat_alpha) {
1089 dstmap = mappings[IDX_ALPHA].from_rgba;
1092 else if (dstFormat == &_mesa_texformat_luminance) {
1093 dstmap = mappings[IDX_LUMINANCE].from_rgba;
1096 else if (dstFormat == &_mesa_texformat_luminance_alpha) {
1097 dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba;
1100 else if (dstFormat == &_mesa_texformat_intensity) {
1101 dstmap = mappings[IDX_INTENSITY].from_rgba;
1105 _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba");
1109 _mesa_swizzle_ubyte_image(ctx, dims,
1114 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1115 dstRowStride, dstImageOffsets,
1116 srcWidth, srcHeight, srcDepth, srcAddr,
1121 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1123 dstFormat->BaseFormat,
1124 srcWidth, srcHeight, srcDepth,
1125 srcFormat, srcType, srcAddr,
1127 const GLchan *src = tempImage;
1132 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1133 bytesPerRow = srcWidth * components * sizeof(GLchan);
1134 for (img = 0; img < srcDepth; img++) {
1135 GLubyte *dstRow = (GLubyte *) dstAddr
1136 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1137 + dstYoffset * dstRowStride
1138 + dstXoffset * dstFormat->TexelBytes;
1139 for (row = 0; row < srcHeight; row++) {
1140 _mesa_memcpy(dstRow, src, bytesPerRow);
1141 dstRow += dstRowStride;
1142 src += srcWidth * components;
1146 _mesa_free((void *) tempImage);
1153 * Store a 32-bit integer depth component texture image.
1156 _mesa_texstore_z32(TEXSTORE_PARAMS)
1158 const GLuint depthScale = 0xffffffff;
1160 ASSERT(dstFormat == &_mesa_texformat_z32);
1161 ASSERT(dstFormat->TexelBytes == sizeof(GLuint));
1163 if (ctx->Pixel.DepthScale == 1.0f &&
1164 ctx->Pixel.DepthBias == 0.0f &&
1165 !srcPacking->SwapBytes &&
1166 baseInternalFormat == GL_DEPTH_COMPONENT &&
1167 srcFormat == GL_DEPTH_COMPONENT &&
1168 srcType == GL_UNSIGNED_INT) {
1169 /* simple memcpy path */
1170 memcpy_texture(ctx, dims,
1171 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1174 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1175 srcAddr, srcPacking);
1180 for (img = 0; img < srcDepth; img++) {
1181 GLubyte *dstRow = (GLubyte *) dstAddr
1182 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1183 + dstYoffset * dstRowStride
1184 + dstXoffset * dstFormat->TexelBytes;
1185 for (row = 0; row < srcHeight; row++) {
1186 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1187 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1188 _mesa_unpack_depth_span(ctx, srcWidth,
1189 GL_UNSIGNED_INT, (GLuint *) dstRow,
1190 depthScale, srcType, src, srcPacking);
1191 dstRow += dstRowStride;
1201 * Store a 16-bit integer depth component texture image.
1204 _mesa_texstore_z16(TEXSTORE_PARAMS)
1206 const GLuint depthScale = 0xffff;
1208 ASSERT(dstFormat == &_mesa_texformat_z16);
1209 ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
1211 if (ctx->Pixel.DepthScale == 1.0f &&
1212 ctx->Pixel.DepthBias == 0.0f &&
1213 !srcPacking->SwapBytes &&
1214 baseInternalFormat == GL_DEPTH_COMPONENT &&
1215 srcFormat == GL_DEPTH_COMPONENT &&
1216 srcType == GL_UNSIGNED_SHORT) {
1217 /* simple memcpy path */
1218 memcpy_texture(ctx, dims,
1219 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1222 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1223 srcAddr, srcPacking);
1228 for (img = 0; img < srcDepth; img++) {
1229 GLubyte *dstRow = (GLubyte *) dstAddr
1230 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1231 + dstYoffset * dstRowStride
1232 + dstXoffset * dstFormat->TexelBytes;
1233 for (row = 0; row < srcHeight; row++) {
1234 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1235 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1236 GLushort *dst16 = (GLushort *) dstRow;
1237 _mesa_unpack_depth_span(ctx, srcWidth,
1238 GL_UNSIGNED_SHORT, dst16, depthScale,
1239 srcType, src, srcPacking);
1240 dstRow += dstRowStride;
1249 * Store an rgb565 or rgb565_rev texture image.
1252 _mesa_texstore_rgb565(TEXSTORE_PARAMS)
1254 ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
1255 dstFormat == &_mesa_texformat_rgb565_rev);
1256 ASSERT(dstFormat->TexelBytes == 2);
1258 if (!ctx->_ImageTransferState &&
1259 !srcPacking->SwapBytes &&
1260 dstFormat == &_mesa_texformat_rgb565 &&
1261 baseInternalFormat == GL_RGB &&
1262 srcFormat == GL_RGB &&
1263 srcType == GL_UNSIGNED_SHORT_5_6_5) {
1264 /* simple memcpy path */
1265 memcpy_texture(ctx, dims,
1266 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1269 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1270 srcAddr, srcPacking);
1272 else if (!ctx->_ImageTransferState &&
1273 !srcPacking->SwapBytes &&
1274 baseInternalFormat == GL_RGB &&
1275 srcFormat == GL_RGB &&
1276 srcType == GL_UNSIGNED_BYTE &&
1278 /* do optimized tex store */
1279 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
1280 srcFormat, srcType);
1281 const GLubyte *src = (const GLubyte *)
1282 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
1283 srcFormat, srcType, 0, 0, 0);
1284 GLubyte *dst = (GLubyte *) dstAddr
1285 + dstYoffset * dstRowStride
1286 + dstXoffset * dstFormat->TexelBytes;
1288 for (row = 0; row < srcHeight; row++) {
1289 const GLubyte *srcUB = (const GLubyte *) src;
1290 GLushort *dstUS = (GLushort *) dst;
1291 /* check for byteswapped format */
1292 if (dstFormat == &_mesa_texformat_rgb565) {
1293 for (col = 0; col < srcWidth; col++) {
1294 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
1299 for (col = 0; col < srcWidth; col++) {
1300 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
1304 dst += dstRowStride;
1305 src += srcRowStride;
1310 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1312 dstFormat->BaseFormat,
1313 srcWidth, srcHeight, srcDepth,
1314 srcFormat, srcType, srcAddr,
1316 const GLchan *src = tempImage;
1317 GLint img, row, col;
1320 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1321 for (img = 0; img < srcDepth; img++) {
1322 GLubyte *dstRow = (GLubyte *) dstAddr
1323 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1324 + dstYoffset * dstRowStride
1325 + dstXoffset * dstFormat->TexelBytes;
1326 for (row = 0; row < srcHeight; row++) {
1327 GLushort *dstUS = (GLushort *) dstRow;
1328 /* check for byteswapped format */
1329 if (dstFormat == &_mesa_texformat_rgb565) {
1330 for (col = 0; col < srcWidth; col++) {
1331 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
1332 CHAN_TO_UBYTE(src[GCOMP]),
1333 CHAN_TO_UBYTE(src[BCOMP]) );
1338 for (col = 0; col < srcWidth; col++) {
1339 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
1340 CHAN_TO_UBYTE(src[GCOMP]),
1341 CHAN_TO_UBYTE(src[BCOMP]) );
1345 dstRow += dstRowStride;
1348 _mesa_free((void *) tempImage);
1355 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1358 _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
1360 const GLboolean littleEndian = _mesa_little_endian();
1362 ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
1363 dstFormat == &_mesa_texformat_rgba8888_rev);
1364 ASSERT(dstFormat->TexelBytes == 4);
1366 if (!ctx->_ImageTransferState &&
1367 !srcPacking->SwapBytes &&
1368 dstFormat == &_mesa_texformat_rgba8888 &&
1369 baseInternalFormat == GL_RGBA &&
1370 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1371 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1372 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
1373 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
1374 /* simple memcpy path */
1375 memcpy_texture(ctx, dims,
1376 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1379 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1380 srcAddr, srcPacking);
1382 else if (!ctx->_ImageTransferState &&
1383 !srcPacking->SwapBytes &&
1384 dstFormat == &_mesa_texformat_rgba8888_rev &&
1385 baseInternalFormat == GL_RGBA &&
1386 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
1387 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1388 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1389 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
1390 /* simple memcpy path */
1391 memcpy_texture(ctx, dims,
1392 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1395 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1396 srcAddr, srcPacking);
1398 else if (!ctx->_ImageTransferState &&
1399 (srcType == GL_UNSIGNED_BYTE ||
1400 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1401 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1402 can_swizzle(baseInternalFormat) &&
1403 can_swizzle(srcFormat)) {
1407 /* dstmap - how to swizzle from RGBA to dst format:
1409 if ((littleEndian && dstFormat == &_mesa_texformat_rgba8888) ||
1410 (!littleEndian && dstFormat == &_mesa_texformat_rgba8888_rev)) {
1423 _mesa_swizzle_ubyte_image(ctx, dims,
1428 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1429 dstRowStride, dstImageOffsets,
1430 srcWidth, srcHeight, srcDepth, srcAddr,
1435 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1437 dstFormat->BaseFormat,
1438 srcWidth, srcHeight, srcDepth,
1439 srcFormat, srcType, srcAddr,
1441 const GLchan *src = tempImage;
1442 GLint img, row, col;
1445 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1446 for (img = 0; img < srcDepth; img++) {
1447 GLubyte *dstRow = (GLubyte *) dstAddr
1448 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1449 + dstYoffset * dstRowStride
1450 + dstXoffset * dstFormat->TexelBytes;
1451 for (row = 0; row < srcHeight; row++) {
1452 GLuint *dstUI = (GLuint *) dstRow;
1453 if (dstFormat == &_mesa_texformat_rgba8888) {
1454 for (col = 0; col < srcWidth; col++) {
1455 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
1456 CHAN_TO_UBYTE(src[GCOMP]),
1457 CHAN_TO_UBYTE(src[BCOMP]),
1458 CHAN_TO_UBYTE(src[ACOMP]) );
1463 for (col = 0; col < srcWidth; col++) {
1464 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
1465 CHAN_TO_UBYTE(src[GCOMP]),
1466 CHAN_TO_UBYTE(src[BCOMP]),
1467 CHAN_TO_UBYTE(src[ACOMP]) );
1471 dstRow += dstRowStride;
1474 _mesa_free((void *) tempImage);
1481 _mesa_texstore_argb8888(TEXSTORE_PARAMS)
1483 const GLboolean littleEndian = _mesa_little_endian();
1485 ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
1486 dstFormat == &_mesa_texformat_argb8888_rev);
1487 ASSERT(dstFormat->TexelBytes == 4);
1489 if (!ctx->_ImageTransferState &&
1490 !srcPacking->SwapBytes &&
1491 dstFormat == &_mesa_texformat_argb8888 &&
1492 baseInternalFormat == GL_RGBA &&
1493 srcFormat == GL_BGRA &&
1494 ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1495 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
1496 /* simple memcpy path (little endian) */
1497 memcpy_texture(ctx, dims,
1498 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1501 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1502 srcAddr, srcPacking);
1504 else if (!ctx->_ImageTransferState &&
1505 !srcPacking->SwapBytes &&
1506 dstFormat == &_mesa_texformat_argb8888_rev &&
1507 baseInternalFormat == GL_RGBA &&
1508 srcFormat == GL_BGRA &&
1509 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1510 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
1511 /* simple memcpy path (big endian) */
1512 memcpy_texture(ctx, dims,
1513 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1516 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1517 srcAddr, srcPacking);
1519 else if (!ctx->_ImageTransferState &&
1520 !srcPacking->SwapBytes &&
1521 dstFormat == &_mesa_texformat_argb8888 &&
1522 srcFormat == GL_RGB &&
1523 (baseInternalFormat == GL_RGBA ||
1524 baseInternalFormat == GL_RGB) &&
1525 srcType == GL_UNSIGNED_BYTE) {
1527 for (img = 0; img < srcDepth; img++) {
1528 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1529 srcWidth, srcFormat, srcType);
1530 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1531 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1532 GLubyte *dstRow = (GLubyte *) dstAddr
1533 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1534 + dstYoffset * dstRowStride
1535 + dstXoffset * dstFormat->TexelBytes;
1536 for (row = 0; row < srcHeight; row++) {
1537 GLuint *d4 = (GLuint *) dstRow;
1538 for (col = 0; col < srcWidth; col++) {
1539 d4[col] = PACK_COLOR_8888(0xff,
1540 srcRow[col * 3 + RCOMP],
1541 srcRow[col * 3 + GCOMP],
1542 srcRow[col * 3 + BCOMP]);
1544 dstRow += dstRowStride;
1545 srcRow += srcRowStride;
1549 else if (!ctx->_ImageTransferState &&
1550 !srcPacking->SwapBytes &&
1551 dstFormat == &_mesa_texformat_argb8888 &&
1552 srcFormat == GL_RGBA &&
1553 baseInternalFormat == GL_RGBA &&
1554 srcType == GL_UNSIGNED_BYTE) {
1555 /* same as above case, but src data has alpha too */
1556 GLint img, row, col;
1557 /* For some reason, streaming copies to write-combined regions
1558 * are extremely sensitive to the characteristics of how the
1559 * source data is retrieved. By reordering the source reads to
1560 * be in-order, the speed of this operation increases by half.
1561 * Strangely the same isn't required for the RGB path, above.
1563 for (img = 0; img < srcDepth; img++) {
1564 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1565 srcWidth, srcFormat, srcType);
1566 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1567 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1568 GLubyte *dstRow = (GLubyte *) dstAddr
1569 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1570 + dstYoffset * dstRowStride
1571 + dstXoffset * dstFormat->TexelBytes;
1572 for (row = 0; row < srcHeight; row++) {
1573 GLuint *d4 = (GLuint *) dstRow;
1574 for (col = 0; col < srcWidth; col++) {
1575 d4[col] = PACK_COLOR_8888(srcRow[col * 4 + ACOMP],
1576 srcRow[col * 4 + RCOMP],
1577 srcRow[col * 4 + GCOMP],
1578 srcRow[col * 4 + BCOMP]);
1580 dstRow += dstRowStride;
1581 srcRow += srcRowStride;
1585 else if (!ctx->_ImageTransferState &&
1586 (srcType == GL_UNSIGNED_BYTE ||
1587 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1588 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1589 can_swizzle(baseInternalFormat) &&
1590 can_swizzle(srcFormat)) {
1594 /* dstmap - how to swizzle from RGBA to dst format:
1596 if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) ||
1597 (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) {
1598 dstmap[3] = 3; /* alpha */
1599 dstmap[2] = 0; /* red */
1600 dstmap[1] = 1; /* green */
1601 dstmap[0] = 2; /* blue */
1604 assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) ||
1605 (!littleEndian && dstFormat == &_mesa_texformat_argb8888));
1612 _mesa_swizzle_ubyte_image(ctx, dims,
1618 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1621 srcWidth, srcHeight, srcDepth, srcAddr,
1626 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1628 dstFormat->BaseFormat,
1629 srcWidth, srcHeight, srcDepth,
1630 srcFormat, srcType, srcAddr,
1632 const GLchan *src = tempImage;
1633 GLint img, row, col;
1636 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1637 for (img = 0; img < srcDepth; img++) {
1638 GLubyte *dstRow = (GLubyte *) dstAddr
1639 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1640 + dstYoffset * dstRowStride
1641 + dstXoffset * dstFormat->TexelBytes;
1642 for (row = 0; row < srcHeight; row++) {
1643 GLuint *dstUI = (GLuint *) dstRow;
1644 if (dstFormat == &_mesa_texformat_argb8888) {
1645 for (col = 0; col < srcWidth; col++) {
1646 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1647 CHAN_TO_UBYTE(src[RCOMP]),
1648 CHAN_TO_UBYTE(src[GCOMP]),
1649 CHAN_TO_UBYTE(src[BCOMP]) );
1654 for (col = 0; col < srcWidth; col++) {
1655 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1656 CHAN_TO_UBYTE(src[RCOMP]),
1657 CHAN_TO_UBYTE(src[GCOMP]),
1658 CHAN_TO_UBYTE(src[BCOMP]) );
1662 dstRow += dstRowStride;
1665 _mesa_free((void *) tempImage);
1672 _mesa_texstore_rgb888(TEXSTORE_PARAMS)
1674 const GLboolean littleEndian = _mesa_little_endian();
1676 ASSERT(dstFormat == &_mesa_texformat_rgb888);
1677 ASSERT(dstFormat->TexelBytes == 3);
1679 if (!ctx->_ImageTransferState &&
1680 !srcPacking->SwapBytes &&
1681 baseInternalFormat == GL_RGB &&
1682 srcFormat == GL_BGR &&
1683 srcType == GL_UNSIGNED_BYTE &&
1685 /* simple memcpy path */
1686 memcpy_texture(ctx, dims,
1687 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1690 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1691 srcAddr, srcPacking);
1693 else if (!ctx->_ImageTransferState &&
1694 !srcPacking->SwapBytes &&
1695 srcFormat == GL_RGBA &&
1696 srcType == GL_UNSIGNED_BYTE) {
1697 /* extract RGB from RGBA */
1698 GLint img, row, col;
1699 for (img = 0; img < srcDepth; img++) {
1700 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1701 srcWidth, srcFormat, srcType);
1702 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1703 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1704 GLubyte *dstRow = (GLubyte *) dstAddr
1705 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1706 + dstYoffset * dstRowStride
1707 + dstXoffset * dstFormat->TexelBytes;
1708 for (row = 0; row < srcHeight; row++) {
1709 for (col = 0; col < srcWidth; col++) {
1710 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1711 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1712 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1714 dstRow += dstRowStride;
1715 srcRow += srcRowStride;
1719 else if (!ctx->_ImageTransferState &&
1720 srcType == GL_UNSIGNED_BYTE &&
1721 can_swizzle(baseInternalFormat) &&
1722 can_swizzle(srcFormat)) {
1726 /* dstmap - how to swizzle from RGBA to dst format:
1731 dstmap[3] = ONE; /* ? */
1733 _mesa_swizzle_ubyte_image(ctx, dims,
1738 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1739 dstRowStride, dstImageOffsets,
1740 srcWidth, srcHeight, srcDepth, srcAddr,
1745 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1747 dstFormat->BaseFormat,
1748 srcWidth, srcHeight, srcDepth,
1749 srcFormat, srcType, srcAddr,
1751 const GLchan *src = (const GLchan *) tempImage;
1752 GLint img, row, col;
1755 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1756 for (img = 0; img < srcDepth; img++) {
1757 GLubyte *dstRow = (GLubyte *) dstAddr
1758 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1759 + dstYoffset * dstRowStride
1760 + dstXoffset * dstFormat->TexelBytes;
1761 for (row = 0; row < srcHeight; row++) {
1764 for (col = 0; col < srcWidth; col++) {
1765 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1766 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1767 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1772 for (col = 0; col < srcWidth; col++) {
1773 dstRow[col * 3 + 0] = srcUB[BCOMP];
1774 dstRow[col * 3 + 1] = srcUB[GCOMP];
1775 dstRow[col * 3 + 2] = srcUB[RCOMP];
1780 for (col = 0; col < srcWidth; col++) {
1781 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1782 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1783 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1787 dstRow += dstRowStride;
1790 _mesa_free((void *) tempImage);
1797 _mesa_texstore_bgr888(TEXSTORE_PARAMS)
1799 const GLboolean littleEndian = _mesa_little_endian();
1801 ASSERT(dstFormat == &_mesa_texformat_bgr888);
1802 ASSERT(dstFormat->TexelBytes == 3);
1804 if (!ctx->_ImageTransferState &&
1805 !srcPacking->SwapBytes &&
1806 baseInternalFormat == GL_RGB &&
1807 srcFormat == GL_RGB &&
1808 srcType == GL_UNSIGNED_BYTE &&
1810 /* simple memcpy path */
1811 memcpy_texture(ctx, dims,
1812 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1815 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1816 srcAddr, srcPacking);
1818 else if (!ctx->_ImageTransferState &&
1819 !srcPacking->SwapBytes &&
1820 srcFormat == GL_RGBA &&
1821 srcType == GL_UNSIGNED_BYTE) {
1822 /* extract BGR from RGBA */
1824 for (img = 0; img < srcDepth; img++) {
1825 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1826 srcWidth, srcFormat, srcType);
1827 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1828 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1829 GLubyte *dstRow = (GLubyte *) dstAddr
1830 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1831 + dstYoffset * dstRowStride
1832 + dstXoffset * dstFormat->TexelBytes;
1833 for (row = 0; row < srcHeight; row++) {
1834 for (col = 0; col < srcWidth; col++) {
1835 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1836 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1837 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1839 dstRow += dstRowStride;
1840 srcRow += srcRowStride;
1844 else if (!ctx->_ImageTransferState &&
1845 srcType == GL_UNSIGNED_BYTE &&
1846 can_swizzle(baseInternalFormat) &&
1847 can_swizzle(srcFormat)) {
1851 /* dstmap - how to swizzle from RGBA to dst format:
1856 dstmap[3] = ONE; /* ? */
1858 _mesa_swizzle_ubyte_image(ctx, dims,
1863 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1864 dstRowStride, dstImageOffsets,
1865 srcWidth, srcHeight, srcDepth, srcAddr,
1870 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1872 dstFormat->BaseFormat,
1873 srcWidth, srcHeight, srcDepth,
1874 srcFormat, srcType, srcAddr,
1876 const GLchan *src = (const GLchan *) tempImage;
1877 GLint img, row, col;
1880 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1881 for (img = 0; img < srcDepth; img++) {
1882 GLubyte *dstRow = (GLubyte *) dstAddr
1883 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1884 + dstYoffset * dstRowStride
1885 + dstXoffset * dstFormat->TexelBytes;
1886 for (row = 0; row < srcHeight; row++) {
1887 for (col = 0; col < srcWidth; col++) {
1888 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1889 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1890 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1893 dstRow += dstRowStride;
1896 _mesa_free((void *) tempImage);
1903 _mesa_texstore_argb4444(TEXSTORE_PARAMS)
1905 ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
1906 dstFormat == &_mesa_texformat_argb4444_rev);
1907 ASSERT(dstFormat->TexelBytes == 2);
1909 if (!ctx->_ImageTransferState &&
1910 !srcPacking->SwapBytes &&
1911 dstFormat == &_mesa_texformat_argb4444 &&
1912 baseInternalFormat == GL_RGBA &&
1913 srcFormat == GL_BGRA &&
1914 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1915 /* simple memcpy path */
1916 memcpy_texture(ctx, dims,
1917 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1920 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1921 srcAddr, srcPacking);
1925 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1927 dstFormat->BaseFormat,
1928 srcWidth, srcHeight, srcDepth,
1929 srcFormat, srcType, srcAddr,
1931 const GLchan *src = tempImage;
1932 GLint img, row, col;
1935 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1936 for (img = 0; img < srcDepth; img++) {
1937 GLubyte *dstRow = (GLubyte *) dstAddr
1938 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1939 + dstYoffset * dstRowStride
1940 + dstXoffset * dstFormat->TexelBytes;
1941 for (row = 0; row < srcHeight; row++) {
1942 GLushort *dstUS = (GLushort *) dstRow;
1943 if (dstFormat == &_mesa_texformat_argb4444) {
1944 for (col = 0; col < srcWidth; col++) {
1945 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1946 CHAN_TO_UBYTE(src[RCOMP]),
1947 CHAN_TO_UBYTE(src[GCOMP]),
1948 CHAN_TO_UBYTE(src[BCOMP]) );
1953 for (col = 0; col < srcWidth; col++) {
1954 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
1955 CHAN_TO_UBYTE(src[RCOMP]),
1956 CHAN_TO_UBYTE(src[GCOMP]),
1957 CHAN_TO_UBYTE(src[BCOMP]) );
1961 dstRow += dstRowStride;
1964 _mesa_free((void *) tempImage);
1972 _mesa_texstore_argb1555(TEXSTORE_PARAMS)
1974 ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
1975 dstFormat == &_mesa_texformat_argb1555_rev);
1976 ASSERT(dstFormat->TexelBytes == 2);
1978 if (!ctx->_ImageTransferState &&
1979 !srcPacking->SwapBytes &&
1980 dstFormat == &_mesa_texformat_argb1555 &&
1981 baseInternalFormat == GL_RGBA &&
1982 srcFormat == GL_BGRA &&
1983 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
1984 /* simple memcpy path */
1985 memcpy_texture(ctx, dims,
1986 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1989 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1990 srcAddr, srcPacking);
1994 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1996 dstFormat->BaseFormat,
1997 srcWidth, srcHeight, srcDepth,
1998 srcFormat, srcType, srcAddr,
2000 const GLchan *src =tempImage;
2001 GLint img, row, col;
2004 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2005 for (img = 0; img < srcDepth; img++) {
2006 GLubyte *dstRow = (GLubyte *) dstAddr
2007 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2008 + dstYoffset * dstRowStride
2009 + dstXoffset * dstFormat->TexelBytes;
2010 for (row = 0; row < srcHeight; row++) {
2011 GLushort *dstUS = (GLushort *) dstRow;
2012 if (dstFormat == &_mesa_texformat_argb1555) {
2013 for (col = 0; col < srcWidth; col++) {
2014 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
2015 CHAN_TO_UBYTE(src[RCOMP]),
2016 CHAN_TO_UBYTE(src[GCOMP]),
2017 CHAN_TO_UBYTE(src[BCOMP]) );
2022 for (col = 0; col < srcWidth; col++) {
2023 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
2024 CHAN_TO_UBYTE(src[RCOMP]),
2025 CHAN_TO_UBYTE(src[GCOMP]),
2026 CHAN_TO_UBYTE(src[BCOMP]) );
2030 dstRow += dstRowStride;
2033 _mesa_free((void *) tempImage);
2040 _mesa_texstore_al88(TEXSTORE_PARAMS)
2042 const GLboolean littleEndian = _mesa_little_endian();
2044 ASSERT(dstFormat == &_mesa_texformat_al88 ||
2045 dstFormat == &_mesa_texformat_al88_rev);
2046 ASSERT(dstFormat->TexelBytes == 2);
2048 if (!ctx->_ImageTransferState &&
2049 !srcPacking->SwapBytes &&
2050 dstFormat == &_mesa_texformat_al88 &&
2051 baseInternalFormat == GL_LUMINANCE_ALPHA &&
2052 srcFormat == GL_LUMINANCE_ALPHA &&
2053 srcType == GL_UNSIGNED_BYTE &&
2055 /* simple memcpy path */
2056 memcpy_texture(ctx, dims,
2057 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2060 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2061 srcAddr, srcPacking);
2063 else if (!ctx->_ImageTransferState &&
2065 srcType == GL_UNSIGNED_BYTE &&
2066 can_swizzle(baseInternalFormat) &&
2067 can_swizzle(srcFormat)) {
2071 /* dstmap - how to swizzle from RGBA to dst format:
2073 if ((littleEndian && dstFormat == &_mesa_texformat_al88) ||
2074 (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) {
2082 dstmap[2] = ZERO; /* ? */
2083 dstmap[3] = ONE; /* ? */
2085 _mesa_swizzle_ubyte_image(ctx, dims,
2090 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2091 dstRowStride, dstImageOffsets,
2092 srcWidth, srcHeight, srcDepth, srcAddr,
2097 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2099 dstFormat->BaseFormat,
2100 srcWidth, srcHeight, srcDepth,
2101 srcFormat, srcType, srcAddr,
2103 const GLchan *src = tempImage;
2104 GLint img, row, col;
2107 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2108 for (img = 0; img < srcDepth; img++) {
2109 GLubyte *dstRow = (GLubyte *) dstAddr
2110 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2111 + dstYoffset * dstRowStride
2112 + dstXoffset * dstFormat->TexelBytes;
2113 for (row = 0; row < srcHeight; row++) {
2114 GLushort *dstUS = (GLushort *) dstRow;
2115 if (dstFormat == &_mesa_texformat_al88) {
2116 for (col = 0; col < srcWidth; col++) {
2117 /* src[0] is luminance, src[1] is alpha */
2118 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
2119 CHAN_TO_UBYTE(src[0]) );
2124 for (col = 0; col < srcWidth; col++) {
2125 /* src[0] is luminance, src[1] is alpha */
2126 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
2127 CHAN_TO_UBYTE(src[0]) );
2131 dstRow += dstRowStride;
2134 _mesa_free((void *) tempImage);
2141 _mesa_texstore_rgb332(TEXSTORE_PARAMS)
2143 ASSERT(dstFormat == &_mesa_texformat_rgb332);
2144 ASSERT(dstFormat->TexelBytes == 1);
2146 if (!ctx->_ImageTransferState &&
2147 !srcPacking->SwapBytes &&
2148 baseInternalFormat == GL_RGB &&
2149 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
2150 /* simple memcpy path */
2151 memcpy_texture(ctx, dims,
2152 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2155 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2156 srcAddr, srcPacking);
2160 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2162 dstFormat->BaseFormat,
2163 srcWidth, srcHeight, srcDepth,
2164 srcFormat, srcType, srcAddr,
2166 const GLchan *src = tempImage;
2167 GLint img, row, col;
2170 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2171 for (img = 0; img < srcDepth; img++) {
2172 GLubyte *dstRow = (GLubyte *) dstAddr
2173 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2174 + dstYoffset * dstRowStride
2175 + dstXoffset * dstFormat->TexelBytes;
2176 for (row = 0; row < srcHeight; row++) {
2177 for (col = 0; col < srcWidth; col++) {
2178 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
2179 CHAN_TO_UBYTE(src[GCOMP]),
2180 CHAN_TO_UBYTE(src[BCOMP]) );
2183 dstRow += dstRowStride;
2186 _mesa_free((void *) tempImage);
2193 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2196 _mesa_texstore_a8(TEXSTORE_PARAMS)
2198 ASSERT(dstFormat == &_mesa_texformat_a8 ||
2199 dstFormat == &_mesa_texformat_l8 ||
2200 dstFormat == &_mesa_texformat_i8);
2201 ASSERT(dstFormat->TexelBytes == 1);
2203 if (!ctx->_ImageTransferState &&
2204 !srcPacking->SwapBytes &&
2205 baseInternalFormat == srcFormat &&
2206 srcType == GL_UNSIGNED_BYTE) {
2207 /* simple memcpy path */
2208 memcpy_texture(ctx, dims,
2209 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2212 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2213 srcAddr, srcPacking);
2215 else if (!ctx->_ImageTransferState &&
2216 srcType == GL_UNSIGNED_BYTE &&
2217 can_swizzle(baseInternalFormat) &&
2218 can_swizzle(srcFormat)) {
2222 /* dstmap - how to swizzle from RGBA to dst format:
2224 if (dstFormat == &_mesa_texformat_a8) {
2230 dstmap[1] = ZERO; /* ? */
2231 dstmap[2] = ZERO; /* ? */
2232 dstmap[3] = ONE; /* ? */
2234 _mesa_swizzle_ubyte_image(ctx, dims,
2239 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2240 dstRowStride, dstImageOffsets,
2241 srcWidth, srcHeight, srcDepth, srcAddr,
2246 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2248 dstFormat->BaseFormat,
2249 srcWidth, srcHeight, srcDepth,
2250 srcFormat, srcType, srcAddr,
2252 const GLchan *src = tempImage;
2253 GLint img, row, col;
2256 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2257 for (img = 0; img < srcDepth; img++) {
2258 GLubyte *dstRow = (GLubyte *) dstAddr
2259 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2260 + dstYoffset * dstRowStride
2261 + dstXoffset * dstFormat->TexelBytes;
2262 for (row = 0; row < srcHeight; row++) {
2263 for (col = 0; col < srcWidth; col++) {
2264 dstRow[col] = CHAN_TO_UBYTE(src[col]);
2266 dstRow += dstRowStride;
2270 _mesa_free((void *) tempImage);
2278 _mesa_texstore_ci8(TEXSTORE_PARAMS)
2280 (void) dims; (void) baseInternalFormat;
2281 ASSERT(dstFormat == &_mesa_texformat_ci8);
2282 ASSERT(dstFormat->TexelBytes == 1);
2283 ASSERT(baseInternalFormat == GL_COLOR_INDEX);
2285 if (!ctx->_ImageTransferState &&
2286 !srcPacking->SwapBytes &&
2287 srcFormat == GL_COLOR_INDEX &&
2288 srcType == GL_UNSIGNED_BYTE) {
2289 /* simple memcpy path */
2290 memcpy_texture(ctx, dims,
2291 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2294 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2295 srcAddr, srcPacking);
2300 for (img = 0; img < srcDepth; img++) {
2301 GLubyte *dstRow = (GLubyte *) dstAddr
2302 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2303 + dstYoffset * dstRowStride
2304 + dstXoffset * dstFormat->TexelBytes;
2305 for (row = 0; row < srcHeight; row++) {
2306 const GLvoid *src = _mesa_image_address(dims, srcPacking,
2307 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
2308 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
2309 srcType, src, srcPacking,
2310 ctx->_ImageTransferState);
2311 dstRow += dstRowStride;
2320 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2323 _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
2325 const GLboolean littleEndian = _mesa_little_endian();
2326 (void) ctx; (void) dims; (void) baseInternalFormat;
2328 ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
2329 (dstFormat == &_mesa_texformat_ycbcr_rev));
2330 ASSERT(dstFormat->TexelBytes == 2);
2331 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
2332 ASSERT(srcFormat == GL_YCBCR_MESA);
2333 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
2334 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
2335 ASSERT(baseInternalFormat == GL_YCBCR_MESA);
2337 /* always just memcpy since no pixel transfer ops apply */
2338 memcpy_texture(ctx, dims,
2339 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2342 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2343 srcAddr, srcPacking);
2345 /* Check if we need byte swapping */
2346 /* XXX the logic here _might_ be wrong */
2347 if (srcPacking->SwapBytes ^
2348 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
2349 (dstFormat == &_mesa_texformat_ycbcr_rev) ^
2352 for (img = 0; img < srcDepth; img++) {
2353 GLubyte *dstRow = (GLubyte *) dstAddr
2354 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2355 + dstYoffset * dstRowStride
2356 + dstXoffset * dstFormat->TexelBytes;
2357 for (row = 0; row < srcHeight; row++) {
2358 _mesa_swap2((GLushort *) dstRow, srcWidth);
2359 dstRow += dstRowStride;
2369 * Store a combined depth/stencil texture image.
2372 _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
2374 const GLfloat depthScale = (GLfloat) 0xffffff;
2376 ASSERT(dstFormat == &_mesa_texformat_z24_s8);
2377 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
2378 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
2380 if (ctx->Pixel.DepthScale == 1.0f &&
2381 ctx->Pixel.DepthBias == 0.0f &&
2382 !srcPacking->SwapBytes) {
2384 memcpy_texture(ctx, dims,
2385 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2388 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2389 srcAddr, srcPacking);
2393 const GLint srcRowStride
2394 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
2398 for (img = 0; img < srcDepth; img++) {
2399 GLuint *dstRow = (GLuint *) dstAddr
2400 + dstImageOffsets[dstZoffset + img]
2401 + dstYoffset * dstRowStride / sizeof(GLuint)
2404 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2405 srcWidth, srcHeight,
2408 for (row = 0; row < srcHeight; row++) {
2409 GLubyte stencil[MAX_WIDTH];
2411 /* the 24 depth bits will be in the high position: */
2412 _mesa_unpack_depth_span(ctx, srcWidth,
2413 GL_UNSIGNED_INT_24_8_EXT, /* dst type */
2414 dstRow, /* dst addr */
2415 (GLuint) depthScale,
2416 srcType, src, srcPacking);
2417 /* get the 8-bit stencil values */
2418 _mesa_unpack_stencil_span(ctx, srcWidth,
2419 GL_UNSIGNED_BYTE, /* dst type */
2420 stencil, /* dst addr */
2421 srcType, src, srcPacking,
2422 ctx->_ImageTransferState);
2423 /* merge stencil values into depth values */
2424 for (i = 0; i < srcWidth; i++)
2425 dstRow[i] |= stencil[i];
2427 src += srcRowStride;
2428 dstRow += dstRowStride / sizeof(GLuint);
2437 * Store a combined depth/stencil texture image.
2440 _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
2442 const GLuint depthScale = 0xffffff;
2443 const GLint srcRowStride
2444 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
2448 ASSERT(dstFormat == &_mesa_texformat_s8_z24);
2449 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
2450 ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
2452 /* In case we only upload depth we need to preserve the stencil */
2453 if (srcFormat == GL_DEPTH_COMPONENT) {
2454 for (img = 0; img < srcDepth; img++) {
2455 GLuint *dstRow = (GLuint *) dstAddr
2456 + dstImageOffsets[dstZoffset + img]
2457 + dstYoffset * dstRowStride / sizeof(GLuint)
2460 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2461 srcWidth, srcHeight,
2464 for (row = 0; row < srcHeight; row++) {
2465 GLuint depth[MAX_WIDTH];
2467 _mesa_unpack_depth_span(ctx, srcWidth,
2468 GL_UNSIGNED_INT, /* dst type */
2469 depth, /* dst addr */
2471 srcType, src, srcPacking);
2473 for (i = 0; i < srcWidth; i++)
2474 dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
2476 src += srcRowStride;
2477 dstRow += dstRowStride / sizeof(GLuint);
2482 for (img = 0; img < srcDepth; img++) {
2483 GLuint *dstRow = (GLuint *) dstAddr
2484 + dstImageOffsets[dstZoffset + img]
2485 + dstYoffset * dstRowStride / sizeof(GLuint)
2488 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2489 srcWidth, srcHeight,
2492 for (row = 0; row < srcHeight; row++) {
2493 GLubyte stencil[MAX_WIDTH];
2495 /* the 24 depth bits will be in the low position: */
2496 _mesa_unpack_depth_span(ctx, srcWidth,
2497 GL_UNSIGNED_INT, /* dst type */
2498 dstRow, /* dst addr */
2500 srcType, src, srcPacking);
2501 /* get the 8-bit stencil values */
2502 _mesa_unpack_stencil_span(ctx, srcWidth,
2503 GL_UNSIGNED_BYTE, /* dst type */
2504 stencil, /* dst addr */
2505 srcType, src, srcPacking,
2506 ctx->_ImageTransferState);
2507 /* merge stencil values into depth values */
2508 for (i = 0; i < srcWidth; i++)
2509 dstRow[i] |= stencil[i] << 24;
2511 src += srcRowStride;
2512 dstRow += dstRowStride / sizeof(GLuint);
2520 * Store an image in any of the formats:
2521 * _mesa_texformat_rgba_float32
2522 * _mesa_texformat_rgb_float32
2523 * _mesa_texformat_alpha_float32
2524 * _mesa_texformat_luminance_float32
2525 * _mesa_texformat_luminance_alpha_float32
2526 * _mesa_texformat_intensity_float32
2529 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
2531 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
2533 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
2534 dstFormat == &_mesa_texformat_rgb_float32 ||
2535 dstFormat == &_mesa_texformat_alpha_float32 ||
2536 dstFormat == &_mesa_texformat_luminance_float32 ||
2537 dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
2538 dstFormat == &_mesa_texformat_intensity_float32);
2539 ASSERT(baseInternalFormat == GL_RGBA ||
2540 baseInternalFormat == GL_RGB ||
2541 baseInternalFormat == GL_ALPHA ||
2542 baseInternalFormat == GL_LUMINANCE ||
2543 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2544 baseInternalFormat == GL_INTENSITY);
2545 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
2547 if (!ctx->_ImageTransferState &&
2548 !srcPacking->SwapBytes &&
2549 baseInternalFormat == srcFormat &&
2550 srcType == GL_FLOAT) {
2551 /* simple memcpy path */
2552 memcpy_texture(ctx, dims,
2553 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2556 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2557 srcAddr, srcPacking);
2561 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2563 dstFormat->BaseFormat,
2564 srcWidth, srcHeight, srcDepth,
2565 srcFormat, srcType, srcAddr,
2567 const GLfloat *srcRow = tempImage;
2572 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2573 bytesPerRow = srcWidth * components * sizeof(GLfloat);
2574 for (img = 0; img < srcDepth; img++) {
2575 GLubyte *dstRow = (GLubyte *) dstAddr
2576 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2577 + dstYoffset * dstRowStride
2578 + dstXoffset * dstFormat->TexelBytes;
2579 for (row = 0; row < srcHeight; row++) {
2580 _mesa_memcpy(dstRow, srcRow, bytesPerRow);
2581 dstRow += dstRowStride;
2582 srcRow += srcWidth * components;
2586 _mesa_free((void *) tempImage);
2593 * As above, but store 16-bit floats.
2596 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
2598 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
2600 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
2601 dstFormat == &_mesa_texformat_rgb_float16 ||
2602 dstFormat == &_mesa_texformat_alpha_float16 ||
2603 dstFormat == &_mesa_texformat_luminance_float16 ||
2604 dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
2605 dstFormat == &_mesa_texformat_intensity_float16);
2606 ASSERT(baseInternalFormat == GL_RGBA ||
2607 baseInternalFormat == GL_RGB ||
2608 baseInternalFormat == GL_ALPHA ||
2609 baseInternalFormat == GL_LUMINANCE ||
2610 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2611 baseInternalFormat == GL_INTENSITY);
2612 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
2614 if (!ctx->_ImageTransferState &&
2615 !srcPacking->SwapBytes &&
2616 baseInternalFormat == srcFormat &&
2617 srcType == GL_HALF_FLOAT_ARB) {
2618 /* simple memcpy path */
2619 memcpy_texture(ctx, dims,
2620 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2623 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2624 srcAddr, srcPacking);
2628 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2630 dstFormat->BaseFormat,
2631 srcWidth, srcHeight, srcDepth,
2632 srcFormat, srcType, srcAddr,
2634 const GLfloat *src = tempImage;
2638 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2639 for (img = 0; img < srcDepth; img++) {
2640 GLubyte *dstRow = (GLubyte *) dstAddr
2641 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2642 + dstYoffset * dstRowStride
2643 + dstXoffset * dstFormat->TexelBytes;
2644 for (row = 0; row < srcHeight; row++) {
2645 GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
2647 for (i = 0; i < srcWidth * components; i++) {
2648 dstTexel[i] = _mesa_float_to_half(src[i]);
2650 dstRow += dstRowStride;
2651 src += srcWidth * components;
2655 _mesa_free((void *) tempImage);
2661 #if FEATURE_EXT_texture_sRGB
2663 _mesa_texstore_srgb8(TEXSTORE_PARAMS)
2665 const GLboolean littleEndian = _mesa_little_endian();
2666 const struct gl_texture_format *newDstFormat;
2667 StoreTexImageFunc store;
2670 ASSERT(dstFormat == &_mesa_texformat_srgb8);
2672 /* reuse normal rgb texstore code */
2674 newDstFormat = &_mesa_texformat_bgr888;
2675 store = _mesa_texstore_bgr888;
2678 newDstFormat = &_mesa_texformat_rgb888;
2679 store = _mesa_texstore_rgb888;
2682 k = store(ctx, dims, baseInternalFormat,
2683 newDstFormat, dstAddr,
2684 dstXoffset, dstYoffset, dstZoffset,
2685 dstRowStride, dstImageOffsets,
2686 srcWidth, srcHeight, srcDepth,
2688 srcAddr, srcPacking);
2694 _mesa_texstore_srgba8(TEXSTORE_PARAMS)
2696 const GLboolean littleEndian = _mesa_little_endian();
2697 const struct gl_texture_format *newDstFormat;
2700 ASSERT(dstFormat == &_mesa_texformat_srgba8);
2702 /* reuse normal rgba texstore code */
2704 newDstFormat = &_mesa_texformat_rgba8888_rev;
2706 newDstFormat = &_mesa_texformat_rgba8888;
2708 k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
2709 newDstFormat, dstAddr,
2710 dstXoffset, dstYoffset, dstZoffset,
2711 dstRowStride, dstImageOffsets,
2712 srcWidth, srcHeight, srcDepth,
2714 srcAddr, srcPacking);
2720 _mesa_texstore_sl8(TEXSTORE_PARAMS)
2722 const struct gl_texture_format *newDstFormat;
2725 ASSERT(dstFormat == &_mesa_texformat_sl8);
2727 newDstFormat = &_mesa_texformat_l8;
2729 /* _mesa_textore_a8 handles luminance8 too */
2730 k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
2731 newDstFormat, dstAddr,
2732 dstXoffset, dstYoffset, dstZoffset,
2733 dstRowStride, dstImageOffsets,
2734 srcWidth, srcHeight, srcDepth,
2736 srcAddr, srcPacking);
2742 _mesa_texstore_sla8(TEXSTORE_PARAMS)
2744 const GLboolean littleEndian = _mesa_little_endian();
2745 const struct gl_texture_format *newDstFormat;
2748 ASSERT(dstFormat == &_mesa_texformat_sla8);
2750 /* reuse normal luminance/alpha texstore code */
2752 newDstFormat = &_mesa_texformat_al88;
2754 newDstFormat = &_mesa_texformat_al88_rev;
2756 k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
2757 newDstFormat, dstAddr,
2758 dstXoffset, dstYoffset, dstZoffset,
2759 dstRowStride, dstImageOffsets,
2760 srcWidth, srcHeight, srcDepth,
2762 srcAddr, srcPacking);
2766 #endif /* FEATURE_EXT_texture_sRGB */
2770 * Check if an unpack PBO is active prior to fetching a texture image.
2771 * If so, do bounds checking and map the buffer into main memory.
2772 * Any errors detected will be recorded.
2773 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2776 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
2777 GLsizei width, GLsizei height, GLsizei depth,
2778 GLenum format, GLenum type, const GLvoid *pixels,
2779 const struct gl_pixelstore_attrib *unpack,
2780 const char *funcName)
2784 if (unpack->BufferObj->Name == 0) {
2788 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
2789 format, type, pixels)) {
2790 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2794 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2795 GL_READ_ONLY_ARB, unpack->BufferObj);
2797 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2801 return ADD_POINTERS(buf, pixels);
2806 * Check if an unpack PBO is active prior to fetching a compressed texture
2808 * If so, do bounds checking and map the buffer into main memory.
2809 * Any errors detected will be recorded.
2810 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2813 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
2814 GLsizei imageSize, const GLvoid *pixels,
2815 const struct gl_pixelstore_attrib *packing,
2816 const char *funcName)
2820 if (packing->BufferObj->Name == 0) {
2821 /* not using a PBO - return pointer unchanged */
2824 if ((const GLubyte *) pixels + imageSize >
2825 ((const GLubyte *) 0) + packing->BufferObj->Size) {
2826 /* out of bounds read! */
2827 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2831 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2832 GL_READ_ONLY_ARB, packing->BufferObj);
2834 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2838 return ADD_POINTERS(buf, pixels);
2843 * This function must be called after either of the validate_pbo_*_teximage()
2844 * functions. It unmaps the PBO buffer if it was mapped earlier.
2847 _mesa_unmap_teximage_pbo(GLcontext *ctx,
2848 const struct gl_pixelstore_attrib *unpack)
2850 if (unpack->BufferObj->Name) {
2851 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2859 * Adaptor for fetching a GLchan texel from a float-valued texture.
2862 fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
2863 GLint i, GLint j, GLint k, GLchan *texelOut)
2866 ASSERT(texImage->FetchTexelf);
2867 texImage->FetchTexelf(texImage, i, j, k, temp);
2868 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
2869 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
2870 /* just one channel */
2871 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2875 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2876 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
2877 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
2878 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
2884 * Adaptor for fetching a float texel from a GLchan-valued texture.
2887 fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
2888 GLint i, GLint j, GLint k, GLfloat *texelOut)
2891 ASSERT(texImage->FetchTexelc);
2892 texImage->FetchTexelc(texImage, i, j, k, temp);
2893 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
2894 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
2895 /* just one channel */
2896 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2900 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2901 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
2902 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
2903 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
2909 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2912 _mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
2914 ASSERT(dims == 1 || dims == 2 || dims == 3);
2915 ASSERT(texImage->TexFormat);
2919 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
2920 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
2923 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2924 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2927 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
2928 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
2934 /* now check if we need to use a float/chan adaptor */
2935 if (!texImage->FetchTexelc) {
2936 texImage->FetchTexelc = fetch_texel_float_to_chan;
2938 else if (!texImage->FetchTexelf) {
2939 texImage->FetchTexelf = fetch_texel_chan_to_float;
2943 ASSERT(texImage->FetchTexelc);
2944 ASSERT(texImage->FetchTexelf);
2949 * Choose the actual storage format for a new texture image.
2950 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2951 * Also set some other texImage fields related to texture compression, etc.
2952 * \param ctx rendering context
2953 * \param texImage the gl_texture_image
2954 * \param dims texture dimensions (1, 2 or 3)
2955 * \param format the user-specified format parameter
2956 * \param type the user-specified type parameter
2957 * \param internalFormat the user-specified internal format hint
2960 choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage,
2962 GLenum format, GLenum type, GLint internalFormat)
2964 ASSERT(dims == 1 || dims == 2 || dims == 3);
2965 ASSERT(ctx->Driver.ChooseTextureFormat);
2968 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2970 ASSERT(texImage->TexFormat);
2972 _mesa_set_fetch_functions(texImage, dims);
2974 if (texImage->TexFormat->TexelBytes == 0) {
2975 /* must be a compressed format */
2976 texImage->IsCompressed = GL_TRUE;
2977 texImage->CompressedSize =
2978 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
2979 texImage->Height, texImage->Depth,
2980 texImage->TexFormat->MesaFormat);
2983 /* non-compressed format */
2984 texImage->IsCompressed = GL_FALSE;
2985 texImage->CompressedSize = 0;
2992 * This is the software fallback for Driver.TexImage1D()
2993 * and Driver.CopyTexImage1D().
2994 * \sa _mesa_store_teximage2d()
2995 * Note that the width may not be the actual texture width since it may
2996 * be changed by convolution w/ GL_REDUCE. The texImage->Width field will
2997 * have the actual texture size.
3000 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3001 GLint internalFormat,
3002 GLint width, GLint border,
3003 GLenum format, GLenum type, const GLvoid *pixels,
3004 const struct gl_pixelstore_attrib *packing,
3005 struct gl_texture_object *texObj,
3006 struct gl_texture_image *texImage)
3011 choose_texture_format(ctx, texImage, 1, format, type, internalFormat);
3013 /* allocate memory */
3014 if (texImage->IsCompressed)
3015 sizeInBytes = texImage->CompressedSize;
3017 sizeInBytes = texImage->Width * texImage->TexFormat->TexelBytes;
3018 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3019 if (!texImage->Data) {
3020 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
3024 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3025 pixels, packing, "glTexImage1D");
3027 /* Note: we check for a NULL image pointer here, _after_ we allocated
3028 * memory for the texture. That's what the GL spec calls for.
3033 const GLint dstRowStride = 0;
3035 ASSERT(texImage->TexFormat->StoreImage);
3036 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
3037 texImage->TexFormat,
3039 0, 0, 0, /* dstX/Y/Zoffset */
3041 texImage->ImageOffsets,
3043 format, type, pixels, packing);
3045 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
3049 /* GL_SGIS_generate_mipmap */
3050 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3051 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3054 _mesa_unmap_teximage_pbo(ctx, packing);
3059 * This is the software fallback for Driver.TexImage2D()
3060 * and Driver.CopyTexImage2D().
3062 * This function is oriented toward storing images in main memory, rather
3063 * than VRAM. Device driver's can easily plug in their own replacement.
3065 * Note: width and height may be pre-convolved dimensions, but
3066 * texImage->Width and texImage->Height will be post-convolved dimensions.
3069 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3070 GLint internalFormat,
3071 GLint width, GLint height, GLint border,
3072 GLenum format, GLenum type, const void *pixels,
3073 const struct gl_pixelstore_attrib *packing,
3074 struct gl_texture_object *texObj,
3075 struct gl_texture_image *texImage)
3077 GLint texelBytes, sizeInBytes;
3080 choose_texture_format(ctx, texImage, 2, format, type, internalFormat);
3082 texelBytes = texImage->TexFormat->TexelBytes;
3084 /* allocate memory */
3085 if (texImage->IsCompressed)
3086 sizeInBytes = texImage->CompressedSize;
3088 sizeInBytes = texImage->Width * texImage->Height * texelBytes;
3089 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3090 if (!texImage->Data) {
3091 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
3095 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3096 pixels, packing, "glTexImage2D");
3098 /* Note: we check for a NULL image pointer here, _after_ we allocated
3099 * memory for the texture. That's what the GL spec calls for.
3106 if (texImage->IsCompressed) {
3108 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3111 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3113 ASSERT(texImage->TexFormat->StoreImage);
3114 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
3115 texImage->TexFormat,
3117 0, 0, 0, /* dstX/Y/Zoffset */
3119 texImage->ImageOffsets,
3121 format, type, pixels, packing);
3123 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
3127 /* GL_SGIS_generate_mipmap */
3128 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3129 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3132 _mesa_unmap_teximage_pbo(ctx, packing);
3138 * This is the software fallback for Driver.TexImage3D()
3139 * and Driver.CopyTexImage3D().
3140 * \sa _mesa_store_teximage2d()
3143 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3144 GLint internalFormat,
3145 GLint width, GLint height, GLint depth, GLint border,
3146 GLenum format, GLenum type, const void *pixels,
3147 const struct gl_pixelstore_attrib *packing,
3148 struct gl_texture_object *texObj,
3149 struct gl_texture_image *texImage)
3151 GLint texelBytes, sizeInBytes;
3154 choose_texture_format(ctx, texImage, 3, format, type, internalFormat);
3156 texelBytes = texImage->TexFormat->TexelBytes;
3158 /* allocate memory */
3159 if (texImage->IsCompressed)
3160 sizeInBytes = texImage->CompressedSize;
3162 sizeInBytes = width * height * depth * texelBytes;
3163 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3164 if (!texImage->Data) {
3165 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3169 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3170 type, pixels, packing, "glTexImage3D");
3172 /* Note: we check for a NULL image pointer here, _after_ we allocated
3173 * memory for the texture. That's what the GL spec calls for.
3180 if (texImage->IsCompressed) {
3182 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3185 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3187 ASSERT(texImage->TexFormat->StoreImage);
3188 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
3189 texImage->TexFormat,
3191 0, 0, 0, /* dstX/Y/Zoffset */
3193 texImage->ImageOffsets,
3194 width, height, depth,
3195 format, type, pixels, packing);
3197 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3201 /* GL_SGIS_generate_mipmap */
3202 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3203 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3206 _mesa_unmap_teximage_pbo(ctx, packing);
3213 * This is the software fallback for Driver.TexSubImage1D()
3214 * and Driver.CopyTexSubImage1D().
3217 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
3218 GLint xoffset, GLint width,
3219 GLenum format, GLenum type, const void *pixels,
3220 const struct gl_pixelstore_attrib *packing,
3221 struct gl_texture_object *texObj,
3222 struct gl_texture_image *texImage)
3224 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3225 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3226 pixels, packing, "glTexSubImage1D");
3231 const GLint dstRowStride = 0;
3233 ASSERT(texImage->TexFormat->StoreImage);
3234 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
3235 texImage->TexFormat,
3237 xoffset, 0, 0, /* offsets */
3239 texImage->ImageOffsets,
3241 format, type, pixels, packing);
3243 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
3247 /* GL_SGIS_generate_mipmap */
3248 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3249 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3252 _mesa_unmap_teximage_pbo(ctx, packing);
3258 * This is the software fallback for Driver.TexSubImage2D()
3259 * and Driver.CopyTexSubImage2D().
3262 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
3263 GLint xoffset, GLint yoffset,
3264 GLint width, GLint height,
3265 GLenum format, GLenum type, const void *pixels,
3266 const struct gl_pixelstore_attrib *packing,
3267 struct gl_texture_object *texObj,
3268 struct gl_texture_image *texImage)
3270 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3271 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3272 pixels, packing, "glTexSubImage2D");
3277 GLint dstRowStride = 0;
3279 if (texImage->IsCompressed) {
3280 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3284 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3286 ASSERT(texImage->TexFormat->StoreImage);
3287 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
3288 texImage->TexFormat,
3290 xoffset, yoffset, 0,
3292 texImage->ImageOffsets,
3294 format, type, pixels, packing);
3296 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
3300 /* GL_SGIS_generate_mipmap */
3301 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3302 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3305 _mesa_unmap_teximage_pbo(ctx, packing);
3310 * This is the software fallback for Driver.TexSubImage3D().
3311 * and Driver.CopyTexSubImage3D().
3314 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
3315 GLint xoffset, GLint yoffset, GLint zoffset,
3316 GLint width, GLint height, GLint depth,
3317 GLenum format, GLenum type, const void *pixels,
3318 const struct gl_pixelstore_attrib *packing,
3319 struct gl_texture_object *texObj,
3320 struct gl_texture_image *texImage)
3322 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3323 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3324 type, pixels, packing,
3332 if (texImage->IsCompressed) {
3333 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3337 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3339 ASSERT(texImage->TexFormat->StoreImage);
3340 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
3341 texImage->TexFormat,
3343 xoffset, yoffset, zoffset,
3345 texImage->ImageOffsets,
3346 width, height, depth,
3347 format, type, pixels, packing);
3349 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
3353 /* GL_SGIS_generate_mipmap */
3354 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3355 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3358 _mesa_unmap_teximage_pbo(ctx, packing);
3363 * Fallback for Driver.CompressedTexImage1D()
3366 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3367 GLint internalFormat,
3368 GLint width, GLint border,
3369 GLsizei imageSize, const GLvoid *data,
3370 struct gl_texture_object *texObj,
3371 struct gl_texture_image *texImage)
3373 /* this space intentionally left blank */
3375 (void) target; (void) level;
3376 (void) internalFormat;
3377 (void) width; (void) border;
3378 (void) imageSize; (void) data;
3386 * Fallback for Driver.CompressedTexImage2D()
3389 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3390 GLint internalFormat,
3391 GLint width, GLint height, GLint border,
3392 GLsizei imageSize, const GLvoid *data,
3393 struct gl_texture_object *texObj,
3394 struct gl_texture_image *texImage)
3396 (void) width; (void) height; (void) border;
3398 /* This is pretty simple, basically just do a memcpy without worrying
3399 * about the usual image unpacking or image transfer operations.
3403 ASSERT(texImage->Width > 0);
3404 ASSERT(texImage->Height > 0);
3405 ASSERT(texImage->Depth == 1);
3406 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
3408 choose_texture_format(ctx, texImage, 2, 0, 0, internalFormat);
3410 /* allocate storage */
3411 texImage->Data = _mesa_alloc_texmemory(imageSize);
3412 if (!texImage->Data) {
3413 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3417 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3419 "glCompressedTexImage2D");
3424 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
3425 MEMCPY(texImage->Data, data, imageSize);
3427 /* GL_SGIS_generate_mipmap */
3428 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3429 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3432 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3438 * Fallback for Driver.CompressedTexImage3D()
3441 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3442 GLint internalFormat,
3443 GLint width, GLint height, GLint depth,
3445 GLsizei imageSize, const GLvoid *data,
3446 struct gl_texture_object *texObj,
3447 struct gl_texture_image *texImage)
3449 /* this space intentionally left blank */
3451 (void) target; (void) level;
3452 (void) internalFormat;
3453 (void) width; (void) height; (void) depth;
3455 (void) imageSize; (void) data;
3463 * Fallback for Driver.CompressedTexSubImage1D()
3466 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
3468 GLint xoffset, GLsizei width,
3470 GLsizei imageSize, const GLvoid *data,
3471 struct gl_texture_object *texObj,
3472 struct gl_texture_image *texImage)
3474 /* there are no compressed 1D texture formats yet */
3476 (void) target; (void) level;
3477 (void) xoffset; (void) width;
3479 (void) imageSize; (void) data;
3486 * Fallback for Driver.CompressedTexSubImage2D()
3489 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
3491 GLint xoffset, GLint yoffset,
3492 GLsizei width, GLsizei height,
3494 GLsizei imageSize, const GLvoid *data,
3495 struct gl_texture_object *texObj,
3496 struct gl_texture_image *texImage)
3498 GLint bytesPerRow, destRowStride, srcRowStride;
3502 const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
3506 /* these should have been caught sooner */
3507 ASSERT((width & 3) == 0 || width == 2 || width == 1);
3508 ASSERT((height & 3) == 0 || height == 2 || height == 1);
3509 ASSERT((xoffset & 3) == 0);
3510 ASSERT((yoffset & 3) == 0);
3512 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3513 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3515 "glCompressedTexSubImage2D");
3519 srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
3520 src = (const GLubyte *) data;
3522 destRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width);
3523 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
3524 texImage->TexFormat->MesaFormat,
3526 (GLubyte *) texImage->Data);
3528 bytesPerRow = srcRowStride;
3531 for (i = 0; i < rows; i++) {
3532 MEMCPY(dest, src, bytesPerRow);
3533 dest += destRowStride;
3534 src += srcRowStride;
3537 /* GL_SGIS_generate_mipmap */
3538 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3539 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3542 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3547 * Fallback for Driver.CompressedTexSubImage3D()
3550 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
3552 GLint xoffset, GLint yoffset, GLint zoffset,
3553 GLsizei width, GLsizei height, GLsizei depth,
3555 GLsizei imageSize, const GLvoid *data,
3556 struct gl_texture_object *texObj,
3557 struct gl_texture_image *texImage)
3559 /* there are no compressed 3D texture formats yet */
3561 (void) target; (void) level;
3562 (void) xoffset; (void) yoffset; (void) zoffset;
3563 (void) width; (void) height; (void) depth;
3565 (void) imageSize; (void) data;
3573 #if FEATURE_EXT_texture_sRGB
3576 * Test if given texture image is an sRGB format.
3579 is_srgb_teximage(const struct gl_texture_image *texImage)
3581 switch (texImage->TexFormat->MesaFormat) {
3582 case MESA_FORMAT_SRGB8:
3583 case MESA_FORMAT_SRGBA8:
3584 case MESA_FORMAT_SL8:
3585 case MESA_FORMAT_SLA8:
3592 #endif /* FEATURE_EXT_texture_sRGB */
3596 * This is the software fallback for Driver.GetTexImage().
3597 * All error checking will have been done before this routine is called.
3600 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
3601 GLenum format, GLenum type, GLvoid *pixels,
3602 struct gl_texture_object *texObj,
3603 struct gl_texture_image *texImage)
3605 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
3607 if (ctx->Pack.BufferObj->Name) {
3608 /* Packing texture image into a PBO.
3609 * Map the (potentially) VRAM-based buffer into our process space so
3610 * we can write into it with the code below.
3611 * A hardware driver might use a sophisticated blit to move the
3612 * texture data to the PBO if the PBO is in VRAM along with the texture.
3614 GLubyte *buf = (GLubyte *)
3615 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3616 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
3618 /* buffer is already mapped - that's an error */
3619 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
3622 /* <pixels> was an offset into the PBO.
3623 * Now make it a real, client-side pointer inside the mapped region.
3625 pixels = ADD_POINTERS(buf, pixels);
3633 const GLint width = texImage->Width;
3634 const GLint height = texImage->Height;
3635 const GLint depth = texImage->Depth;
3637 for (img = 0; img < depth; img++) {
3638 for (row = 0; row < height; row++) {
3639 /* compute destination address in client memory */
3640 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
3641 width, height, format, type,
3645 if (format == GL_COLOR_INDEX) {
3646 GLuint indexRow[MAX_WIDTH];
3648 /* Can't use FetchTexel here because that returns RGBA */
3649 if (texImage->TexFormat->IndexBits == 8) {
3650 const GLubyte *src = (const GLubyte *) texImage->Data;
3651 src += width * (img * texImage->Height + row);
3652 for (col = 0; col < width; col++) {
3653 indexRow[col] = src[col];
3656 else if (texImage->TexFormat->IndexBits == 16) {
3657 const GLushort *src = (const GLushort *) texImage->Data;
3658 src += width * (img * texImage->Height + row);
3659 for (col = 0; col < width; col++) {
3660 indexRow[col] = src[col];
3665 "Color index problem in _mesa_GetTexImage");
3667 _mesa_pack_index_span(ctx, width, type, dest,
3668 indexRow, &ctx->Pack,
3669 0 /* no image transfer */);
3671 else if (format == GL_DEPTH_COMPONENT) {
3672 GLfloat depthRow[MAX_WIDTH];
3674 for (col = 0; col < width; col++) {
3675 (*texImage->FetchTexelf)(texImage, col, row, img,
3678 _mesa_pack_depth_span(ctx, width, dest, type,
3679 depthRow, &ctx->Pack);
3681 else if (format == GL_DEPTH_STENCIL_EXT) {
3682 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3683 const GLuint *src = (const GLuint *) texImage->Data;
3684 src += width * row + width * height * img;
3685 _mesa_memcpy(dest, src, width * sizeof(GLuint));
3686 if (ctx->Pack.SwapBytes) {
3687 _mesa_swap4((GLuint *) dest, width);
3690 else if (format == GL_YCBCR_MESA) {
3691 /* No pixel transfer */
3692 const GLint rowstride = texImage->RowStride;
3694 (const GLushort *) texImage->Data + row * rowstride,
3695 width * sizeof(GLushort));
3696 /* check for byte swapping */
3697 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
3698 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
3699 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
3700 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
3701 if (!ctx->Pack.SwapBytes)
3702 _mesa_swap2((GLushort *) dest, width);
3704 else if (ctx->Pack.SwapBytes) {
3705 _mesa_swap2((GLushort *) dest, width);
3708 #if FEATURE_EXT_texture_sRGB
3709 else if (is_srgb_teximage(texImage)) {
3710 /* no pixel transfer and no non-linear to linear conversion */
3711 const GLint comps = texImage->TexFormat->TexelBytes;
3712 const GLint rowstride = comps * texImage->RowStride;
3714 (const GLubyte *) texImage->Data + row * rowstride,
3715 comps * width * sizeof(GLubyte));
3717 #endif /* FEATURE_EXT_texture_sRGB */
3719 /* general case: convert row to RGBA format */
3720 GLfloat rgba[MAX_WIDTH][4];
3722 for (col = 0; col < width; col++) {
3723 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
3724 if (texImage->TexFormat->BaseFormat == GL_ALPHA) {
3725 rgba[col][RCOMP] = 0.0;
3726 rgba[col][GCOMP] = 0.0;
3727 rgba[col][BCOMP] = 0.0;
3729 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) {
3730 rgba[col][GCOMP] = 0.0;
3731 rgba[col][BCOMP] = 0.0;
3732 rgba[col][ACOMP] = 1.0;
3734 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) {
3735 rgba[col][GCOMP] = 0.0;
3736 rgba[col][BCOMP] = 0.0;
3738 else if (texImage->TexFormat->BaseFormat == GL_INTENSITY) {
3739 rgba[col][GCOMP] = 0.0;
3740 rgba[col][BCOMP] = 0.0;
3741 rgba[col][ACOMP] = 1.0;
3744 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
3746 &ctx->Pack, 0x0 /*image xfer ops*/);
3752 if (ctx->Pack.BufferObj->Name) {
3753 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3754 ctx->Pack.BufferObj);
3761 * This is the software fallback for Driver.GetCompressedTexImage().
3762 * All error checking will have been done before this routine is called.
3765 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
3767 struct gl_texture_object *texObj,
3768 struct gl_texture_image *texImage)
3772 if (ctx->Pack.BufferObj->Name) {
3773 /* pack texture image into a PBO */
3775 if ((const GLubyte *) img + texImage->CompressedSize >
3776 (const GLubyte *) ctx->Pack.BufferObj->Size) {
3777 _mesa_error(ctx, GL_INVALID_OPERATION,
3778 "glGetCompressedTexImage(invalid PBO access)");
3781 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3783 ctx->Pack.BufferObj);
3785 /* buffer is already mapped - that's an error */
3786 _mesa_error(ctx, GL_INVALID_OPERATION,
3787 "glGetCompressedTexImage(PBO is mapped)");
3790 img = ADD_POINTERS(buf, img);
3797 /* don't use texImage->CompressedSize since that may be padded out */
3798 size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height,
3800 texImage->TexFormat->MesaFormat);
3802 /* just memcpy, no pixelstore or pixel transfer */
3803 _mesa_memcpy(img, texImage->Data, size);
3805 if (ctx->Pack.BufferObj->Name) {
3806 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3807 ctx->Pack.BufferObj);