2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
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
) {
1447 for (img
= 0; img
< srcDepth
; img
++) {
1448 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1449 srcWidth
, srcFormat
, srcType
);
1450 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1451 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1452 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1453 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1454 + dstYoffset
* dstRowStride
1455 + dstXoffset
* dstFormat
->TexelBytes
;
1456 for (row
= 0; row
< srcHeight
; row
++) {
1457 GLuint
*d4
= (GLuint
*) dstRow
;
1458 for (col
= 0; col
< srcWidth
; col
++) {
1459 d4
[col
] = ((0xff << 24) |
1460 (srcRow
[col
* 3 + RCOMP
] << 16) |
1461 (srcRow
[col
* 3 + GCOMP
] << 8) |
1462 (srcRow
[col
* 3 + BCOMP
] << 0));
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
&&
1476 /* same as above case, but src data has alpha too */
1477 GLint img
, row
, col
;
1478 /* For some reason, streaming copies to write-combined regions
1479 * are extremely sensitive to the characteristics of how the
1480 * source data is retrieved. By reordering the source reads to
1481 * be in-order, the speed of this operation increases by half.
1482 * Strangely the same isn't required for the RGB path, above.
1484 for (img
= 0; img
< srcDepth
; img
++) {
1485 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1486 srcWidth
, srcFormat
, srcType
);
1487 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1488 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1489 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1490 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1491 + dstYoffset
* dstRowStride
1492 + dstXoffset
* dstFormat
->TexelBytes
;
1493 for (row
= 0; row
< srcHeight
; row
++) {
1494 GLuint
*d4
= (GLuint
*) dstRow
;
1495 for (col
= 0; col
< srcWidth
; col
++) {
1496 d4
[col
] = ((srcRow
[col
* 4 + ACOMP
] << 24) |
1497 (srcRow
[col
* 4 + RCOMP
] << 16) |
1498 (srcRow
[col
* 4 + GCOMP
] << 8) |
1499 (srcRow
[col
* 4 + BCOMP
] << 0));
1501 dstRow
+= dstRowStride
;
1502 srcRow
+= srcRowStride
;
1506 else if (!ctx
->_ImageTransferState
&&
1507 !srcPacking
->SwapBytes
&&
1508 dstFormat
== &_mesa_texformat_argb8888
&&
1509 srcFormat
== GL_RGBA
&&
1510 baseInternalFormat
== GL_RGBA
&&
1511 srcType
== GL_UNSIGNED_BYTE
) {
1513 GLint img
, row
, col
;
1514 for (img
= 0; img
< srcDepth
; img
++) {
1515 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1516 srcWidth
, srcFormat
, srcType
);
1517 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1518 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1519 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1520 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1521 + dstYoffset
* dstRowStride
1522 + dstXoffset
* dstFormat
->TexelBytes
;
1523 for (row
= 0; row
< srcHeight
; row
++) {
1524 for (col
= 0; col
< srcWidth
; col
++) {
1525 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1526 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1527 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1528 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1530 dstRow
+= dstRowStride
;
1531 srcRow
+= srcRowStride
;
1535 else if (!ctx
->_ImageTransferState
&&
1536 (srcType
== GL_UNSIGNED_BYTE
||
1537 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1538 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1539 can_swizzle(baseInternalFormat
) &&
1540 can_swizzle(srcFormat
)) {
1544 /* dstmap - how to swizzle from RGBA to dst format:
1546 if ((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
) ||
1547 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
)) {
1548 dstmap
[3] = 3; /* alpha */
1549 dstmap
[2] = 0; /* red */
1550 dstmap
[1] = 1; /* green */
1551 dstmap
[0] = 2; /* blue */
1554 assert((littleEndian
&& dstFormat
== &_mesa_texformat_argb8888_rev
) ||
1555 (!littleEndian
&& dstFormat
== &_mesa_texformat_argb8888
));
1562 _mesa_swizzle_ubyte_image(ctx
, dims
,
1568 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1571 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1576 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1578 dstFormat
->BaseFormat
,
1579 srcWidth
, srcHeight
, srcDepth
,
1580 srcFormat
, srcType
, srcAddr
,
1582 const GLchan
*src
= tempImage
;
1583 GLint img
, row
, col
;
1586 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1587 for (img
= 0; img
< srcDepth
; img
++) {
1588 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1589 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1590 + dstYoffset
* dstRowStride
1591 + dstXoffset
* dstFormat
->TexelBytes
;
1592 for (row
= 0; row
< srcHeight
; row
++) {
1593 GLuint
*dstUI
= (GLuint
*) dstRow
;
1594 if (dstFormat
== &_mesa_texformat_argb8888
) {
1595 for (col
= 0; col
< srcWidth
; col
++) {
1596 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1597 CHAN_TO_UBYTE(src
[RCOMP
]),
1598 CHAN_TO_UBYTE(src
[GCOMP
]),
1599 CHAN_TO_UBYTE(src
[BCOMP
]) );
1604 for (col
= 0; col
< srcWidth
; col
++) {
1605 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1606 CHAN_TO_UBYTE(src
[RCOMP
]),
1607 CHAN_TO_UBYTE(src
[GCOMP
]),
1608 CHAN_TO_UBYTE(src
[BCOMP
]) );
1612 dstRow
+= dstRowStride
;
1615 _mesa_free((void *) tempImage
);
1622 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1624 const GLboolean littleEndian
= _mesa_little_endian();
1626 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1627 ASSERT(dstFormat
->TexelBytes
== 3);
1629 if (!ctx
->_ImageTransferState
&&
1630 !srcPacking
->SwapBytes
&&
1631 baseInternalFormat
== GL_RGB
&&
1632 srcFormat
== GL_BGR
&&
1633 srcType
== GL_UNSIGNED_BYTE
&&
1635 /* simple memcpy path */
1636 memcpy_texture(ctx
, dims
,
1637 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1640 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1641 srcAddr
, srcPacking
);
1643 else if (!ctx
->_ImageTransferState
&&
1644 !srcPacking
->SwapBytes
&&
1645 srcFormat
== GL_RGBA
&&
1646 srcType
== GL_UNSIGNED_BYTE
) {
1647 /* extract RGB from RGBA */
1648 GLint img
, row
, col
;
1649 for (img
= 0; img
< srcDepth
; img
++) {
1650 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1651 srcWidth
, srcFormat
, srcType
);
1652 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1653 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1654 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1655 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1656 + dstYoffset
* dstRowStride
1657 + dstXoffset
* dstFormat
->TexelBytes
;
1658 for (row
= 0; row
< srcHeight
; row
++) {
1659 for (col
= 0; col
< srcWidth
; col
++) {
1660 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1661 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1662 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1664 dstRow
+= dstRowStride
;
1665 srcRow
+= srcRowStride
;
1669 else if (!ctx
->_ImageTransferState
&&
1670 srcType
== GL_UNSIGNED_BYTE
&&
1671 can_swizzle(baseInternalFormat
) &&
1672 can_swizzle(srcFormat
)) {
1676 /* dstmap - how to swizzle from RGBA to dst format:
1681 dstmap
[3] = ONE
; /* ? */
1683 _mesa_swizzle_ubyte_image(ctx
, dims
,
1688 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1689 dstRowStride
, dstImageOffsets
,
1690 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1695 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1697 dstFormat
->BaseFormat
,
1698 srcWidth
, srcHeight
, srcDepth
,
1699 srcFormat
, srcType
, srcAddr
,
1701 const GLchan
*src
= (const GLchan
*) tempImage
;
1702 GLint img
, row
, col
;
1705 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1706 for (img
= 0; img
< srcDepth
; img
++) {
1707 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1708 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1709 + dstYoffset
* dstRowStride
1710 + dstXoffset
* dstFormat
->TexelBytes
;
1711 for (row
= 0; row
< srcHeight
; row
++) {
1714 for (col
= 0; col
< srcWidth
; col
++) {
1715 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1716 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1717 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1722 for (col
= 0; col
< srcWidth
; col
++) {
1723 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1724 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1725 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1730 for (col
= 0; col
< srcWidth
; col
++) {
1731 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1732 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1733 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1737 dstRow
+= dstRowStride
;
1740 _mesa_free((void *) tempImage
);
1747 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1749 const GLboolean littleEndian
= _mesa_little_endian();
1751 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1752 ASSERT(dstFormat
->TexelBytes
== 3);
1754 if (!ctx
->_ImageTransferState
&&
1755 !srcPacking
->SwapBytes
&&
1756 baseInternalFormat
== GL_RGB
&&
1757 srcFormat
== GL_RGB
&&
1758 srcType
== GL_UNSIGNED_BYTE
&&
1760 /* simple memcpy path */
1761 memcpy_texture(ctx
, dims
,
1762 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1765 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1766 srcAddr
, srcPacking
);
1768 else if (!ctx
->_ImageTransferState
&&
1769 !srcPacking
->SwapBytes
&&
1770 srcFormat
== GL_RGBA
&&
1771 srcType
== GL_UNSIGNED_BYTE
) {
1772 /* extract BGR from RGBA */
1774 for (img
= 0; img
< srcDepth
; img
++) {
1775 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1776 srcWidth
, srcFormat
, srcType
);
1777 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1778 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1779 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1780 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1781 + dstYoffset
* dstRowStride
1782 + dstXoffset
* dstFormat
->TexelBytes
;
1783 for (row
= 0; row
< srcHeight
; row
++) {
1784 for (col
= 0; col
< srcWidth
; col
++) {
1785 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1786 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1787 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1789 dstRow
+= dstRowStride
;
1790 srcRow
+= srcRowStride
;
1794 else if (!ctx
->_ImageTransferState
&&
1795 srcType
== GL_UNSIGNED_BYTE
&&
1796 can_swizzle(baseInternalFormat
) &&
1797 can_swizzle(srcFormat
)) {
1801 /* dstmap - how to swizzle from RGBA to dst format:
1806 dstmap
[3] = ONE
; /* ? */
1808 _mesa_swizzle_ubyte_image(ctx
, dims
,
1813 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1814 dstRowStride
, dstImageOffsets
,
1815 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1820 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1822 dstFormat
->BaseFormat
,
1823 srcWidth
, srcHeight
, srcDepth
,
1824 srcFormat
, srcType
, srcAddr
,
1826 const GLchan
*src
= (const GLchan
*) tempImage
;
1827 GLint img
, row
, col
;
1830 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1831 for (img
= 0; img
< srcDepth
; img
++) {
1832 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1833 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1834 + dstYoffset
* dstRowStride
1835 + dstXoffset
* dstFormat
->TexelBytes
;
1836 for (row
= 0; row
< srcHeight
; row
++) {
1837 for (col
= 0; col
< srcWidth
; col
++) {
1838 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1839 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1840 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1843 dstRow
+= dstRowStride
;
1846 _mesa_free((void *) tempImage
);
1853 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1855 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1856 dstFormat
== &_mesa_texformat_argb4444_rev
);
1857 ASSERT(dstFormat
->TexelBytes
== 2);
1859 if (!ctx
->_ImageTransferState
&&
1860 !srcPacking
->SwapBytes
&&
1861 dstFormat
== &_mesa_texformat_argb4444
&&
1862 baseInternalFormat
== GL_RGBA
&&
1863 srcFormat
== GL_BGRA
&&
1864 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1865 /* simple memcpy path */
1866 memcpy_texture(ctx
, dims
,
1867 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1870 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1871 srcAddr
, srcPacking
);
1875 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1877 dstFormat
->BaseFormat
,
1878 srcWidth
, srcHeight
, srcDepth
,
1879 srcFormat
, srcType
, srcAddr
,
1881 const GLchan
*src
= tempImage
;
1882 GLint img
, row
, col
;
1885 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1886 for (img
= 0; img
< srcDepth
; img
++) {
1887 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1888 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1889 + dstYoffset
* dstRowStride
1890 + dstXoffset
* dstFormat
->TexelBytes
;
1891 for (row
= 0; row
< srcHeight
; row
++) {
1892 GLushort
*dstUS
= (GLushort
*) dstRow
;
1893 if (dstFormat
== &_mesa_texformat_argb4444
) {
1894 for (col
= 0; col
< srcWidth
; col
++) {
1895 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1896 CHAN_TO_UBYTE(src
[RCOMP
]),
1897 CHAN_TO_UBYTE(src
[GCOMP
]),
1898 CHAN_TO_UBYTE(src
[BCOMP
]) );
1903 for (col
= 0; col
< srcWidth
; col
++) {
1904 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1905 CHAN_TO_UBYTE(src
[RCOMP
]),
1906 CHAN_TO_UBYTE(src
[GCOMP
]),
1907 CHAN_TO_UBYTE(src
[BCOMP
]) );
1911 dstRow
+= dstRowStride
;
1914 _mesa_free((void *) tempImage
);
1922 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1924 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1925 dstFormat
== &_mesa_texformat_argb1555_rev
);
1926 ASSERT(dstFormat
->TexelBytes
== 2);
1928 if (!ctx
->_ImageTransferState
&&
1929 !srcPacking
->SwapBytes
&&
1930 dstFormat
== &_mesa_texformat_argb1555
&&
1931 baseInternalFormat
== GL_RGBA
&&
1932 srcFormat
== GL_BGRA
&&
1933 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1934 /* simple memcpy path */
1935 memcpy_texture(ctx
, dims
,
1936 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1939 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1940 srcAddr
, srcPacking
);
1944 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1946 dstFormat
->BaseFormat
,
1947 srcWidth
, srcHeight
, srcDepth
,
1948 srcFormat
, srcType
, srcAddr
,
1950 const GLchan
*src
=tempImage
;
1951 GLint img
, row
, col
;
1954 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1955 for (img
= 0; img
< srcDepth
; img
++) {
1956 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1957 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1958 + dstYoffset
* dstRowStride
1959 + dstXoffset
* dstFormat
->TexelBytes
;
1960 for (row
= 0; row
< srcHeight
; row
++) {
1961 GLushort
*dstUS
= (GLushort
*) dstRow
;
1962 if (dstFormat
== &_mesa_texformat_argb1555
) {
1963 for (col
= 0; col
< srcWidth
; col
++) {
1964 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1965 CHAN_TO_UBYTE(src
[RCOMP
]),
1966 CHAN_TO_UBYTE(src
[GCOMP
]),
1967 CHAN_TO_UBYTE(src
[BCOMP
]) );
1972 for (col
= 0; col
< srcWidth
; col
++) {
1973 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1974 CHAN_TO_UBYTE(src
[RCOMP
]),
1975 CHAN_TO_UBYTE(src
[GCOMP
]),
1976 CHAN_TO_UBYTE(src
[BCOMP
]) );
1980 dstRow
+= dstRowStride
;
1983 _mesa_free((void *) tempImage
);
1990 _mesa_texstore_al88(TEXSTORE_PARAMS
)
1992 const GLboolean littleEndian
= _mesa_little_endian();
1994 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1995 dstFormat
== &_mesa_texformat_al88_rev
);
1996 ASSERT(dstFormat
->TexelBytes
== 2);
1998 if (!ctx
->_ImageTransferState
&&
1999 !srcPacking
->SwapBytes
&&
2000 dstFormat
== &_mesa_texformat_al88
&&
2001 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
2002 srcFormat
== GL_LUMINANCE_ALPHA
&&
2003 srcType
== GL_UNSIGNED_BYTE
&&
2005 /* simple memcpy path */
2006 memcpy_texture(ctx
, dims
,
2007 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2010 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2011 srcAddr
, srcPacking
);
2013 else if (!ctx
->_ImageTransferState
&&
2015 srcType
== GL_UNSIGNED_BYTE
&&
2016 can_swizzle(baseInternalFormat
) &&
2017 can_swizzle(srcFormat
)) {
2021 /* dstmap - how to swizzle from RGBA to dst format:
2023 if ((littleEndian
&& dstFormat
== &_mesa_texformat_al88
) ||
2024 (!littleEndian
&& dstFormat
== &_mesa_texformat_al88_rev
)) {
2032 dstmap
[2] = ZERO
; /* ? */
2033 dstmap
[3] = ONE
; /* ? */
2035 _mesa_swizzle_ubyte_image(ctx
, dims
,
2040 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2041 dstRowStride
, dstImageOffsets
,
2042 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2047 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2049 dstFormat
->BaseFormat
,
2050 srcWidth
, srcHeight
, srcDepth
,
2051 srcFormat
, srcType
, srcAddr
,
2053 const GLchan
*src
= tempImage
;
2054 GLint img
, row
, col
;
2057 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2058 for (img
= 0; img
< srcDepth
; img
++) {
2059 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2060 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2061 + dstYoffset
* dstRowStride
2062 + dstXoffset
* dstFormat
->TexelBytes
;
2063 for (row
= 0; row
< srcHeight
; row
++) {
2064 GLushort
*dstUS
= (GLushort
*) dstRow
;
2065 if (dstFormat
== &_mesa_texformat_al88
) {
2066 for (col
= 0; col
< srcWidth
; col
++) {
2067 /* src[0] is luminance, src[1] is alpha */
2068 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2069 CHAN_TO_UBYTE(src
[0]) );
2074 for (col
= 0; col
< srcWidth
; col
++) {
2075 /* src[0] is luminance, src[1] is alpha */
2076 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2077 CHAN_TO_UBYTE(src
[0]) );
2081 dstRow
+= dstRowStride
;
2084 _mesa_free((void *) tempImage
);
2091 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2093 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2094 ASSERT(dstFormat
->TexelBytes
== 1);
2096 if (!ctx
->_ImageTransferState
&&
2097 !srcPacking
->SwapBytes
&&
2098 baseInternalFormat
== GL_RGB
&&
2099 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2100 /* simple memcpy path */
2101 memcpy_texture(ctx
, dims
,
2102 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2105 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2106 srcAddr
, srcPacking
);
2110 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2112 dstFormat
->BaseFormat
,
2113 srcWidth
, srcHeight
, srcDepth
,
2114 srcFormat
, srcType
, srcAddr
,
2116 const GLchan
*src
= tempImage
;
2117 GLint img
, row
, col
;
2120 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2121 for (img
= 0; img
< srcDepth
; img
++) {
2122 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2123 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2124 + dstYoffset
* dstRowStride
2125 + dstXoffset
* dstFormat
->TexelBytes
;
2126 for (row
= 0; row
< srcHeight
; row
++) {
2127 for (col
= 0; col
< srcWidth
; col
++) {
2128 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2129 CHAN_TO_UBYTE(src
[GCOMP
]),
2130 CHAN_TO_UBYTE(src
[BCOMP
]) );
2133 dstRow
+= dstRowStride
;
2136 _mesa_free((void *) tempImage
);
2143 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2146 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2148 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2149 dstFormat
== &_mesa_texformat_l8
||
2150 dstFormat
== &_mesa_texformat_i8
);
2151 ASSERT(dstFormat
->TexelBytes
== 1);
2153 if (!ctx
->_ImageTransferState
&&
2154 !srcPacking
->SwapBytes
&&
2155 baseInternalFormat
== srcFormat
&&
2156 srcType
== GL_UNSIGNED_BYTE
) {
2157 /* simple memcpy path */
2158 memcpy_texture(ctx
, dims
,
2159 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2162 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2163 srcAddr
, srcPacking
);
2165 else if (!ctx
->_ImageTransferState
&&
2166 srcType
== GL_UNSIGNED_BYTE
&&
2167 can_swizzle(baseInternalFormat
) &&
2168 can_swizzle(srcFormat
)) {
2172 /* dstmap - how to swizzle from RGBA to dst format:
2174 if (dstFormat
== &_mesa_texformat_a8
) {
2180 dstmap
[1] = ZERO
; /* ? */
2181 dstmap
[2] = ZERO
; /* ? */
2182 dstmap
[3] = ONE
; /* ? */
2184 _mesa_swizzle_ubyte_image(ctx
, dims
,
2189 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2190 dstRowStride
, dstImageOffsets
,
2191 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2196 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2198 dstFormat
->BaseFormat
,
2199 srcWidth
, srcHeight
, srcDepth
,
2200 srcFormat
, srcType
, srcAddr
,
2202 const GLchan
*src
= tempImage
;
2203 GLint img
, row
, col
;
2206 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2207 for (img
= 0; img
< srcDepth
; img
++) {
2208 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2209 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2210 + dstYoffset
* dstRowStride
2211 + dstXoffset
* dstFormat
->TexelBytes
;
2212 for (row
= 0; row
< srcHeight
; row
++) {
2213 for (col
= 0; col
< srcWidth
; col
++) {
2214 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2216 dstRow
+= dstRowStride
;
2220 _mesa_free((void *) tempImage
);
2228 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2230 (void) dims
; (void) baseInternalFormat
;
2231 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2232 ASSERT(dstFormat
->TexelBytes
== 1);
2233 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2235 if (!ctx
->_ImageTransferState
&&
2236 !srcPacking
->SwapBytes
&&
2237 srcFormat
== GL_COLOR_INDEX
&&
2238 srcType
== GL_UNSIGNED_BYTE
) {
2239 /* simple memcpy path */
2240 memcpy_texture(ctx
, dims
,
2241 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2244 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2245 srcAddr
, srcPacking
);
2250 for (img
= 0; img
< srcDepth
; img
++) {
2251 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2252 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2253 + dstYoffset
* dstRowStride
2254 + dstXoffset
* dstFormat
->TexelBytes
;
2255 for (row
= 0; row
< srcHeight
; row
++) {
2256 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2257 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2258 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2259 srcType
, src
, srcPacking
,
2260 ctx
->_ImageTransferState
);
2261 dstRow
+= dstRowStride
;
2270 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2273 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2275 const GLboolean littleEndian
= _mesa_little_endian();
2276 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2278 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2279 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2280 ASSERT(dstFormat
->TexelBytes
== 2);
2281 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2282 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2283 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2284 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2285 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2287 /* always just memcpy since no pixel transfer ops apply */
2288 memcpy_texture(ctx
, dims
,
2289 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2292 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2293 srcAddr
, srcPacking
);
2295 /* Check if we need byte swapping */
2296 /* XXX the logic here _might_ be wrong */
2297 if (srcPacking
->SwapBytes
^
2298 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2299 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2302 for (img
= 0; img
< srcDepth
; img
++) {
2303 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2304 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2305 + dstYoffset
* dstRowStride
2306 + dstXoffset
* dstFormat
->TexelBytes
;
2307 for (row
= 0; row
< srcHeight
; row
++) {
2308 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2309 dstRow
+= dstRowStride
;
2319 * Store a combined depth/stencil texture image.
2322 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2324 const GLuint depthScale
= 0xffffff;
2326 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2327 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2328 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2330 if (!ctx
->_ImageTransferState
&&
2331 !srcPacking
->SwapBytes
) {
2333 memcpy_texture(ctx
, dims
,
2334 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2337 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2338 srcAddr
, srcPacking
);
2342 const GLint srcRowStride
2343 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2347 for (img
= 0; img
< srcDepth
; img
++) {
2348 GLuint
*dstRow
= (GLuint
*) dstAddr
2349 + dstImageOffsets
[dstZoffset
+ img
]
2350 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2353 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2354 srcWidth
, srcHeight
,
2357 for (row
= 0; row
< srcHeight
; row
++) {
2358 GLubyte stencil
[MAX_WIDTH
];
2360 /* the 24 depth bits will be in the high position: */
2361 _mesa_unpack_depth_span(ctx
, srcWidth
,
2362 GL_UNSIGNED_INT
, /* dst type */
2363 dstRow
, /* dst addr */
2365 srcType
, src
, srcPacking
);
2366 /* get the 8-bit stencil values */
2367 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2368 GL_UNSIGNED_BYTE
, /* dst type */
2369 stencil
, /* dst addr */
2370 srcType
, src
, srcPacking
,
2371 ctx
->_ImageTransferState
);
2372 /* merge stencil values into depth values */
2373 for (i
= 0; i
< srcWidth
; i
++)
2374 dstRow
[i
] |= stencil
[i
];
2376 src
+= srcRowStride
;
2377 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2387 * Store an image in any of the formats:
2388 * _mesa_texformat_rgba_float32
2389 * _mesa_texformat_rgb_float32
2390 * _mesa_texformat_alpha_float32
2391 * _mesa_texformat_luminance_float32
2392 * _mesa_texformat_luminance_alpha_float32
2393 * _mesa_texformat_intensity_float32
2396 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2398 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2400 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2401 dstFormat
== &_mesa_texformat_rgb_float32
||
2402 dstFormat
== &_mesa_texformat_alpha_float32
||
2403 dstFormat
== &_mesa_texformat_luminance_float32
||
2404 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2405 dstFormat
== &_mesa_texformat_intensity_float32
);
2406 ASSERT(baseInternalFormat
== GL_RGBA
||
2407 baseInternalFormat
== GL_RGB
||
2408 baseInternalFormat
== GL_ALPHA
||
2409 baseInternalFormat
== GL_LUMINANCE
||
2410 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2411 baseInternalFormat
== GL_INTENSITY
);
2412 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2414 if (!ctx
->_ImageTransferState
&&
2415 !srcPacking
->SwapBytes
&&
2416 baseInternalFormat
== srcFormat
&&
2417 srcType
== GL_FLOAT
) {
2418 /* simple memcpy path */
2419 memcpy_texture(ctx
, dims
,
2420 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2423 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2424 srcAddr
, srcPacking
);
2428 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2430 dstFormat
->BaseFormat
,
2431 srcWidth
, srcHeight
, srcDepth
,
2432 srcFormat
, srcType
, srcAddr
,
2434 const GLfloat
*srcRow
= tempImage
;
2439 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2440 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2441 for (img
= 0; img
< srcDepth
; img
++) {
2442 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2443 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2444 + dstYoffset
* dstRowStride
2445 + dstXoffset
* dstFormat
->TexelBytes
;
2446 for (row
= 0; row
< srcHeight
; row
++) {
2447 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2448 dstRow
+= dstRowStride
;
2449 srcRow
+= srcWidth
* components
;
2453 _mesa_free((void *) tempImage
);
2460 * As above, but store 16-bit floats.
2463 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2465 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2467 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2468 dstFormat
== &_mesa_texformat_rgb_float16
||
2469 dstFormat
== &_mesa_texformat_alpha_float16
||
2470 dstFormat
== &_mesa_texformat_luminance_float16
||
2471 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2472 dstFormat
== &_mesa_texformat_intensity_float16
);
2473 ASSERT(baseInternalFormat
== GL_RGBA
||
2474 baseInternalFormat
== GL_RGB
||
2475 baseInternalFormat
== GL_ALPHA
||
2476 baseInternalFormat
== GL_LUMINANCE
||
2477 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2478 baseInternalFormat
== GL_INTENSITY
);
2479 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2481 if (!ctx
->_ImageTransferState
&&
2482 !srcPacking
->SwapBytes
&&
2483 baseInternalFormat
== srcFormat
&&
2484 srcType
== GL_HALF_FLOAT_ARB
) {
2485 /* simple memcpy path */
2486 memcpy_texture(ctx
, dims
,
2487 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2490 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2491 srcAddr
, srcPacking
);
2495 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2497 dstFormat
->BaseFormat
,
2498 srcWidth
, srcHeight
, srcDepth
,
2499 srcFormat
, srcType
, srcAddr
,
2501 const GLfloat
*src
= tempImage
;
2505 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2506 for (img
= 0; img
< srcDepth
; img
++) {
2507 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2508 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2509 + dstYoffset
* dstRowStride
2510 + dstXoffset
* dstFormat
->TexelBytes
;
2511 for (row
= 0; row
< srcHeight
; row
++) {
2512 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2514 for (i
= 0; i
< srcWidth
* components
; i
++) {
2515 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2517 dstRow
+= dstRowStride
;
2518 src
+= srcWidth
* components
;
2522 _mesa_free((void *) tempImage
);
2528 #if FEATURE_EXT_texture_sRGB
2530 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2532 const GLboolean littleEndian
= _mesa_little_endian();
2533 const struct gl_texture_format
*newDstFormat
;
2534 StoreTexImageFunc store
;
2537 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2539 /* reuse normal rgb texstore code */
2541 newDstFormat
= &_mesa_texformat_bgr888
;
2542 store
= _mesa_texstore_bgr888
;
2545 newDstFormat
= &_mesa_texformat_rgb888
;
2546 store
= _mesa_texstore_rgb888
;
2549 k
= store(ctx
, dims
, baseInternalFormat
,
2550 newDstFormat
, dstAddr
,
2551 dstXoffset
, dstYoffset
, dstZoffset
,
2552 dstRowStride
, dstImageOffsets
,
2553 srcWidth
, srcHeight
, srcDepth
,
2555 srcAddr
, srcPacking
);
2561 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2563 const GLboolean littleEndian
= _mesa_little_endian();
2564 const struct gl_texture_format
*newDstFormat
;
2567 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2569 /* reuse normal rgba texstore code */
2571 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2573 newDstFormat
= &_mesa_texformat_rgba8888
;
2575 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2576 newDstFormat
, dstAddr
,
2577 dstXoffset
, dstYoffset
, dstZoffset
,
2578 dstRowStride
, dstImageOffsets
,
2579 srcWidth
, srcHeight
, srcDepth
,
2581 srcAddr
, srcPacking
);
2587 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2589 const struct gl_texture_format
*newDstFormat
;
2592 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2594 newDstFormat
= &_mesa_texformat_l8
;
2596 /* _mesa_textore_a8 handles luminance8 too */
2597 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2598 newDstFormat
, dstAddr
,
2599 dstXoffset
, dstYoffset
, dstZoffset
,
2600 dstRowStride
, dstImageOffsets
,
2601 srcWidth
, srcHeight
, srcDepth
,
2603 srcAddr
, srcPacking
);
2609 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2611 const GLboolean littleEndian
= _mesa_little_endian();
2612 const struct gl_texture_format
*newDstFormat
;
2615 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2617 /* reuse normal luminance/alpha texstore code */
2619 newDstFormat
= &_mesa_texformat_al88
;
2621 newDstFormat
= &_mesa_texformat_al88_rev
;
2623 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2624 newDstFormat
, dstAddr
,
2625 dstXoffset
, dstYoffset
, dstZoffset
,
2626 dstRowStride
, dstImageOffsets
,
2627 srcWidth
, srcHeight
, srcDepth
,
2629 srcAddr
, srcPacking
);
2633 #endif /* FEATURE_EXT_texture_sRGB */
2637 * Check if an unpack PBO is active prior to fetching a texture image.
2638 * If so, do bounds checking and map the buffer into main memory.
2639 * Any errors detected will be recorded.
2640 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2643 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2644 GLsizei width
, GLsizei height
, GLsizei depth
,
2645 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2646 const struct gl_pixelstore_attrib
*unpack
,
2647 const char *funcName
)
2651 if (unpack
->BufferObj
->Name
== 0) {
2655 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2656 format
, type
, pixels
)) {
2657 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2661 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2662 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2664 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2668 return ADD_POINTERS(buf
, pixels
);
2673 * Check if an unpack PBO is active prior to fetching a compressed texture
2675 * If so, do bounds checking and map the buffer into main memory.
2676 * Any errors detected will be recorded.
2677 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2680 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2681 GLsizei imageSize
, const GLvoid
*pixels
,
2682 const struct gl_pixelstore_attrib
*packing
,
2683 const char *funcName
)
2687 if (packing
->BufferObj
->Name
== 0) {
2688 /* not using a PBO - return pointer unchanged */
2691 if ((const GLubyte
*) pixels
+ imageSize
>
2692 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2693 /* out of bounds read! */
2694 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2698 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2699 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2701 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2705 return ADD_POINTERS(buf
, pixels
);
2710 * This function must be called after either of the validate_pbo_*_teximage()
2711 * functions. It unmaps the PBO buffer if it was mapped earlier.
2714 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2715 const struct gl_pixelstore_attrib
*unpack
)
2717 if (unpack
->BufferObj
->Name
) {
2718 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2726 * Adaptor for fetching a GLchan texel from a float-valued texture.
2729 fetch_texel_float_to_chan(const struct gl_texture_image
*texImage
,
2730 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2733 ASSERT(texImage
->FetchTexelf
);
2734 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2735 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2736 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2737 /* just one channel */
2738 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2742 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2743 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2744 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2745 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2751 * Adaptor for fetching a float texel from a GLchan-valued texture.
2754 fetch_texel_chan_to_float(const struct gl_texture_image
*texImage
,
2755 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2758 ASSERT(texImage
->FetchTexelc
);
2759 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2760 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2761 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2762 /* just one channel */
2763 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2767 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2768 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2769 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2770 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2776 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2779 _mesa_set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2781 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2782 ASSERT(texImage
->TexFormat
);
2786 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2787 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2790 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2791 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2794 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2795 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2801 /* now check if we need to use a float/chan adaptor */
2802 if (!texImage
->FetchTexelc
) {
2803 texImage
->FetchTexelc
= fetch_texel_float_to_chan
;
2805 else if (!texImage
->FetchTexelf
) {
2806 texImage
->FetchTexelf
= fetch_texel_chan_to_float
;
2810 ASSERT(texImage
->FetchTexelc
);
2811 ASSERT(texImage
->FetchTexelf
);
2816 * Choose the actual storage format for a new texture image.
2817 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2818 * Also set some other texImage fields related to texture compression, etc.
2819 * \param ctx rendering context
2820 * \param texImage the gl_texture_image
2821 * \param dims texture dimensions (1, 2 or 3)
2822 * \param format the user-specified format parameter
2823 * \param type the user-specified type parameter
2824 * \param internalFormat the user-specified internal format hint
2827 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2829 GLenum format
, GLenum type
, GLint internalFormat
)
2831 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2832 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2835 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2837 ASSERT(texImage
->TexFormat
);
2839 _mesa_set_fetch_functions(texImage
, dims
);
2841 if (texImage
->TexFormat
->TexelBytes
== 0) {
2842 /* must be a compressed format */
2843 texImage
->IsCompressed
= GL_TRUE
;
2844 texImage
->CompressedSize
=
2845 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2846 texImage
->Height
, texImage
->Depth
,
2847 texImage
->TexFormat
->MesaFormat
);
2850 /* non-compressed format */
2851 texImage
->IsCompressed
= GL_FALSE
;
2852 texImage
->CompressedSize
= 0;
2859 * This is the software fallback for Driver.TexImage1D()
2860 * and Driver.CopyTexImage1D().
2861 * \sa _mesa_store_teximage2d()
2864 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2865 GLint internalFormat
,
2866 GLint width
, GLint border
,
2867 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2868 const struct gl_pixelstore_attrib
*packing
,
2869 struct gl_texture_object
*texObj
,
2870 struct gl_texture_image
*texImage
)
2872 GLint postConvWidth
= width
;
2876 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2877 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2880 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2882 /* allocate memory */
2883 if (texImage
->IsCompressed
)
2884 sizeInBytes
= texImage
->CompressedSize
;
2886 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2887 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2888 if (!texImage
->Data
) {
2889 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2893 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2894 pixels
, packing
, "glTexImage1D");
2896 /* Note: we check for a NULL image pointer here, _after_ we allocated
2897 * memory for the texture. That's what the GL spec calls for.
2902 const GLint dstRowStride
= 0;
2904 ASSERT(texImage
->TexFormat
->StoreImage
);
2905 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2906 texImage
->TexFormat
,
2908 0, 0, 0, /* dstX/Y/Zoffset */
2910 texImage
->ImageOffsets
,
2912 format
, type
, pixels
, packing
);
2914 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2918 /* GL_SGIS_generate_mipmap */
2919 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2920 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
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 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3007 _mesa_unmap_teximage_pbo(ctx
, packing
);
3013 * This is the software fallback for Driver.TexImage3D()
3014 * and Driver.CopyTexImage3D().
3015 * \sa _mesa_store_teximage2d()
3018 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3019 GLint internalFormat
,
3020 GLint width
, GLint height
, GLint depth
, GLint border
,
3021 GLenum format
, GLenum type
, const void *pixels
,
3022 const struct gl_pixelstore_attrib
*packing
,
3023 struct gl_texture_object
*texObj
,
3024 struct gl_texture_image
*texImage
)
3026 GLint texelBytes
, sizeInBytes
;
3029 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3031 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3033 /* allocate memory */
3034 if (texImage
->IsCompressed
)
3035 sizeInBytes
= texImage
->CompressedSize
;
3037 sizeInBytes
= width
* height
* depth
* texelBytes
;
3038 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3039 if (!texImage
->Data
) {
3040 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3044 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3045 type
, pixels
, packing
, "glTexImage3D");
3047 /* Note: we check for a NULL image pointer here, _after_ we allocated
3048 * memory for the texture. That's what the GL spec calls for.
3055 if (texImage
->IsCompressed
) {
3057 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3060 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3062 ASSERT(texImage
->TexFormat
->StoreImage
);
3063 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3064 texImage
->TexFormat
,
3066 0, 0, 0, /* dstX/Y/Zoffset */
3068 texImage
->ImageOffsets
,
3069 width
, height
, depth
,
3070 format
, type
, pixels
, packing
);
3072 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3076 /* GL_SGIS_generate_mipmap */
3077 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3078 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3081 _mesa_unmap_teximage_pbo(ctx
, packing
);
3088 * This is the software fallback for Driver.TexSubImage1D()
3089 * and Driver.CopyTexSubImage1D().
3092 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3093 GLint xoffset
, GLint width
,
3094 GLenum format
, GLenum type
, const void *pixels
,
3095 const struct gl_pixelstore_attrib
*packing
,
3096 struct gl_texture_object
*texObj
,
3097 struct gl_texture_image
*texImage
)
3099 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3100 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3101 pixels
, packing
, "glTexSubImage1D");
3106 const GLint dstRowStride
= 0;
3108 ASSERT(texImage
->TexFormat
->StoreImage
);
3109 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3110 texImage
->TexFormat
,
3112 xoffset
, 0, 0, /* offsets */
3114 texImage
->ImageOffsets
,
3116 format
, type
, pixels
, packing
);
3118 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3122 /* GL_SGIS_generate_mipmap */
3123 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3124 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3127 _mesa_unmap_teximage_pbo(ctx
, packing
);
3133 * This is the software fallback for Driver.TexSubImage2D()
3134 * and Driver.CopyTexSubImage2D().
3137 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3138 GLint xoffset
, GLint yoffset
,
3139 GLint width
, GLint height
,
3140 GLenum format
, GLenum type
, const void *pixels
,
3141 const struct gl_pixelstore_attrib
*packing
,
3142 struct gl_texture_object
*texObj
,
3143 struct gl_texture_image
*texImage
)
3145 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3146 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3147 pixels
, packing
, "glTexSubImage2D");
3152 GLint dstRowStride
= 0;
3154 if (texImage
->IsCompressed
) {
3155 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3159 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3161 ASSERT(texImage
->TexFormat
->StoreImage
);
3162 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3163 texImage
->TexFormat
,
3165 xoffset
, yoffset
, 0,
3167 texImage
->ImageOffsets
,
3169 format
, type
, pixels
, packing
);
3171 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3175 /* GL_SGIS_generate_mipmap */
3176 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3177 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3180 _mesa_unmap_teximage_pbo(ctx
, packing
);
3185 * This is the software fallback for Driver.TexSubImage3D().
3186 * and Driver.CopyTexSubImage3D().
3189 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3190 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3191 GLint width
, GLint height
, GLint depth
,
3192 GLenum format
, GLenum type
, const void *pixels
,
3193 const struct gl_pixelstore_attrib
*packing
,
3194 struct gl_texture_object
*texObj
,
3195 struct gl_texture_image
*texImage
)
3197 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3198 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3199 type
, pixels
, packing
,
3207 if (texImage
->IsCompressed
) {
3208 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3212 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3214 ASSERT(texImage
->TexFormat
->StoreImage
);
3215 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3216 texImage
->TexFormat
,
3218 xoffset
, yoffset
, zoffset
,
3220 texImage
->ImageOffsets
,
3221 width
, height
, depth
,
3222 format
, type
, pixels
, packing
);
3224 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3228 /* GL_SGIS_generate_mipmap */
3229 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3230 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3233 _mesa_unmap_teximage_pbo(ctx
, packing
);
3238 * Fallback for Driver.CompressedTexImage1D()
3241 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3242 GLint internalFormat
,
3243 GLint width
, GLint border
,
3244 GLsizei imageSize
, const GLvoid
*data
,
3245 struct gl_texture_object
*texObj
,
3246 struct gl_texture_image
*texImage
)
3248 /* this space intentionally left blank */
3250 (void) target
; (void) level
;
3251 (void) internalFormat
;
3252 (void) width
; (void) border
;
3253 (void) imageSize
; (void) data
;
3261 * Fallback for Driver.CompressedTexImage2D()
3264 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3265 GLint internalFormat
,
3266 GLint width
, GLint height
, GLint border
,
3267 GLsizei imageSize
, const GLvoid
*data
,
3268 struct gl_texture_object
*texObj
,
3269 struct gl_texture_image
*texImage
)
3271 (void) width
; (void) height
; (void) border
;
3273 /* This is pretty simple, basically just do a memcpy without worrying
3274 * about the usual image unpacking or image transfer operations.
3278 ASSERT(texImage
->Width
> 0);
3279 ASSERT(texImage
->Height
> 0);
3280 ASSERT(texImage
->Depth
== 1);
3281 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3283 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3285 /* allocate storage */
3286 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3287 if (!texImage
->Data
) {
3288 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3292 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3294 "glCompressedTexImage2D");
3299 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3300 MEMCPY(texImage
->Data
, data
, imageSize
);
3302 /* GL_SGIS_generate_mipmap */
3303 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3304 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3307 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3313 * Fallback for Driver.CompressedTexImage3D()
3316 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3317 GLint internalFormat
,
3318 GLint width
, GLint height
, GLint depth
,
3320 GLsizei imageSize
, const GLvoid
*data
,
3321 struct gl_texture_object
*texObj
,
3322 struct gl_texture_image
*texImage
)
3324 /* this space intentionally left blank */
3326 (void) target
; (void) level
;
3327 (void) internalFormat
;
3328 (void) width
; (void) height
; (void) depth
;
3330 (void) imageSize
; (void) data
;
3338 * Fallback for Driver.CompressedTexSubImage1D()
3341 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3343 GLint xoffset
, GLsizei width
,
3345 GLsizei imageSize
, const GLvoid
*data
,
3346 struct gl_texture_object
*texObj
,
3347 struct gl_texture_image
*texImage
)
3349 /* there are no compressed 1D texture formats yet */
3351 (void) target
; (void) level
;
3352 (void) xoffset
; (void) width
;
3354 (void) imageSize
; (void) data
;
3361 * Fallback for Driver.CompressedTexSubImage2D()
3364 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3366 GLint xoffset
, GLint yoffset
,
3367 GLsizei width
, GLsizei height
,
3369 GLsizei imageSize
, const GLvoid
*data
,
3370 struct gl_texture_object
*texObj
,
3371 struct gl_texture_image
*texImage
)
3373 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3377 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3381 /* these should have been caught sooner */
3382 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3383 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3384 ASSERT((xoffset
& 3) == 0);
3385 ASSERT((yoffset
& 3) == 0);
3387 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3388 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3390 "glCompressedTexSubImage2D");
3394 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3395 src
= (const GLubyte
*) data
;
3397 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3398 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3399 texImage
->TexFormat
->MesaFormat
,
3401 (GLubyte
*) texImage
->Data
);
3403 bytesPerRow
= srcRowStride
;
3406 for (i
= 0; i
< rows
; i
++) {
3407 MEMCPY(dest
, src
, bytesPerRow
);
3408 dest
+= destRowStride
;
3409 src
+= srcRowStride
;
3412 /* GL_SGIS_generate_mipmap */
3413 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3414 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
3417 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3422 * Fallback for Driver.CompressedTexSubImage3D()
3425 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3427 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3428 GLsizei width
, GLsizei height
, GLsizei depth
,
3430 GLsizei imageSize
, const GLvoid
*data
,
3431 struct gl_texture_object
*texObj
,
3432 struct gl_texture_image
*texImage
)
3434 /* there are no compressed 3D texture formats yet */
3436 (void) target
; (void) level
;
3437 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3438 (void) width
; (void) height
; (void) depth
;
3440 (void) imageSize
; (void) data
;
3448 #if FEATURE_EXT_texture_sRGB
3451 * Test if given texture image is an sRGB format.
3454 is_srgb_teximage(const struct gl_texture_image
*texImage
)
3456 switch (texImage
->TexFormat
->MesaFormat
) {
3457 case MESA_FORMAT_SRGB8
:
3458 case MESA_FORMAT_SRGBA8
:
3459 case MESA_FORMAT_SL8
:
3460 case MESA_FORMAT_SLA8
:
3467 #endif /* FEATURE_EXT_texture_sRGB */
3471 * This is the software fallback for Driver.GetTexImage().
3472 * All error checking will have been done before this routine is called.
3475 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3476 GLenum format
, GLenum type
, GLvoid
*pixels
,
3477 struct gl_texture_object
*texObj
,
3478 struct gl_texture_image
*texImage
)
3480 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3482 if (ctx
->Pack
.BufferObj
->Name
) {
3483 /* Packing texture image into a PBO.
3484 * Map the (potentially) VRAM-based buffer into our process space so
3485 * we can write into it with the code below.
3486 * A hardware driver might use a sophisticated blit to move the
3487 * texture data to the PBO if the PBO is in VRAM along with the texture.
3489 GLubyte
*buf
= (GLubyte
*)
3490 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3491 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
3493 /* buffer is already mapped - that's an error */
3494 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3497 /* <pixels> was an offset into the PBO.
3498 * Now make it a real, client-side pointer inside the mapped region.
3500 pixels
= ADD_POINTERS(buf
, pixels
);
3508 const GLint width
= texImage
->Width
;
3509 const GLint height
= texImage
->Height
;
3510 const GLint depth
= texImage
->Depth
;
3512 for (img
= 0; img
< depth
; img
++) {
3513 for (row
= 0; row
< height
; row
++) {
3514 /* compute destination address in client memory */
3515 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3516 width
, height
, format
, type
,
3520 if (format
== GL_COLOR_INDEX
) {
3521 GLuint indexRow
[MAX_WIDTH
];
3523 /* Can't use FetchTexel here because that returns RGBA */
3524 if (texImage
->TexFormat
->IndexBits
== 8) {
3525 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3526 src
+= width
* (img
* texImage
->Height
+ row
);
3527 for (col
= 0; col
< width
; col
++) {
3528 indexRow
[col
] = src
[col
];
3531 else if (texImage
->TexFormat
->IndexBits
== 16) {
3532 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3533 src
+= width
* (img
* texImage
->Height
+ row
);
3534 for (col
= 0; col
< width
; col
++) {
3535 indexRow
[col
] = src
[col
];
3540 "Color index problem in _mesa_GetTexImage");
3542 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3543 indexRow
, &ctx
->Pack
,
3544 0 /* no image transfer */);
3546 else if (format
== GL_DEPTH_COMPONENT
) {
3547 GLfloat depthRow
[MAX_WIDTH
];
3549 for (col
= 0; col
< width
; col
++) {
3550 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3553 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3554 depthRow
, &ctx
->Pack
);
3556 else if (format
== GL_DEPTH_STENCIL_EXT
) {
3557 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3558 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
3559 src
+= width
* row
+ width
* height
* img
;
3560 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
3561 if (ctx
->Pack
.SwapBytes
) {
3562 _mesa_swap4((GLuint
*) dest
, width
);
3565 else if (format
== GL_YCBCR_MESA
) {
3566 /* No pixel transfer */
3567 const GLint rowstride
= texImage
->RowStride
;
3569 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3570 width
* sizeof(GLushort
));
3571 /* check for byte swapping */
3572 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3573 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3574 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3575 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3576 if (!ctx
->Pack
.SwapBytes
)
3577 _mesa_swap2((GLushort
*) dest
, width
);
3579 else if (ctx
->Pack
.SwapBytes
) {
3580 _mesa_swap2((GLushort
*) dest
, width
);
3583 #if FEATURE_EXT_texture_sRGB
3584 else if (is_srgb_teximage(texImage
)) {
3585 /* no pixel transfer and no non-linear to linear conversion */
3586 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
3587 const GLint rowstride
= comps
* texImage
->RowStride
;
3589 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
3590 comps
* width
* sizeof(GLubyte
));
3592 #endif /* FEATURE_EXT_texture_sRGB */
3594 /* general case: convert row to RGBA format */
3595 GLfloat rgba
[MAX_WIDTH
][4];
3597 for (col
= 0; col
< width
; col
++) {
3598 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3599 if (texImage
->TexFormat
->BaseFormat
== GL_ALPHA
) {
3600 rgba
[col
][RCOMP
] = 0.0;
3601 rgba
[col
][GCOMP
] = 0.0;
3602 rgba
[col
][BCOMP
] = 0.0;
3604 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE
) {
3605 rgba
[col
][GCOMP
] = 0.0;
3606 rgba
[col
][BCOMP
] = 0.0;
3607 rgba
[col
][ACOMP
] = 1.0;
3609 else if (texImage
->TexFormat
->BaseFormat
== GL_LUMINANCE_ALPHA
) {
3610 rgba
[col
][GCOMP
] = 0.0;
3611 rgba
[col
][BCOMP
] = 0.0;
3613 else if (texImage
->TexFormat
->BaseFormat
== GL_INTENSITY
) {
3614 rgba
[col
][GCOMP
] = 0.0;
3615 rgba
[col
][BCOMP
] = 0.0;
3616 rgba
[col
][ACOMP
] = 1.0;
3619 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
3621 &ctx
->Pack
, 0x0 /*image xfer ops*/);
3627 if (ctx
->Pack
.BufferObj
->Name
) {
3628 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3629 ctx
->Pack
.BufferObj
);
3636 * This is the software fallback for Driver.GetCompressedTexImage().
3637 * All error checking will have been done before this routine is called.
3640 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3642 const struct gl_texture_object
*texObj
,
3643 const struct gl_texture_image
*texImage
)
3647 if (ctx
->Pack
.BufferObj
->Name
) {
3648 /* pack texture image into a PBO */
3650 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3651 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
3652 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3653 "glGetCompressedTexImage(invalid PBO access)");
3656 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3658 ctx
->Pack
.BufferObj
);
3660 /* buffer is already mapped - that's an error */
3661 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3662 "glGetCompressedTexImage(PBO is mapped)");
3665 img
= ADD_POINTERS(buf
, img
);
3672 /* don't use texImage->CompressedSize since that may be padded out */
3673 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
3675 texImage
->TexFormat
->MesaFormat
);
3677 /* just memcpy, no pixelstore or pixel transfer */
3678 _mesa_memcpy(img
, texImage
->Data
, size
);
3680 if (ctx
->Pack
.BufferObj
->Name
) {
3681 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3682 ctx
->Pack
.BufferObj
);