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 srcRowStride
== srcWidth
* srcComponents
&&
814 /* 1 and 2D images only */
815 GLubyte
*dstImage
= (GLubyte
*) dstAddr
816 + dstYoffset
* dstRowStride
817 + dstXoffset
* dstComponents
;
818 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
819 srcWidth
* srcHeight
);
823 for (img
= 0; img
< srcDepth
; img
++) {
824 const GLubyte
*srcRow
= srcImage
;
825 GLubyte
*dstRow
= (GLubyte
*) dstAddr
826 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
827 + dstYoffset
* dstRowStride
828 + dstXoffset
* dstComponents
;
829 for (row
= 0; row
< srcHeight
; row
++) {
830 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
831 dstRow
+= dstRowStride
;
832 srcRow
+= srcRowStride
;
834 srcImage
+= srcImageStride
;
841 * Teximage storage routine for when a simple memcpy will do.
842 * No pixel transfer operations or special texel encodings allowed.
843 * 1D, 2D and 3D images supported.
846 memcpy_texture(GLcontext
*ctx
,
848 const struct gl_texture_format
*dstFormat
,
850 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
852 const GLuint
*dstImageOffsets
,
853 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
854 GLenum srcFormat
, GLenum srcType
,
855 const GLvoid
*srcAddr
,
856 const struct gl_pixelstore_attrib
*srcPacking
)
858 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
860 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
861 srcWidth
, srcHeight
, srcFormat
, srcType
);
862 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
863 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
864 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
867 /* XXX update/re-enable for dstImageOffsets array */
868 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
869 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
870 GLubyte
*dstImage
= (GLubyte
*) dstAddr
871 + dstZoffset
* dstImageStride
872 + dstYoffset
* dstRowStride
873 + dstXoffset
* dstFormat
->TexelBytes
;
875 if (dstRowStride
== srcRowStride
&&
876 dstRowStride
== bytesPerRow
&&
877 ((dstImageStride
== srcImageStride
&&
878 dstImageStride
== bytesPerImage
) ||
881 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
886 for (img
= 0; img
< srcDepth
; img
++) {
887 const GLubyte
*srcRow
= srcImage
;
888 GLubyte
*dstRow
= dstImage
;
889 for (row
= 0; row
< srcHeight
; row
++) {
890 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
891 dstRow
+= dstRowStride
;
892 srcRow
+= srcRowStride
;
894 srcImage
+= srcImageStride
;
895 dstImage
+= dstImageStride
;
901 for (img
= 0; img
< srcDepth
; img
++) {
902 const GLubyte
*srcRow
= srcImage
;
903 GLubyte
*dstRow
= (GLubyte
*) dstAddr
904 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
905 + dstYoffset
* dstRowStride
906 + dstXoffset
* dstFormat
->TexelBytes
;
907 for (row
= 0; row
< srcHeight
; row
++) {
908 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
909 dstRow
+= dstRowStride
;
910 srcRow
+= srcRowStride
;
912 srcImage
+= srcImageStride
;
919 * Store an image in any of the formats:
920 * _mesa_texformat_rgba
921 * _mesa_texformat_rgb
922 * _mesa_texformat_alpha
923 * _mesa_texformat_luminance
924 * _mesa_texformat_luminance_alpha
925 * _mesa_texformat_intensity
929 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
931 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
933 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
934 dstFormat
== &_mesa_texformat_rgb
||
935 dstFormat
== &_mesa_texformat_alpha
||
936 dstFormat
== &_mesa_texformat_luminance
||
937 dstFormat
== &_mesa_texformat_luminance_alpha
||
938 dstFormat
== &_mesa_texformat_intensity
);
939 ASSERT(baseInternalFormat
== GL_RGBA
||
940 baseInternalFormat
== GL_RGB
||
941 baseInternalFormat
== GL_ALPHA
||
942 baseInternalFormat
== GL_LUMINANCE
||
943 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
944 baseInternalFormat
== GL_INTENSITY
);
945 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
947 if (!ctx
->_ImageTransferState
&&
948 !srcPacking
->SwapBytes
&&
949 baseInternalFormat
== srcFormat
&&
950 srcType
== CHAN_TYPE
) {
951 /* simple memcpy path */
952 memcpy_texture(ctx
, dims
,
953 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
956 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
957 srcAddr
, srcPacking
);
959 else if (!ctx
->_ImageTransferState
&&
960 !srcPacking
->SwapBytes
&&
961 dstFormat
== &_mesa_texformat_rgb
&&
962 srcFormat
== GL_RGBA
&&
963 srcType
== CHAN_TYPE
) {
964 /* extract RGB from RGBA */
966 for (img
= 0; img
< srcDepth
; img
++) {
967 GLchan
*dstImage
= (GLchan
*)
969 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
970 + dstYoffset
* dstRowStride
971 + dstXoffset
* dstFormat
->TexelBytes
);
973 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
974 srcWidth
, srcFormat
, srcType
);
975 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
976 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
977 GLchan
*dstRow
= dstImage
;
978 for (row
= 0; row
< srcHeight
; row
++) {
979 for (col
= 0; col
< srcWidth
; col
++) {
980 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
981 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
982 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
984 dstRow
+= dstRowStride
/ sizeof(GLchan
);
985 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
989 else if (!ctx
->_ImageTransferState
&&
990 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
991 (srcType
== GL_UNSIGNED_BYTE
||
992 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
993 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
994 can_swizzle(baseInternalFormat
) &&
995 can_swizzle(srcFormat
)) {
997 const GLubyte
*dstmap
;
1000 /* dstmap - how to swizzle from RGBA to dst format:
1002 if (dstFormat
== &_mesa_texformat_rgba
) {
1003 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1006 else if (dstFormat
== &_mesa_texformat_rgb
) {
1007 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1010 else if (dstFormat
== &_mesa_texformat_alpha
) {
1011 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1014 else if (dstFormat
== &_mesa_texformat_luminance
) {
1015 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1018 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1019 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1022 else if (dstFormat
== &_mesa_texformat_intensity
) {
1023 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1027 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1031 _mesa_swizzle_ubyte_image(ctx
, dims
,
1036 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1037 dstRowStride
, dstImageOffsets
,
1038 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1043 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1045 dstFormat
->BaseFormat
,
1046 srcWidth
, srcHeight
, srcDepth
,
1047 srcFormat
, srcType
, srcAddr
,
1049 const GLchan
*src
= tempImage
;
1054 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1055 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1056 for (img
= 0; img
< srcDepth
; img
++) {
1057 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1058 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1059 + dstYoffset
* dstRowStride
1060 + dstXoffset
* dstFormat
->TexelBytes
;
1061 for (row
= 0; row
< srcHeight
; row
++) {
1062 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1063 dstRow
+= dstRowStride
;
1064 src
+= srcWidth
* components
;
1068 _mesa_free((void *) tempImage
);
1075 * Store a 32-bit integer depth component texture image.
1078 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1080 const GLuint depthScale
= 0xffffffff;
1082 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1083 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1085 if (!ctx
->_ImageTransferState
&&
1086 !srcPacking
->SwapBytes
&&
1087 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1088 srcFormat
== GL_DEPTH_COMPONENT
&&
1089 srcType
== GL_UNSIGNED_INT
) {
1090 /* simple memcpy path */
1091 memcpy_texture(ctx
, dims
,
1092 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1095 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1096 srcAddr
, srcPacking
);
1101 for (img
= 0; img
< srcDepth
; img
++) {
1102 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1103 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1104 + dstYoffset
* dstRowStride
1105 + dstXoffset
* dstFormat
->TexelBytes
;
1106 for (row
= 0; row
< srcHeight
; row
++) {
1107 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1108 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1109 _mesa_unpack_depth_span(ctx
, srcWidth
,
1110 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1111 depthScale
, srcType
, src
, srcPacking
);
1112 dstRow
+= dstRowStride
;
1122 * Store a 16-bit integer depth component texture image.
1125 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1127 const GLuint depthScale
= 0xffff;
1129 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1130 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1132 if (!ctx
->_ImageTransferState
&&
1133 !srcPacking
->SwapBytes
&&
1134 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1135 srcFormat
== GL_DEPTH_COMPONENT
&&
1136 srcType
== GL_UNSIGNED_SHORT
) {
1137 /* simple memcpy path */
1138 memcpy_texture(ctx
, dims
,
1139 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1142 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1143 srcAddr
, srcPacking
);
1148 for (img
= 0; img
< srcDepth
; img
++) {
1149 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1150 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1151 + dstYoffset
* dstRowStride
1152 + dstXoffset
* dstFormat
->TexelBytes
;
1153 for (row
= 0; row
< srcHeight
; row
++) {
1154 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1155 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1156 GLushort
*dst16
= (GLushort
*) dstRow
;
1157 _mesa_unpack_depth_span(ctx
, srcWidth
,
1158 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1159 srcType
, src
, srcPacking
);
1160 dstRow
+= dstRowStride
;
1169 * Store an rgb565 or rgb565_rev texture image.
1172 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1174 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1175 dstFormat
== &_mesa_texformat_rgb565_rev
);
1176 ASSERT(dstFormat
->TexelBytes
== 2);
1178 if (!ctx
->_ImageTransferState
&&
1179 !srcPacking
->SwapBytes
&&
1180 dstFormat
== &_mesa_texformat_rgb565
&&
1181 baseInternalFormat
== GL_RGB
&&
1182 srcFormat
== GL_RGB
&&
1183 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1184 /* simple memcpy path */
1185 memcpy_texture(ctx
, dims
,
1186 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1189 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1190 srcAddr
, srcPacking
);
1192 else if (!ctx
->_ImageTransferState
&&
1193 !srcPacking
->SwapBytes
&&
1194 baseInternalFormat
== GL_RGB
&&
1195 srcFormat
== GL_RGB
&&
1196 srcType
== GL_UNSIGNED_BYTE
&&
1198 /* do optimized tex store */
1199 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1200 srcFormat
, srcType
);
1201 const GLubyte
*src
= (const GLubyte
*)
1202 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1203 srcFormat
, srcType
, 0, 0, 0);
1204 GLubyte
*dst
= (GLubyte
*) dstAddr
1205 + dstYoffset
* dstRowStride
1206 + dstXoffset
* dstFormat
->TexelBytes
;
1208 for (row
= 0; row
< srcHeight
; row
++) {
1209 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1210 GLushort
*dstUS
= (GLushort
*) dst
;
1211 /* check for byteswapped format */
1212 if (dstFormat
== &_mesa_texformat_rgb565
) {
1213 for (col
= 0; col
< srcWidth
; col
++) {
1214 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1219 for (col
= 0; col
< srcWidth
; col
++) {
1220 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1224 dst
+= dstRowStride
;
1225 src
+= srcRowStride
;
1230 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1232 dstFormat
->BaseFormat
,
1233 srcWidth
, srcHeight
, srcDepth
,
1234 srcFormat
, srcType
, srcAddr
,
1236 const GLchan
*src
= tempImage
;
1237 GLint img
, row
, col
;
1240 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1241 for (img
= 0; img
< srcDepth
; img
++) {
1242 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1243 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1244 + dstYoffset
* dstRowStride
1245 + dstXoffset
* dstFormat
->TexelBytes
;
1246 for (row
= 0; row
< srcHeight
; row
++) {
1247 GLushort
*dstUS
= (GLushort
*) dstRow
;
1248 /* check for byteswapped format */
1249 if (dstFormat
== &_mesa_texformat_rgb565
) {
1250 for (col
= 0; col
< srcWidth
; col
++) {
1251 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1252 CHAN_TO_UBYTE(src
[GCOMP
]),
1253 CHAN_TO_UBYTE(src
[BCOMP
]) );
1258 for (col
= 0; col
< srcWidth
; col
++) {
1259 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1260 CHAN_TO_UBYTE(src
[GCOMP
]),
1261 CHAN_TO_UBYTE(src
[BCOMP
]) );
1265 dstRow
+= dstRowStride
;
1268 _mesa_free((void *) tempImage
);
1275 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1278 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1280 const GLboolean littleEndian
= _mesa_little_endian();
1282 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1283 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1284 ASSERT(dstFormat
->TexelBytes
== 4);
1286 if (!ctx
->_ImageTransferState
&&
1287 !srcPacking
->SwapBytes
&&
1288 dstFormat
== &_mesa_texformat_rgba8888
&&
1289 baseInternalFormat
== GL_RGBA
&&
1290 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1291 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1292 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1293 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1294 /* simple memcpy path */
1295 memcpy_texture(ctx
, dims
,
1296 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1299 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1300 srcAddr
, srcPacking
);
1302 else if (!ctx
->_ImageTransferState
&&
1303 !srcPacking
->SwapBytes
&&
1304 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1305 baseInternalFormat
== GL_RGBA
&&
1306 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1307 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1308 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1309 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1310 /* simple memcpy path */
1311 memcpy_texture(ctx
, dims
,
1312 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1315 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1316 srcAddr
, srcPacking
);
1318 else if (!ctx
->_ImageTransferState
&&
1319 (srcType
== GL_UNSIGNED_BYTE
||
1320 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1321 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1322 can_swizzle(baseInternalFormat
) &&
1323 can_swizzle(srcFormat
)) {
1327 /* dstmap - how to swizzle from RGBA to dst format:
1329 if ((littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888
) ||
1330 (!littleEndian
&& dstFormat
== &_mesa_texformat_rgba8888_rev
)) {
1343 _mesa_swizzle_ubyte_image(ctx
, dims
,
1348 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1349 dstRowStride
, dstImageOffsets
,
1350 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1355 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1357 dstFormat
->BaseFormat
,
1358 srcWidth
, srcHeight
, srcDepth
,
1359 srcFormat
, srcType
, srcAddr
,
1361 const GLchan
*src
= tempImage
;
1362 GLint img
, row
, col
;
1365 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1366 for (img
= 0; img
< srcDepth
; img
++) {
1367 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1368 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1369 + dstYoffset
* dstRowStride
1370 + dstXoffset
* dstFormat
->TexelBytes
;
1371 for (row
= 0; row
< srcHeight
; row
++) {
1372 GLuint
*dstUI
= (GLuint
*) dstRow
;
1373 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1374 for (col
= 0; col
< srcWidth
; col
++) {
1375 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1376 CHAN_TO_UBYTE(src
[GCOMP
]),
1377 CHAN_TO_UBYTE(src
[BCOMP
]),
1378 CHAN_TO_UBYTE(src
[ACOMP
]) );
1383 for (col
= 0; col
< srcWidth
; col
++) {
1384 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1385 CHAN_TO_UBYTE(src
[GCOMP
]),
1386 CHAN_TO_UBYTE(src
[BCOMP
]),
1387 CHAN_TO_UBYTE(src
[ACOMP
]) );
1391 dstRow
+= dstRowStride
;
1394 _mesa_free((void *) tempImage
);
1401 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1403 const GLboolean littleEndian
= _mesa_little_endian();
1405 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1406 dstFormat
== &_mesa_texformat_argb8888_rev
);
1407 ASSERT(dstFormat
->TexelBytes
== 4);
1409 if (!ctx
->_ImageTransferState
&&
1410 !srcPacking
->SwapBytes
&&
1411 dstFormat
== &_mesa_texformat_argb8888
&&
1412 baseInternalFormat
== GL_RGBA
&&
1413 srcFormat
== GL_BGRA
&&
1414 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1415 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1416 /* simple memcpy path (little endian) */
1417 memcpy_texture(ctx
, dims
,
1418 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1421 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1422 srcAddr
, srcPacking
);
1424 else if (!ctx
->_ImageTransferState
&&
1425 !srcPacking
->SwapBytes
&&
1426 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1427 baseInternalFormat
== GL_RGBA
&&
1428 srcFormat
== GL_BGRA
&&
1429 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1430 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1431 /* simple memcpy path (big endian) */
1432 memcpy_texture(ctx
, dims
,
1433 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1436 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1437 srcAddr
, srcPacking
);
1439 else if (!ctx
->_ImageTransferState
&&
1440 !srcPacking
->SwapBytes
&&
1441 dstFormat
== &_mesa_texformat_argb8888
&&
1442 srcFormat
== GL_RGB
&&
1443 (baseInternalFormat
== GL_RGBA
||
1444 baseInternalFormat
== GL_RGB
) &&
1445 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 for (col
= 0; col
< srcWidth
; col
++) {
1459 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1460 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1461 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1462 dstRow
[col
* 4 + 3] = 0xff;
1464 dstRow
+= dstRowStride
;
1465 srcRow
+= srcRowStride
;
1469 else if (!ctx
->_ImageTransferState
&&
1470 !srcPacking
->SwapBytes
&&
1471 dstFormat
== &_mesa_texformat_argb8888
&&
1472 srcFormat
== GL_RGBA
&&
1473 baseInternalFormat
== GL_RGBA
&&
1474 (srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
1475 GLint img
, row
, col
;
1476 /* For some reason, streaming copies to write-combined regions
1477 * are extremely sensitive to the characteristics of how the
1478 * source data is retrieved. By reordering the source reads to
1479 * be in-order, the speed of this operation increases by half.
1480 * Strangely the same isn't required for the RGB path, above.
1482 for (img
= 0; img
< srcDepth
; img
++) {
1483 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1484 srcWidth
, srcFormat
, srcType
);
1485 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1486 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1487 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1488 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1489 + dstYoffset
* dstRowStride
1490 + dstXoffset
* dstFormat
->TexelBytes
;
1492 for (row
= 0; row
< srcHeight
; row
++) {
1493 for (col
= 0; col
< srcWidth
; col
++) {
1494 *(GLuint
*)(dstRow
+ col
* 4) = (srcRow
[col
* 4 + RCOMP
] << 16 |
1495 srcRow
[col
* 4 + GCOMP
] << 8 |
1496 srcRow
[col
* 4 + BCOMP
] << 0 |
1497 srcRow
[col
* 4 + ACOMP
] << 24);
1499 dstRow
+= dstRowStride
;
1500 srcRow
+= srcRowStride
;
1504 else if (!ctx
->_ImageTransferState
&&
1505 !srcPacking
->SwapBytes
&&
1506 dstFormat
== &_mesa_texformat_argb8888
&&
1507 srcFormat
== GL_RGBA
&&
1508 baseInternalFormat
== GL_RGBA
&&
1509 srcType
== GL_UNSIGNED_BYTE
) {
1511 GLint img
, row
, col
;
1512 for (img
= 0; img
< srcDepth
; img
++) {
1513 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1514 srcWidth
, srcFormat
, srcType
);
1515 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1516 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1517 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1518 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1519 + dstYoffset
* dstRowStride
1520 + dstXoffset
* dstFormat
->TexelBytes
;
1521 for (row
= 0; row
< srcHeight
; row
++) {
1522 for (col
= 0; col
< srcWidth
; col
++) {
1523 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1524 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1525 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1526 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1528 dstRow
+= dstRowStride
;
1529 srcRow
+= srcRowStride
;
1533 else if (!ctx
->_ImageTransferState
&&
1534 (srcType
== GL_UNSIGNED_BYTE
||
1535 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1536 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1537 can_swizzle(baseInternalFormat
) &&
1538 can_swizzle(srcFormat
)) {
1542 /* dstmap - how to swizzle from RGBA to dst format:
1544 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1545 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1546 dstmap
[3] = 3; /* alpha */
1547 dstmap
[2] = 0; /* red */
1548 dstmap
[1] = 1; /* green */
1549 dstmap
[0] = 2; /* blue */
1552 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1553 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1560 _mesa_swizzle_ubyte_image(ctx
, dims
,
1566 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1569 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1574 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1576 dstFormat
->BaseFormat
,
1577 srcWidth
, srcHeight
, srcDepth
,
1578 srcFormat
, srcType
, srcAddr
,
1580 const GLchan
*src
= tempImage
;
1581 GLint img
, row
, col
;
1584 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1585 for (img
= 0; img
< srcDepth
; img
++) {
1586 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1587 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1588 + dstYoffset
* dstRowStride
1589 + dstXoffset
* dstFormat
->TexelBytes
;
1590 for (row
= 0; row
< srcHeight
; row
++) {
1591 GLuint
*dstUI
= (GLuint
*) dstRow
;
1592 if (dstFormat
== &_mesa_texformat_argb8888
) {
1593 for (col
= 0; col
< srcWidth
; col
++) {
1594 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1595 CHAN_TO_UBYTE(src
[RCOMP
]),
1596 CHAN_TO_UBYTE(src
[GCOMP
]),
1597 CHAN_TO_UBYTE(src
[BCOMP
]) );
1602 for (col
= 0; col
< srcWidth
; col
++) {
1603 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1604 CHAN_TO_UBYTE(src
[RCOMP
]),
1605 CHAN_TO_UBYTE(src
[GCOMP
]),
1606 CHAN_TO_UBYTE(src
[BCOMP
]) );
1610 dstRow
+= dstRowStride
;
1613 _mesa_free((void *) tempImage
);
1620 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1622 const GLboolean littleEndian
= _mesa_little_endian();
1624 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1625 ASSERT(dstFormat
->TexelBytes
== 3);
1627 if (!ctx
->_ImageTransferState
&&
1628 !srcPacking
->SwapBytes
&&
1629 baseInternalFormat
== GL_RGB
&&
1630 srcFormat
== GL_BGR
&&
1631 srcType
== GL_UNSIGNED_BYTE
&&
1633 /* simple memcpy path */
1634 memcpy_texture(ctx
, dims
,
1635 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1638 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1639 srcAddr
, srcPacking
);
1641 else if (!ctx
->_ImageTransferState
&&
1642 !srcPacking
->SwapBytes
&&
1643 srcFormat
== GL_RGBA
&&
1644 srcType
== GL_UNSIGNED_BYTE
) {
1645 /* extract RGB from RGBA */
1646 GLint img
, row
, col
;
1647 for (img
= 0; img
< srcDepth
; img
++) {
1648 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1649 srcWidth
, srcFormat
, srcType
);
1650 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1651 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1652 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1653 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1654 + dstYoffset
* dstRowStride
1655 + dstXoffset
* dstFormat
->TexelBytes
;
1656 for (row
= 0; row
< srcHeight
; row
++) {
1657 for (col
= 0; col
< srcWidth
; col
++) {
1658 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1659 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1660 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1662 dstRow
+= dstRowStride
;
1663 srcRow
+= srcRowStride
;
1667 else if (!ctx
->_ImageTransferState
&&
1668 srcType
== GL_UNSIGNED_BYTE
&&
1669 can_swizzle(baseInternalFormat
) &&
1670 can_swizzle(srcFormat
)) {
1674 /* dstmap - how to swizzle from RGBA to dst format:
1679 dstmap
[3] = ONE
; /* ? */
1681 _mesa_swizzle_ubyte_image(ctx
, dims
,
1686 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1687 dstRowStride
, dstImageOffsets
,
1688 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1693 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1695 dstFormat
->BaseFormat
,
1696 srcWidth
, srcHeight
, srcDepth
,
1697 srcFormat
, srcType
, srcAddr
,
1699 const GLchan
*src
= (const GLchan
*) tempImage
;
1700 GLint img
, row
, col
;
1703 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1704 for (img
= 0; img
< srcDepth
; img
++) {
1705 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1706 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1707 + dstYoffset
* dstRowStride
1708 + dstXoffset
* dstFormat
->TexelBytes
;
1709 for (row
= 0; row
< srcHeight
; row
++) {
1712 for (col
= 0; col
< srcWidth
; col
++) {
1713 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1714 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1715 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1720 for (col
= 0; col
< srcWidth
; col
++) {
1721 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1722 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1723 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1728 for (col
= 0; col
< srcWidth
; col
++) {
1729 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1730 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1731 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1735 dstRow
+= dstRowStride
;
1738 _mesa_free((void *) tempImage
);
1745 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1747 const GLboolean littleEndian
= _mesa_little_endian();
1749 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1750 ASSERT(dstFormat
->TexelBytes
== 3);
1752 if (!ctx
->_ImageTransferState
&&
1753 !srcPacking
->SwapBytes
&&
1754 baseInternalFormat
== GL_RGB
&&
1755 srcFormat
== GL_RGB
&&
1756 srcType
== GL_UNSIGNED_BYTE
&&
1758 /* simple memcpy path */
1759 memcpy_texture(ctx
, dims
,
1760 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1763 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1764 srcAddr
, srcPacking
);
1766 else if (!ctx
->_ImageTransferState
&&
1767 !srcPacking
->SwapBytes
&&
1768 srcFormat
== GL_RGBA
&&
1769 srcType
== GL_UNSIGNED_BYTE
) {
1770 /* extract BGR from RGBA */
1772 for (img
= 0; img
< srcDepth
; img
++) {
1773 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1774 srcWidth
, srcFormat
, srcType
);
1775 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1776 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1777 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1778 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1779 + dstYoffset
* dstRowStride
1780 + dstXoffset
* dstFormat
->TexelBytes
;
1781 for (row
= 0; row
< srcHeight
; row
++) {
1782 for (col
= 0; col
< srcWidth
; col
++) {
1783 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1784 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1785 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1787 dstRow
+= dstRowStride
;
1788 srcRow
+= srcRowStride
;
1792 else if (!ctx
->_ImageTransferState
&&
1793 srcType
== GL_UNSIGNED_BYTE
&&
1794 can_swizzle(baseInternalFormat
) &&
1795 can_swizzle(srcFormat
)) {
1799 /* dstmap - how to swizzle from RGBA to dst format:
1804 dstmap
[3] = ONE
; /* ? */
1806 _mesa_swizzle_ubyte_image(ctx
, dims
,
1811 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1812 dstRowStride
, dstImageOffsets
,
1813 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1818 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1820 dstFormat
->BaseFormat
,
1821 srcWidth
, srcHeight
, srcDepth
,
1822 srcFormat
, srcType
, srcAddr
,
1824 const GLchan
*src
= (const GLchan
*) tempImage
;
1825 GLint img
, row
, col
;
1828 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1829 for (img
= 0; img
< srcDepth
; img
++) {
1830 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1831 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1832 + dstYoffset
* dstRowStride
1833 + dstXoffset
* dstFormat
->TexelBytes
;
1834 for (row
= 0; row
< srcHeight
; row
++) {
1835 for (col
= 0; col
< srcWidth
; col
++) {
1836 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1837 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1838 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1841 dstRow
+= dstRowStride
;
1844 _mesa_free((void *) tempImage
);
1851 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1853 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1854 dstFormat
== &_mesa_texformat_argb4444_rev
);
1855 ASSERT(dstFormat
->TexelBytes
== 2);
1857 if (!ctx
->_ImageTransferState
&&
1858 !srcPacking
->SwapBytes
&&
1859 dstFormat
== &_mesa_texformat_argb4444
&&
1860 baseInternalFormat
== GL_RGBA
&&
1861 srcFormat
== GL_BGRA
&&
1862 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1863 /* simple memcpy path */
1864 memcpy_texture(ctx
, dims
,
1865 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1868 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1869 srcAddr
, srcPacking
);
1873 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1875 dstFormat
->BaseFormat
,
1876 srcWidth
, srcHeight
, srcDepth
,
1877 srcFormat
, srcType
, srcAddr
,
1879 const GLchan
*src
= tempImage
;
1880 GLint img
, row
, col
;
1883 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1884 for (img
= 0; img
< srcDepth
; img
++) {
1885 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1886 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1887 + dstYoffset
* dstRowStride
1888 + dstXoffset
* dstFormat
->TexelBytes
;
1889 for (row
= 0; row
< srcHeight
; row
++) {
1890 GLushort
*dstUS
= (GLushort
*) dstRow
;
1891 if (dstFormat
== &_mesa_texformat_argb4444
) {
1892 for (col
= 0; col
< srcWidth
; col
++) {
1893 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1894 CHAN_TO_UBYTE(src
[RCOMP
]),
1895 CHAN_TO_UBYTE(src
[GCOMP
]),
1896 CHAN_TO_UBYTE(src
[BCOMP
]) );
1901 for (col
= 0; col
< srcWidth
; col
++) {
1902 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1903 CHAN_TO_UBYTE(src
[RCOMP
]),
1904 CHAN_TO_UBYTE(src
[GCOMP
]),
1905 CHAN_TO_UBYTE(src
[BCOMP
]) );
1909 dstRow
+= dstRowStride
;
1912 _mesa_free((void *) tempImage
);
1920 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1922 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1923 dstFormat
== &_mesa_texformat_argb1555_rev
);
1924 ASSERT(dstFormat
->TexelBytes
== 2);
1926 if (!ctx
->_ImageTransferState
&&
1927 !srcPacking
->SwapBytes
&&
1928 dstFormat
== &_mesa_texformat_argb1555
&&
1929 baseInternalFormat
== GL_RGBA
&&
1930 srcFormat
== GL_BGRA
&&
1931 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1932 /* simple memcpy path */
1933 memcpy_texture(ctx
, dims
,
1934 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1937 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1938 srcAddr
, srcPacking
);
1942 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1944 dstFormat
->BaseFormat
,
1945 srcWidth
, srcHeight
, srcDepth
,
1946 srcFormat
, srcType
, srcAddr
,
1948 const GLchan
*src
=tempImage
;
1949 GLint img
, row
, col
;
1952 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1953 for (img
= 0; img
< srcDepth
; img
++) {
1954 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1955 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1956 + dstYoffset
* dstRowStride
1957 + dstXoffset
* dstFormat
->TexelBytes
;
1958 for (row
= 0; row
< srcHeight
; row
++) {
1959 GLushort
*dstUS
= (GLushort
*) dstRow
;
1960 if (dstFormat
== &_mesa_texformat_argb1555
) {
1961 for (col
= 0; col
< srcWidth
; col
++) {
1962 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1963 CHAN_TO_UBYTE(src
[RCOMP
]),
1964 CHAN_TO_UBYTE(src
[GCOMP
]),
1965 CHAN_TO_UBYTE(src
[BCOMP
]) );
1970 for (col
= 0; col
< srcWidth
; col
++) {
1971 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1972 CHAN_TO_UBYTE(src
[RCOMP
]),
1973 CHAN_TO_UBYTE(src
[GCOMP
]),
1974 CHAN_TO_UBYTE(src
[BCOMP
]) );
1978 dstRow
+= dstRowStride
;
1981 _mesa_free((void *) tempImage
);
1988 _mesa_texstore_al88(TEXSTORE_PARAMS
)
1990 const GLboolean littleEndian
= _mesa_little_endian();
1992 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1993 dstFormat
== &_mesa_texformat_al88_rev
);
1994 ASSERT(dstFormat
->TexelBytes
== 2);
1996 if (!ctx
->_ImageTransferState
&&
1997 !srcPacking
->SwapBytes
&&
1998 dstFormat
== &_mesa_texformat_al88
&&
1999 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2000 srcFormat
== GL_LUMINANCE_ALPHA
&&
2001 srcType
== GL_UNSIGNED_BYTE
&&
2003 /* simple memcpy path */
2004 memcpy_texture(ctx
, dims
,
2005 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2008 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2009 srcAddr
, srcPacking
);
2011 else if (!ctx
->_ImageTransferState
&&
2013 srcType
== GL_UNSIGNED_BYTE
&&
2014 can_swizzle(baseInternalFormat
) &&
2015 can_swizzle(srcFormat
)) {
2019 /* dstmap - how to swizzle from RGBA to dst format:
2021 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2022 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2030 dstmap
[2] = ZERO
; /* ? */
2031 dstmap
[3] = ONE
; /* ? */
2033 _mesa_swizzle_ubyte_image(ctx
, dims
,
2038 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2039 dstRowStride
, dstImageOffsets
,
2040 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2045 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2047 dstFormat
->BaseFormat
,
2048 srcWidth
, srcHeight
, srcDepth
,
2049 srcFormat
, srcType
, srcAddr
,
2051 const GLchan
*src
= tempImage
;
2052 GLint img
, row
, col
;
2055 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2056 for (img
= 0; img
< srcDepth
; img
++) {
2057 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2058 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2059 + dstYoffset
* dstRowStride
2060 + dstXoffset
* dstFormat
->TexelBytes
;
2061 for (row
= 0; row
< srcHeight
; row
++) {
2062 GLushort
*dstUS
= (GLushort
*) dstRow
;
2063 if (dstFormat
== &_mesa_texformat_al88
) {
2064 for (col
= 0; col
< srcWidth
; col
++) {
2065 /* src[0] is luminance, src[1] is alpha */
2066 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2067 CHAN_TO_UBYTE(src
[0]) );
2072 for (col
= 0; col
< srcWidth
; col
++) {
2073 /* src[0] is luminance, src[1] is alpha */
2074 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2075 CHAN_TO_UBYTE(src
[0]) );
2079 dstRow
+= dstRowStride
;
2082 _mesa_free((void *) tempImage
);
2089 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2091 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2092 ASSERT(dstFormat
->TexelBytes
== 1);
2094 if (!ctx
->_ImageTransferState
&&
2095 !srcPacking
->SwapBytes
&&
2096 baseInternalFormat
== GL_RGB
&&
2097 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2098 /* simple memcpy path */
2099 memcpy_texture(ctx
, dims
,
2100 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2103 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2104 srcAddr
, srcPacking
);
2108 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2110 dstFormat
->BaseFormat
,
2111 srcWidth
, srcHeight
, srcDepth
,
2112 srcFormat
, srcType
, srcAddr
,
2114 const GLchan
*src
= tempImage
;
2115 GLint img
, row
, col
;
2118 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2119 for (img
= 0; img
< srcDepth
; img
++) {
2120 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2121 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2122 + dstYoffset
* dstRowStride
2123 + dstXoffset
* dstFormat
->TexelBytes
;
2124 for (row
= 0; row
< srcHeight
; row
++) {
2125 for (col
= 0; col
< srcWidth
; col
++) {
2126 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2127 CHAN_TO_UBYTE(src
[GCOMP
]),
2128 CHAN_TO_UBYTE(src
[BCOMP
]) );
2131 dstRow
+= dstRowStride
;
2134 _mesa_free((void *) tempImage
);
2141 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2144 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2146 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2147 dstFormat
== &_mesa_texformat_l8
||
2148 dstFormat
== &_mesa_texformat_i8
);
2149 ASSERT(dstFormat
->TexelBytes
== 1);
2151 if (!ctx
->_ImageTransferState
&&
2152 !srcPacking
->SwapBytes
&&
2153 baseInternalFormat
== srcFormat
&&
2154 srcType
== GL_UNSIGNED_BYTE
) {
2155 /* simple memcpy path */
2156 memcpy_texture(ctx
, dims
,
2157 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2160 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2161 srcAddr
, srcPacking
);
2163 else if (!ctx
->_ImageTransferState
&&
2164 srcType
== GL_UNSIGNED_BYTE
&&
2165 can_swizzle(baseInternalFormat
) &&
2166 can_swizzle(srcFormat
)) {
2170 /* dstmap - how to swizzle from RGBA to dst format:
2172 if (dstFormat
== &_mesa_texformat_a8
) {
2178 dstmap
[1] = ZERO
; /* ? */
2179 dstmap
[2] = ZERO
; /* ? */
2180 dstmap
[3] = ONE
; /* ? */
2182 _mesa_swizzle_ubyte_image(ctx
, dims
,
2187 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2188 dstRowStride
, dstImageOffsets
,
2189 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2194 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2196 dstFormat
->BaseFormat
,
2197 srcWidth
, srcHeight
, srcDepth
,
2198 srcFormat
, srcType
, srcAddr
,
2200 const GLchan
*src
= tempImage
;
2201 GLint img
, row
, col
;
2204 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2205 for (img
= 0; img
< srcDepth
; img
++) {
2206 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2207 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2208 + dstYoffset
* dstRowStride
2209 + dstXoffset
* dstFormat
->TexelBytes
;
2210 for (row
= 0; row
< srcHeight
; row
++) {
2211 for (col
= 0; col
< srcWidth
; col
++) {
2212 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2214 dstRow
+= dstRowStride
;
2218 _mesa_free((void *) tempImage
);
2226 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2228 (void) dims
; (void) baseInternalFormat
;
2229 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2230 ASSERT(dstFormat
->TexelBytes
== 1);
2231 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2233 if (!ctx
->_ImageTransferState
&&
2234 !srcPacking
->SwapBytes
&&
2235 srcFormat
== GL_COLOR_INDEX
&&
2236 srcType
== GL_UNSIGNED_BYTE
) {
2237 /* simple memcpy path */
2238 memcpy_texture(ctx
, dims
,
2239 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2242 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2243 srcAddr
, srcPacking
);
2248 for (img
= 0; img
< srcDepth
; img
++) {
2249 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2250 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2251 + dstYoffset
* dstRowStride
2252 + dstXoffset
* dstFormat
->TexelBytes
;
2253 for (row
= 0; row
< srcHeight
; row
++) {
2254 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2255 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2256 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2257 srcType
, src
, srcPacking
,
2258 ctx
->_ImageTransferState
);
2259 dstRow
+= dstRowStride
;
2268 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2271 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2273 const GLboolean littleEndian
= _mesa_little_endian();
2274 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2276 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2277 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2278 ASSERT(dstFormat
->TexelBytes
== 2);
2279 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2280 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2281 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2282 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2283 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2285 /* always just memcpy since no pixel transfer ops apply */
2286 memcpy_texture(ctx
, dims
,
2287 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2290 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2291 srcAddr
, srcPacking
);
2293 /* Check if we need byte swapping */
2294 /* XXX the logic here _might_ be wrong */
2295 if (srcPacking
->SwapBytes
^
2296 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2297 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2300 for (img
= 0; img
< srcDepth
; img
++) {
2301 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2302 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2303 + dstYoffset
* dstRowStride
2304 + dstXoffset
* dstFormat
->TexelBytes
;
2305 for (row
= 0; row
< srcHeight
; row
++) {
2306 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2307 dstRow
+= dstRowStride
;
2317 * Store a combined depth/stencil texture image.
2320 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2322 const GLuint depthScale
= 0xffffff;
2324 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2325 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2326 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2328 if (!ctx
->_ImageTransferState
&&
2329 !srcPacking
->SwapBytes
) {
2331 memcpy_texture(ctx
, dims
,
2332 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2335 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2336 srcAddr
, srcPacking
);
2340 const GLint srcRowStride
2341 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2345 for (img
= 0; img
< srcDepth
; img
++) {
2346 GLuint
*dstRow
= (GLuint
*) dstAddr
2347 + dstImageOffsets
[dstZoffset
+ img
]
2348 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2351 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2352 srcWidth
, srcHeight
,
2355 for (row
= 0; row
< srcHeight
; row
++) {
2356 GLubyte stencil
[MAX_WIDTH
];
2358 /* the 24 depth bits will be in the high position: */
2359 _mesa_unpack_depth_span(ctx
, srcWidth
,
2360 GL_UNSIGNED_INT
, /* dst type */
2361 dstRow
, /* dst addr */
2363 srcType
, src
, srcPacking
);
2364 /* get the 8-bit stencil values */
2365 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2366 GL_UNSIGNED_BYTE
, /* dst type */
2367 stencil
, /* dst addr */
2368 srcType
, src
, srcPacking
,
2369 ctx
->_ImageTransferState
);
2370 /* merge stencil values into depth values */
2371 for (i
= 0; i
< srcWidth
; i
++)
2372 dstRow
[i
] |= stencil
[i
];
2374 src
+= srcRowStride
;
2375 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2385 * Store an image in any of the formats:
2386 * _mesa_texformat_rgba_float32
2387 * _mesa_texformat_rgb_float32
2388 * _mesa_texformat_alpha_float32
2389 * _mesa_texformat_luminance_float32
2390 * _mesa_texformat_luminance_alpha_float32
2391 * _mesa_texformat_intensity_float32
2394 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2396 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2398 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2399 dstFormat
== &_mesa_texformat_rgb_float32
||
2400 dstFormat
== &_mesa_texformat_alpha_float32
||
2401 dstFormat
== &_mesa_texformat_luminance_float32
||
2402 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2403 dstFormat
== &_mesa_texformat_intensity_float32
);
2404 ASSERT(baseInternalFormat
== GL_RGBA
||
2405 baseInternalFormat
== GL_RGB
||
2406 baseInternalFormat
== GL_ALPHA
||
2407 baseInternalFormat
== GL_LUMINANCE
||
2408 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2409 baseInternalFormat
== GL_INTENSITY
);
2410 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2412 if (!ctx
->_ImageTransferState
&&
2413 !srcPacking
->SwapBytes
&&
2414 baseInternalFormat
== srcFormat
&&
2415 srcType
== GL_FLOAT
) {
2416 /* simple memcpy path */
2417 memcpy_texture(ctx
, dims
,
2418 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2421 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2422 srcAddr
, srcPacking
);
2426 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2428 dstFormat
->BaseFormat
,
2429 srcWidth
, srcHeight
, srcDepth
,
2430 srcFormat
, srcType
, srcAddr
,
2432 const GLfloat
*srcRow
= tempImage
;
2437 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2438 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2439 for (img
= 0; img
< srcDepth
; img
++) {
2440 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2441 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2442 + dstYoffset
* dstRowStride
2443 + dstXoffset
* dstFormat
->TexelBytes
;
2444 for (row
= 0; row
< srcHeight
; row
++) {
2445 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2446 dstRow
+= dstRowStride
;
2447 srcRow
+= srcWidth
* components
;
2451 _mesa_free((void *) tempImage
);
2458 * As above, but store 16-bit floats.
2461 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2463 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2465 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2466 dstFormat
== &_mesa_texformat_rgb_float16
||
2467 dstFormat
== &_mesa_texformat_alpha_float16
||
2468 dstFormat
== &_mesa_texformat_luminance_float16
||
2469 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2470 dstFormat
== &_mesa_texformat_intensity_float16
);
2471 ASSERT(baseInternalFormat
== GL_RGBA
||
2472 baseInternalFormat
== GL_RGB
||
2473 baseInternalFormat
== GL_ALPHA
||
2474 baseInternalFormat
== GL_LUMINANCE
||
2475 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2476 baseInternalFormat
== GL_INTENSITY
);
2477 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2479 if (!ctx
->_ImageTransferState
&&
2480 !srcPacking
->SwapBytes
&&
2481 baseInternalFormat
== srcFormat
&&
2482 srcType
== GL_HALF_FLOAT_ARB
) {
2483 /* simple memcpy path */
2484 memcpy_texture(ctx
, dims
,
2485 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2488 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2489 srcAddr
, srcPacking
);
2493 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2495 dstFormat
->BaseFormat
,
2496 srcWidth
, srcHeight
, srcDepth
,
2497 srcFormat
, srcType
, srcAddr
,
2499 const GLfloat
*src
= tempImage
;
2503 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2504 for (img
= 0; img
< srcDepth
; img
++) {
2505 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2506 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2507 + dstYoffset
* dstRowStride
2508 + dstXoffset
* dstFormat
->TexelBytes
;
2509 for (row
= 0; row
< srcHeight
; row
++) {
2510 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2512 for (i
= 0; i
< srcWidth
* components
; i
++) {
2513 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2515 dstRow
+= dstRowStride
;
2516 src
+= srcWidth
* components
;
2520 _mesa_free((void *) tempImage
);
2526 #if FEATURE_EXT_texture_sRGB
2528 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2530 const GLboolean littleEndian
= _mesa_little_endian();
2531 const struct gl_texture_format
*newDstFormat
;
2532 StoreTexImageFunc store
;
2535 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2537 /* reuse normal rgb texstore code */
2539 newDstFormat
= &_mesa_texformat_bgr888
;
2540 store
= _mesa_texstore_bgr888
;
2543 newDstFormat
= &_mesa_texformat_rgb888
;
2544 store
= _mesa_texstore_rgb888
;
2547 k
= store(ctx
, dims
, baseInternalFormat
,
2548 newDstFormat
, dstAddr
,
2549 dstXoffset
, dstYoffset
, dstZoffset
,
2550 dstRowStride
, dstImageOffsets
,
2551 srcWidth
, srcHeight
, srcDepth
,
2553 srcAddr
, srcPacking
);
2559 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2561 const GLboolean littleEndian
= _mesa_little_endian();
2562 const struct gl_texture_format
*newDstFormat
;
2565 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2567 /* reuse normal rgba texstore code */
2569 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2571 newDstFormat
= &_mesa_texformat_rgba8888
;
2573 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2574 newDstFormat
, dstAddr
,
2575 dstXoffset
, dstYoffset
, dstZoffset
,
2576 dstRowStride
, dstImageOffsets
,
2577 srcWidth
, srcHeight
, srcDepth
,
2579 srcAddr
, srcPacking
);
2585 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2587 const struct gl_texture_format
*newDstFormat
;
2590 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2592 newDstFormat
= &_mesa_texformat_l8
;
2594 /* _mesa_textore_a8 handles luminance8 too */
2595 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2596 newDstFormat
, dstAddr
,
2597 dstXoffset
, dstYoffset
, dstZoffset
,
2598 dstRowStride
, dstImageOffsets
,
2599 srcWidth
, srcHeight
, srcDepth
,
2601 srcAddr
, srcPacking
);
2607 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2609 const GLboolean littleEndian
= _mesa_little_endian();
2610 const struct gl_texture_format
*newDstFormat
;
2613 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2615 /* reuse normal luminance/alpha texstore code */
2617 newDstFormat
= &_mesa_texformat_al88
;
2619 newDstFormat
= &_mesa_texformat_al88_rev
;
2621 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2622 newDstFormat
, dstAddr
,
2623 dstXoffset
, dstYoffset
, dstZoffset
,
2624 dstRowStride
, dstImageOffsets
,
2625 srcWidth
, srcHeight
, srcDepth
,
2627 srcAddr
, srcPacking
);
2631 #endif /* FEATURE_EXT_texture_sRGB */
2635 * Check if an unpack PBO is active prior to fetching a texture image.
2636 * If so, do bounds checking and map the buffer into main memory.
2637 * Any errors detected will be recorded.
2638 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2641 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2642 GLsizei width
, GLsizei height
, GLsizei depth
,
2643 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2644 const struct gl_pixelstore_attrib
*unpack
,
2645 const char *funcName
)
2649 if (unpack
->BufferObj
->Name
== 0) {
2653 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2654 format
, type
, pixels
)) {
2655 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2659 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2660 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2662 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2666 return ADD_POINTERS(buf
, pixels
);
2671 * Check if an unpack PBO is active prior to fetching a compressed texture
2673 * If so, do bounds checking and map the buffer into main memory.
2674 * Any errors detected will be recorded.
2675 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2678 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2679 GLsizei imageSize
, const GLvoid
*pixels
,
2680 const struct gl_pixelstore_attrib
*packing
,
2681 const char *funcName
)
2685 if (packing
->BufferObj
->Name
== 0) {
2686 /* not using a PBO - return pointer unchanged */
2689 if ((const GLubyte
*) pixels
+ imageSize
>
2690 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2691 /* out of bounds read! */
2692 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2696 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2697 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2699 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2703 return ADD_POINTERS(buf
, pixels
);
2708 * This function must be called after either of the validate_pbo_*_teximage()
2709 * functions. It unmaps the PBO buffer if it was mapped earlier.
2712 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2713 const struct gl_pixelstore_attrib
*unpack
)
2715 if (unpack
->BufferObj
->Name
) {
2716 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2724 * Adaptor for fetching a GLchan texel from a float-valued texture.
2727 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2728 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2731 ASSERT(texImage
->FetchTexelf
);
2732 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2733 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2734 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2735 /* just one channel */
2736 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2740 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2741 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2742 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2743 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2749 * Adaptor for fetching a float texel from a GLchan-valued texture.
2752 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2753 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2756 ASSERT(texImage
->FetchTexelc
);
2757 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2758 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2759 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2760 /* just one channel */
2761 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2765 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2766 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2767 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2768 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2774 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2777 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2779 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2780 ASSERT(texImage
->TexFormat
);
2784 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2785 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2788 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2789 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2792 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2793 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2799 /* now check if we need to use a float/chan adaptor */
2800 if (!texImage
->FetchTexelc
) {
2801 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
2803 else if (!texImage
->FetchTexelf
) {
2804 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
2808 ASSERT(texImage
->FetchTexelc
);
2809 ASSERT(texImage
->FetchTexelf
);
2814 * Choose the actual storage format for a new texture image.
2815 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2816 * Also set some other texImage fields related to texture compression, etc.
2817 * \param ctx rendering context
2818 * \param texImage the gl_texture_image
2819 * \param dims texture dimensions (1, 2 or 3)
2820 * \param format the user-specified format parameter
2821 * \param type the user-specified type parameter
2822 * \param internalFormat the user-specified internal format hint
2825 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2827 GLenum format
, GLenum type
, GLint internalFormat
)
2829 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2830 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2833 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2835 ASSERT(texImage
->TexFormat
);
2837 _mesa_set_fetch_functions(texImage
, dims
);
2839 if (texImage
->TexFormat
->TexelBytes
== 0) {
2840 /* must be a compressed format */
2841 texImage
->IsCompressed
= GL_TRUE
;
2842 texImage
->CompressedSize
=
2843 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2844 texImage
->Height
, texImage
->Depth
,
2845 texImage
->TexFormat
->MesaFormat
);
2848 /* non-compressed format */
2849 texImage
->IsCompressed
= GL_FALSE
;
2850 texImage
->CompressedSize
= 0;
2857 * This is the software fallback for Driver.TexImage1D()
2858 * and Driver.CopyTexImage1D().
2859 * \sa _mesa_store_teximage2d()
2862 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2863 GLint internalFormat
,
2864 GLint width
, GLint border
,
2865 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2866 const struct gl_pixelstore_attrib
*packing
,
2867 struct gl_texture_object
*texObj
,
2868 struct gl_texture_image
*texImage
)
2870 GLint postConvWidth
= width
;
2874 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2875 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2878 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2880 /* allocate memory */
2881 if (texImage
->IsCompressed
)
2882 sizeInBytes
= texImage
->CompressedSize
;
2884 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2885 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2886 if (!texImage
->Data
) {
2887 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2891 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2892 pixels
, packing
, "glTexImage1D");
2894 /* Note: we check for a NULL image pointer here, _after_ we allocated
2895 * memory for the texture. That's what the GL spec calls for.
2900 const GLint dstRowStride
= 0;
2902 ASSERT(texImage
->TexFormat
->StoreImage
);
2903 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2904 texImage
->TexFormat
,
2906 0, 0, 0, /* dstX/Y/Zoffset */
2908 texImage
->ImageOffsets
,
2910 format
, type
, pixels
, packing
);
2912 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2916 /* GL_SGIS_generate_mipmap */
2917 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2918 _mesa_generate_mipmap(ctx
, target
,
2919 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2923 _mesa_unmap_teximage_pbo(ctx
, packing
);
2928 * This is the software fallback for Driver.TexImage2D()
2929 * and Driver.CopyTexImage2D().
2931 * This function is oriented toward storing images in main memory, rather
2932 * than VRAM. Device driver's can easily plug in their own replacement.
2934 * Note: width and height may be pre-convolved dimensions, but
2935 * texImage->Width and texImage->Height will be post-convolved dimensions.
2938 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2939 GLint internalFormat
,
2940 GLint width
, GLint height
, GLint border
,
2941 GLenum format
, GLenum type
, const void *pixels
,
2942 const struct gl_pixelstore_attrib
*packing
,
2943 struct gl_texture_object
*texObj
,
2944 struct gl_texture_image
*texImage
)
2946 GLint postConvWidth
= width
, postConvHeight
= height
;
2947 GLint texelBytes
, sizeInBytes
;
2950 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2951 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2955 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2957 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2959 /* allocate memory */
2960 if (texImage
->IsCompressed
)
2961 sizeInBytes
= texImage
->CompressedSize
;
2963 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2964 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2965 if (!texImage
->Data
) {
2966 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2970 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2971 pixels
, packing
, "glTexImage2D");
2973 /* Note: we check for a NULL image pointer here, _after_ we allocated
2974 * memory for the texture. That's what the GL spec calls for.
2981 if (texImage
->IsCompressed
) {
2983 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2986 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2988 ASSERT(texImage
->TexFormat
->StoreImage
);
2989 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2990 texImage
->TexFormat
,
2992 0, 0, 0, /* dstX/Y/Zoffset */
2994 texImage
->ImageOffsets
,
2996 format
, type
, pixels
, packing
);
2998 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
3002 /* GL_SGIS_generate_mipmap */
3003 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3004 _mesa_generate_mipmap(ctx
, target
,
3005 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3009 _mesa_unmap_teximage_pbo(ctx
, packing
);
3015 * This is the software fallback for Driver.TexImage3D()
3016 * and Driver.CopyTexImage3D().
3017 * \sa _mesa_store_teximage2d()
3020 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3021 GLint internalFormat
,
3022 GLint width
, GLint height
, GLint depth
, GLint border
,
3023 GLenum format
, GLenum type
, const void *pixels
,
3024 const struct gl_pixelstore_attrib
*packing
,
3025 struct gl_texture_object
*texObj
,
3026 struct gl_texture_image
*texImage
)
3028 GLint texelBytes
, sizeInBytes
;
3031 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3033 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3035 /* allocate memory */
3036 if (texImage
->IsCompressed
)
3037 sizeInBytes
= texImage
->CompressedSize
;
3039 sizeInBytes
= width
* height
* depth
* texelBytes
;
3040 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3041 if (!texImage
->Data
) {
3042 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3046 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3047 type
, pixels
, packing
, "glTexImage3D");
3049 /* Note: we check for a NULL image pointer here, _after_ we allocated
3050 * memory for the texture. That's what the GL spec calls for.
3057 if (texImage
->IsCompressed
) {
3059 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3062 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3064 ASSERT(texImage
->TexFormat
->StoreImage
);
3065 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3066 texImage
->TexFormat
,
3068 0, 0, 0, /* dstX/Y/Zoffset */
3070 texImage
->ImageOffsets
,
3071 width
, height
, depth
,
3072 format
, type
, pixels
, packing
);
3074 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3078 /* GL_SGIS_generate_mipmap */
3079 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3080 _mesa_generate_mipmap(ctx
, target
,
3081 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3085 _mesa_unmap_teximage_pbo(ctx
, packing
);
3092 * This is the software fallback for Driver.TexSubImage1D()
3093 * and Driver.CopyTexSubImage1D().
3096 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3097 GLint xoffset
, GLint width
,
3098 GLenum format
, GLenum type
, const void *pixels
,
3099 const struct gl_pixelstore_attrib
*packing
,
3100 struct gl_texture_object
*texObj
,
3101 struct gl_texture_image
*texImage
)
3103 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3104 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3105 pixels
, packing
, "glTexSubImage1D");
3110 const GLint dstRowStride
= 0;
3112 ASSERT(texImage
->TexFormat
->StoreImage
);
3113 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3114 texImage
->TexFormat
,
3116 xoffset
, 0, 0, /* offsets */
3118 texImage
->ImageOffsets
,
3120 format
, type
, pixels
, packing
);
3122 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3126 /* GL_SGIS_generate_mipmap */
3127 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3128 _mesa_generate_mipmap(ctx
, target
,
3129 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3133 _mesa_unmap_teximage_pbo(ctx
, packing
);
3139 * This is the software fallback for Driver.TexSubImage2D()
3140 * and Driver.CopyTexSubImage2D().
3143 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3144 GLint xoffset
, GLint yoffset
,
3145 GLint width
, GLint height
,
3146 GLenum format
, GLenum type
, const void *pixels
,
3147 const struct gl_pixelstore_attrib
*packing
,
3148 struct gl_texture_object
*texObj
,
3149 struct gl_texture_image
*texImage
)
3151 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3152 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3153 pixels
, packing
, "glTexSubImage2D");
3158 GLint dstRowStride
= 0;
3160 if (texImage
->IsCompressed
) {
3161 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3165 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3167 ASSERT(texImage
->TexFormat
->StoreImage
);
3168 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3169 texImage
->TexFormat
,
3171 xoffset
, yoffset
, 0,
3173 texImage
->ImageOffsets
,
3175 format
, type
, pixels
, packing
);
3177 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3181 /* GL_SGIS_generate_mipmap */
3182 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3183 _mesa_generate_mipmap(ctx
, target
,
3184 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3188 _mesa_unmap_teximage_pbo(ctx
, packing
);
3193 * This is the software fallback for Driver.TexSubImage3D().
3194 * and Driver.CopyTexSubImage3D().
3197 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3198 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3199 GLint width
, GLint height
, GLint depth
,
3200 GLenum format
, GLenum type
, const void *pixels
,
3201 const struct gl_pixelstore_attrib
*packing
,
3202 struct gl_texture_object
*texObj
,
3203 struct gl_texture_image
*texImage
)
3205 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3206 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3207 type
, pixels
, packing
,
3215 if (texImage
->IsCompressed
) {
3216 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3220 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3222 ASSERT(texImage
->TexFormat
->StoreImage
);
3223 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3224 texImage
->TexFormat
,
3226 xoffset
, yoffset
, zoffset
,
3228 texImage
->ImageOffsets
,
3229 width
, height
, depth
,
3230 format
, type
, pixels
, packing
);
3232 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3236 /* GL_SGIS_generate_mipmap */
3237 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3238 _mesa_generate_mipmap(ctx
, target
,
3239 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3243 _mesa_unmap_teximage_pbo(ctx
, packing
);
3248 * Fallback for Driver.CompressedTexImage1D()
3251 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3252 GLint internalFormat
,
3253 GLint width
, GLint border
,
3254 GLsizei imageSize
, const GLvoid
*data
,
3255 struct gl_texture_object
*texObj
,
3256 struct gl_texture_image
*texImage
)
3258 /* this space intentionally left blank */
3260 (void) target
; (void) level
;
3261 (void) internalFormat
;
3262 (void) width
; (void) border
;
3263 (void) imageSize
; (void) data
;
3271 * Fallback for Driver.CompressedTexImage2D()
3274 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3275 GLint internalFormat
,
3276 GLint width
, GLint height
, GLint border
,
3277 GLsizei imageSize
, const GLvoid
*data
,
3278 struct gl_texture_object
*texObj
,
3279 struct gl_texture_image
*texImage
)
3281 (void) width
; (void) height
; (void) border
;
3283 /* This is pretty simple, basically just do a memcpy without worrying
3284 * about the usual image unpacking or image transfer operations.
3288 ASSERT(texImage
->Width
> 0);
3289 ASSERT(texImage
->Height
> 0);
3290 ASSERT(texImage
->Depth
== 1);
3291 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3293 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3295 /* allocate storage */
3296 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3297 if (!texImage
->Data
) {
3298 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3302 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3304 "glCompressedTexImage2D");
3309 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3310 MEMCPY(texImage
->Data
, data
, imageSize
);
3312 /* GL_SGIS_generate_mipmap */
3313 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3314 _mesa_generate_mipmap(ctx
, target
,
3315 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3319 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3325 * Fallback for Driver.CompressedTexImage3D()
3328 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3329 GLint internalFormat
,
3330 GLint width
, GLint height
, GLint depth
,
3332 GLsizei imageSize
, const GLvoid
*data
,
3333 struct gl_texture_object
*texObj
,
3334 struct gl_texture_image
*texImage
)
3336 /* this space intentionally left blank */
3338 (void) target
; (void) level
;
3339 (void) internalFormat
;
3340 (void) width
; (void) height
; (void) depth
;
3342 (void) imageSize
; (void) data
;
3350 * Fallback for Driver.CompressedTexSubImage1D()
3353 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3355 GLint xoffset
, GLsizei width
,
3357 GLsizei imageSize
, const GLvoid
*data
,
3358 struct gl_texture_object
*texObj
,
3359 struct gl_texture_image
*texImage
)
3361 /* there are no compressed 1D texture formats yet */
3363 (void) target
; (void) level
;
3364 (void) xoffset
; (void) width
;
3366 (void) imageSize
; (void) data
;
3373 * Fallback for Driver.CompressedTexSubImage2D()
3376 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3378 GLint xoffset
, GLint yoffset
,
3379 GLsizei width
, GLsizei height
,
3381 GLsizei imageSize
, const GLvoid
*data
,
3382 struct gl_texture_object
*texObj
,
3383 struct gl_texture_image
*texImage
)
3385 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3389 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3393 /* these should have been caught sooner */
3394 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3395 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3396 ASSERT((xoffset
& 3) == 0);
3397 ASSERT((yoffset
& 3) == 0);
3399 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3400 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3402 "glCompressedTexSubImage2D");
3406 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3407 src
= (const GLubyte
*) data
;
3409 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3410 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3411 texImage
->TexFormat
->MesaFormat
,
3413 (GLubyte
*) texImage
->Data
);
3415 bytesPerRow
= srcRowStride
;
3418 for (i
= 0; i
< rows
; i
++) {
3419 MEMCPY(dest
, src
, bytesPerRow
);
3420 dest
+= destRowStride
;
3421 src
+= srcRowStride
;
3424 /* GL_SGIS_generate_mipmap */
3425 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3426 _mesa_generate_mipmap(ctx
, target
,
3427 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3431 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3436 * Fallback for Driver.CompressedTexSubImage3D()
3439 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3441 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3442 GLsizei width
, GLsizei height
, GLsizei depth
,
3444 GLsizei imageSize
, const GLvoid
*data
,
3445 struct gl_texture_object
*texObj
,
3446 struct gl_texture_image
*texImage
)
3448 /* there are no compressed 3D texture formats yet */
3450 (void) target
; (void) level
;
3451 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3452 (void) width
; (void) height
; (void) depth
;
3454 (void) imageSize
; (void) data
;
3462 #if FEATURE_EXT_texture_sRGB
3465 * Test if given texture image is an sRGB format.
3468 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3470 switch (texImage
->TexFormat
->MesaFormat
) {
3471 case MESA_FORMAT_SRGB8
:
3472 case MESA_FORMAT_SRGBA8
:
3473 case MESA_FORMAT_SL8
:
3474 case MESA_FORMAT_SLA8
:
3481 #endif /* FEATURE_EXT_texture_sRGB */
3485 * This is the software fallback for Driver.GetTexImage().
3486 * All error checking will have been done before this routine is called.
3489 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3490 GLenum format
, GLenum type
, GLvoid
*pixels
,
3491 struct gl_texture_object
*texObj
,
3492 struct gl_texture_image
*texImage
)
3494 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3496 if (ctx
->Pack
.BufferObj
->Name
) {
3497 /* Packing texture image into a PBO.
3498 * Map the (potentially) VRAM-based buffer into our process space so
3499 * we can write into it with the code below.
3500 * A hardware driver might use a sophisticated blit to move the
3501 * texture data to the PBO if the PBO is in VRAM along with the texture.
3503 GLubyte
*buf
= (GLubyte
*)
3504 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3505 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3507 /* buffer is already mapped - that's an error */
3508 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3511 /* <pixels> was an offset into the PBO.
3512 * Now make it a real, client-side pointer inside the mapped region.
3514 pixels
= ADD_POINTERS(buf
, pixels
);
3522 const GLint width
= texImage
->Width
;
3523 const GLint height
= texImage
->Height
;
3524 const GLint depth
= texImage
->Depth
;
3526 for (img
= 0; img
< depth
; img
++) {
3527 for (row
= 0; row
< height
; row
++) {
3528 /* compute destination address in client memory */
3529 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3530 width
, height
, format
, type
,
3534 if (format
== GL_COLOR_INDEX
) {
3535 GLuint indexRow
[MAX_WIDTH
];
3537 /* Can't use FetchTexel here because that returns RGBA */
3538 if (texImage
->TexFormat
->IndexBits
== 8) {
3539 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3540 src
+= width
* (img
* texImage
->Height
+ row
);
3541 for (col
= 0; col
< width
; col
++) {
3542 indexRow
[col
] = src
[col
];
3545 else if (texImage
->TexFormat
->IndexBits
== 16) {
3546 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3547 src
+= width
* (img
* texImage
->Height
+ row
);
3548 for (col
= 0; col
< width
; col
++) {
3549 indexRow
[col
] = src
[col
];
3554 "Color index problem in _mesa_GetTexImage");
3556 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3557 indexRow
, &ctx
->Pack
,
3558 0 /* no image transfer */);
3560 else if (format
== GL_DEPTH_COMPONENT
) {
3561 GLfloat depthRow
[MAX_WIDTH
];
3563 for (col
= 0; col
< width
; col
++) {
3564 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3567 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3568 depthRow
, &ctx
->Pack
);
3570 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3571 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3572 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3573 src
+= width
* row
+ width
* height
* img
;
3574 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3575 if (ctx
->Pack
.SwapBytes
) {
3576 _mesa_swap4((GLuint
*) dest
, width
);
3579 else if (format
== GL_YCBCR_MESA
) {
3580 /* No pixel transfer */
3581 const GLint rowstride
= texImage
->RowStride
;
3583 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3584 width
* sizeof(GLushort
));
3585 /* check for byte swapping */
3586 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3587 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3588 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3589 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3590 if (!ctx
->Pack
.SwapBytes
)
3591 _mesa_swap2((GLushort
*) dest
, width
);
3593 else if (ctx
->Pack
.SwapBytes
) {
3594 _mesa_swap2((GLushort
*) dest
, width
);
3597 #if FEATURE_EXT_texture_sRGB
3598 else if (is_srgb_teximage(texImage
)) {
3599 /* no pixel transfer and no non-linear to linear conversion */
3600 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3601 const GLint rowstride
= comps
* texImage
->RowStride
;
3603 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3604 comps
* width
* sizeof(GLubyte
));
3606 #endif /* FEATURE_EXT_texture_sRGB */
3608 /* general case: convert row to RGBA format */
3609 GLfloat rgba
[MAX_WIDTH
][4];
3611 for (col
= 0; col
< width
; col
++) {
3612 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3613 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3614 rgba
[col
][RCOMP
] = 0.0;
3615 rgba
[col
][GCOMP
] = 0.0;
3616 rgba
[col
][BCOMP
] = 0.0;
3618 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3619 rgba
[col
][GCOMP
] = 0.0;
3620 rgba
[col
][BCOMP
] = 0.0;
3621 rgba
[col
][ACOMP
] = 1.0;
3623 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3624 rgba
[col
][GCOMP
] = 0.0;
3625 rgba
[col
][BCOMP
] = 0.0;
3627 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3628 rgba
[col
][GCOMP
] = 0.0;
3629 rgba
[col
][BCOMP
] = 0.0;
3630 rgba
[col
][ACOMP
] = 1.0;
3633 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3635 &ctx
->Pack
, 0x0 /*image xfer ops*/);
3641 if (ctx
->Pack
.BufferObj
->Name
) {
3642 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3643 ctx
->Pack
.BufferObj
);
3650 * This is the software fallback for Driver.GetCompressedTexImage().
3651 * All error checking will have been done before this routine is called.
3654 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3656 const struct gl_texture_object
*texObj
,
3657 const struct gl_texture_image
*texImage
)
3661 if (ctx
->Pack
.BufferObj
->Name
) {
3662 /* pack texture image into a PBO */
3664 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3665 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3666 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3667 "glGetCompressedTexImage(invalid PBO access)");
3670 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3672 ctx
->Pack
.BufferObj
);
3674 /* buffer is already mapped - that's an error */
3675 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3676 "glGetCompressedTexImage(PBO is mapped)");
3679 img
= ADD_POINTERS(buf
, img
);
3686 /* don't use texImage->CompressedSize since that may be padded out */
3687 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3689 texImage
->TexFormat
->MesaFormat
);
3691 /* just memcpy, no pixelstore or pixel transfer */
3692 _mesa_memcpy(img
, texImage
->Data
, size
);
3694 if (ctx
->Pack
.BufferObj
->Name
) {
3695 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3696 ctx
->Pack
.BufferObj
);