2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
65 #include "texcompress.h"
66 #include "texformat.h"
79 * Return GL_TRUE if the given image format is one that be converted
80 * to another format by swizzling.
83 can_swizzle(GLenum logicalBaseFormat
)
85 switch (logicalBaseFormat
) {
88 case GL_LUMINANCE_ALPHA
:
122 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
123 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
124 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
125 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
128 static const struct {
131 GLubyte from_rgba
[6];
132 } mappings
[MAX_IDX
] =
142 MAP4(ZERO
, ZERO
, ZERO
, 0),
173 MAP4(0, ZERO
, ZERO
, ONE
),
179 MAP4(ZERO
, 0, ZERO
, ONE
),
185 MAP4(ZERO
, ZERO
, 0, ONE
),
211 * Convert a GL image format enum to an IDX_* value (see above).
214 get_map_idx(GLenum value
)
217 case GL_LUMINANCE
: return IDX_LUMINANCE
;
218 case GL_ALPHA
: return IDX_ALPHA
;
219 case GL_INTENSITY
: return IDX_INTENSITY
;
220 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
221 case GL_RGB
: return IDX_RGB
;
222 case GL_RGBA
: return IDX_RGBA
;
223 case GL_RED
: return IDX_RED
;
224 case GL_GREEN
: return IDX_GREEN
;
225 case GL_BLUE
: return IDX_BLUE
;
226 case GL_BGR
: return IDX_BGR
;
227 case GL_BGRA
: return IDX_BGRA
;
228 case GL_ABGR_EXT
: return IDX_ABGR
;
230 _mesa_problem(NULL
, "Unexpected inFormat");
237 * When promoting texture formats (see below) we need to compute the
238 * mapping of dest components back to source components.
239 * This function does that.
240 * \param inFormat the incoming format of the texture
241 * \param outFormat the final texture format
242 * \return map[6] a full 6-component map
245 compute_component_mapping(GLenum inFormat
, GLenum outFormat
,
248 const int inFmt
= get_map_idx(inFormat
);
249 const int outFmt
= get_map_idx(outFormat
);
250 const GLubyte
*in2rgba
= mappings
[inFmt
].to_rgba
;
251 const GLubyte
*rgba2out
= mappings
[outFmt
].from_rgba
;
254 for (i
= 0; i
< 4; i
++)
255 map
[i
] = in2rgba
[rgba2out
[i
]];
261 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
262 inFormat, _mesa_lookup_enum_by_nr(inFormat),
263 outFormat, _mesa_lookup_enum_by_nr(outFormat),
274 #if !FEATURE_convolve
276 _mesa_adjust_image_for_convolution(GLcontext
*ctx
, GLuint dims
,
277 GLsizei
*srcWidth
, GLsizei
*srcHeight
)
285 * Make a temporary (color) texture image with GLfloat components.
286 * Apply all needed pixel unpacking and pixel transfer operations.
287 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
288 * Suppose the user specifies GL_LUMINANCE as the internal texture format
289 * but the graphics hardware doesn't support luminance textures. So, might
290 * use an RGB hardware format instead.
291 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
293 * \param ctx the rendering context
294 * \param dims image dimensions: 1, 2 or 3
295 * \param logicalBaseFormat basic texture derived from the user's
296 * internal texture format value
297 * \param textureBaseFormat the actual basic format of the texture
298 * \param srcWidth source image width
299 * \param srcHeight source image height
300 * \param srcDepth source image depth
301 * \param srcFormat source image format
302 * \param srcType source image type
303 * \param srcAddr source image address
304 * \param srcPacking source image pixel packing
305 * \return resulting image with format = textureBaseFormat and type = GLfloat.
308 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
309 GLenum logicalBaseFormat
,
310 GLenum textureBaseFormat
,
311 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
312 GLenum srcFormat
, GLenum srcType
,
313 const GLvoid
*srcAddr
,
314 const struct gl_pixelstore_attrib
*srcPacking
)
316 GLuint transferOps
= ctx
->_ImageTransferState
;
319 ASSERT(dims
>= 1 && dims
<= 3);
321 ASSERT(logicalBaseFormat
== GL_RGBA
||
322 logicalBaseFormat
== GL_RGB
||
323 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
324 logicalBaseFormat
== GL_LUMINANCE
||
325 logicalBaseFormat
== GL_ALPHA
||
326 logicalBaseFormat
== GL_INTENSITY
||
327 logicalBaseFormat
== GL_COLOR_INDEX
||
328 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
330 ASSERT(textureBaseFormat
== GL_RGBA
||
331 textureBaseFormat
== GL_RGB
||
332 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
333 textureBaseFormat
== GL_LUMINANCE
||
334 textureBaseFormat
== GL_ALPHA
||
335 textureBaseFormat
== GL_INTENSITY
||
336 textureBaseFormat
== GL_COLOR_INDEX
||
337 textureBaseFormat
== GL_DEPTH_COMPONENT
);
339 /* conventional color image */
341 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
342 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
343 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
344 /* need image convolution */
345 const GLuint preConvTransferOps
346 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
347 const GLuint postConvTransferOps
348 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
350 GLint convWidth
, convHeight
;
353 /* pre-convolution image buffer (3D) */
354 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
355 * 4 * sizeof(GLfloat
));
359 /* post-convolution image buffer (2D) */
360 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
361 * 4 * sizeof(GLfloat
));
363 _mesa_free(tempImage
);
367 /* loop over 3D image slices */
368 for (img
= 0; img
< srcDepth
; img
++) {
369 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
371 /* unpack and do transfer ops up to convolution */
372 for (row
= 0; row
< srcHeight
; row
++) {
373 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
374 srcAddr
, srcWidth
, srcHeight
,
375 srcFormat
, srcType
, img
, row
, 0);
376 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
377 srcFormat
, srcType
, src
,
383 /* size after optional convolution */
384 convWidth
= srcWidth
;
385 convHeight
= srcHeight
;
390 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
392 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
393 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
396 if (ctx
->Pixel
.Convolution2DEnabled
) {
397 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
401 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
402 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
408 /* do post-convolution transfer and pack into tempImage */
410 const GLint logComponents
411 = _mesa_components_in_format(logicalBaseFormat
);
412 const GLfloat
*src
= convImage
;
413 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
414 for (row
= 0; row
< convHeight
; row
++) {
415 _mesa_pack_rgba_span_float(ctx
, convWidth
,
416 (GLfloat (*)[4]) src
,
417 logicalBaseFormat
, GL_FLOAT
,
418 dst
, &ctx
->DefaultPacking
,
419 postConvTransferOps
);
420 src
+= convWidth
* 4;
421 dst
+= convWidth
* logComponents
;
424 } /* loop over 3D image slices */
426 _mesa_free(convImage
);
428 /* might need these below */
429 srcWidth
= convWidth
;
430 srcHeight
= convHeight
;
434 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
435 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
436 srcWidth
, srcFormat
, srcType
);
440 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
441 * components
* sizeof(GLfloat
));
446 for (img
= 0; img
< srcDepth
; img
++) {
448 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
452 for (row
= 0; row
< srcHeight
; row
++) {
453 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
454 dst
, srcFormat
, srcType
, src
,
455 srcPacking
, transferOps
);
456 dst
+= srcWidth
* components
;
462 if (logicalBaseFormat
!= textureBaseFormat
) {
464 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
465 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
470 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
471 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
472 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
474 /* The actual texture format should have at least as many components
475 * as the logical texture format.
477 ASSERT(texComponents
>= logComponents
);
479 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
480 * texComponents
* sizeof(GLfloat
));
482 _mesa_free(tempImage
);
486 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
488 n
= srcWidth
* srcHeight
* srcDepth
;
489 for (i
= 0; i
< n
; i
++) {
491 for (k
= 0; k
< texComponents
; k
++) {
494 newImage
[i
* texComponents
+ k
] = 0.0F
;
496 newImage
[i
* texComponents
+ k
] = 1.0F
;
498 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
502 _mesa_free(tempImage
);
503 tempImage
= newImage
;
511 * Make a temporary (color) texture image with GLchan components.
512 * Apply all needed pixel unpacking and pixel transfer operations.
513 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
514 * Suppose the user specifies GL_LUMINANCE as the internal texture format
515 * but the graphics hardware doesn't support luminance textures. So, might
516 * use an RGB hardware format instead.
517 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
519 * \param ctx the rendering context
520 * \param dims image dimensions: 1, 2 or 3
521 * \param logicalBaseFormat basic texture derived from the user's
522 * internal texture format value
523 * \param textureBaseFormat the actual basic format of the texture
524 * \param srcWidth source image width
525 * \param srcHeight source image height
526 * \param srcDepth source image depth
527 * \param srcFormat source image format
528 * \param srcType source image type
529 * \param srcAddr source image address
530 * \param srcPacking source image pixel packing
531 * \return resulting image with format = textureBaseFormat and type = GLchan.
534 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
535 GLenum logicalBaseFormat
,
536 GLenum textureBaseFormat
,
537 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
538 GLenum srcFormat
, GLenum srcType
,
539 const GLvoid
*srcAddr
,
540 const struct gl_pixelstore_attrib
*srcPacking
)
542 GLuint transferOps
= ctx
->_ImageTransferState
;
543 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
544 GLboolean freeSrcImage
= GL_FALSE
;
546 GLchan
*tempImage
, *dst
;
548 ASSERT(dims
>= 1 && dims
<= 3);
550 ASSERT(logicalBaseFormat
== GL_RGBA
||
551 logicalBaseFormat
== GL_RGB
||
552 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
553 logicalBaseFormat
== GL_LUMINANCE
||
554 logicalBaseFormat
== GL_ALPHA
||
555 logicalBaseFormat
== GL_INTENSITY
);
557 ASSERT(textureBaseFormat
== GL_RGBA
||
558 textureBaseFormat
== GL_RGB
||
559 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
560 textureBaseFormat
== GL_LUMINANCE
||
561 textureBaseFormat
== GL_ALPHA
||
562 textureBaseFormat
== GL_INTENSITY
);
565 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
566 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
567 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
568 /* get convolved image */
569 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
572 srcWidth
, srcHeight
, srcDepth
,
574 srcAddr
, srcPacking
);
577 /* the convolved image is our new source image */
579 srcFormat
= logicalBaseFormat
;
581 srcPacking
= &ctx
->DefaultPacking
;
582 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
584 freeSrcImage
= GL_TRUE
;
588 /* unpack and transfer the source image */
589 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
590 * components
* sizeof(GLchan
));
595 for (img
= 0; img
< srcDepth
; img
++) {
596 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
600 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
604 for (row
= 0; row
< srcHeight
; row
++) {
605 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
606 srcFormat
, srcType
, src
, srcPacking
,
608 dst
+= srcWidth
* components
;
613 /* If we made a temporary image for convolution, free it here */
615 _mesa_free((void *) srcAddr
);
618 if (logicalBaseFormat
!= textureBaseFormat
) {
619 /* one more conversion step */
620 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
621 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
626 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
627 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
628 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
630 /* The actual texture format should have at least as many components
631 * as the logical texture format.
633 ASSERT(texComponents
>= logComponents
);
635 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
636 * texComponents
* sizeof(GLchan
));
638 _mesa_free(tempImage
);
642 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
644 n
= srcWidth
* srcHeight
* srcDepth
;
645 for (i
= 0; i
< n
; i
++) {
647 for (k
= 0; k
< texComponents
; k
++) {
650 newImage
[i
* texComponents
+ k
] = 0;
652 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
654 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
658 _mesa_free(tempImage
);
659 tempImage
= newImage
;
667 * Copy GLubyte pixels from <src> to <dst> with swizzling.
668 * \param dst destination pixels
669 * \param dstComponents number of color components in destination pixels
670 * \param src source pixels
671 * \param srcComponents number of color components in source pixels
672 * \param map the swizzle mapping. map[X] says where to find the X component
673 * in the source image's pixels. For example, if the source image
674 * is GL_BGRA and X = red, map[0] yields 2.
675 * \param count number of pixels to copy/swizzle.
678 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
679 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
681 #define SWZ_CPY(dst, src, count, dstComps, srcComps) \
684 for (i = 0; i < count; i++) { \
686 if (srcComps == 4) { \
687 COPY_4UBV(tmp, src); \
690 for (j = 0; j < srcComps; j++) { \
695 for (j = 0; j < dstComps; j++) { \
696 dst[j] = tmp[map[j]]; \
707 ASSERT(srcComponents
<= 4);
708 ASSERT(dstComponents
<= 4);
710 switch (dstComponents
) {
712 switch (srcComponents
) {
714 SWZ_CPY(dst
, src
, count
, 4, 4);
717 SWZ_CPY(dst
, src
, count
, 4, 3);
720 SWZ_CPY(dst
, src
, count
, 4, 2);
723 SWZ_CPY(dst
, src
, count
, 4, 1);
730 switch (srcComponents
) {
732 SWZ_CPY(dst
, src
, count
, 3, 4);
735 SWZ_CPY(dst
, src
, count
, 3, 3);
738 SWZ_CPY(dst
, src
, count
, 3, 2);
741 SWZ_CPY(dst
, src
, count
, 3, 1);
748 switch (srcComponents
) {
750 SWZ_CPY(dst
, src
, count
, 2, 4);
753 SWZ_CPY(dst
, src
, count
, 2, 3);
756 SWZ_CPY(dst
, src
, count
, 2, 2);
759 SWZ_CPY(dst
, src
, count
, 2, 1);
766 switch (srcComponents
) {
768 SWZ_CPY(dst
, src
, count
, 1, 4);
771 SWZ_CPY(dst
, src
, count
, 1, 3);
774 SWZ_CPY(dst
, src
, count
, 1, 2);
777 SWZ_CPY(dst
, src
, count
, 1, 1);
791 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
792 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
794 /* Deal with the _REV input types:
796 static const GLubyte
*
797 type_mapping( GLenum srcType
)
800 case GL_UNSIGNED_BYTE
:
802 case GL_UNSIGNED_INT_8_8_8_8
:
803 return _mesa_little_endian() ? map_3210
: map_identity
;
804 case GL_UNSIGNED_INT_8_8_8_8_REV
:
805 return _mesa_little_endian() ? map_identity
: map_3210
;
811 /* Mapping required if input type is
813 static const GLubyte
*
814 byteswap_mapping( GLboolean swapBytes
,
821 case GL_UNSIGNED_BYTE
:
823 case GL_UNSIGNED_INT_8_8_8_8
:
824 case GL_UNSIGNED_INT_8_8_8_8_REV
:
834 * Transfer a GLubyte texture image with component swizzling.
837 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
842 GLenum baseInternalFormat
,
844 const GLubyte
*rgba2dst
,
845 GLuint dstComponents
,
848 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
850 const GLuint
*dstImageOffsets
,
852 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
853 const GLvoid
*srcAddr
,
854 const struct gl_pixelstore_attrib
*srcPacking
)
856 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
857 const GLubyte
*srctype2ubyte
, *swap
;
858 GLubyte map
[4], src2base
[6], base2rgba
[6];
860 const GLint srcRowStride
=
861 _mesa_image_row_stride(srcPacking
, srcWidth
,
862 srcFormat
, GL_UNSIGNED_BYTE
);
863 const GLint srcImageStride
864 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
866 const GLubyte
*srcImage
867 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
868 srcWidth
, srcHeight
, srcFormat
,
869 GL_UNSIGNED_BYTE
, 0, 0, 0);
873 /* Translate from src->baseInternal->GL_RGBA->dst. This will
874 * correctly deal with RGBA->RGB->RGBA conversions where the final
875 * A value must be 0xff regardless of the incoming alpha values.
877 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
878 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
879 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
880 srctype2ubyte
= type_mapping(srcType
);
883 for (i
= 0; i
< 4; i
++)
884 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
886 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
888 if (srcRowStride
== dstRowStride
&&
889 srcComponents
== dstComponents
&&
890 srcRowStride
== srcWidth
* srcComponents
&&
892 /* 1 and 2D images only */
893 GLubyte
*dstImage
= (GLubyte
*) dstAddr
894 + dstYoffset
* dstRowStride
895 + dstXoffset
* dstComponents
;
896 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
897 srcWidth
* srcHeight
);
901 for (img
= 0; img
< srcDepth
; img
++) {
902 const GLubyte
*srcRow
= srcImage
;
903 GLubyte
*dstRow
= (GLubyte
*) dstAddr
904 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
905 + dstYoffset
* dstRowStride
906 + dstXoffset
* dstComponents
;
907 for (row
= 0; row
< srcHeight
; row
++) {
908 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
909 dstRow
+= dstRowStride
;
910 srcRow
+= srcRowStride
;
912 srcImage
+= srcImageStride
;
919 * Teximage storage routine for when a simple memcpy will do.
920 * No pixel transfer operations or special texel encodings allowed.
921 * 1D, 2D and 3D images supported.
924 memcpy_texture(GLcontext
*ctx
,
926 const struct gl_texture_format
*dstFormat
,
928 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
930 const GLuint
*dstImageOffsets
,
931 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
932 GLenum srcFormat
, GLenum srcType
,
933 const GLvoid
*srcAddr
,
934 const struct gl_pixelstore_attrib
*srcPacking
)
936 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
938 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
939 srcWidth
, srcHeight
, srcFormat
, srcType
);
940 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
941 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
942 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
945 /* XXX update/re-enable for dstImageOffsets array */
946 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
947 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
948 GLubyte
*dstImage
= (GLubyte
*) dstAddr
949 + dstZoffset
* dstImageStride
950 + dstYoffset
* dstRowStride
951 + dstXoffset
* dstFormat
->TexelBytes
;
953 if (dstRowStride
== srcRowStride
&&
954 dstRowStride
== bytesPerRow
&&
955 ((dstImageStride
== srcImageStride
&&
956 dstImageStride
== bytesPerImage
) ||
959 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
964 for (img
= 0; img
< srcDepth
; img
++) {
965 const GLubyte
*srcRow
= srcImage
;
966 GLubyte
*dstRow
= dstImage
;
967 for (row
= 0; row
< srcHeight
; row
++) {
968 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
969 dstRow
+= dstRowStride
;
970 srcRow
+= srcRowStride
;
972 srcImage
+= srcImageStride
;
973 dstImage
+= dstImageStride
;
979 for (img
= 0; img
< srcDepth
; img
++) {
980 const GLubyte
*srcRow
= srcImage
;
981 GLubyte
*dstRow
= (GLubyte
*) dstAddr
982 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
983 + dstYoffset
* dstRowStride
984 + dstXoffset
* dstFormat
->TexelBytes
;
985 for (row
= 0; row
< srcHeight
; row
++) {
986 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
987 dstRow
+= dstRowStride
;
988 srcRow
+= srcRowStride
;
990 srcImage
+= srcImageStride
;
997 * Store an image in any of the formats:
998 * _mesa_texformat_rgba
999 * _mesa_texformat_rgb
1000 * _mesa_texformat_alpha
1001 * _mesa_texformat_luminance
1002 * _mesa_texformat_luminance_alpha
1003 * _mesa_texformat_intensity
1007 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
1009 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1011 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
1012 dstFormat
== &_mesa_texformat_rgb
||
1013 dstFormat
== &_mesa_texformat_alpha
||
1014 dstFormat
== &_mesa_texformat_luminance
||
1015 dstFormat
== &_mesa_texformat_luminance_alpha
||
1016 dstFormat
== &_mesa_texformat_intensity
);
1017 ASSERT(baseInternalFormat
== GL_RGBA
||
1018 baseInternalFormat
== GL_RGB
||
1019 baseInternalFormat
== GL_ALPHA
||
1020 baseInternalFormat
== GL_LUMINANCE
||
1021 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1022 baseInternalFormat
== GL_INTENSITY
);
1023 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
1025 if (!ctx
->_ImageTransferState
&&
1026 !srcPacking
->SwapBytes
&&
1027 baseInternalFormat
== srcFormat
&&
1028 srcType
== CHAN_TYPE
) {
1029 /* simple memcpy path */
1030 memcpy_texture(ctx
, dims
,
1031 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1034 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1035 srcAddr
, srcPacking
);
1037 else if (!ctx
->_ImageTransferState
&&
1038 !srcPacking
->SwapBytes
&&
1039 dstFormat
== &_mesa_texformat_rgb
&&
1040 srcFormat
== GL_RGBA
&&
1041 srcType
== CHAN_TYPE
) {
1042 /* extract RGB from RGBA */
1043 GLint img
, row
, col
;
1044 for (img
= 0; img
< srcDepth
; img
++) {
1045 GLchan
*dstImage
= (GLchan
*)
1046 ((GLubyte
*) dstAddr
1047 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1048 + dstYoffset
* dstRowStride
1049 + dstXoffset
* dstFormat
->TexelBytes
);
1051 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1052 srcWidth
, srcFormat
, srcType
);
1053 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
1054 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1055 GLchan
*dstRow
= dstImage
;
1056 for (row
= 0; row
< srcHeight
; row
++) {
1057 for (col
= 0; col
< srcWidth
; col
++) {
1058 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
1059 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
1060 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
1062 dstRow
+= dstRowStride
/ sizeof(GLchan
);
1063 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
1067 else if (!ctx
->_ImageTransferState
&&
1068 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
1069 (srcType
== GL_UNSIGNED_BYTE
||
1070 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1071 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1072 can_swizzle(baseInternalFormat
) &&
1073 can_swizzle(srcFormat
)) {
1075 const GLubyte
*dstmap
;
1078 /* dstmap - how to swizzle from RGBA to dst format:
1080 if (dstFormat
== &_mesa_texformat_rgba
) {
1081 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1084 else if (dstFormat
== &_mesa_texformat_rgb
) {
1085 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1088 else if (dstFormat
== &_mesa_texformat_alpha
) {
1089 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1092 else if (dstFormat
== &_mesa_texformat_luminance
) {
1093 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1096 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1097 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1100 else if (dstFormat
== &_mesa_texformat_intensity
) {
1101 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1105 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1109 _mesa_swizzle_ubyte_image(ctx
, dims
,
1114 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1115 dstRowStride
, dstImageOffsets
,
1116 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1121 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1123 dstFormat
->BaseFormat
,
1124 srcWidth
, srcHeight
, srcDepth
,
1125 srcFormat
, srcType
, srcAddr
,
1127 const GLchan
*src
= tempImage
;
1132 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1133 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1134 for (img
= 0; img
< srcDepth
; img
++) {
1135 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1136 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1137 + dstYoffset
* dstRowStride
1138 + dstXoffset
* dstFormat
->TexelBytes
;
1139 for (row
= 0; row
< srcHeight
; row
++) {
1140 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1141 dstRow
+= dstRowStride
;
1142 src
+= srcWidth
* components
;
1146 _mesa_free((void *) tempImage
);
1153 * Store a 32-bit integer depth component texture image.
1156 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1158 const GLuint depthScale
= 0xffffffff;
1160 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1161 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1163 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
1164 ctx
->Pixel
.DepthBias
== 0.0f
&&
1165 !srcPacking
->SwapBytes
&&
1166 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1167 srcFormat
== GL_DEPTH_COMPONENT
&&
1168 srcType
== GL_UNSIGNED_INT
) {
1169 /* simple memcpy path */
1170 memcpy_texture(ctx
, dims
,
1171 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1174 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1175 srcAddr
, srcPacking
);
1180 for (img
= 0; img
< srcDepth
; img
++) {
1181 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1182 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1183 + dstYoffset
* dstRowStride
1184 + dstXoffset
* dstFormat
->TexelBytes
;
1185 for (row
= 0; row
< srcHeight
; row
++) {
1186 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1187 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1188 _mesa_unpack_depth_span(ctx
, srcWidth
,
1189 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1190 depthScale
, srcType
, src
, srcPacking
);
1191 dstRow
+= dstRowStride
;
1201 * Store a 16-bit integer depth component texture image.
1204 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1206 const GLuint depthScale
= 0xffff;
1208 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1209 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1211 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
1212 ctx
->Pixel
.DepthBias
== 0.0f
&&
1213 !srcPacking
->SwapBytes
&&
1214 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1215 srcFormat
== GL_DEPTH_COMPONENT
&&
1216 srcType
== GL_UNSIGNED_SHORT
) {
1217 /* simple memcpy path */
1218 memcpy_texture(ctx
, dims
,
1219 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1222 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1223 srcAddr
, srcPacking
);
1228 for (img
= 0; img
< srcDepth
; img
++) {
1229 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1230 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1231 + dstYoffset
* dstRowStride
1232 + dstXoffset
* dstFormat
->TexelBytes
;
1233 for (row
= 0; row
< srcHeight
; row
++) {
1234 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1235 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1236 GLushort
*dst16
= (GLushort
*) dstRow
;
1237 _mesa_unpack_depth_span(ctx
, srcWidth
,
1238 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1239 srcType
, src
, srcPacking
);
1240 dstRow
+= dstRowStride
;
1249 * Store an rgb565 or rgb565_rev texture image.
1252 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1254 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1255 dstFormat
== &_mesa_texformat_rgb565_rev
);
1256 ASSERT(dstFormat
->TexelBytes
== 2);
1258 if (!ctx
->_ImageTransferState
&&
1259 !srcPacking
->SwapBytes
&&
1260 dstFormat
== &_mesa_texformat_rgb565
&&
1261 baseInternalFormat
== GL_RGB
&&
1262 srcFormat
== GL_RGB
&&
1263 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1264 /* simple memcpy path */
1265 memcpy_texture(ctx
, dims
,
1266 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1269 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1270 srcAddr
, srcPacking
);
1272 else if (!ctx
->_ImageTransferState
&&
1273 !srcPacking
->SwapBytes
&&
1274 baseInternalFormat
== GL_RGB
&&
1275 srcFormat
== GL_RGB
&&
1276 srcType
== GL_UNSIGNED_BYTE
&&
1278 /* do optimized tex store */
1279 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1280 srcFormat
, srcType
);
1281 const GLubyte
*src
= (const GLubyte
*)
1282 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1283 srcFormat
, srcType
, 0, 0, 0);
1284 GLubyte
*dst
= (GLubyte
*) dstAddr
1285 + dstYoffset
* dstRowStride
1286 + dstXoffset
* dstFormat
->TexelBytes
;
1288 for (row
= 0; row
< srcHeight
; row
++) {
1289 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1290 GLushort
*dstUS
= (GLushort
*) dst
;
1291 /* check for byteswapped format */
1292 if (dstFormat
== &_mesa_texformat_rgb565
) {
1293 for (col
= 0; col
< srcWidth
; col
++) {
1294 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1299 for (col
= 0; col
< srcWidth
; col
++) {
1300 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1304 dst
+= dstRowStride
;
1305 src
+= srcRowStride
;
1310 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1312 dstFormat
->BaseFormat
,
1313 srcWidth
, srcHeight
, srcDepth
,
1314 srcFormat
, srcType
, srcAddr
,
1316 const GLchan
*src
= tempImage
;
1317 GLint img
, row
, col
;
1320 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1321 for (img
= 0; img
< srcDepth
; img
++) {
1322 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1323 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1324 + dstYoffset
* dstRowStride
1325 + dstXoffset
* dstFormat
->TexelBytes
;
1326 for (row
= 0; row
< srcHeight
; row
++) {
1327 GLushort
*dstUS
= (GLushort
*) dstRow
;
1328 /* check for byteswapped format */
1329 if (dstFormat
== &_mesa_texformat_rgb565
) {
1330 for (col
= 0; col
< srcWidth
; col
++) {
1331 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1332 CHAN_TO_UBYTE(src
[GCOMP
]),
1333 CHAN_TO_UBYTE(src
[BCOMP
]) );
1338 for (col
= 0; col
< srcWidth
; col
++) {
1339 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1340 CHAN_TO_UBYTE(src
[GCOMP
]),
1341 CHAN_TO_UBYTE(src
[BCOMP
]) );
1345 dstRow
+= dstRowStride
;
1348 _mesa_free((void *) tempImage
);
1355 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1358 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1360 const GLboolean littleEndian
= _mesa_little_endian();
1362 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1363 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1364 ASSERT(dstFormat
->TexelBytes
== 4);
1366 if (!ctx
->_ImageTransferState
&&
1367 !srcPacking
->SwapBytes
&&
1368 dstFormat
== &_mesa_texformat_rgba8888
&&
1369 baseInternalFormat
== GL_RGBA
&&
1370 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1371 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1372 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1373 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1374 /* simple memcpy path */
1375 memcpy_texture(ctx
, dims
,
1376 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1379 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1380 srcAddr
, srcPacking
);
1382 else if (!ctx
->_ImageTransferState
&&
1383 !srcPacking
->SwapBytes
&&
1384 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1385 baseInternalFormat
== GL_RGBA
&&
1386 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1387 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1388 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1389 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1390 /* simple memcpy path */
1391 memcpy_texture(ctx
, dims
,
1392 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1395 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1396 srcAddr
, srcPacking
);
1398 else if (!ctx
->_ImageTransferState
&&
1399 (srcType
== GL_UNSIGNED_BYTE
||
1400 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1401 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1402 can_swizzle(baseInternalFormat
) &&
1403 can_swizzle(srcFormat
)) {
1407 /* dstmap - how to swizzle from RGBA to dst format:
1409 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1410 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1423 _mesa_swizzle_ubyte_image(ctx
, dims
,
1428 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1429 dstRowStride
, dstImageOffsets
,
1430 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1435 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1437 dstFormat
->BaseFormat
,
1438 srcWidth
, srcHeight
, srcDepth
,
1439 srcFormat
, srcType
, srcAddr
,
1441 const GLchan
*src
= tempImage
;
1442 GLint img
, row
, col
;
1445 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1446 for (img
= 0; img
< srcDepth
; img
++) {
1447 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1448 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1449 + dstYoffset
* dstRowStride
1450 + dstXoffset
* dstFormat
->TexelBytes
;
1451 for (row
= 0; row
< srcHeight
; row
++) {
1452 GLuint
*dstUI
= (GLuint
*) dstRow
;
1453 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1454 for (col
= 0; col
< srcWidth
; col
++) {
1455 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1456 CHAN_TO_UBYTE(src
[GCOMP
]),
1457 CHAN_TO_UBYTE(src
[BCOMP
]),
1458 CHAN_TO_UBYTE(src
[ACOMP
]) );
1463 for (col
= 0; col
< srcWidth
; col
++) {
1464 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1465 CHAN_TO_UBYTE(src
[GCOMP
]),
1466 CHAN_TO_UBYTE(src
[BCOMP
]),
1467 CHAN_TO_UBYTE(src
[ACOMP
]) );
1471 dstRow
+= dstRowStride
;
1474 _mesa_free((void *) tempImage
);
1481 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1483 const GLboolean littleEndian
= _mesa_little_endian();
1485 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1486 dstFormat
== &_mesa_texformat_argb8888_rev
);
1487 ASSERT(dstFormat
->TexelBytes
== 4);
1489 if (!ctx
->_ImageTransferState
&&
1490 !srcPacking
->SwapBytes
&&
1491 dstFormat
== &_mesa_texformat_argb8888
&&
1492 baseInternalFormat
== GL_RGBA
&&
1493 srcFormat
== GL_BGRA
&&
1494 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1495 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1496 /* simple memcpy path (little endian) */
1497 memcpy_texture(ctx
, dims
,
1498 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1501 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1502 srcAddr
, srcPacking
);
1504 else if (!ctx
->_ImageTransferState
&&
1505 !srcPacking
->SwapBytes
&&
1506 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1507 baseInternalFormat
== GL_RGBA
&&
1508 srcFormat
== GL_BGRA
&&
1509 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1510 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1511 /* simple memcpy path (big endian) */
1512 memcpy_texture(ctx
, dims
,
1513 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1516 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1517 srcAddr
, srcPacking
);
1519 else if (!ctx
->_ImageTransferState
&&
1520 !srcPacking
->SwapBytes
&&
1521 dstFormat
== &_mesa_texformat_argb8888
&&
1522 srcFormat
== GL_RGB
&&
1523 (baseInternalFormat
== GL_RGBA
||
1524 baseInternalFormat
== GL_RGB
) &&
1525 srcType
== GL_UNSIGNED_BYTE
) {
1527 for (img
= 0; img
< srcDepth
; img
++) {
1528 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1529 srcWidth
, srcFormat
, srcType
);
1530 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1531 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1532 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1533 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1534 + dstYoffset
* dstRowStride
1535 + dstXoffset
* dstFormat
->TexelBytes
;
1536 for (row
= 0; row
< srcHeight
; row
++) {
1537 GLuint
*d4
= (GLuint
*) dstRow
;
1538 for (col
= 0; col
< srcWidth
; col
++) {
1539 d4
[col
] = PACK_COLOR_8888(0xff,
1540 srcRow
[col
* 3 + RCOMP
],
1541 srcRow
[col
* 3 + GCOMP
],
1542 srcRow
[col
* 3 + BCOMP
]);
1544 dstRow
+= dstRowStride
;
1545 srcRow
+= srcRowStride
;
1549 else if (!ctx
->_ImageTransferState
&&
1550 !srcPacking
->SwapBytes
&&
1551 dstFormat
== &_mesa_texformat_argb8888
&&
1552 srcFormat
== GL_RGBA
&&
1553 baseInternalFormat
== GL_RGBA
&&
1554 srcType
== GL_UNSIGNED_BYTE
) {
1555 /* same as above case, but src data has alpha too */
1556 GLint img
, row
, col
;
1557 /* For some reason, streaming copies to write-combined regions
1558 * are extremely sensitive to the characteristics of how the
1559 * source data is retrieved. By reordering the source reads to
1560 * be in-order, the speed of this operation increases by half.
1561 * Strangely the same isn't required for the RGB path, above.
1563 for (img
= 0; img
< srcDepth
; img
++) {
1564 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1565 srcWidth
, srcFormat
, srcType
);
1566 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1567 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1568 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1569 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1570 + dstYoffset
* dstRowStride
1571 + dstXoffset
* dstFormat
->TexelBytes
;
1572 for (row
= 0; row
< srcHeight
; row
++) {
1573 GLuint
*d4
= (GLuint
*) dstRow
;
1574 for (col
= 0; col
< srcWidth
; col
++) {
1575 d4
[col
] = PACK_COLOR_8888(srcRow
[col
* 4 + ACOMP
],
1576 srcRow
[col
* 4 + RCOMP
],
1577 srcRow
[col
* 4 + GCOMP
],
1578 srcRow
[col
* 4 + BCOMP
]);
1580 dstRow
+= dstRowStride
;
1581 srcRow
+= srcRowStride
;
1585 else if (!ctx
->_ImageTransferState
&&
1586 (srcType
== GL_UNSIGNED_BYTE
||
1587 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1588 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1589 can_swizzle(baseInternalFormat
) &&
1590 can_swizzle(srcFormat
)) {
1594 /* dstmap - how to swizzle from RGBA to dst format:
1596 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1597 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1598 dstmap
[3] = 3; /* alpha */
1599 dstmap
[2] = 0; /* red */
1600 dstmap
[1] = 1; /* green */
1601 dstmap
[0] = 2; /* blue */
1604 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1605 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1612 _mesa_swizzle_ubyte_image(ctx
, dims
,
1618 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1621 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1626 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1628 dstFormat
->BaseFormat
,
1629 srcWidth
, srcHeight
, srcDepth
,
1630 srcFormat
, srcType
, srcAddr
,
1632 const GLchan
*src
= tempImage
;
1633 GLint img
, row
, col
;
1636 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1637 for (img
= 0; img
< srcDepth
; img
++) {
1638 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1639 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1640 + dstYoffset
* dstRowStride
1641 + dstXoffset
* dstFormat
->TexelBytes
;
1642 for (row
= 0; row
< srcHeight
; row
++) {
1643 GLuint
*dstUI
= (GLuint
*) dstRow
;
1644 if (dstFormat
== &_mesa_texformat_argb8888
) {
1645 for (col
= 0; col
< srcWidth
; col
++) {
1646 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1647 CHAN_TO_UBYTE(src
[RCOMP
]),
1648 CHAN_TO_UBYTE(src
[GCOMP
]),
1649 CHAN_TO_UBYTE(src
[BCOMP
]) );
1654 for (col
= 0; col
< srcWidth
; col
++) {
1655 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1656 CHAN_TO_UBYTE(src
[RCOMP
]),
1657 CHAN_TO_UBYTE(src
[GCOMP
]),
1658 CHAN_TO_UBYTE(src
[BCOMP
]) );
1662 dstRow
+= dstRowStride
;
1665 _mesa_free((void *) tempImage
);
1672 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1674 const GLboolean littleEndian
= _mesa_little_endian();
1676 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1677 ASSERT(dstFormat
->TexelBytes
== 3);
1679 if (!ctx
->_ImageTransferState
&&
1680 !srcPacking
->SwapBytes
&&
1681 baseInternalFormat
== GL_RGB
&&
1682 srcFormat
== GL_BGR
&&
1683 srcType
== GL_UNSIGNED_BYTE
&&
1685 /* simple memcpy path */
1686 memcpy_texture(ctx
, dims
,
1687 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1690 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1691 srcAddr
, srcPacking
);
1693 else if (!ctx
->_ImageTransferState
&&
1694 !srcPacking
->SwapBytes
&&
1695 srcFormat
== GL_RGBA
&&
1696 srcType
== GL_UNSIGNED_BYTE
) {
1697 /* extract RGB from RGBA */
1698 GLint img
, row
, col
;
1699 for (img
= 0; img
< srcDepth
; img
++) {
1700 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1701 srcWidth
, srcFormat
, srcType
);
1702 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1703 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1704 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1705 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1706 + dstYoffset
* dstRowStride
1707 + dstXoffset
* dstFormat
->TexelBytes
;
1708 for (row
= 0; row
< srcHeight
; row
++) {
1709 for (col
= 0; col
< srcWidth
; col
++) {
1710 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1711 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1712 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1714 dstRow
+= dstRowStride
;
1715 srcRow
+= srcRowStride
;
1719 else if (!ctx
->_ImageTransferState
&&
1720 srcType
== GL_UNSIGNED_BYTE
&&
1721 can_swizzle(baseInternalFormat
) &&
1722 can_swizzle(srcFormat
)) {
1726 /* dstmap - how to swizzle from RGBA to dst format:
1731 dstmap
[3] = ONE
; /* ? */
1733 _mesa_swizzle_ubyte_image(ctx
, dims
,
1738 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1739 dstRowStride
, dstImageOffsets
,
1740 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1745 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1747 dstFormat
->BaseFormat
,
1748 srcWidth
, srcHeight
, srcDepth
,
1749 srcFormat
, srcType
, srcAddr
,
1751 const GLchan
*src
= (const GLchan
*) tempImage
;
1752 GLint img
, row
, col
;
1755 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1756 for (img
= 0; img
< srcDepth
; img
++) {
1757 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1758 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1759 + dstYoffset
* dstRowStride
1760 + dstXoffset
* dstFormat
->TexelBytes
;
1761 for (row
= 0; row
< srcHeight
; row
++) {
1764 for (col
= 0; col
< srcWidth
; col
++) {
1765 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1766 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1767 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1772 for (col
= 0; col
< srcWidth
; col
++) {
1773 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1774 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1775 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1780 for (col
= 0; col
< srcWidth
; col
++) {
1781 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1782 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1783 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1787 dstRow
+= dstRowStride
;
1790 _mesa_free((void *) tempImage
);
1797 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1799 const GLboolean littleEndian
= _mesa_little_endian();
1801 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1802 ASSERT(dstFormat
->TexelBytes
== 3);
1804 if (!ctx
->_ImageTransferState
&&
1805 !srcPacking
->SwapBytes
&&
1806 baseInternalFormat
== GL_RGB
&&
1807 srcFormat
== GL_RGB
&&
1808 srcType
== GL_UNSIGNED_BYTE
&&
1810 /* simple memcpy path */
1811 memcpy_texture(ctx
, dims
,
1812 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1815 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1816 srcAddr
, srcPacking
);
1818 else if (!ctx
->_ImageTransferState
&&
1819 !srcPacking
->SwapBytes
&&
1820 srcFormat
== GL_RGBA
&&
1821 srcType
== GL_UNSIGNED_BYTE
) {
1822 /* extract BGR from RGBA */
1824 for (img
= 0; img
< srcDepth
; img
++) {
1825 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1826 srcWidth
, srcFormat
, srcType
);
1827 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1828 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1829 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1830 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1831 + dstYoffset
* dstRowStride
1832 + dstXoffset
* dstFormat
->TexelBytes
;
1833 for (row
= 0; row
< srcHeight
; row
++) {
1834 for (col
= 0; col
< srcWidth
; col
++) {
1835 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1836 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1837 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1839 dstRow
+= dstRowStride
;
1840 srcRow
+= srcRowStride
;
1844 else if (!ctx
->_ImageTransferState
&&
1845 srcType
== GL_UNSIGNED_BYTE
&&
1846 can_swizzle(baseInternalFormat
) &&
1847 can_swizzle(srcFormat
)) {
1851 /* dstmap - how to swizzle from RGBA to dst format:
1856 dstmap
[3] = ONE
; /* ? */
1858 _mesa_swizzle_ubyte_image(ctx
, dims
,
1863 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1864 dstRowStride
, dstImageOffsets
,
1865 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1870 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1872 dstFormat
->BaseFormat
,
1873 srcWidth
, srcHeight
, srcDepth
,
1874 srcFormat
, srcType
, srcAddr
,
1876 const GLchan
*src
= (const GLchan
*) tempImage
;
1877 GLint img
, row
, col
;
1880 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1881 for (img
= 0; img
< srcDepth
; img
++) {
1882 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1883 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1884 + dstYoffset
* dstRowStride
1885 + dstXoffset
* dstFormat
->TexelBytes
;
1886 for (row
= 0; row
< srcHeight
; row
++) {
1887 for (col
= 0; col
< srcWidth
; col
++) {
1888 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1889 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1890 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1893 dstRow
+= dstRowStride
;
1896 _mesa_free((void *) tempImage
);
1902 _mesa_texstore_rgba4444(TEXSTORE_PARAMS
)
1904 ASSERT(dstFormat
== &_mesa_texformat_rgba4444
);
1905 ASSERT(dstFormat
->TexelBytes
== 2);
1907 if (!ctx
->_ImageTransferState
&&
1908 !srcPacking
->SwapBytes
&&
1909 dstFormat
== &_mesa_texformat_rgba4444
&&
1910 baseInternalFormat
== GL_RGBA
&&
1911 srcFormat
== GL_RGBA
&&
1912 srcType
== GL_UNSIGNED_SHORT_4_4_4_4
){
1913 /* simple memcpy path */
1914 memcpy_texture(ctx
, dims
,
1915 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1918 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1919 srcAddr
, srcPacking
);
1923 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1925 dstFormat
->BaseFormat
,
1926 srcWidth
, srcHeight
, srcDepth
,
1927 srcFormat
, srcType
, srcAddr
,
1929 const GLchan
*src
= tempImage
;
1930 GLint img
, row
, col
;
1933 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1934 for (img
= 0; img
< srcDepth
; img
++) {
1935 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1936 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1937 + dstYoffset
* dstRowStride
1938 + dstXoffset
* dstFormat
->TexelBytes
;
1939 for (row
= 0; row
< srcHeight
; row
++) {
1940 GLushort
*dstUS
= (GLushort
*) dstRow
;
1941 for (col
= 0; col
< srcWidth
; col
++) {
1942 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[RCOMP
]),
1943 CHAN_TO_UBYTE(src
[GCOMP
]),
1944 CHAN_TO_UBYTE(src
[BCOMP
]),
1945 CHAN_TO_UBYTE(src
[ACOMP
]) );
1948 dstRow
+= dstRowStride
;
1951 _mesa_free((void *) tempImage
);
1957 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1959 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1960 dstFormat
== &_mesa_texformat_argb4444_rev
);
1961 ASSERT(dstFormat
->TexelBytes
== 2);
1963 if (!ctx
->_ImageTransferState
&&
1964 !srcPacking
->SwapBytes
&&
1965 dstFormat
== &_mesa_texformat_argb4444
&&
1966 baseInternalFormat
== GL_RGBA
&&
1967 srcFormat
== GL_BGRA
&&
1968 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1969 /* simple memcpy path */
1970 memcpy_texture(ctx
, dims
,
1971 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1974 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1975 srcAddr
, srcPacking
);
1979 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1981 dstFormat
->BaseFormat
,
1982 srcWidth
, srcHeight
, srcDepth
,
1983 srcFormat
, srcType
, srcAddr
,
1985 const GLchan
*src
= tempImage
;
1986 GLint img
, row
, col
;
1989 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1990 for (img
= 0; img
< srcDepth
; img
++) {
1991 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1992 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1993 + dstYoffset
* dstRowStride
1994 + dstXoffset
* dstFormat
->TexelBytes
;
1995 for (row
= 0; row
< srcHeight
; row
++) {
1996 GLushort
*dstUS
= (GLushort
*) dstRow
;
1997 if (dstFormat
== &_mesa_texformat_argb4444
) {
1998 for (col
= 0; col
< srcWidth
; col
++) {
1999 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
2000 CHAN_TO_UBYTE(src
[RCOMP
]),
2001 CHAN_TO_UBYTE(src
[GCOMP
]),
2002 CHAN_TO_UBYTE(src
[BCOMP
]) );
2007 for (col
= 0; col
< srcWidth
; col
++) {
2008 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
2009 CHAN_TO_UBYTE(src
[RCOMP
]),
2010 CHAN_TO_UBYTE(src
[GCOMP
]),
2011 CHAN_TO_UBYTE(src
[BCOMP
]) );
2015 dstRow
+= dstRowStride
;
2018 _mesa_free((void *) tempImage
);
2024 _mesa_texstore_rgba5551(TEXSTORE_PARAMS
)
2026 ASSERT(dstFormat
== &_mesa_texformat_rgba5551
);
2027 ASSERT(dstFormat
->TexelBytes
== 2);
2029 if (!ctx
->_ImageTransferState
&&
2030 !srcPacking
->SwapBytes
&&
2031 dstFormat
== &_mesa_texformat_rgba5551
&&
2032 baseInternalFormat
== GL_RGBA
&&
2033 srcFormat
== GL_RGBA
&&
2034 srcType
== GL_UNSIGNED_SHORT_5_5_5_1
) {
2035 /* simple memcpy path */
2036 memcpy_texture(ctx
, dims
,
2037 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2040 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2041 srcAddr
, srcPacking
);
2045 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2047 dstFormat
->BaseFormat
,
2048 srcWidth
, srcHeight
, srcDepth
,
2049 srcFormat
, srcType
, srcAddr
,
2051 const GLchan
*src
=tempImage
;
2052 GLint img
, row
, col
;
2055 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2056 for (img
= 0; img
< srcDepth
; img
++) {
2057 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2058 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2059 + dstYoffset
* dstRowStride
2060 + dstXoffset
* dstFormat
->TexelBytes
;
2061 for (row
= 0; row
< srcHeight
; row
++) {
2062 GLushort
*dstUS
= (GLushort
*) dstRow
;
2063 for (col
= 0; col
< srcWidth
; col
++) {
2064 dstUS
[col
] = PACK_COLOR_5551( CHAN_TO_UBYTE(src
[RCOMP
]),
2065 CHAN_TO_UBYTE(src
[GCOMP
]),
2066 CHAN_TO_UBYTE(src
[BCOMP
]),
2067 CHAN_TO_UBYTE(src
[ACOMP
]) );
2070 dstRow
+= dstRowStride
;
2073 _mesa_free((void *) tempImage
);
2079 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
2081 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
2082 dstFormat
== &_mesa_texformat_argb1555_rev
);
2083 ASSERT(dstFormat
->TexelBytes
== 2);
2085 if (!ctx
->_ImageTransferState
&&
2086 !srcPacking
->SwapBytes
&&
2087 dstFormat
== &_mesa_texformat_argb1555
&&
2088 baseInternalFormat
== GL_RGBA
&&
2089 srcFormat
== GL_BGRA
&&
2090 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
2091 /* simple memcpy path */
2092 memcpy_texture(ctx
, dims
,
2093 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2096 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2097 srcAddr
, srcPacking
);
2101 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2103 dstFormat
->BaseFormat
,
2104 srcWidth
, srcHeight
, srcDepth
,
2105 srcFormat
, srcType
, srcAddr
,
2107 const GLchan
*src
=tempImage
;
2108 GLint img
, row
, col
;
2111 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2112 for (img
= 0; img
< srcDepth
; img
++) {
2113 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2114 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2115 + dstYoffset
* dstRowStride
2116 + dstXoffset
* dstFormat
->TexelBytes
;
2117 for (row
= 0; row
< srcHeight
; row
++) {
2118 GLushort
*dstUS
= (GLushort
*) dstRow
;
2119 if (dstFormat
== &_mesa_texformat_argb1555
) {
2120 for (col
= 0; col
< srcWidth
; col
++) {
2121 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
2122 CHAN_TO_UBYTE(src
[RCOMP
]),
2123 CHAN_TO_UBYTE(src
[GCOMP
]),
2124 CHAN_TO_UBYTE(src
[BCOMP
]) );
2129 for (col
= 0; col
< srcWidth
; col
++) {
2130 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
2131 CHAN_TO_UBYTE(src
[RCOMP
]),
2132 CHAN_TO_UBYTE(src
[GCOMP
]),
2133 CHAN_TO_UBYTE(src
[BCOMP
]) );
2137 dstRow
+= dstRowStride
;
2140 _mesa_free((void *) tempImage
);
2147 _mesa_texstore_al88(TEXSTORE_PARAMS
)
2149 const GLboolean littleEndian
= _mesa_little_endian();
2151 ASSERT(dstFormat
== &_mesa_texformat_al88
||
2152 dstFormat
== &_mesa_texformat_al88_rev
);
2153 ASSERT(dstFormat
->TexelBytes
== 2);
2155 if (!ctx
->_ImageTransferState
&&
2156 !srcPacking
->SwapBytes
&&
2157 dstFormat
== &_mesa_texformat_al88
&&
2158 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2159 srcFormat
== GL_LUMINANCE_ALPHA
&&
2160 srcType
== GL_UNSIGNED_BYTE
&&
2162 /* simple memcpy path */
2163 memcpy_texture(ctx
, dims
,
2164 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2167 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2168 srcAddr
, srcPacking
);
2170 else if (!ctx
->_ImageTransferState
&&
2172 srcType
== GL_UNSIGNED_BYTE
&&
2173 can_swizzle(baseInternalFormat
) &&
2174 can_swizzle(srcFormat
)) {
2178 /* dstmap - how to swizzle from RGBA to dst format:
2180 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2181 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2189 dstmap
[2] = ZERO
; /* ? */
2190 dstmap
[3] = ONE
; /* ? */
2192 _mesa_swizzle_ubyte_image(ctx
, dims
,
2197 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2198 dstRowStride
, dstImageOffsets
,
2199 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2204 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2206 dstFormat
->BaseFormat
,
2207 srcWidth
, srcHeight
, srcDepth
,
2208 srcFormat
, srcType
, srcAddr
,
2210 const GLchan
*src
= tempImage
;
2211 GLint img
, row
, col
;
2214 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2215 for (img
= 0; img
< srcDepth
; img
++) {
2216 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2217 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2218 + dstYoffset
* dstRowStride
2219 + dstXoffset
* dstFormat
->TexelBytes
;
2220 for (row
= 0; row
< srcHeight
; row
++) {
2221 GLushort
*dstUS
= (GLushort
*) dstRow
;
2222 if (dstFormat
== &_mesa_texformat_al88
) {
2223 for (col
= 0; col
< srcWidth
; col
++) {
2224 /* src[0] is luminance, src[1] is alpha */
2225 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2226 CHAN_TO_UBYTE(src
[0]) );
2231 for (col
= 0; col
< srcWidth
; col
++) {
2232 /* src[0] is luminance, src[1] is alpha */
2233 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2234 CHAN_TO_UBYTE(src
[0]) );
2238 dstRow
+= dstRowStride
;
2241 _mesa_free((void *) tempImage
);
2248 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2250 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2251 ASSERT(dstFormat
->TexelBytes
== 1);
2253 if (!ctx
->_ImageTransferState
&&
2254 !srcPacking
->SwapBytes
&&
2255 baseInternalFormat
== GL_RGB
&&
2256 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2257 /* simple memcpy path */
2258 memcpy_texture(ctx
, dims
,
2259 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2262 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2263 srcAddr
, srcPacking
);
2267 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2269 dstFormat
->BaseFormat
,
2270 srcWidth
, srcHeight
, srcDepth
,
2271 srcFormat
, srcType
, srcAddr
,
2273 const GLchan
*src
= tempImage
;
2274 GLint img
, row
, col
;
2277 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2278 for (img
= 0; img
< srcDepth
; img
++) {
2279 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2280 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2281 + dstYoffset
* dstRowStride
2282 + dstXoffset
* dstFormat
->TexelBytes
;
2283 for (row
= 0; row
< srcHeight
; row
++) {
2284 for (col
= 0; col
< srcWidth
; col
++) {
2285 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2286 CHAN_TO_UBYTE(src
[GCOMP
]),
2287 CHAN_TO_UBYTE(src
[BCOMP
]) );
2290 dstRow
+= dstRowStride
;
2293 _mesa_free((void *) tempImage
);
2300 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2303 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2305 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2306 dstFormat
== &_mesa_texformat_l8
||
2307 dstFormat
== &_mesa_texformat_i8
);
2308 ASSERT(dstFormat
->TexelBytes
== 1);
2310 if (!ctx
->_ImageTransferState
&&
2311 !srcPacking
->SwapBytes
&&
2312 baseInternalFormat
== srcFormat
&&
2313 srcType
== GL_UNSIGNED_BYTE
) {
2314 /* simple memcpy path */
2315 memcpy_texture(ctx
, dims
,
2316 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2319 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2320 srcAddr
, srcPacking
);
2322 else if (!ctx
->_ImageTransferState
&&
2323 srcType
== GL_UNSIGNED_BYTE
&&
2324 can_swizzle(baseInternalFormat
) &&
2325 can_swizzle(srcFormat
)) {
2329 /* dstmap - how to swizzle from RGBA to dst format:
2331 if (dstFormat
== &_mesa_texformat_a8
) {
2337 dstmap
[1] = ZERO
; /* ? */
2338 dstmap
[2] = ZERO
; /* ? */
2339 dstmap
[3] = ONE
; /* ? */
2341 _mesa_swizzle_ubyte_image(ctx
, dims
,
2346 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2347 dstRowStride
, dstImageOffsets
,
2348 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2353 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2355 dstFormat
->BaseFormat
,
2356 srcWidth
, srcHeight
, srcDepth
,
2357 srcFormat
, srcType
, srcAddr
,
2359 const GLchan
*src
= tempImage
;
2360 GLint img
, row
, col
;
2363 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2364 for (img
= 0; img
< srcDepth
; img
++) {
2365 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2366 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2367 + dstYoffset
* dstRowStride
2368 + dstXoffset
* dstFormat
->TexelBytes
;
2369 for (row
= 0; row
< srcHeight
; row
++) {
2370 for (col
= 0; col
< srcWidth
; col
++) {
2371 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2373 dstRow
+= dstRowStride
;
2377 _mesa_free((void *) tempImage
);
2385 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2387 (void) dims
; (void) baseInternalFormat
;
2388 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2389 ASSERT(dstFormat
->TexelBytes
== 1);
2390 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2392 if (!ctx
->_ImageTransferState
&&
2393 !srcPacking
->SwapBytes
&&
2394 srcFormat
== GL_COLOR_INDEX
&&
2395 srcType
== GL_UNSIGNED_BYTE
) {
2396 /* simple memcpy path */
2397 memcpy_texture(ctx
, dims
,
2398 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2401 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2402 srcAddr
, srcPacking
);
2407 for (img
= 0; img
< srcDepth
; img
++) {
2408 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2409 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2410 + dstYoffset
* dstRowStride
2411 + dstXoffset
* dstFormat
->TexelBytes
;
2412 for (row
= 0; row
< srcHeight
; row
++) {
2413 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2414 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2415 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2416 srcType
, src
, srcPacking
,
2417 ctx
->_ImageTransferState
);
2418 dstRow
+= dstRowStride
;
2427 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2430 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2432 const GLboolean littleEndian
= _mesa_little_endian();
2433 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2435 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2436 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2437 ASSERT(dstFormat
->TexelBytes
== 2);
2438 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2439 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2440 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2441 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2442 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2444 /* always just memcpy since no pixel transfer ops apply */
2445 memcpy_texture(ctx
, dims
,
2446 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2449 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2450 srcAddr
, srcPacking
);
2452 /* Check if we need byte swapping */
2453 /* XXX the logic here _might_ be wrong */
2454 if (srcPacking
->SwapBytes
^
2455 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2456 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2459 for (img
= 0; img
< srcDepth
; img
++) {
2460 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2461 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2462 + dstYoffset
* dstRowStride
2463 + dstXoffset
* dstFormat
->TexelBytes
;
2464 for (row
= 0; row
< srcHeight
; row
++) {
2465 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2466 dstRow
+= dstRowStride
;
2476 * Store a combined depth/stencil texture image.
2479 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2481 const GLfloat depthScale
= (GLfloat
) 0xffffff;
2483 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2484 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2485 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2487 if (ctx
->Pixel
.DepthScale
== 1.0f
&&
2488 ctx
->Pixel
.DepthBias
== 0.0f
&&
2489 !srcPacking
->SwapBytes
) {
2491 memcpy_texture(ctx
, dims
,
2492 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2495 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2496 srcAddr
, srcPacking
);
2500 const GLint srcRowStride
2501 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2505 for (img
= 0; img
< srcDepth
; img
++) {
2506 GLuint
*dstRow
= (GLuint
*) dstAddr
2507 + dstImageOffsets
[dstZoffset
+ img
]
2508 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2511 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2512 srcWidth
, srcHeight
,
2515 for (row
= 0; row
< srcHeight
; row
++) {
2516 GLubyte stencil
[MAX_WIDTH
];
2518 /* the 24 depth bits will be in the high position: */
2519 _mesa_unpack_depth_span(ctx
, srcWidth
,
2520 GL_UNSIGNED_INT_24_8_EXT
, /* dst type */
2521 dstRow
, /* dst addr */
2522 (GLuint
) depthScale
,
2523 srcType
, src
, srcPacking
);
2524 /* get the 8-bit stencil values */
2525 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2526 GL_UNSIGNED_BYTE
, /* dst type */
2527 stencil
, /* dst addr */
2528 srcType
, src
, srcPacking
,
2529 ctx
->_ImageTransferState
);
2530 /* merge stencil values into depth values */
2531 for (i
= 0; i
< srcWidth
; i
++)
2532 dstRow
[i
] |= stencil
[i
];
2534 src
+= srcRowStride
;
2535 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2544 * Store a combined depth/stencil texture image.
2547 _mesa_texstore_s8_z24(TEXSTORE_PARAMS
)
2549 const GLuint depthScale
= 0xffffff;
2550 const GLint srcRowStride
2551 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2555 ASSERT(dstFormat
== &_mesa_texformat_s8_z24
);
2556 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
|| srcFormat
== GL_DEPTH_COMPONENT
);
2557 ASSERT(srcFormat
!= GL_DEPTH_STENCIL_EXT
|| srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2559 /* In case we only upload depth we need to preserve the stencil */
2560 if (srcFormat
== GL_DEPTH_COMPONENT
) {
2561 for (img
= 0; img
< srcDepth
; img
++) {
2562 GLuint
*dstRow
= (GLuint
*) dstAddr
2563 + dstImageOffsets
[dstZoffset
+ img
]
2564 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2567 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2568 srcWidth
, srcHeight
,
2571 for (row
= 0; row
< srcHeight
; row
++) {
2572 GLuint depth
[MAX_WIDTH
];
2574 _mesa_unpack_depth_span(ctx
, srcWidth
,
2575 GL_UNSIGNED_INT
, /* dst type */
2576 depth
, /* dst addr */
2578 srcType
, src
, srcPacking
);
2580 for (i
= 0; i
< srcWidth
; i
++)
2581 dstRow
[i
] = depth
[i
] | (dstRow
[i
] & 0xFF000000);
2583 src
+= srcRowStride
;
2584 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2589 for (img
= 0; img
< srcDepth
; img
++) {
2590 GLuint
*dstRow
= (GLuint
*) dstAddr
2591 + dstImageOffsets
[dstZoffset
+ img
]
2592 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2595 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2596 srcWidth
, srcHeight
,
2599 for (row
= 0; row
< srcHeight
; row
++) {
2600 GLubyte stencil
[MAX_WIDTH
];
2602 /* the 24 depth bits will be in the low position: */
2603 _mesa_unpack_depth_span(ctx
, srcWidth
,
2604 GL_UNSIGNED_INT
, /* dst type */
2605 dstRow
, /* dst addr */
2607 srcType
, src
, srcPacking
);
2608 /* get the 8-bit stencil values */
2609 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2610 GL_UNSIGNED_BYTE
, /* dst type */
2611 stencil
, /* dst addr */
2612 srcType
, src
, srcPacking
,
2613 ctx
->_ImageTransferState
);
2614 /* merge stencil values into depth values */
2615 for (i
= 0; i
< srcWidth
; i
++)
2616 dstRow
[i
] |= stencil
[i
] << 24;
2618 src
+= srcRowStride
;
2619 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2627 * Store an image in any of the formats:
2628 * _mesa_texformat_rgba_float32
2629 * _mesa_texformat_rgb_float32
2630 * _mesa_texformat_alpha_float32
2631 * _mesa_texformat_luminance_float32
2632 * _mesa_texformat_luminance_alpha_float32
2633 * _mesa_texformat_intensity_float32
2636 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2638 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2640 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2641 dstFormat
== &_mesa_texformat_rgb_float32
||
2642 dstFormat
== &_mesa_texformat_alpha_float32
||
2643 dstFormat
== &_mesa_texformat_luminance_float32
||
2644 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2645 dstFormat
== &_mesa_texformat_intensity_float32
);
2646 ASSERT(baseInternalFormat
== GL_RGBA
||
2647 baseInternalFormat
== GL_RGB
||
2648 baseInternalFormat
== GL_ALPHA
||
2649 baseInternalFormat
== GL_LUMINANCE
||
2650 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2651 baseInternalFormat
== GL_INTENSITY
);
2652 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2654 if (!ctx
->_ImageTransferState
&&
2655 !srcPacking
->SwapBytes
&&
2656 baseInternalFormat
== srcFormat
&&
2657 srcType
== GL_FLOAT
) {
2658 /* simple memcpy path */
2659 memcpy_texture(ctx
, dims
,
2660 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2663 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2664 srcAddr
, srcPacking
);
2668 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2670 dstFormat
->BaseFormat
,
2671 srcWidth
, srcHeight
, srcDepth
,
2672 srcFormat
, srcType
, srcAddr
,
2674 const GLfloat
*srcRow
= tempImage
;
2679 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2680 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2681 for (img
= 0; img
< srcDepth
; img
++) {
2682 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2683 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2684 + dstYoffset
* dstRowStride
2685 + dstXoffset
* dstFormat
->TexelBytes
;
2686 for (row
= 0; row
< srcHeight
; row
++) {
2687 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2688 dstRow
+= dstRowStride
;
2689 srcRow
+= srcWidth
* components
;
2693 _mesa_free((void *) tempImage
);
2700 * As above, but store 16-bit floats.
2703 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2705 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2707 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2708 dstFormat
== &_mesa_texformat_rgb_float16
||
2709 dstFormat
== &_mesa_texformat_alpha_float16
||
2710 dstFormat
== &_mesa_texformat_luminance_float16
||
2711 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2712 dstFormat
== &_mesa_texformat_intensity_float16
);
2713 ASSERT(baseInternalFormat
== GL_RGBA
||
2714 baseInternalFormat
== GL_RGB
||
2715 baseInternalFormat
== GL_ALPHA
||
2716 baseInternalFormat
== GL_LUMINANCE
||
2717 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2718 baseInternalFormat
== GL_INTENSITY
);
2719 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2721 if (!ctx
->_ImageTransferState
&&
2722 !srcPacking
->SwapBytes
&&
2723 baseInternalFormat
== srcFormat
&&
2724 srcType
== GL_HALF_FLOAT_ARB
) {
2725 /* simple memcpy path */
2726 memcpy_texture(ctx
, dims
,
2727 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2730 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2731 srcAddr
, srcPacking
);
2735 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2737 dstFormat
->BaseFormat
,
2738 srcWidth
, srcHeight
, srcDepth
,
2739 srcFormat
, srcType
, srcAddr
,
2741 const GLfloat
*src
= tempImage
;
2745 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2746 for (img
= 0; img
< srcDepth
; img
++) {
2747 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2748 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2749 + dstYoffset
* dstRowStride
2750 + dstXoffset
* dstFormat
->TexelBytes
;
2751 for (row
= 0; row
< srcHeight
; row
++) {
2752 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2754 for (i
= 0; i
< srcWidth
* components
; i
++) {
2755 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2757 dstRow
+= dstRowStride
;
2758 src
+= srcWidth
* components
;
2762 _mesa_free((void *) tempImage
);
2768 #if FEATURE_EXT_texture_sRGB
2770 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2772 const GLboolean littleEndian
= _mesa_little_endian();
2773 const struct gl_texture_format
*newDstFormat
;
2774 StoreTexImageFunc store
;
2777 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2779 /* reuse normal rgb texstore code */
2781 newDstFormat
= &_mesa_texformat_bgr888
;
2782 store
= _mesa_texstore_bgr888
;
2785 newDstFormat
= &_mesa_texformat_rgb888
;
2786 store
= _mesa_texstore_rgb888
;
2789 k
= store(ctx
, dims
, baseInternalFormat
,
2790 newDstFormat
, dstAddr
,
2791 dstXoffset
, dstYoffset
, dstZoffset
,
2792 dstRowStride
, dstImageOffsets
,
2793 srcWidth
, srcHeight
, srcDepth
,
2795 srcAddr
, srcPacking
);
2801 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2803 const GLboolean littleEndian
= _mesa_little_endian();
2804 const struct gl_texture_format
*newDstFormat
;
2807 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2809 /* reuse normal rgba texstore code */
2811 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2813 newDstFormat
= &_mesa_texformat_rgba8888
;
2815 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2816 newDstFormat
, dstAddr
,
2817 dstXoffset
, dstYoffset
, dstZoffset
,
2818 dstRowStride
, dstImageOffsets
,
2819 srcWidth
, srcHeight
, srcDepth
,
2821 srcAddr
, srcPacking
);
2827 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2829 const struct gl_texture_format
*newDstFormat
;
2832 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2834 newDstFormat
= &_mesa_texformat_l8
;
2836 /* _mesa_textore_a8 handles luminance8 too */
2837 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2838 newDstFormat
, dstAddr
,
2839 dstXoffset
, dstYoffset
, dstZoffset
,
2840 dstRowStride
, dstImageOffsets
,
2841 srcWidth
, srcHeight
, srcDepth
,
2843 srcAddr
, srcPacking
);
2849 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2851 const GLboolean littleEndian
= _mesa_little_endian();
2852 const struct gl_texture_format
*newDstFormat
;
2855 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2857 /* reuse normal luminance/alpha texstore code */
2859 newDstFormat
= &_mesa_texformat_al88
;
2861 newDstFormat
= &_mesa_texformat_al88_rev
;
2863 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2864 newDstFormat
, dstAddr
,
2865 dstXoffset
, dstYoffset
, dstZoffset
,
2866 dstRowStride
, dstImageOffsets
,
2867 srcWidth
, srcHeight
, srcDepth
,
2869 srcAddr
, srcPacking
);
2873 #endif /* FEATURE_EXT_texture_sRGB */
2877 * Check if an unpack PBO is active prior to fetching a texture image.
2878 * If so, do bounds checking and map the buffer into main memory.
2879 * Any errors detected will be recorded.
2880 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2883 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2884 GLsizei width
, GLsizei height
, GLsizei depth
,
2885 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2886 const struct gl_pixelstore_attrib
*unpack
,
2887 const char *funcName
)
2891 if (unpack
->BufferObj
->Name
== 0) {
2895 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2896 format
, type
, pixels
)) {
2897 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2901 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2902 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2904 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2908 return ADD_POINTERS(buf
, pixels
);
2913 * Check if an unpack PBO is active prior to fetching a compressed texture
2915 * If so, do bounds checking and map the buffer into main memory.
2916 * Any errors detected will be recorded.
2917 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2920 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2921 GLsizei imageSize
, const GLvoid
*pixels
,
2922 const struct gl_pixelstore_attrib
*packing
,
2923 const char *funcName
)
2927 if (packing
->BufferObj
->Name
== 0) {
2928 /* not using a PBO - return pointer unchanged */
2931 if ((const GLubyte
*) pixels
+ imageSize
>
2932 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2933 /* out of bounds read! */
2934 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2938 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2939 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2941 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2945 return ADD_POINTERS(buf
, pixels
);
2950 * This function must be called after either of the validate_pbo_*_teximage()
2951 * functions. It unmaps the PBO buffer if it was mapped earlier.
2954 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2955 const struct gl_pixelstore_attrib
*unpack
)
2957 if (unpack
->BufferObj
->Name
) {
2958 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2966 * Adaptor for fetching a GLchan texel from a float-valued texture.
2969 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2970 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2973 ASSERT(texImage
->FetchTexelf
);
2974 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2975 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2976 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2977 /* just one channel */
2978 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2982 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2983 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2984 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2985 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2991 * Adaptor for fetching a float texel from a GLchan-valued texture.
2994 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2995 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2998 ASSERT(texImage
->FetchTexelc
);
2999 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
3000 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
3001 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
3002 /* just one channel */
3003 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
3007 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
3008 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
3009 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
3010 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
3016 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
3019 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
3021 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
3022 ASSERT(texImage
->TexFormat
);
3026 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
3027 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
3030 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
3031 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
3034 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
3035 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
3041 /* now check if we need to use a float/chan adaptor */
3042 if (!texImage
->FetchTexelc
) {
3043 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
3045 else if (!texImage
->FetchTexelf
) {
3046 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
3050 ASSERT(texImage
->FetchTexelc
);
3051 ASSERT(texImage
->FetchTexelf
);
3056 * Choose the actual storage format for a new texture image.
3057 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
3058 * Also set some other texImage fields related to texture compression, etc.
3059 * \param ctx rendering context
3060 * \param texImage the gl_texture_image
3061 * \param dims texture dimensions (1, 2 or 3)
3062 * \param format the user-specified format parameter
3063 * \param type the user-specified type parameter
3064 * \param internalFormat the user-specified internal format hint
3067 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
3069 GLenum format
, GLenum type
, GLint internalFormat
)
3071 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
3072 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
3075 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
3077 ASSERT(texImage
->TexFormat
);
3079 _mesa_set_fetch_functions(texImage
, dims
);
3081 if (texImage
->TexFormat
->TexelBytes
== 0) {
3082 /* must be a compressed format */
3083 texImage
->IsCompressed
= GL_TRUE
;
3084 texImage
->CompressedSize
=
3085 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
3086 texImage
->Height
, texImage
->Depth
,
3087 texImage
->TexFormat
->MesaFormat
);
3090 /* non-compressed format */
3091 texImage
->IsCompressed
= GL_FALSE
;
3092 texImage
->CompressedSize
= 0;
3099 * This is the software fallback for Driver.TexImage1D()
3100 * and Driver.CopyTexImage1D().
3101 * \sa _mesa_store_teximage2d()
3102 * Note that the width may not be the actual texture width since it may
3103 * be changed by convolution w/ GL_REDUCE. The texImage->Width field will
3104 * have the actual texture size.
3107 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3108 GLint internalFormat
,
3109 GLint width
, GLint border
,
3110 GLenum format
, GLenum type
, const GLvoid
*pixels
,
3111 const struct gl_pixelstore_attrib
*packing
,
3112 struct gl_texture_object
*texObj
,
3113 struct gl_texture_image
*texImage
)
3118 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
3120 /* allocate memory */
3121 if (texImage
->IsCompressed
)
3122 sizeInBytes
= texImage
->CompressedSize
;
3124 sizeInBytes
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
3125 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3126 if (!texImage
->Data
) {
3127 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3131 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3132 pixels
, packing
, "glTexImage1D");
3134 /* Note: we check for a NULL image pointer here, _after_ we allocated
3135 * memory for the texture. That's what the GL spec calls for.
3140 const GLint dstRowStride
= 0;
3142 ASSERT(texImage
->TexFormat
->StoreImage
);
3143 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3144 texImage
->TexFormat
,
3146 0, 0, 0, /* dstX/Y/Zoffset */
3148 texImage
->ImageOffsets
,
3150 format
, type
, pixels
, packing
);
3152 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
3156 /* GL_SGIS_generate_mipmap */
3157 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3158 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3161 _mesa_unmap_teximage_pbo(ctx
, packing
);
3166 * This is the software fallback for Driver.TexImage2D()
3167 * and Driver.CopyTexImage2D().
3169 * This function is oriented toward storing images in main memory, rather
3170 * than VRAM. Device driver's can easily plug in their own replacement.
3172 * Note: width and height may be pre-convolved dimensions, but
3173 * texImage->Width and texImage->Height will be post-convolved dimensions.
3176 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3177 GLint internalFormat
,
3178 GLint width
, GLint height
, GLint border
,
3179 GLenum format
, GLenum type
, const void *pixels
,
3180 const struct gl_pixelstore_attrib
*packing
,
3181 struct gl_texture_object
*texObj
,
3182 struct gl_texture_image
*texImage
)
3184 GLint texelBytes
, sizeInBytes
;
3187 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
3189 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3191 /* allocate memory */
3192 if (texImage
->IsCompressed
)
3193 sizeInBytes
= texImage
->CompressedSize
;
3195 sizeInBytes
= texImage
->Width
* texImage
->Height
* texelBytes
;
3196 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3197 if (!texImage
->Data
) {
3198 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3202 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3203 pixels
, packing
, "glTexImage2D");
3205 /* Note: we check for a NULL image pointer here, _after_ we allocated
3206 * memory for the texture. That's what the GL spec calls for.
3213 if (texImage
->IsCompressed
) {
3215 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3218 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3220 ASSERT(texImage
->TexFormat
->StoreImage
);
3221 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3222 texImage
->TexFormat
,
3224 0, 0, 0, /* dstX/Y/Zoffset */
3226 texImage
->ImageOffsets
,
3228 format
, type
, pixels
, packing
);
3230 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3234 /* GL_SGIS_generate_mipmap */
3235 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3236 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3239 _mesa_unmap_teximage_pbo(ctx
, packing
);
3245 * This is the software fallback for Driver.TexImage3D()
3246 * and Driver.CopyTexImage3D().
3247 * \sa _mesa_store_teximage2d()
3250 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3251 GLint internalFormat
,
3252 GLint width
, GLint height
, GLint depth
, GLint border
,
3253 GLenum format
, GLenum type
, const void *pixels
,
3254 const struct gl_pixelstore_attrib
*packing
,
3255 struct gl_texture_object
*texObj
,
3256 struct gl_texture_image
*texImage
)
3258 GLint texelBytes
, sizeInBytes
;
3261 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3263 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3265 /* allocate memory */
3266 if (texImage
->IsCompressed
)
3267 sizeInBytes
= texImage
->CompressedSize
;
3269 sizeInBytes
= width
* height
* depth
* texelBytes
;
3270 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3271 if (!texImage
->Data
) {
3272 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3276 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3277 type
, pixels
, packing
, "glTexImage3D");
3279 /* Note: we check for a NULL image pointer here, _after_ we allocated
3280 * memory for the texture. That's what the GL spec calls for.
3287 if (texImage
->IsCompressed
) {
3289 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3292 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3294 ASSERT(texImage
->TexFormat
->StoreImage
);
3295 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3296 texImage
->TexFormat
,
3298 0, 0, 0, /* dstX/Y/Zoffset */
3300 texImage
->ImageOffsets
,
3301 width
, height
, depth
,
3302 format
, type
, pixels
, packing
);
3304 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3308 /* GL_SGIS_generate_mipmap */
3309 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3310 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3313 _mesa_unmap_teximage_pbo(ctx
, packing
);
3320 * This is the software fallback for Driver.TexSubImage1D()
3321 * and Driver.CopyTexSubImage1D().
3324 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3325 GLint xoffset
, GLint width
,
3326 GLenum format
, GLenum type
, const void *pixels
,
3327 const struct gl_pixelstore_attrib
*packing
,
3328 struct gl_texture_object
*texObj
,
3329 struct gl_texture_image
*texImage
)
3331 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3332 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3333 pixels
, packing
, "glTexSubImage1D");
3338 const GLint dstRowStride
= 0;
3340 ASSERT(texImage
->TexFormat
->StoreImage
);
3341 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3342 texImage
->TexFormat
,
3344 xoffset
, 0, 0, /* offsets */
3346 texImage
->ImageOffsets
,
3348 format
, type
, pixels
, packing
);
3350 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3354 /* GL_SGIS_generate_mipmap */
3355 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3356 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3359 _mesa_unmap_teximage_pbo(ctx
, packing
);
3365 * This is the software fallback for Driver.TexSubImage2D()
3366 * and Driver.CopyTexSubImage2D().
3369 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3370 GLint xoffset
, GLint yoffset
,
3371 GLint width
, GLint height
,
3372 GLenum format
, GLenum type
, const void *pixels
,
3373 const struct gl_pixelstore_attrib
*packing
,
3374 struct gl_texture_object
*texObj
,
3375 struct gl_texture_image
*texImage
)
3377 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3378 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3379 pixels
, packing
, "glTexSubImage2D");
3384 GLint dstRowStride
= 0;
3386 if (texImage
->IsCompressed
) {
3387 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3391 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3393 ASSERT(texImage
->TexFormat
->StoreImage
);
3394 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3395 texImage
->TexFormat
,
3397 xoffset
, yoffset
, 0,
3399 texImage
->ImageOffsets
,
3401 format
, type
, pixels
, packing
);
3403 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3407 /* GL_SGIS_generate_mipmap */
3408 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3409 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3412 _mesa_unmap_teximage_pbo(ctx
, packing
);
3417 * This is the software fallback for Driver.TexSubImage3D().
3418 * and Driver.CopyTexSubImage3D().
3421 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3422 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3423 GLint width
, GLint height
, GLint depth
,
3424 GLenum format
, GLenum type
, const void *pixels
,
3425 const struct gl_pixelstore_attrib
*packing
,
3426 struct gl_texture_object
*texObj
,
3427 struct gl_texture_image
*texImage
)
3429 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3430 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3431 type
, pixels
, packing
,
3439 if (texImage
->IsCompressed
) {
3440 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3444 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3446 ASSERT(texImage
->TexFormat
->StoreImage
);
3447 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3448 texImage
->TexFormat
,
3450 xoffset
, yoffset
, zoffset
,
3452 texImage
->ImageOffsets
,
3453 width
, height
, depth
,
3454 format
, type
, pixels
, packing
);
3456 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3460 /* GL_SGIS_generate_mipmap */
3461 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3462 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3465 _mesa_unmap_teximage_pbo(ctx
, packing
);
3470 * Fallback for Driver.CompressedTexImage1D()
3473 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3474 GLint internalFormat
,
3475 GLint width
, GLint border
,
3476 GLsizei imageSize
, const GLvoid
*data
,
3477 struct gl_texture_object
*texObj
,
3478 struct gl_texture_image
*texImage
)
3480 /* this space intentionally left blank */
3482 (void) target
; (void) level
;
3483 (void) internalFormat
;
3484 (void) width
; (void) border
;
3485 (void) imageSize
; (void) data
;
3493 * Fallback for Driver.CompressedTexImage2D()
3496 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3497 GLint internalFormat
,
3498 GLint width
, GLint height
, GLint border
,
3499 GLsizei imageSize
, const GLvoid
*data
,
3500 struct gl_texture_object
*texObj
,
3501 struct gl_texture_image
*texImage
)
3503 (void) width
; (void) height
; (void) border
;
3505 /* This is pretty simple, basically just do a memcpy without worrying
3506 * about the usual image unpacking or image transfer operations.
3510 ASSERT(texImage
->Width
> 0);
3511 ASSERT(texImage
->Height
> 0);
3512 ASSERT(texImage
->Depth
== 1);
3513 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3515 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3517 /* allocate storage */
3518 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3519 if (!texImage
->Data
) {
3520 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3524 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3526 "glCompressedTexImage2D");
3531 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3532 MEMCPY(texImage
->Data
, data
, imageSize
);
3534 /* GL_SGIS_generate_mipmap */
3535 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3536 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3539 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3545 * Fallback for Driver.CompressedTexImage3D()
3548 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3549 GLint internalFormat
,
3550 GLint width
, GLint height
, GLint depth
,
3552 GLsizei imageSize
, const GLvoid
*data
,
3553 struct gl_texture_object
*texObj
,
3554 struct gl_texture_image
*texImage
)
3556 /* this space intentionally left blank */
3558 (void) target
; (void) level
;
3559 (void) internalFormat
;
3560 (void) width
; (void) height
; (void) depth
;
3562 (void) imageSize
; (void) data
;
3570 * Fallback for Driver.CompressedTexSubImage1D()
3573 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3575 GLint xoffset
, GLsizei width
,
3577 GLsizei imageSize
, const GLvoid
*data
,
3578 struct gl_texture_object
*texObj
,
3579 struct gl_texture_image
*texImage
)
3581 /* there are no compressed 1D texture formats yet */
3583 (void) target
; (void) level
;
3584 (void) xoffset
; (void) width
;
3586 (void) imageSize
; (void) data
;
3593 * Fallback for Driver.CompressedTexSubImage2D()
3596 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3598 GLint xoffset
, GLint yoffset
,
3599 GLsizei width
, GLsizei height
,
3601 GLsizei imageSize
, const GLvoid
*data
,
3602 struct gl_texture_object
*texObj
,
3603 struct gl_texture_image
*texImage
)
3605 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3609 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3613 /* these should have been caught sooner */
3614 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3615 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3616 ASSERT((xoffset
& 3) == 0);
3617 ASSERT((yoffset
& 3) == 0);
3619 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3620 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3622 "glCompressedTexSubImage2D");
3626 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3627 src
= (const GLubyte
*) data
;
3629 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3630 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3631 texImage
->TexFormat
->MesaFormat
,
3633 (GLubyte
*) texImage
->Data
);
3635 bytesPerRow
= srcRowStride
;
3638 for (i
= 0; i
< rows
; i
++) {
3639 MEMCPY(dest
, src
, bytesPerRow
);
3640 dest
+= destRowStride
;
3641 src
+= srcRowStride
;
3644 /* GL_SGIS_generate_mipmap */
3645 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3646 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3649 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3654 * Fallback for Driver.CompressedTexSubImage3D()
3657 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3659 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3660 GLsizei width
, GLsizei height
, GLsizei depth
,
3662 GLsizei imageSize
, const GLvoid
*data
,
3663 struct gl_texture_object
*texObj
,
3664 struct gl_texture_image
*texImage
)
3666 /* there are no compressed 3D texture formats yet */
3668 (void) target
; (void) level
;
3669 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3670 (void) width
; (void) height
; (void) depth
;
3672 (void) imageSize
; (void) data
;
3680 #if FEATURE_EXT_texture_sRGB
3683 * Test if given texture image is an sRGB format.
3686 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3688 switch (texImage
->TexFormat
->MesaFormat
) {
3689 case MESA_FORMAT_SRGB8
:
3690 case MESA_FORMAT_SRGBA8
:
3691 case MESA_FORMAT_SL8
:
3692 case MESA_FORMAT_SLA8
:
3699 #endif /* FEATURE_EXT_texture_sRGB */
3703 * This is the software fallback for Driver.GetTexImage().
3704 * All error checking will have been done before this routine is called.
3707 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3708 GLenum format
, GLenum type
, GLvoid
*pixels
,
3709 struct gl_texture_object
*texObj
,
3710 struct gl_texture_image
*texImage
)
3712 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3714 if (ctx
->Pack
.BufferObj
->Name
) {
3715 /* Packing texture image into a PBO.
3716 * Map the (potentially) VRAM-based buffer into our process space so
3717 * we can write into it with the code below.
3718 * A hardware driver might use a sophisticated blit to move the
3719 * texture data to the PBO if the PBO is in VRAM along with the texture.
3721 GLubyte
*buf
= (GLubyte
*)
3722 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3723 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3725 /* buffer is already mapped - that's an error */
3726 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3729 /* <pixels> was an offset into the PBO.
3730 * Now make it a real, client-side pointer inside the mapped region.
3732 pixels
= ADD_POINTERS(buf
, pixels
);
3740 const GLint width
= texImage
->Width
;
3741 const GLint height
= texImage
->Height
;
3742 const GLint depth
= texImage
->Depth
;
3744 for (img
= 0; img
< depth
; img
++) {
3745 for (row
= 0; row
< height
; row
++) {
3746 /* compute destination address in client memory */
3747 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3748 width
, height
, format
, type
,
3752 if (format
== GL_COLOR_INDEX
) {
3753 GLuint indexRow
[MAX_WIDTH
];
3755 /* Can't use FetchTexel here because that returns RGBA */
3756 if (texImage
->TexFormat
->IndexBits
== 8) {
3757 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3758 src
+= width
* (img
* texImage
->Height
+ row
);
3759 for (col
= 0; col
< width
; col
++) {
3760 indexRow
[col
] = src
[col
];
3763 else if (texImage
->TexFormat
->IndexBits
== 16) {
3764 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3765 src
+= width
* (img
* texImage
->Height
+ row
);
3766 for (col
= 0; col
< width
; col
++) {
3767 indexRow
[col
] = src
[col
];
3772 "Color index problem in _mesa_GetTexImage");
3774 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3775 indexRow
, &ctx
->Pack
,
3776 0 /* no image transfer */);
3778 else if (format
== GL_DEPTH_COMPONENT
) {
3779 GLfloat depthRow
[MAX_WIDTH
];
3781 for (col
= 0; col
< width
; col
++) {
3782 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3785 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3786 depthRow
, &ctx
->Pack
);
3788 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3789 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3790 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3791 src
+= width
* row
+ width
* height
* img
;
3792 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3793 if (ctx
->Pack
.SwapBytes
) {
3794 _mesa_swap4((GLuint
*) dest
, width
);
3797 else if (format
== GL_YCBCR_MESA
) {
3798 /* No pixel transfer */
3799 const GLint rowstride
= texImage
->RowStride
;
3801 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3802 width
* sizeof(GLushort
));
3803 /* check for byte swapping */
3804 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3805 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3806 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3807 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3808 if (!ctx
->Pack
.SwapBytes
)
3809 _mesa_swap2((GLushort
*) dest
, width
);
3811 else if (ctx
->Pack
.SwapBytes
) {
3812 _mesa_swap2((GLushort
*) dest
, width
);
3815 #if FEATURE_EXT_texture_sRGB
3816 else if (is_srgb_teximage(texImage
)) {
3817 /* no pixel transfer and no non-linear to linear conversion */
3818 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3819 const GLint rowstride
= comps
* texImage
->RowStride
;
3821 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3822 comps
* width
* sizeof(GLubyte
));
3824 #endif /* FEATURE_EXT_texture_sRGB */
3826 /* general case: convert row to RGBA format */
3827 GLfloat rgba
[MAX_WIDTH
][4];
3829 GLbitfield transferOps
= 0x0;
3831 if (type
== GL_FLOAT
&&
3832 ((ctx
->Color
.ClampReadColor
== GL_TRUE
) ||
3833 (ctx
->Color
.ClampReadColor
== GL_FIXED_ONLY_ARB
&&
3834 texImage
->TexFormat
->DataType
!= GL_FLOAT
)))
3835 transferOps
|= IMAGE_CLAMP_BIT
;
3837 for (col
= 0; col
< width
; col
++) {
3838 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3839 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3840 rgba
[col
][RCOMP
] = 0.0;
3841 rgba
[col
][GCOMP
] = 0.0;
3842 rgba
[col
][BCOMP
] = 0.0;
3844 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3845 rgba
[col
][GCOMP
] = 0.0;
3846 rgba
[col
][BCOMP
] = 0.0;
3847 rgba
[col
][ACOMP
] = 1.0;
3849 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3850 rgba
[col
][GCOMP
] = 0.0;
3851 rgba
[col
][BCOMP
] = 0.0;
3853 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3854 rgba
[col
][GCOMP
] = 0.0;
3855 rgba
[col
][BCOMP
] = 0.0;
3856 rgba
[col
][ACOMP
] = 1.0;
3859 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3861 &ctx
->Pack
, transferOps
/*image xfer ops*/);
3867 if (ctx
->Pack
.BufferObj
->Name
) {
3868 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3869 ctx
->Pack
.BufferObj
);
3876 * This is the software fallback for Driver.GetCompressedTexImage().
3877 * All error checking will have been done before this routine is called.
3880 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3882 struct gl_texture_object
*texObj
,
3883 struct gl_texture_image
*texImage
)
3887 if (ctx
->Pack
.BufferObj
->Name
) {
3888 /* pack texture image into a PBO */
3890 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3891 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3892 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3893 "glGetCompressedTexImage(invalid PBO access)");
3896 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3898 ctx
->Pack
.BufferObj
);
3900 /* buffer is already mapped - that's an error */
3901 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3902 "glGetCompressedTexImage(PBO is mapped)");
3905 img
= ADD_POINTERS(buf
, img
);
3912 /* don't use texImage->CompressedSize since that may be padded out */
3913 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3915 texImage
->TexFormat
->MesaFormat
);
3917 /* just memcpy, no pixelstore or pixel transfer */
3918 _mesa_memcpy(img
, texImage
->Data
, size
);
3920 if (ctx
->Pack
.BufferObj
->Name
) {
3921 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3922 ctx
->Pack
.BufferObj
);