2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
65 #include "texcompress.h"
66 #include "texformat.h"
79 * Return GL_TRUE if the given image format is one that be converted
80 * to another format by swizzling.
83 can_swizzle(GLenum logicalBaseFormat
)
85 switch (logicalBaseFormat
) {
88 case GL_LUMINANCE_ALPHA
:
122 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
123 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
124 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
125 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
128 static const struct {
131 GLubyte from_rgba
[6];
132 } mappings
[MAX_IDX
] =
142 MAP4(ZERO
, ZERO
, ZERO
, 0),
173 MAP4(0, ZERO
, ZERO
, ONE
),
179 MAP4(ZERO
, 0, ZERO
, ONE
),
185 MAP4(ZERO
, ZERO
, 0, ONE
),
211 * Convert a GL image format enum to an IDX_* value (see above).
214 get_map_idx(GLenum value
)
217 case GL_LUMINANCE
: return IDX_LUMINANCE
;
218 case GL_ALPHA
: return IDX_ALPHA
;
219 case GL_INTENSITY
: return IDX_INTENSITY
;
220 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
221 case GL_RGB
: return IDX_RGB
;
222 case GL_RGBA
: return IDX_RGBA
;
223 case GL_RED
: return IDX_RED
;
224 case GL_GREEN
: return IDX_GREEN
;
225 case GL_BLUE
: return IDX_BLUE
;
226 case GL_BGR
: return IDX_BGR
;
227 case GL_BGRA
: return IDX_BGRA
;
228 case GL_ABGR_EXT
: return IDX_ABGR
;
230 _mesa_problem(NULL
, "Unexpected inFormat");
237 * When promoting texture formats (see below) we need to compute the
238 * mapping of dest components back to source components.
239 * This function does that.
240 * \param inFormat the incoming format of the texture
241 * \param outFormat the final texture format
242 * \return map[6] a full 6-component map
245 compute_component_mapping(GLenum inFormat
, GLenum outFormat
,
248 const int inFmt
= get_map_idx(inFormat
);
249 const int outFmt
= get_map_idx(outFormat
);
250 const GLubyte
*in2rgba
= mappings
[inFmt
].to_rgba
;
251 const GLubyte
*rgba2out
= mappings
[outFmt
].from_rgba
;
254 for (i
= 0; i
< 4; i
++)
255 map
[i
] = in2rgba
[rgba2out
[i
]];
261 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
262 inFormat, _mesa_lookup_enum_by_nr(inFormat),
263 outFormat, _mesa_lookup_enum_by_nr(outFormat),
274 #if !FEATURE_convolve
276 _mesa_adjust_image_for_convolution(GLcontext
*ctx
, GLuint dims
,
277 GLsizei
*srcWidth
, GLsizei
*srcHeight
)
285 * Make a temporary (color) texture image with GLfloat components.
286 * Apply all needed pixel unpacking and pixel transfer operations.
287 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
288 * Suppose the user specifies GL_LUMINANCE as the internal texture format
289 * but the graphics hardware doesn't support luminance textures. So, might
290 * use an RGB hardware format instead.
291 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
293 * \param ctx the rendering context
294 * \param dims image dimensions: 1, 2 or 3
295 * \param logicalBaseFormat basic texture derived from the user's
296 * internal texture format value
297 * \param textureBaseFormat the actual basic format of the texture
298 * \param srcWidth source image width
299 * \param srcHeight source image height
300 * \param srcDepth source image depth
301 * \param srcFormat source image format
302 * \param srcType source image type
303 * \param srcAddr source image address
304 * \param srcPacking source image pixel packing
305 * \return resulting image with format = textureBaseFormat and type = GLfloat.
308 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
309 GLenum logicalBaseFormat
,
310 GLenum textureBaseFormat
,
311 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
312 GLenum srcFormat
, GLenum srcType
,
313 const GLvoid
*srcAddr
,
314 const struct gl_pixelstore_attrib
*srcPacking
)
316 GLuint transferOps
= ctx
->_ImageTransferState
;
319 ASSERT(dims
>= 1 && dims
<= 3);
321 ASSERT(logicalBaseFormat
== GL_RGBA
||
322 logicalBaseFormat
== GL_RGB
||
323 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
324 logicalBaseFormat
== GL_LUMINANCE
||
325 logicalBaseFormat
== GL_ALPHA
||
326 logicalBaseFormat
== GL_INTENSITY
||
327 logicalBaseFormat
== GL_COLOR_INDEX
||
328 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
330 ASSERT(textureBaseFormat
== GL_RGBA
||
331 textureBaseFormat
== GL_RGB
||
332 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
333 textureBaseFormat
== GL_LUMINANCE
||
334 textureBaseFormat
== GL_ALPHA
||
335 textureBaseFormat
== GL_INTENSITY
||
336 textureBaseFormat
== GL_COLOR_INDEX
||
337 textureBaseFormat
== GL_DEPTH_COMPONENT
);
339 /* conventional color image */
341 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
342 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
343 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
344 /* need image convolution */
345 const GLuint preConvTransferOps
346 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
347 const GLuint postConvTransferOps
348 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
350 GLint convWidth
, convHeight
;
353 /* pre-convolution image buffer (3D) */
354 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
355 * 4 * sizeof(GLfloat
));
359 /* post-convolution image buffer (2D) */
360 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
361 * 4 * sizeof(GLfloat
));
363 _mesa_free(tempImage
);
367 /* loop over 3D image slices */
368 for (img
= 0; img
< srcDepth
; img
++) {
369 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
371 /* unpack and do transfer ops up to convolution */
372 for (row
= 0; row
< srcHeight
; row
++) {
373 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
374 srcAddr
, srcWidth
, srcHeight
,
375 srcFormat
, srcType
, img
, row
, 0);
376 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
377 srcFormat
, srcType
, src
,
383 /* size after optional convolution */
384 convWidth
= srcWidth
;
385 convHeight
= srcHeight
;
390 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
392 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
393 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
396 if (ctx
->Pixel
.Convolution2DEnabled
) {
397 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
401 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
402 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
408 /* do post-convolution transfer and pack into tempImage */
410 const GLint logComponents
411 = _mesa_components_in_format(logicalBaseFormat
);
412 const GLfloat
*src
= convImage
;
413 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
414 for (row
= 0; row
< convHeight
; row
++) {
415 _mesa_pack_rgba_span_float(ctx
, convWidth
,
416 (GLfloat (*)[4]) src
,
417 logicalBaseFormat
, GL_FLOAT
,
418 dst
, &ctx
->DefaultPacking
,
419 postConvTransferOps
);
420 src
+= convWidth
* 4;
421 dst
+= convWidth
* logComponents
;
424 } /* loop over 3D image slices */
426 _mesa_free(convImage
);
428 /* might need these below */
429 srcWidth
= convWidth
;
430 srcHeight
= convHeight
;
434 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
435 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
436 srcWidth
, srcFormat
, srcType
);
440 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
441 * components
* sizeof(GLfloat
));
446 for (img
= 0; img
< srcDepth
; img
++) {
448 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
452 for (row
= 0; row
< srcHeight
; row
++) {
453 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
454 dst
, srcFormat
, srcType
, src
,
455 srcPacking
, transferOps
);
456 dst
+= srcWidth
* components
;
462 if (logicalBaseFormat
!= textureBaseFormat
) {
464 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
465 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
470 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
471 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
472 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
474 /* The actual texture format should have at least as many components
475 * as the logical texture format.
477 ASSERT(texComponents
>= logComponents
);
479 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
480 * texComponents
* sizeof(GLfloat
));
482 _mesa_free(tempImage
);
486 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
488 n
= srcWidth
* srcHeight
* srcDepth
;
489 for (i
= 0; i
< n
; i
++) {
491 for (k
= 0; k
< texComponents
; k
++) {
494 newImage
[i
* texComponents
+ k
] = 0.0F
;
496 newImage
[i
* texComponents
+ k
] = 1.0F
;
498 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
502 _mesa_free(tempImage
);
503 tempImage
= newImage
;
511 * Make a temporary (color) texture image with GLchan components.
512 * Apply all needed pixel unpacking and pixel transfer operations.
513 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
514 * Suppose the user specifies GL_LUMINANCE as the internal texture format
515 * but the graphics hardware doesn't support luminance textures. So, might
516 * use an RGB hardware format instead.
517 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
519 * \param ctx the rendering context
520 * \param dims image dimensions: 1, 2 or 3
521 * \param logicalBaseFormat basic texture derived from the user's
522 * internal texture format value
523 * \param textureBaseFormat the actual basic format of the texture
524 * \param srcWidth source image width
525 * \param srcHeight source image height
526 * \param srcDepth source image depth
527 * \param srcFormat source image format
528 * \param srcType source image type
529 * \param srcAddr source image address
530 * \param srcPacking source image pixel packing
531 * \return resulting image with format = textureBaseFormat and type = GLchan.
534 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
535 GLenum logicalBaseFormat
,
536 GLenum textureBaseFormat
,
537 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
538 GLenum srcFormat
, GLenum srcType
,
539 const GLvoid
*srcAddr
,
540 const struct gl_pixelstore_attrib
*srcPacking
)
542 GLuint transferOps
= ctx
->_ImageTransferState
;
543 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
544 GLboolean freeSrcImage
= GL_FALSE
;
546 GLchan
*tempImage
, *dst
;
548 ASSERT(dims
>= 1 && dims
<= 3);
550 ASSERT(logicalBaseFormat
== GL_RGBA
||
551 logicalBaseFormat
== GL_RGB
||
552 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
553 logicalBaseFormat
== GL_LUMINANCE
||
554 logicalBaseFormat
== GL_ALPHA
||
555 logicalBaseFormat
== GL_INTENSITY
);
557 ASSERT(textureBaseFormat
== GL_RGBA
||
558 textureBaseFormat
== GL_RGB
||
559 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
560 textureBaseFormat
== GL_LUMINANCE
||
561 textureBaseFormat
== GL_ALPHA
||
562 textureBaseFormat
== GL_INTENSITY
);
565 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
566 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
567 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
568 /* get convolved image */
569 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
572 srcWidth
, srcHeight
, srcDepth
,
574 srcAddr
, srcPacking
);
577 /* the convolved image is our new source image */
579 srcFormat
= logicalBaseFormat
;
581 srcPacking
= &ctx
->DefaultPacking
;
582 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
584 freeSrcImage
= GL_TRUE
;
588 /* unpack and transfer the source image */
589 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
590 * components
* sizeof(GLchan
));
595 for (img
= 0; img
< srcDepth
; img
++) {
596 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
600 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
604 for (row
= 0; row
< srcHeight
; row
++) {
605 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
606 srcFormat
, srcType
, src
, srcPacking
,
608 dst
+= srcWidth
* components
;
613 /* If we made a temporary image for convolution, free it here */
615 _mesa_free((void *) srcAddr
);
618 if (logicalBaseFormat
!= textureBaseFormat
) {
619 /* one more conversion step */
620 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
621 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
626 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
627 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
628 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
630 /* The actual texture format should have at least as many components
631 * as the logical texture format.
633 ASSERT(texComponents
>= logComponents
);
635 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
636 * texComponents
* sizeof(GLchan
));
638 _mesa_free(tempImage
);
642 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
644 n
= srcWidth
* srcHeight
* srcDepth
;
645 for (i
= 0; i
< n
; i
++) {
647 for (k
= 0; k
< texComponents
; k
++) {
650 newImage
[i
* texComponents
+ k
] = 0;
652 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
654 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
658 _mesa_free(tempImage
);
659 tempImage
= newImage
;
667 * Copy GLubyte pixels from <src> to <dst> with swizzling.
668 * \param dst destination pixels
669 * \param dstComponents number of color components in destination pixels
670 * \param src source pixels
671 * \param srcComponents number of color components in source pixels
672 * \param map the swizzle mapping. map[X] says where to find the X component
673 * in the source image's pixels. For example, if the source image
674 * is GL_BGRA and X = red, map[0] yields 2.
675 * \param count number of pixels to copy/swizzle.
678 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
679 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
681 #define SWZ_CPY(dst, src, count, dstComps, srcComps) \
684 for (i = 0; i < count; i++) { \
686 if (srcComps == 4) { \
687 COPY_4UBV(tmp, src); \
690 for (j = 0; j < srcComps; j++) { \
695 for (j = 0; j < dstComps; j++) { \
696 dst[j] = tmp[map[j]]; \
707 ASSERT(srcComponents
<= 4);
708 ASSERT(dstComponents
<= 4);
710 switch (dstComponents
) {
712 switch (srcComponents
) {
714 SWZ_CPY(dst
, src
, count
, 4, 4);
717 SWZ_CPY(dst
, src
, count
, 4, 3);
720 SWZ_CPY(dst
, src
, count
, 4, 2);
723 SWZ_CPY(dst
, src
, count
, 4, 1);
730 switch (srcComponents
) {
732 SWZ_CPY(dst
, src
, count
, 3, 4);
735 SWZ_CPY(dst
, src
, count
, 3, 3);
738 SWZ_CPY(dst
, src
, count
, 3, 2);
741 SWZ_CPY(dst
, src
, count
, 3, 1);
748 switch (srcComponents
) {
750 SWZ_CPY(dst
, src
, count
, 2, 4);
753 SWZ_CPY(dst
, src
, count
, 2, 3);
756 SWZ_CPY(dst
, src
, count
, 2, 2);
759 SWZ_CPY(dst
, src
, count
, 2, 1);
766 switch (srcComponents
) {
768 SWZ_CPY(dst
, src
, count
, 1, 4);
771 SWZ_CPY(dst
, src
, count
, 1, 3);
774 SWZ_CPY(dst
, src
, count
, 1, 2);
777 SWZ_CPY(dst
, src
, count
, 1, 1);
791 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
792 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
794 /* Deal with the _REV input types:
796 static const GLubyte
*
797 type_mapping( GLenum srcType
)
800 case GL_UNSIGNED_BYTE
:
802 case GL_UNSIGNED_INT_8_8_8_8
:
803 return _mesa_little_endian() ? map_3210
: map_identity
;
804 case GL_UNSIGNED_INT_8_8_8_8_REV
:
805 return _mesa_little_endian() ? map_identity
: map_3210
;
811 /* Mapping required if input type is
813 static const GLubyte
*
814 byteswap_mapping( GLboolean swapBytes
,
821 case GL_UNSIGNED_BYTE
:
823 case GL_UNSIGNED_INT_8_8_8_8
:
824 case GL_UNSIGNED_INT_8_8_8_8_REV
:
834 * Transfer a GLubyte texture image with component swizzling.
837 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
842 GLenum baseInternalFormat
,
844 const GLubyte
*rgba2dst
,
845 GLuint dstComponents
,
848 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
850 const GLuint
*dstImageOffsets
,
852 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
853 const GLvoid
*srcAddr
,
854 const struct gl_pixelstore_attrib
*srcPacking
)
856 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
857 const GLubyte
*srctype2ubyte
, *swap
;
858 GLubyte map
[4], src2base
[6], base2rgba
[6];
860 const GLint srcRowStride
=
861 _mesa_image_row_stride(srcPacking
, srcWidth
,
862 srcFormat
, GL_UNSIGNED_BYTE
);
863 const GLint srcImageStride
864 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
866 const GLubyte
*srcImage
867 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
868 srcWidth
, srcHeight
, srcFormat
,
869 GL_UNSIGNED_BYTE
, 0, 0, 0);
873 /* Translate from src->baseInternal->GL_RGBA->dst. This will
874 * correctly deal with RGBA->RGB->RGBA conversions where the final
875 * A value must be 0xff regardless of the incoming alpha values.
877 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
878 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
879 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
880 srctype2ubyte
= type_mapping(srcType
);
883 for (i
= 0; i
< 4; i
++)
884 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
886 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
888 if (srcComponents
== dstComponents
&&
889 srcRowStride
== dstRowStride
&&
890 srcRowStride
== srcWidth
* srcComponents
&&
892 /* 1 and 2D images only */
893 GLubyte
*dstImage
= (GLubyte
*) dstAddr
894 + dstYoffset
* dstRowStride
895 + dstXoffset
* dstComponents
;
896 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
897 srcWidth
* srcHeight
);
901 for (img
= 0; img
< srcDepth
; img
++) {
902 const GLubyte
*srcRow
= srcImage
;
903 GLubyte
*dstRow
= (GLubyte
*) dstAddr
904 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
905 + dstYoffset
* dstRowStride
906 + dstXoffset
* dstComponents
;
907 for (row
= 0; row
< srcHeight
; row
++) {
908 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
909 dstRow
+= dstRowStride
;
910 srcRow
+= srcRowStride
;
912 srcImage
+= srcImageStride
;
919 * Teximage storage routine for when a simple memcpy will do.
920 * No pixel transfer operations or special texel encodings allowed.
921 * 1D, 2D and 3D images supported.
924 memcpy_texture(GLcontext
*ctx
,
926 const struct gl_texture_format
*dstFormat
,
928 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
930 const GLuint
*dstImageOffsets
,
931 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
932 GLenum srcFormat
, GLenum srcType
,
933 const GLvoid
*srcAddr
,
934 const struct gl_pixelstore_attrib
*srcPacking
)
936 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
938 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
939 srcWidth
, srcHeight
, srcFormat
, srcType
);
940 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
941 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
942 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
945 /* XXX update/re-enable for dstImageOffsets array */
946 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
947 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
948 GLubyte
*dstImage
= (GLubyte
*) dstAddr
949 + dstZoffset
* dstImageStride
950 + dstYoffset
* dstRowStride
951 + dstXoffset
* dstFormat
->TexelBytes
;
953 if (dstRowStride
== srcRowStride
&&
954 dstRowStride
== bytesPerRow
&&
955 ((dstImageStride
== srcImageStride
&&
956 dstImageStride
== bytesPerImage
) ||
959 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
964 for (img
= 0; img
< srcDepth
; img
++) {
965 const GLubyte
*srcRow
= srcImage
;
966 GLubyte
*dstRow
= dstImage
;
967 for (row
= 0; row
< srcHeight
; row
++) {
968 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
969 dstRow
+= dstRowStride
;
970 srcRow
+= srcRowStride
;
972 srcImage
+= srcImageStride
;
973 dstImage
+= dstImageStride
;
979 for (img
= 0; img
< srcDepth
; img
++) {
980 const GLubyte
*srcRow
= srcImage
;
981 GLubyte
*dstRow
= (GLubyte
*) dstAddr
982 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
983 + dstYoffset
* dstRowStride
984 + dstXoffset
* dstFormat
->TexelBytes
;
985 for (row
= 0; row
< srcHeight
; row
++) {
986 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
987 dstRow
+= dstRowStride
;
988 srcRow
+= srcRowStride
;
990 srcImage
+= srcImageStride
;
997 * Store an image in any of the formats:
998 * _mesa_texformat_rgba
999 * _mesa_texformat_rgb
1000 * _mesa_texformat_alpha
1001 * _mesa_texformat_luminance
1002 * _mesa_texformat_luminance_alpha
1003 * _mesa_texformat_intensity
1007 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
1009 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1011 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
1012 dstFormat
== &_mesa_texformat_rgb
||
1013 dstFormat
== &_mesa_texformat_alpha
||
1014 dstFormat
== &_mesa_texformat_luminance
||
1015 dstFormat
== &_mesa_texformat_luminance_alpha
||
1016 dstFormat
== &_mesa_texformat_intensity
);
1017 ASSERT(baseInternalFormat
== GL_RGBA
||
1018 baseInternalFormat
== GL_RGB
||
1019 baseInternalFormat
== GL_ALPHA
||
1020 baseInternalFormat
== GL_LUMINANCE
||
1021 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1022 baseInternalFormat
== GL_INTENSITY
);
1023 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
1025 if (!ctx
->_ImageTransferState
&&
1026 !srcPacking
->SwapBytes
&&
1027 baseInternalFormat
== srcFormat
&&
1028 srcType
== CHAN_TYPE
) {
1029 /* simple memcpy path */
1030 memcpy_texture(ctx
, dims
,
1031 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1034 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1035 srcAddr
, srcPacking
);
1037 else if (!ctx
->_ImageTransferState
&&
1038 !srcPacking
->SwapBytes
&&
1039 dstFormat
== &_mesa_texformat_rgb
&&
1040 srcFormat
== GL_RGBA
&&
1041 srcType
== CHAN_TYPE
) {
1042 /* extract RGB from RGBA */
1043 GLint img
, row
, col
;
1044 for (img
= 0; img
< srcDepth
; img
++) {
1045 GLchan
*dstImage
= (GLchan
*)
1046 ((GLubyte
*) dstAddr
1047 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1048 + dstYoffset
* dstRowStride
1049 + dstXoffset
* dstFormat
->TexelBytes
);
1051 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1052 srcWidth
, srcFormat
, srcType
);
1053 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
1054 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1055 GLchan
*dstRow
= dstImage
;
1056 for (row
= 0; row
< srcHeight
; row
++) {
1057 for (col
= 0; col
< srcWidth
; col
++) {
1058 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
1059 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
1060 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
1062 dstRow
+= dstRowStride
/ sizeof(GLchan
);
1063 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
1067 else if (!ctx
->_ImageTransferState
&&
1068 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
1069 (srcType
== GL_UNSIGNED_BYTE
||
1070 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1071 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1072 can_swizzle(baseInternalFormat
) &&
1073 can_swizzle(srcFormat
)) {
1075 const GLubyte
*dstmap
;
1078 /* dstmap - how to swizzle from RGBA to dst format:
1080 if (dstFormat
== &_mesa_texformat_rgba
) {
1081 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1084 else if (dstFormat
== &_mesa_texformat_rgb
) {
1085 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1088 else if (dstFormat
== &_mesa_texformat_alpha
) {
1089 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1092 else if (dstFormat
== &_mesa_texformat_luminance
) {
1093 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1096 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1097 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1100 else if (dstFormat
== &_mesa_texformat_intensity
) {
1101 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1105 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1109 _mesa_swizzle_ubyte_image(ctx
, dims
,
1114 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1115 dstRowStride
, dstImageOffsets
,
1116 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1121 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1123 dstFormat
->BaseFormat
,
1124 srcWidth
, srcHeight
, srcDepth
,
1125 srcFormat
, srcType
, srcAddr
,
1127 const GLchan
*src
= tempImage
;
1132 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1133 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1134 for (img
= 0; img
< srcDepth
; img
++) {
1135 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1136 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1137 + dstYoffset
* dstRowStride
1138 + dstXoffset
* dstFormat
->TexelBytes
;
1139 for (row
= 0; row
< srcHeight
; row
++) {
1140 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1141 dstRow
+= dstRowStride
;
1142 src
+= srcWidth
* components
;
1146 _mesa_free((void *) tempImage
);
1153 * Store a 32-bit integer depth component texture image.
1156 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1158 const GLuint depthScale
= 0xffffffff;
1160 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1161 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1163 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
1164 ctx
->Pixel
.DepthBias
== 0.0f
&&
1165 !srcPacking
->SwapBytes
&&
1166 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1167 srcFormat
== GL_DEPTH_COMPONENT
&&
1168 srcType
== GL_UNSIGNED_INT
) {
1169 /* simple memcpy path */
1170 memcpy_texture(ctx
, dims
,
1171 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1174 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1175 srcAddr
, srcPacking
);
1180 for (img
= 0; img
< srcDepth
; img
++) {
1181 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1182 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1183 + dstYoffset
* dstRowStride
1184 + dstXoffset
* dstFormat
->TexelBytes
;
1185 for (row
= 0; row
< srcHeight
; row
++) {
1186 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1187 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1188 _mesa_unpack_depth_span(ctx
, srcWidth
,
1189 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1190 depthScale
, srcType
, src
, srcPacking
);
1191 dstRow
+= dstRowStride
;
1201 * Store a 16-bit integer depth component texture image.
1204 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1206 const GLuint depthScale
= 0xffff;
1208 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1209 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1211 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
1212 ctx
->Pixel
.DepthBias
== 0.0f
&&
1213 !srcPacking
->SwapBytes
&&
1214 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1215 srcFormat
== GL_DEPTH_COMPONENT
&&
1216 srcType
== GL_UNSIGNED_SHORT
) {
1217 /* simple memcpy path */
1218 memcpy_texture(ctx
, dims
,
1219 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1222 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1223 srcAddr
, srcPacking
);
1228 for (img
= 0; img
< srcDepth
; img
++) {
1229 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1230 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1231 + dstYoffset
* dstRowStride
1232 + dstXoffset
* dstFormat
->TexelBytes
;
1233 for (row
= 0; row
< srcHeight
; row
++) {
1234 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1235 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1236 GLushort
*dst16
= (GLushort
*) dstRow
;
1237 _mesa_unpack_depth_span(ctx
, srcWidth
,
1238 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1239 srcType
, src
, srcPacking
);
1240 dstRow
+= dstRowStride
;
1249 * Store an rgb565 or rgb565_rev texture image.
1252 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1254 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1255 dstFormat
== &_mesa_texformat_rgb565_rev
);
1256 ASSERT(dstFormat
->TexelBytes
== 2);
1258 if (!ctx
->_ImageTransferState
&&
1259 !srcPacking
->SwapBytes
&&
1260 dstFormat
== &_mesa_texformat_rgb565
&&
1261 baseInternalFormat
== GL_RGB
&&
1262 srcFormat
== GL_RGB
&&
1263 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1264 /* simple memcpy path */
1265 memcpy_texture(ctx
, dims
,
1266 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1269 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1270 srcAddr
, srcPacking
);
1272 else if (!ctx
->_ImageTransferState
&&
1273 !srcPacking
->SwapBytes
&&
1274 baseInternalFormat
== GL_RGB
&&
1275 srcFormat
== GL_RGB
&&
1276 srcType
== GL_UNSIGNED_BYTE
&&
1278 /* do optimized tex store */
1279 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1280 srcFormat
, srcType
);
1281 const GLubyte
*src
= (const GLubyte
*)
1282 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1283 srcFormat
, srcType
, 0, 0, 0);
1284 GLubyte
*dst
= (GLubyte
*) dstAddr
1285 + dstYoffset
* dstRowStride
1286 + dstXoffset
* dstFormat
->TexelBytes
;
1288 for (row
= 0; row
< srcHeight
; row
++) {
1289 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1290 GLushort
*dstUS
= (GLushort
*) dst
;
1291 /* check for byteswapped format */
1292 if (dstFormat
== &_mesa_texformat_rgb565
) {
1293 for (col
= 0; col
< srcWidth
; col
++) {
1294 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1299 for (col
= 0; col
< srcWidth
; col
++) {
1300 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1304 dst
+= dstRowStride
;
1305 src
+= srcRowStride
;
1310 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1312 dstFormat
->BaseFormat
,
1313 srcWidth
, srcHeight
, srcDepth
,
1314 srcFormat
, srcType
, srcAddr
,
1316 const GLchan
*src
= tempImage
;
1317 GLint img
, row
, col
;
1320 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1321 for (img
= 0; img
< srcDepth
; img
++) {
1322 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1323 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1324 + dstYoffset
* dstRowStride
1325 + dstXoffset
* dstFormat
->TexelBytes
;
1326 for (row
= 0; row
< srcHeight
; row
++) {
1327 GLushort
*dstUS
= (GLushort
*) dstRow
;
1328 /* check for byteswapped format */
1329 if (dstFormat
== &_mesa_texformat_rgb565
) {
1330 for (col
= 0; col
< srcWidth
; col
++) {
1331 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1332 CHAN_TO_UBYTE(src
[GCOMP
]),
1333 CHAN_TO_UBYTE(src
[BCOMP
]) );
1338 for (col
= 0; col
< srcWidth
; col
++) {
1339 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1340 CHAN_TO_UBYTE(src
[GCOMP
]),
1341 CHAN_TO_UBYTE(src
[BCOMP
]) );
1345 dstRow
+= dstRowStride
;
1348 _mesa_free((void *) tempImage
);
1355 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1358 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1360 const GLboolean littleEndian
= _mesa_little_endian();
1362 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1363 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1364 ASSERT(dstFormat
->TexelBytes
== 4);
1366 if (!ctx
->_ImageTransferState
&&
1367 !srcPacking
->SwapBytes
&&
1368 dstFormat
== &_mesa_texformat_rgba8888
&&
1369 baseInternalFormat
== GL_RGBA
&&
1370 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1371 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1372 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1373 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1374 /* simple memcpy path */
1375 memcpy_texture(ctx
, dims
,
1376 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1379 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1380 srcAddr
, srcPacking
);
1382 else if (!ctx
->_ImageTransferState
&&
1383 !srcPacking
->SwapBytes
&&
1384 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1385 baseInternalFormat
== GL_RGBA
&&
1386 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1387 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1388 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1389 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1390 /* simple memcpy path */
1391 memcpy_texture(ctx
, dims
,
1392 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1395 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1396 srcAddr
, srcPacking
);
1398 else if (!ctx
->_ImageTransferState
&&
1399 (srcType
== GL_UNSIGNED_BYTE
||
1400 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1401 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1402 can_swizzle(baseInternalFormat
) &&
1403 can_swizzle(srcFormat
)) {
1407 /* dstmap - how to swizzle from RGBA to dst format:
1409 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1410 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1423 _mesa_swizzle_ubyte_image(ctx
, dims
,
1428 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1429 dstRowStride
, dstImageOffsets
,
1430 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1435 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1437 dstFormat
->BaseFormat
,
1438 srcWidth
, srcHeight
, srcDepth
,
1439 srcFormat
, srcType
, srcAddr
,
1441 const GLchan
*src
= tempImage
;
1442 GLint img
, row
, col
;
1445 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1446 for (img
= 0; img
< srcDepth
; img
++) {
1447 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1448 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1449 + dstYoffset
* dstRowStride
1450 + dstXoffset
* dstFormat
->TexelBytes
;
1451 for (row
= 0; row
< srcHeight
; row
++) {
1452 GLuint
*dstUI
= (GLuint
*) dstRow
;
1453 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1454 for (col
= 0; col
< srcWidth
; col
++) {
1455 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1456 CHAN_TO_UBYTE(src
[GCOMP
]),
1457 CHAN_TO_UBYTE(src
[BCOMP
]),
1458 CHAN_TO_UBYTE(src
[ACOMP
]) );
1463 for (col
= 0; col
< srcWidth
; col
++) {
1464 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1465 CHAN_TO_UBYTE(src
[GCOMP
]),
1466 CHAN_TO_UBYTE(src
[BCOMP
]),
1467 CHAN_TO_UBYTE(src
[ACOMP
]) );
1471 dstRow
+= dstRowStride
;
1474 _mesa_free((void *) tempImage
);
1481 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1483 const GLboolean littleEndian
= _mesa_little_endian();
1485 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1486 dstFormat
== &_mesa_texformat_argb8888_rev
);
1487 ASSERT(dstFormat
->TexelBytes
== 4);
1489 if (!ctx
->_ImageTransferState
&&
1490 !srcPacking
->SwapBytes
&&
1491 dstFormat
== &_mesa_texformat_argb8888
&&
1492 baseInternalFormat
== GL_RGBA
&&
1493 srcFormat
== GL_BGRA
&&
1494 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1495 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1496 /* simple memcpy path (little endian) */
1497 memcpy_texture(ctx
, dims
,
1498 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1501 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1502 srcAddr
, srcPacking
);
1504 else if (!ctx
->_ImageTransferState
&&
1505 !srcPacking
->SwapBytes
&&
1506 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1507 baseInternalFormat
== GL_RGBA
&&
1508 srcFormat
== GL_BGRA
&&
1509 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1510 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1511 /* simple memcpy path (big endian) */
1512 memcpy_texture(ctx
, dims
,
1513 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1516 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1517 srcAddr
, srcPacking
);
1519 else if (!ctx
->_ImageTransferState
&&
1520 !srcPacking
->SwapBytes
&&
1521 dstFormat
== &_mesa_texformat_argb8888
&&
1522 srcFormat
== GL_RGB
&&
1523 (baseInternalFormat
== GL_RGBA
||
1524 baseInternalFormat
== GL_RGB
) &&
1525 srcType
== GL_UNSIGNED_BYTE
) {
1527 for (img
= 0; img
< srcDepth
; img
++) {
1528 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1529 srcWidth
, srcFormat
, srcType
);
1530 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1531 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1532 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1533 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1534 + dstYoffset
* dstRowStride
1535 + dstXoffset
* dstFormat
->TexelBytes
;
1536 for (row
= 0; row
< srcHeight
; row
++) {
1537 GLuint
*d4
= (GLuint
*) dstRow
;
1538 for (col
= 0; col
< srcWidth
; col
++) {
1539 d4
[col
] = ((0xff << 24) |
1540 (srcRow
[col
* 3 + RCOMP
] << 16) |
1541 (srcRow
[col
* 3 + GCOMP
] << 8) |
1542 (srcRow
[col
* 3 + BCOMP
] << 0));
1544 dstRow
+= dstRowStride
;
1545 srcRow
+= srcRowStride
;
1549 else if (!ctx
->_ImageTransferState
&&
1550 !srcPacking
->SwapBytes
&&
1551 dstFormat
== &_mesa_texformat_argb8888
&&
1552 srcFormat
== GL_RGBA
&&
1553 baseInternalFormat
== GL_RGBA
&&
1554 srcType
== GL_UNSIGNED_BYTE
&&
1556 /* same as above case, but src data has alpha too */
1557 GLint img
, row
, col
;
1558 /* For some reason, streaming copies to write-combined regions
1559 * are extremely sensitive to the characteristics of how the
1560 * source data is retrieved. By reordering the source reads to
1561 * be in-order, the speed of this operation increases by half.
1562 * Strangely the same isn't required for the RGB path, above.
1564 for (img
= 0; img
< srcDepth
; img
++) {
1565 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1566 srcWidth
, srcFormat
, srcType
);
1567 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1568 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1569 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1570 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1571 + dstYoffset
* dstRowStride
1572 + dstXoffset
* dstFormat
->TexelBytes
;
1573 for (row
= 0; row
< srcHeight
; row
++) {
1574 GLuint
*d4
= (GLuint
*) dstRow
;
1575 for (col
= 0; col
< srcWidth
; col
++) {
1576 d4
[col
] = ((srcRow
[col
* 4 + ACOMP
] << 24) |
1577 (srcRow
[col
* 4 + RCOMP
] << 16) |
1578 (srcRow
[col
* 4 + GCOMP
] << 8) |
1579 (srcRow
[col
* 4 + BCOMP
] << 0));
1581 dstRow
+= dstRowStride
;
1582 srcRow
+= srcRowStride
;
1586 else if (!ctx
->_ImageTransferState
&&
1587 !srcPacking
->SwapBytes
&&
1588 dstFormat
== &_mesa_texformat_argb8888
&&
1589 srcFormat
== GL_RGBA
&&
1590 baseInternalFormat
== GL_RGBA
&&
1591 srcType
== GL_UNSIGNED_BYTE
) {
1593 GLint img
, row
, col
;
1594 for (img
= 0; img
< srcDepth
; img
++) {
1595 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1596 srcWidth
, srcFormat
, srcType
);
1597 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1598 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1599 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1600 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1601 + dstYoffset
* dstRowStride
1602 + dstXoffset
* dstFormat
->TexelBytes
;
1603 for (row
= 0; row
< srcHeight
; row
++) {
1604 for (col
= 0; col
< srcWidth
; col
++) {
1605 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1606 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1607 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1608 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1610 dstRow
+= dstRowStride
;
1611 srcRow
+= srcRowStride
;
1615 else if (!ctx
->_ImageTransferState
&&
1616 (srcType
== GL_UNSIGNED_BYTE
||
1617 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1618 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1619 can_swizzle(baseInternalFormat
) &&
1620 can_swizzle(srcFormat
)) {
1624 /* dstmap - how to swizzle from RGBA to dst format:
1626 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1627 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1628 dstmap
[3] = 3; /* alpha */
1629 dstmap
[2] = 0; /* red */
1630 dstmap
[1] = 1; /* green */
1631 dstmap
[0] = 2; /* blue */
1634 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1635 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1642 _mesa_swizzle_ubyte_image(ctx
, dims
,
1648 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1651 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1656 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1658 dstFormat
->BaseFormat
,
1659 srcWidth
, srcHeight
, srcDepth
,
1660 srcFormat
, srcType
, srcAddr
,
1662 const GLchan
*src
= tempImage
;
1663 GLint img
, row
, col
;
1666 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1667 for (img
= 0; img
< srcDepth
; img
++) {
1668 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1669 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1670 + dstYoffset
* dstRowStride
1671 + dstXoffset
* dstFormat
->TexelBytes
;
1672 for (row
= 0; row
< srcHeight
; row
++) {
1673 GLuint
*dstUI
= (GLuint
*) dstRow
;
1674 if (dstFormat
== &_mesa_texformat_argb8888
) {
1675 for (col
= 0; col
< srcWidth
; col
++) {
1676 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1677 CHAN_TO_UBYTE(src
[RCOMP
]),
1678 CHAN_TO_UBYTE(src
[GCOMP
]),
1679 CHAN_TO_UBYTE(src
[BCOMP
]) );
1684 for (col
= 0; col
< srcWidth
; col
++) {
1685 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1686 CHAN_TO_UBYTE(src
[RCOMP
]),
1687 CHAN_TO_UBYTE(src
[GCOMP
]),
1688 CHAN_TO_UBYTE(src
[BCOMP
]) );
1692 dstRow
+= dstRowStride
;
1695 _mesa_free((void *) tempImage
);
1702 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1704 const GLboolean littleEndian
= _mesa_little_endian();
1706 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1707 ASSERT(dstFormat
->TexelBytes
== 3);
1709 if (!ctx
->_ImageTransferState
&&
1710 !srcPacking
->SwapBytes
&&
1711 baseInternalFormat
== GL_RGB
&&
1712 srcFormat
== GL_BGR
&&
1713 srcType
== GL_UNSIGNED_BYTE
&&
1715 /* simple memcpy path */
1716 memcpy_texture(ctx
, dims
,
1717 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1720 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1721 srcAddr
, srcPacking
);
1723 else if (!ctx
->_ImageTransferState
&&
1724 !srcPacking
->SwapBytes
&&
1725 srcFormat
== GL_RGBA
&&
1726 srcType
== GL_UNSIGNED_BYTE
) {
1727 /* extract RGB from RGBA */
1728 GLint img
, row
, col
;
1729 for (img
= 0; img
< srcDepth
; img
++) {
1730 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1731 srcWidth
, srcFormat
, srcType
);
1732 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1733 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1734 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1735 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1736 + dstYoffset
* dstRowStride
1737 + dstXoffset
* dstFormat
->TexelBytes
;
1738 for (row
= 0; row
< srcHeight
; row
++) {
1739 for (col
= 0; col
< srcWidth
; col
++) {
1740 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1741 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1742 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1744 dstRow
+= dstRowStride
;
1745 srcRow
+= srcRowStride
;
1749 else if (!ctx
->_ImageTransferState
&&
1750 srcType
== GL_UNSIGNED_BYTE
&&
1751 can_swizzle(baseInternalFormat
) &&
1752 can_swizzle(srcFormat
)) {
1756 /* dstmap - how to swizzle from RGBA to dst format:
1761 dstmap
[3] = ONE
; /* ? */
1763 _mesa_swizzle_ubyte_image(ctx
, dims
,
1768 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1769 dstRowStride
, dstImageOffsets
,
1770 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1775 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1777 dstFormat
->BaseFormat
,
1778 srcWidth
, srcHeight
, srcDepth
,
1779 srcFormat
, srcType
, srcAddr
,
1781 const GLchan
*src
= (const GLchan
*) tempImage
;
1782 GLint img
, row
, col
;
1785 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1786 for (img
= 0; img
< srcDepth
; img
++) {
1787 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1788 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1789 + dstYoffset
* dstRowStride
1790 + dstXoffset
* dstFormat
->TexelBytes
;
1791 for (row
= 0; row
< srcHeight
; row
++) {
1794 for (col
= 0; col
< srcWidth
; col
++) {
1795 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1796 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1797 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1802 for (col
= 0; col
< srcWidth
; col
++) {
1803 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1804 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1805 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1810 for (col
= 0; col
< srcWidth
; col
++) {
1811 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1812 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1813 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1817 dstRow
+= dstRowStride
;
1820 _mesa_free((void *) tempImage
);
1827 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1829 const GLboolean littleEndian
= _mesa_little_endian();
1831 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1832 ASSERT(dstFormat
->TexelBytes
== 3);
1834 if (!ctx
->_ImageTransferState
&&
1835 !srcPacking
->SwapBytes
&&
1836 baseInternalFormat
== GL_RGB
&&
1837 srcFormat
== GL_RGB
&&
1838 srcType
== GL_UNSIGNED_BYTE
&&
1840 /* simple memcpy path */
1841 memcpy_texture(ctx
, dims
,
1842 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1845 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1846 srcAddr
, srcPacking
);
1848 else if (!ctx
->_ImageTransferState
&&
1849 !srcPacking
->SwapBytes
&&
1850 srcFormat
== GL_RGBA
&&
1851 srcType
== GL_UNSIGNED_BYTE
) {
1852 /* extract BGR from RGBA */
1854 for (img
= 0; img
< srcDepth
; img
++) {
1855 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1856 srcWidth
, srcFormat
, srcType
);
1857 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1858 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1859 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1860 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1861 + dstYoffset
* dstRowStride
1862 + dstXoffset
* dstFormat
->TexelBytes
;
1863 for (row
= 0; row
< srcHeight
; row
++) {
1864 for (col
= 0; col
< srcWidth
; col
++) {
1865 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1866 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1867 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1869 dstRow
+= dstRowStride
;
1870 srcRow
+= srcRowStride
;
1874 else if (!ctx
->_ImageTransferState
&&
1875 srcType
== GL_UNSIGNED_BYTE
&&
1876 can_swizzle(baseInternalFormat
) &&
1877 can_swizzle(srcFormat
)) {
1881 /* dstmap - how to swizzle from RGBA to dst format:
1886 dstmap
[3] = ONE
; /* ? */
1888 _mesa_swizzle_ubyte_image(ctx
, dims
,
1893 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1894 dstRowStride
, dstImageOffsets
,
1895 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1900 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1902 dstFormat
->BaseFormat
,
1903 srcWidth
, srcHeight
, srcDepth
,
1904 srcFormat
, srcType
, srcAddr
,
1906 const GLchan
*src
= (const GLchan
*) tempImage
;
1907 GLint img
, row
, col
;
1910 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1911 for (img
= 0; img
< srcDepth
; img
++) {
1912 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1913 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1914 + dstYoffset
* dstRowStride
1915 + dstXoffset
* dstFormat
->TexelBytes
;
1916 for (row
= 0; row
< srcHeight
; row
++) {
1917 for (col
= 0; col
< srcWidth
; col
++) {
1918 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1919 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1920 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1923 dstRow
+= dstRowStride
;
1926 _mesa_free((void *) tempImage
);
1933 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1935 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1936 dstFormat
== &_mesa_texformat_argb4444_rev
);
1937 ASSERT(dstFormat
->TexelBytes
== 2);
1939 if (!ctx
->_ImageTransferState
&&
1940 !srcPacking
->SwapBytes
&&
1941 dstFormat
== &_mesa_texformat_argb4444
&&
1942 baseInternalFormat
== GL_RGBA
&&
1943 srcFormat
== GL_BGRA
&&
1944 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1945 /* simple memcpy path */
1946 memcpy_texture(ctx
, dims
,
1947 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1950 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1951 srcAddr
, srcPacking
);
1955 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1957 dstFormat
->BaseFormat
,
1958 srcWidth
, srcHeight
, srcDepth
,
1959 srcFormat
, srcType
, srcAddr
,
1961 const GLchan
*src
= tempImage
;
1962 GLint img
, row
, col
;
1965 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1966 for (img
= 0; img
< srcDepth
; img
++) {
1967 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1968 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1969 + dstYoffset
* dstRowStride
1970 + dstXoffset
* dstFormat
->TexelBytes
;
1971 for (row
= 0; row
< srcHeight
; row
++) {
1972 GLushort
*dstUS
= (GLushort
*) dstRow
;
1973 if (dstFormat
== &_mesa_texformat_argb4444
) {
1974 for (col
= 0; col
< srcWidth
; col
++) {
1975 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1976 CHAN_TO_UBYTE(src
[RCOMP
]),
1977 CHAN_TO_UBYTE(src
[GCOMP
]),
1978 CHAN_TO_UBYTE(src
[BCOMP
]) );
1983 for (col
= 0; col
< srcWidth
; col
++) {
1984 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1985 CHAN_TO_UBYTE(src
[RCOMP
]),
1986 CHAN_TO_UBYTE(src
[GCOMP
]),
1987 CHAN_TO_UBYTE(src
[BCOMP
]) );
1991 dstRow
+= dstRowStride
;
1994 _mesa_free((void *) tempImage
);
2002 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
2004 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
2005 dstFormat
== &_mesa_texformat_argb1555_rev
);
2006 ASSERT(dstFormat
->TexelBytes
== 2);
2008 if (!ctx
->_ImageTransferState
&&
2009 !srcPacking
->SwapBytes
&&
2010 dstFormat
== &_mesa_texformat_argb1555
&&
2011 baseInternalFormat
== GL_RGBA
&&
2012 srcFormat
== GL_BGRA
&&
2013 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
2014 /* simple memcpy path */
2015 memcpy_texture(ctx
, dims
,
2016 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2019 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2020 srcAddr
, srcPacking
);
2024 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2026 dstFormat
->BaseFormat
,
2027 srcWidth
, srcHeight
, srcDepth
,
2028 srcFormat
, srcType
, srcAddr
,
2030 const GLchan
*src
=tempImage
;
2031 GLint img
, row
, col
;
2034 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2035 for (img
= 0; img
< srcDepth
; img
++) {
2036 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2037 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2038 + dstYoffset
* dstRowStride
2039 + dstXoffset
* dstFormat
->TexelBytes
;
2040 for (row
= 0; row
< srcHeight
; row
++) {
2041 GLushort
*dstUS
= (GLushort
*) dstRow
;
2042 if (dstFormat
== &_mesa_texformat_argb1555
) {
2043 for (col
= 0; col
< srcWidth
; col
++) {
2044 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
2045 CHAN_TO_UBYTE(src
[RCOMP
]),
2046 CHAN_TO_UBYTE(src
[GCOMP
]),
2047 CHAN_TO_UBYTE(src
[BCOMP
]) );
2052 for (col
= 0; col
< srcWidth
; col
++) {
2053 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
2054 CHAN_TO_UBYTE(src
[RCOMP
]),
2055 CHAN_TO_UBYTE(src
[GCOMP
]),
2056 CHAN_TO_UBYTE(src
[BCOMP
]) );
2060 dstRow
+= dstRowStride
;
2063 _mesa_free((void *) tempImage
);
2070 _mesa_texstore_al88(TEXSTORE_PARAMS
)
2072 const GLboolean littleEndian
= _mesa_little_endian();
2074 ASSERT(dstFormat
== &_mesa_texformat_al88
||
2075 dstFormat
== &_mesa_texformat_al88_rev
);
2076 ASSERT(dstFormat
->TexelBytes
== 2);
2078 if (!ctx
->_ImageTransferState
&&
2079 !srcPacking
->SwapBytes
&&
2080 dstFormat
== &_mesa_texformat_al88
&&
2081 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2082 srcFormat
== GL_LUMINANCE_ALPHA
&&
2083 srcType
== GL_UNSIGNED_BYTE
&&
2085 /* simple memcpy path */
2086 memcpy_texture(ctx
, dims
,
2087 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2090 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2091 srcAddr
, srcPacking
);
2093 else if (!ctx
->_ImageTransferState
&&
2095 srcType
== GL_UNSIGNED_BYTE
&&
2096 can_swizzle(baseInternalFormat
) &&
2097 can_swizzle(srcFormat
)) {
2101 /* dstmap - how to swizzle from RGBA to dst format:
2103 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2104 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2112 dstmap
[2] = ZERO
; /* ? */
2113 dstmap
[3] = ONE
; /* ? */
2115 _mesa_swizzle_ubyte_image(ctx
, dims
,
2120 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2121 dstRowStride
, dstImageOffsets
,
2122 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2127 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2129 dstFormat
->BaseFormat
,
2130 srcWidth
, srcHeight
, srcDepth
,
2131 srcFormat
, srcType
, srcAddr
,
2133 const GLchan
*src
= tempImage
;
2134 GLint img
, row
, col
;
2137 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2138 for (img
= 0; img
< srcDepth
; img
++) {
2139 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2140 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2141 + dstYoffset
* dstRowStride
2142 + dstXoffset
* dstFormat
->TexelBytes
;
2143 for (row
= 0; row
< srcHeight
; row
++) {
2144 GLushort
*dstUS
= (GLushort
*) dstRow
;
2145 if (dstFormat
== &_mesa_texformat_al88
) {
2146 for (col
= 0; col
< srcWidth
; col
++) {
2147 /* src[0] is luminance, src[1] is alpha */
2148 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2149 CHAN_TO_UBYTE(src
[0]) );
2154 for (col
= 0; col
< srcWidth
; col
++) {
2155 /* src[0] is luminance, src[1] is alpha */
2156 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2157 CHAN_TO_UBYTE(src
[0]) );
2161 dstRow
+= dstRowStride
;
2164 _mesa_free((void *) tempImage
);
2171 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2173 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2174 ASSERT(dstFormat
->TexelBytes
== 1);
2176 if (!ctx
->_ImageTransferState
&&
2177 !srcPacking
->SwapBytes
&&
2178 baseInternalFormat
== GL_RGB
&&
2179 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2180 /* simple memcpy path */
2181 memcpy_texture(ctx
, dims
,
2182 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2185 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2186 srcAddr
, srcPacking
);
2190 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2192 dstFormat
->BaseFormat
,
2193 srcWidth
, srcHeight
, srcDepth
,
2194 srcFormat
, srcType
, srcAddr
,
2196 const GLchan
*src
= tempImage
;
2197 GLint img
, row
, col
;
2200 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2201 for (img
= 0; img
< srcDepth
; img
++) {
2202 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2203 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2204 + dstYoffset
* dstRowStride
2205 + dstXoffset
* dstFormat
->TexelBytes
;
2206 for (row
= 0; row
< srcHeight
; row
++) {
2207 for (col
= 0; col
< srcWidth
; col
++) {
2208 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2209 CHAN_TO_UBYTE(src
[GCOMP
]),
2210 CHAN_TO_UBYTE(src
[BCOMP
]) );
2213 dstRow
+= dstRowStride
;
2216 _mesa_free((void *) tempImage
);
2223 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2226 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2228 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2229 dstFormat
== &_mesa_texformat_l8
||
2230 dstFormat
== &_mesa_texformat_i8
);
2231 ASSERT(dstFormat
->TexelBytes
== 1);
2233 if (!ctx
->_ImageTransferState
&&
2234 !srcPacking
->SwapBytes
&&
2235 baseInternalFormat
== srcFormat
&&
2236 srcType
== GL_UNSIGNED_BYTE
) {
2237 /* simple memcpy path */
2238 memcpy_texture(ctx
, dims
,
2239 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2242 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2243 srcAddr
, srcPacking
);
2245 else if (!ctx
->_ImageTransferState
&&
2246 srcType
== GL_UNSIGNED_BYTE
&&
2247 can_swizzle(baseInternalFormat
) &&
2248 can_swizzle(srcFormat
)) {
2252 /* dstmap - how to swizzle from RGBA to dst format:
2254 if (dstFormat
== &_mesa_texformat_a8
) {
2260 dstmap
[1] = ZERO
; /* ? */
2261 dstmap
[2] = ZERO
; /* ? */
2262 dstmap
[3] = ONE
; /* ? */
2264 _mesa_swizzle_ubyte_image(ctx
, dims
,
2269 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2270 dstRowStride
, dstImageOffsets
,
2271 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2276 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2278 dstFormat
->BaseFormat
,
2279 srcWidth
, srcHeight
, srcDepth
,
2280 srcFormat
, srcType
, srcAddr
,
2282 const GLchan
*src
= tempImage
;
2283 GLint img
, row
, col
;
2286 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2287 for (img
= 0; img
< srcDepth
; img
++) {
2288 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2289 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2290 + dstYoffset
* dstRowStride
2291 + dstXoffset
* dstFormat
->TexelBytes
;
2292 for (row
= 0; row
< srcHeight
; row
++) {
2293 for (col
= 0; col
< srcWidth
; col
++) {
2294 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2296 dstRow
+= dstRowStride
;
2300 _mesa_free((void *) tempImage
);
2308 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2310 (void) dims
; (void) baseInternalFormat
;
2311 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2312 ASSERT(dstFormat
->TexelBytes
== 1);
2313 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2315 if (!ctx
->_ImageTransferState
&&
2316 !srcPacking
->SwapBytes
&&
2317 srcFormat
== GL_COLOR_INDEX
&&
2318 srcType
== GL_UNSIGNED_BYTE
) {
2319 /* simple memcpy path */
2320 memcpy_texture(ctx
, dims
,
2321 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2324 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2325 srcAddr
, srcPacking
);
2330 for (img
= 0; img
< srcDepth
; img
++) {
2331 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2332 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2333 + dstYoffset
* dstRowStride
2334 + dstXoffset
* dstFormat
->TexelBytes
;
2335 for (row
= 0; row
< srcHeight
; row
++) {
2336 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2337 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2338 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2339 srcType
, src
, srcPacking
,
2340 ctx
->_ImageTransferState
);
2341 dstRow
+= dstRowStride
;
2350 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2353 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2355 const GLboolean littleEndian
= _mesa_little_endian();
2356 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2358 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2359 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2360 ASSERT(dstFormat
->TexelBytes
== 2);
2361 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2362 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2363 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2364 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2365 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2367 /* always just memcpy since no pixel transfer ops apply */
2368 memcpy_texture(ctx
, dims
,
2369 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2372 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2373 srcAddr
, srcPacking
);
2375 /* Check if we need byte swapping */
2376 /* XXX the logic here _might_ be wrong */
2377 if (srcPacking
->SwapBytes
^
2378 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2379 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2382 for (img
= 0; img
< srcDepth
; img
++) {
2383 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2384 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2385 + dstYoffset
* dstRowStride
2386 + dstXoffset
* dstFormat
->TexelBytes
;
2387 for (row
= 0; row
< srcHeight
; row
++) {
2388 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2389 dstRow
+= dstRowStride
;
2399 * Store a combined depth/stencil texture image.
2402 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2404 const GLfloat depthScale
= (GLfloat
) 0xffffff;
2406 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2407 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2408 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2410 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
2411 ctx
->Pixel
.DepthBias
== 0.0f
&&
2412 !srcPacking
->SwapBytes
) {
2414 memcpy_texture(ctx
, dims
,
2415 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2418 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2419 srcAddr
, srcPacking
);
2423 const GLint srcRowStride
2424 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2428 for (img
= 0; img
< srcDepth
; img
++) {
2429 GLuint
*dstRow
= (GLuint
*) dstAddr
2430 + dstImageOffsets
[dstZoffset
+ img
]
2431 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2434 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2435 srcWidth
, srcHeight
,
2438 for (row
= 0; row
< srcHeight
; row
++) {
2439 GLubyte stencil
[MAX_WIDTH
];
2441 /* the 24 depth bits will be in the high position: */
2442 _mesa_unpack_depth_span(ctx
, srcWidth
,
2443 GL_UNSIGNED_INT_24_8_EXT
, /* dst type */
2444 dstRow
, /* dst addr */
2445 (GLuint
) depthScale
,
2446 srcType
, src
, srcPacking
);
2447 /* get the 8-bit stencil values */
2448 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2449 GL_UNSIGNED_BYTE
, /* dst type */
2450 stencil
, /* dst addr */
2451 srcType
, src
, srcPacking
,
2452 ctx
->_ImageTransferState
);
2453 /* merge stencil values into depth values */
2454 for (i
= 0; i
< srcWidth
; i
++)
2455 dstRow
[i
] |= stencil
[i
];
2457 src
+= srcRowStride
;
2458 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2467 * Store a combined depth/stencil texture image.
2470 _mesa_texstore_s8_z24(TEXSTORE_PARAMS
)
2472 const GLuint depthScale
= 0xffffff;
2473 const GLint srcRowStride
2474 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2478 ASSERT(dstFormat
== &_mesa_texformat_s8_z24
);
2479 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
|| srcFormat
== GL_DEPTH_COMPONENT
);
2480 ASSERT(srcFormat
!= GL_DEPTH_STENCIL_EXT
|| srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2482 /* In case we only upload depth we need to preserve the stencil */
2483 if (srcFormat
== GL_DEPTH_COMPONENT
) {
2484 for (img
= 0; img
< srcDepth
; img
++) {
2485 GLuint
*dstRow
= (GLuint
*) dstAddr
2486 + dstImageOffsets
[dstZoffset
+ img
]
2487 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2490 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2491 srcWidth
, srcHeight
,
2494 for (row
= 0; row
< srcHeight
; row
++) {
2495 GLuint depth
[MAX_WIDTH
];
2497 _mesa_unpack_depth_span(ctx
, srcWidth
,
2498 GL_UNSIGNED_INT
, /* dst type */
2499 depth
, /* dst addr */
2501 srcType
, src
, srcPacking
);
2503 for (i
= 0; i
< srcWidth
; i
++)
2504 dstRow
[i
] = depth
[i
] | (dstRow
[i
] & 0xFF000000);
2506 src
+= srcRowStride
;
2507 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2512 for (img
= 0; img
< srcDepth
; img
++) {
2513 GLuint
*dstRow
= (GLuint
*) dstAddr
2514 + dstImageOffsets
[dstZoffset
+ img
]
2515 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2518 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2519 srcWidth
, srcHeight
,
2522 for (row
= 0; row
< srcHeight
; row
++) {
2523 GLubyte stencil
[MAX_WIDTH
];
2525 /* the 24 depth bits will be in the low position: */
2526 _mesa_unpack_depth_span(ctx
, srcWidth
,
2527 GL_UNSIGNED_INT
, /* dst type */
2528 dstRow
, /* dst addr */
2530 srcType
, src
, srcPacking
);
2531 /* get the 8-bit stencil values */
2532 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2533 GL_UNSIGNED_BYTE
, /* dst type */
2534 stencil
, /* dst addr */
2535 srcType
, src
, srcPacking
,
2536 ctx
->_ImageTransferState
);
2537 /* merge stencil values into depth values */
2538 for (i
= 0; i
< srcWidth
; i
++)
2539 dstRow
[i
] |= stencil
[i
] << 24;
2541 src
+= srcRowStride
;
2542 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2550 * Store an image in any of the formats:
2551 * _mesa_texformat_rgba_float32
2552 * _mesa_texformat_rgb_float32
2553 * _mesa_texformat_alpha_float32
2554 * _mesa_texformat_luminance_float32
2555 * _mesa_texformat_luminance_alpha_float32
2556 * _mesa_texformat_intensity_float32
2559 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2561 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2563 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2564 dstFormat
== &_mesa_texformat_rgb_float32
||
2565 dstFormat
== &_mesa_texformat_alpha_float32
||
2566 dstFormat
== &_mesa_texformat_luminance_float32
||
2567 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2568 dstFormat
== &_mesa_texformat_intensity_float32
);
2569 ASSERT(baseInternalFormat
== GL_RGBA
||
2570 baseInternalFormat
== GL_RGB
||
2571 baseInternalFormat
== GL_ALPHA
||
2572 baseInternalFormat
== GL_LUMINANCE
||
2573 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2574 baseInternalFormat
== GL_INTENSITY
);
2575 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2577 if (!ctx
->_ImageTransferState
&&
2578 !srcPacking
->SwapBytes
&&
2579 baseInternalFormat
== srcFormat
&&
2580 srcType
== GL_FLOAT
) {
2581 /* simple memcpy path */
2582 memcpy_texture(ctx
, dims
,
2583 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2586 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2587 srcAddr
, srcPacking
);
2591 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2593 dstFormat
->BaseFormat
,
2594 srcWidth
, srcHeight
, srcDepth
,
2595 srcFormat
, srcType
, srcAddr
,
2597 const GLfloat
*srcRow
= tempImage
;
2602 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2603 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2604 for (img
= 0; img
< srcDepth
; img
++) {
2605 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2606 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2607 + dstYoffset
* dstRowStride
2608 + dstXoffset
* dstFormat
->TexelBytes
;
2609 for (row
= 0; row
< srcHeight
; row
++) {
2610 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2611 dstRow
+= dstRowStride
;
2612 srcRow
+= srcWidth
* components
;
2616 _mesa_free((void *) tempImage
);
2623 * As above, but store 16-bit floats.
2626 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2628 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2630 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2631 dstFormat
== &_mesa_texformat_rgb_float16
||
2632 dstFormat
== &_mesa_texformat_alpha_float16
||
2633 dstFormat
== &_mesa_texformat_luminance_float16
||
2634 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2635 dstFormat
== &_mesa_texformat_intensity_float16
);
2636 ASSERT(baseInternalFormat
== GL_RGBA
||
2637 baseInternalFormat
== GL_RGB
||
2638 baseInternalFormat
== GL_ALPHA
||
2639 baseInternalFormat
== GL_LUMINANCE
||
2640 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2641 baseInternalFormat
== GL_INTENSITY
);
2642 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2644 if (!ctx
->_ImageTransferState
&&
2645 !srcPacking
->SwapBytes
&&
2646 baseInternalFormat
== srcFormat
&&
2647 srcType
== GL_HALF_FLOAT_ARB
) {
2648 /* simple memcpy path */
2649 memcpy_texture(ctx
, dims
,
2650 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2653 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2654 srcAddr
, srcPacking
);
2658 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2660 dstFormat
->BaseFormat
,
2661 srcWidth
, srcHeight
, srcDepth
,
2662 srcFormat
, srcType
, srcAddr
,
2664 const GLfloat
*src
= tempImage
;
2668 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2669 for (img
= 0; img
< srcDepth
; img
++) {
2670 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2671 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2672 + dstYoffset
* dstRowStride
2673 + dstXoffset
* dstFormat
->TexelBytes
;
2674 for (row
= 0; row
< srcHeight
; row
++) {
2675 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2677 for (i
= 0; i
< srcWidth
* components
; i
++) {
2678 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2680 dstRow
+= dstRowStride
;
2681 src
+= srcWidth
* components
;
2685 _mesa_free((void *) tempImage
);
2691 #if FEATURE_EXT_texture_sRGB
2693 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2695 const GLboolean littleEndian
= _mesa_little_endian();
2696 const struct gl_texture_format
*newDstFormat
;
2697 StoreTexImageFunc store
;
2700 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2702 /* reuse normal rgb texstore code */
2704 newDstFormat
= &_mesa_texformat_bgr888
;
2705 store
= _mesa_texstore_bgr888
;
2708 newDstFormat
= &_mesa_texformat_rgb888
;
2709 store
= _mesa_texstore_rgb888
;
2712 k
= store(ctx
, dims
, baseInternalFormat
,
2713 newDstFormat
, dstAddr
,
2714 dstXoffset
, dstYoffset
, dstZoffset
,
2715 dstRowStride
, dstImageOffsets
,
2716 srcWidth
, srcHeight
, srcDepth
,
2718 srcAddr
, srcPacking
);
2724 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2726 const GLboolean littleEndian
= _mesa_little_endian();
2727 const struct gl_texture_format
*newDstFormat
;
2730 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2732 /* reuse normal rgba texstore code */
2734 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2736 newDstFormat
= &_mesa_texformat_rgba8888
;
2738 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2739 newDstFormat
, dstAddr
,
2740 dstXoffset
, dstYoffset
, dstZoffset
,
2741 dstRowStride
, dstImageOffsets
,
2742 srcWidth
, srcHeight
, srcDepth
,
2744 srcAddr
, srcPacking
);
2750 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2752 const struct gl_texture_format
*newDstFormat
;
2755 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2757 newDstFormat
= &_mesa_texformat_l8
;
2759 /* _mesa_textore_a8 handles luminance8 too */
2760 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2761 newDstFormat
, dstAddr
,
2762 dstXoffset
, dstYoffset
, dstZoffset
,
2763 dstRowStride
, dstImageOffsets
,
2764 srcWidth
, srcHeight
, srcDepth
,
2766 srcAddr
, srcPacking
);
2772 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2774 const GLboolean littleEndian
= _mesa_little_endian();
2775 const struct gl_texture_format
*newDstFormat
;
2778 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2780 /* reuse normal luminance/alpha texstore code */
2782 newDstFormat
= &_mesa_texformat_al88
;
2784 newDstFormat
= &_mesa_texformat_al88_rev
;
2786 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2787 newDstFormat
, dstAddr
,
2788 dstXoffset
, dstYoffset
, dstZoffset
,
2789 dstRowStride
, dstImageOffsets
,
2790 srcWidth
, srcHeight
, srcDepth
,
2792 srcAddr
, srcPacking
);
2796 #endif /* FEATURE_EXT_texture_sRGB */
2800 * Check if an unpack PBO is active prior to fetching a texture image.
2801 * If so, do bounds checking and map the buffer into main memory.
2802 * Any errors detected will be recorded.
2803 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2806 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2807 GLsizei width
, GLsizei height
, GLsizei depth
,
2808 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2809 const struct gl_pixelstore_attrib
*unpack
,
2810 const char *funcName
)
2814 if (unpack
->BufferObj
->Name
== 0) {
2818 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2819 format
, type
, pixels
)) {
2820 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2824 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2825 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2827 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2831 return ADD_POINTERS(buf
, pixels
);
2836 * Check if an unpack PBO is active prior to fetching a compressed texture
2838 * If so, do bounds checking and map the buffer into main memory.
2839 * Any errors detected will be recorded.
2840 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2843 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2844 GLsizei imageSize
, const GLvoid
*pixels
,
2845 const struct gl_pixelstore_attrib
*packing
,
2846 const char *funcName
)
2850 if (packing
->BufferObj
->Name
== 0) {
2851 /* not using a PBO - return pointer unchanged */
2854 if ((const GLubyte
*) pixels
+ imageSize
>
2855 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2856 /* out of bounds read! */
2857 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2861 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2862 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2864 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2868 return ADD_POINTERS(buf
, pixels
);
2873 * This function must be called after either of the validate_pbo_*_teximage()
2874 * functions. It unmaps the PBO buffer if it was mapped earlier.
2877 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2878 const struct gl_pixelstore_attrib
*unpack
)
2880 if (unpack
->BufferObj
->Name
) {
2881 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2889 * Adaptor for fetching a GLchan texel from a float-valued texture.
2892 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2893 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2896 ASSERT(texImage
->FetchTexelf
);
2897 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2898 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2899 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2900 /* just one channel */
2901 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2905 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2906 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2907 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2908 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2914 * Adaptor for fetching a float texel from a GLchan-valued texture.
2917 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2918 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2921 ASSERT(texImage
->FetchTexelc
);
2922 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2923 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2924 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2925 /* just one channel */
2926 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2930 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2931 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2932 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2933 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2939 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2942 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2944 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2945 ASSERT(texImage
->TexFormat
);
2949 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2950 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2953 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2954 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2957 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2958 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2964 /* now check if we need to use a float/chan adaptor */
2965 if (!texImage
->FetchTexelc
) {
2966 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
2968 else if (!texImage
->FetchTexelf
) {
2969 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
2973 ASSERT(texImage
->FetchTexelc
);
2974 ASSERT(texImage
->FetchTexelf
);
2979 * Choose the actual storage format for a new texture image.
2980 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2981 * Also set some other texImage fields related to texture compression, etc.
2982 * \param ctx rendering context
2983 * \param texImage the gl_texture_image
2984 * \param dims texture dimensions (1, 2 or 3)
2985 * \param format the user-specified format parameter
2986 * \param type the user-specified type parameter
2987 * \param internalFormat the user-specified internal format hint
2990 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2992 GLenum format
, GLenum type
, GLint internalFormat
)
2994 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2995 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2998 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
3000 ASSERT(texImage
->TexFormat
);
3002 _mesa_set_fetch_functions(texImage
, dims
);
3004 if (texImage
->TexFormat
->TexelBytes
== 0) {
3005 /* must be a compressed format */
3006 texImage
->IsCompressed
= GL_TRUE
;
3007 texImage
->CompressedSize
=
3008 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
3009 texImage
->Height
, texImage
->Depth
,
3010 texImage
->TexFormat
->MesaFormat
);
3013 /* non-compressed format */
3014 texImage
->IsCompressed
= GL_FALSE
;
3015 texImage
->CompressedSize
= 0;
3022 * This is the software fallback for Driver.TexImage1D()
3023 * and Driver.CopyTexImage1D().
3024 * \sa _mesa_store_teximage2d()
3027 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3028 GLint internalFormat
,
3029 GLint width
, GLint border
,
3030 GLenum format
, GLenum type
, const GLvoid
*pixels
,
3031 const struct gl_pixelstore_attrib
*packing
,
3032 struct gl_texture_object
*texObj
,
3033 struct gl_texture_image
*texImage
)
3035 GLint postConvWidth
= width
;
3039 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
3040 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
3043 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
3045 /* allocate memory */
3046 if (texImage
->IsCompressed
)
3047 sizeInBytes
= texImage
->CompressedSize
;
3049 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
3050 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3051 if (!texImage
->Data
) {
3052 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3056 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3057 pixels
, packing
, "glTexImage1D");
3059 /* Note: we check for a NULL image pointer here, _after_ we allocated
3060 * memory for the texture. That's what the GL spec calls for.
3065 const GLint dstRowStride
= 0;
3067 ASSERT(texImage
->TexFormat
->StoreImage
);
3068 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3069 texImage
->TexFormat
,
3071 0, 0, 0, /* dstX/Y/Zoffset */
3073 texImage
->ImageOffsets
,
3075 format
, type
, pixels
, packing
);
3077 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3081 /* GL_SGIS_generate_mipmap */
3082 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3083 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3086 _mesa_unmap_teximage_pbo(ctx
, packing
);
3091 * This is the software fallback for Driver.TexImage2D()
3092 * and Driver.CopyTexImage2D().
3094 * This function is oriented toward storing images in main memory, rather
3095 * than VRAM. Device driver's can easily plug in their own replacement.
3097 * Note: width and height may be pre-convolved dimensions, but
3098 * texImage->Width and texImage->Height will be post-convolved dimensions.
3101 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3102 GLint internalFormat
,
3103 GLint width
, GLint height
, GLint border
,
3104 GLenum format
, GLenum type
, const void *pixels
,
3105 const struct gl_pixelstore_attrib
*packing
,
3106 struct gl_texture_object
*texObj
,
3107 struct gl_texture_image
*texImage
)
3109 GLint postConvWidth
= width
, postConvHeight
= height
;
3110 GLint texelBytes
, sizeInBytes
;
3113 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
3114 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
3118 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
3120 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3122 /* allocate memory */
3123 if (texImage
->IsCompressed
)
3124 sizeInBytes
= texImage
->CompressedSize
;
3126 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
3127 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3128 if (!texImage
->Data
) {
3129 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3133 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3134 pixels
, packing
, "glTexImage2D");
3136 /* Note: we check for a NULL image pointer here, _after_ we allocated
3137 * memory for the texture. That's what the GL spec calls for.
3144 if (texImage
->IsCompressed
) {
3146 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3149 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3151 ASSERT(texImage
->TexFormat
->StoreImage
);
3152 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3153 texImage
->TexFormat
,
3155 0, 0, 0, /* dstX/Y/Zoffset */
3157 texImage
->ImageOffsets
,
3159 format
, type
, pixels
, packing
);
3161 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3165 /* GL_SGIS_generate_mipmap */
3166 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3167 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3170 _mesa_unmap_teximage_pbo(ctx
, packing
);
3176 * This is the software fallback for Driver.TexImage3D()
3177 * and Driver.CopyTexImage3D().
3178 * \sa _mesa_store_teximage2d()
3181 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3182 GLint internalFormat
,
3183 GLint width
, GLint height
, GLint depth
, GLint border
,
3184 GLenum format
, GLenum type
, const void *pixels
,
3185 const struct gl_pixelstore_attrib
*packing
,
3186 struct gl_texture_object
*texObj
,
3187 struct gl_texture_image
*texImage
)
3189 GLint texelBytes
, sizeInBytes
;
3192 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3194 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3196 /* allocate memory */
3197 if (texImage
->IsCompressed
)
3198 sizeInBytes
= texImage
->CompressedSize
;
3200 sizeInBytes
= width
* height
* depth
* texelBytes
;
3201 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3202 if (!texImage
->Data
) {
3203 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3207 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3208 type
, pixels
, packing
, "glTexImage3D");
3210 /* Note: we check for a NULL image pointer here, _after_ we allocated
3211 * memory for the texture. That's what the GL spec calls for.
3218 if (texImage
->IsCompressed
) {
3220 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3223 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3225 ASSERT(texImage
->TexFormat
->StoreImage
);
3226 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3227 texImage
->TexFormat
,
3229 0, 0, 0, /* dstX/Y/Zoffset */
3231 texImage
->ImageOffsets
,
3232 width
, height
, depth
,
3233 format
, type
, pixels
, packing
);
3235 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3239 /* GL_SGIS_generate_mipmap */
3240 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3241 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3244 _mesa_unmap_teximage_pbo(ctx
, packing
);
3251 * This is the software fallback for Driver.TexSubImage1D()
3252 * and Driver.CopyTexSubImage1D().
3255 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3256 GLint xoffset
, GLint width
,
3257 GLenum format
, GLenum type
, const void *pixels
,
3258 const struct gl_pixelstore_attrib
*packing
,
3259 struct gl_texture_object
*texObj
,
3260 struct gl_texture_image
*texImage
)
3262 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3263 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3264 pixels
, packing
, "glTexSubImage1D");
3269 const GLint dstRowStride
= 0;
3271 ASSERT(texImage
->TexFormat
->StoreImage
);
3272 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3273 texImage
->TexFormat
,
3275 xoffset
, 0, 0, /* offsets */
3277 texImage
->ImageOffsets
,
3279 format
, type
, pixels
, packing
);
3281 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3285 /* GL_SGIS_generate_mipmap */
3286 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3287 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3290 _mesa_unmap_teximage_pbo(ctx
, packing
);
3296 * This is the software fallback for Driver.TexSubImage2D()
3297 * and Driver.CopyTexSubImage2D().
3300 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3301 GLint xoffset
, GLint yoffset
,
3302 GLint width
, GLint height
,
3303 GLenum format
, GLenum type
, const void *pixels
,
3304 const struct gl_pixelstore_attrib
*packing
,
3305 struct gl_texture_object
*texObj
,
3306 struct gl_texture_image
*texImage
)
3308 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3309 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3310 pixels
, packing
, "glTexSubImage2D");
3315 GLint dstRowStride
= 0;
3317 if (texImage
->IsCompressed
) {
3318 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3322 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3324 ASSERT(texImage
->TexFormat
->StoreImage
);
3325 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3326 texImage
->TexFormat
,
3328 xoffset
, yoffset
, 0,
3330 texImage
->ImageOffsets
,
3332 format
, type
, pixels
, packing
);
3334 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3338 /* GL_SGIS_generate_mipmap */
3339 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3340 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3343 _mesa_unmap_teximage_pbo(ctx
, packing
);
3348 * This is the software fallback for Driver.TexSubImage3D().
3349 * and Driver.CopyTexSubImage3D().
3352 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3353 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3354 GLint width
, GLint height
, GLint depth
,
3355 GLenum format
, GLenum type
, const void *pixels
,
3356 const struct gl_pixelstore_attrib
*packing
,
3357 struct gl_texture_object
*texObj
,
3358 struct gl_texture_image
*texImage
)
3360 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3361 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3362 type
, pixels
, packing
,
3370 if (texImage
->IsCompressed
) {
3371 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3375 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3377 ASSERT(texImage
->TexFormat
->StoreImage
);
3378 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3379 texImage
->TexFormat
,
3381 xoffset
, yoffset
, zoffset
,
3383 texImage
->ImageOffsets
,
3384 width
, height
, depth
,
3385 format
, type
, pixels
, packing
);
3387 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3391 /* GL_SGIS_generate_mipmap */
3392 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3393 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3396 _mesa_unmap_teximage_pbo(ctx
, packing
);
3401 * Fallback for Driver.CompressedTexImage1D()
3404 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3405 GLint internalFormat
,
3406 GLint width
, GLint border
,
3407 GLsizei imageSize
, const GLvoid
*data
,
3408 struct gl_texture_object
*texObj
,
3409 struct gl_texture_image
*texImage
)
3411 /* this space intentionally left blank */
3413 (void) target
; (void) level
;
3414 (void) internalFormat
;
3415 (void) width
; (void) border
;
3416 (void) imageSize
; (void) data
;
3424 * Fallback for Driver.CompressedTexImage2D()
3427 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3428 GLint internalFormat
,
3429 GLint width
, GLint height
, GLint border
,
3430 GLsizei imageSize
, const GLvoid
*data
,
3431 struct gl_texture_object
*texObj
,
3432 struct gl_texture_image
*texImage
)
3434 (void) width
; (void) height
; (void) border
;
3436 /* This is pretty simple, basically just do a memcpy without worrying
3437 * about the usual image unpacking or image transfer operations.
3441 ASSERT(texImage
->Width
> 0);
3442 ASSERT(texImage
->Height
> 0);
3443 ASSERT(texImage
->Depth
== 1);
3444 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3446 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3448 /* allocate storage */
3449 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3450 if (!texImage
->Data
) {
3451 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3455 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3457 "glCompressedTexImage2D");
3462 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3463 MEMCPY(texImage
->Data
, data
, imageSize
);
3465 /* GL_SGIS_generate_mipmap */
3466 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3467 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3470 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3476 * Fallback for Driver.CompressedTexImage3D()
3479 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3480 GLint internalFormat
,
3481 GLint width
, GLint height
, GLint depth
,
3483 GLsizei imageSize
, const GLvoid
*data
,
3484 struct gl_texture_object
*texObj
,
3485 struct gl_texture_image
*texImage
)
3487 /* this space intentionally left blank */
3489 (void) target
; (void) level
;
3490 (void) internalFormat
;
3491 (void) width
; (void) height
; (void) depth
;
3493 (void) imageSize
; (void) data
;
3501 * Fallback for Driver.CompressedTexSubImage1D()
3504 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3506 GLint xoffset
, GLsizei width
,
3508 GLsizei imageSize
, const GLvoid
*data
,
3509 struct gl_texture_object
*texObj
,
3510 struct gl_texture_image
*texImage
)
3512 /* there are no compressed 1D texture formats yet */
3514 (void) target
; (void) level
;
3515 (void) xoffset
; (void) width
;
3517 (void) imageSize
; (void) data
;
3524 * Fallback for Driver.CompressedTexSubImage2D()
3527 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3529 GLint xoffset
, GLint yoffset
,
3530 GLsizei width
, GLsizei height
,
3532 GLsizei imageSize
, const GLvoid
*data
,
3533 struct gl_texture_object
*texObj
,
3534 struct gl_texture_image
*texImage
)
3536 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3540 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3544 /* these should have been caught sooner */
3545 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3546 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3547 ASSERT((xoffset
& 3) == 0);
3548 ASSERT((yoffset
& 3) == 0);
3550 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3551 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3553 "glCompressedTexSubImage2D");
3557 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3558 src
= (const GLubyte
*) data
;
3560 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3561 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3562 texImage
->TexFormat
->MesaFormat
,
3564 (GLubyte
*) texImage
->Data
);
3566 bytesPerRow
= srcRowStride
;
3569 for (i
= 0; i
< rows
; i
++) {
3570 MEMCPY(dest
, src
, bytesPerRow
);
3571 dest
+= destRowStride
;
3572 src
+= srcRowStride
;
3575 /* GL_SGIS_generate_mipmap */
3576 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3577 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3580 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3585 * Fallback for Driver.CompressedTexSubImage3D()
3588 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3590 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3591 GLsizei width
, GLsizei height
, GLsizei depth
,
3593 GLsizei imageSize
, const GLvoid
*data
,
3594 struct gl_texture_object
*texObj
,
3595 struct gl_texture_image
*texImage
)
3597 /* there are no compressed 3D texture formats yet */
3599 (void) target
; (void) level
;
3600 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3601 (void) width
; (void) height
; (void) depth
;
3603 (void) imageSize
; (void) data
;
3611 #if FEATURE_EXT_texture_sRGB
3614 * Test if given texture image is an sRGB format.
3617 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3619 switch (texImage
->TexFormat
->MesaFormat
) {
3620 case MESA_FORMAT_SRGB8
:
3621 case MESA_FORMAT_SRGBA8
:
3622 case MESA_FORMAT_SL8
:
3623 case MESA_FORMAT_SLA8
:
3630 #endif /* FEATURE_EXT_texture_sRGB */
3634 * This is the software fallback for Driver.GetTexImage().
3635 * All error checking will have been done before this routine is called.
3638 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3639 GLenum format
, GLenum type
, GLvoid
*pixels
,
3640 struct gl_texture_object
*texObj
,
3641 struct gl_texture_image
*texImage
)
3643 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3645 if (ctx
->Pack
.BufferObj
->Name
) {
3646 /* Packing texture image into a PBO.
3647 * Map the (potentially) VRAM-based buffer into our process space so
3648 * we can write into it with the code below.
3649 * A hardware driver might use a sophisticated blit to move the
3650 * texture data to the PBO if the PBO is in VRAM along with the texture.
3652 GLubyte
*buf
= (GLubyte
*)
3653 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3654 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3656 /* buffer is already mapped - that's an error */
3657 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3660 /* <pixels> was an offset into the PBO.
3661 * Now make it a real, client-side pointer inside the mapped region.
3663 pixels
= ADD_POINTERS(buf
, pixels
);
3671 const GLint width
= texImage
->Width
;
3672 const GLint height
= texImage
->Height
;
3673 const GLint depth
= texImage
->Depth
;
3675 for (img
= 0; img
< depth
; img
++) {
3676 for (row
= 0; row
< height
; row
++) {
3677 /* compute destination address in client memory */
3678 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3679 width
, height
, format
, type
,
3683 if (format
== GL_COLOR_INDEX
) {
3684 GLuint indexRow
[MAX_WIDTH
];
3686 /* Can't use FetchTexel here because that returns RGBA */
3687 if (texImage
->TexFormat
->IndexBits
== 8) {
3688 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3689 src
+= width
* (img
* texImage
->Height
+ row
);
3690 for (col
= 0; col
< width
; col
++) {
3691 indexRow
[col
] = src
[col
];
3694 else if (texImage
->TexFormat
->IndexBits
== 16) {
3695 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3696 src
+= width
* (img
* texImage
->Height
+ row
);
3697 for (col
= 0; col
< width
; col
++) {
3698 indexRow
[col
] = src
[col
];
3703 "Color index problem in _mesa_GetTexImage");
3705 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3706 indexRow
, &ctx
->Pack
,
3707 0 /* no image transfer */);
3709 else if (format
== GL_DEPTH_COMPONENT
) {
3710 GLfloat depthRow
[MAX_WIDTH
];
3712 for (col
= 0; col
< width
; col
++) {
3713 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3716 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3717 depthRow
, &ctx
->Pack
);
3719 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3720 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3721 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3722 src
+= width
* row
+ width
* height
* img
;
3723 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3724 if (ctx
->Pack
.SwapBytes
) {
3725 _mesa_swap4((GLuint
*) dest
, width
);
3728 else if (format
== GL_YCBCR_MESA
) {
3729 /* No pixel transfer */
3730 const GLint rowstride
= texImage
->RowStride
;
3732 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3733 width
* sizeof(GLushort
));
3734 /* check for byte swapping */
3735 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3736 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3737 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3738 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3739 if (!ctx
->Pack
.SwapBytes
)
3740 _mesa_swap2((GLushort
*) dest
, width
);
3742 else if (ctx
->Pack
.SwapBytes
) {
3743 _mesa_swap2((GLushort
*) dest
, width
);
3746 #if FEATURE_EXT_texture_sRGB
3747 else if (is_srgb_teximage(texImage
)) {
3748 /* no pixel transfer and no non-linear to linear conversion */
3749 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3750 const GLint rowstride
= comps
* texImage
->RowStride
;
3752 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3753 comps
* width
* sizeof(GLubyte
));
3755 #endif /* FEATURE_EXT_texture_sRGB */
3757 /* general case: convert row to RGBA format */
3758 GLfloat rgba
[MAX_WIDTH
][4];
3760 for (col
= 0; col
< width
; col
++) {
3761 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3762 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3763 rgba
[col
][RCOMP
] = 0.0;
3764 rgba
[col
][GCOMP
] = 0.0;
3765 rgba
[col
][BCOMP
] = 0.0;
3767 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3768 rgba
[col
][GCOMP
] = 0.0;
3769 rgba
[col
][BCOMP
] = 0.0;
3770 rgba
[col
][ACOMP
] = 1.0;
3772 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3773 rgba
[col
][GCOMP
] = 0.0;
3774 rgba
[col
][BCOMP
] = 0.0;
3776 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3777 rgba
[col
][GCOMP
] = 0.0;
3778 rgba
[col
][BCOMP
] = 0.0;
3779 rgba
[col
][ACOMP
] = 1.0;
3782 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3784 &ctx
->Pack
, 0x0 /*image xfer ops*/);
3790 if (ctx
->Pack
.BufferObj
->Name
) {
3791 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3792 ctx
->Pack
.BufferObj
);
3799 * This is the software fallback for Driver.GetCompressedTexImage().
3800 * All error checking will have been done before this routine is called.
3803 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3805 const struct gl_texture_object
*texObj
,
3806 const struct gl_texture_image
*texImage
)
3810 if (ctx
->Pack
.BufferObj
->Name
) {
3811 /* pack texture image into a PBO */
3813 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3814 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3815 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3816 "glGetCompressedTexImage(invalid PBO access)");
3819 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3821 ctx
->Pack
.BufferObj
);
3823 /* buffer is already mapped - that's an error */
3824 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3825 "glGetCompressedTexImage(PBO is mapped)");
3828 img
= ADD_POINTERS(buf
, img
);
3835 /* don't use texImage->CompressedSize since that may be padded out */
3836 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3838 texImage
->TexFormat
->MesaFormat
);
3840 /* just memcpy, no pixelstore or pixel transfer */
3841 _mesa_memcpy(img
, texImage
->Data
, size
);
3843 if (ctx
->Pack
.BufferObj
->Name
) {
3844 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3845 ctx
->Pack
.BufferObj
);