2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (c) 2008 VMware, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 * The GL texture image functions in teximage.c basically just do
33 * error checking and data structure allocation. They in turn call
34 * device driver functions which actually copy/convert/store the user's
37 * However, most device drivers will be able to use the fallback functions
38 * in this file. That is, most drivers will have the following bit of
40 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
41 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
42 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
45 * Texture image processing is actually kind of complicated. We have to do:
46 * Format/type conversions
48 * pixel transfer (scale, bais, lookup, convolution!, etc)
50 * These functions can handle most everything, including processing full
51 * images and sub-images.
56 #include "bufferobj.h"
66 #include "texcompress.h"
67 #include "texformat.h"
80 * Return GL_TRUE if the given image format is one that be converted
81 * to another format by swizzling.
84 can_swizzle(GLenum logicalBaseFormat
)
86 switch (logicalBaseFormat
) {
89 case GL_LUMINANCE_ALPHA
:
123 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
124 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
125 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
126 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
129 static const struct {
132 GLubyte from_rgba
[6];
133 } mappings
[MAX_IDX
] =
143 MAP4(ZERO
, ZERO
, ZERO
, 0),
174 MAP4(0, ZERO
, ZERO
, ONE
),
180 MAP4(ZERO
, 0, ZERO
, ONE
),
186 MAP4(ZERO
, ZERO
, 0, ONE
),
212 * Convert a GL image format enum to an IDX_* value (see above).
215 get_map_idx(GLenum value
)
218 case GL_LUMINANCE
: return IDX_LUMINANCE
;
219 case GL_ALPHA
: return IDX_ALPHA
;
220 case GL_INTENSITY
: return IDX_INTENSITY
;
221 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
222 case GL_RGB
: return IDX_RGB
;
223 case GL_RGBA
: return IDX_RGBA
;
224 case GL_RED
: return IDX_RED
;
225 case GL_GREEN
: return IDX_GREEN
;
226 case GL_BLUE
: return IDX_BLUE
;
227 case GL_BGR
: return IDX_BGR
;
228 case GL_BGRA
: return IDX_BGRA
;
229 case GL_ABGR_EXT
: return IDX_ABGR
;
231 _mesa_problem(NULL
, "Unexpected inFormat");
238 * When promoting texture formats (see below) we need to compute the
239 * mapping of dest components back to source components.
240 * This function does that.
241 * \param inFormat the incoming format of the texture
242 * \param outFormat the final texture format
243 * \return map[6] a full 6-component map
246 compute_component_mapping(GLenum inFormat
, GLenum outFormat
,
249 const int inFmt
= get_map_idx(inFormat
);
250 const int outFmt
= get_map_idx(outFormat
);
251 const GLubyte
*in2rgba
= mappings
[inFmt
].to_rgba
;
252 const GLubyte
*rgba2out
= mappings
[outFmt
].from_rgba
;
255 for (i
= 0; i
< 4; i
++)
256 map
[i
] = in2rgba
[rgba2out
[i
]];
262 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
263 inFormat, _mesa_lookup_enum_by_nr(inFormat),
264 outFormat, _mesa_lookup_enum_by_nr(outFormat),
275 #if !FEATURE_convolve
277 _mesa_adjust_image_for_convolution(GLcontext
*ctx
, GLuint dims
,
278 GLsizei
*srcWidth
, GLsizei
*srcHeight
)
286 * Make a temporary (color) texture image with GLfloat components.
287 * Apply all needed pixel unpacking and pixel transfer operations.
288 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
289 * Suppose the user specifies GL_LUMINANCE as the internal texture format
290 * but the graphics hardware doesn't support luminance textures. So, might
291 * use an RGB hardware format instead.
292 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
294 * \param ctx the rendering context
295 * \param dims image dimensions: 1, 2 or 3
296 * \param logicalBaseFormat basic texture derived from the user's
297 * internal texture format value
298 * \param textureBaseFormat the actual basic format of the texture
299 * \param srcWidth source image width
300 * \param srcHeight source image height
301 * \param srcDepth source image depth
302 * \param srcFormat source image format
303 * \param srcType source image type
304 * \param srcAddr source image address
305 * \param srcPacking source image pixel packing
306 * \return resulting image with format = textureBaseFormat and type = GLfloat.
309 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
310 GLenum logicalBaseFormat
,
311 GLenum textureBaseFormat
,
312 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
313 GLenum srcFormat
, GLenum srcType
,
314 const GLvoid
*srcAddr
,
315 const struct gl_pixelstore_attrib
*srcPacking
)
317 GLuint transferOps
= ctx
->_ImageTransferState
;
320 ASSERT(dims
>= 1 && dims
<= 3);
322 ASSERT(logicalBaseFormat
== GL_RGBA
||
323 logicalBaseFormat
== GL_RGB
||
324 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
325 logicalBaseFormat
== GL_LUMINANCE
||
326 logicalBaseFormat
== GL_ALPHA
||
327 logicalBaseFormat
== GL_INTENSITY
||
328 logicalBaseFormat
== GL_COLOR_INDEX
||
329 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
331 ASSERT(textureBaseFormat
== GL_RGBA
||
332 textureBaseFormat
== GL_RGB
||
333 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
334 textureBaseFormat
== GL_LUMINANCE
||
335 textureBaseFormat
== GL_ALPHA
||
336 textureBaseFormat
== GL_INTENSITY
||
337 textureBaseFormat
== GL_COLOR_INDEX
||
338 textureBaseFormat
== GL_DEPTH_COMPONENT
);
340 /* conventional color image */
342 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
343 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
344 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
345 /* need image convolution */
346 const GLuint preConvTransferOps
347 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
348 const GLuint postConvTransferOps
349 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
351 GLint convWidth
, convHeight
;
354 /* pre-convolution image buffer (3D) */
355 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
356 * 4 * sizeof(GLfloat
));
360 /* post-convolution image buffer (2D) */
361 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
362 * 4 * sizeof(GLfloat
));
364 _mesa_free(tempImage
);
368 /* loop over 3D image slices */
369 for (img
= 0; img
< srcDepth
; img
++) {
370 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
372 /* unpack and do transfer ops up to convolution */
373 for (row
= 0; row
< srcHeight
; row
++) {
374 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
375 srcAddr
, srcWidth
, srcHeight
,
376 srcFormat
, srcType
, img
, row
, 0);
377 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
378 srcFormat
, srcType
, src
,
384 /* size after optional convolution */
385 convWidth
= srcWidth
;
386 convHeight
= srcHeight
;
391 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
393 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
394 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
397 if (ctx
->Pixel
.Convolution2DEnabled
) {
398 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
402 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
403 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
409 /* do post-convolution transfer and pack into tempImage */
411 const GLint logComponents
412 = _mesa_components_in_format(logicalBaseFormat
);
413 const GLfloat
*src
= convImage
;
414 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
415 for (row
= 0; row
< convHeight
; row
++) {
416 _mesa_pack_rgba_span_float(ctx
, convWidth
,
417 (GLfloat (*)[4]) src
,
418 logicalBaseFormat
, GL_FLOAT
,
419 dst
, &ctx
->DefaultPacking
,
420 postConvTransferOps
);
421 src
+= convWidth
* 4;
422 dst
+= convWidth
* logComponents
;
425 } /* loop over 3D image slices */
427 _mesa_free(convImage
);
429 /* might need these below */
430 srcWidth
= convWidth
;
431 srcHeight
= convHeight
;
435 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
436 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
437 srcWidth
, srcFormat
, srcType
);
441 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
442 * components
* sizeof(GLfloat
));
447 for (img
= 0; img
< srcDepth
; img
++) {
449 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
453 for (row
= 0; row
< srcHeight
; row
++) {
454 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
455 dst
, srcFormat
, srcType
, src
,
456 srcPacking
, transferOps
);
457 dst
+= srcWidth
* components
;
463 if (logicalBaseFormat
!= textureBaseFormat
) {
465 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
466 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
471 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
472 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
473 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
475 /* The actual texture format should have at least as many components
476 * as the logical texture format.
478 ASSERT(texComponents
>= logComponents
);
480 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
481 * texComponents
* sizeof(GLfloat
));
483 _mesa_free(tempImage
);
487 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
489 n
= srcWidth
* srcHeight
* srcDepth
;
490 for (i
= 0; i
< n
; i
++) {
492 for (k
= 0; k
< texComponents
; k
++) {
495 newImage
[i
* texComponents
+ k
] = 0.0F
;
497 newImage
[i
* texComponents
+ k
] = 1.0F
;
499 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
503 _mesa_free(tempImage
);
504 tempImage
= newImage
;
512 * Make a temporary (color) texture image with GLchan components.
513 * Apply all needed pixel unpacking and pixel transfer operations.
514 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
515 * Suppose the user specifies GL_LUMINANCE as the internal texture format
516 * but the graphics hardware doesn't support luminance textures. So, might
517 * use an RGB hardware format instead.
518 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
520 * \param ctx the rendering context
521 * \param dims image dimensions: 1, 2 or 3
522 * \param logicalBaseFormat basic texture derived from the user's
523 * internal texture format value
524 * \param textureBaseFormat the actual basic format of the texture
525 * \param srcWidth source image width
526 * \param srcHeight source image height
527 * \param srcDepth source image depth
528 * \param srcFormat source image format
529 * \param srcType source image type
530 * \param srcAddr source image address
531 * \param srcPacking source image pixel packing
532 * \return resulting image with format = textureBaseFormat and type = GLchan.
535 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
536 GLenum logicalBaseFormat
,
537 GLenum textureBaseFormat
,
538 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
539 GLenum srcFormat
, GLenum srcType
,
540 const GLvoid
*srcAddr
,
541 const struct gl_pixelstore_attrib
*srcPacking
)
543 GLuint transferOps
= ctx
->_ImageTransferState
;
544 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
545 GLboolean freeSrcImage
= GL_FALSE
;
547 GLchan
*tempImage
, *dst
;
549 ASSERT(dims
>= 1 && dims
<= 3);
551 ASSERT(logicalBaseFormat
== GL_RGBA
||
552 logicalBaseFormat
== GL_RGB
||
553 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
554 logicalBaseFormat
== GL_LUMINANCE
||
555 logicalBaseFormat
== GL_ALPHA
||
556 logicalBaseFormat
== GL_INTENSITY
);
558 ASSERT(textureBaseFormat
== GL_RGBA
||
559 textureBaseFormat
== GL_RGB
||
560 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
561 textureBaseFormat
== GL_LUMINANCE
||
562 textureBaseFormat
== GL_ALPHA
||
563 textureBaseFormat
== GL_INTENSITY
);
566 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
567 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
568 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
569 /* get convolved image */
570 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
573 srcWidth
, srcHeight
, srcDepth
,
575 srcAddr
, srcPacking
);
578 /* the convolved image is our new source image */
580 srcFormat
= logicalBaseFormat
;
582 srcPacking
= &ctx
->DefaultPacking
;
583 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
585 freeSrcImage
= GL_TRUE
;
589 /* unpack and transfer the source image */
590 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
591 * components
* sizeof(GLchan
));
596 for (img
= 0; img
< srcDepth
; img
++) {
597 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
601 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
605 for (row
= 0; row
< srcHeight
; row
++) {
606 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
607 srcFormat
, srcType
, src
, srcPacking
,
609 dst
+= srcWidth
* components
;
614 /* If we made a temporary image for convolution, free it here */
616 _mesa_free((void *) srcAddr
);
619 if (logicalBaseFormat
!= textureBaseFormat
) {
620 /* one more conversion step */
621 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
622 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
627 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
628 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
629 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
631 /* The actual texture format should have at least as many components
632 * as the logical texture format.
634 ASSERT(texComponents
>= logComponents
);
636 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
637 * texComponents
* sizeof(GLchan
));
639 _mesa_free(tempImage
);
643 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
645 n
= srcWidth
* srcHeight
* srcDepth
;
646 for (i
= 0; i
< n
; i
++) {
648 for (k
= 0; k
< texComponents
; k
++) {
651 newImage
[i
* texComponents
+ k
] = 0;
653 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
655 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
659 _mesa_free(tempImage
);
660 tempImage
= newImage
;
668 * Copy GLubyte pixels from <src> to <dst> with swizzling.
669 * \param dst destination pixels
670 * \param dstComponents number of color components in destination pixels
671 * \param src source pixels
672 * \param srcComponents number of color components in source pixels
673 * \param map the swizzle mapping. map[X] says where to find the X component
674 * in the source image's pixels. For example, if the source image
675 * is GL_BGRA and X = red, map[0] yields 2.
676 * \param count number of pixels to copy/swizzle.
679 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
680 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
682 #define SWZ_CPY(dst, src, count, dstComps, srcComps) \
685 for (i = 0; i < count; i++) { \
687 if (srcComps == 4) { \
688 COPY_4UBV(tmp, src); \
691 for (j = 0; j < srcComps; j++) { \
696 for (j = 0; j < dstComps; j++) { \
697 dst[j] = tmp[map[j]]; \
708 ASSERT(srcComponents
<= 4);
709 ASSERT(dstComponents
<= 4);
711 switch (dstComponents
) {
713 switch (srcComponents
) {
715 SWZ_CPY(dst
, src
, count
, 4, 4);
718 SWZ_CPY(dst
, src
, count
, 4, 3);
721 SWZ_CPY(dst
, src
, count
, 4, 2);
724 SWZ_CPY(dst
, src
, count
, 4, 1);
731 switch (srcComponents
) {
733 SWZ_CPY(dst
, src
, count
, 3, 4);
736 SWZ_CPY(dst
, src
, count
, 3, 3);
739 SWZ_CPY(dst
, src
, count
, 3, 2);
742 SWZ_CPY(dst
, src
, count
, 3, 1);
749 switch (srcComponents
) {
751 SWZ_CPY(dst
, src
, count
, 2, 4);
754 SWZ_CPY(dst
, src
, count
, 2, 3);
757 SWZ_CPY(dst
, src
, count
, 2, 2);
760 SWZ_CPY(dst
, src
, count
, 2, 1);
767 switch (srcComponents
) {
769 SWZ_CPY(dst
, src
, count
, 1, 4);
772 SWZ_CPY(dst
, src
, count
, 1, 3);
775 SWZ_CPY(dst
, src
, count
, 1, 2);
778 SWZ_CPY(dst
, src
, count
, 1, 1);
792 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
793 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
795 /* Deal with the _REV input types:
797 static const GLubyte
*
798 type_mapping( GLenum srcType
)
801 case GL_UNSIGNED_BYTE
:
803 case GL_UNSIGNED_INT_8_8_8_8
:
804 return _mesa_little_endian() ? map_3210
: map_identity
;
805 case GL_UNSIGNED_INT_8_8_8_8_REV
:
806 return _mesa_little_endian() ? map_identity
: map_3210
;
812 /* Mapping required if input type is
814 static const GLubyte
*
815 byteswap_mapping( GLboolean swapBytes
,
822 case GL_UNSIGNED_BYTE
:
824 case GL_UNSIGNED_INT_8_8_8_8
:
825 case GL_UNSIGNED_INT_8_8_8_8_REV
:
835 * Transfer a GLubyte texture image with component swizzling.
838 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
843 GLenum baseInternalFormat
,
845 const GLubyte
*rgba2dst
,
846 GLuint dstComponents
,
849 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
851 const GLuint
*dstImageOffsets
,
853 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
854 const GLvoid
*srcAddr
,
855 const struct gl_pixelstore_attrib
*srcPacking
)
857 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
858 const GLubyte
*srctype2ubyte
, *swap
;
859 GLubyte map
[4], src2base
[6], base2rgba
[6];
861 const GLint srcRowStride
=
862 _mesa_image_row_stride(srcPacking
, srcWidth
,
863 srcFormat
, GL_UNSIGNED_BYTE
);
864 const GLint srcImageStride
865 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
867 const GLubyte
*srcImage
868 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
869 srcWidth
, srcHeight
, srcFormat
,
870 GL_UNSIGNED_BYTE
, 0, 0, 0);
874 /* Translate from src->baseInternal->GL_RGBA->dst. This will
875 * correctly deal with RGBA->RGB->RGBA conversions where the final
876 * A value must be 0xff regardless of the incoming alpha values.
878 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
879 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
880 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
881 srctype2ubyte
= type_mapping(srcType
);
884 for (i
= 0; i
< 4; i
++)
885 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
887 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
889 if (srcComponents
== dstComponents
&&
890 srcRowStride
== dstRowStride
&&
891 srcRowStride
== srcWidth
* srcComponents
&&
893 /* 1 and 2D images only */
894 GLubyte
*dstImage
= (GLubyte
*) dstAddr
895 + dstYoffset
* dstRowStride
896 + dstXoffset
* dstComponents
;
897 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
898 srcWidth
* srcHeight
);
902 for (img
= 0; img
< srcDepth
; img
++) {
903 const GLubyte
*srcRow
= srcImage
;
904 GLubyte
*dstRow
= (GLubyte
*) dstAddr
905 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
906 + dstYoffset
* dstRowStride
907 + dstXoffset
* dstComponents
;
908 for (row
= 0; row
< srcHeight
; row
++) {
909 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
910 dstRow
+= dstRowStride
;
911 srcRow
+= srcRowStride
;
913 srcImage
+= srcImageStride
;
920 * Teximage storage routine for when a simple memcpy will do.
921 * No pixel transfer operations or special texel encodings allowed.
922 * 1D, 2D and 3D images supported.
925 memcpy_texture(GLcontext
*ctx
,
927 const struct gl_texture_format
*dstFormat
,
929 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
931 const GLuint
*dstImageOffsets
,
932 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
933 GLenum srcFormat
, GLenum srcType
,
934 const GLvoid
*srcAddr
,
935 const struct gl_pixelstore_attrib
*srcPacking
)
937 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
939 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
940 srcWidth
, srcHeight
, srcFormat
, srcType
);
941 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
942 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
943 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
946 /* XXX update/re-enable for dstImageOffsets array */
947 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
948 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
949 GLubyte
*dstImage
= (GLubyte
*) dstAddr
950 + dstZoffset
* dstImageStride
951 + dstYoffset
* dstRowStride
952 + dstXoffset
* dstFormat
->TexelBytes
;
954 if (dstRowStride
== srcRowStride
&&
955 dstRowStride
== bytesPerRow
&&
956 ((dstImageStride
== srcImageStride
&&
957 dstImageStride
== bytesPerImage
) ||
960 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
965 for (img
= 0; img
< srcDepth
; img
++) {
966 const GLubyte
*srcRow
= srcImage
;
967 GLubyte
*dstRow
= dstImage
;
968 for (row
= 0; row
< srcHeight
; row
++) {
969 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
970 dstRow
+= dstRowStride
;
971 srcRow
+= srcRowStride
;
973 srcImage
+= srcImageStride
;
974 dstImage
+= dstImageStride
;
980 for (img
= 0; img
< srcDepth
; img
++) {
981 const GLubyte
*srcRow
= srcImage
;
982 GLubyte
*dstRow
= (GLubyte
*) dstAddr
983 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
984 + dstYoffset
* dstRowStride
985 + dstXoffset
* dstFormat
->TexelBytes
;
986 for (row
= 0; row
< srcHeight
; row
++) {
987 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
988 dstRow
+= dstRowStride
;
989 srcRow
+= srcRowStride
;
991 srcImage
+= srcImageStride
;
998 * Store an image in any of the formats:
999 * _mesa_texformat_rgba
1000 * _mesa_texformat_rgb
1001 * _mesa_texformat_alpha
1002 * _mesa_texformat_luminance
1003 * _mesa_texformat_luminance_alpha
1004 * _mesa_texformat_intensity
1008 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
1010 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1012 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
1013 dstFormat
== &_mesa_texformat_rgb
||
1014 dstFormat
== &_mesa_texformat_alpha
||
1015 dstFormat
== &_mesa_texformat_luminance
||
1016 dstFormat
== &_mesa_texformat_luminance_alpha
||
1017 dstFormat
== &_mesa_texformat_intensity
);
1018 ASSERT(baseInternalFormat
== GL_RGBA
||
1019 baseInternalFormat
== GL_RGB
||
1020 baseInternalFormat
== GL_ALPHA
||
1021 baseInternalFormat
== GL_LUMINANCE
||
1022 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1023 baseInternalFormat
== GL_INTENSITY
);
1024 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
1026 if (!ctx
->_ImageTransferState
&&
1027 !srcPacking
->SwapBytes
&&
1028 baseInternalFormat
== srcFormat
&&
1029 srcType
== CHAN_TYPE
) {
1030 /* simple memcpy path */
1031 memcpy_texture(ctx
, dims
,
1032 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1035 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1036 srcAddr
, srcPacking
);
1038 else if (!ctx
->_ImageTransferState
&&
1039 !srcPacking
->SwapBytes
&&
1040 dstFormat
== &_mesa_texformat_rgb
&&
1041 srcFormat
== GL_RGBA
&&
1042 srcType
== CHAN_TYPE
) {
1043 /* extract RGB from RGBA */
1044 GLint img
, row
, col
;
1045 for (img
= 0; img
< srcDepth
; img
++) {
1046 GLchan
*dstImage
= (GLchan
*)
1047 ((GLubyte
*) dstAddr
1048 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1049 + dstYoffset
* dstRowStride
1050 + dstXoffset
* dstFormat
->TexelBytes
);
1052 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1053 srcWidth
, srcFormat
, srcType
);
1054 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
1055 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1056 GLchan
*dstRow
= dstImage
;
1057 for (row
= 0; row
< srcHeight
; row
++) {
1058 for (col
= 0; col
< srcWidth
; col
++) {
1059 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
1060 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
1061 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
1063 dstRow
+= dstRowStride
/ sizeof(GLchan
);
1064 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
1068 else if (!ctx
->_ImageTransferState
&&
1069 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
1070 (srcType
== GL_UNSIGNED_BYTE
||
1071 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1072 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1073 can_swizzle(baseInternalFormat
) &&
1074 can_swizzle(srcFormat
)) {
1076 const GLubyte
*dstmap
;
1079 /* dstmap - how to swizzle from RGBA to dst format:
1081 if (dstFormat
== &_mesa_texformat_rgba
) {
1082 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1085 else if (dstFormat
== &_mesa_texformat_rgb
) {
1086 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1089 else if (dstFormat
== &_mesa_texformat_alpha
) {
1090 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1093 else if (dstFormat
== &_mesa_texformat_luminance
) {
1094 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1097 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1098 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1101 else if (dstFormat
== &_mesa_texformat_intensity
) {
1102 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1106 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1110 _mesa_swizzle_ubyte_image(ctx
, dims
,
1115 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1116 dstRowStride
, dstImageOffsets
,
1117 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1122 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1124 dstFormat
->BaseFormat
,
1125 srcWidth
, srcHeight
, srcDepth
,
1126 srcFormat
, srcType
, srcAddr
,
1128 const GLchan
*src
= tempImage
;
1133 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1134 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1135 for (img
= 0; img
< srcDepth
; img
++) {
1136 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1137 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1138 + dstYoffset
* dstRowStride
1139 + dstXoffset
* dstFormat
->TexelBytes
;
1140 for (row
= 0; row
< srcHeight
; row
++) {
1141 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1142 dstRow
+= dstRowStride
;
1143 src
+= srcWidth
* components
;
1147 _mesa_free((void *) tempImage
);
1154 * Store a 32-bit integer depth component texture image.
1157 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1159 const GLuint depthScale
= 0xffffffff;
1161 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1162 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1164 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
1165 ctx
->Pixel
.DepthBias
== 0.0f
&&
1166 !srcPacking
->SwapBytes
&&
1167 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1168 srcFormat
== GL_DEPTH_COMPONENT
&&
1169 srcType
== GL_UNSIGNED_INT
) {
1170 /* simple memcpy path */
1171 memcpy_texture(ctx
, dims
,
1172 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1175 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1176 srcAddr
, srcPacking
);
1181 for (img
= 0; img
< srcDepth
; img
++) {
1182 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1183 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1184 + dstYoffset
* dstRowStride
1185 + dstXoffset
* dstFormat
->TexelBytes
;
1186 for (row
= 0; row
< srcHeight
; row
++) {
1187 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1188 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1189 _mesa_unpack_depth_span(ctx
, srcWidth
,
1190 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1191 depthScale
, srcType
, src
, srcPacking
);
1192 dstRow
+= dstRowStride
;
1202 * Store a 16-bit integer depth component texture image.
1205 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1207 const GLuint depthScale
= 0xffff;
1209 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1210 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1212 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
1213 ctx
->Pixel
.DepthBias
== 0.0f
&&
1214 !srcPacking
->SwapBytes
&&
1215 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1216 srcFormat
== GL_DEPTH_COMPONENT
&&
1217 srcType
== GL_UNSIGNED_SHORT
) {
1218 /* simple memcpy path */
1219 memcpy_texture(ctx
, dims
,
1220 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1223 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1224 srcAddr
, srcPacking
);
1229 for (img
= 0; img
< srcDepth
; img
++) {
1230 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1231 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1232 + dstYoffset
* dstRowStride
1233 + dstXoffset
* dstFormat
->TexelBytes
;
1234 for (row
= 0; row
< srcHeight
; row
++) {
1235 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1236 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1237 GLushort
*dst16
= (GLushort
*) dstRow
;
1238 _mesa_unpack_depth_span(ctx
, srcWidth
,
1239 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1240 srcType
, src
, srcPacking
);
1241 dstRow
+= dstRowStride
;
1250 * Store an rgb565 or rgb565_rev texture image.
1253 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1255 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1256 dstFormat
== &_mesa_texformat_rgb565_rev
);
1257 ASSERT(dstFormat
->TexelBytes
== 2);
1259 if (!ctx
->_ImageTransferState
&&
1260 !srcPacking
->SwapBytes
&&
1261 dstFormat
== &_mesa_texformat_rgb565
&&
1262 baseInternalFormat
== GL_RGB
&&
1263 srcFormat
== GL_RGB
&&
1264 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1265 /* simple memcpy path */
1266 memcpy_texture(ctx
, dims
,
1267 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1270 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1271 srcAddr
, srcPacking
);
1273 else if (!ctx
->_ImageTransferState
&&
1274 !srcPacking
->SwapBytes
&&
1275 baseInternalFormat
== GL_RGB
&&
1276 srcFormat
== GL_RGB
&&
1277 srcType
== GL_UNSIGNED_BYTE
&&
1279 /* do optimized tex store */
1280 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1281 srcFormat
, srcType
);
1282 const GLubyte
*src
= (const GLubyte
*)
1283 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1284 srcFormat
, srcType
, 0, 0, 0);
1285 GLubyte
*dst
= (GLubyte
*) dstAddr
1286 + dstYoffset
* dstRowStride
1287 + dstXoffset
* dstFormat
->TexelBytes
;
1289 for (row
= 0; row
< srcHeight
; row
++) {
1290 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1291 GLushort
*dstUS
= (GLushort
*) dst
;
1292 /* check for byteswapped format */
1293 if (dstFormat
== &_mesa_texformat_rgb565
) {
1294 for (col
= 0; col
< srcWidth
; col
++) {
1295 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1300 for (col
= 0; col
< srcWidth
; col
++) {
1301 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1305 dst
+= dstRowStride
;
1306 src
+= srcRowStride
;
1311 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1313 dstFormat
->BaseFormat
,
1314 srcWidth
, srcHeight
, srcDepth
,
1315 srcFormat
, srcType
, srcAddr
,
1317 const GLchan
*src
= tempImage
;
1318 GLint img
, row
, col
;
1321 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1322 for (img
= 0; img
< srcDepth
; img
++) {
1323 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1324 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1325 + dstYoffset
* dstRowStride
1326 + dstXoffset
* dstFormat
->TexelBytes
;
1327 for (row
= 0; row
< srcHeight
; row
++) {
1328 GLushort
*dstUS
= (GLushort
*) dstRow
;
1329 /* check for byteswapped format */
1330 if (dstFormat
== &_mesa_texformat_rgb565
) {
1331 for (col
= 0; col
< srcWidth
; col
++) {
1332 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1333 CHAN_TO_UBYTE(src
[GCOMP
]),
1334 CHAN_TO_UBYTE(src
[BCOMP
]) );
1339 for (col
= 0; col
< srcWidth
; col
++) {
1340 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1341 CHAN_TO_UBYTE(src
[GCOMP
]),
1342 CHAN_TO_UBYTE(src
[BCOMP
]) );
1346 dstRow
+= dstRowStride
;
1349 _mesa_free((void *) tempImage
);
1356 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1359 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1361 const GLboolean littleEndian
= _mesa_little_endian();
1363 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1364 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1365 ASSERT(dstFormat
->TexelBytes
== 4);
1367 if (!ctx
->_ImageTransferState
&&
1368 !srcPacking
->SwapBytes
&&
1369 dstFormat
== &_mesa_texformat_rgba8888
&&
1370 baseInternalFormat
== GL_RGBA
&&
1371 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1372 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1373 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1374 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1375 /* simple memcpy path */
1376 memcpy_texture(ctx
, dims
,
1377 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1380 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1381 srcAddr
, srcPacking
);
1383 else if (!ctx
->_ImageTransferState
&&
1384 !srcPacking
->SwapBytes
&&
1385 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1386 baseInternalFormat
== GL_RGBA
&&
1387 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1388 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1389 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1390 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1391 /* simple memcpy path */
1392 memcpy_texture(ctx
, dims
,
1393 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1396 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1397 srcAddr
, srcPacking
);
1399 else if (!ctx
->_ImageTransferState
&&
1400 (srcType
== GL_UNSIGNED_BYTE
||
1401 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1402 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1403 can_swizzle(baseInternalFormat
) &&
1404 can_swizzle(srcFormat
)) {
1408 /* dstmap - how to swizzle from RGBA to dst format:
1410 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1411 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1424 _mesa_swizzle_ubyte_image(ctx
, dims
,
1429 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1430 dstRowStride
, dstImageOffsets
,
1431 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1436 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1438 dstFormat
->BaseFormat
,
1439 srcWidth
, srcHeight
, srcDepth
,
1440 srcFormat
, srcType
, srcAddr
,
1442 const GLchan
*src
= tempImage
;
1443 GLint img
, row
, col
;
1446 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1447 for (img
= 0; img
< srcDepth
; img
++) {
1448 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1449 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1450 + dstYoffset
* dstRowStride
1451 + dstXoffset
* dstFormat
->TexelBytes
;
1452 for (row
= 0; row
< srcHeight
; row
++) {
1453 GLuint
*dstUI
= (GLuint
*) dstRow
;
1454 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1455 for (col
= 0; col
< srcWidth
; col
++) {
1456 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1457 CHAN_TO_UBYTE(src
[GCOMP
]),
1458 CHAN_TO_UBYTE(src
[BCOMP
]),
1459 CHAN_TO_UBYTE(src
[ACOMP
]) );
1464 for (col
= 0; col
< srcWidth
; col
++) {
1465 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1466 CHAN_TO_UBYTE(src
[GCOMP
]),
1467 CHAN_TO_UBYTE(src
[BCOMP
]),
1468 CHAN_TO_UBYTE(src
[ACOMP
]) );
1472 dstRow
+= dstRowStride
;
1475 _mesa_free((void *) tempImage
);
1482 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1484 const GLboolean littleEndian
= _mesa_little_endian();
1486 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1487 dstFormat
== &_mesa_texformat_argb8888_rev
);
1488 ASSERT(dstFormat
->TexelBytes
== 4);
1490 if (!ctx
->_ImageTransferState
&&
1491 !srcPacking
->SwapBytes
&&
1492 dstFormat
== &_mesa_texformat_argb8888
&&
1493 baseInternalFormat
== GL_RGBA
&&
1494 srcFormat
== GL_BGRA
&&
1495 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1496 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1497 /* simple memcpy path (little endian) */
1498 memcpy_texture(ctx
, dims
,
1499 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1502 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1503 srcAddr
, srcPacking
);
1505 else if (!ctx
->_ImageTransferState
&&
1506 !srcPacking
->SwapBytes
&&
1507 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1508 baseInternalFormat
== GL_RGBA
&&
1509 srcFormat
== GL_BGRA
&&
1510 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1511 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1512 /* simple memcpy path (big endian) */
1513 memcpy_texture(ctx
, dims
,
1514 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1517 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1518 srcAddr
, srcPacking
);
1520 else if (!ctx
->_ImageTransferState
&&
1521 !srcPacking
->SwapBytes
&&
1522 dstFormat
== &_mesa_texformat_argb8888
&&
1523 srcFormat
== GL_RGB
&&
1524 (baseInternalFormat
== GL_RGBA
||
1525 baseInternalFormat
== GL_RGB
) &&
1526 srcType
== GL_UNSIGNED_BYTE
) {
1528 for (img
= 0; img
< srcDepth
; img
++) {
1529 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1530 srcWidth
, srcFormat
, srcType
);
1531 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1532 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1533 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1534 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1535 + dstYoffset
* dstRowStride
1536 + dstXoffset
* dstFormat
->TexelBytes
;
1537 for (row
= 0; row
< srcHeight
; row
++) {
1538 GLuint
*d4
= (GLuint
*) dstRow
;
1539 for (col
= 0; col
< srcWidth
; col
++) {
1540 d4
[col
] = PACK_COLOR_8888(0xff,
1541 srcRow
[col
* 3 + RCOMP
],
1542 srcRow
[col
* 3 + GCOMP
],
1543 srcRow
[col
* 3 + BCOMP
]);
1545 dstRow
+= dstRowStride
;
1546 srcRow
+= srcRowStride
;
1550 else if (!ctx
->_ImageTransferState
&&
1551 !srcPacking
->SwapBytes
&&
1552 dstFormat
== &_mesa_texformat_argb8888
&&
1553 srcFormat
== GL_RGBA
&&
1554 baseInternalFormat
== GL_RGBA
&&
1555 srcType
== GL_UNSIGNED_BYTE
) {
1556 /* same as above case, but src data has alpha too */
1557 GLint img
, row
, col
;
1558 /* For some reason, streaming copies to write-combined regions
1559 * are extremely sensitive to the characteristics of how the
1560 * source data is retrieved. By reordering the source reads to
1561 * be in-order, the speed of this operation increases by half.
1562 * Strangely the same isn't required for the RGB path, above.
1564 for (img
= 0; img
< srcDepth
; img
++) {
1565 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1566 srcWidth
, srcFormat
, srcType
);
1567 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1568 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1569 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1570 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1571 + dstYoffset
* dstRowStride
1572 + dstXoffset
* dstFormat
->TexelBytes
;
1573 for (row
= 0; row
< srcHeight
; row
++) {
1574 GLuint
*d4
= (GLuint
*) dstRow
;
1575 for (col
= 0; col
< srcWidth
; col
++) {
1576 d4
[col
] = PACK_COLOR_8888(srcRow
[col
* 4 + ACOMP
],
1577 srcRow
[col
* 4 + RCOMP
],
1578 srcRow
[col
* 4 + GCOMP
],
1579 srcRow
[col
* 4 + BCOMP
]);
1581 dstRow
+= dstRowStride
;
1582 srcRow
+= srcRowStride
;
1586 else if (!ctx
->_ImageTransferState
&&
1587 (srcType
== GL_UNSIGNED_BYTE
||
1588 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1589 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1590 can_swizzle(baseInternalFormat
) &&
1591 can_swizzle(srcFormat
)) {
1595 /* dstmap - how to swizzle from RGBA to dst format:
1597 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1598 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1599 dstmap
[3] = 3; /* alpha */
1600 dstmap
[2] = 0; /* red */
1601 dstmap
[1] = 1; /* green */
1602 dstmap
[0] = 2; /* blue */
1605 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1606 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1613 _mesa_swizzle_ubyte_image(ctx
, dims
,
1619 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1622 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1627 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1629 dstFormat
->BaseFormat
,
1630 srcWidth
, srcHeight
, srcDepth
,
1631 srcFormat
, srcType
, srcAddr
,
1633 const GLchan
*src
= tempImage
;
1634 GLint img
, row
, col
;
1637 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1638 for (img
= 0; img
< srcDepth
; img
++) {
1639 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1640 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1641 + dstYoffset
* dstRowStride
1642 + dstXoffset
* dstFormat
->TexelBytes
;
1643 for (row
= 0; row
< srcHeight
; row
++) {
1644 GLuint
*dstUI
= (GLuint
*) dstRow
;
1645 if (dstFormat
== &_mesa_texformat_argb8888
) {
1646 for (col
= 0; col
< srcWidth
; col
++) {
1647 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1648 CHAN_TO_UBYTE(src
[RCOMP
]),
1649 CHAN_TO_UBYTE(src
[GCOMP
]),
1650 CHAN_TO_UBYTE(src
[BCOMP
]) );
1655 for (col
= 0; col
< srcWidth
; col
++) {
1656 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1657 CHAN_TO_UBYTE(src
[RCOMP
]),
1658 CHAN_TO_UBYTE(src
[GCOMP
]),
1659 CHAN_TO_UBYTE(src
[BCOMP
]) );
1663 dstRow
+= dstRowStride
;
1666 _mesa_free((void *) tempImage
);
1673 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1675 const GLboolean littleEndian
= _mesa_little_endian();
1677 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1678 ASSERT(dstFormat
->TexelBytes
== 3);
1680 if (!ctx
->_ImageTransferState
&&
1681 !srcPacking
->SwapBytes
&&
1682 baseInternalFormat
== GL_RGB
&&
1683 srcFormat
== GL_BGR
&&
1684 srcType
== GL_UNSIGNED_BYTE
&&
1686 /* simple memcpy path */
1687 memcpy_texture(ctx
, dims
,
1688 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1691 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1692 srcAddr
, srcPacking
);
1694 else if (!ctx
->_ImageTransferState
&&
1695 !srcPacking
->SwapBytes
&&
1696 srcFormat
== GL_RGBA
&&
1697 srcType
== GL_UNSIGNED_BYTE
) {
1698 /* extract RGB from RGBA */
1699 GLint img
, row
, col
;
1700 for (img
= 0; img
< srcDepth
; img
++) {
1701 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1702 srcWidth
, srcFormat
, srcType
);
1703 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1704 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1705 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1706 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1707 + dstYoffset
* dstRowStride
1708 + dstXoffset
* dstFormat
->TexelBytes
;
1709 for (row
= 0; row
< srcHeight
; row
++) {
1710 for (col
= 0; col
< srcWidth
; col
++) {
1711 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1712 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1713 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1715 dstRow
+= dstRowStride
;
1716 srcRow
+= srcRowStride
;
1720 else if (!ctx
->_ImageTransferState
&&
1721 srcType
== GL_UNSIGNED_BYTE
&&
1722 can_swizzle(baseInternalFormat
) &&
1723 can_swizzle(srcFormat
)) {
1727 /* dstmap - how to swizzle from RGBA to dst format:
1732 dstmap
[3] = ONE
; /* ? */
1734 _mesa_swizzle_ubyte_image(ctx
, dims
,
1739 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1740 dstRowStride
, dstImageOffsets
,
1741 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1746 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1748 dstFormat
->BaseFormat
,
1749 srcWidth
, srcHeight
, srcDepth
,
1750 srcFormat
, srcType
, srcAddr
,
1752 const GLchan
*src
= (const GLchan
*) tempImage
;
1753 GLint img
, row
, col
;
1756 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1757 for (img
= 0; img
< srcDepth
; img
++) {
1758 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1759 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1760 + dstYoffset
* dstRowStride
1761 + dstXoffset
* dstFormat
->TexelBytes
;
1762 for (row
= 0; row
< srcHeight
; row
++) {
1765 for (col
= 0; col
< srcWidth
; col
++) {
1766 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1767 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1768 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1773 for (col
= 0; col
< srcWidth
; col
++) {
1774 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1775 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1776 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1781 for (col
= 0; col
< srcWidth
; col
++) {
1782 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1783 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1784 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1788 dstRow
+= dstRowStride
;
1791 _mesa_free((void *) tempImage
);
1798 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1800 const GLboolean littleEndian
= _mesa_little_endian();
1802 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1803 ASSERT(dstFormat
->TexelBytes
== 3);
1805 if (!ctx
->_ImageTransferState
&&
1806 !srcPacking
->SwapBytes
&&
1807 baseInternalFormat
== GL_RGB
&&
1808 srcFormat
== GL_RGB
&&
1809 srcType
== GL_UNSIGNED_BYTE
&&
1811 /* simple memcpy path */
1812 memcpy_texture(ctx
, dims
,
1813 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1816 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1817 srcAddr
, srcPacking
);
1819 else if (!ctx
->_ImageTransferState
&&
1820 !srcPacking
->SwapBytes
&&
1821 srcFormat
== GL_RGBA
&&
1822 srcType
== GL_UNSIGNED_BYTE
) {
1823 /* extract BGR from RGBA */
1825 for (img
= 0; img
< srcDepth
; img
++) {
1826 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1827 srcWidth
, srcFormat
, srcType
);
1828 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1829 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1830 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1831 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1832 + dstYoffset
* dstRowStride
1833 + dstXoffset
* dstFormat
->TexelBytes
;
1834 for (row
= 0; row
< srcHeight
; row
++) {
1835 for (col
= 0; col
< srcWidth
; col
++) {
1836 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1837 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1838 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1840 dstRow
+= dstRowStride
;
1841 srcRow
+= srcRowStride
;
1845 else if (!ctx
->_ImageTransferState
&&
1846 srcType
== GL_UNSIGNED_BYTE
&&
1847 can_swizzle(baseInternalFormat
) &&
1848 can_swizzle(srcFormat
)) {
1852 /* dstmap - how to swizzle from RGBA to dst format:
1857 dstmap
[3] = ONE
; /* ? */
1859 _mesa_swizzle_ubyte_image(ctx
, dims
,
1864 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1865 dstRowStride
, dstImageOffsets
,
1866 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1871 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1873 dstFormat
->BaseFormat
,
1874 srcWidth
, srcHeight
, srcDepth
,
1875 srcFormat
, srcType
, srcAddr
,
1877 const GLchan
*src
= (const GLchan
*) tempImage
;
1878 GLint img
, row
, col
;
1881 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1882 for (img
= 0; img
< srcDepth
; img
++) {
1883 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1884 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1885 + dstYoffset
* dstRowStride
1886 + dstXoffset
* dstFormat
->TexelBytes
;
1887 for (row
= 0; row
< srcHeight
; row
++) {
1888 for (col
= 0; col
< srcWidth
; col
++) {
1889 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1890 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1891 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1894 dstRow
+= dstRowStride
;
1897 _mesa_free((void *) tempImage
);
1903 _mesa_texstore_rgba4444(TEXSTORE_PARAMS
)
1905 ASSERT(dstFormat
== &_mesa_texformat_rgba4444
);
1906 ASSERT(dstFormat
->TexelBytes
== 2);
1908 if (!ctx
->_ImageTransferState
&&
1909 !srcPacking
->SwapBytes
&&
1910 dstFormat
== &_mesa_texformat_rgba4444
&&
1911 baseInternalFormat
== GL_RGBA
&&
1912 srcFormat
== GL_RGBA
&&
1913 srcType
== GL_UNSIGNED_SHORT_4_4_4_4
){
1914 /* simple memcpy path */
1915 memcpy_texture(ctx
, dims
,
1916 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1919 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1920 srcAddr
, srcPacking
);
1924 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1926 dstFormat
->BaseFormat
,
1927 srcWidth
, srcHeight
, srcDepth
,
1928 srcFormat
, srcType
, srcAddr
,
1930 const GLchan
*src
= tempImage
;
1931 GLint img
, row
, col
;
1934 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1935 for (img
= 0; img
< srcDepth
; img
++) {
1936 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1937 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1938 + dstYoffset
* dstRowStride
1939 + dstXoffset
* dstFormat
->TexelBytes
;
1940 for (row
= 0; row
< srcHeight
; row
++) {
1941 GLushort
*dstUS
= (GLushort
*) dstRow
;
1942 for (col
= 0; col
< srcWidth
; col
++) {
1943 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[RCOMP
]),
1944 CHAN_TO_UBYTE(src
[GCOMP
]),
1945 CHAN_TO_UBYTE(src
[BCOMP
]),
1946 CHAN_TO_UBYTE(src
[ACOMP
]) );
1949 dstRow
+= dstRowStride
;
1952 _mesa_free((void *) tempImage
);
1958 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1960 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1961 dstFormat
== &_mesa_texformat_argb4444_rev
);
1962 ASSERT(dstFormat
->TexelBytes
== 2);
1964 if (!ctx
->_ImageTransferState
&&
1965 !srcPacking
->SwapBytes
&&
1966 dstFormat
== &_mesa_texformat_argb4444
&&
1967 baseInternalFormat
== GL_RGBA
&&
1968 srcFormat
== GL_BGRA
&&
1969 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1970 /* simple memcpy path */
1971 memcpy_texture(ctx
, dims
,
1972 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1975 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1976 srcAddr
, srcPacking
);
1980 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1982 dstFormat
->BaseFormat
,
1983 srcWidth
, srcHeight
, srcDepth
,
1984 srcFormat
, srcType
, srcAddr
,
1986 const GLchan
*src
= tempImage
;
1987 GLint img
, row
, col
;
1990 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1991 for (img
= 0; img
< srcDepth
; img
++) {
1992 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1993 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1994 + dstYoffset
* dstRowStride
1995 + dstXoffset
* dstFormat
->TexelBytes
;
1996 for (row
= 0; row
< srcHeight
; row
++) {
1997 GLushort
*dstUS
= (GLushort
*) dstRow
;
1998 if (dstFormat
== &_mesa_texformat_argb4444
) {
1999 for (col
= 0; col
< srcWidth
; col
++) {
2000 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
2001 CHAN_TO_UBYTE(src
[RCOMP
]),
2002 CHAN_TO_UBYTE(src
[GCOMP
]),
2003 CHAN_TO_UBYTE(src
[BCOMP
]) );
2008 for (col
= 0; col
< srcWidth
; col
++) {
2009 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
2010 CHAN_TO_UBYTE(src
[RCOMP
]),
2011 CHAN_TO_UBYTE(src
[GCOMP
]),
2012 CHAN_TO_UBYTE(src
[BCOMP
]) );
2016 dstRow
+= dstRowStride
;
2019 _mesa_free((void *) tempImage
);
2025 _mesa_texstore_rgba5551(TEXSTORE_PARAMS
)
2027 ASSERT(dstFormat
== &_mesa_texformat_rgba5551
);
2028 ASSERT(dstFormat
->TexelBytes
== 2);
2030 if (!ctx
->_ImageTransferState
&&
2031 !srcPacking
->SwapBytes
&&
2032 dstFormat
== &_mesa_texformat_rgba5551
&&
2033 baseInternalFormat
== GL_RGBA
&&
2034 srcFormat
== GL_RGBA
&&
2035 srcType
== GL_UNSIGNED_SHORT_5_5_5_1
) {
2036 /* simple memcpy path */
2037 memcpy_texture(ctx
, dims
,
2038 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2041 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2042 srcAddr
, srcPacking
);
2046 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2048 dstFormat
->BaseFormat
,
2049 srcWidth
, srcHeight
, srcDepth
,
2050 srcFormat
, srcType
, srcAddr
,
2052 const GLchan
*src
=tempImage
;
2053 GLint img
, row
, col
;
2056 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2057 for (img
= 0; img
< srcDepth
; img
++) {
2058 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2059 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2060 + dstYoffset
* dstRowStride
2061 + dstXoffset
* dstFormat
->TexelBytes
;
2062 for (row
= 0; row
< srcHeight
; row
++) {
2063 GLushort
*dstUS
= (GLushort
*) dstRow
;
2064 for (col
= 0; col
< srcWidth
; col
++) {
2065 dstUS
[col
] = PACK_COLOR_5551( CHAN_TO_UBYTE(src
[RCOMP
]),
2066 CHAN_TO_UBYTE(src
[GCOMP
]),
2067 CHAN_TO_UBYTE(src
[BCOMP
]),
2068 CHAN_TO_UBYTE(src
[ACOMP
]) );
2071 dstRow
+= dstRowStride
;
2074 _mesa_free((void *) tempImage
);
2080 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
2082 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
2083 dstFormat
== &_mesa_texformat_argb1555_rev
);
2084 ASSERT(dstFormat
->TexelBytes
== 2);
2086 if (!ctx
->_ImageTransferState
&&
2087 !srcPacking
->SwapBytes
&&
2088 dstFormat
== &_mesa_texformat_argb1555
&&
2089 baseInternalFormat
== GL_RGBA
&&
2090 srcFormat
== GL_BGRA
&&
2091 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
2092 /* simple memcpy path */
2093 memcpy_texture(ctx
, dims
,
2094 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2097 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2098 srcAddr
, srcPacking
);
2102 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2104 dstFormat
->BaseFormat
,
2105 srcWidth
, srcHeight
, srcDepth
,
2106 srcFormat
, srcType
, srcAddr
,
2108 const GLchan
*src
=tempImage
;
2109 GLint img
, row
, col
;
2112 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2113 for (img
= 0; img
< srcDepth
; img
++) {
2114 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2115 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2116 + dstYoffset
* dstRowStride
2117 + dstXoffset
* dstFormat
->TexelBytes
;
2118 for (row
= 0; row
< srcHeight
; row
++) {
2119 GLushort
*dstUS
= (GLushort
*) dstRow
;
2120 if (dstFormat
== &_mesa_texformat_argb1555
) {
2121 for (col
= 0; col
< srcWidth
; col
++) {
2122 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
2123 CHAN_TO_UBYTE(src
[RCOMP
]),
2124 CHAN_TO_UBYTE(src
[GCOMP
]),
2125 CHAN_TO_UBYTE(src
[BCOMP
]) );
2130 for (col
= 0; col
< srcWidth
; col
++) {
2131 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
2132 CHAN_TO_UBYTE(src
[RCOMP
]),
2133 CHAN_TO_UBYTE(src
[GCOMP
]),
2134 CHAN_TO_UBYTE(src
[BCOMP
]) );
2138 dstRow
+= dstRowStride
;
2141 _mesa_free((void *) tempImage
);
2148 _mesa_texstore_al88(TEXSTORE_PARAMS
)
2150 const GLboolean littleEndian
= _mesa_little_endian();
2152 ASSERT(dstFormat
== &_mesa_texformat_al88
||
2153 dstFormat
== &_mesa_texformat_al88_rev
);
2154 ASSERT(dstFormat
->TexelBytes
== 2);
2156 if (!ctx
->_ImageTransferState
&&
2157 !srcPacking
->SwapBytes
&&
2158 dstFormat
== &_mesa_texformat_al88
&&
2159 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2160 srcFormat
== GL_LUMINANCE_ALPHA
&&
2161 srcType
== GL_UNSIGNED_BYTE
&&
2163 /* simple memcpy path */
2164 memcpy_texture(ctx
, dims
,
2165 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2168 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2169 srcAddr
, srcPacking
);
2171 else if (!ctx
->_ImageTransferState
&&
2173 srcType
== GL_UNSIGNED_BYTE
&&
2174 can_swizzle(baseInternalFormat
) &&
2175 can_swizzle(srcFormat
)) {
2179 /* dstmap - how to swizzle from RGBA to dst format:
2181 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2182 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2190 dstmap
[2] = ZERO
; /* ? */
2191 dstmap
[3] = ONE
; /* ? */
2193 _mesa_swizzle_ubyte_image(ctx
, dims
,
2198 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2199 dstRowStride
, dstImageOffsets
,
2200 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2205 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2207 dstFormat
->BaseFormat
,
2208 srcWidth
, srcHeight
, srcDepth
,
2209 srcFormat
, srcType
, srcAddr
,
2211 const GLchan
*src
= tempImage
;
2212 GLint img
, row
, col
;
2215 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2216 for (img
= 0; img
< srcDepth
; img
++) {
2217 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2218 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2219 + dstYoffset
* dstRowStride
2220 + dstXoffset
* dstFormat
->TexelBytes
;
2221 for (row
= 0; row
< srcHeight
; row
++) {
2222 GLushort
*dstUS
= (GLushort
*) dstRow
;
2223 if (dstFormat
== &_mesa_texformat_al88
) {
2224 for (col
= 0; col
< srcWidth
; col
++) {
2225 /* src[0] is luminance, src[1] is alpha */
2226 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2227 CHAN_TO_UBYTE(src
[0]) );
2232 for (col
= 0; col
< srcWidth
; col
++) {
2233 /* src[0] is luminance, src[1] is alpha */
2234 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2235 CHAN_TO_UBYTE(src
[0]) );
2239 dstRow
+= dstRowStride
;
2242 _mesa_free((void *) tempImage
);
2249 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2251 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2252 ASSERT(dstFormat
->TexelBytes
== 1);
2254 if (!ctx
->_ImageTransferState
&&
2255 !srcPacking
->SwapBytes
&&
2256 baseInternalFormat
== GL_RGB
&&
2257 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2258 /* simple memcpy path */
2259 memcpy_texture(ctx
, dims
,
2260 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2263 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2264 srcAddr
, srcPacking
);
2268 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2270 dstFormat
->BaseFormat
,
2271 srcWidth
, srcHeight
, srcDepth
,
2272 srcFormat
, srcType
, srcAddr
,
2274 const GLchan
*src
= tempImage
;
2275 GLint img
, row
, col
;
2278 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2279 for (img
= 0; img
< srcDepth
; img
++) {
2280 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2281 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2282 + dstYoffset
* dstRowStride
2283 + dstXoffset
* dstFormat
->TexelBytes
;
2284 for (row
= 0; row
< srcHeight
; row
++) {
2285 for (col
= 0; col
< srcWidth
; col
++) {
2286 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2287 CHAN_TO_UBYTE(src
[GCOMP
]),
2288 CHAN_TO_UBYTE(src
[BCOMP
]) );
2291 dstRow
+= dstRowStride
;
2294 _mesa_free((void *) tempImage
);
2301 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2304 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2306 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2307 dstFormat
== &_mesa_texformat_l8
||
2308 dstFormat
== &_mesa_texformat_i8
);
2309 ASSERT(dstFormat
->TexelBytes
== 1);
2311 if (!ctx
->_ImageTransferState
&&
2312 !srcPacking
->SwapBytes
&&
2313 baseInternalFormat
== srcFormat
&&
2314 srcType
== GL_UNSIGNED_BYTE
) {
2315 /* simple memcpy path */
2316 memcpy_texture(ctx
, dims
,
2317 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2320 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2321 srcAddr
, srcPacking
);
2323 else if (!ctx
->_ImageTransferState
&&
2324 srcType
== GL_UNSIGNED_BYTE
&&
2325 can_swizzle(baseInternalFormat
) &&
2326 can_swizzle(srcFormat
)) {
2330 /* dstmap - how to swizzle from RGBA to dst format:
2332 if (dstFormat
== &_mesa_texformat_a8
) {
2338 dstmap
[1] = ZERO
; /* ? */
2339 dstmap
[2] = ZERO
; /* ? */
2340 dstmap
[3] = ONE
; /* ? */
2342 _mesa_swizzle_ubyte_image(ctx
, dims
,
2347 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2348 dstRowStride
, dstImageOffsets
,
2349 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2354 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2356 dstFormat
->BaseFormat
,
2357 srcWidth
, srcHeight
, srcDepth
,
2358 srcFormat
, srcType
, srcAddr
,
2360 const GLchan
*src
= tempImage
;
2361 GLint img
, row
, col
;
2364 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2365 for (img
= 0; img
< srcDepth
; img
++) {
2366 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2367 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2368 + dstYoffset
* dstRowStride
2369 + dstXoffset
* dstFormat
->TexelBytes
;
2370 for (row
= 0; row
< srcHeight
; row
++) {
2371 for (col
= 0; col
< srcWidth
; col
++) {
2372 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2374 dstRow
+= dstRowStride
;
2378 _mesa_free((void *) tempImage
);
2386 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2388 (void) dims
; (void) baseInternalFormat
;
2389 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2390 ASSERT(dstFormat
->TexelBytes
== 1);
2391 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2393 if (!ctx
->_ImageTransferState
&&
2394 !srcPacking
->SwapBytes
&&
2395 srcFormat
== GL_COLOR_INDEX
&&
2396 srcType
== GL_UNSIGNED_BYTE
) {
2397 /* simple memcpy path */
2398 memcpy_texture(ctx
, dims
,
2399 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2402 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2403 srcAddr
, srcPacking
);
2408 for (img
= 0; img
< srcDepth
; img
++) {
2409 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2410 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2411 + dstYoffset
* dstRowStride
2412 + dstXoffset
* dstFormat
->TexelBytes
;
2413 for (row
= 0; row
< srcHeight
; row
++) {
2414 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2415 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2416 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2417 srcType
, src
, srcPacking
,
2418 ctx
->_ImageTransferState
);
2419 dstRow
+= dstRowStride
;
2428 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2431 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2433 const GLboolean littleEndian
= _mesa_little_endian();
2434 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2436 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2437 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2438 ASSERT(dstFormat
->TexelBytes
== 2);
2439 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2440 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2441 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2442 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2443 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2445 /* always just memcpy since no pixel transfer ops apply */
2446 memcpy_texture(ctx
, dims
,
2447 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2450 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2451 srcAddr
, srcPacking
);
2453 /* Check if we need byte swapping */
2454 /* XXX the logic here _might_ be wrong */
2455 if (srcPacking
->SwapBytes
^
2456 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2457 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2460 for (img
= 0; img
< srcDepth
; img
++) {
2461 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2462 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2463 + dstYoffset
* dstRowStride
2464 + dstXoffset
* dstFormat
->TexelBytes
;
2465 for (row
= 0; row
< srcHeight
; row
++) {
2466 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2467 dstRow
+= dstRowStride
;
2475 _mesa_texstore_dudv8(TEXSTORE_PARAMS
)
2477 const GLboolean littleEndian
= _mesa_little_endian();
2479 ASSERT(dstFormat
== &_mesa_texformat_dudv8
);
2480 ASSERT(dstFormat
->TexelBytes
== 2);
2481 ASSERT(ctx
->Extensions
.ATI_envmap_bumpmap
);
2482 ASSERT((srcFormat
== GL_DU8DV8_ATI
) ||
2483 (srcFormat
== GL_DUDV_ATI
));
2484 ASSERT(baseInternalFormat
== GL_DUDV_ATI
);
2486 if (!srcPacking
->SwapBytes
&& srcType
== GL_BYTE
&&
2488 /* simple memcpy path */
2489 memcpy_texture(ctx
, dims
,
2490 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2493 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2494 srcAddr
, srcPacking
);
2496 else if (srcType
== GL_BYTE
) {
2500 /* dstmap - how to swizzle from RGBA to dst format:
2510 dstmap
[2] = ZERO
; /* ? */
2511 dstmap
[3] = ONE
; /* ? */
2513 _mesa_swizzle_ubyte_image(ctx
, dims
,
2514 GL_LUMINANCE_ALPHA
, /* hack */
2515 GL_UNSIGNED_BYTE
, /* hack */
2516 GL_LUMINANCE_ALPHA
, /* hack */
2518 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2519 dstRowStride
, dstImageOffsets
,
2520 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2524 /* general path - note this is defined for 2d textures only */
2525 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
2526 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
2527 srcWidth
, srcFormat
, srcType
);
2528 GLbyte
*tempImage
, *dst
, *src
;
2531 tempImage
= (GLbyte
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
2532 * components
* sizeof(GLbyte
));
2536 src
= (GLbyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2537 srcWidth
, srcHeight
,
2542 for (row
= 0; row
< srcHeight
; row
++) {
2543 _mesa_unpack_dudv_span_byte(ctx
, srcWidth
, baseInternalFormat
,
2544 dst
, srcFormat
, srcType
, src
,
2546 dst
+= srcWidth
* components
;
2551 dst
= (GLbyte
*) dstAddr
2552 + dstYoffset
* dstRowStride
2553 + dstXoffset
* dstFormat
->TexelBytes
;
2554 for (row
= 0; row
< srcHeight
; row
++) {
2555 memcpy(dst
, src
, srcWidth
* dstFormat
->TexelBytes
);
2556 dst
+= dstRowStride
;
2557 src
+= srcWidth
* dstFormat
->TexelBytes
;
2559 _mesa_free((void *) tempImage
);
2566 * Store a combined depth/stencil texture image.
2569 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2571 const GLfloat depthScale
= (GLfloat
) 0xffffff;
2573 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2574 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2575 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2577 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
2578 ctx
->Pixel
.DepthBias
== 0.0f
&&
2579 !srcPacking
->SwapBytes
) {
2581 memcpy_texture(ctx
, dims
,
2582 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2585 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2586 srcAddr
, srcPacking
);
2590 const GLint srcRowStride
2591 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2595 for (img
= 0; img
< srcDepth
; img
++) {
2596 GLuint
*dstRow
= (GLuint
*) dstAddr
2597 + dstImageOffsets
[dstZoffset
+ img
]
2598 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2601 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2602 srcWidth
, srcHeight
,
2605 for (row
= 0; row
< srcHeight
; row
++) {
2606 GLubyte stencil
[MAX_WIDTH
];
2608 /* the 24 depth bits will be in the high position: */
2609 _mesa_unpack_depth_span(ctx
, srcWidth
,
2610 GL_UNSIGNED_INT_24_8_EXT
, /* dst type */
2611 dstRow
, /* dst addr */
2612 (GLuint
) depthScale
,
2613 srcType
, src
, srcPacking
);
2614 /* get the 8-bit stencil values */
2615 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2616 GL_UNSIGNED_BYTE
, /* dst type */
2617 stencil
, /* dst addr */
2618 srcType
, src
, srcPacking
,
2619 ctx
->_ImageTransferState
);
2620 /* merge stencil values into depth values */
2621 for (i
= 0; i
< srcWidth
; i
++)
2622 dstRow
[i
] |= stencil
[i
];
2624 src
+= srcRowStride
;
2625 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2634 * Store a combined depth/stencil texture image.
2637 _mesa_texstore_s8_z24(TEXSTORE_PARAMS
)
2639 const GLuint depthScale
= 0xffffff;
2640 const GLint srcRowStride
2641 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2645 ASSERT(dstFormat
== &_mesa_texformat_s8_z24
);
2646 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
|| srcFormat
== GL_DEPTH_COMPONENT
);
2647 ASSERT(srcFormat
!= GL_DEPTH_STENCIL_EXT
|| srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2649 /* In case we only upload depth we need to preserve the stencil */
2650 if (srcFormat
== GL_DEPTH_COMPONENT
) {
2651 for (img
= 0; img
< srcDepth
; img
++) {
2652 GLuint
*dstRow
= (GLuint
*) dstAddr
2653 + dstImageOffsets
[dstZoffset
+ img
]
2654 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2657 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2658 srcWidth
, srcHeight
,
2661 for (row
= 0; row
< srcHeight
; row
++) {
2662 GLuint depth
[MAX_WIDTH
];
2664 _mesa_unpack_depth_span(ctx
, srcWidth
,
2665 GL_UNSIGNED_INT
, /* dst type */
2666 depth
, /* dst addr */
2668 srcType
, src
, srcPacking
);
2670 for (i
= 0; i
< srcWidth
; i
++)
2671 dstRow
[i
] = depth
[i
] | (dstRow
[i
] & 0xFF000000);
2673 src
+= srcRowStride
;
2674 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2679 for (img
= 0; img
< srcDepth
; img
++) {
2680 GLuint
*dstRow
= (GLuint
*) dstAddr
2681 + dstImageOffsets
[dstZoffset
+ img
]
2682 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2685 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2686 srcWidth
, srcHeight
,
2689 for (row
= 0; row
< srcHeight
; row
++) {
2690 GLubyte stencil
[MAX_WIDTH
];
2692 /* the 24 depth bits will be in the low position: */
2693 _mesa_unpack_depth_span(ctx
, srcWidth
,
2694 GL_UNSIGNED_INT
, /* dst type */
2695 dstRow
, /* dst addr */
2697 srcType
, src
, srcPacking
);
2698 /* get the 8-bit stencil values */
2699 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2700 GL_UNSIGNED_BYTE
, /* dst type */
2701 stencil
, /* dst addr */
2702 srcType
, src
, srcPacking
,
2703 ctx
->_ImageTransferState
);
2704 /* merge stencil values into depth values */
2705 for (i
= 0; i
< srcWidth
; i
++)
2706 dstRow
[i
] |= stencil
[i
] << 24;
2708 src
+= srcRowStride
;
2709 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2717 * Store an image in any of the formats:
2718 * _mesa_texformat_rgba_float32
2719 * _mesa_texformat_rgb_float32
2720 * _mesa_texformat_alpha_float32
2721 * _mesa_texformat_luminance_float32
2722 * _mesa_texformat_luminance_alpha_float32
2723 * _mesa_texformat_intensity_float32
2726 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2728 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2730 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2731 dstFormat
== &_mesa_texformat_rgb_float32
||
2732 dstFormat
== &_mesa_texformat_alpha_float32
||
2733 dstFormat
== &_mesa_texformat_luminance_float32
||
2734 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2735 dstFormat
== &_mesa_texformat_intensity_float32
);
2736 ASSERT(baseInternalFormat
== GL_RGBA
||
2737 baseInternalFormat
== GL_RGB
||
2738 baseInternalFormat
== GL_ALPHA
||
2739 baseInternalFormat
== GL_LUMINANCE
||
2740 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2741 baseInternalFormat
== GL_INTENSITY
);
2742 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2744 if (!ctx
->_ImageTransferState
&&
2745 !srcPacking
->SwapBytes
&&
2746 baseInternalFormat
== srcFormat
&&
2747 srcType
== GL_FLOAT
) {
2748 /* simple memcpy path */
2749 memcpy_texture(ctx
, dims
,
2750 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2753 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2754 srcAddr
, srcPacking
);
2758 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2760 dstFormat
->BaseFormat
,
2761 srcWidth
, srcHeight
, srcDepth
,
2762 srcFormat
, srcType
, srcAddr
,
2764 const GLfloat
*srcRow
= tempImage
;
2769 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2770 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2771 for (img
= 0; img
< srcDepth
; img
++) {
2772 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2773 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2774 + dstYoffset
* dstRowStride
2775 + dstXoffset
* dstFormat
->TexelBytes
;
2776 for (row
= 0; row
< srcHeight
; row
++) {
2777 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2778 dstRow
+= dstRowStride
;
2779 srcRow
+= srcWidth
* components
;
2783 _mesa_free((void *) tempImage
);
2790 * As above, but store 16-bit floats.
2793 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2795 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2797 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2798 dstFormat
== &_mesa_texformat_rgb_float16
||
2799 dstFormat
== &_mesa_texformat_alpha_float16
||
2800 dstFormat
== &_mesa_texformat_luminance_float16
||
2801 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2802 dstFormat
== &_mesa_texformat_intensity_float16
);
2803 ASSERT(baseInternalFormat
== GL_RGBA
||
2804 baseInternalFormat
== GL_RGB
||
2805 baseInternalFormat
== GL_ALPHA
||
2806 baseInternalFormat
== GL_LUMINANCE
||
2807 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2808 baseInternalFormat
== GL_INTENSITY
);
2809 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2811 if (!ctx
->_ImageTransferState
&&
2812 !srcPacking
->SwapBytes
&&
2813 baseInternalFormat
== srcFormat
&&
2814 srcType
== GL_HALF_FLOAT_ARB
) {
2815 /* simple memcpy path */
2816 memcpy_texture(ctx
, dims
,
2817 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2820 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2821 srcAddr
, srcPacking
);
2825 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2827 dstFormat
->BaseFormat
,
2828 srcWidth
, srcHeight
, srcDepth
,
2829 srcFormat
, srcType
, srcAddr
,
2831 const GLfloat
*src
= tempImage
;
2835 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2836 for (img
= 0; img
< srcDepth
; img
++) {
2837 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2838 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2839 + dstYoffset
* dstRowStride
2840 + dstXoffset
* dstFormat
->TexelBytes
;
2841 for (row
= 0; row
< srcHeight
; row
++) {
2842 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2844 for (i
= 0; i
< srcWidth
* components
; i
++) {
2845 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2847 dstRow
+= dstRowStride
;
2848 src
+= srcWidth
* components
;
2852 _mesa_free((void *) tempImage
);
2858 #if FEATURE_EXT_texture_sRGB
2860 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2862 const struct gl_texture_format
*newDstFormat
;
2863 StoreTexImageFunc store
;
2866 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2868 /* reuse normal rgb texstore code */
2869 newDstFormat
= &_mesa_texformat_rgb888
;
2870 store
= _mesa_texstore_rgb888
;
2872 k
= store(ctx
, dims
, baseInternalFormat
,
2873 newDstFormat
, dstAddr
,
2874 dstXoffset
, dstYoffset
, dstZoffset
,
2875 dstRowStride
, dstImageOffsets
,
2876 srcWidth
, srcHeight
, srcDepth
,
2878 srcAddr
, srcPacking
);
2884 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2886 const struct gl_texture_format
*newDstFormat
;
2889 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2891 /* reuse normal rgba texstore code */
2892 newDstFormat
= &_mesa_texformat_rgba8888
;
2894 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2895 newDstFormat
, dstAddr
,
2896 dstXoffset
, dstYoffset
, dstZoffset
,
2897 dstRowStride
, dstImageOffsets
,
2898 srcWidth
, srcHeight
, srcDepth
,
2900 srcAddr
, srcPacking
);
2906 _mesa_texstore_sargb8(TEXSTORE_PARAMS
)
2908 const struct gl_texture_format
*newDstFormat
;
2911 ASSERT(dstFormat
== &_mesa_texformat_sargb8
);
2913 /* reuse normal rgba texstore code */
2914 newDstFormat
= &_mesa_texformat_argb8888
;
2916 k
= _mesa_texstore_argb8888(ctx
, dims
, baseInternalFormat
,
2917 newDstFormat
, dstAddr
,
2918 dstXoffset
, dstYoffset
, dstZoffset
,
2919 dstRowStride
, dstImageOffsets
,
2920 srcWidth
, srcHeight
, srcDepth
,
2922 srcAddr
, srcPacking
);
2928 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2930 const struct gl_texture_format
*newDstFormat
;
2933 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2935 newDstFormat
= &_mesa_texformat_l8
;
2937 /* _mesa_textore_a8 handles luminance8 too */
2938 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2939 newDstFormat
, dstAddr
,
2940 dstXoffset
, dstYoffset
, dstZoffset
,
2941 dstRowStride
, dstImageOffsets
,
2942 srcWidth
, srcHeight
, srcDepth
,
2944 srcAddr
, srcPacking
);
2950 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2952 const struct gl_texture_format
*newDstFormat
;
2955 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2957 /* reuse normal luminance/alpha texstore code */
2958 newDstFormat
= &_mesa_texformat_al88
;
2960 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2961 newDstFormat
, dstAddr
,
2962 dstXoffset
, dstYoffset
, dstZoffset
,
2963 dstRowStride
, dstImageOffsets
,
2964 srcWidth
, srcHeight
, srcDepth
,
2966 srcAddr
, srcPacking
);
2970 #endif /* FEATURE_EXT_texture_sRGB */
2974 * Check if an unpack PBO is active prior to fetching a texture image.
2975 * If so, do bounds checking and map the buffer into main memory.
2976 * Any errors detected will be recorded.
2977 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2980 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2981 GLsizei width
, GLsizei height
, GLsizei depth
,
2982 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2983 const struct gl_pixelstore_attrib
*unpack
,
2984 const char *funcName
)
2988 if (unpack
->BufferObj
->Name
== 0) {
2992 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2993 format
, type
, pixels
)) {
2994 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2998 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2999 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
3001 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
3005 return ADD_POINTERS(buf
, pixels
);
3010 * Check if an unpack PBO is active prior to fetching a compressed texture
3012 * If so, do bounds checking and map the buffer into main memory.
3013 * Any errors detected will be recorded.
3014 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
3017 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
3018 GLsizei imageSize
, const GLvoid
*pixels
,
3019 const struct gl_pixelstore_attrib
*packing
,
3020 const char *funcName
)
3024 if (packing
->BufferObj
->Name
== 0) {
3025 /* not using a PBO - return pointer unchanged */
3028 if ((const GLubyte
*) pixels
+ imageSize
>
3029 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
3030 /* out of bounds read! */
3031 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
3035 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
3036 GL_READ_ONLY_ARB
, packing
->BufferObj
);
3038 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
3042 return ADD_POINTERS(buf
, pixels
);
3047 * This function must be called after either of the validate_pbo_*_teximage()
3048 * functions. It unmaps the PBO buffer if it was mapped earlier.
3051 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
3052 const struct gl_pixelstore_attrib
*unpack
)
3054 if (unpack
->BufferObj
->Name
) {
3055 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
3063 * Adaptor for fetching a GLchan texel from a float-valued texture.
3066 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
3067 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
3070 ASSERT(texImage
->FetchTexelf
);
3071 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
3072 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
3073 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
3074 /* just one channel */
3075 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
3079 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
3080 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
3081 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
3082 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
3088 * Adaptor for fetching a float texel from a GLchan-valued texture.
3091 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
3092 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
3095 ASSERT(texImage
->FetchTexelc
);
3096 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
3097 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
3098 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
3099 /* just one channel */
3100 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
3104 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
3105 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
3106 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
3107 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
3113 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
3116 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
3118 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
3119 ASSERT(texImage
->TexFormat
);
3123 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
3124 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
3127 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
3128 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
3131 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
3132 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
3138 /* now check if we need to use a float/chan adaptor */
3139 if (!texImage
->FetchTexelc
) {
3140 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
3142 else if (!texImage
->FetchTexelf
) {
3143 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
3147 ASSERT(texImage
->FetchTexelc
);
3148 ASSERT(texImage
->FetchTexelf
);
3153 * Choose the actual storage format for a new texture image.
3154 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
3155 * Also set some other texImage fields related to texture compression, etc.
3156 * \param ctx rendering context
3157 * \param texImage the gl_texture_image
3158 * \param dims texture dimensions (1, 2 or 3)
3159 * \param format the user-specified format parameter
3160 * \param type the user-specified type parameter
3161 * \param internalFormat the user-specified internal format hint
3164 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
3166 GLenum format
, GLenum type
, GLint internalFormat
)
3168 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
3169 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
3172 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
3174 ASSERT(texImage
->TexFormat
);
3176 _mesa_set_fetch_functions(texImage
, dims
);
3178 if (texImage
->TexFormat
->TexelBytes
== 0) {
3179 /* must be a compressed format */
3180 texImage
->IsCompressed
= GL_TRUE
;
3181 texImage
->CompressedSize
=
3182 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
3183 texImage
->Height
, texImage
->Depth
,
3184 texImage
->TexFormat
->MesaFormat
);
3187 /* non-compressed format */
3188 texImage
->IsCompressed
= GL_FALSE
;
3189 texImage
->CompressedSize
= 0;
3196 * This is the software fallback for Driver.TexImage1D()
3197 * and Driver.CopyTexImage1D().
3198 * \sa _mesa_store_teximage2d()
3199 * Note that the width may not be the actual texture width since it may
3200 * be changed by convolution w/ GL_REDUCE. The texImage->Width field will
3201 * have the actual texture size.
3204 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3205 GLint internalFormat
,
3206 GLint width
, GLint border
,
3207 GLenum format
, GLenum type
, const GLvoid
*pixels
,
3208 const struct gl_pixelstore_attrib
*packing
,
3209 struct gl_texture_object
*texObj
,
3210 struct gl_texture_image
*texImage
)
3215 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
3217 /* allocate memory */
3218 if (texImage
->IsCompressed
)
3219 sizeInBytes
= texImage
->CompressedSize
;
3221 sizeInBytes
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
3222 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3223 if (!texImage
->Data
) {
3224 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3228 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3229 pixels
, packing
, "glTexImage1D");
3231 /* Note: we check for a NULL image pointer here, _after_ we allocated
3232 * memory for the texture. That's what the GL spec calls for.
3237 const GLint dstRowStride
= 0;
3239 ASSERT(texImage
->TexFormat
->StoreImage
);
3240 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3241 texImage
->TexFormat
,
3243 0, 0, 0, /* dstX/Y/Zoffset */
3245 texImage
->ImageOffsets
,
3247 format
, type
, pixels
, packing
);
3249 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3253 /* GL_SGIS_generate_mipmap */
3254 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3255 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3258 _mesa_unmap_teximage_pbo(ctx
, packing
);
3263 * This is the software fallback for Driver.TexImage2D()
3264 * and Driver.CopyTexImage2D().
3266 * This function is oriented toward storing images in main memory, rather
3267 * than VRAM. Device driver's can easily plug in their own replacement.
3269 * Note: width and height may be pre-convolved dimensions, but
3270 * texImage->Width and texImage->Height will be post-convolved dimensions.
3273 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3274 GLint internalFormat
,
3275 GLint width
, GLint height
, GLint border
,
3276 GLenum format
, GLenum type
, const void *pixels
,
3277 const struct gl_pixelstore_attrib
*packing
,
3278 struct gl_texture_object
*texObj
,
3279 struct gl_texture_image
*texImage
)
3281 GLint texelBytes
, sizeInBytes
;
3284 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
3286 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3288 /* allocate memory */
3289 if (texImage
->IsCompressed
)
3290 sizeInBytes
= texImage
->CompressedSize
;
3292 sizeInBytes
= texImage
->Width
* texImage
->Height
* texelBytes
;
3293 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3294 if (!texImage
->Data
) {
3295 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3299 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3300 pixels
, packing
, "glTexImage2D");
3302 /* Note: we check for a NULL image pointer here, _after_ we allocated
3303 * memory for the texture. That's what the GL spec calls for.
3310 if (texImage
->IsCompressed
) {
3312 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3315 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3317 ASSERT(texImage
->TexFormat
->StoreImage
);
3318 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3319 texImage
->TexFormat
,
3321 0, 0, 0, /* dstX/Y/Zoffset */
3323 texImage
->ImageOffsets
,
3325 format
, type
, pixels
, packing
);
3327 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3331 /* GL_SGIS_generate_mipmap */
3332 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3333 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3336 _mesa_unmap_teximage_pbo(ctx
, packing
);
3342 * This is the software fallback for Driver.TexImage3D()
3343 * and Driver.CopyTexImage3D().
3344 * \sa _mesa_store_teximage2d()
3347 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3348 GLint internalFormat
,
3349 GLint width
, GLint height
, GLint depth
, GLint border
,
3350 GLenum format
, GLenum type
, const void *pixels
,
3351 const struct gl_pixelstore_attrib
*packing
,
3352 struct gl_texture_object
*texObj
,
3353 struct gl_texture_image
*texImage
)
3355 GLint texelBytes
, sizeInBytes
;
3358 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3360 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3362 /* allocate memory */
3363 if (texImage
->IsCompressed
)
3364 sizeInBytes
= texImage
->CompressedSize
;
3366 sizeInBytes
= width
* height
* depth
* texelBytes
;
3367 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3368 if (!texImage
->Data
) {
3369 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3373 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3374 type
, pixels
, packing
, "glTexImage3D");
3376 /* Note: we check for a NULL image pointer here, _after_ we allocated
3377 * memory for the texture. That's what the GL spec calls for.
3384 if (texImage
->IsCompressed
) {
3386 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3389 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3391 ASSERT(texImage
->TexFormat
->StoreImage
);
3392 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3393 texImage
->TexFormat
,
3395 0, 0, 0, /* dstX/Y/Zoffset */
3397 texImage
->ImageOffsets
,
3398 width
, height
, depth
,
3399 format
, type
, pixels
, packing
);
3401 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3405 /* GL_SGIS_generate_mipmap */
3406 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3407 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3410 _mesa_unmap_teximage_pbo(ctx
, packing
);
3417 * This is the software fallback for Driver.TexSubImage1D()
3418 * and Driver.CopyTexSubImage1D().
3421 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3422 GLint xoffset
, GLint width
,
3423 GLenum format
, GLenum type
, const void *pixels
,
3424 const struct gl_pixelstore_attrib
*packing
,
3425 struct gl_texture_object
*texObj
,
3426 struct gl_texture_image
*texImage
)
3428 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3429 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3430 pixels
, packing
, "glTexSubImage1D");
3435 const GLint dstRowStride
= 0;
3437 ASSERT(texImage
->TexFormat
->StoreImage
);
3438 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3439 texImage
->TexFormat
,
3441 xoffset
, 0, 0, /* offsets */
3443 texImage
->ImageOffsets
,
3445 format
, type
, pixels
, packing
);
3447 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3451 /* GL_SGIS_generate_mipmap */
3452 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3453 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3456 _mesa_unmap_teximage_pbo(ctx
, packing
);
3462 * This is the software fallback for Driver.TexSubImage2D()
3463 * and Driver.CopyTexSubImage2D().
3466 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3467 GLint xoffset
, GLint yoffset
,
3468 GLint width
, GLint height
,
3469 GLenum format
, GLenum type
, const void *pixels
,
3470 const struct gl_pixelstore_attrib
*packing
,
3471 struct gl_texture_object
*texObj
,
3472 struct gl_texture_image
*texImage
)
3474 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3475 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3476 pixels
, packing
, "glTexSubImage2D");
3481 GLint dstRowStride
= 0;
3483 if (texImage
->IsCompressed
) {
3484 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3488 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3490 ASSERT(texImage
->TexFormat
->StoreImage
);
3491 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3492 texImage
->TexFormat
,
3494 xoffset
, yoffset
, 0,
3496 texImage
->ImageOffsets
,
3498 format
, type
, pixels
, packing
);
3500 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3504 /* GL_SGIS_generate_mipmap */
3505 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3506 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3509 _mesa_unmap_teximage_pbo(ctx
, packing
);
3514 * This is the software fallback for Driver.TexSubImage3D().
3515 * and Driver.CopyTexSubImage3D().
3518 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3519 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3520 GLint width
, GLint height
, GLint depth
,
3521 GLenum format
, GLenum type
, const void *pixels
,
3522 const struct gl_pixelstore_attrib
*packing
,
3523 struct gl_texture_object
*texObj
,
3524 struct gl_texture_image
*texImage
)
3526 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3527 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3528 type
, pixels
, packing
,
3536 if (texImage
->IsCompressed
) {
3537 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3541 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3543 ASSERT(texImage
->TexFormat
->StoreImage
);
3544 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3545 texImage
->TexFormat
,
3547 xoffset
, yoffset
, zoffset
,
3549 texImage
->ImageOffsets
,
3550 width
, height
, depth
,
3551 format
, type
, pixels
, packing
);
3553 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3557 /* GL_SGIS_generate_mipmap */
3558 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3559 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3562 _mesa_unmap_teximage_pbo(ctx
, packing
);
3567 * Fallback for Driver.CompressedTexImage1D()
3570 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3571 GLint internalFormat
,
3572 GLint width
, GLint border
,
3573 GLsizei imageSize
, const GLvoid
*data
,
3574 struct gl_texture_object
*texObj
,
3575 struct gl_texture_image
*texImage
)
3577 /* this space intentionally left blank */
3579 (void) target
; (void) level
;
3580 (void) internalFormat
;
3581 (void) width
; (void) border
;
3582 (void) imageSize
; (void) data
;
3590 * Fallback for Driver.CompressedTexImage2D()
3593 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3594 GLint internalFormat
,
3595 GLint width
, GLint height
, GLint border
,
3596 GLsizei imageSize
, const GLvoid
*data
,
3597 struct gl_texture_object
*texObj
,
3598 struct gl_texture_image
*texImage
)
3600 (void) width
; (void) height
; (void) border
;
3602 /* This is pretty simple, basically just do a memcpy without worrying
3603 * about the usual image unpacking or image transfer operations.
3607 ASSERT(texImage
->Width
> 0);
3608 ASSERT(texImage
->Height
> 0);
3609 ASSERT(texImage
->Depth
== 1);
3610 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3612 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3614 /* allocate storage */
3615 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3616 if (!texImage
->Data
) {
3617 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3621 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3623 "glCompressedTexImage2D");
3628 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3629 MEMCPY(texImage
->Data
, data
, imageSize
);
3631 /* GL_SGIS_generate_mipmap */
3632 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3633 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3636 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3642 * Fallback for Driver.CompressedTexImage3D()
3645 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3646 GLint internalFormat
,
3647 GLint width
, GLint height
, GLint depth
,
3649 GLsizei imageSize
, const GLvoid
*data
,
3650 struct gl_texture_object
*texObj
,
3651 struct gl_texture_image
*texImage
)
3653 /* this space intentionally left blank */
3655 (void) target
; (void) level
;
3656 (void) internalFormat
;
3657 (void) width
; (void) height
; (void) depth
;
3659 (void) imageSize
; (void) data
;
3667 * Fallback for Driver.CompressedTexSubImage1D()
3670 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3672 GLint xoffset
, GLsizei width
,
3674 GLsizei imageSize
, const GLvoid
*data
,
3675 struct gl_texture_object
*texObj
,
3676 struct gl_texture_image
*texImage
)
3678 /* there are no compressed 1D texture formats yet */
3680 (void) target
; (void) level
;
3681 (void) xoffset
; (void) width
;
3683 (void) imageSize
; (void) data
;
3690 * Fallback for Driver.CompressedTexSubImage2D()
3693 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3695 GLint xoffset
, GLint yoffset
,
3696 GLsizei width
, GLsizei height
,
3698 GLsizei imageSize
, const GLvoid
*data
,
3699 struct gl_texture_object
*texObj
,
3700 struct gl_texture_image
*texImage
)
3702 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3706 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3710 /* these should have been caught sooner */
3711 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3712 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3713 ASSERT((xoffset
& 3) == 0);
3714 ASSERT((yoffset
& 3) == 0);
3716 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3717 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3719 "glCompressedTexSubImage2D");
3723 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3724 src
= (const GLubyte
*) data
;
3726 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3727 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3728 texImage
->TexFormat
->MesaFormat
,
3730 (GLubyte
*) texImage
->Data
);
3732 bytesPerRow
= srcRowStride
;
3735 for (i
= 0; i
< rows
; i
++) {
3736 MEMCPY(dest
, src
, bytesPerRow
);
3737 dest
+= destRowStride
;
3738 src
+= srcRowStride
;
3741 /* GL_SGIS_generate_mipmap */
3742 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3743 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3746 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3751 * Fallback for Driver.CompressedTexSubImage3D()
3754 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3756 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3757 GLsizei width
, GLsizei height
, GLsizei depth
,
3759 GLsizei imageSize
, const GLvoid
*data
,
3760 struct gl_texture_object
*texObj
,
3761 struct gl_texture_image
*texImage
)
3763 /* there are no compressed 3D texture formats yet */
3765 (void) target
; (void) level
;
3766 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3767 (void) width
; (void) height
; (void) depth
;
3769 (void) imageSize
; (void) data
;
3777 #if FEATURE_EXT_texture_sRGB
3780 * Test if given texture image is an sRGB format.
3783 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3785 switch (texImage
->TexFormat
->MesaFormat
) {
3786 case MESA_FORMAT_SRGB8
:
3787 case MESA_FORMAT_SRGBA8
:
3788 case MESA_FORMAT_SARGB8
:
3789 case MESA_FORMAT_SL8
:
3790 case MESA_FORMAT_SLA8
:
3791 case MESA_FORMAT_SRGB_DXT1
:
3792 case MESA_FORMAT_SRGBA_DXT1
:
3793 case MESA_FORMAT_SRGBA_DXT3
:
3794 case MESA_FORMAT_SRGBA_DXT5
:
3803 * Convert a float value from linear space to a
3804 * non-linear sRGB value in [0, 255].
3805 * Not terribly efficient.
3807 static INLINE GLfloat
3808 linear_to_nonlinear(GLfloat cl
)
3810 /* can't have values outside [0, 1] */
3812 if (cl
< 0.0031308) {
3816 cs
= 1.055 * _mesa_pow(cl
, 0.41666) - 0.055;
3821 #endif /* FEATURE_EXT_texture_sRGB */
3824 * This is the software fallback for Driver.GetTexImage().
3825 * All error checking will have been done before this routine is called.
3828 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3829 GLenum format
, GLenum type
, GLvoid
*pixels
,
3830 struct gl_texture_object
*texObj
,
3831 struct gl_texture_image
*texImage
)
3833 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3835 if (ctx
->Pack
.BufferObj
->Name
) {
3836 /* Packing texture image into a PBO.
3837 * Map the (potentially) VRAM-based buffer into our process space so
3838 * we can write into it with the code below.
3839 * A hardware driver might use a sophisticated blit to move the
3840 * texture data to the PBO if the PBO is in VRAM along with the texture.
3842 GLubyte
*buf
= (GLubyte
*)
3843 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3844 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3846 /* buffer is already mapped - that's an error */
3847 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3850 /* <pixels> was an offset into the PBO.
3851 * Now make it a real, client-side pointer inside the mapped region.
3853 pixels
= ADD_POINTERS(buf
, pixels
);
3861 const GLint width
= texImage
->Width
;
3862 const GLint height
= texImage
->Height
;
3863 const GLint depth
= texImage
->Depth
;
3865 for (img
= 0; img
< depth
; img
++) {
3866 for (row
= 0; row
< height
; row
++) {
3867 /* compute destination address in client memory */
3868 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3869 width
, height
, format
, type
,
3873 if (format
== GL_COLOR_INDEX
) {
3874 GLuint indexRow
[MAX_WIDTH
];
3876 /* Can't use FetchTexel here because that returns RGBA */
3877 if (texImage
->TexFormat
->IndexBits
== 8) {
3878 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3879 src
+= width
* (img
* texImage
->Height
+ row
);
3880 for (col
= 0; col
< width
; col
++) {
3881 indexRow
[col
] = src
[col
];
3884 else if (texImage
->TexFormat
->IndexBits
== 16) {
3885 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3886 src
+= width
* (img
* texImage
->Height
+ row
);
3887 for (col
= 0; col
< width
; col
++) {
3888 indexRow
[col
] = src
[col
];
3893 "Color index problem in _mesa_GetTexImage");
3895 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3896 indexRow
, &ctx
->Pack
,
3897 0 /* no image transfer */);
3899 else if (format
== GL_DEPTH_COMPONENT
) {
3900 GLfloat depthRow
[MAX_WIDTH
];
3902 for (col
= 0; col
< width
; col
++) {
3903 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3906 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3907 depthRow
, &ctx
->Pack
);
3909 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3910 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3911 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3912 src
+= width
* row
+ width
* height
* img
;
3913 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3914 if (ctx
->Pack
.SwapBytes
) {
3915 _mesa_swap4((GLuint
*) dest
, width
);
3918 else if (format
== GL_YCBCR_MESA
) {
3919 /* No pixel transfer */
3920 const GLint rowstride
= texImage
->RowStride
;
3922 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3923 width
* sizeof(GLushort
));
3924 /* check for byte swapping */
3925 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3926 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3927 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3928 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3929 if (!ctx
->Pack
.SwapBytes
)
3930 _mesa_swap2((GLushort
*) dest
, width
);
3932 else if (ctx
->Pack
.SwapBytes
) {
3933 _mesa_swap2((GLushort
*) dest
, width
);
3936 #if FEATURE_EXT_texture_sRGB
3937 else if (is_srgb_teximage(texImage
)) {
3938 /* special case this since need to backconvert values */
3939 /* convert row to RGBA format */
3940 GLfloat rgba
[MAX_WIDTH
][4];
3942 GLbitfield transferOps
= 0x0;
3944 for (col
= 0; col
< width
; col
++) {
3945 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3946 if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3947 rgba
[col
][RCOMP
] = linear_to_nonlinear(rgba
[col
][RCOMP
]);
3948 rgba
[col
][GCOMP
] = 0.0;
3949 rgba
[col
][BCOMP
] = 0.0;
3951 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3952 rgba
[col
][RCOMP
] = linear_to_nonlinear(rgba
[col
][RCOMP
]);
3953 rgba
[col
][GCOMP
] = 0.0;
3954 rgba
[col
][BCOMP
] = 0.0;
3956 else if (texImage
->TexFormat
->BaseFormat
== GL_RGB
||
3957 texImage
->TexFormat
->BaseFormat
== GL_RGBA
) {
3958 rgba
[col
][RCOMP
] = linear_to_nonlinear(rgba
[col
][RCOMP
]);
3959 rgba
[col
][GCOMP
] = linear_to_nonlinear(rgba
[col
][GCOMP
]);
3960 rgba
[col
][BCOMP
] = linear_to_nonlinear(rgba
[col
][BCOMP
]);
3963 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3965 &ctx
->Pack
, transferOps
/*image xfer ops*/);
3967 #endif /* FEATURE_EXT_texture_sRGB */
3969 /* general case: convert row to RGBA format */
3970 GLfloat rgba
[MAX_WIDTH
][4];
3972 GLbitfield transferOps
= 0x0;
3974 if (type
== GL_FLOAT
&& texImage
->TexFormat
->BaseFormat
!= GL_DUDV_ATI
&&
3975 ((ctx
->Color
.ClampReadColor
== GL_TRUE
) ||
3976 (ctx
->Color
.ClampReadColor
== GL_FIXED_ONLY_ARB
&&
3977 texImage
->TexFormat
->DataType
!= GL_FLOAT
)))
3978 transferOps
|= IMAGE_CLAMP_BIT
;
3980 for (col
= 0; col
< width
; col
++) {
3981 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3982 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3983 rgba
[col
][RCOMP
] = 0.0;
3984 rgba
[col
][GCOMP
] = 0.0;
3985 rgba
[col
][BCOMP
] = 0.0;
3987 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3988 rgba
[col
][GCOMP
] = 0.0;
3989 rgba
[col
][BCOMP
] = 0.0;
3990 rgba
[col
][ACOMP
] = 1.0;
3992 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3993 rgba
[col
][GCOMP
] = 0.0;
3994 rgba
[col
][BCOMP
] = 0.0;
3996 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3997 rgba
[col
][GCOMP
] = 0.0;
3998 rgba
[col
][BCOMP
] = 0.0;
3999 rgba
[col
][ACOMP
] = 1.0;
4002 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
4004 &ctx
->Pack
, transferOps
/*image xfer ops*/);
4010 if (ctx
->Pack
.BufferObj
->Name
) {
4011 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4012 ctx
->Pack
.BufferObj
);
4019 * This is the software fallback for Driver.GetCompressedTexImage().
4020 * All error checking will have been done before this routine is called.
4023 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4025 struct gl_texture_object
*texObj
,
4026 struct gl_texture_image
*texImage
)
4030 if (ctx
->Pack
.BufferObj
->Name
) {
4031 /* pack texture image into a PBO */
4033 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4034 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4035 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4036 "glGetCompressedTexImage(invalid PBO access)");
4039 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4041 ctx
->Pack
.BufferObj
);
4043 /* buffer is already mapped - that's an error */
4044 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4045 "glGetCompressedTexImage(PBO is mapped)");
4048 img
= ADD_POINTERS(buf
, img
);
4055 /* don't use texImage->CompressedSize since that may be padded out */
4056 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
4058 texImage
->TexFormat
->MesaFormat
);
4060 /* just memcpy, no pixelstore or pixel transfer */
4061 _mesa_memcpy(img
, texImage
->Data
, size
);
4063 if (ctx
->Pack
.BufferObj
->Name
) {
4064 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4065 ctx
->Pack
.BufferObj
);