2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
62 #include "texcompress.h"
63 #include "texformat.h"
76 * Return GL_TRUE if the given image format is one that be converted
77 * to another format by swizzling.
80 can_swizzle(GLenum logicalBaseFormat
)
82 switch (logicalBaseFormat
) {
85 case GL_LUMINANCE_ALPHA
:
119 #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
120 #define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
121 #define MAP3(x,y,z) MAP4(x, y, z, ZERO)
122 #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
125 static const struct {
128 GLubyte from_rgba
[6];
129 } mappings
[MAX_IDX
] =
139 MAP4(ZERO
, ZERO
, ZERO
, 0),
170 MAP4(0, ZERO
, ZERO
, ONE
),
176 MAP4(ZERO
, 0, ZERO
, ONE
),
182 MAP4(ZERO
, ZERO
, 0, ONE
),
208 * Convert a GL image format enum to an IDX_* value (see above).
211 get_map_idx(GLenum value
)
214 case GL_LUMINANCE
: return IDX_LUMINANCE
;
215 case GL_ALPHA
: return IDX_ALPHA
;
216 case GL_INTENSITY
: return IDX_INTENSITY
;
217 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
218 case GL_RGB
: return IDX_RGB
;
219 case GL_RGBA
: return IDX_RGBA
;
220 case GL_RED
: return IDX_RED
;
221 case GL_GREEN
: return IDX_GREEN
;
222 case GL_BLUE
: return IDX_BLUE
;
223 case GL_BGR
: return IDX_BGR
;
224 case GL_BGRA
: return IDX_BGRA
;
225 case GL_ABGR_EXT
: return IDX_ABGR
;
227 _mesa_problem(NULL
, "Unexpected inFormat");
234 * When promoting texture formats (see below) we need to compute the
235 * mapping of dest components back to source components.
236 * This function does that.
237 * \param inFormat the incoming format of the texture
238 * \param outFormat the final texture format
239 * \return map[6] a full 6-component map
242 compute_component_mapping(GLenum inFormat
, GLenum outFormat
,
245 const int inFmt
= get_map_idx(inFormat
);
246 const int outFmt
= get_map_idx(outFormat
);
247 const GLubyte
*in2rgba
= mappings
[inFmt
].to_rgba
;
248 const GLubyte
*rgba2out
= mappings
[outFmt
].from_rgba
;
251 for (i
= 0; i
< 4; i
++)
252 map
[i
] = in2rgba
[rgba2out
[i
]];
258 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
259 inFormat, _mesa_lookup_enum_by_nr(inFormat),
260 outFormat, _mesa_lookup_enum_by_nr(outFormat),
272 * Make a temporary (color) texture image with GLfloat components.
273 * Apply all needed pixel unpacking and pixel transfer operations.
274 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
275 * Suppose the user specifies GL_LUMINANCE as the internal texture format
276 * but the graphics hardware doesn't support luminance textures. So, might
277 * use an RGB hardware format instead.
278 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
280 * \param ctx the rendering context
281 * \param dims image dimensions: 1, 2 or 3
282 * \param logicalBaseFormat basic texture derived from the user's
283 * internal texture format value
284 * \param textureBaseFormat the actual basic format of the texture
285 * \param srcWidth source image width
286 * \param srcHeight source image height
287 * \param srcDepth source image depth
288 * \param srcFormat source image format
289 * \param srcType source image type
290 * \param srcAddr source image address
291 * \param srcPacking source image pixel packing
292 * \return resulting image with format = textureBaseFormat and type = GLfloat.
295 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
296 GLenum logicalBaseFormat
,
297 GLenum textureBaseFormat
,
298 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
299 GLenum srcFormat
, GLenum srcType
,
300 const GLvoid
*srcAddr
,
301 const struct gl_pixelstore_attrib
*srcPacking
)
303 GLuint transferOps
= ctx
->_ImageTransferState
;
306 ASSERT(dims
>= 1 && dims
<= 3);
308 ASSERT(logicalBaseFormat
== GL_RGBA
||
309 logicalBaseFormat
== GL_RGB
||
310 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
311 logicalBaseFormat
== GL_LUMINANCE
||
312 logicalBaseFormat
== GL_ALPHA
||
313 logicalBaseFormat
== GL_INTENSITY
||
314 logicalBaseFormat
== GL_COLOR_INDEX
||
315 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
317 ASSERT(textureBaseFormat
== GL_RGBA
||
318 textureBaseFormat
== GL_RGB
||
319 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
320 textureBaseFormat
== GL_LUMINANCE
||
321 textureBaseFormat
== GL_ALPHA
||
322 textureBaseFormat
== GL_INTENSITY
||
323 textureBaseFormat
== GL_COLOR_INDEX
||
324 textureBaseFormat
== GL_DEPTH_COMPONENT
);
326 /* conventional color image */
328 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
329 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
330 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
331 /* need image convolution */
332 const GLuint preConvTransferOps
333 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
334 const GLuint postConvTransferOps
335 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
337 GLint convWidth
, convHeight
;
340 /* pre-convolution image buffer (3D) */
341 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
342 * 4 * sizeof(GLfloat
));
346 /* post-convolution image buffer (2D) */
347 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
348 * 4 * sizeof(GLfloat
));
350 _mesa_free(tempImage
);
354 /* loop over 3D image slices */
355 for (img
= 0; img
< srcDepth
; img
++) {
356 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
358 /* unpack and do transfer ops up to convolution */
359 for (row
= 0; row
< srcHeight
; row
++) {
360 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
361 srcAddr
, srcWidth
, srcHeight
,
362 srcFormat
, srcType
, img
, row
, 0);
363 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
364 srcFormat
, srcType
, src
,
372 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
373 convWidth
= srcWidth
;
374 convHeight
= srcHeight
;
376 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
377 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
380 if (ctx
->Pixel
.Convolution2DEnabled
) {
381 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
385 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
386 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
392 /* do post-convolution transfer and pack into tempImage */
394 const GLint logComponents
395 = _mesa_components_in_format(logicalBaseFormat
);
396 const GLfloat
*src
= convImage
;
397 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
398 for (row
= 0; row
< convHeight
; row
++) {
399 _mesa_pack_rgba_span_float(ctx
, convWidth
,
400 (const GLfloat (*)[4]) src
,
401 logicalBaseFormat
, GL_FLOAT
,
402 dst
, &ctx
->DefaultPacking
,
403 postConvTransferOps
);
404 src
+= convWidth
* 4;
405 dst
+= convWidth
* logComponents
;
408 } /* loop over 3D image slices */
410 _mesa_free(convImage
);
412 /* might need these below */
413 srcWidth
= convWidth
;
414 srcHeight
= convHeight
;
418 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
419 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
420 srcWidth
, srcFormat
, srcType
);
424 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
425 * components
* sizeof(GLfloat
));
430 for (img
= 0; img
< srcDepth
; img
++) {
432 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
436 for (row
= 0; row
< srcHeight
; row
++) {
437 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
438 dst
, srcFormat
, srcType
, src
,
439 srcPacking
, transferOps
);
440 dst
+= srcWidth
* components
;
446 if (logicalBaseFormat
!= textureBaseFormat
) {
448 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
449 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
454 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
455 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
456 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
458 /* The actual texture format should have at least as many components
459 * as the logical texture format.
461 ASSERT(texComponents
>= logComponents
);
463 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
464 * texComponents
* sizeof(GLfloat
));
466 _mesa_free(tempImage
);
470 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
472 n
= srcWidth
* srcHeight
* srcDepth
;
473 for (i
= 0; i
< n
; i
++) {
475 for (k
= 0; k
< texComponents
; k
++) {
478 newImage
[i
* texComponents
+ k
] = 0.0F
;
480 newImage
[i
* texComponents
+ k
] = 1.0F
;
482 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
486 _mesa_free(tempImage
);
487 tempImage
= newImage
;
495 * Make a temporary (color) texture image with GLchan components.
496 * Apply all needed pixel unpacking and pixel transfer operations.
497 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
498 * Suppose the user specifies GL_LUMINANCE as the internal texture format
499 * but the graphics hardware doesn't support luminance textures. So, might
500 * use an RGB hardware format instead.
501 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
503 * \param ctx the rendering context
504 * \param dims image dimensions: 1, 2 or 3
505 * \param logicalBaseFormat basic texture derived from the user's
506 * internal texture format value
507 * \param textureBaseFormat the actual basic format of the texture
508 * \param srcWidth source image width
509 * \param srcHeight source image height
510 * \param srcDepth source image depth
511 * \param srcFormat source image format
512 * \param srcType source image type
513 * \param srcAddr source image address
514 * \param srcPacking source image pixel packing
515 * \return resulting image with format = textureBaseFormat and type = GLchan.
518 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
519 GLenum logicalBaseFormat
,
520 GLenum textureBaseFormat
,
521 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
522 GLenum srcFormat
, GLenum srcType
,
523 const GLvoid
*srcAddr
,
524 const struct gl_pixelstore_attrib
*srcPacking
)
526 GLuint transferOps
= ctx
->_ImageTransferState
;
527 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
528 GLboolean freeSrcImage
= GL_FALSE
;
530 GLchan
*tempImage
, *dst
;
532 ASSERT(dims
>= 1 && dims
<= 3);
534 ASSERT(logicalBaseFormat
== GL_RGBA
||
535 logicalBaseFormat
== GL_RGB
||
536 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
537 logicalBaseFormat
== GL_LUMINANCE
||
538 logicalBaseFormat
== GL_ALPHA
||
539 logicalBaseFormat
== GL_INTENSITY
);
541 ASSERT(textureBaseFormat
== GL_RGBA
||
542 textureBaseFormat
== GL_RGB
||
543 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
544 textureBaseFormat
== GL_LUMINANCE
||
545 textureBaseFormat
== GL_ALPHA
||
546 textureBaseFormat
== GL_INTENSITY
);
548 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
549 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
550 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
551 /* get convolved image */
552 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
555 srcWidth
, srcHeight
, srcDepth
,
557 srcAddr
, srcPacking
);
560 /* the convolved image is our new source image */
562 srcFormat
= logicalBaseFormat
;
564 srcPacking
= &ctx
->DefaultPacking
;
565 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
567 freeSrcImage
= GL_TRUE
;
570 /* unpack and transfer the source image */
571 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
572 * components
* sizeof(GLchan
));
577 for (img
= 0; img
< srcDepth
; img
++) {
578 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
582 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
586 for (row
= 0; row
< srcHeight
; row
++) {
587 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
588 srcFormat
, srcType
, src
, srcPacking
,
590 dst
+= srcWidth
* components
;
595 /* If we made a temporary image for convolution, free it here */
597 _mesa_free((void *) srcAddr
);
600 if (logicalBaseFormat
!= textureBaseFormat
) {
601 /* one more conversion step */
602 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
603 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
608 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
609 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
610 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
612 /* The actual texture format should have at least as many components
613 * as the logical texture format.
615 ASSERT(texComponents
>= logComponents
);
617 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
618 * texComponents
* sizeof(GLchan
));
620 _mesa_free(tempImage
);
624 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
626 n
= srcWidth
* srcHeight
* srcDepth
;
627 for (i
= 0; i
< n
; i
++) {
629 for (k
= 0; k
< texComponents
; k
++) {
632 newImage
[i
* texComponents
+ k
] = 0;
634 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
636 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
640 _mesa_free(tempImage
);
641 tempImage
= newImage
;
649 * Copy GLubyte pixels from <src> to <dst> with swizzling.
650 * \param dst destination pixels
651 * \param dstComponents number of color components in destination pixels
652 * \param src source pixels
653 * \param srcComponents number of color components in source pixels
654 * \param map the swizzle mapping. map[X] says where to find the X component
655 * in the source image's pixels. For example, if the source image
656 * is GL_BGRA and X = red, map[0] yields 2.
657 * \param count number of pixels to copy/swizzle.
660 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
661 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
669 switch (dstComponents
) {
671 for (i
= 0; i
< count
; i
++) {
673 src
+= srcComponents
;
674 dst
[0] = tmp
[map
[0]];
675 dst
[1] = tmp
[map
[1]];
676 dst
[2] = tmp
[map
[2]];
677 dst
[3] = tmp
[map
[3]];
682 for (i
= 0; i
< count
; i
++) {
684 src
+= srcComponents
;
685 dst
[0] = tmp
[map
[0]];
686 dst
[1] = tmp
[map
[1]];
687 dst
[2] = tmp
[map
[2]];
692 for (i
= 0; i
< count
; i
++) {
694 src
+= srcComponents
;
695 dst
[0] = tmp
[map
[0]];
696 dst
[1] = tmp
[map
[1]];
701 for (i
= 0; i
< count
; i
++) {
703 src
+= srcComponents
;
704 dst
[0] = tmp
[map
[0]];
712 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
713 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
715 /* Deal with the _REV input types:
717 static const GLubyte
*
718 type_mapping( GLenum srcType
)
721 case GL_UNSIGNED_BYTE
:
723 case GL_UNSIGNED_INT_8_8_8_8
:
725 case GL_UNSIGNED_INT_8_8_8_8_REV
:
732 /* Mapping required if input type is
734 static const GLubyte
*
735 byteswap_mapping( GLboolean swapBytes
,
742 case GL_UNSIGNED_BYTE
:
744 case GL_UNSIGNED_INT_8_8_8_8
:
745 case GL_UNSIGNED_INT_8_8_8_8_REV
:
755 * Transfer a GLubyte texture image with component swizzling.
758 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
763 GLenum baseInternalFormat
,
765 const GLubyte
*rgba2dst
,
766 GLuint dstComponents
,
769 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
771 const GLuint
*dstImageOffsets
,
773 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
774 const GLvoid
*srcAddr
,
775 const struct gl_pixelstore_attrib
*srcPacking
)
777 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
778 const GLubyte
*srctype2ubyte
, *swap
;
779 GLubyte map
[4], src2base
[6], base2rgba
[6];
781 const GLint srcRowStride
=
782 _mesa_image_row_stride(srcPacking
, srcWidth
,
783 srcFormat
, GL_UNSIGNED_BYTE
);
784 const GLint srcImageStride
785 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
787 const GLubyte
*srcImage
788 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
789 srcWidth
, srcHeight
, srcFormat
,
790 GL_UNSIGNED_BYTE
, 0, 0, 0);
794 /* Translate from src->baseInternal->GL_RGBA->dst. This will
795 * correctly deal with RGBA->RGB->RGBA conversions where the final
796 * A value must be 0xff regardless of the incoming alpha values.
798 compute_component_mapping(srcFormat
, baseInternalFormat
, src2base
);
799 compute_component_mapping(baseInternalFormat
, GL_RGBA
, base2rgba
);
800 swap
= byteswap_mapping(srcPacking
->SwapBytes
, srcType
);
801 srctype2ubyte
= type_mapping(srcType
);
804 for (i
= 0; i
< 4; i
++)
805 map
[i
] = srctype2ubyte
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
807 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
809 if (srcRowStride
== srcWidth
* srcComponents
&&
811 /* 1 and 2D images only */
812 GLubyte
*dstImage
= (GLubyte
*) dstAddr
813 + dstYoffset
* dstRowStride
814 + dstXoffset
* dstComponents
;
815 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
816 srcWidth
* srcHeight
);
820 for (img
= 0; img
< srcDepth
; img
++) {
821 const GLubyte
*srcRow
= srcImage
;
822 GLubyte
*dstRow
= (GLubyte
*) dstAddr
823 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
824 + dstYoffset
* dstRowStride
825 + dstXoffset
* dstComponents
;
826 for (row
= 0; row
< srcHeight
; row
++) {
827 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
828 dstRow
+= dstRowStride
;
829 srcRow
+= srcRowStride
;
831 srcImage
+= srcImageStride
;
838 * Teximage storage routine for when a simple memcpy will do.
839 * No pixel transfer operations or special texel encodings allowed.
840 * 1D, 2D and 3D images supported.
843 memcpy_texture(GLcontext
*ctx
,
845 const struct gl_texture_format
*dstFormat
,
847 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
849 const GLuint
*dstImageOffsets
,
850 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
851 GLenum srcFormat
, GLenum srcType
,
852 const GLvoid
*srcAddr
,
853 const struct gl_pixelstore_attrib
*srcPacking
)
855 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
857 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
858 srcWidth
, srcHeight
, srcFormat
, srcType
);
859 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
860 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
861 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
864 /* XXX update/re-enable for dstImageOffsets array */
865 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
866 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
867 GLubyte
*dstImage
= (GLubyte
*) dstAddr
868 + dstZoffset
* dstImageStride
869 + dstYoffset
* dstRowStride
870 + dstXoffset
* dstFormat
->TexelBytes
;
872 if (dstRowStride
== srcRowStride
&&
873 dstRowStride
== bytesPerRow
&&
874 ((dstImageStride
== srcImageStride
&&
875 dstImageStride
== bytesPerImage
) ||
878 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
883 for (img
= 0; img
< srcDepth
; img
++) {
884 const GLubyte
*srcRow
= srcImage
;
885 GLubyte
*dstRow
= dstImage
;
886 for (row
= 0; row
< srcHeight
; row
++) {
887 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
888 dstRow
+= dstRowStride
;
889 srcRow
+= srcRowStride
;
891 srcImage
+= srcImageStride
;
892 dstImage
+= dstImageStride
;
898 for (img
= 0; img
< srcDepth
; img
++) {
899 const GLubyte
*srcRow
= srcImage
;
900 GLubyte
*dstRow
= (GLubyte
*) dstAddr
901 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
902 + dstYoffset
* dstRowStride
903 + dstXoffset
* dstFormat
->TexelBytes
;
904 for (row
= 0; row
< srcHeight
; row
++) {
905 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
906 dstRow
+= dstRowStride
;
907 srcRow
+= srcRowStride
;
909 srcImage
+= srcImageStride
;
916 * Store an image in any of the formats:
917 * _mesa_texformat_rgba
918 * _mesa_texformat_rgb
919 * _mesa_texformat_alpha
920 * _mesa_texformat_luminance
921 * _mesa_texformat_luminance_alpha
922 * _mesa_texformat_intensity
926 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
928 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
930 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
931 dstFormat
== &_mesa_texformat_rgb
||
932 dstFormat
== &_mesa_texformat_alpha
||
933 dstFormat
== &_mesa_texformat_luminance
||
934 dstFormat
== &_mesa_texformat_luminance_alpha
||
935 dstFormat
== &_mesa_texformat_intensity
);
936 ASSERT(baseInternalFormat
== GL_RGBA
||
937 baseInternalFormat
== GL_RGB
||
938 baseInternalFormat
== GL_ALPHA
||
939 baseInternalFormat
== GL_LUMINANCE
||
940 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
941 baseInternalFormat
== GL_INTENSITY
);
942 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
944 if (!ctx
->_ImageTransferState
&&
945 !srcPacking
->SwapBytes
&&
946 baseInternalFormat
== srcFormat
&&
947 srcType
== CHAN_TYPE
) {
948 /* simple memcpy path */
949 memcpy_texture(ctx
, dims
,
950 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
953 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
954 srcAddr
, srcPacking
);
956 else if (!ctx
->_ImageTransferState
&&
957 !srcPacking
->SwapBytes
&&
958 dstFormat
== &_mesa_texformat_rgb
&&
959 srcFormat
== GL_RGBA
&&
960 srcType
== CHAN_TYPE
) {
961 /* extract RGB from RGBA */
963 for (img
= 0; img
< srcDepth
; img
++) {
964 GLchan
*dstImage
= (GLchan
*)
966 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
967 + dstYoffset
* dstRowStride
968 + dstXoffset
* dstFormat
->TexelBytes
);
970 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
971 srcWidth
, srcFormat
, srcType
);
972 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
973 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
974 GLchan
*dstRow
= dstImage
;
975 for (row
= 0; row
< srcHeight
; row
++) {
976 for (col
= 0; col
< srcWidth
; col
++) {
977 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
978 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
979 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
981 dstRow
+= dstRowStride
/ sizeof(GLchan
);
982 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
986 else if (!ctx
->_ImageTransferState
&&
987 _mesa_little_endian() &&
988 CHAN_TYPE
== GL_UNSIGNED_BYTE
&&
989 (srcType
== GL_UNSIGNED_BYTE
||
990 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
991 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
992 can_swizzle(baseInternalFormat
) &&
993 can_swizzle(srcFormat
)) {
995 const GLubyte
*dstmap
;
998 /* dstmap - how to swizzle from RGBA to dst format:
1000 if (dstFormat
== &_mesa_texformat_rgba
) {
1001 dstmap
= mappings
[IDX_RGBA
].from_rgba
;
1004 else if (dstFormat
== &_mesa_texformat_rgb
) {
1005 dstmap
= mappings
[IDX_RGB
].from_rgba
;
1008 else if (dstFormat
== &_mesa_texformat_alpha
) {
1009 dstmap
= mappings
[IDX_ALPHA
].from_rgba
;
1012 else if (dstFormat
== &_mesa_texformat_luminance
) {
1013 dstmap
= mappings
[IDX_LUMINANCE
].from_rgba
;
1016 else if (dstFormat
== &_mesa_texformat_luminance_alpha
) {
1017 dstmap
= mappings
[IDX_LUMINANCE_ALPHA
].from_rgba
;
1020 else if (dstFormat
== &_mesa_texformat_intensity
) {
1021 dstmap
= mappings
[IDX_INTENSITY
].from_rgba
;
1025 _mesa_problem(ctx
, "Unexpected dstFormat in _mesa_texstore_rgba");
1029 _mesa_swizzle_ubyte_image(ctx
, dims
,
1034 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1035 dstRowStride
, dstImageOffsets
,
1036 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1041 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1043 dstFormat
->BaseFormat
,
1044 srcWidth
, srcHeight
, srcDepth
,
1045 srcFormat
, srcType
, srcAddr
,
1047 const GLchan
*src
= tempImage
;
1052 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1053 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
1054 for (img
= 0; img
< srcDepth
; img
++) {
1055 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1056 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1057 + dstYoffset
* dstRowStride
1058 + dstXoffset
* dstFormat
->TexelBytes
;
1059 for (row
= 0; row
< srcHeight
; row
++) {
1060 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
1061 dstRow
+= dstRowStride
;
1062 src
+= srcWidth
* components
;
1066 _mesa_free((void *) tempImage
);
1073 * Store a 32-bit integer depth component texture image.
1076 _mesa_texstore_z32(TEXSTORE_PARAMS
)
1078 const GLfloat depthScale
= (GLfloat
) 0xffffffff;
1080 ASSERT(dstFormat
== &_mesa_texformat_z32
);
1081 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
1083 if (!ctx
->_ImageTransferState
&&
1084 !srcPacking
->SwapBytes
&&
1085 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1086 srcFormat
== GL_DEPTH_COMPONENT
&&
1087 srcType
== GL_UNSIGNED_INT
) {
1088 /* simple memcpy path */
1089 memcpy_texture(ctx
, dims
,
1090 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1093 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1094 srcAddr
, srcPacking
);
1099 for (img
= 0; img
< srcDepth
; img
++) {
1100 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1101 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1102 + dstYoffset
* dstRowStride
1103 + dstXoffset
* dstFormat
->TexelBytes
;
1104 for (row
= 0; row
< srcHeight
; row
++) {
1105 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1106 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1107 _mesa_unpack_depth_span(ctx
, srcWidth
,
1108 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1109 depthScale
, srcType
, src
, srcPacking
);
1110 dstRow
+= dstRowStride
;
1120 * Store a 16-bit integer depth component texture image.
1123 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1125 const GLfloat depthScale
= 65535.0f
;
1127 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1128 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1130 if (!ctx
->_ImageTransferState
&&
1131 !srcPacking
->SwapBytes
&&
1132 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1133 srcFormat
== GL_DEPTH_COMPONENT
&&
1134 srcType
== GL_UNSIGNED_SHORT
) {
1135 /* simple memcpy path */
1136 memcpy_texture(ctx
, dims
,
1137 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1140 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1141 srcAddr
, srcPacking
);
1146 for (img
= 0; img
< srcDepth
; img
++) {
1147 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1148 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1149 + dstYoffset
* dstRowStride
1150 + dstXoffset
* dstFormat
->TexelBytes
;
1151 for (row
= 0; row
< srcHeight
; row
++) {
1152 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1153 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1154 GLushort
*dst16
= (GLushort
*) dstRow
;
1155 _mesa_unpack_depth_span(ctx
, srcWidth
,
1156 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1157 srcType
, src
, srcPacking
);
1158 dstRow
+= dstRowStride
;
1167 * Store an rgb565 or rgb565_rev texture image.
1170 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1172 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1173 dstFormat
== &_mesa_texformat_rgb565_rev
);
1174 ASSERT(dstFormat
->TexelBytes
== 2);
1176 if (!ctx
->_ImageTransferState
&&
1177 !srcPacking
->SwapBytes
&&
1178 dstFormat
== &_mesa_texformat_rgb565
&&
1179 baseInternalFormat
== GL_RGB
&&
1180 srcFormat
== GL_RGB
&&
1181 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1182 /* simple memcpy path */
1183 memcpy_texture(ctx
, dims
,
1184 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1187 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1188 srcAddr
, srcPacking
);
1190 else if (!ctx
->_ImageTransferState
&&
1191 !srcPacking
->SwapBytes
&&
1192 baseInternalFormat
== GL_RGB
&&
1193 srcFormat
== GL_RGB
&&
1194 srcType
== GL_UNSIGNED_BYTE
&&
1196 /* do optimized tex store */
1197 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1198 srcFormat
, srcType
);
1199 const GLubyte
*src
= (const GLubyte
*)
1200 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1201 srcFormat
, srcType
, 0, 0, 0);
1202 GLubyte
*dst
= (GLubyte
*) dstAddr
1203 + dstYoffset
* dstRowStride
1204 + dstXoffset
* dstFormat
->TexelBytes
;
1206 for (row
= 0; row
< srcHeight
; row
++) {
1207 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1208 GLushort
*dstUS
= (GLushort
*) dst
;
1209 /* check for byteswapped format */
1210 if (dstFormat
== &_mesa_texformat_rgb565
) {
1211 for (col
= 0; col
< srcWidth
; col
++) {
1212 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1217 for (col
= 0; col
< srcWidth
; col
++) {
1218 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1222 dst
+= dstRowStride
;
1223 src
+= srcRowStride
;
1228 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1230 dstFormat
->BaseFormat
,
1231 srcWidth
, srcHeight
, srcDepth
,
1232 srcFormat
, srcType
, srcAddr
,
1234 const GLchan
*src
= tempImage
;
1235 GLint img
, row
, col
;
1238 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1239 for (img
= 0; img
< srcDepth
; img
++) {
1240 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1241 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1242 + dstYoffset
* dstRowStride
1243 + dstXoffset
* dstFormat
->TexelBytes
;
1244 for (row
= 0; row
< srcHeight
; row
++) {
1245 GLushort
*dstUS
= (GLushort
*) dstRow
;
1246 /* check for byteswapped format */
1247 if (dstFormat
== &_mesa_texformat_rgb565
) {
1248 for (col
= 0; col
< srcWidth
; col
++) {
1249 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1250 CHAN_TO_UBYTE(src
[GCOMP
]),
1251 CHAN_TO_UBYTE(src
[BCOMP
]) );
1256 for (col
= 0; col
< srcWidth
; col
++) {
1257 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1258 CHAN_TO_UBYTE(src
[GCOMP
]),
1259 CHAN_TO_UBYTE(src
[BCOMP
]) );
1263 dstRow
+= dstRowStride
;
1266 _mesa_free((void *) tempImage
);
1273 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1276 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1278 const GLboolean littleEndian
= _mesa_little_endian();
1280 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1281 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1282 ASSERT(dstFormat
->TexelBytes
== 4);
1284 if (!ctx
->_ImageTransferState
&&
1285 !srcPacking
->SwapBytes
&&
1286 dstFormat
== &_mesa_texformat_rgba8888
&&
1287 baseInternalFormat
== GL_RGBA
&&
1288 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1289 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1290 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1291 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1292 /* simple memcpy path */
1293 memcpy_texture(ctx
, dims
,
1294 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1297 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1298 srcAddr
, srcPacking
);
1300 else if (!ctx
->_ImageTransferState
&&
1301 !srcPacking
->SwapBytes
&&
1302 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1303 baseInternalFormat
== GL_RGBA
&&
1304 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1305 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1306 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1307 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1308 /* simple memcpy path */
1309 memcpy_texture(ctx
, dims
,
1310 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1313 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1314 srcAddr
, srcPacking
);
1316 else if (!ctx
->_ImageTransferState
&&
1318 (srcType
== GL_UNSIGNED_BYTE
||
1319 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1320 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1321 can_swizzle(baseInternalFormat
) &&
1322 can_swizzle(srcFormat
)) {
1326 /* dstmap - how to swizzle from RGBA to dst format:
1328 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1341 _mesa_swizzle_ubyte_image(ctx
, dims
,
1346 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1347 dstRowStride
, dstImageOffsets
,
1348 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1353 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1355 dstFormat
->BaseFormat
,
1356 srcWidth
, srcHeight
, srcDepth
,
1357 srcFormat
, srcType
, srcAddr
,
1359 const GLchan
*src
= tempImage
;
1360 GLint img
, row
, col
;
1363 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1364 for (img
= 0; img
< srcDepth
; img
++) {
1365 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1366 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1367 + dstYoffset
* dstRowStride
1368 + dstXoffset
* dstFormat
->TexelBytes
;
1369 for (row
= 0; row
< srcHeight
; row
++) {
1370 GLuint
*dstUI
= (GLuint
*) dstRow
;
1371 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1372 for (col
= 0; col
< srcWidth
; col
++) {
1373 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1374 CHAN_TO_UBYTE(src
[GCOMP
]),
1375 CHAN_TO_UBYTE(src
[BCOMP
]),
1376 CHAN_TO_UBYTE(src
[ACOMP
]) );
1381 for (col
= 0; col
< srcWidth
; col
++) {
1382 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1383 CHAN_TO_UBYTE(src
[GCOMP
]),
1384 CHAN_TO_UBYTE(src
[BCOMP
]),
1385 CHAN_TO_UBYTE(src
[ACOMP
]) );
1389 dstRow
+= dstRowStride
;
1392 _mesa_free((void *) tempImage
);
1399 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1401 const GLboolean littleEndian
= _mesa_little_endian();
1403 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1404 dstFormat
== &_mesa_texformat_argb8888_rev
);
1405 ASSERT(dstFormat
->TexelBytes
== 4);
1407 if (!ctx
->_ImageTransferState
&&
1408 !srcPacking
->SwapBytes
&&
1409 dstFormat
== &_mesa_texformat_argb8888
&&
1410 baseInternalFormat
== GL_RGBA
&&
1411 srcFormat
== GL_BGRA
&&
1412 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1413 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1414 /* simple memcpy path (little endian) */
1415 memcpy_texture(ctx
, dims
,
1416 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1419 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1420 srcAddr
, srcPacking
);
1422 else if (!ctx
->_ImageTransferState
&&
1423 !srcPacking
->SwapBytes
&&
1424 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1425 baseInternalFormat
== GL_RGBA
&&
1426 srcFormat
== GL_BGRA
&&
1427 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1428 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1429 /* simple memcpy path (big endian) */
1430 memcpy_texture(ctx
, dims
,
1431 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1434 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1435 srcAddr
, srcPacking
);
1437 else if (!ctx
->_ImageTransferState
&&
1438 !srcPacking
->SwapBytes
&&
1439 dstFormat
== &_mesa_texformat_argb8888
&&
1440 srcFormat
== GL_RGB
&&
1441 (baseInternalFormat
== GL_RGBA
||
1442 baseInternalFormat
== GL_RGB
) &&
1443 srcType
== GL_UNSIGNED_BYTE
) {
1446 for (img
= 0; img
< srcDepth
; img
++) {
1447 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1448 srcWidth
, srcFormat
, srcType
);
1449 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1450 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1451 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1452 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1453 + dstYoffset
* dstRowStride
1454 + dstXoffset
* dstFormat
->TexelBytes
;
1455 for (row
= 0; row
< srcHeight
; row
++) {
1456 for (col
= 0; col
< srcWidth
; col
++) {
1457 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1458 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1459 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1460 dstRow
[col
* 4 + 3] = 0xff;
1462 dstRow
+= dstRowStride
;
1463 srcRow
+= srcRowStride
;
1467 else if (!ctx
->_ImageTransferState
&&
1468 !srcPacking
->SwapBytes
&&
1469 dstFormat
== &_mesa_texformat_argb8888
&&
1470 srcFormat
== GL_RGBA
&&
1471 baseInternalFormat
== GL_RGBA
&&
1472 (srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
1473 GLint img
, row
, col
;
1474 /* For some reason, streaming copies to write-combined regions
1475 * are extremely sensitive to the characteristics of how the
1476 * source data is retrieved. By reordering the source reads to
1477 * be in-order, the speed of this operation increases by half.
1478 * Strangely the same isn't required for the RGB path, above.
1480 for (img
= 0; img
< srcDepth
; img
++) {
1481 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1482 srcWidth
, srcFormat
, srcType
);
1483 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1484 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1485 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1486 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1487 + dstYoffset
* dstRowStride
1488 + dstXoffset
* dstFormat
->TexelBytes
;
1490 for (row
= 0; row
< srcHeight
; row
++) {
1491 for (col
= 0; col
< srcWidth
; col
++) {
1492 *(GLuint
*)(dstRow
+ col
* 4) = (srcRow
[col
* 4 + RCOMP
] << 16 |
1493 srcRow
[col
* 4 + GCOMP
] << 8 |
1494 srcRow
[col
* 4 + BCOMP
] << 0 |
1495 srcRow
[col
* 4 + ACOMP
] << 24);
1497 dstRow
+= dstRowStride
;
1498 srcRow
+= srcRowStride
;
1502 else if (!ctx
->_ImageTransferState
&&
1503 !srcPacking
->SwapBytes
&&
1504 dstFormat
== &_mesa_texformat_argb8888
&&
1505 srcFormat
== GL_RGBA
&&
1506 baseInternalFormat
== GL_RGBA
&&
1507 srcType
== GL_UNSIGNED_BYTE
) {
1509 GLint img
, row
, col
;
1510 for (img
= 0; img
< srcDepth
; img
++) {
1511 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1512 srcWidth
, srcFormat
, srcType
);
1513 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1514 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1515 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1516 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1517 + dstYoffset
* dstRowStride
1518 + dstXoffset
* dstFormat
->TexelBytes
;
1519 for (row
= 0; row
< srcHeight
; row
++) {
1520 for (col
= 0; col
< srcWidth
; col
++) {
1521 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1522 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1523 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1524 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1526 dstRow
+= dstRowStride
;
1527 srcRow
+= srcRowStride
;
1531 else if (!ctx
->_ImageTransferState
&&
1533 (srcType
== GL_UNSIGNED_BYTE
||
1534 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1535 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1536 can_swizzle(baseInternalFormat
) &&
1537 can_swizzle(srcFormat
)) {
1541 /* dstmap - how to swizzle from RGBA to dst format:
1543 if (dstFormat
== &_mesa_texformat_argb8888
) {
1544 dstmap
[3] = 3; /* alpha */
1545 dstmap
[2] = 0; /* red */
1546 dstmap
[1] = 1; /* green */
1547 dstmap
[0] = 2; /* blue */
1550 assert(dstFormat
== &_mesa_texformat_argb8888_rev
);
1557 _mesa_swizzle_ubyte_image(ctx
, dims
,
1563 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1566 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1571 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1573 dstFormat
->BaseFormat
,
1574 srcWidth
, srcHeight
, srcDepth
,
1575 srcFormat
, srcType
, srcAddr
,
1577 const GLchan
*src
= tempImage
;
1578 GLint img
, row
, col
;
1581 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1582 for (img
= 0; img
< srcDepth
; img
++) {
1583 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1584 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1585 + dstYoffset
* dstRowStride
1586 + dstXoffset
* dstFormat
->TexelBytes
;
1587 for (row
= 0; row
< srcHeight
; row
++) {
1588 GLuint
*dstUI
= (GLuint
*) dstRow
;
1589 if (dstFormat
== &_mesa_texformat_argb8888
) {
1590 for (col
= 0; col
< srcWidth
; col
++) {
1591 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1592 CHAN_TO_UBYTE(src
[RCOMP
]),
1593 CHAN_TO_UBYTE(src
[GCOMP
]),
1594 CHAN_TO_UBYTE(src
[BCOMP
]) );
1599 for (col
= 0; col
< srcWidth
; col
++) {
1600 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1601 CHAN_TO_UBYTE(src
[RCOMP
]),
1602 CHAN_TO_UBYTE(src
[GCOMP
]),
1603 CHAN_TO_UBYTE(src
[BCOMP
]) );
1607 dstRow
+= dstRowStride
;
1610 _mesa_free((void *) tempImage
);
1617 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1619 const GLboolean littleEndian
= _mesa_little_endian();
1621 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1622 ASSERT(dstFormat
->TexelBytes
== 3);
1624 if (!ctx
->_ImageTransferState
&&
1625 !srcPacking
->SwapBytes
&&
1626 baseInternalFormat
== GL_RGB
&&
1627 srcFormat
== GL_BGR
&&
1628 srcType
== GL_UNSIGNED_BYTE
&&
1630 /* simple memcpy path */
1631 memcpy_texture(ctx
, dims
,
1632 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1635 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1636 srcAddr
, srcPacking
);
1638 else if (!ctx
->_ImageTransferState
&&
1639 !srcPacking
->SwapBytes
&&
1640 srcFormat
== GL_RGBA
&&
1641 srcType
== GL_UNSIGNED_BYTE
) {
1642 /* extract RGB from RGBA */
1643 GLint img
, row
, col
;
1644 for (img
= 0; img
< srcDepth
; img
++) {
1645 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1646 srcWidth
, srcFormat
, srcType
);
1647 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1648 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1649 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1650 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1651 + dstYoffset
* dstRowStride
1652 + dstXoffset
* dstFormat
->TexelBytes
;
1653 for (row
= 0; row
< srcHeight
; row
++) {
1654 for (col
= 0; col
< srcWidth
; col
++) {
1655 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1656 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1657 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1659 dstRow
+= dstRowStride
;
1660 srcRow
+= srcRowStride
;
1664 else if (!ctx
->_ImageTransferState
&&
1666 srcType
== GL_UNSIGNED_BYTE
&&
1667 can_swizzle(baseInternalFormat
) &&
1668 can_swizzle(srcFormat
)) {
1672 /* dstmap - how to swizzle from RGBA to dst format:
1677 dstmap
[3] = ONE
; /* ? */
1679 _mesa_swizzle_ubyte_image(ctx
, dims
,
1684 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1685 dstRowStride
, dstImageOffsets
,
1686 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1691 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1693 dstFormat
->BaseFormat
,
1694 srcWidth
, srcHeight
, srcDepth
,
1695 srcFormat
, srcType
, srcAddr
,
1697 const GLchan
*src
= (const GLchan
*) tempImage
;
1698 GLint img
, row
, col
;
1701 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1702 for (img
= 0; img
< srcDepth
; img
++) {
1703 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1704 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1705 + dstYoffset
* dstRowStride
1706 + dstXoffset
* dstFormat
->TexelBytes
;
1707 for (row
= 0; row
< srcHeight
; row
++) {
1710 for (col
= 0; col
< srcWidth
; col
++) {
1711 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1712 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1713 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1718 for (col
= 0; col
< srcWidth
; col
++) {
1719 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1720 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1721 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1726 for (col
= 0; col
< srcWidth
; col
++) {
1727 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1728 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1729 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1733 dstRow
+= dstRowStride
;
1736 _mesa_free((void *) tempImage
);
1743 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1745 const GLboolean littleEndian
= _mesa_little_endian();
1747 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1748 ASSERT(dstFormat
->TexelBytes
== 3);
1750 if (!ctx
->_ImageTransferState
&&
1751 !srcPacking
->SwapBytes
&&
1752 baseInternalFormat
== GL_RGB
&&
1753 srcFormat
== GL_RGB
&&
1754 srcType
== GL_UNSIGNED_BYTE
&&
1756 /* simple memcpy path */
1757 memcpy_texture(ctx
, dims
,
1758 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1761 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1762 srcAddr
, srcPacking
);
1764 else if (!ctx
->_ImageTransferState
&&
1765 !srcPacking
->SwapBytes
&&
1766 srcFormat
== GL_RGBA
&&
1767 srcType
== GL_UNSIGNED_BYTE
) {
1768 /* extract BGR from RGBA */
1770 for (img
= 0; img
< srcDepth
; img
++) {
1771 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1772 srcWidth
, srcFormat
, srcType
);
1773 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1774 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1775 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1776 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1777 + dstYoffset
* dstRowStride
1778 + dstXoffset
* dstFormat
->TexelBytes
;
1779 for (row
= 0; row
< srcHeight
; row
++) {
1780 for (col
= 0; col
< srcWidth
; col
++) {
1781 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1782 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1783 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1785 dstRow
+= dstRowStride
;
1786 srcRow
+= srcRowStride
;
1790 else if (!ctx
->_ImageTransferState
&&
1792 srcType
== GL_UNSIGNED_BYTE
&&
1793 can_swizzle(baseInternalFormat
) &&
1794 can_swizzle(srcFormat
)) {
1798 /* dstmap - how to swizzle from RGBA to dst format:
1803 dstmap
[3] = ONE
; /* ? */
1805 _mesa_swizzle_ubyte_image(ctx
, dims
,
1810 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1811 dstRowStride
, dstImageOffsets
,
1812 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1817 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1819 dstFormat
->BaseFormat
,
1820 srcWidth
, srcHeight
, srcDepth
,
1821 srcFormat
, srcType
, srcAddr
,
1823 const GLchan
*src
= (const GLchan
*) tempImage
;
1824 GLint img
, row
, col
;
1827 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1828 for (img
= 0; img
< srcDepth
; img
++) {
1829 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1830 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1831 + dstYoffset
* dstRowStride
1832 + dstXoffset
* dstFormat
->TexelBytes
;
1833 for (row
= 0; row
< srcHeight
; row
++) {
1834 for (col
= 0; col
< srcWidth
; col
++) {
1835 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1836 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1837 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1840 dstRow
+= dstRowStride
;
1843 _mesa_free((void *) tempImage
);
1850 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1852 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1853 dstFormat
== &_mesa_texformat_argb4444_rev
);
1854 ASSERT(dstFormat
->TexelBytes
== 2);
1856 if (!ctx
->_ImageTransferState
&&
1857 !srcPacking
->SwapBytes
&&
1858 dstFormat
== &_mesa_texformat_argb4444
&&
1859 baseInternalFormat
== GL_RGBA
&&
1860 srcFormat
== GL_BGRA
&&
1861 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1862 /* simple memcpy path */
1863 memcpy_texture(ctx
, dims
,
1864 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1867 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1868 srcAddr
, srcPacking
);
1872 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1874 dstFormat
->BaseFormat
,
1875 srcWidth
, srcHeight
, srcDepth
,
1876 srcFormat
, srcType
, srcAddr
,
1878 const GLchan
*src
= tempImage
;
1879 GLint img
, row
, col
;
1882 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1883 for (img
= 0; img
< srcDepth
; img
++) {
1884 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1885 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1886 + dstYoffset
* dstRowStride
1887 + dstXoffset
* dstFormat
->TexelBytes
;
1888 for (row
= 0; row
< srcHeight
; row
++) {
1889 GLushort
*dstUS
= (GLushort
*) dstRow
;
1890 if (dstFormat
== &_mesa_texformat_argb4444
) {
1891 for (col
= 0; col
< srcWidth
; col
++) {
1892 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1893 CHAN_TO_UBYTE(src
[RCOMP
]),
1894 CHAN_TO_UBYTE(src
[GCOMP
]),
1895 CHAN_TO_UBYTE(src
[BCOMP
]) );
1900 for (col
= 0; col
< srcWidth
; col
++) {
1901 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1902 CHAN_TO_UBYTE(src
[RCOMP
]),
1903 CHAN_TO_UBYTE(src
[GCOMP
]),
1904 CHAN_TO_UBYTE(src
[BCOMP
]) );
1908 dstRow
+= dstRowStride
;
1911 _mesa_free((void *) tempImage
);
1919 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1921 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1922 dstFormat
== &_mesa_texformat_argb1555_rev
);
1923 ASSERT(dstFormat
->TexelBytes
== 2);
1925 if (!ctx
->_ImageTransferState
&&
1926 !srcPacking
->SwapBytes
&&
1927 dstFormat
== &_mesa_texformat_argb1555
&&
1928 baseInternalFormat
== GL_RGBA
&&
1929 srcFormat
== GL_BGRA
&&
1930 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1931 /* simple memcpy path */
1932 memcpy_texture(ctx
, dims
,
1933 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1936 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1937 srcAddr
, srcPacking
);
1941 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1943 dstFormat
->BaseFormat
,
1944 srcWidth
, srcHeight
, srcDepth
,
1945 srcFormat
, srcType
, srcAddr
,
1947 const GLchan
*src
=tempImage
;
1948 GLint img
, row
, col
;
1951 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1952 for (img
= 0; img
< srcDepth
; img
++) {
1953 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1954 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1955 + dstYoffset
* dstRowStride
1956 + dstXoffset
* dstFormat
->TexelBytes
;
1957 for (row
= 0; row
< srcHeight
; row
++) {
1958 GLushort
*dstUS
= (GLushort
*) dstRow
;
1959 if (dstFormat
== &_mesa_texformat_argb1555
) {
1960 for (col
= 0; col
< srcWidth
; col
++) {
1961 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1962 CHAN_TO_UBYTE(src
[RCOMP
]),
1963 CHAN_TO_UBYTE(src
[GCOMP
]),
1964 CHAN_TO_UBYTE(src
[BCOMP
]) );
1969 for (col
= 0; col
< srcWidth
; col
++) {
1970 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1971 CHAN_TO_UBYTE(src
[RCOMP
]),
1972 CHAN_TO_UBYTE(src
[GCOMP
]),
1973 CHAN_TO_UBYTE(src
[BCOMP
]) );
1977 dstRow
+= dstRowStride
;
1980 _mesa_free((void *) tempImage
);
1987 _mesa_texstore_al88(TEXSTORE_PARAMS
)
1989 const GLboolean littleEndian
= _mesa_little_endian();
1991 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1992 dstFormat
== &_mesa_texformat_al88_rev
);
1993 ASSERT(dstFormat
->TexelBytes
== 2);
1995 if (!ctx
->_ImageTransferState
&&
1996 !srcPacking
->SwapBytes
&&
1997 dstFormat
== &_mesa_texformat_al88
&&
1998 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1999 srcFormat
== GL_LUMINANCE_ALPHA
&&
2000 srcType
== GL_UNSIGNED_BYTE
&&
2002 /* simple memcpy path */
2003 memcpy_texture(ctx
, dims
,
2004 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2007 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2008 srcAddr
, srcPacking
);
2010 else if (!ctx
->_ImageTransferState
&&
2012 srcType
== GL_UNSIGNED_BYTE
&&
2013 can_swizzle(baseInternalFormat
) &&
2014 can_swizzle(srcFormat
)) {
2018 /* dstmap - how to swizzle from RGBA to dst format:
2020 if (dstFormat
== &_mesa_texformat_al88
) {
2028 dstmap
[2] = ZERO
; /* ? */
2029 dstmap
[3] = ONE
; /* ? */
2031 _mesa_swizzle_ubyte_image(ctx
, dims
,
2036 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2037 dstRowStride
, dstImageOffsets
,
2038 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2043 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2045 dstFormat
->BaseFormat
,
2046 srcWidth
, srcHeight
, srcDepth
,
2047 srcFormat
, srcType
, srcAddr
,
2049 const GLchan
*src
= tempImage
;
2050 GLint img
, row
, col
;
2053 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2054 for (img
= 0; img
< srcDepth
; img
++) {
2055 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2056 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2057 + dstYoffset
* dstRowStride
2058 + dstXoffset
* dstFormat
->TexelBytes
;
2059 for (row
= 0; row
< srcHeight
; row
++) {
2060 GLushort
*dstUS
= (GLushort
*) dstRow
;
2061 if (dstFormat
== &_mesa_texformat_al88
) {
2062 for (col
= 0; col
< srcWidth
; col
++) {
2063 /* src[0] is luminance, src[1] is alpha */
2064 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
2065 CHAN_TO_UBYTE(src
[0]) );
2070 for (col
= 0; col
< srcWidth
; col
++) {
2071 /* src[0] is luminance, src[1] is alpha */
2072 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
2073 CHAN_TO_UBYTE(src
[0]) );
2077 dstRow
+= dstRowStride
;
2080 _mesa_free((void *) tempImage
);
2087 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
2089 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
2090 ASSERT(dstFormat
->TexelBytes
== 1);
2092 if (!ctx
->_ImageTransferState
&&
2093 !srcPacking
->SwapBytes
&&
2094 baseInternalFormat
== GL_RGB
&&
2095 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
2096 /* simple memcpy path */
2097 memcpy_texture(ctx
, dims
,
2098 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2101 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2102 srcAddr
, srcPacking
);
2106 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2108 dstFormat
->BaseFormat
,
2109 srcWidth
, srcHeight
, srcDepth
,
2110 srcFormat
, srcType
, srcAddr
,
2112 const GLchan
*src
= tempImage
;
2113 GLint img
, row
, col
;
2116 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2117 for (img
= 0; img
< srcDepth
; img
++) {
2118 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2119 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2120 + dstYoffset
* dstRowStride
2121 + dstXoffset
* dstFormat
->TexelBytes
;
2122 for (row
= 0; row
< srcHeight
; row
++) {
2123 for (col
= 0; col
< srcWidth
; col
++) {
2124 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
2125 CHAN_TO_UBYTE(src
[GCOMP
]),
2126 CHAN_TO_UBYTE(src
[BCOMP
]) );
2129 dstRow
+= dstRowStride
;
2132 _mesa_free((void *) tempImage
);
2139 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2142 _mesa_texstore_a8(TEXSTORE_PARAMS
)
2144 ASSERT(dstFormat
== &_mesa_texformat_a8
||
2145 dstFormat
== &_mesa_texformat_l8
||
2146 dstFormat
== &_mesa_texformat_i8
);
2147 ASSERT(dstFormat
->TexelBytes
== 1);
2149 if (!ctx
->_ImageTransferState
&&
2150 !srcPacking
->SwapBytes
&&
2151 baseInternalFormat
== srcFormat
&&
2152 srcType
== GL_UNSIGNED_BYTE
) {
2153 /* simple memcpy path */
2154 memcpy_texture(ctx
, dims
,
2155 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2158 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2159 srcAddr
, srcPacking
);
2161 else if (!ctx
->_ImageTransferState
&&
2162 _mesa_little_endian() &&
2163 srcType
== GL_UNSIGNED_BYTE
&&
2164 can_swizzle(baseInternalFormat
) &&
2165 can_swizzle(srcFormat
)) {
2169 /* dstmap - how to swizzle from RGBA to dst format:
2171 if (dstFormat
== &_mesa_texformat_a8
) {
2177 dstmap
[1] = ZERO
; /* ? */
2178 dstmap
[2] = ZERO
; /* ? */
2179 dstmap
[3] = ONE
; /* ? */
2181 _mesa_swizzle_ubyte_image(ctx
, dims
,
2186 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2187 dstRowStride
, dstImageOffsets
,
2188 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
2193 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
2195 dstFormat
->BaseFormat
,
2196 srcWidth
, srcHeight
, srcDepth
,
2197 srcFormat
, srcType
, srcAddr
,
2199 const GLchan
*src
= tempImage
;
2200 GLint img
, row
, col
;
2203 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2204 for (img
= 0; img
< srcDepth
; img
++) {
2205 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2206 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2207 + dstYoffset
* dstRowStride
2208 + dstXoffset
* dstFormat
->TexelBytes
;
2209 for (row
= 0; row
< srcHeight
; row
++) {
2210 for (col
= 0; col
< srcWidth
; col
++) {
2211 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
2213 dstRow
+= dstRowStride
;
2217 _mesa_free((void *) tempImage
);
2225 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2227 (void) dims
; (void) baseInternalFormat
;
2228 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2229 ASSERT(dstFormat
->TexelBytes
== 1);
2230 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2232 if (!ctx
->_ImageTransferState
&&
2233 !srcPacking
->SwapBytes
&&
2234 srcFormat
== GL_COLOR_INDEX
&&
2235 srcType
== GL_UNSIGNED_BYTE
) {
2236 /* simple memcpy path */
2237 memcpy_texture(ctx
, dims
,
2238 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2241 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2242 srcAddr
, srcPacking
);
2247 for (img
= 0; img
< srcDepth
; img
++) {
2248 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2249 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2250 + dstYoffset
* dstRowStride
2251 + dstXoffset
* dstFormat
->TexelBytes
;
2252 for (row
= 0; row
< srcHeight
; row
++) {
2253 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2254 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2255 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2256 srcType
, src
, srcPacking
,
2257 ctx
->_ImageTransferState
);
2258 dstRow
+= dstRowStride
;
2267 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2270 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2272 const GLboolean littleEndian
= _mesa_little_endian();
2273 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2275 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2276 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2277 ASSERT(dstFormat
->TexelBytes
== 2);
2278 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2279 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2280 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2281 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2282 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2284 /* always just memcpy since no pixel transfer ops apply */
2285 memcpy_texture(ctx
, dims
,
2286 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2289 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2290 srcAddr
, srcPacking
);
2292 /* Check if we need byte swapping */
2293 /* XXX the logic here _might_ be wrong */
2294 if (srcPacking
->SwapBytes
^
2295 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2296 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2299 for (img
= 0; img
< srcDepth
; img
++) {
2300 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2301 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2302 + dstYoffset
* dstRowStride
2303 + dstXoffset
* dstFormat
->TexelBytes
;
2304 for (row
= 0; row
< srcHeight
; row
++) {
2305 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2306 dstRow
+= dstRowStride
;
2316 * Store a combined depth/stencil texture image.
2319 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2321 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2322 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2323 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2325 if (!ctx
->_ImageTransferState
&&
2326 !srcPacking
->SwapBytes
) {
2328 memcpy_texture(ctx
, dims
,
2329 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2332 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2333 srcAddr
, srcPacking
);
2337 const GLint srcRowStride
2338 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2342 for (img
= 0; img
< srcDepth
; img
++) {
2343 GLuint
*dstRow
= (GLuint
*) dstAddr
2344 + dstImageOffsets
[dstZoffset
+ img
]
2345 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2348 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2349 srcWidth
, srcHeight
,
2352 for (row
= 0; row
< srcHeight
; row
++) {
2353 GLubyte stencil
[MAX_WIDTH
];
2355 /* the 24 depth bits will be in the high position: */
2356 _mesa_unpack_depth_span(ctx
, srcWidth
,
2357 GL_UNSIGNED_INT
, /* dst type */
2358 dstRow
, /* dst addr */
2359 (GLfloat
) 0xffffff, /* depthScale */
2360 srcType
, src
, srcPacking
);
2361 /* get the 8-bit stencil values */
2362 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2363 GL_UNSIGNED_BYTE
, /* dst type */
2364 stencil
, /* dst addr */
2365 srcType
, src
, srcPacking
,
2366 ctx
->_ImageTransferState
);
2367 /* merge stencil values into depth values */
2368 for (i
= 0; i
< srcWidth
; i
++)
2369 dstRow
[i
] |= stencil
[i
];
2371 src
+= srcRowStride
;
2372 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2382 * Store an image in any of the formats:
2383 * _mesa_texformat_rgba_float32
2384 * _mesa_texformat_rgb_float32
2385 * _mesa_texformat_alpha_float32
2386 * _mesa_texformat_luminance_float32
2387 * _mesa_texformat_luminance_alpha_float32
2388 * _mesa_texformat_intensity_float32
2391 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2393 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2395 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2396 dstFormat
== &_mesa_texformat_rgb_float32
||
2397 dstFormat
== &_mesa_texformat_alpha_float32
||
2398 dstFormat
== &_mesa_texformat_luminance_float32
||
2399 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2400 dstFormat
== &_mesa_texformat_intensity_float32
);
2401 ASSERT(baseInternalFormat
== GL_RGBA
||
2402 baseInternalFormat
== GL_RGB
||
2403 baseInternalFormat
== GL_ALPHA
||
2404 baseInternalFormat
== GL_LUMINANCE
||
2405 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2406 baseInternalFormat
== GL_INTENSITY
);
2407 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2409 if (!ctx
->_ImageTransferState
&&
2410 !srcPacking
->SwapBytes
&&
2411 baseInternalFormat
== srcFormat
&&
2412 srcType
== GL_FLOAT
) {
2413 /* simple memcpy path */
2414 memcpy_texture(ctx
, dims
,
2415 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2418 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2419 srcAddr
, srcPacking
);
2423 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2425 dstFormat
->BaseFormat
,
2426 srcWidth
, srcHeight
, srcDepth
,
2427 srcFormat
, srcType
, srcAddr
,
2429 const GLfloat
*srcRow
= tempImage
;
2434 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2435 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2436 for (img
= 0; img
< srcDepth
; img
++) {
2437 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2438 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2439 + dstYoffset
* dstRowStride
2440 + dstXoffset
* dstFormat
->TexelBytes
;
2441 for (row
= 0; row
< srcHeight
; row
++) {
2442 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2443 dstRow
+= dstRowStride
;
2444 srcRow
+= srcWidth
* components
;
2448 _mesa_free((void *) tempImage
);
2455 * As above, but store 16-bit floats.
2458 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2460 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2462 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2463 dstFormat
== &_mesa_texformat_rgb_float16
||
2464 dstFormat
== &_mesa_texformat_alpha_float16
||
2465 dstFormat
== &_mesa_texformat_luminance_float16
||
2466 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2467 dstFormat
== &_mesa_texformat_intensity_float16
);
2468 ASSERT(baseInternalFormat
== GL_RGBA
||
2469 baseInternalFormat
== GL_RGB
||
2470 baseInternalFormat
== GL_ALPHA
||
2471 baseInternalFormat
== GL_LUMINANCE
||
2472 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2473 baseInternalFormat
== GL_INTENSITY
);
2474 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2476 if (!ctx
->_ImageTransferState
&&
2477 !srcPacking
->SwapBytes
&&
2478 baseInternalFormat
== srcFormat
&&
2479 srcType
== GL_HALF_FLOAT_ARB
) {
2480 /* simple memcpy path */
2481 memcpy_texture(ctx
, dims
,
2482 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2485 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2486 srcAddr
, srcPacking
);
2490 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2492 dstFormat
->BaseFormat
,
2493 srcWidth
, srcHeight
, srcDepth
,
2494 srcFormat
, srcType
, srcAddr
,
2496 const GLfloat
*src
= tempImage
;
2500 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2501 for (img
= 0; img
< srcDepth
; img
++) {
2502 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2503 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2504 + dstYoffset
* dstRowStride
2505 + dstXoffset
* dstFormat
->TexelBytes
;
2506 for (row
= 0; row
< srcHeight
; row
++) {
2507 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2509 for (i
= 0; i
< srcWidth
* components
; i
++) {
2510 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2512 dstRow
+= dstRowStride
;
2513 src
+= srcWidth
* components
;
2517 _mesa_free((void *) tempImage
);
2523 #if FEATURE_EXT_texture_sRGB
2525 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2527 const GLboolean littleEndian
= _mesa_little_endian();
2528 const struct gl_texture_format
*newDstFormat
;
2529 StoreTexImageFunc store
;
2532 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2534 /* reuse normal rgb texstore code */
2536 newDstFormat
= &_mesa_texformat_bgr888
;
2537 store
= _mesa_texstore_bgr888
;
2540 newDstFormat
= &_mesa_texformat_rgb888
;
2541 store
= _mesa_texstore_rgb888
;
2544 k
= store(ctx
, dims
, baseInternalFormat
,
2545 newDstFormat
, dstAddr
,
2546 dstXoffset
, dstYoffset
, dstZoffset
,
2547 dstRowStride
, dstImageOffsets
,
2548 srcWidth
, srcHeight
, srcDepth
,
2550 srcAddr
, srcPacking
);
2556 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2558 const GLboolean littleEndian
= _mesa_little_endian();
2559 const struct gl_texture_format
*newDstFormat
;
2562 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2564 /* reuse normal rgba texstore code */
2566 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2568 newDstFormat
= &_mesa_texformat_rgba8888
;
2570 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2571 newDstFormat
, dstAddr
,
2572 dstXoffset
, dstYoffset
, dstZoffset
,
2573 dstRowStride
, dstImageOffsets
,
2574 srcWidth
, srcHeight
, srcDepth
,
2576 srcAddr
, srcPacking
);
2582 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2584 const struct gl_texture_format
*newDstFormat
;
2587 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2589 newDstFormat
= &_mesa_texformat_l8
;
2591 /* _mesa_textore_a8 handles luminance8 too */
2592 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2593 newDstFormat
, dstAddr
,
2594 dstXoffset
, dstYoffset
, dstZoffset
,
2595 dstRowStride
, dstImageOffsets
,
2596 srcWidth
, srcHeight
, srcDepth
,
2598 srcAddr
, srcPacking
);
2604 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2606 const GLboolean littleEndian
= _mesa_little_endian();
2607 const struct gl_texture_format
*newDstFormat
;
2610 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2612 /* reuse normal luminance/alpha texstore code */
2614 newDstFormat
= &_mesa_texformat_al88
;
2616 newDstFormat
= &_mesa_texformat_al88_rev
;
2618 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2619 newDstFormat
, dstAddr
,
2620 dstXoffset
, dstYoffset
, dstZoffset
,
2621 dstRowStride
, dstImageOffsets
,
2622 srcWidth
, srcHeight
, srcDepth
,
2624 srcAddr
, srcPacking
);
2628 #endif /* FEATURE_EXT_texture_sRGB */
2632 * Check if an unpack PBO is active prior to fetching a texture image.
2633 * If so, do bounds checking and map the buffer into main memory.
2634 * Any errors detected will be recorded.
2635 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2638 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2639 GLsizei width
, GLsizei height
, GLsizei depth
,
2640 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2641 const struct gl_pixelstore_attrib
*unpack
,
2642 const char *funcName
)
2646 if (unpack
->BufferObj
->Name
== 0) {
2650 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2651 format
, type
, pixels
)) {
2652 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2656 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2657 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2659 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2663 return ADD_POINTERS(buf
, pixels
);
2668 * Check if an unpack PBO is active prior to fetching a compressed texture
2670 * If so, do bounds checking and map the buffer into main memory.
2671 * Any errors detected will be recorded.
2672 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2675 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2676 GLsizei imageSize
, const GLvoid
*pixels
,
2677 const struct gl_pixelstore_attrib
*packing
,
2678 const char *funcName
)
2682 if (packing
->BufferObj
->Name
== 0) {
2683 /* not using a PBO - return pointer unchanged */
2686 if ((const GLubyte
*) pixels
+ imageSize
>
2687 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2688 /* out of bounds read! */
2689 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2693 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2694 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2696 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2700 return ADD_POINTERS(buf
, pixels
);
2705 * This function must be called after either of the validate_pbo_*_teximage()
2706 * functions. It unmaps the PBO buffer if it was mapped earlier.
2709 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2710 const struct gl_pixelstore_attrib
*unpack
)
2712 if (unpack
->BufferObj
->Name
) {
2713 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2721 * Adaptor for fetching a GLchan texel from a float-valued texture.
2724 FetchTexelFloatToChan( const struct gl_texture_image
*texImage
,
2725 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2728 ASSERT(texImage
->FetchTexelf
);
2729 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2730 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2731 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2732 /* just one channel */
2733 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2737 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2738 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2739 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2740 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2746 * Adaptor for fetching a float texel from a GLchan-valued texture.
2749 FetchTexelChanToFloat( const struct gl_texture_image
*texImage
,
2750 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2753 ASSERT(texImage
->FetchTexelc
);
2754 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2755 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2756 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2757 /* just one channel */
2758 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2762 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2763 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2764 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2765 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2771 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2774 set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2776 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2777 ASSERT(texImage
->TexFormat
);
2781 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2782 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2785 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2786 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2789 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2790 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2796 /* now check if we need to use a float/chan adaptor */
2797 if (!texImage
->FetchTexelc
) {
2798 texImage
->FetchTexelc
= FetchTexelFloatToChan
;
2800 else if (!texImage
->FetchTexelf
) {
2801 texImage
->FetchTexelf
= FetchTexelChanToFloat
;
2805 ASSERT(texImage
->FetchTexelc
);
2806 ASSERT(texImage
->FetchTexelf
);
2811 * Choose the actual storage format for a new texture image.
2812 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2813 * Also set some other texImage fields related to texture compression, etc.
2814 * \param ctx rendering context
2815 * \param texImage the gl_texture_image
2816 * \param dims texture dimensions (1, 2 or 3)
2817 * \param format the user-specified format parameter
2818 * \param type the user-specified type parameter
2819 * \param internalFormat the user-specified internal format hint
2822 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2824 GLenum format
, GLenum type
, GLint internalFormat
)
2826 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2827 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2830 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2832 ASSERT(texImage
->TexFormat
);
2834 set_fetch_functions(texImage
, dims
);
2836 if (texImage
->TexFormat
->TexelBytes
== 0) {
2837 /* must be a compressed format */
2838 texImage
->IsCompressed
= GL_TRUE
;
2839 texImage
->CompressedSize
=
2840 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2841 texImage
->Height
, texImage
->Depth
,
2842 texImage
->TexFormat
->MesaFormat
);
2845 /* non-compressed format */
2846 texImage
->IsCompressed
= GL_FALSE
;
2847 texImage
->CompressedSize
= 0;
2854 * This is the software fallback for Driver.TexImage1D()
2855 * and Driver.CopyTexImage1D().
2856 * \sa _mesa_store_teximage2d()
2859 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2860 GLint internalFormat
,
2861 GLint width
, GLint border
,
2862 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2863 const struct gl_pixelstore_attrib
*packing
,
2864 struct gl_texture_object
*texObj
,
2865 struct gl_texture_image
*texImage
)
2867 GLint postConvWidth
= width
;
2871 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2872 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2875 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2877 /* allocate memory */
2878 if (texImage
->IsCompressed
)
2879 sizeInBytes
= texImage
->CompressedSize
;
2881 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2882 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2883 if (!texImage
->Data
) {
2884 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2888 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2889 pixels
, packing
, "glTexImage1D");
2891 /* Note: we check for a NULL image pointer here, _after_ we allocated
2892 * memory for the texture. That's what the GL spec calls for.
2897 const GLint dstRowStride
= 0;
2899 ASSERT(texImage
->TexFormat
->StoreImage
);
2900 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2901 texImage
->TexFormat
,
2903 0, 0, 0, /* dstX/Y/Zoffset */
2905 texImage
->ImageOffsets
,
2907 format
, type
, pixels
, packing
);
2909 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2913 /* GL_SGIS_generate_mipmap */
2914 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2915 _mesa_generate_mipmap(ctx
, target
,
2916 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2920 _mesa_unmap_teximage_pbo(ctx
, packing
);
2925 * This is the software fallback for Driver.TexImage2D()
2926 * and Driver.CopyTexImage2D().
2928 * This function is oriented toward storing images in main memory, rather
2929 * than VRAM. Device driver's can easily plug in their own replacement.
2931 * Note: width and height may be pre-convolved dimensions, but
2932 * texImage->Width and texImage->Height will be post-convolved dimensions.
2935 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2936 GLint internalFormat
,
2937 GLint width
, GLint height
, GLint border
,
2938 GLenum format
, GLenum type
, const void *pixels
,
2939 const struct gl_pixelstore_attrib
*packing
,
2940 struct gl_texture_object
*texObj
,
2941 struct gl_texture_image
*texImage
)
2943 GLint postConvWidth
= width
, postConvHeight
= height
;
2944 GLint texelBytes
, sizeInBytes
;
2947 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2948 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2952 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2954 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2956 /* allocate memory */
2957 if (texImage
->IsCompressed
)
2958 sizeInBytes
= texImage
->CompressedSize
;
2960 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2961 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2962 if (!texImage
->Data
) {
2963 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2967 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2968 pixels
, packing
, "glTexImage2D");
2970 /* Note: we check for a NULL image pointer here, _after_ we allocated
2971 * memory for the texture. That's what the GL spec calls for.
2978 if (texImage
->IsCompressed
) {
2980 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2983 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2985 ASSERT(texImage
->TexFormat
->StoreImage
);
2986 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2987 texImage
->TexFormat
,
2989 0, 0, 0, /* dstX/Y/Zoffset */
2991 texImage
->ImageOffsets
,
2993 format
, type
, pixels
, packing
);
2995 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2999 /* GL_SGIS_generate_mipmap */
3000 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3001 _mesa_generate_mipmap(ctx
, target
,
3002 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3006 _mesa_unmap_teximage_pbo(ctx
, packing
);
3012 * This is the software fallback for Driver.TexImage3D()
3013 * and Driver.CopyTexImage3D().
3014 * \sa _mesa_store_teximage2d()
3017 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3018 GLint internalFormat
,
3019 GLint width
, GLint height
, GLint depth
, GLint border
,
3020 GLenum format
, GLenum type
, const void *pixels
,
3021 const struct gl_pixelstore_attrib
*packing
,
3022 struct gl_texture_object
*texObj
,
3023 struct gl_texture_image
*texImage
)
3025 GLint texelBytes
, sizeInBytes
;
3028 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
3030 texelBytes
= texImage
->TexFormat
->TexelBytes
;
3032 /* allocate memory */
3033 if (texImage
->IsCompressed
)
3034 sizeInBytes
= texImage
->CompressedSize
;
3036 sizeInBytes
= width
* height
* depth
* texelBytes
;
3037 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
3038 if (!texImage
->Data
) {
3039 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3043 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3044 type
, pixels
, packing
, "glTexImage3D");
3046 /* Note: we check for a NULL image pointer here, _after_ we allocated
3047 * memory for the texture. That's what the GL spec calls for.
3054 if (texImage
->IsCompressed
) {
3056 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
3059 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3061 ASSERT(texImage
->TexFormat
->StoreImage
);
3062 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3063 texImage
->TexFormat
,
3065 0, 0, 0, /* dstX/Y/Zoffset */
3067 texImage
->ImageOffsets
,
3068 width
, height
, depth
,
3069 format
, type
, pixels
, packing
);
3071 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
3075 /* GL_SGIS_generate_mipmap */
3076 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3077 _mesa_generate_mipmap(ctx
, target
,
3078 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3082 _mesa_unmap_teximage_pbo(ctx
, packing
);
3089 * This is the software fallback for Driver.TexSubImage1D()
3090 * and Driver.CopyTexSubImage1D().
3093 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3094 GLint xoffset
, GLint width
,
3095 GLenum format
, GLenum type
, const void *pixels
,
3096 const struct gl_pixelstore_attrib
*packing
,
3097 struct gl_texture_object
*texObj
,
3098 struct gl_texture_image
*texImage
)
3100 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3101 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
3102 pixels
, packing
, "glTexSubImage1D");
3107 const GLint dstRowStride
= 0;
3109 ASSERT(texImage
->TexFormat
->StoreImage
);
3110 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
3111 texImage
->TexFormat
,
3113 xoffset
, 0, 0, /* offsets */
3115 texImage
->ImageOffsets
,
3117 format
, type
, pixels
, packing
);
3119 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
3123 /* GL_SGIS_generate_mipmap */
3124 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3125 _mesa_generate_mipmap(ctx
, target
,
3126 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3130 _mesa_unmap_teximage_pbo(ctx
, packing
);
3136 * This is the software fallback for Driver.TexSubImage2D()
3137 * and Driver.CopyTexSubImage2D().
3140 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3141 GLint xoffset
, GLint yoffset
,
3142 GLint width
, GLint height
,
3143 GLenum format
, GLenum type
, const void *pixels
,
3144 const struct gl_pixelstore_attrib
*packing
,
3145 struct gl_texture_object
*texObj
,
3146 struct gl_texture_image
*texImage
)
3148 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3149 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
3150 pixels
, packing
, "glTexSubImage2D");
3155 GLint dstRowStride
= 0;
3157 if (texImage
->IsCompressed
) {
3158 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3162 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3164 ASSERT(texImage
->TexFormat
->StoreImage
);
3165 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
3166 texImage
->TexFormat
,
3168 xoffset
, yoffset
, 0,
3170 texImage
->ImageOffsets
,
3172 format
, type
, pixels
, packing
);
3174 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
3178 /* GL_SGIS_generate_mipmap */
3179 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3180 _mesa_generate_mipmap(ctx
, target
,
3181 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3185 _mesa_unmap_teximage_pbo(ctx
, packing
);
3190 * This is the software fallback for Driver.TexSubImage3D().
3191 * and Driver.CopyTexSubImage3D().
3194 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3195 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3196 GLint width
, GLint height
, GLint depth
,
3197 GLenum format
, GLenum type
, const void *pixels
,
3198 const struct gl_pixelstore_attrib
*packing
,
3199 struct gl_texture_object
*texObj
,
3200 struct gl_texture_image
*texImage
)
3202 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3203 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
3204 type
, pixels
, packing
,
3212 if (texImage
->IsCompressed
) {
3213 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3217 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3219 ASSERT(texImage
->TexFormat
->StoreImage
);
3220 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3221 texImage
->TexFormat
,
3223 xoffset
, yoffset
, zoffset
,
3225 texImage
->ImageOffsets
,
3226 width
, height
, depth
,
3227 format
, type
, pixels
, packing
);
3229 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3233 /* GL_SGIS_generate_mipmap */
3234 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3235 _mesa_generate_mipmap(ctx
, target
,
3236 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3240 _mesa_unmap_teximage_pbo(ctx
, packing
);
3245 * Fallback for Driver.CompressedTexImage1D()
3248 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3249 GLint internalFormat
,
3250 GLint width
, GLint border
,
3251 GLsizei imageSize
, const GLvoid
*data
,
3252 struct gl_texture_object
*texObj
,
3253 struct gl_texture_image
*texImage
)
3255 /* this space intentionally left blank */
3257 (void) target
; (void) level
;
3258 (void) internalFormat
;
3259 (void) width
; (void) border
;
3260 (void) imageSize
; (void) data
;
3268 * Fallback for Driver.CompressedTexImage2D()
3271 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3272 GLint internalFormat
,
3273 GLint width
, GLint height
, GLint border
,
3274 GLsizei imageSize
, const GLvoid
*data
,
3275 struct gl_texture_object
*texObj
,
3276 struct gl_texture_image
*texImage
)
3278 (void) width
; (void) height
; (void) border
;
3280 /* This is pretty simple, basically just do a memcpy without worrying
3281 * about the usual image unpacking or image transfer operations.
3285 ASSERT(texImage
->Width
> 0);
3286 ASSERT(texImage
->Height
> 0);
3287 ASSERT(texImage
->Depth
== 1);
3288 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3290 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3292 /* allocate storage */
3293 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3294 if (!texImage
->Data
) {
3295 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3299 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3301 "glCompressedTexImage2D");
3306 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3307 MEMCPY(texImage
->Data
, data
, imageSize
);
3309 /* GL_SGIS_generate_mipmap */
3310 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3311 _mesa_generate_mipmap(ctx
, target
,
3312 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3316 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3322 * Fallback for Driver.CompressedTexImage3D()
3325 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3326 GLint internalFormat
,
3327 GLint width
, GLint height
, GLint depth
,
3329 GLsizei imageSize
, const GLvoid
*data
,
3330 struct gl_texture_object
*texObj
,
3331 struct gl_texture_image
*texImage
)
3333 /* this space intentionally left blank */
3335 (void) target
; (void) level
;
3336 (void) internalFormat
;
3337 (void) width
; (void) height
; (void) depth
;
3339 (void) imageSize
; (void) data
;
3347 * Fallback for Driver.CompressedTexSubImage1D()
3350 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3352 GLint xoffset
, GLsizei width
,
3354 GLsizei imageSize
, const GLvoid
*data
,
3355 struct gl_texture_object
*texObj
,
3356 struct gl_texture_image
*texImage
)
3358 /* there are no compressed 1D texture formats yet */
3360 (void) target
; (void) level
;
3361 (void) xoffset
; (void) width
;
3363 (void) imageSize
; (void) data
;
3370 * Fallback for Driver.CompressedTexSubImage2D()
3373 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3375 GLint xoffset
, GLint yoffset
,
3376 GLsizei width
, GLsizei height
,
3378 GLsizei imageSize
, const GLvoid
*data
,
3379 struct gl_texture_object
*texObj
,
3380 struct gl_texture_image
*texImage
)
3382 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3386 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3390 /* these should have been caught sooner */
3391 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3392 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3393 ASSERT((xoffset
& 3) == 0);
3394 ASSERT((yoffset
& 3) == 0);
3396 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3397 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3399 "glCompressedTexSubImage2D");
3403 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3404 src
= (const GLubyte
*) data
;
3406 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3407 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3408 texImage
->TexFormat
->MesaFormat
,
3410 (GLubyte
*) texImage
->Data
);
3412 bytesPerRow
= srcRowStride
;
3415 for (i
= 0; i
< rows
; i
++) {
3416 MEMCPY(dest
, src
, bytesPerRow
);
3417 dest
+= destRowStride
;
3418 src
+= srcRowStride
;
3421 /* GL_SGIS_generate_mipmap */
3422 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3423 _mesa_generate_mipmap(ctx
, target
,
3424 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3428 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3433 * Fallback for Driver.CompressedTexSubImage3D()
3436 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3438 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3439 GLsizei width
, GLsizei height
, GLsizei depth
,
3441 GLsizei imageSize
, const GLvoid
*data
,
3442 struct gl_texture_object
*texObj
,
3443 struct gl_texture_image
*texImage
)
3445 /* there are no compressed 3D texture formats yet */
3447 (void) target
; (void) level
;
3448 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3449 (void) width
; (void) height
; (void) depth
;
3451 (void) imageSize
; (void) data
;
3458 * Average together two rows of a source image to produce a single new
3459 * row in the dest image. It's legal for the two source rows to point
3460 * to the same data. The source width must be equal to either the
3461 * dest width or two times the dest width.
3464 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
3465 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
3466 GLint dstWidth
, GLvoid
*dstRow
)
3468 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
3469 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
3471 /* This assertion is no longer valid with non-power-of-2 textures
3472 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
3475 switch (format
->MesaFormat
) {
3476 case MESA_FORMAT_RGBA
:
3479 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
3480 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
3481 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
3482 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3483 i
++, j
+= colStride
, k
+= colStride
) {
3484 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3485 rowB
[j
][0] + rowB
[k
][0]) / 4;
3486 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3487 rowB
[j
][1] + rowB
[k
][1]) / 4;
3488 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3489 rowB
[j
][2] + rowB
[k
][2]) / 4;
3490 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3491 rowB
[j
][3] + rowB
[k
][3]) / 4;
3495 case MESA_FORMAT_RGB
:
3498 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
3499 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
3500 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
3501 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3502 i
++, j
+= colStride
, k
+= colStride
) {
3503 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3504 rowB
[j
][0] + rowB
[k
][0]) / 4;
3505 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3506 rowB
[j
][1] + rowB
[k
][1]) / 4;
3507 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3508 rowB
[j
][2] + rowB
[k
][2]) / 4;
3512 case MESA_FORMAT_ALPHA
:
3513 case MESA_FORMAT_LUMINANCE
:
3514 case MESA_FORMAT_INTENSITY
:
3517 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
3518 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
3519 GLchan
*dst
= (GLchan
*) dstRow
;
3520 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3521 i
++, j
+= colStride
, k
+= colStride
) {
3522 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3526 case MESA_FORMAT_LUMINANCE_ALPHA
:
3529 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
3530 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
3531 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
3532 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3533 i
++, j
+= colStride
, k
+= colStride
) {
3534 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3535 rowB
[j
][0] + rowB
[k
][0]) / 4;
3536 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3537 rowB
[j
][1] + rowB
[k
][1]) / 4;
3541 case MESA_FORMAT_Z32
:
3544 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
3545 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
3546 GLfloat
*dst
= (GLfloat
*) dstRow
;
3547 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3548 i
++, j
+= colStride
, k
+= colStride
) {
3549 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
3553 case MESA_FORMAT_Z16
:
3556 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3557 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3558 GLushort
*dst
= (GLushort
*) dstRow
;
3559 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3560 i
++, j
+= colStride
, k
+= colStride
) {
3561 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3565 /* Begin hardware formats */
3566 case MESA_FORMAT_RGBA8888
:
3567 case MESA_FORMAT_RGBA8888_REV
:
3568 case MESA_FORMAT_ARGB8888
:
3569 case MESA_FORMAT_ARGB8888_REV
:
3570 #if FEATURE_EXT_texture_sRGB
3571 case MESA_FORMAT_SRGBA8
:
3575 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
3576 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
3577 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
3578 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3579 i
++, j
+= colStride
, k
+= colStride
) {
3580 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3581 rowB
[j
][0] + rowB
[k
][0]) / 4;
3582 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3583 rowB
[j
][1] + rowB
[k
][1]) / 4;
3584 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3585 rowB
[j
][2] + rowB
[k
][2]) / 4;
3586 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3587 rowB
[j
][3] + rowB
[k
][3]) / 4;
3591 case MESA_FORMAT_RGB888
:
3592 case MESA_FORMAT_BGR888
:
3593 #if FEATURE_EXT_texture_sRGB
3594 case MESA_FORMAT_SRGB8
:
3598 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
3599 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
3600 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
3601 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3602 i
++, j
+= colStride
, k
+= colStride
) {
3603 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3604 rowB
[j
][0] + rowB
[k
][0]) / 4;
3605 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3606 rowB
[j
][1] + rowB
[k
][1]) / 4;
3607 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3608 rowB
[j
][2] + rowB
[k
][2]) / 4;
3612 case MESA_FORMAT_RGB565
:
3613 case MESA_FORMAT_RGB565_REV
:
3616 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3617 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3618 GLushort
*dst
= (GLushort
*) dstRow
;
3619 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3620 i
++, j
+= colStride
, k
+= colStride
) {
3621 const GLint rowAr0
= rowA
[j
] & 0x1f;
3622 const GLint rowAr1
= rowA
[k
] & 0x1f;
3623 const GLint rowBr0
= rowB
[j
] & 0x1f;
3624 const GLint rowBr1
= rowB
[k
] & 0x1f;
3625 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
3626 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
3627 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
3628 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
3629 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
3630 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
3631 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
3632 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
3633 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3634 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3635 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3636 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
3640 case MESA_FORMAT_ARGB4444
:
3641 case MESA_FORMAT_ARGB4444_REV
:
3644 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3645 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3646 GLushort
*dst
= (GLushort
*) dstRow
;
3647 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3648 i
++, j
+= colStride
, k
+= colStride
) {
3649 const GLint rowAr0
= rowA
[j
] & 0xf;
3650 const GLint rowAr1
= rowA
[k
] & 0xf;
3651 const GLint rowBr0
= rowB
[j
] & 0xf;
3652 const GLint rowBr1
= rowB
[k
] & 0xf;
3653 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
3654 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
3655 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
3656 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
3657 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
3658 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
3659 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
3660 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
3661 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
3662 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
3663 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
3664 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
3665 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3666 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3667 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3668 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3669 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
3673 case MESA_FORMAT_ARGB1555
:
3674 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
3677 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3678 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3679 GLushort
*dst
= (GLushort
*) dstRow
;
3680 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3681 i
++, j
+= colStride
, k
+= colStride
) {
3682 const GLint rowAr0
= rowA
[j
] & 0x1f;
3683 const GLint rowAr1
= rowA
[k
] & 0x1f;
3684 const GLint rowBr0
= rowB
[j
] & 0x1f;
3685 const GLint rowBr1
= rowB
[k
] & 0xf;
3686 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
3687 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
3688 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
3689 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
3690 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
3691 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3692 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3693 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3694 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3695 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3696 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3697 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3698 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3699 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3700 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3701 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3702 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3706 case MESA_FORMAT_AL88
:
3707 case MESA_FORMAT_AL88_REV
:
3708 #if FEATURE_EXT_texture_sRGB
3709 case MESA_FORMAT_SLA8
:
3713 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3714 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3715 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3716 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3717 i
++, j
+= colStride
, k
+= colStride
) {
3718 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3719 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3720 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3721 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3725 case MESA_FORMAT_RGB332
:
3728 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3729 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3730 GLubyte
*dst
= (GLubyte
*) dstRow
;
3731 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3732 i
++, j
+= colStride
, k
+= colStride
) {
3733 const GLint rowAr0
= rowA
[j
] & 0x3;
3734 const GLint rowAr1
= rowA
[k
] & 0x3;
3735 const GLint rowBr0
= rowB
[j
] & 0x3;
3736 const GLint rowBr1
= rowB
[k
] & 0x3;
3737 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3738 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3739 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3740 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3741 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3742 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3743 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3744 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3745 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3746 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3747 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3748 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3752 case MESA_FORMAT_A8
:
3753 case MESA_FORMAT_L8
:
3754 case MESA_FORMAT_I8
:
3755 case MESA_FORMAT_CI8
:
3756 #if FEATURE_EXT_texture_sRGB
3757 case MESA_FORMAT_SL8
:
3761 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3762 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3763 GLubyte
*dst
= (GLubyte
*) dstRow
;
3764 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3765 i
++, j
+= colStride
, k
+= colStride
) {
3766 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
3770 case MESA_FORMAT_RGBA_FLOAT32
:
3773 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3774 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3775 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
3776 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3777 i
++, j
+= colStride
, k
+= colStride
) {
3778 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3779 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3780 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3781 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3782 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3783 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3784 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3785 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3789 case MESA_FORMAT_RGBA_FLOAT16
:
3791 GLuint i
, j
, k
, comp
;
3792 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3793 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3794 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3795 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3796 i
++, j
+= colStride
, k
+= colStride
) {
3797 for (comp
= 0; comp
< 4; comp
++) {
3798 GLfloat aj
, ak
, bj
, bk
;
3799 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3800 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3801 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3802 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3803 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3808 case MESA_FORMAT_RGB_FLOAT32
:
3811 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3812 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3813 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3814 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3815 i
++, j
+= colStride
, k
+= colStride
) {
3816 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3817 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3818 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3819 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3820 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3821 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3825 case MESA_FORMAT_RGB_FLOAT16
:
3827 GLuint i
, j
, k
, comp
;
3828 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3829 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3830 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3831 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3832 i
++, j
+= colStride
, k
+= colStride
) {
3833 for (comp
= 0; comp
< 3; comp
++) {
3834 GLfloat aj
, ak
, bj
, bk
;
3835 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3836 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3837 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3838 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3839 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3844 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3847 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3848 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3849 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3850 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3851 i
++, j
+= colStride
, k
+= colStride
) {
3852 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3853 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3854 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3855 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3859 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3861 GLuint i
, j
, k
, comp
;
3862 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3863 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3864 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3865 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3866 i
++, j
+= colStride
, k
+= colStride
) {
3867 for (comp
= 0; comp
< 2; comp
++) {
3868 GLfloat aj
, ak
, bj
, bk
;
3869 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3870 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3871 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3872 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3873 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3878 case MESA_FORMAT_ALPHA_FLOAT32
:
3879 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3880 case MESA_FORMAT_INTENSITY_FLOAT32
:
3883 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3884 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3885 GLfloat
*dst
= (GLfloat
*) dstRow
;
3886 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3887 i
++, j
+= colStride
, k
+= colStride
) {
3888 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3892 case MESA_FORMAT_ALPHA_FLOAT16
:
3893 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3894 case MESA_FORMAT_INTENSITY_FLOAT16
:
3897 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3898 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3899 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3900 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3901 i
++, j
+= colStride
, k
+= colStride
) {
3902 GLfloat aj
, ak
, bj
, bk
;
3903 aj
= _mesa_half_to_float(rowA
[j
]);
3904 ak
= _mesa_half_to_float(rowA
[k
]);
3905 bj
= _mesa_half_to_float(rowB
[j
]);
3906 bk
= _mesa_half_to_float(rowB
[k
]);
3907 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3913 _mesa_problem(NULL
, "bad format in do_row()");
3919 * These functions generate a 1/2-size mipmap image from a source image.
3920 * Texture borders are handled by copying or averaging the source image's
3921 * border texels, depending on the scale-down factor.
3925 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3926 GLint srcWidth
, const GLubyte
*srcPtr
,
3927 GLint dstWidth
, GLubyte
*dstPtr
)
3929 const GLint bpt
= format
->TexelBytes
;
3933 /* skip the border pixel, if any */
3934 src
= srcPtr
+ border
* bpt
;
3935 dst
= dstPtr
+ border
* bpt
;
3937 /* we just duplicate the input row, kind of hack, saves code */
3938 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3939 dstWidth
- 2 * border
, dst
);
3942 /* copy left-most pixel from source */
3943 MEMCPY(dstPtr
, srcPtr
, bpt
);
3944 /* copy right-most pixel from source */
3945 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3946 srcPtr
+ (srcWidth
- 1) * bpt
,
3953 * XXX need to use the tex image's row stride!
3956 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3957 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3958 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3960 const GLint bpt
= format
->TexelBytes
;
3961 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3962 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3963 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3964 const GLint srcRowStride
= bpt
* srcWidth
;
3965 const GLint dstRowStride
= bpt
* dstWidth
;
3966 const GLubyte
*srcA
, *srcB
;
3970 /* Compute src and dst pointers, skipping any border */
3971 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3973 srcB
= srcA
+ srcRowStride
;
3976 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3978 for (row
= 0; row
< dstHeightNB
; row
++) {
3979 do_row(format
, srcWidthNB
, srcA
, srcB
,
3981 srcA
+= 2 * srcRowStride
;
3982 srcB
+= 2 * srcRowStride
;
3983 dst
+= dstRowStride
;
3986 /* This is ugly but probably won't be used much */
3988 /* fill in dest border */
3989 /* lower-left border pixel */
3990 MEMCPY(dstPtr
, srcPtr
, bpt
);
3991 /* lower-right border pixel */
3992 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3993 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3994 /* upper-left border pixel */
3995 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3996 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3997 /* upper-right border pixel */
3998 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3999 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
4001 do_row(format
, srcWidthNB
,
4004 dstWidthNB
, dstPtr
+ bpt
);
4006 do_row(format
, srcWidthNB
,
4007 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
4008 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
4010 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
4011 /* left and right borders */
4012 if (srcHeight
== dstHeight
) {
4013 /* copy border pixel from src to dst */
4014 for (row
= 1; row
< srcHeight
; row
++) {
4015 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
4016 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
4017 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
4018 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
4022 /* average two src pixels each dest pixel */
4023 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
4025 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
4026 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
4027 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
4029 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
4030 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
4031 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
4039 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
4040 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
4041 const GLubyte
*srcPtr
,
4042 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
4045 const GLint bpt
= format
->TexelBytes
;
4046 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
4047 const GLint srcDepthNB
= srcDepth
- 2 * border
;
4048 const GLint dstWidthNB
= dstWidth
- 2 * border
;
4049 const GLint dstHeightNB
= dstHeight
- 2 * border
;
4050 const GLint dstDepthNB
= dstDepth
- 2 * border
;
4051 GLvoid
*tmpRowA
, *tmpRowB
;
4053 GLint bytesPerSrcImage
, bytesPerDstImage
;
4054 GLint bytesPerSrcRow
, bytesPerDstRow
;
4055 GLint srcImageOffset
, srcRowOffset
;
4057 (void) srcDepthNB
; /* silence warnings */
4059 /* Need two temporary row buffers */
4060 tmpRowA
= _mesa_malloc(srcWidth
* bpt
);
4063 tmpRowB
= _mesa_malloc(srcWidth
* bpt
);
4065 _mesa_free(tmpRowA
);
4069 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
4070 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
4072 bytesPerSrcRow
= srcWidth
* bpt
;
4073 bytesPerDstRow
= dstWidth
* bpt
;
4075 /* Offset between adjacent src images to be averaged together */
4076 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
4078 /* Offset between adjacent src rows to be averaged together */
4079 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
4082 * Need to average together up to 8 src pixels for each dest pixel.
4083 * Break that down into 3 operations:
4084 * 1. take two rows from source image and average them together.
4085 * 2. take two rows from next source image and average them together.
4086 * 3. take the two averaged rows and average them for the final dst row.
4090 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
4091 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
4094 for (img
= 0; img
< dstDepthNB
; img
++) {
4095 /* first source image pointer, skipping border */
4096 const GLubyte
*imgSrcA
= srcPtr
4097 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
4098 + img
* (bytesPerSrcImage
+ srcImageOffset
);
4099 /* second source image pointer, skipping border */
4100 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
4101 /* address of the dest image, skipping border */
4102 GLubyte
*imgDst
= dstPtr
4103 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
4104 + img
* bytesPerDstImage
;
4106 /* setup the four source row pointers and the dest row pointer */
4107 const GLubyte
*srcImgARowA
= imgSrcA
;
4108 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
4109 const GLubyte
*srcImgBRowA
= imgSrcB
;
4110 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
4111 GLubyte
*dstImgRow
= imgDst
;
4113 for (row
= 0; row
< dstHeightNB
; row
++) {
4114 /* Average together two rows from first src image */
4115 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
4116 srcWidthNB
, tmpRowA
);
4117 /* Average together two rows from second src image */
4118 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
4119 srcWidthNB
, tmpRowB
);
4120 /* Average together the temp rows to make the final row */
4121 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
4122 dstWidthNB
, dstImgRow
);
4123 /* advance to next rows */
4124 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
4125 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
4126 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
4127 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
4128 dstImgRow
+= bytesPerDstRow
;
4132 _mesa_free(tmpRowA
);
4133 _mesa_free(tmpRowB
);
4135 /* Luckily we can leverage the make_2d_mipmap() function here! */
4137 /* do front border image */
4138 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
4139 dstWidth
, dstHeight
, dstPtr
);
4140 /* do back border image */
4141 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
4142 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
4143 dstWidth
, dstHeight
,
4144 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
4145 /* do four remaining border edges that span the image slices */
4146 if (srcDepth
== dstDepth
) {
4147 /* just copy border pixels from src to dst */
4148 for (img
= 0; img
< dstDepthNB
; img
++) {
4152 /* do border along [img][row=0][col=0] */
4153 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
4154 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
4155 MEMCPY(dst
, src
, bpt
);
4157 /* do border along [img][row=dstHeight-1][col=0] */
4158 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
4159 + (srcHeight
- 1) * bytesPerSrcRow
;
4160 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
4161 + (dstHeight
- 1) * bytesPerDstRow
;
4162 MEMCPY(dst
, src
, bpt
);
4164 /* do border along [img][row=0][col=dstWidth-1] */
4165 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
4166 + (srcWidth
- 1) * bpt
;
4167 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
4168 + (dstWidth
- 1) * bpt
;
4169 MEMCPY(dst
, src
, bpt
);
4171 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
4172 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
4173 + (bytesPerSrcImage
- bpt
);
4174 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
4175 + (bytesPerDstImage
- bpt
);
4176 MEMCPY(dst
, src
, bpt
);
4180 /* average border pixels from adjacent src image pairs */
4181 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
4182 for (img
= 0; img
< dstDepthNB
; img
++) {
4186 /* do border along [img][row=0][col=0] */
4187 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
4188 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
4189 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
4191 /* do border along [img][row=dstHeight-1][col=0] */
4192 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
4193 + (srcHeight
- 1) * bytesPerSrcRow
;
4194 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
4195 + (dstHeight
- 1) * bytesPerDstRow
;
4196 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
4198 /* do border along [img][row=0][col=dstWidth-1] */
4199 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
4200 + (srcWidth
- 1) * bpt
;
4201 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
4202 + (dstWidth
- 1) * bpt
;
4203 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
4205 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
4206 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
4207 + (bytesPerSrcImage
- bpt
);
4208 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
4209 + (bytesPerDstImage
- bpt
);
4210 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
4218 * For GL_SGIX_generate_mipmap:
4219 * Generate a complete set of mipmaps from texObj's base-level image.
4220 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
4223 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
4224 const struct gl_texture_unit
*texUnit
,
4225 struct gl_texture_object
*texObj
)
4227 const struct gl_texture_image
*srcImage
;
4228 const struct gl_texture_format
*convertFormat
;
4229 const GLubyte
*srcData
= NULL
;
4230 GLubyte
*dstData
= NULL
;
4231 GLint level
, maxLevels
;
4234 /* XXX choose cube map face here??? */
4235 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
4238 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
4239 ASSERT(maxLevels
> 0); /* bad target */
4241 /* Find convertFormat - the format that do_row() will process */
4242 if (srcImage
->IsCompressed
) {
4243 /* setup for compressed textures */
4245 GLint components
, size
;
4248 assert(texObj
->Target
== GL_TEXTURE_2D
);
4250 if (srcImage
->_BaseFormat
== GL_RGB
) {
4251 convertFormat
= &_mesa_texformat_rgb
;
4254 else if (srcImage
->_BaseFormat
== GL_RGBA
) {
4255 convertFormat
= &_mesa_texformat_rgba
;
4259 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
4263 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
4264 size
= _mesa_bytes_per_pixel(srcImage
->_BaseFormat
, CHAN_TYPE
)
4265 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
4266 /* 20 extra bytes, just be safe when calling last FetchTexel */
4267 srcData
= (GLubyte
*) _mesa_malloc(size
);
4269 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
4272 dstData
= (GLubyte
*) _mesa_malloc(size
/ 2); /* 1/4 would probably be OK */
4274 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
4275 _mesa_free((void *) srcData
);
4279 /* decompress base image here */
4280 dst
= (GLchan
*) srcData
;
4281 for (row
= 0; row
< srcImage
->Height
; row
++) {
4283 for (col
= 0; col
< srcImage
->Width
; col
++) {
4284 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
4291 convertFormat
= srcImage
->TexFormat
;
4294 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
4295 && level
< maxLevels
- 1; level
++) {
4296 /* generate image[level+1] from image[level] */
4297 const struct gl_texture_image
*srcImage
;
4298 struct gl_texture_image
*dstImage
;
4299 GLint srcWidth
, srcHeight
, srcDepth
;
4300 GLint dstWidth
, dstHeight
, dstDepth
;
4301 GLint border
, bytesPerTexel
;
4303 /* get src image parameters */
4304 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
4306 srcWidth
= srcImage
->Width
;
4307 srcHeight
= srcImage
->Height
;
4308 srcDepth
= srcImage
->Depth
;
4309 border
= srcImage
->Border
;
4311 /* compute next (level+1) image size */
4312 if (srcWidth
- 2 * border
> 1) {
4313 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
4316 dstWidth
= srcWidth
; /* can't go smaller */
4318 if (srcHeight
- 2 * border
> 1) {
4319 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
4322 dstHeight
= srcHeight
; /* can't go smaller */
4324 if (srcDepth
- 2 * border
> 1) {
4325 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
4328 dstDepth
= srcDepth
; /* can't go smaller */
4331 if (dstWidth
== srcWidth
&&
4332 dstHeight
== srcHeight
&&
4333 dstDepth
== srcDepth
) {
4335 if (srcImage
->IsCompressed
) {
4336 _mesa_free((void *) srcData
);
4337 _mesa_free(dstData
);
4342 /* get dest gl_texture_image */
4343 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
4345 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
4349 /* Free old image data */
4351 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
4353 /* initialize new image */
4354 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
4355 dstDepth
, border
, srcImage
->InternalFormat
);
4356 dstImage
->DriverData
= NULL
;
4357 dstImage
->TexFormat
= srcImage
->TexFormat
;
4358 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
4359 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
4360 dstImage
->IsCompressed
= srcImage
->IsCompressed
;
4361 if (dstImage
->IsCompressed
) {
4362 dstImage
->CompressedSize
4363 = ctx
->Driver
.CompressedTextureSize(ctx
, dstImage
->Width
,
4366 dstImage
->TexFormat
->MesaFormat
);
4367 ASSERT(dstImage
->CompressedSize
> 0);
4370 ASSERT(dstImage
->TexFormat
);
4371 ASSERT(dstImage
->FetchTexelc
);
4372 ASSERT(dstImage
->FetchTexelf
);
4374 /* Alloc new teximage data buffer.
4375 * Setup src and dest data pointers.
4377 if (dstImage
->IsCompressed
) {
4378 dstImage
->Data
= _mesa_alloc_texmemory(dstImage
->CompressedSize
);
4379 if (!dstImage
->Data
) {
4380 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
4383 /* srcData and dstData are already set */
4388 bytesPerTexel
= dstImage
->TexFormat
->TexelBytes
;
4389 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
4390 dstImage
->Data
= _mesa_alloc_texmemory(dstWidth
* dstHeight
4391 * dstDepth
* bytesPerTexel
);
4392 if (!dstImage
->Data
) {
4393 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
4396 srcData
= (const GLubyte
*) srcImage
->Data
;
4397 dstData
= (GLubyte
*) dstImage
->Data
;
4401 * We use simple 2x2 averaging to compute the next mipmap level.
4405 make_1d_mipmap(convertFormat
, border
,
4410 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
4411 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
4412 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4413 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4414 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4415 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4416 make_2d_mipmap(convertFormat
, border
,
4417 srcWidth
, srcHeight
, srcData
,
4418 dstWidth
, dstHeight
, dstData
);
4421 make_3d_mipmap(convertFormat
, border
,
4422 srcWidth
, srcHeight
, srcDepth
, srcData
,
4423 dstWidth
, dstHeight
, dstDepth
, dstData
);
4425 case GL_TEXTURE_RECTANGLE_NV
:
4426 /* no mipmaps, do nothing */
4429 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
4433 if (dstImage
->IsCompressed
) {
4435 /* compress image from dstData into dstImage->Data */
4436 const GLenum srcFormat
= convertFormat
->BaseFormat
;
4438 = _mesa_compressed_row_stride(dstImage
->TexFormat
->MesaFormat
, dstWidth
);
4439 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
4440 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->_BaseFormat
,
4441 dstImage
->TexFormat
,
4443 0, 0, 0, /* dstX/Y/Zoffset */
4444 dstRowStride
, 0, /* strides */
4445 dstWidth
, dstHeight
, 1, /* size */
4446 srcFormat
, CHAN_TYPE
,
4447 dstData
, /* src data, actually */
4448 &ctx
->DefaultPacking
);
4449 /* swap src and dest pointers */
4450 temp
= (GLubyte
*) srcData
;
4455 } /* loop over mipmap levels */
4460 * Helper function for drivers which need to rescale texture images to
4461 * certain aspect ratios.
4462 * Nearest filtering only (for broken hardware that can't support
4463 * all aspect ratios). This can be made a lot faster, but I don't
4464 * really care enough...
4467 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
4468 GLuint srcStrideInPixels
,
4469 GLuint dstRowStride
,
4470 GLint srcWidth
, GLint srcHeight
,
4471 GLint dstWidth
, GLint dstHeight
,
4472 const GLvoid
*srcImage
, GLvoid
*dstImage
)
4476 #define INNER_LOOP( TYPE, HOP, WOP ) \
4477 for ( row = 0 ; row < dstHeight ; row++ ) { \
4478 GLint srcRow = row HOP hScale; \
4479 for ( col = 0 ; col < dstWidth ; col++ ) { \
4480 GLint srcCol = col WOP wScale; \
4481 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
4483 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
4486 #define RESCALE_IMAGE( TYPE ) \
4488 const TYPE *src = (const TYPE *)srcImage; \
4489 TYPE *dst = (TYPE *)dstImage; \
4491 if ( srcHeight < dstHeight ) { \
4492 const GLint hScale = dstHeight / srcHeight; \
4493 if ( srcWidth < dstWidth ) { \
4494 const GLint wScale = dstWidth / srcWidth; \
4495 INNER_LOOP( TYPE, /, / ); \
4498 const GLint wScale = srcWidth / dstWidth; \
4499 INNER_LOOP( TYPE, /, * ); \
4503 const GLint hScale = srcHeight / dstHeight; \
4504 if ( srcWidth < dstWidth ) { \
4505 const GLint wScale = dstWidth / srcWidth; \
4506 INNER_LOOP( TYPE, *, / ); \
4509 const GLint wScale = srcWidth / dstWidth; \
4510 INNER_LOOP( TYPE, *, * ); \
4515 switch ( bytesPerPixel
) {
4517 RESCALE_IMAGE( GLuint
);
4521 RESCALE_IMAGE( GLushort
);
4525 RESCALE_IMAGE( GLubyte
);
4528 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
4534 * Upscale an image by replication, not (typical) stretching.
4535 * We use this when the image width or height is less than a
4536 * certain size (4, 8) and we need to upscale an image.
4539 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
4540 GLsizei outWidth
, GLsizei outHeight
,
4541 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
4546 ASSERT(outWidth
>= inWidth
);
4547 ASSERT(outHeight
>= inHeight
);
4549 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
4550 ASSERT((outWidth
& 3) == 0);
4551 ASSERT((outHeight
& 3) == 0);
4554 for (i
= 0; i
< outHeight
; i
++) {
4555 const GLint ii
= i
% inHeight
;
4556 for (j
= 0; j
< outWidth
; j
++) {
4557 const GLint jj
= j
% inWidth
;
4558 for (k
= 0; k
< comps
; k
++) {
4559 dest
[(i
* outWidth
+ j
) * comps
+ k
]
4560 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
4567 #if FEATURE_EXT_texture_sRGB
4570 * Test if given texture image is an sRGB format.
4573 is_srgb_teximage(const struct gl_texture_image
*texImage
)
4575 switch (texImage
->TexFormat
->MesaFormat
) {
4576 case MESA_FORMAT_SRGB8
:
4577 case MESA_FORMAT_SRGBA8
:
4578 case MESA_FORMAT_SL8
:
4579 case MESA_FORMAT_SLA8
:
4586 #endif /* FEATURE_EXT_texture_sRGB */
4590 * This is the software fallback for Driver.GetTexImage().
4591 * All error checking will have been done before this routine is called.
4594 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4595 GLenum format
, GLenum type
, GLvoid
*pixels
,
4596 struct gl_texture_object
*texObj
,
4597 struct gl_texture_image
*texImage
)
4599 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
4601 if (ctx
->Pack
.BufferObj
->Name
) {
4602 /* Packing texture image into a PBO.
4603 * Map the (potentially) VRAM-based buffer into our process space so
4604 * we can write into it with the code below.
4605 * A hardware driver might use a sophisticated blit to move the
4606 * texture data to the PBO if the PBO is in VRAM along with the texture.
4608 GLubyte
*buf
= (GLubyte
*)
4609 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4610 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
4612 /* buffer is already mapped - that's an error */
4613 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
4616 /* <pixels> was an offset into the PBO.
4617 * Now make it a real, client-side pointer inside the mapped region.
4619 pixels
= ADD_POINTERS(buf
, pixels
);
4627 const GLint width
= texImage
->Width
;
4628 const GLint height
= texImage
->Height
;
4629 const GLint depth
= texImage
->Depth
;
4631 for (img
= 0; img
< depth
; img
++) {
4632 for (row
= 0; row
< height
; row
++) {
4633 /* compute destination address in client memory */
4634 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
4635 width
, height
, format
, type
,
4639 if (format
== GL_COLOR_INDEX
) {
4640 GLuint indexRow
[MAX_WIDTH
];
4642 /* Can't use FetchTexel here because that returns RGBA */
4643 if (texImage
->TexFormat
->IndexBits
== 8) {
4644 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
4645 src
+= width
* (img
* texImage
->Height
+ row
);
4646 for (col
= 0; col
< width
; col
++) {
4647 indexRow
[col
] = src
[col
];
4650 else if (texImage
->TexFormat
->IndexBits
== 16) {
4651 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
4652 src
+= width
* (img
* texImage
->Height
+ row
);
4653 for (col
= 0; col
< width
; col
++) {
4654 indexRow
[col
] = src
[col
];
4659 "Color index problem in _mesa_GetTexImage");
4661 _mesa_pack_index_span(ctx
, width
, type
, dest
,
4662 indexRow
, &ctx
->Pack
,
4663 0 /* no image transfer */);
4665 else if (format
== GL_DEPTH_COMPONENT
) {
4666 GLfloat depthRow
[MAX_WIDTH
];
4668 for (col
= 0; col
< width
; col
++) {
4669 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
4672 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
4673 depthRow
, &ctx
->Pack
);
4675 else if (format
== GL_DEPTH_STENCIL_EXT
) {
4676 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4677 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
4678 src
+= width
* row
+ width
* height
* img
;
4679 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
4680 if (ctx
->Pack
.SwapBytes
) {
4681 _mesa_swap4((GLuint
*) dest
, width
);
4684 else if (format
== GL_YCBCR_MESA
) {
4685 /* No pixel transfer */
4686 const GLint rowstride
= texImage
->RowStride
;
4688 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
4689 width
* sizeof(GLushort
));
4690 /* check for byte swapping */
4691 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
4692 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
4693 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
4694 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
4695 if (!ctx
->Pack
.SwapBytes
)
4696 _mesa_swap2((GLushort
*) dest
, width
);
4698 else if (ctx
->Pack
.SwapBytes
) {
4699 _mesa_swap2((GLushort
*) dest
, width
);
4702 #if FEATURE_EXT_texture_sRGB
4703 else if (is_srgb_teximage(texImage
)) {
4704 /* no pixel transfer and no non-linear to linear conversion */
4705 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
4706 const GLint rowstride
= comps
* texImage
->RowStride
;
4708 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
4709 comps
* width
* sizeof(GLubyte
));
4711 #endif /* FEATURE_EXT_texture_sRGB */
4713 /* general case: convert row to RGBA format */
4714 GLfloat rgba
[MAX_WIDTH
][4];
4716 for (col
= 0; col
< width
; col
++) {
4717 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
4719 _mesa_pack_rgba_span_float(ctx
, width
,
4720 (const GLfloat (*)[4]) rgba
,
4721 format
, type
, dest
, &ctx
->Pack
,
4722 0 /* no image transfer */);
4728 if (ctx
->Pack
.BufferObj
->Name
) {
4729 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4730 ctx
->Pack
.BufferObj
);
4737 * This is the software fallback for Driver.GetCompressedTexImage().
4738 * All error checking will have been done before this routine is called.
4741 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4743 const struct gl_texture_object
*texObj
,
4744 const struct gl_texture_image
*texImage
)
4748 if (ctx
->Pack
.BufferObj
->Name
) {
4749 /* pack texture image into a PBO */
4751 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4752 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4753 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4754 "glGetCompressedTexImage(invalid PBO access)");
4757 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4759 ctx
->Pack
.BufferObj
);
4761 /* buffer is already mapped - that's an error */
4762 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4763 "glGetCompressedTexImage(PBO is mapped)");
4766 img
= ADD_POINTERS(buf
, img
);
4773 /* don't use texImage->CompressedSize since that may be padded out */
4774 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
4776 texImage
->TexFormat
->MesaFormat
);
4778 /* just memcpy, no pixelstore or pixel transfer */
4779 _mesa_memcpy(img
, texImage
->Data
, size
);
4781 if (ctx
->Pack
.BufferObj
->Name
) {
4782 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4783 ctx
->Pack
.BufferObj
);