2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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"
63 #include "texcompress.h"
64 #include "texformat.h"
77 * Return GL_TRUE if the given image format is one that be converted
78 * to another format by swizzling.
81 can_swizzle(GLenum logicalBaseFormat
)
83 switch (logicalBaseFormat
) {
86 case GL_LUMINANCE_ALPHA
:
120 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
121 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
122 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
123 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
126 static const struct {
129 GLubyte from_rgba
[6];
130 } mappings
[MAX_IDX
] =
140 MAP4(ZERO
, ZERO
, ZERO
, 0),
171 MAP4(0, ZERO
, ZERO
, ONE
),
177 MAP4(ZERO
, 0, ZERO
, ONE
),
183 MAP4(ZERO
, ZERO
, 0, ONE
),
209 * Convert a GL image format enum to an IDX_* value (see above).
212 get_map_idx(GLenum value
)
215 case GL_LUMINANCE
: return IDX_LUMINANCE
;
216 case GL_ALPHA
: return IDX_ALPHA
;
217 case GL_INTENSITY
: return IDX_INTENSITY
;
218 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
219 case GL_RGB
: return IDX_RGB
;
220 case GL_RGBA
: return IDX_RGBA
;
221 case GL_RED
: return IDX_RED
;
222 case GL_GREEN
: return IDX_GREEN
;
223 case GL_BLUE
: return IDX_BLUE
;
224 case GL_BGR
: return IDX_BGR
;
225 case GL_BGRA
: return IDX_BGRA
;
226 case GL_ABGR_EXT
: return IDX_ABGR
;
228 _mesa_problem(NULL
, "Unexpected inFormat");
235 * When promoting texture formats (see below) we need to compute the
236 * mapping of dest components back to source components.
237 * This function does that.
238 * \param inFormat the incoming format of the texture
239 * \param outFormat the final texture format
240 * \return map[6] a full 6-component map
243 compute_component_mapping(GLenum inFormat
, GLenum outFormat
,
246 const int inFmt
= get_map_idx(inFormat
);
247 const int outFmt
= get_map_idx(outFormat
);
248 const GLubyte
*in2rgba
= mappings
[inFmt
].to_rgba
;
249 const GLubyte
*rgba2out
= mappings
[outFmt
].from_rgba
;
252 for (i
= 0; i
< 4; i
++)
253 map
[i
] = in2rgba
[rgba2out
[i
]];
259 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
260 inFormat, _mesa_lookup_enum_by_nr(inFormat),
261 outFormat, _mesa_lookup_enum_by_nr(outFormat),
273 * Make a temporary (color) texture image with GLfloat components.
274 * Apply all needed pixel unpacking and pixel transfer operations.
275 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
276 * Suppose the user specifies GL_LUMINANCE as the internal texture format
277 * but the graphics hardware doesn't support luminance textures. So, might
278 * use an RGB hardware format instead.
279 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
281 * \param ctx the rendering context
282 * \param dims image dimensions: 1, 2 or 3
283 * \param logicalBaseFormat basic texture derived from the user's
284 * internal texture format value
285 * \param textureBaseFormat the actual basic format of the texture
286 * \param srcWidth source image width
287 * \param srcHeight source image height
288 * \param srcDepth source image depth
289 * \param srcFormat source image format
290 * \param srcType source image type
291 * \param srcAddr source image address
292 * \param srcPacking source image pixel packing
293 * \return resulting image with format = textureBaseFormat and type = GLfloat.
296 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
297 GLenum logicalBaseFormat
,
298 GLenum textureBaseFormat
,
299 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
300 GLenum srcFormat
, GLenum srcType
,
301 const GLvoid
*srcAddr
,
302 const struct gl_pixelstore_attrib
*srcPacking
)
304 GLuint transferOps
= ctx
->_ImageTransferState
;
307 ASSERT(dims
>= 1 && dims
<= 3);
309 ASSERT(logicalBaseFormat
== GL_RGBA
||
310 logicalBaseFormat
== GL_RGB
||
311 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
312 logicalBaseFormat
== GL_LUMINANCE
||
313 logicalBaseFormat
== GL_ALPHA
||
314 logicalBaseFormat
== GL_INTENSITY
||
315 logicalBaseFormat
== GL_COLOR_INDEX
||
316 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
318 ASSERT(textureBaseFormat
== GL_RGBA
||
319 textureBaseFormat
== GL_RGB
||
320 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
321 textureBaseFormat
== GL_LUMINANCE
||
322 textureBaseFormat
== GL_ALPHA
||
323 textureBaseFormat
== GL_INTENSITY
||
324 textureBaseFormat
== GL_COLOR_INDEX
||
325 textureBaseFormat
== GL_DEPTH_COMPONENT
);
327 /* conventional color image */
329 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
330 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
331 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
332 /* need image convolution */
333 const GLuint preConvTransferOps
334 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
335 const GLuint postConvTransferOps
336 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
338 GLint convWidth
, convHeight
;
341 /* pre-convolution image buffer (3D) */
342 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
343 * 4 * sizeof(GLfloat
));
347 /* post-convolution image buffer (2D) */
348 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
349 * 4 * sizeof(GLfloat
));
351 _mesa_free(tempImage
);
355 /* loop over 3D image slices */
356 for (img
= 0; img
< srcDepth
; img
++) {
357 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
359 /* unpack and do transfer ops up to convolution */
360 for (row
= 0; row
< srcHeight
; row
++) {
361 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
362 srcAddr
, srcWidth
, srcHeight
,
363 srcFormat
, srcType
, img
, row
, 0);
364 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
365 srcFormat
, srcType
, src
,
373 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
374 convWidth
= srcWidth
;
375 convHeight
= srcHeight
;
377 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
378 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
381 if (ctx
->Pixel
.Convolution2DEnabled
) {
382 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
386 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
387 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
393 /* do post-convolution transfer and pack into tempImage */
395 const GLint logComponents
396 = _mesa_components_in_format(logicalBaseFormat
);
397 const GLfloat
*src
= convImage
;
398 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
399 for (row
= 0; row
< convHeight
; row
++) {
400 _mesa_pack_rgba_span_float(ctx
, convWidth
,
401 (GLfloat (*)[4]) src
,
402 logicalBaseFormat
, GL_FLOAT
,
403 dst
, &ctx
->DefaultPacking
,
404 postConvTransferOps
);
405 src
+= convWidth
* 4;
406 dst
+= convWidth
* logComponents
;
409 } /* loop over 3D image slices */
411 _mesa_free(convImage
);
413 /* might need these below */
414 srcWidth
= convWidth
;
415 srcHeight
= convHeight
;
419 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
420 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
421 srcWidth
, srcFormat
, srcType
);
425 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
426 * components
* sizeof(GLfloat
));
431 for (img
= 0; img
< srcDepth
; img
++) {
433 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
437 for (row
= 0; row
< srcHeight
; row
++) {
438 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
439 dst
, srcFormat
, srcType
, src
,
440 srcPacking
, transferOps
);
441 dst
+= srcWidth
* components
;
447 if (logicalBaseFormat
!= textureBaseFormat
) {
449 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
450 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
455 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
456 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
457 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
459 /* The actual texture format should have at least as many components
460 * as the logical texture format.
462 ASSERT(texComponents
>= logComponents
);
464 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
465 * texComponents
* sizeof(GLfloat
));
467 _mesa_free(tempImage
);
471 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
473 n
= srcWidth
* srcHeight
* srcDepth
;
474 for (i
= 0; i
< n
; i
++) {
476 for (k
= 0; k
< texComponents
; k
++) {
479 newImage
[i
* texComponents
+ k
] = 0.0F
;
481 newImage
[i
* texComponents
+ k
] = 1.0F
;
483 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
487 _mesa_free(tempImage
);
488 tempImage
= newImage
;
496 * Make a temporary (color) texture image with GLchan components.
497 * Apply all needed pixel unpacking and pixel transfer operations.
498 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
499 * Suppose the user specifies GL_LUMINANCE as the internal texture format
500 * but the graphics hardware doesn't support luminance textures. So, might
501 * use an RGB hardware format instead.
502 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
504 * \param ctx the rendering context
505 * \param dims image dimensions: 1, 2 or 3
506 * \param logicalBaseFormat basic texture derived from the user's
507 * internal texture format value
508 * \param textureBaseFormat the actual basic format of the texture
509 * \param srcWidth source image width
510 * \param srcHeight source image height
511 * \param srcDepth source image depth
512 * \param srcFormat source image format
513 * \param srcType source image type
514 * \param srcAddr source image address
515 * \param srcPacking source image pixel packing
516 * \return resulting image with format = textureBaseFormat and type = GLchan.
519 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
520 GLenum logicalBaseFormat
,
521 GLenum textureBaseFormat
,
522 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
523 GLenum srcFormat
, GLenum srcType
,
524 const GLvoid
*srcAddr
,
525 const struct gl_pixelstore_attrib
*srcPacking
)
527 GLuint transferOps
= ctx
->_ImageTransferState
;
528 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
529 GLboolean freeSrcImage
= GL_FALSE
;
531 GLchan
*tempImage
, *dst
;
533 ASSERT(dims
>= 1 && dims
<= 3);
535 ASSERT(logicalBaseFormat
== GL_RGBA
||
536 logicalBaseFormat
== GL_RGB
||
537 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
538 logicalBaseFormat
== GL_LUMINANCE
||
539 logicalBaseFormat
== GL_ALPHA
||
540 logicalBaseFormat
== GL_INTENSITY
);
542 ASSERT(textureBaseFormat
== GL_RGBA
||
543 textureBaseFormat
== GL_RGB
||
544 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
545 textureBaseFormat
== GL_LUMINANCE
||
546 textureBaseFormat
== GL_ALPHA
||
547 textureBaseFormat
== GL_INTENSITY
);
549 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
550 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
551 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
552 /* get convolved image */
553 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
556 srcWidth
, srcHeight
, srcDepth
,
558 srcAddr
, srcPacking
);
561 /* the convolved image is our new source image */
563 srcFormat
= logicalBaseFormat
;
565 srcPacking
= &ctx
->DefaultPacking
;
566 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
568 freeSrcImage
= GL_TRUE
;
571 /* unpack and transfer the source image */
572 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
573 * components
* sizeof(GLchan
));
578 for (img
= 0; img
< srcDepth
; img
++) {
579 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
583 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
587 for (row
= 0; row
< srcHeight
; row
++) {
588 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
589 srcFormat
, srcType
, src
, srcPacking
,
591 dst
+= srcWidth
* components
;
596 /* If we made a temporary image for convolution, free it here */
598 _mesa_free((void *) srcAddr
);
601 if (logicalBaseFormat
!= textureBaseFormat
) {
602 /* one more conversion step */
603 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
604 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
609 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
610 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
611 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
613 /* The actual texture format should have at least as many components
614 * as the logical texture format.
616 ASSERT(texComponents
>= logComponents
);
618 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
619 * texComponents
* sizeof(GLchan
));
621 _mesa_free(tempImage
);
625 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
627 n
= srcWidth
* srcHeight
* srcDepth
;
628 for (i
= 0; i
< n
; i
++) {
630 for (k
= 0; k
< texComponents
; k
++) {
633 newImage
[i
* texComponents
+ k
] = 0;
635 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
637 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
641 _mesa_free(tempImage
);
642 tempImage
= newImage
;
650 * Copy GLubyte pixels from <src> to <dst> with swizzling.
651 * \param dst destination pixels
652 * \param dstComponents number of color components in destination pixels
653 * \param src source pixels
654 * \param srcComponents number of color components in source pixels
655 * \param map the swizzle mapping. map[X] says where to find the X component
656 * in the source image's pixels. For example, if the source image
657 * is GL_BGRA and X = red, map[0] yields 2.
658 * \param count number of pixels to copy/swizzle.
661 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
662 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
670 switch (dstComponents
) {
672 for (i
= 0; i
< count
; i
++) {
674 src
+= srcComponents
;
675 dst
[0] = tmp
[map
[0]];
676 dst
[1] = tmp
[map
[1]];
677 dst
[2] = tmp
[map
[2]];
678 dst
[3] = tmp
[map
[3]];
683 for (i
= 0; i
< count
; i
++) {
685 src
+= srcComponents
;
686 dst
[0] = tmp
[map
[0]];
687 dst
[1] = tmp
[map
[1]];
688 dst
[2] = tmp
[map
[2]];
693 for (i
= 0; i
< count
; i
++) {
695 src
+= srcComponents
;
696 dst
[0] = tmp
[map
[0]];
697 dst
[1] = tmp
[map
[1]];
702 /* XXX investigate valgrind invalid read when running demos/texenv.c */
703 for (i
= 0; i
< count
; i
++) {
705 src
+= srcComponents
;
706 dst
[0] = tmp
[map
[0]];
714 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
715 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
717 /* Deal with the _REV input types:
719 static const GLubyte
*
720 type_mapping( GLenum srcType
)
723 case GL_UNSIGNED_BYTE
:
725 case GL_UNSIGNED_INT_8_8_8_8
:
726 return _mesa_little_endian() ? map_3210
: map_identity
;
727 case GL_UNSIGNED_INT_8_8_8_8_REV
:
728 return _mesa_little_endian() ? map_identity
: map_3210
;
734 /* Mapping required if input type is
736 static const GLubyte
*
737 byteswap_mapping( GLboolean swapBytes
,
744 case GL_UNSIGNED_BYTE
:
746 case GL_UNSIGNED_INT_8_8_8_8
:
747 case GL_UNSIGNED_INT_8_8_8_8_REV
:
757 * Transfer a GLubyte texture image with component swizzling.
760 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
765 GLenum baseInternalFormat
,
767 const GLubyte
*rgba2dst
,
768 GLuint dstComponents
,
771 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
773 const GLuint
*dstImageOffsets
,
775 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
776 const GLvoid
*srcAddr
,
777 const struct gl_pixelstore_attrib
*srcPacking
)
779 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
780 const GLubyte
*srctype2ubyte
, *swap
;
781 GLubyte map
[4], src2base
[6], base2rgba
[6];
783 const GLint srcRowStride
=
784 _mesa_image_row_stride(srcPacking
, srcWidth
,
785 srcFormat
, GL_UNSIGNED_BYTE
);
786 const GLint srcImageStride
787 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
789 const GLubyte
*srcImage
790 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
791 srcWidth
, srcHeight
, srcFormat
,
792 GL_UNSIGNED_BYTE
, 0, 0, 0);
796 /* Translate from src->baseInternal->GL_RGBA->dst. This will
797 * correctly deal with RGBA->RGB->RGBA conversions where the final
798 * A value must be 0xff regardless of the incoming alpha values.
800 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
801 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
802 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
803 srctype2ubyte
= type_mapping(srcType
);
806 for (i
= 0; i
< 4; i
++)
807 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
809 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
811 if (srcRowStride
== dstRowStride
&&
812 srcComponents
== dstComponents
&&
813 srcRowStride
== srcWidth
* srcComponents
&&
815 /* 1 and 2D images only */
816 GLubyte
*dstImage
= (GLubyte
*) dstAddr
817 + dstYoffset
* dstRowStride
818 + dstXoffset
* dstComponents
;
819 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
820 srcWidth
* srcHeight
);
824 for (img
= 0; img
< srcDepth
; img
++) {
825 const GLubyte
*srcRow
= srcImage
;
826 GLubyte
*dstRow
= (GLubyte
*) dstAddr
827 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
828 + dstYoffset
* dstRowStride
829 + dstXoffset
* dstComponents
;
830 for (row
= 0; row
< srcHeight
; row
++) {
831 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
832 dstRow
+= dstRowStride
;
833 srcRow
+= srcRowStride
;
835 srcImage
+= srcImageStride
;
842 * Teximage storage routine for when a simple memcpy will do.
843 * No pixel transfer operations or special texel encodings allowed.
844 * 1D, 2D and 3D images supported.
847 memcpy_texture(GLcontext
*ctx
,
849 const struct gl_texture_format
*dstFormat
,
851 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
853 const GLuint
*dstImageOffsets
,
854 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
855 GLenum srcFormat
, GLenum srcType
,
856 const GLvoid
*srcAddr
,
857 const struct gl_pixelstore_attrib
*srcPacking
)
859 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
861 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
862 srcWidth
, srcHeight
, srcFormat
, srcType
);
863 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
864 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
865 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
868 /* XXX update/re-enable for dstImageOffsets array */
869 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
870 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
871 GLubyte
*dstImage
= (GLubyte
*) dstAddr
872 + dstZoffset
* dstImageStride
873 + dstYoffset
* dstRowStride
874 + dstXoffset
* dstFormat
->TexelBytes
;
876 if (dstRowStride
== srcRowStride
&&
877 dstRowStride
== bytesPerRow
&&
878 ((dstImageStride
== srcImageStride
&&
879 dstImageStride
== bytesPerImage
) ||
882 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
887 for (img
= 0; img
< srcDepth
; img
++) {
888 const GLubyte
*srcRow
= srcImage
;
889 GLubyte
*dstRow
= dstImage
;
890 for (row
= 0; row
< srcHeight
; row
++) {
891 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
892 dstRow
+= dstRowStride
;
893 srcRow
+= srcRowStride
;
895 srcImage
+= srcImageStride
;
896 dstImage
+= dstImageStride
;
902 for (img
= 0; img
< srcDepth
; img
++) {
903 const GLubyte
*srcRow
= srcImage
;
904 GLubyte
*dstRow
= (GLubyte
*) dstAddr
905 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
906 + dstYoffset
* dstRowStride
907 + dstXoffset
* dstFormat
->TexelBytes
;
908 for (row
= 0; row
< srcHeight
; row
++) {
909 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
910 dstRow
+= dstRowStride
;
911 srcRow
+= srcRowStride
;
913 srcImage
+= srcImageStride
;
920 * Store an image in any of the formats:
921 * _mesa_texformat_rgba
922 * _mesa_texformat_rgb
923 * _mesa_texformat_alpha
924 * _mesa_texformat_luminance
925 * _mesa_texformat_luminance_alpha
926 * _mesa_texformat_intensity
930 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
932 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
934 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
935 dstFormat
== &_mesa_texformat_rgb
||
936 dstFormat
== &_mesa_texformat_alpha
||
937 dstFormat
== &_mesa_texformat_luminance
||
938 dstFormat
== &_mesa_texformat_luminance_alpha
||
939 dstFormat
== &_mesa_texformat_intensity
);
940 ASSERT(baseInternalFormat
== GL_RGBA
||
941 baseInternalFormat
== GL_RGB
||
942 baseInternalFormat
== GL_ALPHA
||
943 baseInternalFormat
== GL_LUMINANCE
||
944 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
945 baseInternalFormat
== GL_INTENSITY
);
946 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
948 if (!ctx
->_ImageTransferState
&&
949 !srcPacking
->SwapBytes
&&
950 baseInternalFormat
== srcFormat
&&
951 srcType
== CHAN_TYPE
) {
952 /* simple memcpy path */
953 memcpy_texture(ctx
, dims
,
954 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
957 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
958 srcAddr
, srcPacking
);
960 else if (!ctx
->_ImageTransferState
&&
961 !srcPacking
->SwapBytes
&&
962 dstFormat
== &_mesa_texformat_rgb
&&
963 srcFormat
== GL_RGBA
&&
964 srcType
== CHAN_TYPE
) {
965 /* extract RGB from RGBA */
967 for (img
= 0; img
< srcDepth
; img
++) {
968 GLchan
*dstImage
= (GLchan
*)
970 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
971 + dstYoffset
* dstRowStride
972 + dstXoffset
* dstFormat
->TexelBytes
);
974 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
975 srcWidth
, srcFormat
, srcType
);
976 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
977 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
978 GLchan
*dstRow
= dstImage
;
979 for (row
= 0; row
< srcHeight
; row
++) {
980 for (col
= 0; col
< srcWidth
; col
++) {
981 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
982 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
983 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
985 dstRow
+= dstRowStride
/ sizeof(GLchan
);
986 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
990 else if (!ctx
->_ImageTransferState
&&
991 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
992 (srcType
== GL_UNSIGNED_BYTE
||
993 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
994 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
995 can_swizzle(baseInternalFormat
) &&
996 can_swizzle(srcFormat
)) {
998 const GLubyte
*dstmap
;
1001 /* dstmap - how to swizzle from RGBA to dst format:
1003 if (dstFormat
== &_mesa_texformat_rgba
) {
1004 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1007 else if (dstFormat
== &_mesa_texformat_rgb
) {
1008 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1011 else if (dstFormat
== &_mesa_texformat_alpha
) {
1012 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1015 else if (dstFormat
== &_mesa_texformat_luminance
) {
1016 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1019 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1020 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1023 else if (dstFormat
== &_mesa_texformat_intensity
) {
1024 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1028 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1032 _mesa_swizzle_ubyte_image(ctx
, dims
,
1037 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1038 dstRowStride
, dstImageOffsets
,
1039 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1044 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1046 dstFormat
->BaseFormat
,
1047 srcWidth
, srcHeight
, srcDepth
,
1048 srcFormat
, srcType
, srcAddr
,
1050 const GLchan
*src
= tempImage
;
1055 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1056 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1057 for (img
= 0; img
< srcDepth
; img
++) {
1058 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1059 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1060 + dstYoffset
* dstRowStride
1061 + dstXoffset
* dstFormat
->TexelBytes
;
1062 for (row
= 0; row
< srcHeight
; row
++) {
1063 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1064 dstRow
+= dstRowStride
;
1065 src
+= srcWidth
* components
;
1069 _mesa_free((void *) tempImage
);
1076 * Store a 32-bit integer depth component texture image.
1079 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1081 const GLuint depthScale
= 0xffffffff;
1083 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1084 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1086 if (!ctx
->_ImageTransferState
&&
1087 !srcPacking
->SwapBytes
&&
1088 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1089 srcFormat
== GL_DEPTH_COMPONENT
&&
1090 srcType
== GL_UNSIGNED_INT
) {
1091 /* simple memcpy path */
1092 memcpy_texture(ctx
, dims
,
1093 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1096 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1097 srcAddr
, srcPacking
);
1102 for (img
= 0; img
< srcDepth
; img
++) {
1103 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1104 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1105 + dstYoffset
* dstRowStride
1106 + dstXoffset
* dstFormat
->TexelBytes
;
1107 for (row
= 0; row
< srcHeight
; row
++) {
1108 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1109 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1110 _mesa_unpack_depth_span(ctx
, srcWidth
,
1111 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1112 depthScale
, srcType
, src
, srcPacking
);
1113 dstRow
+= dstRowStride
;
1123 * Store a 16-bit integer depth component texture image.
1126 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1128 const GLuint depthScale
= 0xffff;
1130 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1131 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1133 if (!ctx
->_ImageTransferState
&&
1134 !srcPacking
->SwapBytes
&&
1135 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1136 srcFormat
== GL_DEPTH_COMPONENT
&&
1137 srcType
== GL_UNSIGNED_SHORT
) {
1138 /* simple memcpy path */
1139 memcpy_texture(ctx
, dims
,
1140 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1143 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1144 srcAddr
, srcPacking
);
1149 for (img
= 0; img
< srcDepth
; img
++) {
1150 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1151 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1152 + dstYoffset
* dstRowStride
1153 + dstXoffset
* dstFormat
->TexelBytes
;
1154 for (row
= 0; row
< srcHeight
; row
++) {
1155 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1156 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1157 GLushort
*dst16
= (GLushort
*) dstRow
;
1158 _mesa_unpack_depth_span(ctx
, srcWidth
,
1159 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1160 srcType
, src
, srcPacking
);
1161 dstRow
+= dstRowStride
;
1170 * Store an rgb565 or rgb565_rev texture image.
1173 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1175 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1176 dstFormat
== &_mesa_texformat_rgb565_rev
);
1177 ASSERT(dstFormat
->TexelBytes
== 2);
1179 if (!ctx
->_ImageTransferState
&&
1180 !srcPacking
->SwapBytes
&&
1181 dstFormat
== &_mesa_texformat_rgb565
&&
1182 baseInternalFormat
== GL_RGB
&&
1183 srcFormat
== GL_RGB
&&
1184 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1185 /* simple memcpy path */
1186 memcpy_texture(ctx
, dims
,
1187 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1190 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1191 srcAddr
, srcPacking
);
1193 else if (!ctx
->_ImageTransferState
&&
1194 !srcPacking
->SwapBytes
&&
1195 baseInternalFormat
== GL_RGB
&&
1196 srcFormat
== GL_RGB
&&
1197 srcType
== GL_UNSIGNED_BYTE
&&
1199 /* do optimized tex store */
1200 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1201 srcFormat
, srcType
);
1202 const GLubyte
*src
= (const GLubyte
*)
1203 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1204 srcFormat
, srcType
, 0, 0, 0);
1205 GLubyte
*dst
= (GLubyte
*) dstAddr
1206 + dstYoffset
* dstRowStride
1207 + dstXoffset
* dstFormat
->TexelBytes
;
1209 for (row
= 0; row
< srcHeight
; row
++) {
1210 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1211 GLushort
*dstUS
= (GLushort
*) dst
;
1212 /* check for byteswapped format */
1213 if (dstFormat
== &_mesa_texformat_rgb565
) {
1214 for (col
= 0; col
< srcWidth
; col
++) {
1215 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1220 for (col
= 0; col
< srcWidth
; col
++) {
1221 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1225 dst
+= dstRowStride
;
1226 src
+= srcRowStride
;
1231 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1233 dstFormat
->BaseFormat
,
1234 srcWidth
, srcHeight
, srcDepth
,
1235 srcFormat
, srcType
, srcAddr
,
1237 const GLchan
*src
= tempImage
;
1238 GLint img
, row
, col
;
1241 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1242 for (img
= 0; img
< srcDepth
; img
++) {
1243 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1244 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1245 + dstYoffset
* dstRowStride
1246 + dstXoffset
* dstFormat
->TexelBytes
;
1247 for (row
= 0; row
< srcHeight
; row
++) {
1248 GLushort
*dstUS
= (GLushort
*) dstRow
;
1249 /* check for byteswapped format */
1250 if (dstFormat
== &_mesa_texformat_rgb565
) {
1251 for (col
= 0; col
< srcWidth
; col
++) {
1252 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1253 CHAN_TO_UBYTE(src
[GCOMP
]),
1254 CHAN_TO_UBYTE(src
[BCOMP
]) );
1259 for (col
= 0; col
< srcWidth
; col
++) {
1260 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1261 CHAN_TO_UBYTE(src
[GCOMP
]),
1262 CHAN_TO_UBYTE(src
[BCOMP
]) );
1266 dstRow
+= dstRowStride
;
1269 _mesa_free((void *) tempImage
);
1276 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1279 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1281 const GLboolean littleEndian
= _mesa_little_endian();
1283 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1284 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1285 ASSERT(dstFormat
->TexelBytes
== 4);
1287 if (!ctx
->_ImageTransferState
&&
1288 !srcPacking
->SwapBytes
&&
1289 dstFormat
== &_mesa_texformat_rgba8888
&&
1290 baseInternalFormat
== GL_RGBA
&&
1291 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1292 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1293 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1294 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1295 /* simple memcpy path */
1296 memcpy_texture(ctx
, dims
,
1297 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1300 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1301 srcAddr
, srcPacking
);
1303 else if (!ctx
->_ImageTransferState
&&
1304 !srcPacking
->SwapBytes
&&
1305 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1306 baseInternalFormat
== GL_RGBA
&&
1307 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1308 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1309 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1310 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1311 /* simple memcpy path */
1312 memcpy_texture(ctx
, dims
,
1313 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1316 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1317 srcAddr
, srcPacking
);
1319 else if (!ctx
->_ImageTransferState
&&
1320 (srcType
== GL_UNSIGNED_BYTE
||
1321 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1322 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1323 can_swizzle(baseInternalFormat
) &&
1324 can_swizzle(srcFormat
)) {
1328 /* dstmap - how to swizzle from RGBA to dst format:
1330 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1331 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1344 _mesa_swizzle_ubyte_image(ctx
, dims
,
1349 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1350 dstRowStride
, dstImageOffsets
,
1351 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1356 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1358 dstFormat
->BaseFormat
,
1359 srcWidth
, srcHeight
, srcDepth
,
1360 srcFormat
, srcType
, srcAddr
,
1362 const GLchan
*src
= tempImage
;
1363 GLint img
, row
, col
;
1366 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1367 for (img
= 0; img
< srcDepth
; img
++) {
1368 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1369 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1370 + dstYoffset
* dstRowStride
1371 + dstXoffset
* dstFormat
->TexelBytes
;
1372 for (row
= 0; row
< srcHeight
; row
++) {
1373 GLuint
*dstUI
= (GLuint
*) dstRow
;
1374 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1375 for (col
= 0; col
< srcWidth
; col
++) {
1376 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1377 CHAN_TO_UBYTE(src
[GCOMP
]),
1378 CHAN_TO_UBYTE(src
[BCOMP
]),
1379 CHAN_TO_UBYTE(src
[ACOMP
]) );
1384 for (col
= 0; col
< srcWidth
; col
++) {
1385 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1386 CHAN_TO_UBYTE(src
[GCOMP
]),
1387 CHAN_TO_UBYTE(src
[BCOMP
]),
1388 CHAN_TO_UBYTE(src
[ACOMP
]) );
1392 dstRow
+= dstRowStride
;
1395 _mesa_free((void *) tempImage
);
1402 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1404 const GLboolean littleEndian
= _mesa_little_endian();
1406 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1407 dstFormat
== &_mesa_texformat_argb8888_rev
);
1408 ASSERT(dstFormat
->TexelBytes
== 4);
1410 if (!ctx
->_ImageTransferState
&&
1411 !srcPacking
->SwapBytes
&&
1412 dstFormat
== &_mesa_texformat_argb8888
&&
1413 baseInternalFormat
== GL_RGBA
&&
1414 srcFormat
== GL_BGRA
&&
1415 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1416 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1417 /* simple memcpy path (little endian) */
1418 memcpy_texture(ctx
, dims
,
1419 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1422 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1423 srcAddr
, srcPacking
);
1425 else if (!ctx
->_ImageTransferState
&&
1426 !srcPacking
->SwapBytes
&&
1427 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1428 baseInternalFormat
== GL_RGBA
&&
1429 srcFormat
== GL_BGRA
&&
1430 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1431 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1432 /* simple memcpy path (big endian) */
1433 memcpy_texture(ctx
, dims
,
1434 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1437 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1438 srcAddr
, srcPacking
);
1440 else if (!ctx
->_ImageTransferState
&&
1441 !srcPacking
->SwapBytes
&&
1442 dstFormat
== &_mesa_texformat_argb8888
&&
1443 srcFormat
== GL_RGB
&&
1444 (baseInternalFormat
== GL_RGBA
||
1445 baseInternalFormat
== GL_RGB
) &&
1446 srcType
== GL_UNSIGNED_BYTE
) {
1448 for (img
= 0; img
< srcDepth
; img
++) {
1449 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1450 srcWidth
, srcFormat
, srcType
);
1451 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1452 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1453 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1454 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1455 + dstYoffset
* dstRowStride
1456 + dstXoffset
* dstFormat
->TexelBytes
;
1457 for (row
= 0; row
< srcHeight
; row
++) {
1458 GLuint
*d4
= (GLuint
*) dstRow
;
1459 for (col
= 0; col
< srcWidth
; col
++) {
1460 d4
[col
] = ((0xff << 24) |
1461 (srcRow
[col
* 3 + RCOMP
] << 16) |
1462 (srcRow
[col
* 3 + GCOMP
] << 8) |
1463 (srcRow
[col
* 3 + BCOMP
] << 0));
1465 dstRow
+= dstRowStride
;
1466 srcRow
+= srcRowStride
;
1470 else if (!ctx
->_ImageTransferState
&&
1471 !srcPacking
->SwapBytes
&&
1472 dstFormat
== &_mesa_texformat_argb8888
&&
1473 srcFormat
== GL_RGBA
&&
1474 baseInternalFormat
== GL_RGBA
&&
1475 srcType
== GL_UNSIGNED_BYTE
&&
1477 /* same as above case, but src data has alpha too */
1478 GLint img
, row
, col
;
1479 /* For some reason, streaming copies to write-combined regions
1480 * are extremely sensitive to the characteristics of how the
1481 * source data is retrieved. By reordering the source reads to
1482 * be in-order, the speed of this operation increases by half.
1483 * Strangely the same isn't required for the RGB path, above.
1485 for (img
= 0; img
< srcDepth
; img
++) {
1486 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1487 srcWidth
, srcFormat
, srcType
);
1488 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1489 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1490 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1491 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1492 + dstYoffset
* dstRowStride
1493 + dstXoffset
* dstFormat
->TexelBytes
;
1494 for (row
= 0; row
< srcHeight
; row
++) {
1495 GLuint
*d4
= (GLuint
*) dstRow
;
1496 for (col
= 0; col
< srcWidth
; col
++) {
1497 d4
[col
] = ((srcRow
[col
* 4 + ACOMP
] << 24) |
1498 (srcRow
[col
* 4 + RCOMP
] << 16) |
1499 (srcRow
[col
* 4 + GCOMP
] << 8) |
1500 (srcRow
[col
* 4 + BCOMP
] << 0));
1502 dstRow
+= dstRowStride
;
1503 srcRow
+= srcRowStride
;
1507 else if (!ctx
->_ImageTransferState
&&
1508 !srcPacking
->SwapBytes
&&
1509 dstFormat
== &_mesa_texformat_argb8888
&&
1510 srcFormat
== GL_RGBA
&&
1511 baseInternalFormat
== GL_RGBA
&&
1512 srcType
== GL_UNSIGNED_BYTE
) {
1514 GLint img
, row
, col
;
1515 for (img
= 0; img
< srcDepth
; img
++) {
1516 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1517 srcWidth
, srcFormat
, srcType
);
1518 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1519 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1520 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1521 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1522 + dstYoffset
* dstRowStride
1523 + dstXoffset
* dstFormat
->TexelBytes
;
1524 for (row
= 0; row
< srcHeight
; row
++) {
1525 for (col
= 0; col
< srcWidth
; col
++) {
1526 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1527 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1528 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1529 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1531 dstRow
+= dstRowStride
;
1532 srcRow
+= srcRowStride
;
1536 else if (!ctx
->_ImageTransferState
&&
1537 (srcType
== GL_UNSIGNED_BYTE
||
1538 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1539 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1540 can_swizzle(baseInternalFormat
) &&
1541 can_swizzle(srcFormat
)) {
1545 /* dstmap - how to swizzle from RGBA to dst format:
1547 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1548 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1549 dstmap
[3] = 3; /* alpha */
1550 dstmap
[2] = 0; /* red */
1551 dstmap
[1] = 1; /* green */
1552 dstmap
[0] = 2; /* blue */
1555 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1556 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1563 _mesa_swizzle_ubyte_image(ctx
, dims
,
1569 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1572 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1577 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1579 dstFormat
->BaseFormat
,
1580 srcWidth
, srcHeight
, srcDepth
,
1581 srcFormat
, srcType
, srcAddr
,
1583 const GLchan
*src
= tempImage
;
1584 GLint img
, row
, col
;
1587 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1588 for (img
= 0; img
< srcDepth
; img
++) {
1589 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1590 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1591 + dstYoffset
* dstRowStride
1592 + dstXoffset
* dstFormat
->TexelBytes
;
1593 for (row
= 0; row
< srcHeight
; row
++) {
1594 GLuint
*dstUI
= (GLuint
*) dstRow
;
1595 if (dstFormat
== &_mesa_texformat_argb8888
) {
1596 for (col
= 0; col
< srcWidth
; col
++) {
1597 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1598 CHAN_TO_UBYTE(src
[RCOMP
]),
1599 CHAN_TO_UBYTE(src
[GCOMP
]),
1600 CHAN_TO_UBYTE(src
[BCOMP
]) );
1605 for (col
= 0; col
< srcWidth
; col
++) {
1606 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1607 CHAN_TO_UBYTE(src
[RCOMP
]),
1608 CHAN_TO_UBYTE(src
[GCOMP
]),
1609 CHAN_TO_UBYTE(src
[BCOMP
]) );
1613 dstRow
+= dstRowStride
;
1616 _mesa_free((void *) tempImage
);
1623 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1625 const GLboolean littleEndian
= _mesa_little_endian();
1627 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1628 ASSERT(dstFormat
->TexelBytes
== 3);
1630 if (!ctx
->_ImageTransferState
&&
1631 !srcPacking
->SwapBytes
&&
1632 baseInternalFormat
== GL_RGB
&&
1633 srcFormat
== GL_BGR
&&
1634 srcType
== GL_UNSIGNED_BYTE
&&
1636 /* simple memcpy path */
1637 memcpy_texture(ctx
, dims
,
1638 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1641 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1642 srcAddr
, srcPacking
);
1644 else if (!ctx
->_ImageTransferState
&&
1645 !srcPacking
->SwapBytes
&&
1646 srcFormat
== GL_RGBA
&&
1647 srcType
== GL_UNSIGNED_BYTE
) {
1648 /* extract RGB from RGBA */
1649 GLint img
, row
, col
;
1650 for (img
= 0; img
< srcDepth
; img
++) {
1651 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1652 srcWidth
, srcFormat
, srcType
);
1653 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1654 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1655 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1656 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1657 + dstYoffset
* dstRowStride
1658 + dstXoffset
* dstFormat
->TexelBytes
;
1659 for (row
= 0; row
< srcHeight
; row
++) {
1660 for (col
= 0; col
< srcWidth
; col
++) {
1661 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1662 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1663 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1665 dstRow
+= dstRowStride
;
1666 srcRow
+= srcRowStride
;
1670 else if (!ctx
->_ImageTransferState
&&
1671 srcType
== GL_UNSIGNED_BYTE
&&
1672 can_swizzle(baseInternalFormat
) &&
1673 can_swizzle(srcFormat
)) {
1677 /* dstmap - how to swizzle from RGBA to dst format:
1682 dstmap
[3] = ONE
; /* ? */
1684 _mesa_swizzle_ubyte_image(ctx
, dims
,
1689 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1690 dstRowStride
, dstImageOffsets
,
1691 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1696 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1698 dstFormat
->BaseFormat
,
1699 srcWidth
, srcHeight
, srcDepth
,
1700 srcFormat
, srcType
, srcAddr
,
1702 const GLchan
*src
= (const GLchan
*) tempImage
;
1703 GLint img
, row
, col
;
1706 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1707 for (img
= 0; img
< srcDepth
; img
++) {
1708 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1709 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1710 + dstYoffset
* dstRowStride
1711 + dstXoffset
* dstFormat
->TexelBytes
;
1712 for (row
= 0; row
< srcHeight
; row
++) {
1715 for (col
= 0; col
< srcWidth
; col
++) {
1716 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1717 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1718 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1723 for (col
= 0; col
< srcWidth
; col
++) {
1724 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1725 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1726 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1731 for (col
= 0; col
< srcWidth
; col
++) {
1732 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1733 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1734 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1738 dstRow
+= dstRowStride
;
1741 _mesa_free((void *) tempImage
);
1748 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1750 const GLboolean littleEndian
= _mesa_little_endian();
1752 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1753 ASSERT(dstFormat
->TexelBytes
== 3);
1755 if (!ctx
->_ImageTransferState
&&
1756 !srcPacking
->SwapBytes
&&
1757 baseInternalFormat
== GL_RGB
&&
1758 srcFormat
== GL_RGB
&&
1759 srcType
== GL_UNSIGNED_BYTE
&&
1761 /* simple memcpy path */
1762 memcpy_texture(ctx
, dims
,
1763 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1766 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1767 srcAddr
, srcPacking
);
1769 else if (!ctx
->_ImageTransferState
&&
1770 !srcPacking
->SwapBytes
&&
1771 srcFormat
== GL_RGBA
&&
1772 srcType
== GL_UNSIGNED_BYTE
) {
1773 /* extract BGR from RGBA */
1775 for (img
= 0; img
< srcDepth
; img
++) {
1776 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1777 srcWidth
, srcFormat
, srcType
);
1778 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1779 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1780 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1781 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1782 + dstYoffset
* dstRowStride
1783 + dstXoffset
* dstFormat
->TexelBytes
;
1784 for (row
= 0; row
< srcHeight
; row
++) {
1785 for (col
= 0; col
< srcWidth
; col
++) {
1786 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1787 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1788 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1790 dstRow
+= dstRowStride
;
1791 srcRow
+= srcRowStride
;
1795 else if (!ctx
->_ImageTransferState
&&
1796 srcType
== GL_UNSIGNED_BYTE
&&
1797 can_swizzle(baseInternalFormat
) &&
1798 can_swizzle(srcFormat
)) {
1802 /* dstmap - how to swizzle from RGBA to dst format:
1807 dstmap
[3] = ONE
; /* ? */
1809 _mesa_swizzle_ubyte_image(ctx
, dims
,
1814 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1815 dstRowStride
, dstImageOffsets
,
1816 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1821 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1823 dstFormat
->BaseFormat
,
1824 srcWidth
, srcHeight
, srcDepth
,
1825 srcFormat
, srcType
, srcAddr
,
1827 const GLchan
*src
= (const GLchan
*) tempImage
;
1828 GLint img
, row
, col
;
1831 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1832 for (img
= 0; img
< srcDepth
; img
++) {
1833 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1834 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1835 + dstYoffset
* dstRowStride
1836 + dstXoffset
* dstFormat
->TexelBytes
;
1837 for (row
= 0; row
< srcHeight
; row
++) {
1838 for (col
= 0; col
< srcWidth
; col
++) {
1839 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1840 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1841 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1844 dstRow
+= dstRowStride
;
1847 _mesa_free((void *) tempImage
);
1854 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1856 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1857 dstFormat
== &_mesa_texformat_argb4444_rev
);
1858 ASSERT(dstFormat
->TexelBytes
== 2);
1860 if (!ctx
->_ImageTransferState
&&
1861 !srcPacking
->SwapBytes
&&
1862 dstFormat
== &_mesa_texformat_argb4444
&&
1863 baseInternalFormat
== GL_RGBA
&&
1864 srcFormat
== GL_BGRA
&&
1865 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1866 /* simple memcpy path */
1867 memcpy_texture(ctx
, dims
,
1868 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1871 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1872 srcAddr
, srcPacking
);
1876 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1878 dstFormat
->BaseFormat
,
1879 srcWidth
, srcHeight
, srcDepth
,
1880 srcFormat
, srcType
, srcAddr
,
1882 const GLchan
*src
= tempImage
;
1883 GLint img
, row
, col
;
1886 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1887 for (img
= 0; img
< srcDepth
; img
++) {
1888 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1889 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1890 + dstYoffset
* dstRowStride
1891 + dstXoffset
* dstFormat
->TexelBytes
;
1892 for (row
= 0; row
< srcHeight
; row
++) {
1893 GLushort
*dstUS
= (GLushort
*) dstRow
;
1894 if (dstFormat
== &_mesa_texformat_argb4444
) {
1895 for (col
= 0; col
< srcWidth
; col
++) {
1896 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1897 CHAN_TO_UBYTE(src
[RCOMP
]),
1898 CHAN_TO_UBYTE(src
[GCOMP
]),
1899 CHAN_TO_UBYTE(src
[BCOMP
]) );
1904 for (col
= 0; col
< srcWidth
; col
++) {
1905 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1906 CHAN_TO_UBYTE(src
[RCOMP
]),
1907 CHAN_TO_UBYTE(src
[GCOMP
]),
1908 CHAN_TO_UBYTE(src
[BCOMP
]) );
1912 dstRow
+= dstRowStride
;
1915 _mesa_free((void *) tempImage
);
1923 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1925 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1926 dstFormat
== &_mesa_texformat_argb1555_rev
);
1927 ASSERT(dstFormat
->TexelBytes
== 2);
1929 if (!ctx
->_ImageTransferState
&&
1930 !srcPacking
->SwapBytes
&&
1931 dstFormat
== &_mesa_texformat_argb1555
&&
1932 baseInternalFormat
== GL_RGBA
&&
1933 srcFormat
== GL_BGRA
&&
1934 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1935 /* simple memcpy path */
1936 memcpy_texture(ctx
, dims
,
1937 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1940 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1941 srcAddr
, srcPacking
);
1945 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1947 dstFormat
->BaseFormat
,
1948 srcWidth
, srcHeight
, srcDepth
,
1949 srcFormat
, srcType
, srcAddr
,
1951 const GLchan
*src
=tempImage
;
1952 GLint img
, row
, col
;
1955 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1956 for (img
= 0; img
< srcDepth
; img
++) {
1957 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1958 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1959 + dstYoffset
* dstRowStride
1960 + dstXoffset
* dstFormat
->TexelBytes
;
1961 for (row
= 0; row
< srcHeight
; row
++) {
1962 GLushort
*dstUS
= (GLushort
*) dstRow
;
1963 if (dstFormat
== &_mesa_texformat_argb1555
) {
1964 for (col
= 0; col
< srcWidth
; col
++) {
1965 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1966 CHAN_TO_UBYTE(src
[RCOMP
]),
1967 CHAN_TO_UBYTE(src
[GCOMP
]),
1968 CHAN_TO_UBYTE(src
[BCOMP
]) );
1973 for (col
= 0; col
< srcWidth
; col
++) {
1974 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1975 CHAN_TO_UBYTE(src
[RCOMP
]),
1976 CHAN_TO_UBYTE(src
[GCOMP
]),
1977 CHAN_TO_UBYTE(src
[BCOMP
]) );
1981 dstRow
+= dstRowStride
;
1984 _mesa_free((void *) tempImage
);
1991 _mesa_texstore_al88(TEXSTORE_PARAMS
)
1993 const GLboolean littleEndian
= _mesa_little_endian();
1995 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1996 dstFormat
== &_mesa_texformat_al88_rev
);
1997 ASSERT(dstFormat
->TexelBytes
== 2);
1999 if (!ctx
->_ImageTransferState
&&
2000 !srcPacking
->SwapBytes
&&
2001 dstFormat
== &_mesa_texformat_al88
&&
2002 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2003 srcFormat
== GL_LUMINANCE_ALPHA
&&
2004 srcType
== GL_UNSIGNED_BYTE
&&
2006 /* simple memcpy path */
2007 memcpy_texture(ctx
, dims
,
2008 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2011 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2012 srcAddr
, srcPacking
);
2014 else if (!ctx
->_ImageTransferState
&&
2016 srcType
== GL_UNSIGNED_BYTE
&&
2017 can_swizzle(baseInternalFormat
) &&
2018 can_swizzle(srcFormat
)) {
2022 /* dstmap - how to swizzle from RGBA to dst format:
2024 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2025 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2033 dstmap
[2] = ZERO
; /* ? */
2034 dstmap
[3] = ONE
; /* ? */
2036 _mesa_swizzle_ubyte_image(ctx
, dims
,
2041 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2042 dstRowStride
, dstImageOffsets
,
2043 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2048 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2050 dstFormat
->BaseFormat
,
2051 srcWidth
, srcHeight
, srcDepth
,
2052 srcFormat
, srcType
, srcAddr
,
2054 const GLchan
*src
= tempImage
;
2055 GLint img
, row
, col
;
2058 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2059 for (img
= 0; img
< srcDepth
; img
++) {
2060 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2061 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2062 + dstYoffset
* dstRowStride
2063 + dstXoffset
* dstFormat
->TexelBytes
;
2064 for (row
= 0; row
< srcHeight
; row
++) {
2065 GLushort
*dstUS
= (GLushort
*) dstRow
;
2066 if (dstFormat
== &_mesa_texformat_al88
) {
2067 for (col
= 0; col
< srcWidth
; col
++) {
2068 /* src[0] is luminance, src[1] is alpha */
2069 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2070 CHAN_TO_UBYTE(src
[0]) );
2075 for (col
= 0; col
< srcWidth
; col
++) {
2076 /* src[0] is luminance, src[1] is alpha */
2077 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2078 CHAN_TO_UBYTE(src
[0]) );
2082 dstRow
+= dstRowStride
;
2085 _mesa_free((void *) tempImage
);
2092 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2094 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2095 ASSERT(dstFormat
->TexelBytes
== 1);
2097 if (!ctx
->_ImageTransferState
&&
2098 !srcPacking
->SwapBytes
&&
2099 baseInternalFormat
== GL_RGB
&&
2100 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2101 /* simple memcpy path */
2102 memcpy_texture(ctx
, dims
,
2103 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2106 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2107 srcAddr
, srcPacking
);
2111 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2113 dstFormat
->BaseFormat
,
2114 srcWidth
, srcHeight
, srcDepth
,
2115 srcFormat
, srcType
, srcAddr
,
2117 const GLchan
*src
= tempImage
;
2118 GLint img
, row
, col
;
2121 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2122 for (img
= 0; img
< srcDepth
; img
++) {
2123 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2124 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2125 + dstYoffset
* dstRowStride
2126 + dstXoffset
* dstFormat
->TexelBytes
;
2127 for (row
= 0; row
< srcHeight
; row
++) {
2128 for (col
= 0; col
< srcWidth
; col
++) {
2129 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2130 CHAN_TO_UBYTE(src
[GCOMP
]),
2131 CHAN_TO_UBYTE(src
[BCOMP
]) );
2134 dstRow
+= dstRowStride
;
2137 _mesa_free((void *) tempImage
);
2144 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2147 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2149 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2150 dstFormat
== &_mesa_texformat_l8
||
2151 dstFormat
== &_mesa_texformat_i8
);
2152 ASSERT(dstFormat
->TexelBytes
== 1);
2154 if (!ctx
->_ImageTransferState
&&
2155 !srcPacking
->SwapBytes
&&
2156 baseInternalFormat
== srcFormat
&&
2157 srcType
== GL_UNSIGNED_BYTE
) {
2158 /* simple memcpy path */
2159 memcpy_texture(ctx
, dims
,
2160 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2163 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2164 srcAddr
, srcPacking
);
2166 else if (!ctx
->_ImageTransferState
&&
2167 srcType
== GL_UNSIGNED_BYTE
&&
2168 can_swizzle(baseInternalFormat
) &&
2169 can_swizzle(srcFormat
)) {
2173 /* dstmap - how to swizzle from RGBA to dst format:
2175 if (dstFormat
== &_mesa_texformat_a8
) {
2181 dstmap
[1] = ZERO
; /* ? */
2182 dstmap
[2] = ZERO
; /* ? */
2183 dstmap
[3] = ONE
; /* ? */
2185 _mesa_swizzle_ubyte_image(ctx
, dims
,
2190 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2191 dstRowStride
, dstImageOffsets
,
2192 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2197 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2199 dstFormat
->BaseFormat
,
2200 srcWidth
, srcHeight
, srcDepth
,
2201 srcFormat
, srcType
, srcAddr
,
2203 const GLchan
*src
= tempImage
;
2204 GLint img
, row
, col
;
2207 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2208 for (img
= 0; img
< srcDepth
; img
++) {
2209 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2210 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2211 + dstYoffset
* dstRowStride
2212 + dstXoffset
* dstFormat
->TexelBytes
;
2213 for (row
= 0; row
< srcHeight
; row
++) {
2214 for (col
= 0; col
< srcWidth
; col
++) {
2215 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2217 dstRow
+= dstRowStride
;
2221 _mesa_free((void *) tempImage
);
2229 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2231 (void) dims
; (void) baseInternalFormat
;
2232 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2233 ASSERT(dstFormat
->TexelBytes
== 1);
2234 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2236 if (!ctx
->_ImageTransferState
&&
2237 !srcPacking
->SwapBytes
&&
2238 srcFormat
== GL_COLOR_INDEX
&&
2239 srcType
== GL_UNSIGNED_BYTE
) {
2240 /* simple memcpy path */
2241 memcpy_texture(ctx
, dims
,
2242 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2245 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2246 srcAddr
, srcPacking
);
2251 for (img
= 0; img
< srcDepth
; img
++) {
2252 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2253 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2254 + dstYoffset
* dstRowStride
2255 + dstXoffset
* dstFormat
->TexelBytes
;
2256 for (row
= 0; row
< srcHeight
; row
++) {
2257 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2258 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2259 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2260 srcType
, src
, srcPacking
,
2261 ctx
->_ImageTransferState
);
2262 dstRow
+= dstRowStride
;
2271 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2274 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2276 const GLboolean littleEndian
= _mesa_little_endian();
2277 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2279 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2280 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2281 ASSERT(dstFormat
->TexelBytes
== 2);
2282 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2283 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2284 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2285 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2286 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2288 /* always just memcpy since no pixel transfer ops apply */
2289 memcpy_texture(ctx
, dims
,
2290 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2293 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2294 srcAddr
, srcPacking
);
2296 /* Check if we need byte swapping */
2297 /* XXX the logic here _might_ be wrong */
2298 if (srcPacking
->SwapBytes
^
2299 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2300 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2303 for (img
= 0; img
< srcDepth
; img
++) {
2304 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2305 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2306 + dstYoffset
* dstRowStride
2307 + dstXoffset
* dstFormat
->TexelBytes
;
2308 for (row
= 0; row
< srcHeight
; row
++) {
2309 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2310 dstRow
+= dstRowStride
;
2320 * Store a combined depth/stencil texture image.
2323 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2325 const GLuint depthScale
= 0xffffff;
2327 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2328 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2329 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2331 if (!ctx
->_ImageTransferState
&&
2332 !srcPacking
->SwapBytes
) {
2334 memcpy_texture(ctx
, dims
,
2335 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2338 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2339 srcAddr
, srcPacking
);
2343 const GLint srcRowStride
2344 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2348 for (img
= 0; img
< srcDepth
; img
++) {
2349 GLuint
*dstRow
= (GLuint
*) dstAddr
2350 + dstImageOffsets
[dstZoffset
+ img
]
2351 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2354 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2355 srcWidth
, srcHeight
,
2358 for (row
= 0; row
< srcHeight
; row
++) {
2359 GLubyte stencil
[MAX_WIDTH
];
2361 /* the 24 depth bits will be in the high position: */
2362 _mesa_unpack_depth_span(ctx
, srcWidth
,
2363 GL_UNSIGNED_INT
, /* dst type */
2364 dstRow
, /* dst addr */
2366 srcType
, src
, srcPacking
);
2367 /* get the 8-bit stencil values */
2368 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2369 GL_UNSIGNED_BYTE
, /* dst type */
2370 stencil
, /* dst addr */
2371 srcType
, src
, srcPacking
,
2372 ctx
->_ImageTransferState
);
2373 /* merge stencil values into depth values */
2374 for (i
= 0; i
< srcWidth
; i
++)
2375 dstRow
[i
] |= stencil
[i
];
2377 src
+= srcRowStride
;
2378 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2388 * Store an image in any of the formats:
2389 * _mesa_texformat_rgba_float32
2390 * _mesa_texformat_rgb_float32
2391 * _mesa_texformat_alpha_float32
2392 * _mesa_texformat_luminance_float32
2393 * _mesa_texformat_luminance_alpha_float32
2394 * _mesa_texformat_intensity_float32
2397 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2399 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2401 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2402 dstFormat
== &_mesa_texformat_rgb_float32
||
2403 dstFormat
== &_mesa_texformat_alpha_float32
||
2404 dstFormat
== &_mesa_texformat_luminance_float32
||
2405 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2406 dstFormat
== &_mesa_texformat_intensity_float32
);
2407 ASSERT(baseInternalFormat
== GL_RGBA
||
2408 baseInternalFormat
== GL_RGB
||
2409 baseInternalFormat
== GL_ALPHA
||
2410 baseInternalFormat
== GL_LUMINANCE
||
2411 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2412 baseInternalFormat
== GL_INTENSITY
);
2413 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2415 if (!ctx
->_ImageTransferState
&&
2416 !srcPacking
->SwapBytes
&&
2417 baseInternalFormat
== srcFormat
&&
2418 srcType
== GL_FLOAT
) {
2419 /* simple memcpy path */
2420 memcpy_texture(ctx
, dims
,
2421 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2424 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2425 srcAddr
, srcPacking
);
2429 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2431 dstFormat
->BaseFormat
,
2432 srcWidth
, srcHeight
, srcDepth
,
2433 srcFormat
, srcType
, srcAddr
,
2435 const GLfloat
*srcRow
= tempImage
;
2440 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2441 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2442 for (img
= 0; img
< srcDepth
; img
++) {
2443 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2444 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2445 + dstYoffset
* dstRowStride
2446 + dstXoffset
* dstFormat
->TexelBytes
;
2447 for (row
= 0; row
< srcHeight
; row
++) {
2448 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2449 dstRow
+= dstRowStride
;
2450 srcRow
+= srcWidth
* components
;
2454 _mesa_free((void *) tempImage
);
2461 * As above, but store 16-bit floats.
2464 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2466 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2468 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2469 dstFormat
== &_mesa_texformat_rgb_float16
||
2470 dstFormat
== &_mesa_texformat_alpha_float16
||
2471 dstFormat
== &_mesa_texformat_luminance_float16
||
2472 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2473 dstFormat
== &_mesa_texformat_intensity_float16
);
2474 ASSERT(baseInternalFormat
== GL_RGBA
||
2475 baseInternalFormat
== GL_RGB
||
2476 baseInternalFormat
== GL_ALPHA
||
2477 baseInternalFormat
== GL_LUMINANCE
||
2478 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2479 baseInternalFormat
== GL_INTENSITY
);
2480 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2482 if (!ctx
->_ImageTransferState
&&
2483 !srcPacking
->SwapBytes
&&
2484 baseInternalFormat
== srcFormat
&&
2485 srcType
== GL_HALF_FLOAT_ARB
) {
2486 /* simple memcpy path */
2487 memcpy_texture(ctx
, dims
,
2488 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2491 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2492 srcAddr
, srcPacking
);
2496 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2498 dstFormat
->BaseFormat
,
2499 srcWidth
, srcHeight
, srcDepth
,
2500 srcFormat
, srcType
, srcAddr
,
2502 const GLfloat
*src
= tempImage
;
2506 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2507 for (img
= 0; img
< srcDepth
; img
++) {
2508 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2509 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2510 + dstYoffset
* dstRowStride
2511 + dstXoffset
* dstFormat
->TexelBytes
;
2512 for (row
= 0; row
< srcHeight
; row
++) {
2513 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2515 for (i
= 0; i
< srcWidth
* components
; i
++) {
2516 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2518 dstRow
+= dstRowStride
;
2519 src
+= srcWidth
* components
;
2523 _mesa_free((void *) tempImage
);
2529 #if FEATURE_EXT_texture_sRGB
2531 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2533 const GLboolean littleEndian
= _mesa_little_endian();
2534 const struct gl_texture_format
*newDstFormat
;
2535 StoreTexImageFunc store
;
2538 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2540 /* reuse normal rgb texstore code */
2542 newDstFormat
= &_mesa_texformat_bgr888
;
2543 store
= _mesa_texstore_bgr888
;
2546 newDstFormat
= &_mesa_texformat_rgb888
;
2547 store
= _mesa_texstore_rgb888
;
2550 k
= store(ctx
, dims
, baseInternalFormat
,
2551 newDstFormat
, dstAddr
,
2552 dstXoffset
, dstYoffset
, dstZoffset
,
2553 dstRowStride
, dstImageOffsets
,
2554 srcWidth
, srcHeight
, srcDepth
,
2556 srcAddr
, srcPacking
);
2562 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2564 const GLboolean littleEndian
= _mesa_little_endian();
2565 const struct gl_texture_format
*newDstFormat
;
2568 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2570 /* reuse normal rgba texstore code */
2572 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2574 newDstFormat
= &_mesa_texformat_rgba8888
;
2576 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2577 newDstFormat
, dstAddr
,
2578 dstXoffset
, dstYoffset
, dstZoffset
,
2579 dstRowStride
, dstImageOffsets
,
2580 srcWidth
, srcHeight
, srcDepth
,
2582 srcAddr
, srcPacking
);
2588 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2590 const struct gl_texture_format
*newDstFormat
;
2593 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2595 newDstFormat
= &_mesa_texformat_l8
;
2597 /* _mesa_textore_a8 handles luminance8 too */
2598 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2599 newDstFormat
, dstAddr
,
2600 dstXoffset
, dstYoffset
, dstZoffset
,
2601 dstRowStride
, dstImageOffsets
,
2602 srcWidth
, srcHeight
, srcDepth
,
2604 srcAddr
, srcPacking
);
2610 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2612 const GLboolean littleEndian
= _mesa_little_endian();
2613 const struct gl_texture_format
*newDstFormat
;
2616 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2618 /* reuse normal luminance/alpha texstore code */
2620 newDstFormat
= &_mesa_texformat_al88
;
2622 newDstFormat
= &_mesa_texformat_al88_rev
;
2624 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2625 newDstFormat
, dstAddr
,
2626 dstXoffset
, dstYoffset
, dstZoffset
,
2627 dstRowStride
, dstImageOffsets
,
2628 srcWidth
, srcHeight
, srcDepth
,
2630 srcAddr
, srcPacking
);
2634 #endif /* FEATURE_EXT_texture_sRGB */
2638 * Check if an unpack PBO is active prior to fetching a texture image.
2639 * If so, do bounds checking and map the buffer into main memory.
2640 * Any errors detected will be recorded.
2641 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2644 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2645 GLsizei width
, GLsizei height
, GLsizei depth
,
2646 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2647 const struct gl_pixelstore_attrib
*unpack
,
2648 const char *funcName
)
2652 if (unpack
->BufferObj
->Name
== 0) {
2656 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2657 format
, type
, pixels
)) {
2658 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2662 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2663 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2665 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2669 return ADD_POINTERS(buf
, pixels
);
2674 * Check if an unpack PBO is active prior to fetching a compressed texture
2676 * If so, do bounds checking and map the buffer into main memory.
2677 * Any errors detected will be recorded.
2678 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2681 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2682 GLsizei imageSize
, const GLvoid
*pixels
,
2683 const struct gl_pixelstore_attrib
*packing
,
2684 const char *funcName
)
2688 if (packing
->BufferObj
->Name
== 0) {
2689 /* not using a PBO - return pointer unchanged */
2692 if ((const GLubyte
*) pixels
+ imageSize
>
2693 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2694 /* out of bounds read! */
2695 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2699 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2700 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2702 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2706 return ADD_POINTERS(buf
, pixels
);
2711 * This function must be called after either of the validate_pbo_*_teximage()
2712 * functions. It unmaps the PBO buffer if it was mapped earlier.
2715 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2716 const struct gl_pixelstore_attrib
*unpack
)
2718 if (unpack
->BufferObj
->Name
) {
2719 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2727 * Adaptor for fetching a GLchan texel from a float-valued texture.
2730 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2731 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2734 ASSERT(texImage
->FetchTexelf
);
2735 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2736 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2737 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2738 /* just one channel */
2739 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2743 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2744 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2745 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2746 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2752 * Adaptor for fetching a float texel from a GLchan-valued texture.
2755 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2756 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2759 ASSERT(texImage
->FetchTexelc
);
2760 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2761 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2762 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2763 /* just one channel */
2764 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2768 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2769 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2770 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2771 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2777 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2780 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2782 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2783 ASSERT(texImage
->TexFormat
);
2787 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2788 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2791 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2792 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2795 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2796 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2802 /* now check if we need to use a float/chan adaptor */
2803 if (!texImage
->FetchTexelc
) {
2804 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
2806 else if (!texImage
->FetchTexelf
) {
2807 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
2811 ASSERT(texImage
->FetchTexelc
);
2812 ASSERT(texImage
->FetchTexelf
);
2817 * Choose the actual storage format for a new texture image.
2818 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2819 * Also set some other texImage fields related to texture compression, etc.
2820 * \param ctx rendering context
2821 * \param texImage the gl_texture_image
2822 * \param dims texture dimensions (1, 2 or 3)
2823 * \param format the user-specified format parameter
2824 * \param type the user-specified type parameter
2825 * \param internalFormat the user-specified internal format hint
2828 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2830 GLenum format
, GLenum type
, GLint internalFormat
)
2832 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2833 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2836 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2838 ASSERT(texImage
->TexFormat
);
2840 _mesa_set_fetch_functions(texImage
, dims
);
2842 if (texImage
->TexFormat
->TexelBytes
== 0) {
2843 /* must be a compressed format */
2844 texImage
->IsCompressed
= GL_TRUE
;
2845 texImage
->CompressedSize
=
2846 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2847 texImage
->Height
, texImage
->Depth
,
2848 texImage
->TexFormat
->MesaFormat
);
2851 /* non-compressed format */
2852 texImage
->IsCompressed
= GL_FALSE
;
2853 texImage
->CompressedSize
= 0;
2860 * This is the software fallback for Driver.TexImage1D()
2861 * and Driver.CopyTexImage1D().
2862 * \sa _mesa_store_teximage2d()
2865 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2866 GLint internalFormat
,
2867 GLint width
, GLint border
,
2868 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2869 const struct gl_pixelstore_attrib
*packing
,
2870 struct gl_texture_object
*texObj
,
2871 struct gl_texture_image
*texImage
)
2873 GLint postConvWidth
= width
;
2877 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2878 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2881 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2883 /* allocate memory */
2884 if (texImage
->IsCompressed
)
2885 sizeInBytes
= texImage
->CompressedSize
;
2887 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2888 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2889 if (!texImage
->Data
) {
2890 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2894 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2895 pixels
, packing
, "glTexImage1D");
2897 /* Note: we check for a NULL image pointer here, _after_ we allocated
2898 * memory for the texture. That's what the GL spec calls for.
2903 const GLint dstRowStride
= 0;
2905 ASSERT(texImage
->TexFormat
->StoreImage
);
2906 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2907 texImage
->TexFormat
,
2909 0, 0, 0, /* dstX/Y/Zoffset */
2911 texImage
->ImageOffsets
,
2913 format
, type
, pixels
, packing
);
2915 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2919 /* GL_SGIS_generate_mipmap */
2920 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2921 _mesa_generate_mipmap(ctx
, target
,
2922 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2926 _mesa_unmap_teximage_pbo(ctx
, packing
);
2931 * This is the software fallback for Driver.TexImage2D()
2932 * and Driver.CopyTexImage2D().
2934 * This function is oriented toward storing images in main memory, rather
2935 * than VRAM. Device driver's can easily plug in their own replacement.
2937 * Note: width and height may be pre-convolved dimensions, but
2938 * texImage->Width and texImage->Height will be post-convolved dimensions.
2941 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2942 GLint internalFormat
,
2943 GLint width
, GLint height
, GLint border
,
2944 GLenum format
, GLenum type
, const void *pixels
,
2945 const struct gl_pixelstore_attrib
*packing
,
2946 struct gl_texture_object
*texObj
,
2947 struct gl_texture_image
*texImage
)
2949 GLint postConvWidth
= width
, postConvHeight
= height
;
2950 GLint texelBytes
, sizeInBytes
;
2953 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2954 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2958 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2960 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2962 /* allocate memory */
2963 if (texImage
->IsCompressed
)
2964 sizeInBytes
= texImage
->CompressedSize
;
2966 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2967 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2968 if (!texImage
->Data
) {
2969 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2973 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2974 pixels
, packing
, "glTexImage2D");
2976 /* Note: we check for a NULL image pointer here, _after_ we allocated
2977 * memory for the texture. That's what the GL spec calls for.
2984 if (texImage
->IsCompressed
) {
2986 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2989 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2991 ASSERT(texImage
->TexFormat
->StoreImage
);
2992 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2993 texImage
->TexFormat
,
2995 0, 0, 0, /* dstX/Y/Zoffset */
2997 texImage
->ImageOffsets
,
2999 format
, type
, pixels
, packing
);
3001 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3005 /* GL_SGIS_generate_mipmap */
3006 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3007 _mesa_generate_mipmap(ctx
, target
,
3008 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3012 _mesa_unmap_teximage_pbo(ctx
, packing
);
3018 * This is the software fallback for Driver.TexImage3D()
3019 * and Driver.CopyTexImage3D().
3020 * \sa _mesa_store_teximage2d()
3023 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3024 GLint internalFormat
,
3025 GLint width
, GLint height
, GLint depth
, GLint border
,
3026 GLenum format
, GLenum type
, const void *pixels
,
3027 const struct gl_pixelstore_attrib
*packing
,
3028 struct gl_texture_object
*texObj
,
3029 struct gl_texture_image
*texImage
)
3031 GLint texelBytes
, sizeInBytes
;
3034 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3036 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3038 /* allocate memory */
3039 if (texImage
->IsCompressed
)
3040 sizeInBytes
= texImage
->CompressedSize
;
3042 sizeInBytes
= width
* height
* depth
* texelBytes
;
3043 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3044 if (!texImage
->Data
) {
3045 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3049 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3050 type
, pixels
, packing
, "glTexImage3D");
3052 /* Note: we check for a NULL image pointer here, _after_ we allocated
3053 * memory for the texture. That's what the GL spec calls for.
3060 if (texImage
->IsCompressed
) {
3062 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3065 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3067 ASSERT(texImage
->TexFormat
->StoreImage
);
3068 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3069 texImage
->TexFormat
,
3071 0, 0, 0, /* dstX/Y/Zoffset */
3073 texImage
->ImageOffsets
,
3074 width
, height
, depth
,
3075 format
, type
, pixels
, packing
);
3077 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3081 /* GL_SGIS_generate_mipmap */
3082 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3083 _mesa_generate_mipmap(ctx
, target
,
3084 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3088 _mesa_unmap_teximage_pbo(ctx
, packing
);
3095 * This is the software fallback for Driver.TexSubImage1D()
3096 * and Driver.CopyTexSubImage1D().
3099 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3100 GLint xoffset
, GLint width
,
3101 GLenum format
, GLenum type
, const void *pixels
,
3102 const struct gl_pixelstore_attrib
*packing
,
3103 struct gl_texture_object
*texObj
,
3104 struct gl_texture_image
*texImage
)
3106 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3107 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3108 pixels
, packing
, "glTexSubImage1D");
3113 const GLint dstRowStride
= 0;
3115 ASSERT(texImage
->TexFormat
->StoreImage
);
3116 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3117 texImage
->TexFormat
,
3119 xoffset
, 0, 0, /* offsets */
3121 texImage
->ImageOffsets
,
3123 format
, type
, pixels
, packing
);
3125 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3129 /* GL_SGIS_generate_mipmap */
3130 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3131 _mesa_generate_mipmap(ctx
, target
,
3132 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3136 _mesa_unmap_teximage_pbo(ctx
, packing
);
3142 * This is the software fallback for Driver.TexSubImage2D()
3143 * and Driver.CopyTexSubImage2D().
3146 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3147 GLint xoffset
, GLint yoffset
,
3148 GLint width
, GLint height
,
3149 GLenum format
, GLenum type
, const void *pixels
,
3150 const struct gl_pixelstore_attrib
*packing
,
3151 struct gl_texture_object
*texObj
,
3152 struct gl_texture_image
*texImage
)
3154 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3155 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3156 pixels
, packing
, "glTexSubImage2D");
3161 GLint dstRowStride
= 0;
3163 if (texImage
->IsCompressed
) {
3164 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3168 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3170 ASSERT(texImage
->TexFormat
->StoreImage
);
3171 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3172 texImage
->TexFormat
,
3174 xoffset
, yoffset
, 0,
3176 texImage
->ImageOffsets
,
3178 format
, type
, pixels
, packing
);
3180 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3184 /* GL_SGIS_generate_mipmap */
3185 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3186 _mesa_generate_mipmap(ctx
, target
,
3187 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3191 _mesa_unmap_teximage_pbo(ctx
, packing
);
3196 * This is the software fallback for Driver.TexSubImage3D().
3197 * and Driver.CopyTexSubImage3D().
3200 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3201 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3202 GLint width
, GLint height
, GLint depth
,
3203 GLenum format
, GLenum type
, const void *pixels
,
3204 const struct gl_pixelstore_attrib
*packing
,
3205 struct gl_texture_object
*texObj
,
3206 struct gl_texture_image
*texImage
)
3208 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3209 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3210 type
, pixels
, packing
,
3218 if (texImage
->IsCompressed
) {
3219 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3223 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3225 ASSERT(texImage
->TexFormat
->StoreImage
);
3226 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3227 texImage
->TexFormat
,
3229 xoffset
, yoffset
, zoffset
,
3231 texImage
->ImageOffsets
,
3232 width
, height
, depth
,
3233 format
, type
, pixels
, packing
);
3235 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3239 /* GL_SGIS_generate_mipmap */
3240 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3241 _mesa_generate_mipmap(ctx
, target
,
3242 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3246 _mesa_unmap_teximage_pbo(ctx
, packing
);
3251 * Fallback for Driver.CompressedTexImage1D()
3254 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3255 GLint internalFormat
,
3256 GLint width
, GLint border
,
3257 GLsizei imageSize
, const GLvoid
*data
,
3258 struct gl_texture_object
*texObj
,
3259 struct gl_texture_image
*texImage
)
3261 /* this space intentionally left blank */
3263 (void) target
; (void) level
;
3264 (void) internalFormat
;
3265 (void) width
; (void) border
;
3266 (void) imageSize
; (void) data
;
3274 * Fallback for Driver.CompressedTexImage2D()
3277 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3278 GLint internalFormat
,
3279 GLint width
, GLint height
, GLint border
,
3280 GLsizei imageSize
, const GLvoid
*data
,
3281 struct gl_texture_object
*texObj
,
3282 struct gl_texture_image
*texImage
)
3284 (void) width
; (void) height
; (void) border
;
3286 /* This is pretty simple, basically just do a memcpy without worrying
3287 * about the usual image unpacking or image transfer operations.
3291 ASSERT(texImage
->Width
> 0);
3292 ASSERT(texImage
->Height
> 0);
3293 ASSERT(texImage
->Depth
== 1);
3294 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3296 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3298 /* allocate storage */
3299 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3300 if (!texImage
->Data
) {
3301 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3305 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3307 "glCompressedTexImage2D");
3312 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3313 MEMCPY(texImage
->Data
, data
, imageSize
);
3315 /* GL_SGIS_generate_mipmap */
3316 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3317 _mesa_generate_mipmap(ctx
, target
,
3318 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3322 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3328 * Fallback for Driver.CompressedTexImage3D()
3331 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3332 GLint internalFormat
,
3333 GLint width
, GLint height
, GLint depth
,
3335 GLsizei imageSize
, const GLvoid
*data
,
3336 struct gl_texture_object
*texObj
,
3337 struct gl_texture_image
*texImage
)
3339 /* this space intentionally left blank */
3341 (void) target
; (void) level
;
3342 (void) internalFormat
;
3343 (void) width
; (void) height
; (void) depth
;
3345 (void) imageSize
; (void) data
;
3353 * Fallback for Driver.CompressedTexSubImage1D()
3356 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3358 GLint xoffset
, GLsizei width
,
3360 GLsizei imageSize
, const GLvoid
*data
,
3361 struct gl_texture_object
*texObj
,
3362 struct gl_texture_image
*texImage
)
3364 /* there are no compressed 1D texture formats yet */
3366 (void) target
; (void) level
;
3367 (void) xoffset
; (void) width
;
3369 (void) imageSize
; (void) data
;
3376 * Fallback for Driver.CompressedTexSubImage2D()
3379 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3381 GLint xoffset
, GLint yoffset
,
3382 GLsizei width
, GLsizei height
,
3384 GLsizei imageSize
, const GLvoid
*data
,
3385 struct gl_texture_object
*texObj
,
3386 struct gl_texture_image
*texImage
)
3388 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3392 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3396 /* these should have been caught sooner */
3397 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3398 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3399 ASSERT((xoffset
& 3) == 0);
3400 ASSERT((yoffset
& 3) == 0);
3402 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3403 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3405 "glCompressedTexSubImage2D");
3409 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3410 src
= (const GLubyte
*) data
;
3412 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3413 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3414 texImage
->TexFormat
->MesaFormat
,
3416 (GLubyte
*) texImage
->Data
);
3418 bytesPerRow
= srcRowStride
;
3421 for (i
= 0; i
< rows
; i
++) {
3422 MEMCPY(dest
, src
, bytesPerRow
);
3423 dest
+= destRowStride
;
3424 src
+= srcRowStride
;
3427 /* GL_SGIS_generate_mipmap */
3428 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3429 _mesa_generate_mipmap(ctx
, target
,
3430 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3434 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3439 * Fallback for Driver.CompressedTexSubImage3D()
3442 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3444 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3445 GLsizei width
, GLsizei height
, GLsizei depth
,
3447 GLsizei imageSize
, const GLvoid
*data
,
3448 struct gl_texture_object
*texObj
,
3449 struct gl_texture_image
*texImage
)
3451 /* there are no compressed 3D texture formats yet */
3453 (void) target
; (void) level
;
3454 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3455 (void) width
; (void) height
; (void) depth
;
3457 (void) imageSize
; (void) data
;
3465 #if FEATURE_EXT_texture_sRGB
3468 * Test if given texture image is an sRGB format.
3471 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3473 switch (texImage
->TexFormat
->MesaFormat
) {
3474 case MESA_FORMAT_SRGB8
:
3475 case MESA_FORMAT_SRGBA8
:
3476 case MESA_FORMAT_SL8
:
3477 case MESA_FORMAT_SLA8
:
3484 #endif /* FEATURE_EXT_texture_sRGB */
3488 * This is the software fallback for Driver.GetTexImage().
3489 * All error checking will have been done before this routine is called.
3492 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3493 GLenum format
, GLenum type
, GLvoid
*pixels
,
3494 struct gl_texture_object
*texObj
,
3495 struct gl_texture_image
*texImage
)
3497 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3499 if (ctx
->Pack
.BufferObj
->Name
) {
3500 /* Packing texture image into a PBO.
3501 * Map the (potentially) VRAM-based buffer into our process space so
3502 * we can write into it with the code below.
3503 * A hardware driver might use a sophisticated blit to move the
3504 * texture data to the PBO if the PBO is in VRAM along with the texture.
3506 GLubyte
*buf
= (GLubyte
*)
3507 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3508 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3510 /* buffer is already mapped - that's an error */
3511 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3514 /* <pixels> was an offset into the PBO.
3515 * Now make it a real, client-side pointer inside the mapped region.
3517 pixels
= ADD_POINTERS(buf
, pixels
);
3525 const GLint width
= texImage
->Width
;
3526 const GLint height
= texImage
->Height
;
3527 const GLint depth
= texImage
->Depth
;
3529 for (img
= 0; img
< depth
; img
++) {
3530 for (row
= 0; row
< height
; row
++) {
3531 /* compute destination address in client memory */
3532 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3533 width
, height
, format
, type
,
3537 if (format
== GL_COLOR_INDEX
) {
3538 GLuint indexRow
[MAX_WIDTH
];
3540 /* Can't use FetchTexel here because that returns RGBA */
3541 if (texImage
->TexFormat
->IndexBits
== 8) {
3542 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3543 src
+= width
* (img
* texImage
->Height
+ row
);
3544 for (col
= 0; col
< width
; col
++) {
3545 indexRow
[col
] = src
[col
];
3548 else if (texImage
->TexFormat
->IndexBits
== 16) {
3549 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3550 src
+= width
* (img
* texImage
->Height
+ row
);
3551 for (col
= 0; col
< width
; col
++) {
3552 indexRow
[col
] = src
[col
];
3557 "Color index problem in _mesa_GetTexImage");
3559 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3560 indexRow
, &ctx
->Pack
,
3561 0 /* no image transfer */);
3563 else if (format
== GL_DEPTH_COMPONENT
) {
3564 GLfloat depthRow
[MAX_WIDTH
];
3566 for (col
= 0; col
< width
; col
++) {
3567 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3570 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3571 depthRow
, &ctx
->Pack
);
3573 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3574 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3575 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3576 src
+= width
* row
+ width
* height
* img
;
3577 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3578 if (ctx
->Pack
.SwapBytes
) {
3579 _mesa_swap4((GLuint
*) dest
, width
);
3582 else if (format
== GL_YCBCR_MESA
) {
3583 /* No pixel transfer */
3584 const GLint rowstride
= texImage
->RowStride
;
3586 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3587 width
* sizeof(GLushort
));
3588 /* check for byte swapping */
3589 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3590 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3591 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3592 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3593 if (!ctx
->Pack
.SwapBytes
)
3594 _mesa_swap2((GLushort
*) dest
, width
);
3596 else if (ctx
->Pack
.SwapBytes
) {
3597 _mesa_swap2((GLushort
*) dest
, width
);
3600 #if FEATURE_EXT_texture_sRGB
3601 else if (is_srgb_teximage(texImage
)) {
3602 /* no pixel transfer and no non-linear to linear conversion */
3603 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3604 const GLint rowstride
= comps
* texImage
->RowStride
;
3606 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3607 comps
* width
* sizeof(GLubyte
));
3609 #endif /* FEATURE_EXT_texture_sRGB */
3611 /* general case: convert row to RGBA format */
3612 GLfloat rgba
[MAX_WIDTH
][4];
3614 for (col
= 0; col
< width
; col
++) {
3615 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3616 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3617 rgba
[col
][RCOMP
] = 0.0;
3618 rgba
[col
][GCOMP
] = 0.0;
3619 rgba
[col
][BCOMP
] = 0.0;
3621 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3622 rgba
[col
][GCOMP
] = 0.0;
3623 rgba
[col
][BCOMP
] = 0.0;
3624 rgba
[col
][ACOMP
] = 1.0;
3626 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3627 rgba
[col
][GCOMP
] = 0.0;
3628 rgba
[col
][BCOMP
] = 0.0;
3630 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3631 rgba
[col
][GCOMP
] = 0.0;
3632 rgba
[col
][BCOMP
] = 0.0;
3633 rgba
[col
][ACOMP
] = 1.0;
3636 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3638 &ctx
->Pack
, 0x0 /*image xfer ops*/);
3644 if (ctx
->Pack
.BufferObj
->Name
) {
3645 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3646 ctx
->Pack
.BufferObj
);
3653 * This is the software fallback for Driver.GetCompressedTexImage().
3654 * All error checking will have been done before this routine is called.
3657 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3659 struct gl_texture_object
*texObj
,
3660 struct gl_texture_image
*texImage
)
3664 if (ctx
->Pack
.BufferObj
->Name
) {
3665 /* pack texture image into a PBO */
3667 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3668 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3669 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3670 "glGetCompressedTexImage(invalid PBO access)");
3673 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3675 ctx
->Pack
.BufferObj
);
3677 /* buffer is already mapped - that's an error */
3678 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3679 "glGetCompressedTexImage(PBO is mapped)");
3682 img
= ADD_POINTERS(buf
, img
);
3689 /* don't use texImage->CompressedSize since that may be padded out */
3690 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3692 texImage
->TexFormat
->MesaFormat
);
3694 /* just memcpy, no pixelstore or pixel transfer */
3695 _mesa_memcpy(img
, texImage
->Data
, size
);
3697 if (ctx
->Pack
.BufferObj
->Name
) {
3698 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3699 ctx
->Pack
.BufferObj
);