2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
65 #include "texcompress.h"
66 #include "texformat.h"
79 * Return GL_TRUE if the given image format is one that be converted
80 * to another format by swizzling.
83 can_swizzle(GLenum logicalBaseFormat
)
85 switch (logicalBaseFormat
) {
88 case GL_LUMINANCE_ALPHA
:
122 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
123 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
124 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
125 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
128 static const struct {
131 GLubyte from_rgba
[6];
132 } mappings
[MAX_IDX
] =
142 MAP4(ZERO
, ZERO
, ZERO
, 0),
173 MAP4(0, ZERO
, ZERO
, ONE
),
179 MAP4(ZERO
, 0, ZERO
, ONE
),
185 MAP4(ZERO
, ZERO
, 0, ONE
),
211 * Convert a GL image format enum to an IDX_* value (see above).
214 get_map_idx(GLenum value
)
217 case GL_LUMINANCE
: return IDX_LUMINANCE
;
218 case GL_ALPHA
: return IDX_ALPHA
;
219 case GL_INTENSITY
: return IDX_INTENSITY
;
220 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
221 case GL_RGB
: return IDX_RGB
;
222 case GL_RGBA
: return IDX_RGBA
;
223 case GL_RED
: return IDX_RED
;
224 case GL_GREEN
: return IDX_GREEN
;
225 case GL_BLUE
: return IDX_BLUE
;
226 case GL_BGR
: return IDX_BGR
;
227 case GL_BGRA
: return IDX_BGRA
;
228 case GL_ABGR_EXT
: return IDX_ABGR
;
230 _mesa_problem(NULL
, "Unexpected inFormat");
237 * When promoting texture formats (see below) we need to compute the
238 * mapping of dest components back to source components.
239 * This function does that.
240 * \param inFormat the incoming format of the texture
241 * \param outFormat the final texture format
242 * \return map[6] a full 6-component map
245 compute_component_mapping(GLenum inFormat
, GLenum outFormat
,
248 const int inFmt
= get_map_idx(inFormat
);
249 const int outFmt
= get_map_idx(outFormat
);
250 const GLubyte
*in2rgba
= mappings
[inFmt
].to_rgba
;
251 const GLubyte
*rgba2out
= mappings
[outFmt
].from_rgba
;
254 for (i
= 0; i
< 4; i
++)
255 map
[i
] = in2rgba
[rgba2out
[i
]];
261 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
262 inFormat, _mesa_lookup_enum_by_nr(inFormat),
263 outFormat, _mesa_lookup_enum_by_nr(outFormat),
274 #if !FEATURE_convolve
276 _mesa_adjust_image_for_convolution(GLcontext
*ctx
, GLuint dims
,
277 GLsizei
*srcWidth
, GLsizei
*srcHeight
)
285 * Make a temporary (color) texture image with GLfloat components.
286 * Apply all needed pixel unpacking and pixel transfer operations.
287 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
288 * Suppose the user specifies GL_LUMINANCE as the internal texture format
289 * but the graphics hardware doesn't support luminance textures. So, might
290 * use an RGB hardware format instead.
291 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
293 * \param ctx the rendering context
294 * \param dims image dimensions: 1, 2 or 3
295 * \param logicalBaseFormat basic texture derived from the user's
296 * internal texture format value
297 * \param textureBaseFormat the actual basic format of the texture
298 * \param srcWidth source image width
299 * \param srcHeight source image height
300 * \param srcDepth source image depth
301 * \param srcFormat source image format
302 * \param srcType source image type
303 * \param srcAddr source image address
304 * \param srcPacking source image pixel packing
305 * \return resulting image with format = textureBaseFormat and type = GLfloat.
308 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
309 GLenum logicalBaseFormat
,
310 GLenum textureBaseFormat
,
311 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
312 GLenum srcFormat
, GLenum srcType
,
313 const GLvoid
*srcAddr
,
314 const struct gl_pixelstore_attrib
*srcPacking
)
316 GLuint transferOps
= ctx
->_ImageTransferState
;
319 ASSERT(dims
>= 1 && dims
<= 3);
321 ASSERT(logicalBaseFormat
== GL_RGBA
||
322 logicalBaseFormat
== GL_RGB
||
323 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
324 logicalBaseFormat
== GL_LUMINANCE
||
325 logicalBaseFormat
== GL_ALPHA
||
326 logicalBaseFormat
== GL_INTENSITY
||
327 logicalBaseFormat
== GL_COLOR_INDEX
||
328 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
330 ASSERT(textureBaseFormat
== GL_RGBA
||
331 textureBaseFormat
== GL_RGB
||
332 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
333 textureBaseFormat
== GL_LUMINANCE
||
334 textureBaseFormat
== GL_ALPHA
||
335 textureBaseFormat
== GL_INTENSITY
||
336 textureBaseFormat
== GL_COLOR_INDEX
||
337 textureBaseFormat
== GL_DEPTH_COMPONENT
);
339 /* conventional color image */
341 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
342 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
343 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
344 /* need image convolution */
345 const GLuint preConvTransferOps
346 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
347 const GLuint postConvTransferOps
348 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
350 GLint convWidth
, convHeight
;
353 /* pre-convolution image buffer (3D) */
354 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
355 * 4 * sizeof(GLfloat
));
359 /* post-convolution image buffer (2D) */
360 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
361 * 4 * sizeof(GLfloat
));
363 _mesa_free(tempImage
);
367 /* loop over 3D image slices */
368 for (img
= 0; img
< srcDepth
; img
++) {
369 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
371 /* unpack and do transfer ops up to convolution */
372 for (row
= 0; row
< srcHeight
; row
++) {
373 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
374 srcAddr
, srcWidth
, srcHeight
,
375 srcFormat
, srcType
, img
, row
, 0);
376 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
377 srcFormat
, srcType
, src
,
386 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
387 convWidth
= srcWidth
;
388 convHeight
= srcHeight
;
390 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
391 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
394 if (ctx
->Pixel
.Convolution2DEnabled
) {
395 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
399 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
400 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
406 /* do post-convolution transfer and pack into tempImage */
408 const GLint logComponents
409 = _mesa_components_in_format(logicalBaseFormat
);
410 const GLfloat
*src
= convImage
;
411 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
412 for (row
= 0; row
< convHeight
; row
++) {
413 _mesa_pack_rgba_span_float(ctx
, convWidth
,
414 (GLfloat (*)[4]) src
,
415 logicalBaseFormat
, GL_FLOAT
,
416 dst
, &ctx
->DefaultPacking
,
417 postConvTransferOps
);
418 src
+= convWidth
* 4;
419 dst
+= convWidth
* logComponents
;
422 } /* loop over 3D image slices */
424 _mesa_free(convImage
);
426 /* might need these below */
427 srcWidth
= convWidth
;
428 srcHeight
= convHeight
;
432 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
433 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
434 srcWidth
, srcFormat
, srcType
);
438 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
439 * components
* sizeof(GLfloat
));
444 for (img
= 0; img
< srcDepth
; img
++) {
446 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
450 for (row
= 0; row
< srcHeight
; row
++) {
451 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
452 dst
, srcFormat
, srcType
, src
,
453 srcPacking
, transferOps
);
454 dst
+= srcWidth
* components
;
460 if (logicalBaseFormat
!= textureBaseFormat
) {
462 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
463 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
468 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
469 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
470 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
472 /* The actual texture format should have at least as many components
473 * as the logical texture format.
475 ASSERT(texComponents
>= logComponents
);
477 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
478 * texComponents
* sizeof(GLfloat
));
480 _mesa_free(tempImage
);
484 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
486 n
= srcWidth
* srcHeight
* srcDepth
;
487 for (i
= 0; i
< n
; i
++) {
489 for (k
= 0; k
< texComponents
; k
++) {
492 newImage
[i
* texComponents
+ k
] = 0.0F
;
494 newImage
[i
* texComponents
+ k
] = 1.0F
;
496 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
500 _mesa_free(tempImage
);
501 tempImage
= newImage
;
509 * Make a temporary (color) texture image with GLchan components.
510 * Apply all needed pixel unpacking and pixel transfer operations.
511 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
512 * Suppose the user specifies GL_LUMINANCE as the internal texture format
513 * but the graphics hardware doesn't support luminance textures. So, might
514 * use an RGB hardware format instead.
515 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
517 * \param ctx the rendering context
518 * \param dims image dimensions: 1, 2 or 3
519 * \param logicalBaseFormat basic texture derived from the user's
520 * internal texture format value
521 * \param textureBaseFormat the actual basic format of the texture
522 * \param srcWidth source image width
523 * \param srcHeight source image height
524 * \param srcDepth source image depth
525 * \param srcFormat source image format
526 * \param srcType source image type
527 * \param srcAddr source image address
528 * \param srcPacking source image pixel packing
529 * \return resulting image with format = textureBaseFormat and type = GLchan.
532 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
533 GLenum logicalBaseFormat
,
534 GLenum textureBaseFormat
,
535 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
536 GLenum srcFormat
, GLenum srcType
,
537 const GLvoid
*srcAddr
,
538 const struct gl_pixelstore_attrib
*srcPacking
)
540 GLuint transferOps
= ctx
->_ImageTransferState
;
541 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
542 GLboolean freeSrcImage
= GL_FALSE
;
544 GLchan
*tempImage
, *dst
;
546 ASSERT(dims
>= 1 && dims
<= 3);
548 ASSERT(logicalBaseFormat
== GL_RGBA
||
549 logicalBaseFormat
== GL_RGB
||
550 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
551 logicalBaseFormat
== GL_LUMINANCE
||
552 logicalBaseFormat
== GL_ALPHA
||
553 logicalBaseFormat
== GL_INTENSITY
);
555 ASSERT(textureBaseFormat
== GL_RGBA
||
556 textureBaseFormat
== GL_RGB
||
557 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
558 textureBaseFormat
== GL_LUMINANCE
||
559 textureBaseFormat
== GL_ALPHA
||
560 textureBaseFormat
== GL_INTENSITY
);
563 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
564 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
565 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
566 /* get convolved image */
567 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
570 srcWidth
, srcHeight
, srcDepth
,
572 srcAddr
, srcPacking
);
575 /* the convolved image is our new source image */
577 srcFormat
= logicalBaseFormat
;
579 srcPacking
= &ctx
->DefaultPacking
;
580 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
582 freeSrcImage
= GL_TRUE
;
586 /* unpack and transfer the source image */
587 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
588 * components
* sizeof(GLchan
));
593 for (img
= 0; img
< srcDepth
; img
++) {
594 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
598 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
602 for (row
= 0; row
< srcHeight
; row
++) {
603 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
604 srcFormat
, srcType
, src
, srcPacking
,
606 dst
+= srcWidth
* components
;
611 /* If we made a temporary image for convolution, free it here */
613 _mesa_free((void *) srcAddr
);
616 if (logicalBaseFormat
!= textureBaseFormat
) {
617 /* one more conversion step */
618 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
619 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
624 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
625 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
626 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
628 /* The actual texture format should have at least as many components
629 * as the logical texture format.
631 ASSERT(texComponents
>= logComponents
);
633 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
634 * texComponents
* sizeof(GLchan
));
636 _mesa_free(tempImage
);
640 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
642 n
= srcWidth
* srcHeight
* srcDepth
;
643 for (i
= 0; i
< n
; i
++) {
645 for (k
= 0; k
< texComponents
; k
++) {
648 newImage
[i
* texComponents
+ k
] = 0;
650 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
652 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
656 _mesa_free(tempImage
);
657 tempImage
= newImage
;
665 * Copy GLubyte pixels from <src> to <dst> with swizzling.
666 * \param dst destination pixels
667 * \param dstComponents number of color components in destination pixels
668 * \param src source pixels
669 * \param srcComponents number of color components in source pixels
670 * \param map the swizzle mapping. map[X] says where to find the X component
671 * in the source image's pixels. For example, if the source image
672 * is GL_BGRA and X = red, map[0] yields 2.
673 * \param count number of pixels to copy/swizzle.
676 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
677 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
685 switch (dstComponents
) {
687 for (i
= 0; i
< count
; i
++) {
689 src
+= srcComponents
;
690 dst
[0] = tmp
[map
[0]];
691 dst
[1] = tmp
[map
[1]];
692 dst
[2] = tmp
[map
[2]];
693 dst
[3] = tmp
[map
[3]];
698 for (i
= 0; i
< count
; i
++) {
700 src
+= srcComponents
;
701 dst
[0] = tmp
[map
[0]];
702 dst
[1] = tmp
[map
[1]];
703 dst
[2] = tmp
[map
[2]];
708 for (i
= 0; i
< count
; i
++) {
710 src
+= srcComponents
;
711 dst
[0] = tmp
[map
[0]];
712 dst
[1] = tmp
[map
[1]];
717 /* XXX investigate valgrind invalid read when running demos/texenv.c */
718 for (i
= 0; i
< count
; i
++) {
720 src
+= srcComponents
;
721 dst
[0] = tmp
[map
[0]];
729 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
730 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
732 /* Deal with the _REV input types:
734 static const GLubyte
*
735 type_mapping( GLenum srcType
)
738 case GL_UNSIGNED_BYTE
:
740 case GL_UNSIGNED_INT_8_8_8_8
:
741 return _mesa_little_endian() ? map_3210
: map_identity
;
742 case GL_UNSIGNED_INT_8_8_8_8_REV
:
743 return _mesa_little_endian() ? map_identity
: map_3210
;
749 /* Mapping required if input type is
751 static const GLubyte
*
752 byteswap_mapping( GLboolean swapBytes
,
759 case GL_UNSIGNED_BYTE
:
761 case GL_UNSIGNED_INT_8_8_8_8
:
762 case GL_UNSIGNED_INT_8_8_8_8_REV
:
772 * Transfer a GLubyte texture image with component swizzling.
775 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
780 GLenum baseInternalFormat
,
782 const GLubyte
*rgba2dst
,
783 GLuint dstComponents
,
786 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
788 const GLuint
*dstImageOffsets
,
790 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
791 const GLvoid
*srcAddr
,
792 const struct gl_pixelstore_attrib
*srcPacking
)
794 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
795 const GLubyte
*srctype2ubyte
, *swap
;
796 GLubyte map
[4], src2base
[6], base2rgba
[6];
798 const GLint srcRowStride
=
799 _mesa_image_row_stride(srcPacking
, srcWidth
,
800 srcFormat
, GL_UNSIGNED_BYTE
);
801 const GLint srcImageStride
802 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
804 const GLubyte
*srcImage
805 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
806 srcWidth
, srcHeight
, srcFormat
,
807 GL_UNSIGNED_BYTE
, 0, 0, 0);
811 /* Translate from src->baseInternal->GL_RGBA->dst. This will
812 * correctly deal with RGBA->RGB->RGBA conversions where the final
813 * A value must be 0xff regardless of the incoming alpha values.
815 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
816 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
817 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
818 srctype2ubyte
= type_mapping(srcType
);
821 for (i
= 0; i
< 4; i
++)
822 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
824 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
826 if (srcRowStride
== dstRowStride
&&
827 srcRowStride
== srcWidth
* srcComponents
&&
829 /* 1 and 2D images only */
830 GLubyte
*dstImage
= (GLubyte
*) dstAddr
831 + dstYoffset
* dstRowStride
832 + dstXoffset
* dstComponents
;
833 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
834 srcWidth
* srcHeight
);
838 for (img
= 0; img
< srcDepth
; img
++) {
839 const GLubyte
*srcRow
= srcImage
;
840 GLubyte
*dstRow
= (GLubyte
*) dstAddr
841 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
842 + dstYoffset
* dstRowStride
843 + dstXoffset
* dstComponents
;
844 for (row
= 0; row
< srcHeight
; row
++) {
845 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
846 dstRow
+= dstRowStride
;
847 srcRow
+= srcRowStride
;
849 srcImage
+= srcImageStride
;
856 * Teximage storage routine for when a simple memcpy will do.
857 * No pixel transfer operations or special texel encodings allowed.
858 * 1D, 2D and 3D images supported.
861 memcpy_texture(GLcontext
*ctx
,
863 const struct gl_texture_format
*dstFormat
,
865 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
867 const GLuint
*dstImageOffsets
,
868 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
869 GLenum srcFormat
, GLenum srcType
,
870 const GLvoid
*srcAddr
,
871 const struct gl_pixelstore_attrib
*srcPacking
)
873 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
875 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
876 srcWidth
, srcHeight
, srcFormat
, srcType
);
877 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
878 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
879 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
882 /* XXX update/re-enable for dstImageOffsets array */
883 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
884 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
885 GLubyte
*dstImage
= (GLubyte
*) dstAddr
886 + dstZoffset
* dstImageStride
887 + dstYoffset
* dstRowStride
888 + dstXoffset
* dstFormat
->TexelBytes
;
890 if (dstRowStride
== srcRowStride
&&
891 dstRowStride
== bytesPerRow
&&
892 ((dstImageStride
== srcImageStride
&&
893 dstImageStride
== bytesPerImage
) ||
896 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
901 for (img
= 0; img
< srcDepth
; img
++) {
902 const GLubyte
*srcRow
= srcImage
;
903 GLubyte
*dstRow
= dstImage
;
904 for (row
= 0; row
< srcHeight
; row
++) {
905 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
906 dstRow
+= dstRowStride
;
907 srcRow
+= srcRowStride
;
909 srcImage
+= srcImageStride
;
910 dstImage
+= dstImageStride
;
916 for (img
= 0; img
< srcDepth
; img
++) {
917 const GLubyte
*srcRow
= srcImage
;
918 GLubyte
*dstRow
= (GLubyte
*) dstAddr
919 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
920 + dstYoffset
* dstRowStride
921 + dstXoffset
* dstFormat
->TexelBytes
;
922 for (row
= 0; row
< srcHeight
; row
++) {
923 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
924 dstRow
+= dstRowStride
;
925 srcRow
+= srcRowStride
;
927 srcImage
+= srcImageStride
;
934 * Store an image in any of the formats:
935 * _mesa_texformat_rgba
936 * _mesa_texformat_rgb
937 * _mesa_texformat_alpha
938 * _mesa_texformat_luminance
939 * _mesa_texformat_luminance_alpha
940 * _mesa_texformat_intensity
944 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
946 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
948 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
949 dstFormat
== &_mesa_texformat_rgb
||
950 dstFormat
== &_mesa_texformat_alpha
||
951 dstFormat
== &_mesa_texformat_luminance
||
952 dstFormat
== &_mesa_texformat_luminance_alpha
||
953 dstFormat
== &_mesa_texformat_intensity
);
954 ASSERT(baseInternalFormat
== GL_RGBA
||
955 baseInternalFormat
== GL_RGB
||
956 baseInternalFormat
== GL_ALPHA
||
957 baseInternalFormat
== GL_LUMINANCE
||
958 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
959 baseInternalFormat
== GL_INTENSITY
);
960 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
962 if (!ctx
->_ImageTransferState
&&
963 !srcPacking
->SwapBytes
&&
964 baseInternalFormat
== srcFormat
&&
965 srcType
== CHAN_TYPE
) {
966 /* simple memcpy path */
967 memcpy_texture(ctx
, dims
,
968 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
971 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
972 srcAddr
, srcPacking
);
974 else if (!ctx
->_ImageTransferState
&&
975 !srcPacking
->SwapBytes
&&
976 dstFormat
== &_mesa_texformat_rgb
&&
977 srcFormat
== GL_RGBA
&&
978 srcType
== CHAN_TYPE
) {
979 /* extract RGB from RGBA */
981 for (img
= 0; img
< srcDepth
; img
++) {
982 GLchan
*dstImage
= (GLchan
*)
984 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
985 + dstYoffset
* dstRowStride
986 + dstXoffset
* dstFormat
->TexelBytes
);
988 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
989 srcWidth
, srcFormat
, srcType
);
990 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
991 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
992 GLchan
*dstRow
= dstImage
;
993 for (row
= 0; row
< srcHeight
; row
++) {
994 for (col
= 0; col
< srcWidth
; col
++) {
995 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
996 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
997 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
999 dstRow
+= dstRowStride
/ sizeof(GLchan
);
1000 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
1004 else if (!ctx
->_ImageTransferState
&&
1005 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
1006 (srcType
== GL_UNSIGNED_BYTE
||
1007 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1008 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1009 can_swizzle(baseInternalFormat
) &&
1010 can_swizzle(srcFormat
)) {
1012 const GLubyte
*dstmap
;
1015 /* dstmap - how to swizzle from RGBA to dst format:
1017 if (dstFormat
== &_mesa_texformat_rgba
) {
1018 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1021 else if (dstFormat
== &_mesa_texformat_rgb
) {
1022 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1025 else if (dstFormat
== &_mesa_texformat_alpha
) {
1026 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1029 else if (dstFormat
== &_mesa_texformat_luminance
) {
1030 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1033 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1034 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1037 else if (dstFormat
== &_mesa_texformat_intensity
) {
1038 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1042 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1046 _mesa_swizzle_ubyte_image(ctx
, dims
,
1051 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1052 dstRowStride
, dstImageOffsets
,
1053 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1058 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1060 dstFormat
->BaseFormat
,
1061 srcWidth
, srcHeight
, srcDepth
,
1062 srcFormat
, srcType
, srcAddr
,
1064 const GLchan
*src
= tempImage
;
1069 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1070 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1071 for (img
= 0; img
< srcDepth
; img
++) {
1072 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1073 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1074 + dstYoffset
* dstRowStride
1075 + dstXoffset
* dstFormat
->TexelBytes
;
1076 for (row
= 0; row
< srcHeight
; row
++) {
1077 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1078 dstRow
+= dstRowStride
;
1079 src
+= srcWidth
* components
;
1083 _mesa_free((void *) tempImage
);
1090 * Store a 32-bit integer depth component texture image.
1093 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1095 const GLuint depthScale
= 0xffffffff;
1097 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1098 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1100 if (!ctx
->_ImageTransferState
&&
1101 !srcPacking
->SwapBytes
&&
1102 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1103 srcFormat
== GL_DEPTH_COMPONENT
&&
1104 srcType
== GL_UNSIGNED_INT
) {
1105 /* simple memcpy path */
1106 memcpy_texture(ctx
, dims
,
1107 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1110 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1111 srcAddr
, srcPacking
);
1116 for (img
= 0; img
< srcDepth
; img
++) {
1117 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1118 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1119 + dstYoffset
* dstRowStride
1120 + dstXoffset
* dstFormat
->TexelBytes
;
1121 for (row
= 0; row
< srcHeight
; row
++) {
1122 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1123 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1124 _mesa_unpack_depth_span(ctx
, srcWidth
,
1125 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1126 depthScale
, srcType
, src
, srcPacking
);
1127 dstRow
+= dstRowStride
;
1137 * Store a 16-bit integer depth component texture image.
1140 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1142 const GLuint depthScale
= 0xffff;
1144 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1145 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1147 if (!ctx
->_ImageTransferState
&&
1148 !srcPacking
->SwapBytes
&&
1149 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1150 srcFormat
== GL_DEPTH_COMPONENT
&&
1151 srcType
== GL_UNSIGNED_SHORT
) {
1152 /* simple memcpy path */
1153 memcpy_texture(ctx
, dims
,
1154 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1157 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1158 srcAddr
, srcPacking
);
1163 for (img
= 0; img
< srcDepth
; img
++) {
1164 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1165 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1166 + dstYoffset
* dstRowStride
1167 + dstXoffset
* dstFormat
->TexelBytes
;
1168 for (row
= 0; row
< srcHeight
; row
++) {
1169 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1170 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1171 GLushort
*dst16
= (GLushort
*) dstRow
;
1172 _mesa_unpack_depth_span(ctx
, srcWidth
,
1173 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1174 srcType
, src
, srcPacking
);
1175 dstRow
+= dstRowStride
;
1184 * Store an rgb565 or rgb565_rev texture image.
1187 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1189 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1190 dstFormat
== &_mesa_texformat_rgb565_rev
);
1191 ASSERT(dstFormat
->TexelBytes
== 2);
1193 if (!ctx
->_ImageTransferState
&&
1194 !srcPacking
->SwapBytes
&&
1195 dstFormat
== &_mesa_texformat_rgb565
&&
1196 baseInternalFormat
== GL_RGB
&&
1197 srcFormat
== GL_RGB
&&
1198 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1199 /* simple memcpy path */
1200 memcpy_texture(ctx
, dims
,
1201 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1204 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1205 srcAddr
, srcPacking
);
1207 else if (!ctx
->_ImageTransferState
&&
1208 !srcPacking
->SwapBytes
&&
1209 baseInternalFormat
== GL_RGB
&&
1210 srcFormat
== GL_RGB
&&
1211 srcType
== GL_UNSIGNED_BYTE
&&
1213 /* do optimized tex store */
1214 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1215 srcFormat
, srcType
);
1216 const GLubyte
*src
= (const GLubyte
*)
1217 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1218 srcFormat
, srcType
, 0, 0, 0);
1219 GLubyte
*dst
= (GLubyte
*) dstAddr
1220 + dstYoffset
* dstRowStride
1221 + dstXoffset
* dstFormat
->TexelBytes
;
1223 for (row
= 0; row
< srcHeight
; row
++) {
1224 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1225 GLushort
*dstUS
= (GLushort
*) dst
;
1226 /* check for byteswapped format */
1227 if (dstFormat
== &_mesa_texformat_rgb565
) {
1228 for (col
= 0; col
< srcWidth
; col
++) {
1229 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1234 for (col
= 0; col
< srcWidth
; col
++) {
1235 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1239 dst
+= dstRowStride
;
1240 src
+= srcRowStride
;
1245 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1247 dstFormat
->BaseFormat
,
1248 srcWidth
, srcHeight
, srcDepth
,
1249 srcFormat
, srcType
, srcAddr
,
1251 const GLchan
*src
= tempImage
;
1252 GLint img
, row
, col
;
1255 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1256 for (img
= 0; img
< srcDepth
; img
++) {
1257 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1258 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1259 + dstYoffset
* dstRowStride
1260 + dstXoffset
* dstFormat
->TexelBytes
;
1261 for (row
= 0; row
< srcHeight
; row
++) {
1262 GLushort
*dstUS
= (GLushort
*) dstRow
;
1263 /* check for byteswapped format */
1264 if (dstFormat
== &_mesa_texformat_rgb565
) {
1265 for (col
= 0; col
< srcWidth
; col
++) {
1266 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1267 CHAN_TO_UBYTE(src
[GCOMP
]),
1268 CHAN_TO_UBYTE(src
[BCOMP
]) );
1273 for (col
= 0; col
< srcWidth
; col
++) {
1274 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1275 CHAN_TO_UBYTE(src
[GCOMP
]),
1276 CHAN_TO_UBYTE(src
[BCOMP
]) );
1280 dstRow
+= dstRowStride
;
1283 _mesa_free((void *) tempImage
);
1290 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1293 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1295 const GLboolean littleEndian
= _mesa_little_endian();
1297 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1298 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1299 ASSERT(dstFormat
->TexelBytes
== 4);
1301 if (!ctx
->_ImageTransferState
&&
1302 !srcPacking
->SwapBytes
&&
1303 dstFormat
== &_mesa_texformat_rgba8888
&&
1304 baseInternalFormat
== GL_RGBA
&&
1305 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1306 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1307 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1308 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1309 /* simple memcpy path */
1310 memcpy_texture(ctx
, dims
,
1311 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1314 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1315 srcAddr
, srcPacking
);
1317 else if (!ctx
->_ImageTransferState
&&
1318 !srcPacking
->SwapBytes
&&
1319 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1320 baseInternalFormat
== GL_RGBA
&&
1321 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1322 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1323 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1324 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1325 /* simple memcpy path */
1326 memcpy_texture(ctx
, dims
,
1327 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1330 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1331 srcAddr
, srcPacking
);
1333 else if (!ctx
->_ImageTransferState
&&
1334 (srcType
== GL_UNSIGNED_BYTE
||
1335 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1336 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1337 can_swizzle(baseInternalFormat
) &&
1338 can_swizzle(srcFormat
)) {
1342 /* dstmap - how to swizzle from RGBA to dst format:
1344 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1345 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1358 _mesa_swizzle_ubyte_image(ctx
, dims
,
1363 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1364 dstRowStride
, dstImageOffsets
,
1365 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1370 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1372 dstFormat
->BaseFormat
,
1373 srcWidth
, srcHeight
, srcDepth
,
1374 srcFormat
, srcType
, srcAddr
,
1376 const GLchan
*src
= tempImage
;
1377 GLint img
, row
, col
;
1380 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1381 for (img
= 0; img
< srcDepth
; img
++) {
1382 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1383 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1384 + dstYoffset
* dstRowStride
1385 + dstXoffset
* dstFormat
->TexelBytes
;
1386 for (row
= 0; row
< srcHeight
; row
++) {
1387 GLuint
*dstUI
= (GLuint
*) dstRow
;
1388 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1389 for (col
= 0; col
< srcWidth
; col
++) {
1390 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1391 CHAN_TO_UBYTE(src
[GCOMP
]),
1392 CHAN_TO_UBYTE(src
[BCOMP
]),
1393 CHAN_TO_UBYTE(src
[ACOMP
]) );
1398 for (col
= 0; col
< srcWidth
; col
++) {
1399 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1400 CHAN_TO_UBYTE(src
[GCOMP
]),
1401 CHAN_TO_UBYTE(src
[BCOMP
]),
1402 CHAN_TO_UBYTE(src
[ACOMP
]) );
1406 dstRow
+= dstRowStride
;
1409 _mesa_free((void *) tempImage
);
1416 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1418 const GLboolean littleEndian
= _mesa_little_endian();
1420 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1421 dstFormat
== &_mesa_texformat_argb8888_rev
);
1422 ASSERT(dstFormat
->TexelBytes
== 4);
1424 if (!ctx
->_ImageTransferState
&&
1425 !srcPacking
->SwapBytes
&&
1426 dstFormat
== &_mesa_texformat_argb8888
&&
1427 baseInternalFormat
== GL_RGBA
&&
1428 srcFormat
== GL_BGRA
&&
1429 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1430 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1431 /* simple memcpy path (little endian) */
1432 memcpy_texture(ctx
, dims
,
1433 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1436 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1437 srcAddr
, srcPacking
);
1439 else if (!ctx
->_ImageTransferState
&&
1440 !srcPacking
->SwapBytes
&&
1441 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1442 baseInternalFormat
== GL_RGBA
&&
1443 srcFormat
== GL_BGRA
&&
1444 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1445 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1446 /* simple memcpy path (big endian) */
1447 memcpy_texture(ctx
, dims
,
1448 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1451 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1452 srcAddr
, srcPacking
);
1454 else if (!ctx
->_ImageTransferState
&&
1455 !srcPacking
->SwapBytes
&&
1456 dstFormat
== &_mesa_texformat_argb8888
&&
1457 srcFormat
== GL_RGB
&&
1458 (baseInternalFormat
== GL_RGBA
||
1459 baseInternalFormat
== GL_RGB
) &&
1460 srcType
== GL_UNSIGNED_BYTE
) {
1462 for (img
= 0; img
< srcDepth
; img
++) {
1463 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1464 srcWidth
, srcFormat
, srcType
);
1465 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1466 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1467 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1468 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1469 + dstYoffset
* dstRowStride
1470 + dstXoffset
* dstFormat
->TexelBytes
;
1471 for (row
= 0; row
< srcHeight
; row
++) {
1472 GLuint
*d4
= (GLuint
*) dstRow
;
1473 for (col
= 0; col
< srcWidth
; col
++) {
1474 d4
[col
] = ((0xff << 24) |
1475 (srcRow
[col
* 3 + RCOMP
] << 16) |
1476 (srcRow
[col
* 3 + GCOMP
] << 8) |
1477 (srcRow
[col
* 3 + BCOMP
] << 0));
1479 dstRow
+= dstRowStride
;
1480 srcRow
+= srcRowStride
;
1484 else if (!ctx
->_ImageTransferState
&&
1485 !srcPacking
->SwapBytes
&&
1486 dstFormat
== &_mesa_texformat_argb8888
&&
1487 srcFormat
== GL_RGBA
&&
1488 baseInternalFormat
== GL_RGBA
&&
1489 srcType
== GL_UNSIGNED_BYTE
&&
1491 /* same as above case, but src data has alpha too */
1492 GLint img
, row
, col
;
1493 /* For some reason, streaming copies to write-combined regions
1494 * are extremely sensitive to the characteristics of how the
1495 * source data is retrieved. By reordering the source reads to
1496 * be in-order, the speed of this operation increases by half.
1497 * Strangely the same isn't required for the RGB path, above.
1499 for (img
= 0; img
< srcDepth
; img
++) {
1500 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1501 srcWidth
, srcFormat
, srcType
);
1502 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1503 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1504 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1505 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1506 + dstYoffset
* dstRowStride
1507 + dstXoffset
* dstFormat
->TexelBytes
;
1508 for (row
= 0; row
< srcHeight
; row
++) {
1509 GLuint
*d4
= (GLuint
*) dstRow
;
1510 for (col
= 0; col
< srcWidth
; col
++) {
1511 d4
[col
] = ((srcRow
[col
* 4 + ACOMP
] << 24) |
1512 (srcRow
[col
* 4 + RCOMP
] << 16) |
1513 (srcRow
[col
* 4 + GCOMP
] << 8) |
1514 (srcRow
[col
* 4 + BCOMP
] << 0));
1516 dstRow
+= dstRowStride
;
1517 srcRow
+= srcRowStride
;
1521 else if (!ctx
->_ImageTransferState
&&
1522 !srcPacking
->SwapBytes
&&
1523 dstFormat
== &_mesa_texformat_argb8888
&&
1524 srcFormat
== GL_RGBA
&&
1525 baseInternalFormat
== GL_RGBA
&&
1526 srcType
== GL_UNSIGNED_BYTE
) {
1528 GLint img
, row
, col
;
1529 for (img
= 0; img
< srcDepth
; img
++) {
1530 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1531 srcWidth
, srcFormat
, srcType
);
1532 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1533 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1534 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1535 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1536 + dstYoffset
* dstRowStride
1537 + dstXoffset
* dstFormat
->TexelBytes
;
1538 for (row
= 0; row
< srcHeight
; row
++) {
1539 for (col
= 0; col
< srcWidth
; col
++) {
1540 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1541 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1542 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1543 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1545 dstRow
+= dstRowStride
;
1546 srcRow
+= srcRowStride
;
1550 else if (!ctx
->_ImageTransferState
&&
1551 (srcType
== GL_UNSIGNED_BYTE
||
1552 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1553 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1554 can_swizzle(baseInternalFormat
) &&
1555 can_swizzle(srcFormat
)) {
1559 /* dstmap - how to swizzle from RGBA to dst format:
1561 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1562 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1563 dstmap
[3] = 3; /* alpha */
1564 dstmap
[2] = 0; /* red */
1565 dstmap
[1] = 1; /* green */
1566 dstmap
[0] = 2; /* blue */
1569 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1570 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1577 _mesa_swizzle_ubyte_image(ctx
, dims
,
1583 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1586 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1591 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1593 dstFormat
->BaseFormat
,
1594 srcWidth
, srcHeight
, srcDepth
,
1595 srcFormat
, srcType
, srcAddr
,
1597 const GLchan
*src
= tempImage
;
1598 GLint img
, row
, col
;
1601 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1602 for (img
= 0; img
< srcDepth
; img
++) {
1603 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1604 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1605 + dstYoffset
* dstRowStride
1606 + dstXoffset
* dstFormat
->TexelBytes
;
1607 for (row
= 0; row
< srcHeight
; row
++) {
1608 GLuint
*dstUI
= (GLuint
*) dstRow
;
1609 if (dstFormat
== &_mesa_texformat_argb8888
) {
1610 for (col
= 0; col
< srcWidth
; col
++) {
1611 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1612 CHAN_TO_UBYTE(src
[RCOMP
]),
1613 CHAN_TO_UBYTE(src
[GCOMP
]),
1614 CHAN_TO_UBYTE(src
[BCOMP
]) );
1619 for (col
= 0; col
< srcWidth
; col
++) {
1620 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1621 CHAN_TO_UBYTE(src
[RCOMP
]),
1622 CHAN_TO_UBYTE(src
[GCOMP
]),
1623 CHAN_TO_UBYTE(src
[BCOMP
]) );
1627 dstRow
+= dstRowStride
;
1630 _mesa_free((void *) tempImage
);
1637 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1639 const GLboolean littleEndian
= _mesa_little_endian();
1641 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1642 ASSERT(dstFormat
->TexelBytes
== 3);
1644 if (!ctx
->_ImageTransferState
&&
1645 !srcPacking
->SwapBytes
&&
1646 baseInternalFormat
== GL_RGB
&&
1647 srcFormat
== GL_BGR
&&
1648 srcType
== GL_UNSIGNED_BYTE
&&
1650 /* simple memcpy path */
1651 memcpy_texture(ctx
, dims
,
1652 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1655 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1656 srcAddr
, srcPacking
);
1658 else if (!ctx
->_ImageTransferState
&&
1659 !srcPacking
->SwapBytes
&&
1660 srcFormat
== GL_RGBA
&&
1661 srcType
== GL_UNSIGNED_BYTE
) {
1662 /* extract RGB from RGBA */
1663 GLint img
, row
, col
;
1664 for (img
= 0; img
< srcDepth
; img
++) {
1665 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1666 srcWidth
, srcFormat
, srcType
);
1667 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1668 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1669 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1670 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1671 + dstYoffset
* dstRowStride
1672 + dstXoffset
* dstFormat
->TexelBytes
;
1673 for (row
= 0; row
< srcHeight
; row
++) {
1674 for (col
= 0; col
< srcWidth
; col
++) {
1675 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1676 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1677 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1679 dstRow
+= dstRowStride
;
1680 srcRow
+= srcRowStride
;
1684 else if (!ctx
->_ImageTransferState
&&
1685 srcType
== GL_UNSIGNED_BYTE
&&
1686 can_swizzle(baseInternalFormat
) &&
1687 can_swizzle(srcFormat
)) {
1691 /* dstmap - how to swizzle from RGBA to dst format:
1696 dstmap
[3] = ONE
; /* ? */
1698 _mesa_swizzle_ubyte_image(ctx
, dims
,
1703 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1704 dstRowStride
, dstImageOffsets
,
1705 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1710 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1712 dstFormat
->BaseFormat
,
1713 srcWidth
, srcHeight
, srcDepth
,
1714 srcFormat
, srcType
, srcAddr
,
1716 const GLchan
*src
= (const GLchan
*) tempImage
;
1717 GLint img
, row
, col
;
1720 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1721 for (img
= 0; img
< srcDepth
; img
++) {
1722 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1723 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1724 + dstYoffset
* dstRowStride
1725 + dstXoffset
* dstFormat
->TexelBytes
;
1726 for (row
= 0; row
< srcHeight
; row
++) {
1729 for (col
= 0; col
< srcWidth
; col
++) {
1730 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1731 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1732 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1737 for (col
= 0; col
< srcWidth
; col
++) {
1738 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1739 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1740 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1745 for (col
= 0; col
< srcWidth
; col
++) {
1746 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1747 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1748 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1752 dstRow
+= dstRowStride
;
1755 _mesa_free((void *) tempImage
);
1762 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1764 const GLboolean littleEndian
= _mesa_little_endian();
1766 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1767 ASSERT(dstFormat
->TexelBytes
== 3);
1769 if (!ctx
->_ImageTransferState
&&
1770 !srcPacking
->SwapBytes
&&
1771 baseInternalFormat
== GL_RGB
&&
1772 srcFormat
== GL_RGB
&&
1773 srcType
== GL_UNSIGNED_BYTE
&&
1775 /* simple memcpy path */
1776 memcpy_texture(ctx
, dims
,
1777 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1780 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1781 srcAddr
, srcPacking
);
1783 else if (!ctx
->_ImageTransferState
&&
1784 !srcPacking
->SwapBytes
&&
1785 srcFormat
== GL_RGBA
&&
1786 srcType
== GL_UNSIGNED_BYTE
) {
1787 /* extract BGR from RGBA */
1789 for (img
= 0; img
< srcDepth
; img
++) {
1790 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1791 srcWidth
, srcFormat
, srcType
);
1792 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1793 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1794 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1795 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1796 + dstYoffset
* dstRowStride
1797 + dstXoffset
* dstFormat
->TexelBytes
;
1798 for (row
= 0; row
< srcHeight
; row
++) {
1799 for (col
= 0; col
< srcWidth
; col
++) {
1800 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1801 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1802 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1804 dstRow
+= dstRowStride
;
1805 srcRow
+= srcRowStride
;
1809 else if (!ctx
->_ImageTransferState
&&
1810 srcType
== GL_UNSIGNED_BYTE
&&
1811 can_swizzle(baseInternalFormat
) &&
1812 can_swizzle(srcFormat
)) {
1816 /* dstmap - how to swizzle from RGBA to dst format:
1821 dstmap
[3] = ONE
; /* ? */
1823 _mesa_swizzle_ubyte_image(ctx
, dims
,
1828 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1829 dstRowStride
, dstImageOffsets
,
1830 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1835 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1837 dstFormat
->BaseFormat
,
1838 srcWidth
, srcHeight
, srcDepth
,
1839 srcFormat
, srcType
, srcAddr
,
1841 const GLchan
*src
= (const GLchan
*) tempImage
;
1842 GLint img
, row
, col
;
1845 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1846 for (img
= 0; img
< srcDepth
; img
++) {
1847 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1848 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1849 + dstYoffset
* dstRowStride
1850 + dstXoffset
* dstFormat
->TexelBytes
;
1851 for (row
= 0; row
< srcHeight
; row
++) {
1852 for (col
= 0; col
< srcWidth
; col
++) {
1853 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1854 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1855 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1858 dstRow
+= dstRowStride
;
1861 _mesa_free((void *) tempImage
);
1868 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1870 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1871 dstFormat
== &_mesa_texformat_argb4444_rev
);
1872 ASSERT(dstFormat
->TexelBytes
== 2);
1874 if (!ctx
->_ImageTransferState
&&
1875 !srcPacking
->SwapBytes
&&
1876 dstFormat
== &_mesa_texformat_argb4444
&&
1877 baseInternalFormat
== GL_RGBA
&&
1878 srcFormat
== GL_BGRA
&&
1879 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1880 /* simple memcpy path */
1881 memcpy_texture(ctx
, dims
,
1882 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1885 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1886 srcAddr
, srcPacking
);
1890 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1892 dstFormat
->BaseFormat
,
1893 srcWidth
, srcHeight
, srcDepth
,
1894 srcFormat
, srcType
, srcAddr
,
1896 const GLchan
*src
= tempImage
;
1897 GLint img
, row
, col
;
1900 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1901 for (img
= 0; img
< srcDepth
; img
++) {
1902 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1903 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1904 + dstYoffset
* dstRowStride
1905 + dstXoffset
* dstFormat
->TexelBytes
;
1906 for (row
= 0; row
< srcHeight
; row
++) {
1907 GLushort
*dstUS
= (GLushort
*) dstRow
;
1908 if (dstFormat
== &_mesa_texformat_argb4444
) {
1909 for (col
= 0; col
< srcWidth
; col
++) {
1910 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1911 CHAN_TO_UBYTE(src
[RCOMP
]),
1912 CHAN_TO_UBYTE(src
[GCOMP
]),
1913 CHAN_TO_UBYTE(src
[BCOMP
]) );
1918 for (col
= 0; col
< srcWidth
; col
++) {
1919 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1920 CHAN_TO_UBYTE(src
[RCOMP
]),
1921 CHAN_TO_UBYTE(src
[GCOMP
]),
1922 CHAN_TO_UBYTE(src
[BCOMP
]) );
1926 dstRow
+= dstRowStride
;
1929 _mesa_free((void *) tempImage
);
1937 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1939 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1940 dstFormat
== &_mesa_texformat_argb1555_rev
);
1941 ASSERT(dstFormat
->TexelBytes
== 2);
1943 if (!ctx
->_ImageTransferState
&&
1944 !srcPacking
->SwapBytes
&&
1945 dstFormat
== &_mesa_texformat_argb1555
&&
1946 baseInternalFormat
== GL_RGBA
&&
1947 srcFormat
== GL_BGRA
&&
1948 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1949 /* simple memcpy path */
1950 memcpy_texture(ctx
, dims
,
1951 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1954 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1955 srcAddr
, srcPacking
);
1959 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1961 dstFormat
->BaseFormat
,
1962 srcWidth
, srcHeight
, srcDepth
,
1963 srcFormat
, srcType
, srcAddr
,
1965 const GLchan
*src
=tempImage
;
1966 GLint img
, row
, col
;
1969 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1970 for (img
= 0; img
< srcDepth
; img
++) {
1971 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1972 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1973 + dstYoffset
* dstRowStride
1974 + dstXoffset
* dstFormat
->TexelBytes
;
1975 for (row
= 0; row
< srcHeight
; row
++) {
1976 GLushort
*dstUS
= (GLushort
*) dstRow
;
1977 if (dstFormat
== &_mesa_texformat_argb1555
) {
1978 for (col
= 0; col
< srcWidth
; col
++) {
1979 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1980 CHAN_TO_UBYTE(src
[RCOMP
]),
1981 CHAN_TO_UBYTE(src
[GCOMP
]),
1982 CHAN_TO_UBYTE(src
[BCOMP
]) );
1987 for (col
= 0; col
< srcWidth
; col
++) {
1988 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1989 CHAN_TO_UBYTE(src
[RCOMP
]),
1990 CHAN_TO_UBYTE(src
[GCOMP
]),
1991 CHAN_TO_UBYTE(src
[BCOMP
]) );
1995 dstRow
+= dstRowStride
;
1998 _mesa_free((void *) tempImage
);
2005 _mesa_texstore_al88(TEXSTORE_PARAMS
)
2007 const GLboolean littleEndian
= _mesa_little_endian();
2009 ASSERT(dstFormat
== &_mesa_texformat_al88
||
2010 dstFormat
== &_mesa_texformat_al88_rev
);
2011 ASSERT(dstFormat
->TexelBytes
== 2);
2013 if (!ctx
->_ImageTransferState
&&
2014 !srcPacking
->SwapBytes
&&
2015 dstFormat
== &_mesa_texformat_al88
&&
2016 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2017 srcFormat
== GL_LUMINANCE_ALPHA
&&
2018 srcType
== GL_UNSIGNED_BYTE
&&
2020 /* simple memcpy path */
2021 memcpy_texture(ctx
, dims
,
2022 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2025 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2026 srcAddr
, srcPacking
);
2028 else if (!ctx
->_ImageTransferState
&&
2030 srcType
== GL_UNSIGNED_BYTE
&&
2031 can_swizzle(baseInternalFormat
) &&
2032 can_swizzle(srcFormat
)) {
2036 /* dstmap - how to swizzle from RGBA to dst format:
2038 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2039 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2047 dstmap
[2] = ZERO
; /* ? */
2048 dstmap
[3] = ONE
; /* ? */
2050 _mesa_swizzle_ubyte_image(ctx
, dims
,
2055 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2056 dstRowStride
, dstImageOffsets
,
2057 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2062 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2064 dstFormat
->BaseFormat
,
2065 srcWidth
, srcHeight
, srcDepth
,
2066 srcFormat
, srcType
, srcAddr
,
2068 const GLchan
*src
= tempImage
;
2069 GLint img
, row
, col
;
2072 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2073 for (img
= 0; img
< srcDepth
; img
++) {
2074 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2075 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2076 + dstYoffset
* dstRowStride
2077 + dstXoffset
* dstFormat
->TexelBytes
;
2078 for (row
= 0; row
< srcHeight
; row
++) {
2079 GLushort
*dstUS
= (GLushort
*) dstRow
;
2080 if (dstFormat
== &_mesa_texformat_al88
) {
2081 for (col
= 0; col
< srcWidth
; col
++) {
2082 /* src[0] is luminance, src[1] is alpha */
2083 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2084 CHAN_TO_UBYTE(src
[0]) );
2089 for (col
= 0; col
< srcWidth
; col
++) {
2090 /* src[0] is luminance, src[1] is alpha */
2091 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2092 CHAN_TO_UBYTE(src
[0]) );
2096 dstRow
+= dstRowStride
;
2099 _mesa_free((void *) tempImage
);
2106 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2108 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2109 ASSERT(dstFormat
->TexelBytes
== 1);
2111 if (!ctx
->_ImageTransferState
&&
2112 !srcPacking
->SwapBytes
&&
2113 baseInternalFormat
== GL_RGB
&&
2114 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2115 /* simple memcpy path */
2116 memcpy_texture(ctx
, dims
,
2117 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2120 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2121 srcAddr
, srcPacking
);
2125 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2127 dstFormat
->BaseFormat
,
2128 srcWidth
, srcHeight
, srcDepth
,
2129 srcFormat
, srcType
, srcAddr
,
2131 const GLchan
*src
= tempImage
;
2132 GLint img
, row
, col
;
2135 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2136 for (img
= 0; img
< srcDepth
; img
++) {
2137 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2138 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2139 + dstYoffset
* dstRowStride
2140 + dstXoffset
* dstFormat
->TexelBytes
;
2141 for (row
= 0; row
< srcHeight
; row
++) {
2142 for (col
= 0; col
< srcWidth
; col
++) {
2143 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2144 CHAN_TO_UBYTE(src
[GCOMP
]),
2145 CHAN_TO_UBYTE(src
[BCOMP
]) );
2148 dstRow
+= dstRowStride
;
2151 _mesa_free((void *) tempImage
);
2158 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2161 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2163 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2164 dstFormat
== &_mesa_texformat_l8
||
2165 dstFormat
== &_mesa_texformat_i8
);
2166 ASSERT(dstFormat
->TexelBytes
== 1);
2168 if (!ctx
->_ImageTransferState
&&
2169 !srcPacking
->SwapBytes
&&
2170 baseInternalFormat
== srcFormat
&&
2171 srcType
== GL_UNSIGNED_BYTE
) {
2172 /* simple memcpy path */
2173 memcpy_texture(ctx
, dims
,
2174 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2177 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2178 srcAddr
, srcPacking
);
2180 else if (!ctx
->_ImageTransferState
&&
2181 srcType
== GL_UNSIGNED_BYTE
&&
2182 can_swizzle(baseInternalFormat
) &&
2183 can_swizzle(srcFormat
)) {
2187 /* dstmap - how to swizzle from RGBA to dst format:
2189 if (dstFormat
== &_mesa_texformat_a8
) {
2195 dstmap
[1] = ZERO
; /* ? */
2196 dstmap
[2] = ZERO
; /* ? */
2197 dstmap
[3] = ONE
; /* ? */
2199 _mesa_swizzle_ubyte_image(ctx
, dims
,
2204 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2205 dstRowStride
, dstImageOffsets
,
2206 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2211 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2213 dstFormat
->BaseFormat
,
2214 srcWidth
, srcHeight
, srcDepth
,
2215 srcFormat
, srcType
, srcAddr
,
2217 const GLchan
*src
= tempImage
;
2218 GLint img
, row
, col
;
2221 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2222 for (img
= 0; img
< srcDepth
; img
++) {
2223 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2224 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2225 + dstYoffset
* dstRowStride
2226 + dstXoffset
* dstFormat
->TexelBytes
;
2227 for (row
= 0; row
< srcHeight
; row
++) {
2228 for (col
= 0; col
< srcWidth
; col
++) {
2229 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2231 dstRow
+= dstRowStride
;
2235 _mesa_free((void *) tempImage
);
2243 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2245 (void) dims
; (void) baseInternalFormat
;
2246 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2247 ASSERT(dstFormat
->TexelBytes
== 1);
2248 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2250 if (!ctx
->_ImageTransferState
&&
2251 !srcPacking
->SwapBytes
&&
2252 srcFormat
== GL_COLOR_INDEX
&&
2253 srcType
== GL_UNSIGNED_BYTE
) {
2254 /* simple memcpy path */
2255 memcpy_texture(ctx
, dims
,
2256 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2259 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2260 srcAddr
, srcPacking
);
2265 for (img
= 0; img
< srcDepth
; img
++) {
2266 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2267 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2268 + dstYoffset
* dstRowStride
2269 + dstXoffset
* dstFormat
->TexelBytes
;
2270 for (row
= 0; row
< srcHeight
; row
++) {
2271 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2272 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2273 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2274 srcType
, src
, srcPacking
,
2275 ctx
->_ImageTransferState
);
2276 dstRow
+= dstRowStride
;
2285 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2288 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2290 const GLboolean littleEndian
= _mesa_little_endian();
2291 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2293 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2294 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2295 ASSERT(dstFormat
->TexelBytes
== 2);
2296 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2297 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2298 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2299 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2300 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2302 /* always just memcpy since no pixel transfer ops apply */
2303 memcpy_texture(ctx
, dims
,
2304 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2307 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2308 srcAddr
, srcPacking
);
2310 /* Check if we need byte swapping */
2311 /* XXX the logic here _might_ be wrong */
2312 if (srcPacking
->SwapBytes
^
2313 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2314 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2317 for (img
= 0; img
< srcDepth
; img
++) {
2318 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2319 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2320 + dstYoffset
* dstRowStride
2321 + dstXoffset
* dstFormat
->TexelBytes
;
2322 for (row
= 0; row
< srcHeight
; row
++) {
2323 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2324 dstRow
+= dstRowStride
;
2334 * Store a combined depth/stencil texture image.
2337 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2339 const GLuint depthScale
= 0xffffff;
2341 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2342 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2343 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2345 if (!ctx
->_ImageTransferState
&&
2346 !srcPacking
->SwapBytes
) {
2348 memcpy_texture(ctx
, dims
,
2349 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2352 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2353 srcAddr
, srcPacking
);
2357 const GLint srcRowStride
2358 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2362 for (img
= 0; img
< srcDepth
; img
++) {
2363 GLuint
*dstRow
= (GLuint
*) dstAddr
2364 + dstImageOffsets
[dstZoffset
+ img
]
2365 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2368 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2369 srcWidth
, srcHeight
,
2372 for (row
= 0; row
< srcHeight
; row
++) {
2373 GLubyte stencil
[MAX_WIDTH
];
2375 /* the 24 depth bits will be in the high position: */
2376 _mesa_unpack_depth_span(ctx
, srcWidth
,
2377 GL_UNSIGNED_INT
, /* dst type */
2378 dstRow
, /* dst addr */
2380 srcType
, src
, srcPacking
);
2381 /* get the 8-bit stencil values */
2382 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2383 GL_UNSIGNED_BYTE
, /* dst type */
2384 stencil
, /* dst addr */
2385 srcType
, src
, srcPacking
,
2386 ctx
->_ImageTransferState
);
2387 /* merge stencil values into depth values */
2388 for (i
= 0; i
< srcWidth
; i
++)
2389 dstRow
[i
] |= stencil
[i
];
2391 src
+= srcRowStride
;
2392 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2402 * Store an image in any of the formats:
2403 * _mesa_texformat_rgba_float32
2404 * _mesa_texformat_rgb_float32
2405 * _mesa_texformat_alpha_float32
2406 * _mesa_texformat_luminance_float32
2407 * _mesa_texformat_luminance_alpha_float32
2408 * _mesa_texformat_intensity_float32
2411 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2413 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2415 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2416 dstFormat
== &_mesa_texformat_rgb_float32
||
2417 dstFormat
== &_mesa_texformat_alpha_float32
||
2418 dstFormat
== &_mesa_texformat_luminance_float32
||
2419 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2420 dstFormat
== &_mesa_texformat_intensity_float32
);
2421 ASSERT(baseInternalFormat
== GL_RGBA
||
2422 baseInternalFormat
== GL_RGB
||
2423 baseInternalFormat
== GL_ALPHA
||
2424 baseInternalFormat
== GL_LUMINANCE
||
2425 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2426 baseInternalFormat
== GL_INTENSITY
);
2427 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2429 if (!ctx
->_ImageTransferState
&&
2430 !srcPacking
->SwapBytes
&&
2431 baseInternalFormat
== srcFormat
&&
2432 srcType
== GL_FLOAT
) {
2433 /* simple memcpy path */
2434 memcpy_texture(ctx
, dims
,
2435 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2438 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2439 srcAddr
, srcPacking
);
2443 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2445 dstFormat
->BaseFormat
,
2446 srcWidth
, srcHeight
, srcDepth
,
2447 srcFormat
, srcType
, srcAddr
,
2449 const GLfloat
*srcRow
= tempImage
;
2454 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2455 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2456 for (img
= 0; img
< srcDepth
; img
++) {
2457 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2458 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2459 + dstYoffset
* dstRowStride
2460 + dstXoffset
* dstFormat
->TexelBytes
;
2461 for (row
= 0; row
< srcHeight
; row
++) {
2462 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2463 dstRow
+= dstRowStride
;
2464 srcRow
+= srcWidth
* components
;
2468 _mesa_free((void *) tempImage
);
2475 * As above, but store 16-bit floats.
2478 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2480 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2482 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2483 dstFormat
== &_mesa_texformat_rgb_float16
||
2484 dstFormat
== &_mesa_texformat_alpha_float16
||
2485 dstFormat
== &_mesa_texformat_luminance_float16
||
2486 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2487 dstFormat
== &_mesa_texformat_intensity_float16
);
2488 ASSERT(baseInternalFormat
== GL_RGBA
||
2489 baseInternalFormat
== GL_RGB
||
2490 baseInternalFormat
== GL_ALPHA
||
2491 baseInternalFormat
== GL_LUMINANCE
||
2492 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2493 baseInternalFormat
== GL_INTENSITY
);
2494 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2496 if (!ctx
->_ImageTransferState
&&
2497 !srcPacking
->SwapBytes
&&
2498 baseInternalFormat
== srcFormat
&&
2499 srcType
== GL_HALF_FLOAT_ARB
) {
2500 /* simple memcpy path */
2501 memcpy_texture(ctx
, dims
,
2502 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2505 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2506 srcAddr
, srcPacking
);
2510 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2512 dstFormat
->BaseFormat
,
2513 srcWidth
, srcHeight
, srcDepth
,
2514 srcFormat
, srcType
, srcAddr
,
2516 const GLfloat
*src
= tempImage
;
2520 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2521 for (img
= 0; img
< srcDepth
; img
++) {
2522 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2523 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2524 + dstYoffset
* dstRowStride
2525 + dstXoffset
* dstFormat
->TexelBytes
;
2526 for (row
= 0; row
< srcHeight
; row
++) {
2527 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2529 for (i
= 0; i
< srcWidth
* components
; i
++) {
2530 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2532 dstRow
+= dstRowStride
;
2533 src
+= srcWidth
* components
;
2537 _mesa_free((void *) tempImage
);
2543 #if FEATURE_EXT_texture_sRGB
2545 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2547 const GLboolean littleEndian
= _mesa_little_endian();
2548 const struct gl_texture_format
*newDstFormat
;
2549 StoreTexImageFunc store
;
2552 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2554 /* reuse normal rgb texstore code */
2556 newDstFormat
= &_mesa_texformat_bgr888
;
2557 store
= _mesa_texstore_bgr888
;
2560 newDstFormat
= &_mesa_texformat_rgb888
;
2561 store
= _mesa_texstore_rgb888
;
2564 k
= store(ctx
, dims
, baseInternalFormat
,
2565 newDstFormat
, dstAddr
,
2566 dstXoffset
, dstYoffset
, dstZoffset
,
2567 dstRowStride
, dstImageOffsets
,
2568 srcWidth
, srcHeight
, srcDepth
,
2570 srcAddr
, srcPacking
);
2576 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2578 const GLboolean littleEndian
= _mesa_little_endian();
2579 const struct gl_texture_format
*newDstFormat
;
2582 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2584 /* reuse normal rgba texstore code */
2586 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2588 newDstFormat
= &_mesa_texformat_rgba8888
;
2590 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2591 newDstFormat
, dstAddr
,
2592 dstXoffset
, dstYoffset
, dstZoffset
,
2593 dstRowStride
, dstImageOffsets
,
2594 srcWidth
, srcHeight
, srcDepth
,
2596 srcAddr
, srcPacking
);
2602 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2604 const struct gl_texture_format
*newDstFormat
;
2607 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2609 newDstFormat
= &_mesa_texformat_l8
;
2611 /* _mesa_textore_a8 handles luminance8 too */
2612 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2613 newDstFormat
, dstAddr
,
2614 dstXoffset
, dstYoffset
, dstZoffset
,
2615 dstRowStride
, dstImageOffsets
,
2616 srcWidth
, srcHeight
, srcDepth
,
2618 srcAddr
, srcPacking
);
2624 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2626 const GLboolean littleEndian
= _mesa_little_endian();
2627 const struct gl_texture_format
*newDstFormat
;
2630 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2632 /* reuse normal luminance/alpha texstore code */
2634 newDstFormat
= &_mesa_texformat_al88
;
2636 newDstFormat
= &_mesa_texformat_al88_rev
;
2638 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2639 newDstFormat
, dstAddr
,
2640 dstXoffset
, dstYoffset
, dstZoffset
,
2641 dstRowStride
, dstImageOffsets
,
2642 srcWidth
, srcHeight
, srcDepth
,
2644 srcAddr
, srcPacking
);
2648 #endif /* FEATURE_EXT_texture_sRGB */
2652 * Check if an unpack PBO is active prior to fetching a texture image.
2653 * If so, do bounds checking and map the buffer into main memory.
2654 * Any errors detected will be recorded.
2655 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2658 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2659 GLsizei width
, GLsizei height
, GLsizei depth
,
2660 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2661 const struct gl_pixelstore_attrib
*unpack
,
2662 const char *funcName
)
2666 if (unpack
->BufferObj
->Name
== 0) {
2670 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2671 format
, type
, pixels
)) {
2672 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2676 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2677 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2679 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2683 return ADD_POINTERS(buf
, pixels
);
2688 * Check if an unpack PBO is active prior to fetching a compressed texture
2690 * If so, do bounds checking and map the buffer into main memory.
2691 * Any errors detected will be recorded.
2692 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2695 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2696 GLsizei imageSize
, const GLvoid
*pixels
,
2697 const struct gl_pixelstore_attrib
*packing
,
2698 const char *funcName
)
2702 if (packing
->BufferObj
->Name
== 0) {
2703 /* not using a PBO - return pointer unchanged */
2706 if ((const GLubyte
*) pixels
+ imageSize
>
2707 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2708 /* out of bounds read! */
2709 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2713 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2714 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2716 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2720 return ADD_POINTERS(buf
, pixels
);
2725 * This function must be called after either of the validate_pbo_*_teximage()
2726 * functions. It unmaps the PBO buffer if it was mapped earlier.
2729 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2730 const struct gl_pixelstore_attrib
*unpack
)
2732 if (unpack
->BufferObj
->Name
) {
2733 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2741 * Adaptor for fetching a GLchan texel from a float-valued texture.
2744 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2745 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2748 ASSERT(texImage
->FetchTexelf
);
2749 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2750 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2751 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2752 /* just one channel */
2753 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2757 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2758 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2759 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2760 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2766 * Adaptor for fetching a float texel from a GLchan-valued texture.
2769 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2770 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2773 ASSERT(texImage
->FetchTexelc
);
2774 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2775 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2776 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2777 /* just one channel */
2778 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2782 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2783 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2784 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2785 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2791 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2794 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2796 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2797 ASSERT(texImage
->TexFormat
);
2801 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2802 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2805 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2806 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2809 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2810 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2816 /* now check if we need to use a float/chan adaptor */
2817 if (!texImage
->FetchTexelc
) {
2818 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
2820 else if (!texImage
->FetchTexelf
) {
2821 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
2825 ASSERT(texImage
->FetchTexelc
);
2826 ASSERT(texImage
->FetchTexelf
);
2831 * Choose the actual storage format for a new texture image.
2832 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2833 * Also set some other texImage fields related to texture compression, etc.
2834 * \param ctx rendering context
2835 * \param texImage the gl_texture_image
2836 * \param dims texture dimensions (1, 2 or 3)
2837 * \param format the user-specified format parameter
2838 * \param type the user-specified type parameter
2839 * \param internalFormat the user-specified internal format hint
2842 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2844 GLenum format
, GLenum type
, GLint internalFormat
)
2846 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2847 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2850 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2852 ASSERT(texImage
->TexFormat
);
2854 _mesa_set_fetch_functions(texImage
, dims
);
2856 if (texImage
->TexFormat
->TexelBytes
== 0) {
2857 /* must be a compressed format */
2858 texImage
->IsCompressed
= GL_TRUE
;
2859 texImage
->CompressedSize
=
2860 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2861 texImage
->Height
, texImage
->Depth
,
2862 texImage
->TexFormat
->MesaFormat
);
2865 /* non-compressed format */
2866 texImage
->IsCompressed
= GL_FALSE
;
2867 texImage
->CompressedSize
= 0;
2874 * This is the software fallback for Driver.TexImage1D()
2875 * and Driver.CopyTexImage1D().
2876 * \sa _mesa_store_teximage2d()
2879 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2880 GLint internalFormat
,
2881 GLint width
, GLint border
,
2882 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2883 const struct gl_pixelstore_attrib
*packing
,
2884 struct gl_texture_object
*texObj
,
2885 struct gl_texture_image
*texImage
)
2887 GLint postConvWidth
= width
;
2891 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2892 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2895 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2897 /* allocate memory */
2898 if (texImage
->IsCompressed
)
2899 sizeInBytes
= texImage
->CompressedSize
;
2901 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2902 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2903 if (!texImage
->Data
) {
2904 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2908 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2909 pixels
, packing
, "glTexImage1D");
2911 /* Note: we check for a NULL image pointer here, _after_ we allocated
2912 * memory for the texture. That's what the GL spec calls for.
2917 const GLint dstRowStride
= 0;
2919 ASSERT(texImage
->TexFormat
->StoreImage
);
2920 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2921 texImage
->TexFormat
,
2923 0, 0, 0, /* dstX/Y/Zoffset */
2925 texImage
->ImageOffsets
,
2927 format
, type
, pixels
, packing
);
2929 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2933 /* GL_SGIS_generate_mipmap */
2934 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2935 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
2938 _mesa_unmap_teximage_pbo(ctx
, packing
);
2943 * This is the software fallback for Driver.TexImage2D()
2944 * and Driver.CopyTexImage2D().
2946 * This function is oriented toward storing images in main memory, rather
2947 * than VRAM. Device driver's can easily plug in their own replacement.
2949 * Note: width and height may be pre-convolved dimensions, but
2950 * texImage->Width and texImage->Height will be post-convolved dimensions.
2953 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2954 GLint internalFormat
,
2955 GLint width
, GLint height
, GLint border
,
2956 GLenum format
, GLenum type
, const void *pixels
,
2957 const struct gl_pixelstore_attrib
*packing
,
2958 struct gl_texture_object
*texObj
,
2959 struct gl_texture_image
*texImage
)
2961 GLint postConvWidth
= width
, postConvHeight
= height
;
2962 GLint texelBytes
, sizeInBytes
;
2965 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2966 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2970 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2972 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2974 /* allocate memory */
2975 if (texImage
->IsCompressed
)
2976 sizeInBytes
= texImage
->CompressedSize
;
2978 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2979 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2980 if (!texImage
->Data
) {
2981 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2985 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2986 pixels
, packing
, "glTexImage2D");
2988 /* Note: we check for a NULL image pointer here, _after_ we allocated
2989 * memory for the texture. That's what the GL spec calls for.
2996 if (texImage
->IsCompressed
) {
2998 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3001 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3003 ASSERT(texImage
->TexFormat
->StoreImage
);
3004 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3005 texImage
->TexFormat
,
3007 0, 0, 0, /* dstX/Y/Zoffset */
3009 texImage
->ImageOffsets
,
3011 format
, type
, pixels
, packing
);
3013 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3017 /* GL_SGIS_generate_mipmap */
3018 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3019 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3022 _mesa_unmap_teximage_pbo(ctx
, packing
);
3028 * This is the software fallback for Driver.TexImage3D()
3029 * and Driver.CopyTexImage3D().
3030 * \sa _mesa_store_teximage2d()
3033 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3034 GLint internalFormat
,
3035 GLint width
, GLint height
, GLint depth
, GLint border
,
3036 GLenum format
, GLenum type
, const void *pixels
,
3037 const struct gl_pixelstore_attrib
*packing
,
3038 struct gl_texture_object
*texObj
,
3039 struct gl_texture_image
*texImage
)
3041 GLint texelBytes
, sizeInBytes
;
3044 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3046 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3048 /* allocate memory */
3049 if (texImage
->IsCompressed
)
3050 sizeInBytes
= texImage
->CompressedSize
;
3052 sizeInBytes
= width
* height
* depth
* texelBytes
;
3053 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3054 if (!texImage
->Data
) {
3055 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3059 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3060 type
, pixels
, packing
, "glTexImage3D");
3062 /* Note: we check for a NULL image pointer here, _after_ we allocated
3063 * memory for the texture. That's what the GL spec calls for.
3070 if (texImage
->IsCompressed
) {
3072 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3075 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3077 ASSERT(texImage
->TexFormat
->StoreImage
);
3078 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3079 texImage
->TexFormat
,
3081 0, 0, 0, /* dstX/Y/Zoffset */
3083 texImage
->ImageOffsets
,
3084 width
, height
, depth
,
3085 format
, type
, pixels
, packing
);
3087 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3091 /* GL_SGIS_generate_mipmap */
3092 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3093 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3096 _mesa_unmap_teximage_pbo(ctx
, packing
);
3103 * This is the software fallback for Driver.TexSubImage1D()
3104 * and Driver.CopyTexSubImage1D().
3107 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3108 GLint xoffset
, GLint width
,
3109 GLenum format
, GLenum type
, const void *pixels
,
3110 const struct gl_pixelstore_attrib
*packing
,
3111 struct gl_texture_object
*texObj
,
3112 struct gl_texture_image
*texImage
)
3114 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3115 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3116 pixels
, packing
, "glTexSubImage1D");
3121 const GLint dstRowStride
= 0;
3123 ASSERT(texImage
->TexFormat
->StoreImage
);
3124 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3125 texImage
->TexFormat
,
3127 xoffset
, 0, 0, /* offsets */
3129 texImage
->ImageOffsets
,
3131 format
, type
, pixels
, packing
);
3133 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3137 /* GL_SGIS_generate_mipmap */
3138 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3139 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3142 _mesa_unmap_teximage_pbo(ctx
, packing
);
3148 * This is the software fallback for Driver.TexSubImage2D()
3149 * and Driver.CopyTexSubImage2D().
3152 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3153 GLint xoffset
, GLint yoffset
,
3154 GLint width
, GLint height
,
3155 GLenum format
, GLenum type
, const void *pixels
,
3156 const struct gl_pixelstore_attrib
*packing
,
3157 struct gl_texture_object
*texObj
,
3158 struct gl_texture_image
*texImage
)
3160 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3161 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3162 pixels
, packing
, "glTexSubImage2D");
3167 GLint dstRowStride
= 0;
3169 if (texImage
->IsCompressed
) {
3170 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3174 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3176 ASSERT(texImage
->TexFormat
->StoreImage
);
3177 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3178 texImage
->TexFormat
,
3180 xoffset
, yoffset
, 0,
3182 texImage
->ImageOffsets
,
3184 format
, type
, pixels
, packing
);
3186 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3190 /* GL_SGIS_generate_mipmap */
3191 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3192 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3195 _mesa_unmap_teximage_pbo(ctx
, packing
);
3200 * This is the software fallback for Driver.TexSubImage3D().
3201 * and Driver.CopyTexSubImage3D().
3204 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3205 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3206 GLint width
, GLint height
, GLint depth
,
3207 GLenum format
, GLenum type
, const void *pixels
,
3208 const struct gl_pixelstore_attrib
*packing
,
3209 struct gl_texture_object
*texObj
,
3210 struct gl_texture_image
*texImage
)
3212 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3213 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3214 type
, pixels
, packing
,
3222 if (texImage
->IsCompressed
) {
3223 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3227 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3229 ASSERT(texImage
->TexFormat
->StoreImage
);
3230 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3231 texImage
->TexFormat
,
3233 xoffset
, yoffset
, zoffset
,
3235 texImage
->ImageOffsets
,
3236 width
, height
, depth
,
3237 format
, type
, pixels
, packing
);
3239 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3243 /* GL_SGIS_generate_mipmap */
3244 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3245 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3248 _mesa_unmap_teximage_pbo(ctx
, packing
);
3253 * Fallback for Driver.CompressedTexImage1D()
3256 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3257 GLint internalFormat
,
3258 GLint width
, GLint border
,
3259 GLsizei imageSize
, const GLvoid
*data
,
3260 struct gl_texture_object
*texObj
,
3261 struct gl_texture_image
*texImage
)
3263 /* this space intentionally left blank */
3265 (void) target
; (void) level
;
3266 (void) internalFormat
;
3267 (void) width
; (void) border
;
3268 (void) imageSize
; (void) data
;
3276 * Fallback for Driver.CompressedTexImage2D()
3279 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3280 GLint internalFormat
,
3281 GLint width
, GLint height
, GLint border
,
3282 GLsizei imageSize
, const GLvoid
*data
,
3283 struct gl_texture_object
*texObj
,
3284 struct gl_texture_image
*texImage
)
3286 (void) width
; (void) height
; (void) border
;
3288 /* This is pretty simple, basically just do a memcpy without worrying
3289 * about the usual image unpacking or image transfer operations.
3293 ASSERT(texImage
->Width
> 0);
3294 ASSERT(texImage
->Height
> 0);
3295 ASSERT(texImage
->Depth
== 1);
3296 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3298 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3300 /* allocate storage */
3301 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3302 if (!texImage
->Data
) {
3303 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3307 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3309 "glCompressedTexImage2D");
3314 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3315 MEMCPY(texImage
->Data
, data
, imageSize
);
3317 /* GL_SGIS_generate_mipmap */
3318 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3319 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3322 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3328 * Fallback for Driver.CompressedTexImage3D()
3331 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3332 GLint internalFormat
,
3333 GLint width
, GLint height
, GLint depth
,
3335 GLsizei imageSize
, const GLvoid
*data
,
3336 struct gl_texture_object
*texObj
,
3337 struct gl_texture_image
*texImage
)
3339 /* this space intentionally left blank */
3341 (void) target
; (void) level
;
3342 (void) internalFormat
;
3343 (void) width
; (void) height
; (void) depth
;
3345 (void) imageSize
; (void) data
;
3353 * Fallback for Driver.CompressedTexSubImage1D()
3356 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3358 GLint xoffset
, GLsizei width
,
3360 GLsizei imageSize
, const GLvoid
*data
,
3361 struct gl_texture_object
*texObj
,
3362 struct gl_texture_image
*texImage
)
3364 /* there are no compressed 1D texture formats yet */
3366 (void) target
; (void) level
;
3367 (void) xoffset
; (void) width
;
3369 (void) imageSize
; (void) data
;
3376 * Fallback for Driver.CompressedTexSubImage2D()
3379 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3381 GLint xoffset
, GLint yoffset
,
3382 GLsizei width
, GLsizei height
,
3384 GLsizei imageSize
, const GLvoid
*data
,
3385 struct gl_texture_object
*texObj
,
3386 struct gl_texture_image
*texImage
)
3388 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3392 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3396 /* these should have been caught sooner */
3397 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3398 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3399 ASSERT((xoffset
& 3) == 0);
3400 ASSERT((yoffset
& 3) == 0);
3402 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3403 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3405 "glCompressedTexSubImage2D");
3409 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3410 src
= (const GLubyte
*) data
;
3412 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3413 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3414 texImage
->TexFormat
->MesaFormat
,
3416 (GLubyte
*) texImage
->Data
);
3418 bytesPerRow
= srcRowStride
;
3421 for (i
= 0; i
< rows
; i
++) {
3422 MEMCPY(dest
, src
, bytesPerRow
);
3423 dest
+= destRowStride
;
3424 src
+= srcRowStride
;
3427 /* GL_SGIS_generate_mipmap */
3428 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3429 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3432 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3437 * Fallback for Driver.CompressedTexSubImage3D()
3440 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3442 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3443 GLsizei width
, GLsizei height
, GLsizei depth
,
3445 GLsizei imageSize
, const GLvoid
*data
,
3446 struct gl_texture_object
*texObj
,
3447 struct gl_texture_image
*texImage
)
3449 /* there are no compressed 3D texture formats yet */
3451 (void) target
; (void) level
;
3452 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3453 (void) width
; (void) height
; (void) depth
;
3455 (void) imageSize
; (void) data
;
3463 #if FEATURE_EXT_texture_sRGB
3466 * Test if given texture image is an sRGB format.
3469 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3471 switch (texImage
->TexFormat
->MesaFormat
) {
3472 case MESA_FORMAT_SRGB8
:
3473 case MESA_FORMAT_SRGBA8
:
3474 case MESA_FORMAT_SL8
:
3475 case MESA_FORMAT_SLA8
:
3482 #endif /* FEATURE_EXT_texture_sRGB */
3486 * This is the software fallback for Driver.GetTexImage().
3487 * All error checking will have been done before this routine is called.
3490 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3491 GLenum format
, GLenum type
, GLvoid
*pixels
,
3492 struct gl_texture_object
*texObj
,
3493 struct gl_texture_image
*texImage
)
3495 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3497 if (ctx
->Pack
.BufferObj
->Name
) {
3498 /* Packing texture image into a PBO.
3499 * Map the (potentially) VRAM-based buffer into our process space so
3500 * we can write into it with the code below.
3501 * A hardware driver might use a sophisticated blit to move the
3502 * texture data to the PBO if the PBO is in VRAM along with the texture.
3504 GLubyte
*buf
= (GLubyte
*)
3505 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3506 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3508 /* buffer is already mapped - that's an error */
3509 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3512 /* <pixels> was an offset into the PBO.
3513 * Now make it a real, client-side pointer inside the mapped region.
3515 pixels
= ADD_POINTERS(buf
, pixels
);
3523 const GLint width
= texImage
->Width
;
3524 const GLint height
= texImage
->Height
;
3525 const GLint depth
= texImage
->Depth
;
3527 for (img
= 0; img
< depth
; img
++) {
3528 for (row
= 0; row
< height
; row
++) {
3529 /* compute destination address in client memory */
3530 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3531 width
, height
, format
, type
,
3535 if (format
== GL_COLOR_INDEX
) {
3536 GLuint indexRow
[MAX_WIDTH
];
3538 /* Can't use FetchTexel here because that returns RGBA */
3539 if (texImage
->TexFormat
->IndexBits
== 8) {
3540 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3541 src
+= width
* (img
* texImage
->Height
+ row
);
3542 for (col
= 0; col
< width
; col
++) {
3543 indexRow
[col
] = src
[col
];
3546 else if (texImage
->TexFormat
->IndexBits
== 16) {
3547 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3548 src
+= width
* (img
* texImage
->Height
+ row
);
3549 for (col
= 0; col
< width
; col
++) {
3550 indexRow
[col
] = src
[col
];
3555 "Color index problem in _mesa_GetTexImage");
3557 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3558 indexRow
, &ctx
->Pack
,
3559 0 /* no image transfer */);
3561 else if (format
== GL_DEPTH_COMPONENT
) {
3562 GLfloat depthRow
[MAX_WIDTH
];
3564 for (col
= 0; col
< width
; col
++) {
3565 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3568 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3569 depthRow
, &ctx
->Pack
);
3571 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3572 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3573 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3574 src
+= width
* row
+ width
* height
* img
;
3575 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3576 if (ctx
->Pack
.SwapBytes
) {
3577 _mesa_swap4((GLuint
*) dest
, width
);
3580 else if (format
== GL_YCBCR_MESA
) {
3581 /* No pixel transfer */
3582 const GLint rowstride
= texImage
->RowStride
;
3584 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3585 width
* sizeof(GLushort
));
3586 /* check for byte swapping */
3587 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3588 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3589 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3590 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3591 if (!ctx
->Pack
.SwapBytes
)
3592 _mesa_swap2((GLushort
*) dest
, width
);
3594 else if (ctx
->Pack
.SwapBytes
) {
3595 _mesa_swap2((GLushort
*) dest
, width
);
3598 #if FEATURE_EXT_texture_sRGB
3599 else if (is_srgb_teximage(texImage
)) {
3600 /* no pixel transfer and no non-linear to linear conversion */
3601 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3602 const GLint rowstride
= comps
* texImage
->RowStride
;
3604 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3605 comps
* width
* sizeof(GLubyte
));
3607 #endif /* FEATURE_EXT_texture_sRGB */
3609 /* general case: convert row to RGBA format */
3610 GLfloat rgba
[MAX_WIDTH
][4];
3612 for (col
= 0; col
< width
; col
++) {
3613 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3614 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3615 rgba
[col
][RCOMP
] = 0.0;
3616 rgba
[col
][GCOMP
] = 0.0;
3617 rgba
[col
][BCOMP
] = 0.0;
3619 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3620 rgba
[col
][GCOMP
] = 0.0;
3621 rgba
[col
][BCOMP
] = 0.0;
3622 rgba
[col
][ACOMP
] = 1.0;
3624 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3625 rgba
[col
][GCOMP
] = 0.0;
3626 rgba
[col
][BCOMP
] = 0.0;
3628 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3629 rgba
[col
][GCOMP
] = 0.0;
3630 rgba
[col
][BCOMP
] = 0.0;
3631 rgba
[col
][ACOMP
] = 1.0;
3634 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3636 &ctx
->Pack
, 0x0 /*image xfer ops*/);
3642 if (ctx
->Pack
.BufferObj
->Name
) {
3643 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3644 ctx
->Pack
.BufferObj
);
3651 * This is the software fallback for Driver.GetCompressedTexImage().
3652 * All error checking will have been done before this routine is called.
3655 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3657 const struct gl_texture_object
*texObj
,
3658 const struct gl_texture_image
*texImage
)
3662 if (ctx
->Pack
.BufferObj
->Name
) {
3663 /* pack texture image into a PBO */
3665 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3666 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3667 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3668 "glGetCompressedTexImage(invalid PBO access)");
3671 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3673 ctx
->Pack
.BufferObj
);
3675 /* buffer is already mapped - that's an error */
3676 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3677 "glGetCompressedTexImage(PBO is mapped)");
3680 img
= ADD_POINTERS(buf
, img
);
3687 /* don't use texImage->CompressedSize since that may be padded out */
3688 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3690 texImage
->TexFormat
->MesaFormat
);
3692 /* just memcpy, no pixelstore or pixel transfer */
3693 _mesa_memcpy(img
, texImage
->Data
, size
);
3695 if (ctx
->Pack
.BufferObj
->Name
) {
3696 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3697 ctx
->Pack
.BufferObj
);