2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 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
,
386 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
387 convWidth
= srcWidth
;
388 convHeight
= srcHeight
;
390 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
391 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
394 if (ctx
->Pixel
.Convolution2DEnabled
) {
395 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
399 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
400 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
406 /* do post-convolution transfer and pack into tempImage */
408 const GLint logComponents
409 = _mesa_components_in_format(logicalBaseFormat
);
410 const GLfloat
*src
= convImage
;
412 /* XXX: Both `convWidth' and `convHeight' are uninitialised -- windows compiler
413 * will issue warnings for the following line.
414 * Presumably this happens when `FEATURE_convolve' is defined to `0'.
416 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
417 for (row
= 0; row
< convHeight
; row
++) {
418 _mesa_pack_rgba_span_float(ctx
, convWidth
,
419 (GLfloat (*)[4]) src
,
420 logicalBaseFormat
, GL_FLOAT
,
421 dst
, &ctx
->DefaultPacking
,
422 postConvTransferOps
);
423 src
+= convWidth
* 4;
424 dst
+= convWidth
* logComponents
;
427 } /* loop over 3D image slices */
429 _mesa_free(convImage
);
431 /* might need these below */
432 srcWidth
= convWidth
;
433 srcHeight
= convHeight
;
437 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
438 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
439 srcWidth
, srcFormat
, srcType
);
443 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
444 * components
* sizeof(GLfloat
));
449 for (img
= 0; img
< srcDepth
; img
++) {
451 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
455 for (row
= 0; row
< srcHeight
; row
++) {
456 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
457 dst
, srcFormat
, srcType
, src
,
458 srcPacking
, transferOps
);
459 dst
+= srcWidth
* components
;
465 if (logicalBaseFormat
!= textureBaseFormat
) {
467 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
468 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
473 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
474 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
475 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
477 /* The actual texture format should have at least as many components
478 * as the logical texture format.
480 ASSERT(texComponents
>= logComponents
);
482 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
483 * texComponents
* sizeof(GLfloat
));
485 _mesa_free(tempImage
);
489 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
491 n
= srcWidth
* srcHeight
* srcDepth
;
492 for (i
= 0; i
< n
; i
++) {
494 for (k
= 0; k
< texComponents
; k
++) {
497 newImage
[i
* texComponents
+ k
] = 0.0F
;
499 newImage
[i
* texComponents
+ k
] = 1.0F
;
501 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
505 _mesa_free(tempImage
);
506 tempImage
= newImage
;
514 * Make a temporary (color) texture image with GLchan components.
515 * Apply all needed pixel unpacking and pixel transfer operations.
516 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
517 * Suppose the user specifies GL_LUMINANCE as the internal texture format
518 * but the graphics hardware doesn't support luminance textures. So, might
519 * use an RGB hardware format instead.
520 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
522 * \param ctx the rendering context
523 * \param dims image dimensions: 1, 2 or 3
524 * \param logicalBaseFormat basic texture derived from the user's
525 * internal texture format value
526 * \param textureBaseFormat the actual basic format of the texture
527 * \param srcWidth source image width
528 * \param srcHeight source image height
529 * \param srcDepth source image depth
530 * \param srcFormat source image format
531 * \param srcType source image type
532 * \param srcAddr source image address
533 * \param srcPacking source image pixel packing
534 * \return resulting image with format = textureBaseFormat and type = GLchan.
537 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
538 GLenum logicalBaseFormat
,
539 GLenum textureBaseFormat
,
540 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
541 GLenum srcFormat
, GLenum srcType
,
542 const GLvoid
*srcAddr
,
543 const struct gl_pixelstore_attrib
*srcPacking
)
545 GLuint transferOps
= ctx
->_ImageTransferState
;
546 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
547 GLboolean freeSrcImage
= GL_FALSE
;
549 GLchan
*tempImage
, *dst
;
551 ASSERT(dims
>= 1 && dims
<= 3);
553 ASSERT(logicalBaseFormat
== GL_RGBA
||
554 logicalBaseFormat
== GL_RGB
||
555 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
556 logicalBaseFormat
== GL_LUMINANCE
||
557 logicalBaseFormat
== GL_ALPHA
||
558 logicalBaseFormat
== GL_INTENSITY
);
560 ASSERT(textureBaseFormat
== GL_RGBA
||
561 textureBaseFormat
== GL_RGB
||
562 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
563 textureBaseFormat
== GL_LUMINANCE
||
564 textureBaseFormat
== GL_ALPHA
||
565 textureBaseFormat
== GL_INTENSITY
);
568 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
569 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
570 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
571 /* get convolved image */
572 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
575 srcWidth
, srcHeight
, srcDepth
,
577 srcAddr
, srcPacking
);
580 /* the convolved image is our new source image */
582 srcFormat
= logicalBaseFormat
;
584 srcPacking
= &ctx
->DefaultPacking
;
585 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
587 freeSrcImage
= GL_TRUE
;
591 /* unpack and transfer the source image */
592 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
593 * components
* sizeof(GLchan
));
598 for (img
= 0; img
< srcDepth
; img
++) {
599 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
603 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
607 for (row
= 0; row
< srcHeight
; row
++) {
608 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
609 srcFormat
, srcType
, src
, srcPacking
,
611 dst
+= srcWidth
* components
;
616 /* If we made a temporary image for convolution, free it here */
618 _mesa_free((void *) srcAddr
);
621 if (logicalBaseFormat
!= textureBaseFormat
) {
622 /* one more conversion step */
623 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
624 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
629 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
630 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
631 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
633 /* The actual texture format should have at least as many components
634 * as the logical texture format.
636 ASSERT(texComponents
>= logComponents
);
638 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
639 * texComponents
* sizeof(GLchan
));
641 _mesa_free(tempImage
);
645 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
647 n
= srcWidth
* srcHeight
* srcDepth
;
648 for (i
= 0; i
< n
; i
++) {
650 for (k
= 0; k
< texComponents
; k
++) {
653 newImage
[i
* texComponents
+ k
] = 0;
655 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
657 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
661 _mesa_free(tempImage
);
662 tempImage
= newImage
;
670 * Copy GLubyte pixels from <src> to <dst> with swizzling.
671 * \param dst destination pixels
672 * \param dstComponents number of color components in destination pixels
673 * \param src source pixels
674 * \param srcComponents number of color components in source pixels
675 * \param map the swizzle mapping. map[X] says where to find the X component
676 * in the source image's pixels. For example, if the source image
677 * is GL_BGRA and X = red, map[0] yields 2.
678 * \param count number of pixels to copy/swizzle.
681 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
682 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
690 switch (dstComponents
) {
692 for (i
= 0; i
< count
; i
++) {
694 src
+= srcComponents
;
695 dst
[0] = tmp
[map
[0]];
696 dst
[1] = tmp
[map
[1]];
697 dst
[2] = tmp
[map
[2]];
698 dst
[3] = tmp
[map
[3]];
703 for (i
= 0; i
< count
; i
++) {
705 src
+= srcComponents
;
706 dst
[0] = tmp
[map
[0]];
707 dst
[1] = tmp
[map
[1]];
708 dst
[2] = tmp
[map
[2]];
713 for (i
= 0; i
< count
; i
++) {
715 src
+= srcComponents
;
716 dst
[0] = tmp
[map
[0]];
717 dst
[1] = tmp
[map
[1]];
722 /* XXX investigate valgrind invalid read when running demos/texenv.c */
723 for (i
= 0; i
< count
; i
++) {
725 src
+= srcComponents
;
726 dst
[0] = tmp
[map
[0]];
734 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
735 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
737 /* Deal with the _REV input types:
739 static const GLubyte
*
740 type_mapping( GLenum srcType
)
743 case GL_UNSIGNED_BYTE
:
745 case GL_UNSIGNED_INT_8_8_8_8
:
746 return _mesa_little_endian() ? map_3210
: map_identity
;
747 case GL_UNSIGNED_INT_8_8_8_8_REV
:
748 return _mesa_little_endian() ? map_identity
: map_3210
;
754 /* Mapping required if input type is
756 static const GLubyte
*
757 byteswap_mapping( GLboolean swapBytes
,
764 case GL_UNSIGNED_BYTE
:
766 case GL_UNSIGNED_INT_8_8_8_8
:
767 case GL_UNSIGNED_INT_8_8_8_8_REV
:
777 * Transfer a GLubyte texture image with component swizzling.
780 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
785 GLenum baseInternalFormat
,
787 const GLubyte
*rgba2dst
,
788 GLuint dstComponents
,
791 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
793 const GLuint
*dstImageOffsets
,
795 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
796 const GLvoid
*srcAddr
,
797 const struct gl_pixelstore_attrib
*srcPacking
)
799 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
800 const GLubyte
*srctype2ubyte
, *swap
;
801 GLubyte map
[4], src2base
[6], base2rgba
[6];
803 const GLint srcRowStride
=
804 _mesa_image_row_stride(srcPacking
, srcWidth
,
805 srcFormat
, GL_UNSIGNED_BYTE
);
806 const GLint srcImageStride
807 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
809 const GLubyte
*srcImage
810 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
811 srcWidth
, srcHeight
, srcFormat
,
812 GL_UNSIGNED_BYTE
, 0, 0, 0);
816 /* Translate from src->baseInternal->GL_RGBA->dst. This will
817 * correctly deal with RGBA->RGB->RGBA conversions where the final
818 * A value must be 0xff regardless of the incoming alpha values.
820 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
821 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
822 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
823 srctype2ubyte
= type_mapping(srcType
);
826 for (i
= 0; i
< 4; i
++)
827 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
829 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
831 if (srcComponents
== dstComponents
&&
832 srcRowStride
== dstRowStride
&&
833 srcRowStride
== srcWidth
* srcComponents
&&
835 /* 1 and 2D images only */
836 GLubyte
*dstImage
= (GLubyte
*) dstAddr
837 + dstYoffset
* dstRowStride
838 + dstXoffset
* dstComponents
;
839 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
840 srcWidth
* srcHeight
);
844 for (img
= 0; img
< srcDepth
; img
++) {
845 const GLubyte
*srcRow
= srcImage
;
846 GLubyte
*dstRow
= (GLubyte
*) dstAddr
847 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
848 + dstYoffset
* dstRowStride
849 + dstXoffset
* dstComponents
;
850 for (row
= 0; row
< srcHeight
; row
++) {
851 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
852 dstRow
+= dstRowStride
;
853 srcRow
+= srcRowStride
;
855 srcImage
+= srcImageStride
;
862 * Teximage storage routine for when a simple memcpy will do.
863 * No pixel transfer operations or special texel encodings allowed.
864 * 1D, 2D and 3D images supported.
867 memcpy_texture(GLcontext
*ctx
,
869 const struct gl_texture_format
*dstFormat
,
871 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
873 const GLuint
*dstImageOffsets
,
874 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
875 GLenum srcFormat
, GLenum srcType
,
876 const GLvoid
*srcAddr
,
877 const struct gl_pixelstore_attrib
*srcPacking
)
879 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
881 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
882 srcWidth
, srcHeight
, srcFormat
, srcType
);
883 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
884 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
885 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
888 /* XXX update/re-enable for dstImageOffsets array */
889 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
890 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
891 GLubyte
*dstImage
= (GLubyte
*) dstAddr
892 + dstZoffset
* dstImageStride
893 + dstYoffset
* dstRowStride
894 + dstXoffset
* dstFormat
->TexelBytes
;
896 if (dstRowStride
== srcRowStride
&&
897 dstRowStride
== bytesPerRow
&&
898 ((dstImageStride
== srcImageStride
&&
899 dstImageStride
== bytesPerImage
) ||
902 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
907 for (img
= 0; img
< srcDepth
; img
++) {
908 const GLubyte
*srcRow
= srcImage
;
909 GLubyte
*dstRow
= dstImage
;
910 for (row
= 0; row
< srcHeight
; row
++) {
911 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
912 dstRow
+= dstRowStride
;
913 srcRow
+= srcRowStride
;
915 srcImage
+= srcImageStride
;
916 dstImage
+= dstImageStride
;
922 for (img
= 0; img
< srcDepth
; img
++) {
923 const GLubyte
*srcRow
= srcImage
;
924 GLubyte
*dstRow
= (GLubyte
*) dstAddr
925 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
926 + dstYoffset
* dstRowStride
927 + dstXoffset
* dstFormat
->TexelBytes
;
928 for (row
= 0; row
< srcHeight
; row
++) {
929 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
930 dstRow
+= dstRowStride
;
931 srcRow
+= srcRowStride
;
933 srcImage
+= srcImageStride
;
940 * Store an image in any of the formats:
941 * _mesa_texformat_rgba
942 * _mesa_texformat_rgb
943 * _mesa_texformat_alpha
944 * _mesa_texformat_luminance
945 * _mesa_texformat_luminance_alpha
946 * _mesa_texformat_intensity
950 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
952 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
954 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
955 dstFormat
== &_mesa_texformat_rgb
||
956 dstFormat
== &_mesa_texformat_alpha
||
957 dstFormat
== &_mesa_texformat_luminance
||
958 dstFormat
== &_mesa_texformat_luminance_alpha
||
959 dstFormat
== &_mesa_texformat_intensity
);
960 ASSERT(baseInternalFormat
== GL_RGBA
||
961 baseInternalFormat
== GL_RGB
||
962 baseInternalFormat
== GL_ALPHA
||
963 baseInternalFormat
== GL_LUMINANCE
||
964 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
965 baseInternalFormat
== GL_INTENSITY
);
966 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
968 if (!ctx
->_ImageTransferState
&&
969 !srcPacking
->SwapBytes
&&
970 baseInternalFormat
== srcFormat
&&
971 srcType
== CHAN_TYPE
) {
972 /* simple memcpy path */
973 memcpy_texture(ctx
, dims
,
974 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
977 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
978 srcAddr
, srcPacking
);
980 else if (!ctx
->_ImageTransferState
&&
981 !srcPacking
->SwapBytes
&&
982 dstFormat
== &_mesa_texformat_rgb
&&
983 srcFormat
== GL_RGBA
&&
984 srcType
== CHAN_TYPE
) {
985 /* extract RGB from RGBA */
987 for (img
= 0; img
< srcDepth
; img
++) {
988 GLchan
*dstImage
= (GLchan
*)
990 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
991 + dstYoffset
* dstRowStride
992 + dstXoffset
* dstFormat
->TexelBytes
);
994 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
995 srcWidth
, srcFormat
, srcType
);
996 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
997 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
998 GLchan
*dstRow
= dstImage
;
999 for (row
= 0; row
< srcHeight
; row
++) {
1000 for (col
= 0; col
< srcWidth
; col
++) {
1001 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
1002 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
1003 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
1005 dstRow
+= dstRowStride
/ sizeof(GLchan
);
1006 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
1010 else if (!ctx
->_ImageTransferState
&&
1011 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
1012 (srcType
== GL_UNSIGNED_BYTE
||
1013 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1014 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1015 can_swizzle(baseInternalFormat
) &&
1016 can_swizzle(srcFormat
)) {
1018 const GLubyte
*dstmap
;
1021 /* dstmap - how to swizzle from RGBA to dst format:
1023 if (dstFormat
== &_mesa_texformat_rgba
) {
1024 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1027 else if (dstFormat
== &_mesa_texformat_rgb
) {
1028 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1031 else if (dstFormat
== &_mesa_texformat_alpha
) {
1032 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1035 else if (dstFormat
== &_mesa_texformat_luminance
) {
1036 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1039 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1040 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1043 else if (dstFormat
== &_mesa_texformat_intensity
) {
1044 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1048 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1052 _mesa_swizzle_ubyte_image(ctx
, dims
,
1057 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1058 dstRowStride
, dstImageOffsets
,
1059 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1064 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1066 dstFormat
->BaseFormat
,
1067 srcWidth
, srcHeight
, srcDepth
,
1068 srcFormat
, srcType
, srcAddr
,
1070 const GLchan
*src
= tempImage
;
1075 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1076 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1077 for (img
= 0; img
< srcDepth
; img
++) {
1078 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1079 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1080 + dstYoffset
* dstRowStride
1081 + dstXoffset
* dstFormat
->TexelBytes
;
1082 for (row
= 0; row
< srcHeight
; row
++) {
1083 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1084 dstRow
+= dstRowStride
;
1085 src
+= srcWidth
* components
;
1089 _mesa_free((void *) tempImage
);
1096 * Store a 32-bit integer depth component texture image.
1099 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1101 const GLuint depthScale
= 0xffffffff;
1103 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1104 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1106 if (!ctx
->_ImageTransferState
&&
1107 !srcPacking
->SwapBytes
&&
1108 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1109 srcFormat
== GL_DEPTH_COMPONENT
&&
1110 srcType
== GL_UNSIGNED_INT
) {
1111 /* simple memcpy path */
1112 memcpy_texture(ctx
, dims
,
1113 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1116 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1117 srcAddr
, srcPacking
);
1122 for (img
= 0; img
< srcDepth
; img
++) {
1123 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1124 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1125 + dstYoffset
* dstRowStride
1126 + dstXoffset
* dstFormat
->TexelBytes
;
1127 for (row
= 0; row
< srcHeight
; row
++) {
1128 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1129 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1130 _mesa_unpack_depth_span(ctx
, srcWidth
,
1131 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1132 depthScale
, srcType
, src
, srcPacking
);
1133 dstRow
+= dstRowStride
;
1143 * Store a 16-bit integer depth component texture image.
1146 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1148 const GLuint depthScale
= 0xffff;
1150 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1151 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1153 if (!ctx
->_ImageTransferState
&&
1154 !srcPacking
->SwapBytes
&&
1155 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1156 srcFormat
== GL_DEPTH_COMPONENT
&&
1157 srcType
== GL_UNSIGNED_SHORT
) {
1158 /* simple memcpy path */
1159 memcpy_texture(ctx
, dims
,
1160 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1163 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1164 srcAddr
, srcPacking
);
1169 for (img
= 0; img
< srcDepth
; img
++) {
1170 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1171 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1172 + dstYoffset
* dstRowStride
1173 + dstXoffset
* dstFormat
->TexelBytes
;
1174 for (row
= 0; row
< srcHeight
; row
++) {
1175 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1176 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1177 GLushort
*dst16
= (GLushort
*) dstRow
;
1178 _mesa_unpack_depth_span(ctx
, srcWidth
,
1179 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1180 srcType
, src
, srcPacking
);
1181 dstRow
+= dstRowStride
;
1190 * Store an rgb565 or rgb565_rev texture image.
1193 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1195 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1196 dstFormat
== &_mesa_texformat_rgb565_rev
);
1197 ASSERT(dstFormat
->TexelBytes
== 2);
1199 if (!ctx
->_ImageTransferState
&&
1200 !srcPacking
->SwapBytes
&&
1201 dstFormat
== &_mesa_texformat_rgb565
&&
1202 baseInternalFormat
== GL_RGB
&&
1203 srcFormat
== GL_RGB
&&
1204 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1205 /* simple memcpy path */
1206 memcpy_texture(ctx
, dims
,
1207 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1210 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1211 srcAddr
, srcPacking
);
1213 else if (!ctx
->_ImageTransferState
&&
1214 !srcPacking
->SwapBytes
&&
1215 baseInternalFormat
== GL_RGB
&&
1216 srcFormat
== GL_RGB
&&
1217 srcType
== GL_UNSIGNED_BYTE
&&
1219 /* do optimized tex store */
1220 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1221 srcFormat
, srcType
);
1222 const GLubyte
*src
= (const GLubyte
*)
1223 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1224 srcFormat
, srcType
, 0, 0, 0);
1225 GLubyte
*dst
= (GLubyte
*) dstAddr
1226 + dstYoffset
* dstRowStride
1227 + dstXoffset
* dstFormat
->TexelBytes
;
1229 for (row
= 0; row
< srcHeight
; row
++) {
1230 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1231 GLushort
*dstUS
= (GLushort
*) dst
;
1232 /* check for byteswapped format */
1233 if (dstFormat
== &_mesa_texformat_rgb565
) {
1234 for (col
= 0; col
< srcWidth
; col
++) {
1235 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1240 for (col
= 0; col
< srcWidth
; col
++) {
1241 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1245 dst
+= dstRowStride
;
1246 src
+= srcRowStride
;
1251 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1253 dstFormat
->BaseFormat
,
1254 srcWidth
, srcHeight
, srcDepth
,
1255 srcFormat
, srcType
, srcAddr
,
1257 const GLchan
*src
= tempImage
;
1258 GLint img
, row
, col
;
1261 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1262 for (img
= 0; img
< srcDepth
; img
++) {
1263 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1264 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1265 + dstYoffset
* dstRowStride
1266 + dstXoffset
* dstFormat
->TexelBytes
;
1267 for (row
= 0; row
< srcHeight
; row
++) {
1268 GLushort
*dstUS
= (GLushort
*) dstRow
;
1269 /* check for byteswapped format */
1270 if (dstFormat
== &_mesa_texformat_rgb565
) {
1271 for (col
= 0; col
< srcWidth
; col
++) {
1272 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1273 CHAN_TO_UBYTE(src
[GCOMP
]),
1274 CHAN_TO_UBYTE(src
[BCOMP
]) );
1279 for (col
= 0; col
< srcWidth
; col
++) {
1280 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1281 CHAN_TO_UBYTE(src
[GCOMP
]),
1282 CHAN_TO_UBYTE(src
[BCOMP
]) );
1286 dstRow
+= dstRowStride
;
1289 _mesa_free((void *) tempImage
);
1296 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1299 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1301 const GLboolean littleEndian
= _mesa_little_endian();
1303 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1304 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1305 ASSERT(dstFormat
->TexelBytes
== 4);
1307 if (!ctx
->_ImageTransferState
&&
1308 !srcPacking
->SwapBytes
&&
1309 dstFormat
== &_mesa_texformat_rgba8888
&&
1310 baseInternalFormat
== GL_RGBA
&&
1311 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1312 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1313 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1314 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1315 /* simple memcpy path */
1316 memcpy_texture(ctx
, dims
,
1317 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1320 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1321 srcAddr
, srcPacking
);
1323 else if (!ctx
->_ImageTransferState
&&
1324 !srcPacking
->SwapBytes
&&
1325 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1326 baseInternalFormat
== GL_RGBA
&&
1327 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1328 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1329 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1330 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1331 /* simple memcpy path */
1332 memcpy_texture(ctx
, dims
,
1333 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1336 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1337 srcAddr
, srcPacking
);
1339 else if (!ctx
->_ImageTransferState
&&
1340 (srcType
== GL_UNSIGNED_BYTE
||
1341 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1342 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1343 can_swizzle(baseInternalFormat
) &&
1344 can_swizzle(srcFormat
)) {
1348 /* dstmap - how to swizzle from RGBA to dst format:
1350 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1351 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1364 _mesa_swizzle_ubyte_image(ctx
, dims
,
1369 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1370 dstRowStride
, dstImageOffsets
,
1371 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1376 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1378 dstFormat
->BaseFormat
,
1379 srcWidth
, srcHeight
, srcDepth
,
1380 srcFormat
, srcType
, srcAddr
,
1382 const GLchan
*src
= tempImage
;
1383 GLint img
, row
, col
;
1386 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1387 for (img
= 0; img
< srcDepth
; img
++) {
1388 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1389 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1390 + dstYoffset
* dstRowStride
1391 + dstXoffset
* dstFormat
->TexelBytes
;
1392 for (row
= 0; row
< srcHeight
; row
++) {
1393 GLuint
*dstUI
= (GLuint
*) dstRow
;
1394 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1395 for (col
= 0; col
< srcWidth
; col
++) {
1396 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1397 CHAN_TO_UBYTE(src
[GCOMP
]),
1398 CHAN_TO_UBYTE(src
[BCOMP
]),
1399 CHAN_TO_UBYTE(src
[ACOMP
]) );
1404 for (col
= 0; col
< srcWidth
; col
++) {
1405 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1406 CHAN_TO_UBYTE(src
[GCOMP
]),
1407 CHAN_TO_UBYTE(src
[BCOMP
]),
1408 CHAN_TO_UBYTE(src
[ACOMP
]) );
1412 dstRow
+= dstRowStride
;
1415 _mesa_free((void *) tempImage
);
1422 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1424 const GLboolean littleEndian
= _mesa_little_endian();
1426 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1427 dstFormat
== &_mesa_texformat_argb8888_rev
);
1428 ASSERT(dstFormat
->TexelBytes
== 4);
1430 if (!ctx
->_ImageTransferState
&&
1431 !srcPacking
->SwapBytes
&&
1432 dstFormat
== &_mesa_texformat_argb8888
&&
1433 baseInternalFormat
== GL_RGBA
&&
1434 srcFormat
== GL_BGRA
&&
1435 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1436 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1437 /* simple memcpy path (little endian) */
1438 memcpy_texture(ctx
, dims
,
1439 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1442 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1443 srcAddr
, srcPacking
);
1445 else if (!ctx
->_ImageTransferState
&&
1446 !srcPacking
->SwapBytes
&&
1447 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1448 baseInternalFormat
== GL_RGBA
&&
1449 srcFormat
== GL_BGRA
&&
1450 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1451 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1452 /* simple memcpy path (big endian) */
1453 memcpy_texture(ctx
, dims
,
1454 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1457 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1458 srcAddr
, srcPacking
);
1460 else if (!ctx
->_ImageTransferState
&&
1461 !srcPacking
->SwapBytes
&&
1462 dstFormat
== &_mesa_texformat_argb8888
&&
1463 srcFormat
== GL_RGB
&&
1464 (baseInternalFormat
== GL_RGBA
||
1465 baseInternalFormat
== GL_RGB
) &&
1466 srcType
== GL_UNSIGNED_BYTE
) {
1468 for (img
= 0; img
< srcDepth
; img
++) {
1469 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1470 srcWidth
, srcFormat
, srcType
);
1471 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1472 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1473 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1474 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1475 + dstYoffset
* dstRowStride
1476 + dstXoffset
* dstFormat
->TexelBytes
;
1477 for (row
= 0; row
< srcHeight
; row
++) {
1478 GLuint
*d4
= (GLuint
*) dstRow
;
1479 for (col
= 0; col
< srcWidth
; col
++) {
1480 d4
[col
] = ((0xff << 24) |
1481 (srcRow
[col
* 3 + RCOMP
] << 16) |
1482 (srcRow
[col
* 3 + GCOMP
] << 8) |
1483 (srcRow
[col
* 3 + BCOMP
] << 0));
1485 dstRow
+= dstRowStride
;
1486 srcRow
+= srcRowStride
;
1490 else if (!ctx
->_ImageTransferState
&&
1491 !srcPacking
->SwapBytes
&&
1492 dstFormat
== &_mesa_texformat_argb8888
&&
1493 srcFormat
== GL_RGBA
&&
1494 baseInternalFormat
== GL_RGBA
&&
1495 srcType
== GL_UNSIGNED_BYTE
&&
1497 /* same as above case, but src data has alpha too */
1498 GLint img
, row
, col
;
1499 /* For some reason, streaming copies to write-combined regions
1500 * are extremely sensitive to the characteristics of how the
1501 * source data is retrieved. By reordering the source reads to
1502 * be in-order, the speed of this operation increases by half.
1503 * Strangely the same isn't required for the RGB path, above.
1505 for (img
= 0; img
< srcDepth
; img
++) {
1506 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1507 srcWidth
, srcFormat
, srcType
);
1508 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1509 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1510 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1511 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1512 + dstYoffset
* dstRowStride
1513 + dstXoffset
* dstFormat
->TexelBytes
;
1514 for (row
= 0; row
< srcHeight
; row
++) {
1515 GLuint
*d4
= (GLuint
*) dstRow
;
1516 for (col
= 0; col
< srcWidth
; col
++) {
1517 d4
[col
] = ((srcRow
[col
* 4 + ACOMP
] << 24) |
1518 (srcRow
[col
* 4 + RCOMP
] << 16) |
1519 (srcRow
[col
* 4 + GCOMP
] << 8) |
1520 (srcRow
[col
* 4 + BCOMP
] << 0));
1522 dstRow
+= dstRowStride
;
1523 srcRow
+= srcRowStride
;
1527 else if (!ctx
->_ImageTransferState
&&
1528 !srcPacking
->SwapBytes
&&
1529 dstFormat
== &_mesa_texformat_argb8888
&&
1530 srcFormat
== GL_RGBA
&&
1531 baseInternalFormat
== GL_RGBA
&&
1532 srcType
== GL_UNSIGNED_BYTE
) {
1534 GLint img
, row
, col
;
1535 for (img
= 0; img
< srcDepth
; img
++) {
1536 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1537 srcWidth
, srcFormat
, srcType
);
1538 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1539 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1540 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1541 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1542 + dstYoffset
* dstRowStride
1543 + dstXoffset
* dstFormat
->TexelBytes
;
1544 for (row
= 0; row
< srcHeight
; row
++) {
1545 for (col
= 0; col
< srcWidth
; col
++) {
1546 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1547 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1548 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1549 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1551 dstRow
+= dstRowStride
;
1552 srcRow
+= srcRowStride
;
1556 else if (!ctx
->_ImageTransferState
&&
1557 (srcType
== GL_UNSIGNED_BYTE
||
1558 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1559 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1560 can_swizzle(baseInternalFormat
) &&
1561 can_swizzle(srcFormat
)) {
1565 /* dstmap - how to swizzle from RGBA to dst format:
1567 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1568 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1569 dstmap
[3] = 3; /* alpha */
1570 dstmap
[2] = 0; /* red */
1571 dstmap
[1] = 1; /* green */
1572 dstmap
[0] = 2; /* blue */
1575 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1576 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1583 _mesa_swizzle_ubyte_image(ctx
, dims
,
1589 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1592 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1597 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1599 dstFormat
->BaseFormat
,
1600 srcWidth
, srcHeight
, srcDepth
,
1601 srcFormat
, srcType
, srcAddr
,
1603 const GLchan
*src
= tempImage
;
1604 GLint img
, row
, col
;
1607 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1608 for (img
= 0; img
< srcDepth
; img
++) {
1609 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1610 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1611 + dstYoffset
* dstRowStride
1612 + dstXoffset
* dstFormat
->TexelBytes
;
1613 for (row
= 0; row
< srcHeight
; row
++) {
1614 GLuint
*dstUI
= (GLuint
*) dstRow
;
1615 if (dstFormat
== &_mesa_texformat_argb8888
) {
1616 for (col
= 0; col
< srcWidth
; col
++) {
1617 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1618 CHAN_TO_UBYTE(src
[RCOMP
]),
1619 CHAN_TO_UBYTE(src
[GCOMP
]),
1620 CHAN_TO_UBYTE(src
[BCOMP
]) );
1625 for (col
= 0; col
< srcWidth
; col
++) {
1626 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1627 CHAN_TO_UBYTE(src
[RCOMP
]),
1628 CHAN_TO_UBYTE(src
[GCOMP
]),
1629 CHAN_TO_UBYTE(src
[BCOMP
]) );
1633 dstRow
+= dstRowStride
;
1636 _mesa_free((void *) tempImage
);
1643 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1645 const GLboolean littleEndian
= _mesa_little_endian();
1647 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1648 ASSERT(dstFormat
->TexelBytes
== 3);
1650 if (!ctx
->_ImageTransferState
&&
1651 !srcPacking
->SwapBytes
&&
1652 baseInternalFormat
== GL_RGB
&&
1653 srcFormat
== GL_BGR
&&
1654 srcType
== GL_UNSIGNED_BYTE
&&
1656 /* simple memcpy path */
1657 memcpy_texture(ctx
, dims
,
1658 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1661 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1662 srcAddr
, srcPacking
);
1664 else if (!ctx
->_ImageTransferState
&&
1665 !srcPacking
->SwapBytes
&&
1666 srcFormat
== GL_RGBA
&&
1667 srcType
== GL_UNSIGNED_BYTE
) {
1668 /* extract RGB from RGBA */
1669 GLint img
, row
, col
;
1670 for (img
= 0; img
< srcDepth
; img
++) {
1671 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1672 srcWidth
, srcFormat
, srcType
);
1673 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1674 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1675 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1676 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1677 + dstYoffset
* dstRowStride
1678 + dstXoffset
* dstFormat
->TexelBytes
;
1679 for (row
= 0; row
< srcHeight
; row
++) {
1680 for (col
= 0; col
< srcWidth
; col
++) {
1681 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1682 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1683 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1685 dstRow
+= dstRowStride
;
1686 srcRow
+= srcRowStride
;
1690 else if (!ctx
->_ImageTransferState
&&
1691 srcType
== GL_UNSIGNED_BYTE
&&
1692 can_swizzle(baseInternalFormat
) &&
1693 can_swizzle(srcFormat
)) {
1697 /* dstmap - how to swizzle from RGBA to dst format:
1702 dstmap
[3] = ONE
; /* ? */
1704 _mesa_swizzle_ubyte_image(ctx
, dims
,
1709 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1710 dstRowStride
, dstImageOffsets
,
1711 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1716 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1718 dstFormat
->BaseFormat
,
1719 srcWidth
, srcHeight
, srcDepth
,
1720 srcFormat
, srcType
, srcAddr
,
1722 const GLchan
*src
= (const GLchan
*) tempImage
;
1723 GLint img
, row
, col
;
1726 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1727 for (img
= 0; img
< srcDepth
; img
++) {
1728 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1729 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1730 + dstYoffset
* dstRowStride
1731 + dstXoffset
* dstFormat
->TexelBytes
;
1732 for (row
= 0; row
< srcHeight
; row
++) {
1735 for (col
= 0; col
< srcWidth
; col
++) {
1736 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1737 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1738 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1743 for (col
= 0; col
< srcWidth
; col
++) {
1744 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1745 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1746 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1751 for (col
= 0; col
< srcWidth
; col
++) {
1752 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1753 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1754 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1758 dstRow
+= dstRowStride
;
1761 _mesa_free((void *) tempImage
);
1768 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1770 const GLboolean littleEndian
= _mesa_little_endian();
1772 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1773 ASSERT(dstFormat
->TexelBytes
== 3);
1775 if (!ctx
->_ImageTransferState
&&
1776 !srcPacking
->SwapBytes
&&
1777 baseInternalFormat
== GL_RGB
&&
1778 srcFormat
== GL_RGB
&&
1779 srcType
== GL_UNSIGNED_BYTE
&&
1781 /* simple memcpy path */
1782 memcpy_texture(ctx
, dims
,
1783 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1786 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1787 srcAddr
, srcPacking
);
1789 else if (!ctx
->_ImageTransferState
&&
1790 !srcPacking
->SwapBytes
&&
1791 srcFormat
== GL_RGBA
&&
1792 srcType
== GL_UNSIGNED_BYTE
) {
1793 /* extract BGR from RGBA */
1795 for (img
= 0; img
< srcDepth
; img
++) {
1796 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1797 srcWidth
, srcFormat
, srcType
);
1798 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1799 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1800 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1801 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1802 + dstYoffset
* dstRowStride
1803 + dstXoffset
* dstFormat
->TexelBytes
;
1804 for (row
= 0; row
< srcHeight
; row
++) {
1805 for (col
= 0; col
< srcWidth
; col
++) {
1806 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1807 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1808 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1810 dstRow
+= dstRowStride
;
1811 srcRow
+= srcRowStride
;
1815 else if (!ctx
->_ImageTransferState
&&
1816 srcType
== GL_UNSIGNED_BYTE
&&
1817 can_swizzle(baseInternalFormat
) &&
1818 can_swizzle(srcFormat
)) {
1822 /* dstmap - how to swizzle from RGBA to dst format:
1827 dstmap
[3] = ONE
; /* ? */
1829 _mesa_swizzle_ubyte_image(ctx
, dims
,
1834 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1835 dstRowStride
, dstImageOffsets
,
1836 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1841 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1843 dstFormat
->BaseFormat
,
1844 srcWidth
, srcHeight
, srcDepth
,
1845 srcFormat
, srcType
, srcAddr
,
1847 const GLchan
*src
= (const GLchan
*) tempImage
;
1848 GLint img
, row
, col
;
1851 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1852 for (img
= 0; img
< srcDepth
; img
++) {
1853 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1854 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1855 + dstYoffset
* dstRowStride
1856 + dstXoffset
* dstFormat
->TexelBytes
;
1857 for (row
= 0; row
< srcHeight
; row
++) {
1858 for (col
= 0; col
< srcWidth
; col
++) {
1859 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1860 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1861 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1864 dstRow
+= dstRowStride
;
1867 _mesa_free((void *) tempImage
);
1874 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1876 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1877 dstFormat
== &_mesa_texformat_argb4444_rev
);
1878 ASSERT(dstFormat
->TexelBytes
== 2);
1880 if (!ctx
->_ImageTransferState
&&
1881 !srcPacking
->SwapBytes
&&
1882 dstFormat
== &_mesa_texformat_argb4444
&&
1883 baseInternalFormat
== GL_RGBA
&&
1884 srcFormat
== GL_BGRA
&&
1885 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1886 /* simple memcpy path */
1887 memcpy_texture(ctx
, dims
,
1888 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1891 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1892 srcAddr
, srcPacking
);
1896 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1898 dstFormat
->BaseFormat
,
1899 srcWidth
, srcHeight
, srcDepth
,
1900 srcFormat
, srcType
, srcAddr
,
1902 const GLchan
*src
= tempImage
;
1903 GLint img
, row
, col
;
1906 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1907 for (img
= 0; img
< srcDepth
; img
++) {
1908 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1909 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1910 + dstYoffset
* dstRowStride
1911 + dstXoffset
* dstFormat
->TexelBytes
;
1912 for (row
= 0; row
< srcHeight
; row
++) {
1913 GLushort
*dstUS
= (GLushort
*) dstRow
;
1914 if (dstFormat
== &_mesa_texformat_argb4444
) {
1915 for (col
= 0; col
< srcWidth
; col
++) {
1916 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1917 CHAN_TO_UBYTE(src
[RCOMP
]),
1918 CHAN_TO_UBYTE(src
[GCOMP
]),
1919 CHAN_TO_UBYTE(src
[BCOMP
]) );
1924 for (col
= 0; col
< srcWidth
; col
++) {
1925 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1926 CHAN_TO_UBYTE(src
[RCOMP
]),
1927 CHAN_TO_UBYTE(src
[GCOMP
]),
1928 CHAN_TO_UBYTE(src
[BCOMP
]) );
1932 dstRow
+= dstRowStride
;
1935 _mesa_free((void *) tempImage
);
1943 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1945 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1946 dstFormat
== &_mesa_texformat_argb1555_rev
);
1947 ASSERT(dstFormat
->TexelBytes
== 2);
1949 if (!ctx
->_ImageTransferState
&&
1950 !srcPacking
->SwapBytes
&&
1951 dstFormat
== &_mesa_texformat_argb1555
&&
1952 baseInternalFormat
== GL_RGBA
&&
1953 srcFormat
== GL_BGRA
&&
1954 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1955 /* simple memcpy path */
1956 memcpy_texture(ctx
, dims
,
1957 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1960 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1961 srcAddr
, srcPacking
);
1965 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1967 dstFormat
->BaseFormat
,
1968 srcWidth
, srcHeight
, srcDepth
,
1969 srcFormat
, srcType
, srcAddr
,
1971 const GLchan
*src
=tempImage
;
1972 GLint img
, row
, col
;
1975 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1976 for (img
= 0; img
< srcDepth
; img
++) {
1977 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1978 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1979 + dstYoffset
* dstRowStride
1980 + dstXoffset
* dstFormat
->TexelBytes
;
1981 for (row
= 0; row
< srcHeight
; row
++) {
1982 GLushort
*dstUS
= (GLushort
*) dstRow
;
1983 if (dstFormat
== &_mesa_texformat_argb1555
) {
1984 for (col
= 0; col
< srcWidth
; col
++) {
1985 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1986 CHAN_TO_UBYTE(src
[RCOMP
]),
1987 CHAN_TO_UBYTE(src
[GCOMP
]),
1988 CHAN_TO_UBYTE(src
[BCOMP
]) );
1993 for (col
= 0; col
< srcWidth
; col
++) {
1994 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1995 CHAN_TO_UBYTE(src
[RCOMP
]),
1996 CHAN_TO_UBYTE(src
[GCOMP
]),
1997 CHAN_TO_UBYTE(src
[BCOMP
]) );
2001 dstRow
+= dstRowStride
;
2004 _mesa_free((void *) tempImage
);
2011 _mesa_texstore_al88(TEXSTORE_PARAMS
)
2013 const GLboolean littleEndian
= _mesa_little_endian();
2015 ASSERT(dstFormat
== &_mesa_texformat_al88
||
2016 dstFormat
== &_mesa_texformat_al88_rev
);
2017 ASSERT(dstFormat
->TexelBytes
== 2);
2019 if (!ctx
->_ImageTransferState
&&
2020 !srcPacking
->SwapBytes
&&
2021 dstFormat
== &_mesa_texformat_al88
&&
2022 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2023 srcFormat
== GL_LUMINANCE_ALPHA
&&
2024 srcType
== GL_UNSIGNED_BYTE
&&
2026 /* simple memcpy path */
2027 memcpy_texture(ctx
, dims
,
2028 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2031 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2032 srcAddr
, srcPacking
);
2034 else if (!ctx
->_ImageTransferState
&&
2036 srcType
== GL_UNSIGNED_BYTE
&&
2037 can_swizzle(baseInternalFormat
) &&
2038 can_swizzle(srcFormat
)) {
2042 /* dstmap - how to swizzle from RGBA to dst format:
2044 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2045 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2053 dstmap
[2] = ZERO
; /* ? */
2054 dstmap
[3] = ONE
; /* ? */
2056 _mesa_swizzle_ubyte_image(ctx
, dims
,
2061 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2062 dstRowStride
, dstImageOffsets
,
2063 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2068 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2070 dstFormat
->BaseFormat
,
2071 srcWidth
, srcHeight
, srcDepth
,
2072 srcFormat
, srcType
, srcAddr
,
2074 const GLchan
*src
= tempImage
;
2075 GLint img
, row
, col
;
2078 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2079 for (img
= 0; img
< srcDepth
; img
++) {
2080 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2081 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2082 + dstYoffset
* dstRowStride
2083 + dstXoffset
* dstFormat
->TexelBytes
;
2084 for (row
= 0; row
< srcHeight
; row
++) {
2085 GLushort
*dstUS
= (GLushort
*) dstRow
;
2086 if (dstFormat
== &_mesa_texformat_al88
) {
2087 for (col
= 0; col
< srcWidth
; col
++) {
2088 /* src[0] is luminance, src[1] is alpha */
2089 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2090 CHAN_TO_UBYTE(src
[0]) );
2095 for (col
= 0; col
< srcWidth
; col
++) {
2096 /* src[0] is luminance, src[1] is alpha */
2097 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2098 CHAN_TO_UBYTE(src
[0]) );
2102 dstRow
+= dstRowStride
;
2105 _mesa_free((void *) tempImage
);
2112 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2114 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2115 ASSERT(dstFormat
->TexelBytes
== 1);
2117 if (!ctx
->_ImageTransferState
&&
2118 !srcPacking
->SwapBytes
&&
2119 baseInternalFormat
== GL_RGB
&&
2120 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2121 /* simple memcpy path */
2122 memcpy_texture(ctx
, dims
,
2123 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2126 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2127 srcAddr
, srcPacking
);
2131 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2133 dstFormat
->BaseFormat
,
2134 srcWidth
, srcHeight
, srcDepth
,
2135 srcFormat
, srcType
, srcAddr
,
2137 const GLchan
*src
= tempImage
;
2138 GLint img
, row
, col
;
2141 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2142 for (img
= 0; img
< srcDepth
; img
++) {
2143 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2144 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2145 + dstYoffset
* dstRowStride
2146 + dstXoffset
* dstFormat
->TexelBytes
;
2147 for (row
= 0; row
< srcHeight
; row
++) {
2148 for (col
= 0; col
< srcWidth
; col
++) {
2149 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2150 CHAN_TO_UBYTE(src
[GCOMP
]),
2151 CHAN_TO_UBYTE(src
[BCOMP
]) );
2154 dstRow
+= dstRowStride
;
2157 _mesa_free((void *) tempImage
);
2164 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2167 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2169 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2170 dstFormat
== &_mesa_texformat_l8
||
2171 dstFormat
== &_mesa_texformat_i8
);
2172 ASSERT(dstFormat
->TexelBytes
== 1);
2174 if (!ctx
->_ImageTransferState
&&
2175 !srcPacking
->SwapBytes
&&
2176 baseInternalFormat
== srcFormat
&&
2177 srcType
== GL_UNSIGNED_BYTE
) {
2178 /* simple memcpy path */
2179 memcpy_texture(ctx
, dims
,
2180 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2183 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2184 srcAddr
, srcPacking
);
2186 else if (!ctx
->_ImageTransferState
&&
2187 srcType
== GL_UNSIGNED_BYTE
&&
2188 can_swizzle(baseInternalFormat
) &&
2189 can_swizzle(srcFormat
)) {
2193 /* dstmap - how to swizzle from RGBA to dst format:
2195 if (dstFormat
== &_mesa_texformat_a8
) {
2201 dstmap
[1] = ZERO
; /* ? */
2202 dstmap
[2] = ZERO
; /* ? */
2203 dstmap
[3] = ONE
; /* ? */
2205 _mesa_swizzle_ubyte_image(ctx
, dims
,
2210 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2211 dstRowStride
, dstImageOffsets
,
2212 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2217 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2219 dstFormat
->BaseFormat
,
2220 srcWidth
, srcHeight
, srcDepth
,
2221 srcFormat
, srcType
, srcAddr
,
2223 const GLchan
*src
= tempImage
;
2224 GLint img
, row
, col
;
2227 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2228 for (img
= 0; img
< srcDepth
; img
++) {
2229 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2230 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2231 + dstYoffset
* dstRowStride
2232 + dstXoffset
* dstFormat
->TexelBytes
;
2233 for (row
= 0; row
< srcHeight
; row
++) {
2234 for (col
= 0; col
< srcWidth
; col
++) {
2235 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2237 dstRow
+= dstRowStride
;
2241 _mesa_free((void *) tempImage
);
2249 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2251 (void) dims
; (void) baseInternalFormat
;
2252 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2253 ASSERT(dstFormat
->TexelBytes
== 1);
2254 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2256 if (!ctx
->_ImageTransferState
&&
2257 !srcPacking
->SwapBytes
&&
2258 srcFormat
== GL_COLOR_INDEX
&&
2259 srcType
== GL_UNSIGNED_BYTE
) {
2260 /* simple memcpy path */
2261 memcpy_texture(ctx
, dims
,
2262 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2265 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2266 srcAddr
, srcPacking
);
2271 for (img
= 0; img
< srcDepth
; img
++) {
2272 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2273 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2274 + dstYoffset
* dstRowStride
2275 + dstXoffset
* dstFormat
->TexelBytes
;
2276 for (row
= 0; row
< srcHeight
; row
++) {
2277 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2278 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2279 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2280 srcType
, src
, srcPacking
,
2281 ctx
->_ImageTransferState
);
2282 dstRow
+= dstRowStride
;
2291 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2294 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2296 const GLboolean littleEndian
= _mesa_little_endian();
2297 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2299 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2300 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2301 ASSERT(dstFormat
->TexelBytes
== 2);
2302 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2303 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2304 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2305 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2306 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2308 /* always just memcpy since no pixel transfer ops apply */
2309 memcpy_texture(ctx
, dims
,
2310 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2313 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2314 srcAddr
, srcPacking
);
2316 /* Check if we need byte swapping */
2317 /* XXX the logic here _might_ be wrong */
2318 if (srcPacking
->SwapBytes
^
2319 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2320 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2323 for (img
= 0; img
< srcDepth
; img
++) {
2324 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2325 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2326 + dstYoffset
* dstRowStride
2327 + dstXoffset
* dstFormat
->TexelBytes
;
2328 for (row
= 0; row
< srcHeight
; row
++) {
2329 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2330 dstRow
+= dstRowStride
;
2340 * Store a combined depth/stencil texture image.
2343 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2345 const GLfloat depthScale
= (GLfloat
) 0xffffff;
2347 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2348 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2349 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2351 if (!ctx
->_ImageTransferState
&&
2352 !srcPacking
->SwapBytes
) {
2354 memcpy_texture(ctx
, dims
,
2355 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2358 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2359 srcAddr
, srcPacking
);
2363 const GLint srcRowStride
2364 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2368 for (img
= 0; img
< srcDepth
; img
++) {
2369 GLuint
*dstRow
= (GLuint
*) dstAddr
2370 + dstImageOffsets
[dstZoffset
+ img
]
2371 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2374 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2375 srcWidth
, srcHeight
,
2378 for (row
= 0; row
< srcHeight
; row
++) {
2379 GLubyte stencil
[MAX_WIDTH
];
2381 /* the 24 depth bits will be in the high position: */
2382 _mesa_unpack_depth_span(ctx
, srcWidth
,
2383 GL_UNSIGNED_INT_24_8_EXT
, /* dst type */
2384 dstRow
, /* dst addr */
2385 (GLuint
) depthScale
,
2386 srcType
, src
, srcPacking
);
2387 /* get the 8-bit stencil values */
2388 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2389 GL_UNSIGNED_BYTE
, /* dst type */
2390 stencil
, /* dst addr */
2391 srcType
, src
, srcPacking
,
2392 ctx
->_ImageTransferState
);
2393 /* merge stencil values into depth values */
2394 for (i
= 0; i
< srcWidth
; i
++)
2395 dstRow
[i
] |= stencil
[i
];
2397 src
+= srcRowStride
;
2398 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2407 * Store a combined depth/stencil texture image.
2410 _mesa_texstore_s8_z24(TEXSTORE_PARAMS
)
2412 const GLuint depthScale
= 0xffffff;
2413 const GLint srcRowStride
2414 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2418 ASSERT(dstFormat
== &_mesa_texformat_s8_z24
);
2419 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
|| srcFormat
== GL_DEPTH_COMPONENT
);
2420 ASSERT(srcFormat
!= GL_DEPTH_STENCIL_EXT
|| srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2422 /* Incase we only upload depth we need to preserve the stencil */
2423 if (srcFormat
== GL_DEPTH_COMPONENT
) {
2424 for (img
= 0; img
< srcDepth
; img
++) {
2425 GLuint
*dstRow
= (GLuint
*) dstAddr
2426 + dstImageOffsets
[dstZoffset
+ img
]
2427 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2430 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2431 srcWidth
, srcHeight
,
2434 for (row
= 0; row
< srcHeight
; row
++) {
2435 GLuint depth
[MAX_WIDTH
];
2437 _mesa_unpack_depth_span(ctx
, srcWidth
,
2438 GL_UNSIGNED_INT
, /* dst type */
2439 depth
, /* dst addr */
2441 srcType
, src
, srcPacking
);
2443 for (i
= 0; i
< srcWidth
; i
++)
2444 dstRow
[i
] = depth
[i
] | (dstRow
[i
] & 0xFF000000);
2446 src
+= srcRowStride
;
2447 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2451 for (img
= 0; img
< srcDepth
; img
++) {
2452 GLuint
*dstRow
= (GLuint
*) dstAddr
2453 + dstImageOffsets
[dstZoffset
+ img
]
2454 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2457 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2458 srcWidth
, srcHeight
,
2461 for (row
= 0; row
< srcHeight
; row
++) {
2462 GLubyte stencil
[MAX_WIDTH
];
2464 /* the 24 depth bits will be in the high position: */
2465 _mesa_unpack_depth_span(ctx
, srcWidth
,
2466 GL_UNSIGNED_INT
, /* dst type */
2467 dstRow
, /* dst addr */
2469 srcType
, src
, srcPacking
);
2470 /* get the 8-bit stencil values */
2471 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2472 GL_UNSIGNED_BYTE
, /* dst type */
2473 stencil
, /* dst addr */
2474 srcType
, src
, srcPacking
,
2475 ctx
->_ImageTransferState
);
2476 /* merge stencil values into depth values */
2477 for (i
= 0; i
< srcWidth
; i
++)
2478 dstRow
[i
] = stencil
[i
] << 24;
2480 src
+= srcRowStride
;
2481 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2489 * Store an image in any of the formats:
2490 * _mesa_texformat_rgba_float32
2491 * _mesa_texformat_rgb_float32
2492 * _mesa_texformat_alpha_float32
2493 * _mesa_texformat_luminance_float32
2494 * _mesa_texformat_luminance_alpha_float32
2495 * _mesa_texformat_intensity_float32
2498 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2500 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2502 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2503 dstFormat
== &_mesa_texformat_rgb_float32
||
2504 dstFormat
== &_mesa_texformat_alpha_float32
||
2505 dstFormat
== &_mesa_texformat_luminance_float32
||
2506 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2507 dstFormat
== &_mesa_texformat_intensity_float32
);
2508 ASSERT(baseInternalFormat
== GL_RGBA
||
2509 baseInternalFormat
== GL_RGB
||
2510 baseInternalFormat
== GL_ALPHA
||
2511 baseInternalFormat
== GL_LUMINANCE
||
2512 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2513 baseInternalFormat
== GL_INTENSITY
);
2514 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2516 if (!ctx
->_ImageTransferState
&&
2517 !srcPacking
->SwapBytes
&&
2518 baseInternalFormat
== srcFormat
&&
2519 srcType
== GL_FLOAT
) {
2520 /* simple memcpy path */
2521 memcpy_texture(ctx
, dims
,
2522 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2525 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2526 srcAddr
, srcPacking
);
2530 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2532 dstFormat
->BaseFormat
,
2533 srcWidth
, srcHeight
, srcDepth
,
2534 srcFormat
, srcType
, srcAddr
,
2536 const GLfloat
*srcRow
= tempImage
;
2541 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2542 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2543 for (img
= 0; img
< srcDepth
; img
++) {
2544 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2545 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2546 + dstYoffset
* dstRowStride
2547 + dstXoffset
* dstFormat
->TexelBytes
;
2548 for (row
= 0; row
< srcHeight
; row
++) {
2549 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2550 dstRow
+= dstRowStride
;
2551 srcRow
+= srcWidth
* components
;
2555 _mesa_free((void *) tempImage
);
2562 * As above, but store 16-bit floats.
2565 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2567 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2569 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2570 dstFormat
== &_mesa_texformat_rgb_float16
||
2571 dstFormat
== &_mesa_texformat_alpha_float16
||
2572 dstFormat
== &_mesa_texformat_luminance_float16
||
2573 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2574 dstFormat
== &_mesa_texformat_intensity_float16
);
2575 ASSERT(baseInternalFormat
== GL_RGBA
||
2576 baseInternalFormat
== GL_RGB
||
2577 baseInternalFormat
== GL_ALPHA
||
2578 baseInternalFormat
== GL_LUMINANCE
||
2579 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2580 baseInternalFormat
== GL_INTENSITY
);
2581 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2583 if (!ctx
->_ImageTransferState
&&
2584 !srcPacking
->SwapBytes
&&
2585 baseInternalFormat
== srcFormat
&&
2586 srcType
== GL_HALF_FLOAT_ARB
) {
2587 /* simple memcpy path */
2588 memcpy_texture(ctx
, dims
,
2589 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2592 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2593 srcAddr
, srcPacking
);
2597 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2599 dstFormat
->BaseFormat
,
2600 srcWidth
, srcHeight
, srcDepth
,
2601 srcFormat
, srcType
, srcAddr
,
2603 const GLfloat
*src
= tempImage
;
2607 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2608 for (img
= 0; img
< srcDepth
; img
++) {
2609 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2610 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2611 + dstYoffset
* dstRowStride
2612 + dstXoffset
* dstFormat
->TexelBytes
;
2613 for (row
= 0; row
< srcHeight
; row
++) {
2614 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2616 for (i
= 0; i
< srcWidth
* components
; i
++) {
2617 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2619 dstRow
+= dstRowStride
;
2620 src
+= srcWidth
* components
;
2624 _mesa_free((void *) tempImage
);
2630 #if FEATURE_EXT_texture_sRGB
2632 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2634 const GLboolean littleEndian
= _mesa_little_endian();
2635 const struct gl_texture_format
*newDstFormat
;
2636 StoreTexImageFunc store
;
2639 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2641 /* reuse normal rgb texstore code */
2643 newDstFormat
= &_mesa_texformat_bgr888
;
2644 store
= _mesa_texstore_bgr888
;
2647 newDstFormat
= &_mesa_texformat_rgb888
;
2648 store
= _mesa_texstore_rgb888
;
2651 k
= store(ctx
, dims
, baseInternalFormat
,
2652 newDstFormat
, dstAddr
,
2653 dstXoffset
, dstYoffset
, dstZoffset
,
2654 dstRowStride
, dstImageOffsets
,
2655 srcWidth
, srcHeight
, srcDepth
,
2657 srcAddr
, srcPacking
);
2663 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2665 const GLboolean littleEndian
= _mesa_little_endian();
2666 const struct gl_texture_format
*newDstFormat
;
2669 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2671 /* reuse normal rgba texstore code */
2673 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2675 newDstFormat
= &_mesa_texformat_rgba8888
;
2677 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2678 newDstFormat
, dstAddr
,
2679 dstXoffset
, dstYoffset
, dstZoffset
,
2680 dstRowStride
, dstImageOffsets
,
2681 srcWidth
, srcHeight
, srcDepth
,
2683 srcAddr
, srcPacking
);
2689 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2691 const struct gl_texture_format
*newDstFormat
;
2694 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2696 newDstFormat
= &_mesa_texformat_l8
;
2698 /* _mesa_textore_a8 handles luminance8 too */
2699 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2700 newDstFormat
, dstAddr
,
2701 dstXoffset
, dstYoffset
, dstZoffset
,
2702 dstRowStride
, dstImageOffsets
,
2703 srcWidth
, srcHeight
, srcDepth
,
2705 srcAddr
, srcPacking
);
2711 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2713 const GLboolean littleEndian
= _mesa_little_endian();
2714 const struct gl_texture_format
*newDstFormat
;
2717 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2719 /* reuse normal luminance/alpha texstore code */
2721 newDstFormat
= &_mesa_texformat_al88
;
2723 newDstFormat
= &_mesa_texformat_al88_rev
;
2725 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2726 newDstFormat
, dstAddr
,
2727 dstXoffset
, dstYoffset
, dstZoffset
,
2728 dstRowStride
, dstImageOffsets
,
2729 srcWidth
, srcHeight
, srcDepth
,
2731 srcAddr
, srcPacking
);
2735 #endif /* FEATURE_EXT_texture_sRGB */
2739 * Check if an unpack PBO is active prior to fetching a texture image.
2740 * If so, do bounds checking and map the buffer into main memory.
2741 * Any errors detected will be recorded.
2742 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2745 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2746 GLsizei width
, GLsizei height
, GLsizei depth
,
2747 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2748 const struct gl_pixelstore_attrib
*unpack
,
2749 const char *funcName
)
2753 if (unpack
->BufferObj
->Name
== 0) {
2757 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2758 format
, type
, pixels
)) {
2759 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2763 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2764 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2766 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2770 return ADD_POINTERS(buf
, pixels
);
2775 * Check if an unpack PBO is active prior to fetching a compressed texture
2777 * If so, do bounds checking and map the buffer into main memory.
2778 * Any errors detected will be recorded.
2779 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2782 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2783 GLsizei imageSize
, const GLvoid
*pixels
,
2784 const struct gl_pixelstore_attrib
*packing
,
2785 const char *funcName
)
2789 if (packing
->BufferObj
->Name
== 0) {
2790 /* not using a PBO - return pointer unchanged */
2793 if ((const GLubyte
*) pixels
+ imageSize
>
2794 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2795 /* out of bounds read! */
2796 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2800 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2801 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2803 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2807 return ADD_POINTERS(buf
, pixels
);
2812 * This function must be called after either of the validate_pbo_*_teximage()
2813 * functions. It unmaps the PBO buffer if it was mapped earlier.
2816 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2817 const struct gl_pixelstore_attrib
*unpack
)
2819 if (unpack
->BufferObj
->Name
) {
2820 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2828 * Adaptor for fetching a GLchan texel from a float-valued texture.
2831 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2832 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2835 ASSERT(texImage
->FetchTexelf
);
2836 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2837 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2838 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2839 /* just one channel */
2840 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2844 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2845 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2846 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2847 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2853 * Adaptor for fetching a float texel from a GLchan-valued texture.
2856 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2857 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2860 ASSERT(texImage
->FetchTexelc
);
2861 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2862 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2863 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2864 /* just one channel */
2865 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2869 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2870 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2871 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2872 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2878 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2881 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2883 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2884 ASSERT(texImage
->TexFormat
);
2888 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2889 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2892 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2893 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2896 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2897 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2903 /* now check if we need to use a float/chan adaptor */
2904 if (!texImage
->FetchTexelc
) {
2905 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
2907 else if (!texImage
->FetchTexelf
) {
2908 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
2912 ASSERT(texImage
->FetchTexelc
);
2913 ASSERT(texImage
->FetchTexelf
);
2918 * Choose the actual storage format for a new texture image.
2919 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2920 * Also set some other texImage fields related to texture compression, etc.
2921 * \param ctx rendering context
2922 * \param texImage the gl_texture_image
2923 * \param dims texture dimensions (1, 2 or 3)
2924 * \param format the user-specified format parameter
2925 * \param type the user-specified type parameter
2926 * \param internalFormat the user-specified internal format hint
2929 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2931 GLenum format
, GLenum type
, GLint internalFormat
)
2933 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2934 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2937 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2939 ASSERT(texImage
->TexFormat
);
2941 _mesa_set_fetch_functions(texImage
, dims
);
2943 if (texImage
->TexFormat
->TexelBytes
== 0) {
2944 /* must be a compressed format */
2945 texImage
->IsCompressed
= GL_TRUE
;
2946 texImage
->CompressedSize
=
2947 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2948 texImage
->Height
, texImage
->Depth
,
2949 texImage
->TexFormat
->MesaFormat
);
2952 /* non-compressed format */
2953 texImage
->IsCompressed
= GL_FALSE
;
2954 texImage
->CompressedSize
= 0;
2961 * This is the software fallback for Driver.TexImage1D()
2962 * and Driver.CopyTexImage1D().
2963 * \sa _mesa_store_teximage2d()
2966 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2967 GLint internalFormat
,
2968 GLint width
, GLint border
,
2969 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2970 const struct gl_pixelstore_attrib
*packing
,
2971 struct gl_texture_object
*texObj
,
2972 struct gl_texture_image
*texImage
)
2974 GLint postConvWidth
= width
;
2978 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2979 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2982 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2984 /* allocate memory */
2985 if (texImage
->IsCompressed
)
2986 sizeInBytes
= texImage
->CompressedSize
;
2988 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2989 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2990 if (!texImage
->Data
) {
2991 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2995 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2996 pixels
, packing
, "glTexImage1D");
2998 /* Note: we check for a NULL image pointer here, _after_ we allocated
2999 * memory for the texture. That's what the GL spec calls for.
3004 const GLint dstRowStride
= 0;
3006 ASSERT(texImage
->TexFormat
->StoreImage
);
3007 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3008 texImage
->TexFormat
,
3010 0, 0, 0, /* dstX/Y/Zoffset */
3012 texImage
->ImageOffsets
,
3014 format
, type
, pixels
, packing
);
3016 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3020 /* GL_SGIS_generate_mipmap */
3021 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3022 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3025 _mesa_unmap_teximage_pbo(ctx
, packing
);
3030 * This is the software fallback for Driver.TexImage2D()
3031 * and Driver.CopyTexImage2D().
3033 * This function is oriented toward storing images in main memory, rather
3034 * than VRAM. Device driver's can easily plug in their own replacement.
3036 * Note: width and height may be pre-convolved dimensions, but
3037 * texImage->Width and texImage->Height will be post-convolved dimensions.
3040 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3041 GLint internalFormat
,
3042 GLint width
, GLint height
, GLint border
,
3043 GLenum format
, GLenum type
, const void *pixels
,
3044 const struct gl_pixelstore_attrib
*packing
,
3045 struct gl_texture_object
*texObj
,
3046 struct gl_texture_image
*texImage
)
3048 GLint postConvWidth
= width
, postConvHeight
= height
;
3049 GLint texelBytes
, sizeInBytes
;
3052 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
3053 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
3057 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
3059 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3061 /* allocate memory */
3062 if (texImage
->IsCompressed
)
3063 sizeInBytes
= texImage
->CompressedSize
;
3065 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
3066 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3067 if (!texImage
->Data
) {
3068 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3072 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3073 pixels
, packing
, "glTexImage2D");
3075 /* Note: we check for a NULL image pointer here, _after_ we allocated
3076 * memory for the texture. That's what the GL spec calls for.
3083 if (texImage
->IsCompressed
) {
3085 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3088 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3090 ASSERT(texImage
->TexFormat
->StoreImage
);
3091 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3092 texImage
->TexFormat
,
3094 0, 0, 0, /* dstX/Y/Zoffset */
3096 texImage
->ImageOffsets
,
3098 format
, type
, pixels
, packing
);
3100 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3104 /* GL_SGIS_generate_mipmap */
3105 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3106 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3109 _mesa_unmap_teximage_pbo(ctx
, packing
);
3115 * This is the software fallback for Driver.TexImage3D()
3116 * and Driver.CopyTexImage3D().
3117 * \sa _mesa_store_teximage2d()
3120 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3121 GLint internalFormat
,
3122 GLint width
, GLint height
, GLint depth
, GLint border
,
3123 GLenum format
, GLenum type
, const void *pixels
,
3124 const struct gl_pixelstore_attrib
*packing
,
3125 struct gl_texture_object
*texObj
,
3126 struct gl_texture_image
*texImage
)
3128 GLint texelBytes
, sizeInBytes
;
3131 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3133 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3135 /* allocate memory */
3136 if (texImage
->IsCompressed
)
3137 sizeInBytes
= texImage
->CompressedSize
;
3139 sizeInBytes
= width
* height
* depth
* texelBytes
;
3140 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3141 if (!texImage
->Data
) {
3142 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3146 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3147 type
, pixels
, packing
, "glTexImage3D");
3149 /* Note: we check for a NULL image pointer here, _after_ we allocated
3150 * memory for the texture. That's what the GL spec calls for.
3157 if (texImage
->IsCompressed
) {
3159 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3162 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3164 ASSERT(texImage
->TexFormat
->StoreImage
);
3165 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3166 texImage
->TexFormat
,
3168 0, 0, 0, /* dstX/Y/Zoffset */
3170 texImage
->ImageOffsets
,
3171 width
, height
, depth
,
3172 format
, type
, pixels
, packing
);
3174 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3178 /* GL_SGIS_generate_mipmap */
3179 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3180 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3183 _mesa_unmap_teximage_pbo(ctx
, packing
);
3190 * This is the software fallback for Driver.TexSubImage1D()
3191 * and Driver.CopyTexSubImage1D().
3194 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3195 GLint xoffset
, GLint width
,
3196 GLenum format
, GLenum type
, const void *pixels
,
3197 const struct gl_pixelstore_attrib
*packing
,
3198 struct gl_texture_object
*texObj
,
3199 struct gl_texture_image
*texImage
)
3201 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3202 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3203 pixels
, packing
, "glTexSubImage1D");
3208 const GLint dstRowStride
= 0;
3210 ASSERT(texImage
->TexFormat
->StoreImage
);
3211 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3212 texImage
->TexFormat
,
3214 xoffset
, 0, 0, /* offsets */
3216 texImage
->ImageOffsets
,
3218 format
, type
, pixels
, packing
);
3220 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3224 /* GL_SGIS_generate_mipmap */
3225 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3226 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3229 _mesa_unmap_teximage_pbo(ctx
, packing
);
3235 * This is the software fallback for Driver.TexSubImage2D()
3236 * and Driver.CopyTexSubImage2D().
3239 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3240 GLint xoffset
, GLint yoffset
,
3241 GLint width
, GLint height
,
3242 GLenum format
, GLenum type
, const void *pixels
,
3243 const struct gl_pixelstore_attrib
*packing
,
3244 struct gl_texture_object
*texObj
,
3245 struct gl_texture_image
*texImage
)
3247 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3248 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3249 pixels
, packing
, "glTexSubImage2D");
3254 GLint dstRowStride
= 0;
3256 if (texImage
->IsCompressed
) {
3257 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3261 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3263 ASSERT(texImage
->TexFormat
->StoreImage
);
3264 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3265 texImage
->TexFormat
,
3267 xoffset
, yoffset
, 0,
3269 texImage
->ImageOffsets
,
3271 format
, type
, pixels
, packing
);
3273 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3277 /* GL_SGIS_generate_mipmap */
3278 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3279 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3282 _mesa_unmap_teximage_pbo(ctx
, packing
);
3287 * This is the software fallback for Driver.TexSubImage3D().
3288 * and Driver.CopyTexSubImage3D().
3291 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3292 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3293 GLint width
, GLint height
, GLint depth
,
3294 GLenum format
, GLenum type
, const void *pixels
,
3295 const struct gl_pixelstore_attrib
*packing
,
3296 struct gl_texture_object
*texObj
,
3297 struct gl_texture_image
*texImage
)
3299 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3300 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3301 type
, pixels
, packing
,
3309 if (texImage
->IsCompressed
) {
3310 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3314 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3316 ASSERT(texImage
->TexFormat
->StoreImage
);
3317 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3318 texImage
->TexFormat
,
3320 xoffset
, yoffset
, zoffset
,
3322 texImage
->ImageOffsets
,
3323 width
, height
, depth
,
3324 format
, type
, pixels
, packing
);
3326 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3330 /* GL_SGIS_generate_mipmap */
3331 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3332 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3335 _mesa_unmap_teximage_pbo(ctx
, packing
);
3340 * Fallback for Driver.CompressedTexImage1D()
3343 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3344 GLint internalFormat
,
3345 GLint width
, GLint border
,
3346 GLsizei imageSize
, const GLvoid
*data
,
3347 struct gl_texture_object
*texObj
,
3348 struct gl_texture_image
*texImage
)
3350 /* this space intentionally left blank */
3352 (void) target
; (void) level
;
3353 (void) internalFormat
;
3354 (void) width
; (void) border
;
3355 (void) imageSize
; (void) data
;
3363 * Fallback for Driver.CompressedTexImage2D()
3366 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3367 GLint internalFormat
,
3368 GLint width
, GLint height
, GLint border
,
3369 GLsizei imageSize
, const GLvoid
*data
,
3370 struct gl_texture_object
*texObj
,
3371 struct gl_texture_image
*texImage
)
3373 (void) width
; (void) height
; (void) border
;
3375 /* This is pretty simple, basically just do a memcpy without worrying
3376 * about the usual image unpacking or image transfer operations.
3380 ASSERT(texImage
->Width
> 0);
3381 ASSERT(texImage
->Height
> 0);
3382 ASSERT(texImage
->Depth
== 1);
3383 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3385 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3387 /* allocate storage */
3388 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3389 if (!texImage
->Data
) {
3390 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3394 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3396 "glCompressedTexImage2D");
3401 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3402 MEMCPY(texImage
->Data
, data
, imageSize
);
3404 /* GL_SGIS_generate_mipmap */
3405 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3406 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3409 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3415 * Fallback for Driver.CompressedTexImage3D()
3418 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3419 GLint internalFormat
,
3420 GLint width
, GLint height
, GLint depth
,
3422 GLsizei imageSize
, const GLvoid
*data
,
3423 struct gl_texture_object
*texObj
,
3424 struct gl_texture_image
*texImage
)
3426 /* this space intentionally left blank */
3428 (void) target
; (void) level
;
3429 (void) internalFormat
;
3430 (void) width
; (void) height
; (void) depth
;
3432 (void) imageSize
; (void) data
;
3440 * Fallback for Driver.CompressedTexSubImage1D()
3443 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3445 GLint xoffset
, GLsizei width
,
3447 GLsizei imageSize
, const GLvoid
*data
,
3448 struct gl_texture_object
*texObj
,
3449 struct gl_texture_image
*texImage
)
3451 /* there are no compressed 1D texture formats yet */
3453 (void) target
; (void) level
;
3454 (void) xoffset
; (void) width
;
3456 (void) imageSize
; (void) data
;
3463 * Fallback for Driver.CompressedTexSubImage2D()
3466 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3468 GLint xoffset
, GLint yoffset
,
3469 GLsizei width
, GLsizei height
,
3471 GLsizei imageSize
, const GLvoid
*data
,
3472 struct gl_texture_object
*texObj
,
3473 struct gl_texture_image
*texImage
)
3475 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3479 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3483 /* these should have been caught sooner */
3484 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3485 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3486 ASSERT((xoffset
& 3) == 0);
3487 ASSERT((yoffset
& 3) == 0);
3489 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3490 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3492 "glCompressedTexSubImage2D");
3496 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3497 src
= (const GLubyte
*) data
;
3499 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3500 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3501 texImage
->TexFormat
->MesaFormat
,
3503 (GLubyte
*) texImage
->Data
);
3505 bytesPerRow
= srcRowStride
;
3508 for (i
= 0; i
< rows
; i
++) {
3509 MEMCPY(dest
, src
, bytesPerRow
);
3510 dest
+= destRowStride
;
3511 src
+= srcRowStride
;
3514 /* GL_SGIS_generate_mipmap */
3515 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3516 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3519 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3524 * Fallback for Driver.CompressedTexSubImage3D()
3527 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3529 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3530 GLsizei width
, GLsizei height
, GLsizei depth
,
3532 GLsizei imageSize
, const GLvoid
*data
,
3533 struct gl_texture_object
*texObj
,
3534 struct gl_texture_image
*texImage
)
3536 /* there are no compressed 3D texture formats yet */
3538 (void) target
; (void) level
;
3539 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3540 (void) width
; (void) height
; (void) depth
;
3542 (void) imageSize
; (void) data
;
3550 #if FEATURE_EXT_texture_sRGB
3553 * Test if given texture image is an sRGB format.
3556 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3558 switch (texImage
->TexFormat
->MesaFormat
) {
3559 case MESA_FORMAT_SRGB8
:
3560 case MESA_FORMAT_SRGBA8
:
3561 case MESA_FORMAT_SL8
:
3562 case MESA_FORMAT_SLA8
:
3569 #endif /* FEATURE_EXT_texture_sRGB */
3573 * This is the software fallback for Driver.GetTexImage().
3574 * All error checking will have been done before this routine is called.
3577 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3578 GLenum format
, GLenum type
, GLvoid
*pixels
,
3579 struct gl_texture_object
*texObj
,
3580 struct gl_texture_image
*texImage
)
3582 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3584 if (ctx
->Pack
.BufferObj
->Name
) {
3585 /* Packing texture image into a PBO.
3586 * Map the (potentially) VRAM-based buffer into our process space so
3587 * we can write into it with the code below.
3588 * A hardware driver might use a sophisticated blit to move the
3589 * texture data to the PBO if the PBO is in VRAM along with the texture.
3591 GLubyte
*buf
= (GLubyte
*)
3592 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3593 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3595 /* buffer is already mapped - that's an error */
3596 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3599 /* <pixels> was an offset into the PBO.
3600 * Now make it a real, client-side pointer inside the mapped region.
3602 pixels
= ADD_POINTERS(buf
, pixels
);
3610 const GLint width
= texImage
->Width
;
3611 const GLint height
= texImage
->Height
;
3612 const GLint depth
= texImage
->Depth
;
3614 for (img
= 0; img
< depth
; img
++) {
3615 for (row
= 0; row
< height
; row
++) {
3616 /* compute destination address in client memory */
3617 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3618 width
, height
, format
, type
,
3622 if (format
== GL_COLOR_INDEX
) {
3623 GLuint indexRow
[MAX_WIDTH
];
3625 /* Can't use FetchTexel here because that returns RGBA */
3626 if (texImage
->TexFormat
->IndexBits
== 8) {
3627 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3628 src
+= width
* (img
* texImage
->Height
+ row
);
3629 for (col
= 0; col
< width
; col
++) {
3630 indexRow
[col
] = src
[col
];
3633 else if (texImage
->TexFormat
->IndexBits
== 16) {
3634 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3635 src
+= width
* (img
* texImage
->Height
+ row
);
3636 for (col
= 0; col
< width
; col
++) {
3637 indexRow
[col
] = src
[col
];
3642 "Color index problem in _mesa_GetTexImage");
3644 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3645 indexRow
, &ctx
->Pack
,
3646 0 /* no image transfer */);
3648 else if (format
== GL_DEPTH_COMPONENT
) {
3649 GLfloat depthRow
[MAX_WIDTH
];
3651 for (col
= 0; col
< width
; col
++) {
3652 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3655 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3656 depthRow
, &ctx
->Pack
);
3658 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3659 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3660 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3661 src
+= width
* row
+ width
* height
* img
;
3662 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3663 if (ctx
->Pack
.SwapBytes
) {
3664 _mesa_swap4((GLuint
*) dest
, width
);
3667 else if (format
== GL_YCBCR_MESA
) {
3668 /* No pixel transfer */
3669 const GLint rowstride
= texImage
->RowStride
;
3671 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3672 width
* sizeof(GLushort
));
3673 /* check for byte swapping */
3674 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3675 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3676 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3677 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3678 if (!ctx
->Pack
.SwapBytes
)
3679 _mesa_swap2((GLushort
*) dest
, width
);
3681 else if (ctx
->Pack
.SwapBytes
) {
3682 _mesa_swap2((GLushort
*) dest
, width
);
3685 #if FEATURE_EXT_texture_sRGB
3686 else if (is_srgb_teximage(texImage
)) {
3687 /* no pixel transfer and no non-linear to linear conversion */
3688 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3689 const GLint rowstride
= comps
* texImage
->RowStride
;
3691 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3692 comps
* width
* sizeof(GLubyte
));
3694 #endif /* FEATURE_EXT_texture_sRGB */
3696 /* general case: convert row to RGBA format */
3697 GLfloat rgba
[MAX_WIDTH
][4];
3699 for (col
= 0; col
< width
; col
++) {
3700 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3701 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3702 rgba
[col
][RCOMP
] = 0.0;
3703 rgba
[col
][GCOMP
] = 0.0;
3704 rgba
[col
][BCOMP
] = 0.0;
3706 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3707 rgba
[col
][GCOMP
] = 0.0;
3708 rgba
[col
][BCOMP
] = 0.0;
3709 rgba
[col
][ACOMP
] = 1.0;
3711 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3712 rgba
[col
][GCOMP
] = 0.0;
3713 rgba
[col
][BCOMP
] = 0.0;
3715 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3716 rgba
[col
][GCOMP
] = 0.0;
3717 rgba
[col
][BCOMP
] = 0.0;
3718 rgba
[col
][ACOMP
] = 1.0;
3721 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3723 &ctx
->Pack
, 0x0 /*image xfer ops*/);
3729 if (ctx
->Pack
.BufferObj
->Name
) {
3730 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3731 ctx
->Pack
.BufferObj
);
3738 * This is the software fallback for Driver.GetCompressedTexImage().
3739 * All error checking will have been done before this routine is called.
3742 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3744 const struct gl_texture_object
*texObj
,
3745 const struct gl_texture_image
*texImage
)
3749 if (ctx
->Pack
.BufferObj
->Name
) {
3750 /* pack texture image into a PBO */
3752 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3753 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3754 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3755 "glGetCompressedTexImage(invalid PBO access)");
3758 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3760 ctx
->Pack
.BufferObj
);
3762 /* buffer is already mapped - that's an error */
3763 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3764 "glGetCompressedTexImage(PBO is mapped)");
3767 img
= ADD_POINTERS(buf
, img
);
3774 /* don't use texImage->CompressedSize since that may be padded out */
3775 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3777 texImage
->TexFormat
->MesaFormat
);
3779 /* just memcpy, no pixelstore or pixel transfer */
3780 _mesa_memcpy(img
, texImage
->Data
, size
);
3782 if (ctx
->Pack
.BufferObj
->Name
) {
3783 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3784 ctx
->Pack
.BufferObj
);