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"
73 static GLboolean
can_swizzle(GLenum logicalBaseFormat
)
75 switch (logicalBaseFormat
) {
78 case GL_LUMINANCE_ALPHA
:
98 #define MAP1(from,to,x) MAP4(from, to, x, ZERO, ZERO, ZERO)
99 #define MAP2(from,to,x,y) MAP4(from, to, x, y, ZERO, ZERO)
100 #define MAP3(from,to,x,y,z) MAP4(from, to, x, y, z, ZERO)
101 #define MAP4(from,to,x,y,z,w) { IDX_##from, IDX_##to, { x, y, z, w, ZERO, ONE } }
104 static const struct {
108 } mappings
[MAX_IDX
][MAX_IDX
] =
111 MAP1(LUMINANCE
, LUMINANCE
, 0),
112 MAP1(ALPHA
, LUMINANCE
, ZERO
),
113 MAP1(INTENSITY
, LUMINANCE
, 0),
114 MAP1(LUMINANCE_ALPHA
, LUMINANCE
, 0),
115 MAP1(RGB
, LUMINANCE
, 0),
116 MAP1(RGBA
, LUMINANCE
, 0),
120 MAP1(LUMINANCE
, ALPHA
, ONE
),
121 MAP1(ALPHA
, ALPHA
, 0),
122 MAP1(INTENSITY
, ALPHA
, 0),
123 MAP1(LUMINANCE_ALPHA
, ALPHA
, 1),
124 MAP1(RGB
, ALPHA
, ONE
),
125 MAP1(RGBA
, ALPHA
, 3),
129 MAP1(LUMINANCE
, INTENSITY
, 0),
130 MAP1(ALPHA
, INTENSITY
, ZERO
),
131 MAP1(INTENSITY
, INTENSITY
, 0),
132 MAP1(LUMINANCE_ALPHA
, INTENSITY
, 0),
133 MAP1(RGB
, INTENSITY
, 0),
134 MAP1(RGBA
, INTENSITY
, 0),
138 MAP2(LUMINANCE
, LUMINANCE_ALPHA
, 0, ONE
),
139 MAP2(ALPHA
, LUMINANCE_ALPHA
, ZERO
, 0),
140 MAP2(INTENSITY
, LUMINANCE_ALPHA
, 0, 0),
141 MAP2(LUMINANCE_ALPHA
, LUMINANCE_ALPHA
, 0, 1),
142 MAP2(RGB
, LUMINANCE_ALPHA
, 0, ONE
),
143 MAP2(RGBA
, LUMINANCE_ALPHA
, 0, 3),
147 MAP3(LUMINANCE
, RGB
, 0, 0, 0),
148 MAP3(ALPHA
, RGB
, ZERO
, ZERO
, ZERO
),
149 MAP3(INTENSITY
, RGB
, 0, 0, 0),
150 MAP3(LUMINANCE_ALPHA
, RGB
, 0, 0, 0),
151 MAP3(RGB
, RGB
, 0, 1, 2),
152 MAP3(RGBA
, RGB
, 0, 1, 2),
156 MAP4(LUMINANCE
, RGBA
, 0, 0, 0, ONE
),
157 MAP4(ALPHA
, RGBA
, ZERO
, ZERO
, ZERO
, 0),
158 MAP4(INTENSITY
, RGBA
, 0, 0, 0, 0),
159 MAP4(LUMINANCE_ALPHA
, RGBA
, 0, 0, 0, 1),
160 MAP4(RGB
, RGBA
, 0, 1, 2, ONE
),
161 MAP4(RGBA
, RGBA
, 0, 1, 2, 3),
170 static int get_map_idx( GLenum value
)
173 case GL_LUMINANCE
: return IDX_LUMINANCE
;
174 case GL_ALPHA
: return IDX_ALPHA
;
175 case GL_INTENSITY
: return IDX_INTENSITY
;
176 case GL_LUMINANCE_ALPHA
: return IDX_LUMINANCE_ALPHA
;
177 case GL_RGB
: return IDX_RGB
;
178 case GL_RGBA
: return IDX_RGBA
;
180 _mesa_problem(NULL
, "Unexpected inFormat");
187 * When promoting texture formats (see below) we need to compute the
188 * mapping of dest components back to source components.
189 * This function does that.
190 * \param inFormat the incoming format of the texture
191 * \param outFormat the final texture format
192 * \return map[6] a full 6-component map
194 static const GLubyte
*
195 compute_component_mapping(GLenum inFormat
, GLenum outFormat
)
197 int in
= get_map_idx(inFormat
);
198 int out
= get_map_idx(outFormat
);
199 ASSERT(mappings
[out
][in
].from
== in
);
200 ASSERT(mappings
[out
][in
].to
== out
);
203 const GLubyte *map = mappings[out][in].map;
204 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
205 inFormat, _mesa_lookup_enum_by_nr(inFormat),
206 outFormat, _mesa_lookup_enum_by_nr(outFormat),
215 return mappings
[out
][in
].map
;
220 * Make a temporary (color) texture image with GLfloat components.
221 * Apply all needed pixel unpacking and pixel transfer operations.
222 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
223 * Suppose the user specifies GL_LUMINANCE as the internal texture format
224 * but the graphics hardware doesn't support luminance textures. So, might
225 * use an RGB hardware format instead.
226 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
228 * \param ctx the rendering context
229 * \param dims image dimensions: 1, 2 or 3
230 * \param logicalBaseFormat basic texture derived from the user's
231 * internal texture format value
232 * \param textureBaseFormat the actual basic format of the texture
233 * \param srcWidth source image width
234 * \param srcHeight source image height
235 * \param srcDepth source image depth
236 * \param srcFormat source image format
237 * \param srcType source image type
238 * \param srcAddr source image address
239 * \param srcPacking source image pixel packing
240 * \return resulting image with format = textureBaseFormat and type = GLfloat.
243 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
244 GLenum logicalBaseFormat
,
245 GLenum textureBaseFormat
,
246 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
247 GLenum srcFormat
, GLenum srcType
,
248 const GLvoid
*srcAddr
,
249 const struct gl_pixelstore_attrib
*srcPacking
)
251 GLuint transferOps
= ctx
->_ImageTransferState
;
254 ASSERT(dims
>= 1 && dims
<= 3);
256 ASSERT(logicalBaseFormat
== GL_RGBA
||
257 logicalBaseFormat
== GL_RGB
||
258 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
259 logicalBaseFormat
== GL_LUMINANCE
||
260 logicalBaseFormat
== GL_ALPHA
||
261 logicalBaseFormat
== GL_INTENSITY
||
262 logicalBaseFormat
== GL_COLOR_INDEX
||
263 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
265 ASSERT(textureBaseFormat
== GL_RGBA
||
266 textureBaseFormat
== GL_RGB
||
267 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
268 textureBaseFormat
== GL_LUMINANCE
||
269 textureBaseFormat
== GL_ALPHA
||
270 textureBaseFormat
== GL_INTENSITY
||
271 textureBaseFormat
== GL_COLOR_INDEX
||
272 textureBaseFormat
== GL_DEPTH_COMPONENT
);
274 /* conventional color image */
276 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
277 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
278 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
279 /* need image convolution */
280 const GLuint preConvTransferOps
281 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
282 const GLuint postConvTransferOps
283 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
285 GLint convWidth
, convHeight
;
288 /* pre-convolution image buffer (3D) */
289 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
290 * 4 * sizeof(GLfloat
));
294 /* post-convolution image buffer (2D) */
295 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
296 * 4 * sizeof(GLfloat
));
298 _mesa_free(tempImage
);
302 /* loop over 3D image slices */
303 for (img
= 0; img
< srcDepth
; img
++) {
304 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
306 /* unpack and do transfer ops up to convolution */
307 for (row
= 0; row
< srcHeight
; row
++) {
308 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
309 srcAddr
, srcWidth
, srcHeight
,
310 srcFormat
, srcType
, img
, row
, 0);
311 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
312 srcFormat
, srcType
, src
,
320 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
321 convWidth
= srcWidth
;
322 convHeight
= srcHeight
;
324 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
325 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
328 if (ctx
->Pixel
.Convolution2DEnabled
) {
329 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
333 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
334 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
340 /* do post-convolution transfer and pack into tempImage */
342 const GLint logComponents
343 = _mesa_components_in_format(logicalBaseFormat
);
344 const GLfloat
*src
= convImage
;
345 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
346 for (row
= 0; row
< convHeight
; row
++) {
347 _mesa_pack_rgba_span_float(ctx
, convWidth
,
348 (const GLfloat (*)[4]) src
,
349 logicalBaseFormat
, GL_FLOAT
,
350 dst
, &ctx
->DefaultPacking
,
351 postConvTransferOps
);
352 src
+= convWidth
* 4;
353 dst
+= convWidth
* logComponents
;
356 } /* loop over 3D image slices */
358 _mesa_free(convImage
);
360 /* might need these below */
361 srcWidth
= convWidth
;
362 srcHeight
= convHeight
;
366 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
367 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
368 srcWidth
, srcFormat
, srcType
);
372 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
373 * components
* sizeof(GLfloat
));
378 for (img
= 0; img
< srcDepth
; img
++) {
380 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
384 for (row
= 0; row
< srcHeight
; row
++) {
385 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
386 dst
, srcFormat
, srcType
, src
,
387 srcPacking
, transferOps
);
388 dst
+= srcWidth
* components
;
394 if (logicalBaseFormat
!= textureBaseFormat
) {
396 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
397 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
402 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
403 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
404 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
406 /* The actual texture format should have at least as many components
407 * as the logical texture format.
409 ASSERT(texComponents
>= logComponents
);
411 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
412 * texComponents
* sizeof(GLfloat
));
414 _mesa_free(tempImage
);
418 map
= compute_component_mapping(logicalBaseFormat
, textureBaseFormat
);
420 n
= srcWidth
* srcHeight
* srcDepth
;
421 for (i
= 0; i
< n
; i
++) {
423 for (k
= 0; k
< texComponents
; k
++) {
426 newImage
[i
* texComponents
+ k
] = 0.0F
;
428 newImage
[i
* texComponents
+ k
] = 1.0F
;
430 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
434 _mesa_free(tempImage
);
435 tempImage
= newImage
;
443 * Make a temporary (color) texture image with GLchan components.
444 * Apply all needed pixel unpacking and pixel transfer operations.
445 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
446 * Suppose the user specifies GL_LUMINANCE as the internal texture format
447 * but the graphics hardware doesn't support luminance textures. So, might
448 * use an RGB hardware format instead.
449 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
451 * \param ctx the rendering context
452 * \param dims image dimensions: 1, 2 or 3
453 * \param logicalBaseFormat basic texture derived from the user's
454 * internal texture format value
455 * \param textureBaseFormat the actual basic format of the texture
456 * \param srcWidth source image width
457 * \param srcHeight source image height
458 * \param srcDepth source image depth
459 * \param srcFormat source image format
460 * \param srcType source image type
461 * \param srcAddr source image address
462 * \param srcPacking source image pixel packing
463 * \return resulting image with format = textureBaseFormat and type = GLchan.
466 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
467 GLenum logicalBaseFormat
,
468 GLenum textureBaseFormat
,
469 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
470 GLenum srcFormat
, GLenum srcType
,
471 const GLvoid
*srcAddr
,
472 const struct gl_pixelstore_attrib
*srcPacking
)
474 GLuint transferOps
= ctx
->_ImageTransferState
;
475 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
476 GLboolean freeSrcImage
= GL_FALSE
;
478 GLchan
*tempImage
, *dst
;
480 ASSERT(dims
>= 1 && dims
<= 3);
482 ASSERT(logicalBaseFormat
== GL_RGBA
||
483 logicalBaseFormat
== GL_RGB
||
484 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
485 logicalBaseFormat
== GL_LUMINANCE
||
486 logicalBaseFormat
== GL_ALPHA
||
487 logicalBaseFormat
== GL_INTENSITY
);
489 ASSERT(textureBaseFormat
== GL_RGBA
||
490 textureBaseFormat
== GL_RGB
||
491 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
492 textureBaseFormat
== GL_LUMINANCE
||
493 textureBaseFormat
== GL_ALPHA
||
494 textureBaseFormat
== GL_INTENSITY
);
496 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
497 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
498 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
499 /* get convolved image */
500 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
503 srcWidth
, srcHeight
, srcDepth
,
505 srcAddr
, srcPacking
);
508 /* the convolved image is our new source image */
510 srcFormat
= logicalBaseFormat
;
512 srcPacking
= &ctx
->DefaultPacking
;
513 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
515 freeSrcImage
= GL_TRUE
;
518 /* unpack and transfer the source image */
519 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
520 * components
* sizeof(GLchan
));
525 for (img
= 0; img
< srcDepth
; img
++) {
526 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
530 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
534 for (row
= 0; row
< srcHeight
; row
++) {
535 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
536 srcFormat
, srcType
, src
, srcPacking
,
538 dst
+= srcWidth
* components
;
543 /* If we made a temporary image for convolution, free it here */
545 _mesa_free((void *) srcAddr
);
548 if (logicalBaseFormat
!= textureBaseFormat
) {
549 /* one more conversion step */
550 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
551 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
556 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
557 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
558 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
560 /* The actual texture format should have at least as many components
561 * as the logical texture format.
563 ASSERT(texComponents
>= logComponents
);
565 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
566 * texComponents
* sizeof(GLchan
));
568 _mesa_free(tempImage
);
572 map
= compute_component_mapping(logicalBaseFormat
, textureBaseFormat
);
574 n
= srcWidth
* srcHeight
* srcDepth
;
575 for (i
= 0; i
< n
; i
++) {
577 for (k
= 0; k
< texComponents
; k
++) {
580 newImage
[i
* texComponents
+ k
] = 0;
582 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
584 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
588 _mesa_free(tempImage
);
589 tempImage
= newImage
;
597 * Copy GLubyte pixels from <src> to <dst> with swizzling.
598 * \param dst destination pixels
599 * \param dstComponents number of color components in destination pixels
600 * \param src source pixels
601 * \param srcComponents number of color components in source pixels
602 * \param map the swizzle mapping
603 * \param count number of pixels to copy/swizzle.
606 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
607 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
615 switch (dstComponents
) {
617 for (i
= 0; i
< count
; i
++) {
619 src
+= srcComponents
;
620 dst
[0] = tmp
[map
[0]];
621 dst
[1] = tmp
[map
[1]];
622 dst
[2] = tmp
[map
[2]];
623 dst
[3] = tmp
[map
[3]];
628 for (i
= 0; i
< count
; i
++) {
630 src
+= srcComponents
;
631 dst
[0] = tmp
[map
[0]];
632 dst
[1] = tmp
[map
[1]];
633 dst
[2] = tmp
[map
[2]];
638 for (i
= 0; i
< count
; i
++) {
640 src
+= srcComponents
;
641 dst
[0] = tmp
[map
[0]];
642 dst
[1] = tmp
[map
[1]];
649 /* Help! I'm just making this up!
651 * This should take the incoming Type, Endian pair and produce a
652 * mapping from that data when examined through a (char *) pointer
653 * natively, to the equivalent of what that data would look like if it
654 * were presented as GL_UNSIGNED_BYTEs on a littleEndian machine... I
657 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, 4, 5 };
658 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, 4, 5 };
661 static const GLubyte
*
662 type_endian_mapping( GLenum srcType
, GLboolean littleEndian
)
666 case GL_UNSIGNED_BYTE
:
671 case GL_UNSIGNED_INT_8_8_8_8
:
673 case GL_UNSIGNED_INT_8_8_8_8_REV
:
680 /* This will have to change to support GL_UNSIGNED_SHORT input types.
681 * It's making my mind swim at the moment though.
683 static const GLubyte
*
684 byteswap_mapping( GLenum srcType
)
687 case GL_UNSIGNED_BYTE
:
689 case GL_UNSIGNED_INT_8_8_8_8
:
690 case GL_UNSIGNED_INT_8_8_8_8_REV
:
701 * Transfer a GLubyte texture image with component swizzling.
704 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
708 GLboolean littleEndian
,
710 GLenum baseInternalFormat
,
712 const GLubyte
*rgba2dst
,
713 GLuint dstComponents
,
716 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
718 const GLuint
*dstImageOffsets
,
720 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
721 const GLvoid
*srcAddr
,
722 const struct gl_pixelstore_attrib
*srcPacking
)
724 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
725 const GLubyte
*src2base
, *base2rgba
, *srctype2ubyte_le
, *swap
;
728 const GLint srcRowStride
=
729 _mesa_image_row_stride(srcPacking
, srcWidth
,
730 srcFormat
, GL_UNSIGNED_BYTE
);
731 const GLint srcImageStride
732 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
734 const GLubyte
*srcImage
735 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
736 srcWidth
, srcHeight
, srcFormat
,
737 GL_UNSIGNED_BYTE
, 0, 0, 0);
741 /* Translate from src->baseInternal->GL_RGBA->dst. This will
742 * correctly deal with RGBA->RGB->RGBA conversions where the final
743 * A value must be 0xff regardless of the incoming alpha values.
745 src2base
= compute_component_mapping(srcFormat
, baseInternalFormat
);
746 base2rgba
= compute_component_mapping(baseInternalFormat
, GL_RGBA
);
747 swap
= byteswap_mapping(srcType
);
748 srctype2ubyte_le
= type_endian_mapping(srcType
, littleEndian
);
751 for (i
= 0; i
< 4; i
++)
752 map
[i
] = srctype2ubyte_le
[swap
[src2base
[base2rgba
[rgba2dst
[i
]]]]];
754 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
756 if (srcRowStride
== srcWidth
* srcComponents
&&
758 /* 1 and 2D images only */
759 GLubyte
*dstImage
= (GLubyte
*) dstAddr
760 + dstYoffset
* dstRowStride
761 + dstXoffset
* dstComponents
;
762 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
763 srcWidth
* srcHeight
);
767 for (img
= 0; img
< srcDepth
; img
++) {
768 const GLubyte
*srcRow
= srcImage
;
769 GLubyte
*dstRow
= (GLubyte
*) dstAddr
770 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
771 + dstYoffset
* dstRowStride
772 + dstXoffset
* dstComponents
;
773 for (row
= 0; row
< srcHeight
; row
++) {
774 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
775 dstRow
+= dstRowStride
;
776 srcRow
+= srcRowStride
;
778 srcImage
+= srcImageStride
;
785 * Teximage storage routine for when a simple memcpy will do.
786 * No pixel transfer operations or special texel encodings allowed.
787 * 1D, 2D and 3D images supported.
790 memcpy_texture(GLcontext
*ctx
,
792 const struct gl_texture_format
*dstFormat
,
794 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
796 const GLuint
*dstImageOffsets
,
797 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
798 GLenum srcFormat
, GLenum srcType
,
799 const GLvoid
*srcAddr
,
800 const struct gl_pixelstore_attrib
*srcPacking
)
802 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
804 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
805 srcWidth
, srcHeight
, srcFormat
, srcType
);
806 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
807 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
808 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
811 /* XXX update/re-enable for dstImageOffsets array */
812 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
813 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
814 GLubyte
*dstImage
= (GLubyte
*) dstAddr
815 + dstZoffset
* dstImageStride
816 + dstYoffset
* dstRowStride
817 + dstXoffset
* dstFormat
->TexelBytes
;
819 if (dstRowStride
== srcRowStride
&&
820 dstRowStride
== bytesPerRow
&&
821 ((dstImageStride
== srcImageStride
&&
822 dstImageStride
== bytesPerImage
) ||
825 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
830 for (img
= 0; img
< srcDepth
; img
++) {
831 const GLubyte
*srcRow
= srcImage
;
832 GLubyte
*dstRow
= dstImage
;
833 for (row
= 0; row
< srcHeight
; row
++) {
834 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
835 dstRow
+= dstRowStride
;
836 srcRow
+= srcRowStride
;
838 srcImage
+= srcImageStride
;
839 dstImage
+= dstImageStride
;
845 for (img
= 0; img
< srcDepth
; img
++) {
846 const GLubyte
*srcRow
= srcImage
;
847 GLubyte
*dstRow
= (GLubyte
*) dstAddr
848 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
849 + dstYoffset
* dstRowStride
850 + dstXoffset
* dstFormat
->TexelBytes
;
851 for (row
= 0; row
< srcHeight
; row
++) {
852 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
853 dstRow
+= dstRowStride
;
854 srcRow
+= srcRowStride
;
856 srcImage
+= srcImageStride
;
863 * Store an image in any of the formats:
864 * _mesa_texformat_rgba
865 * _mesa_texformat_rgb
866 * _mesa_texformat_alpha
867 * _mesa_texformat_luminance
868 * _mesa_texformat_luminance_alpha
869 * _mesa_texformat_intensity
873 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
875 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
877 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
878 dstFormat
== &_mesa_texformat_rgb
||
879 dstFormat
== &_mesa_texformat_alpha
||
880 dstFormat
== &_mesa_texformat_luminance
||
881 dstFormat
== &_mesa_texformat_luminance_alpha
||
882 dstFormat
== &_mesa_texformat_intensity
);
883 ASSERT(baseInternalFormat
== GL_RGBA
||
884 baseInternalFormat
== GL_RGB
||
885 baseInternalFormat
== GL_ALPHA
||
886 baseInternalFormat
== GL_LUMINANCE
||
887 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
888 baseInternalFormat
== GL_INTENSITY
);
889 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
891 if (!ctx
->_ImageTransferState
&&
892 !srcPacking
->SwapBytes
&&
893 baseInternalFormat
== srcFormat
&&
894 srcType
== CHAN_TYPE
) {
895 /* simple memcpy path */
896 memcpy_texture(ctx
, dims
,
897 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
900 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
901 srcAddr
, srcPacking
);
903 else if (!ctx
->_ImageTransferState
&&
904 !srcPacking
->SwapBytes
&&
905 dstFormat
== &_mesa_texformat_rgb
&&
906 srcFormat
== GL_RGBA
&&
907 srcType
== CHAN_TYPE
) {
908 /* extract RGB from RGBA */
910 for (img
= 0; img
< srcDepth
; img
++) {
911 GLchan
*dstImage
= (GLchan
*)
913 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
914 + dstYoffset
* dstRowStride
915 + dstXoffset
* dstFormat
->TexelBytes
);
917 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
918 srcWidth
, srcFormat
, srcType
);
919 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
920 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
921 GLchan
*dstRow
= dstImage
;
922 for (row
= 0; row
< srcHeight
; row
++) {
923 for (col
= 0; col
< srcWidth
; col
++) {
924 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
925 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
926 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
928 dstRow
+= dstRowStride
/ sizeof(GLchan
);
929 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
935 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
937 dstFormat
->BaseFormat
,
938 srcWidth
, srcHeight
, srcDepth
,
939 srcFormat
, srcType
, srcAddr
,
941 const GLchan
*src
= tempImage
;
946 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
947 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
948 for (img
= 0; img
< srcDepth
; img
++) {
949 GLubyte
*dstRow
= (GLubyte
*) dstAddr
950 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
951 + dstYoffset
* dstRowStride
952 + dstXoffset
* dstFormat
->TexelBytes
;
953 for (row
= 0; row
< srcHeight
; row
++) {
954 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
955 dstRow
+= dstRowStride
;
956 src
+= srcWidth
* components
;
960 _mesa_free((void *) tempImage
);
967 * Store a 32-bit integer depth component texture image.
970 _mesa_texstore_z32(TEXSTORE_PARAMS
)
972 const GLfloat depthScale
= (GLfloat
) 0xffffffff;
974 ASSERT(dstFormat
== &_mesa_texformat_z32
);
975 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
977 if (!ctx
->_ImageTransferState
&&
978 !srcPacking
->SwapBytes
&&
979 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
980 srcFormat
== GL_DEPTH_COMPONENT
&&
981 srcType
== GL_UNSIGNED_INT
) {
982 /* simple memcpy path */
983 memcpy_texture(ctx
, dims
,
984 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
987 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
988 srcAddr
, srcPacking
);
993 for (img
= 0; img
< srcDepth
; img
++) {
994 GLubyte
*dstRow
= (GLubyte
*) dstAddr
995 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
996 + dstYoffset
* dstRowStride
997 + dstXoffset
* dstFormat
->TexelBytes
;
998 for (row
= 0; row
< srcHeight
; row
++) {
999 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1000 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1001 _mesa_unpack_depth_span(ctx
, srcWidth
,
1002 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
1003 depthScale
, srcType
, src
, srcPacking
);
1004 dstRow
+= dstRowStride
;
1014 * Store a 16-bit integer depth component texture image.
1017 _mesa_texstore_z16(TEXSTORE_PARAMS
)
1019 const GLfloat depthScale
= 65535.0f
;
1021 ASSERT(dstFormat
== &_mesa_texformat_z16
);
1022 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
1024 if (!ctx
->_ImageTransferState
&&
1025 !srcPacking
->SwapBytes
&&
1026 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
1027 srcFormat
== GL_DEPTH_COMPONENT
&&
1028 srcType
== GL_UNSIGNED_SHORT
) {
1029 /* simple memcpy path */
1030 memcpy_texture(ctx
, dims
,
1031 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1034 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1035 srcAddr
, srcPacking
);
1040 for (img
= 0; img
< srcDepth
; img
++) {
1041 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1042 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1043 + dstYoffset
* dstRowStride
1044 + dstXoffset
* dstFormat
->TexelBytes
;
1045 for (row
= 0; row
< srcHeight
; row
++) {
1046 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1047 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1048 GLushort
*dst16
= (GLushort
*) dstRow
;
1049 _mesa_unpack_depth_span(ctx
, srcWidth
,
1050 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
1051 srcType
, src
, srcPacking
);
1052 dstRow
+= dstRowStride
;
1061 * Store an rgb565 or rgb565_rev texture image.
1064 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
1066 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
1067 dstFormat
== &_mesa_texformat_rgb565_rev
);
1068 ASSERT(dstFormat
->TexelBytes
== 2);
1070 if (!ctx
->_ImageTransferState
&&
1071 !srcPacking
->SwapBytes
&&
1072 dstFormat
== &_mesa_texformat_rgb565
&&
1073 baseInternalFormat
== GL_RGB
&&
1074 srcFormat
== GL_RGB
&&
1075 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
1076 /* simple memcpy path */
1077 memcpy_texture(ctx
, dims
,
1078 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1081 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1082 srcAddr
, srcPacking
);
1084 else if (!ctx
->_ImageTransferState
&&
1085 !srcPacking
->SwapBytes
&&
1086 baseInternalFormat
== GL_RGB
&&
1087 srcFormat
== GL_RGB
&&
1088 srcType
== GL_UNSIGNED_BYTE
&&
1090 /* do optimized tex store */
1091 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1092 srcFormat
, srcType
);
1093 const GLubyte
*src
= (const GLubyte
*)
1094 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1095 srcFormat
, srcType
, 0, 0, 0);
1096 GLubyte
*dst
= (GLubyte
*) dstAddr
1097 + dstYoffset
* dstRowStride
1098 + dstXoffset
* dstFormat
->TexelBytes
;
1100 for (row
= 0; row
< srcHeight
; row
++) {
1101 const GLubyte
*srcUB
= (const GLubyte
*) src
;
1102 GLushort
*dstUS
= (GLushort
*) dst
;
1103 /* check for byteswapped format */
1104 if (dstFormat
== &_mesa_texformat_rgb565
) {
1105 for (col
= 0; col
< srcWidth
; col
++) {
1106 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
1111 for (col
= 0; col
< srcWidth
; col
++) {
1112 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1116 dst
+= dstRowStride
;
1117 src
+= srcRowStride
;
1122 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1124 dstFormat
->BaseFormat
,
1125 srcWidth
, srcHeight
, srcDepth
,
1126 srcFormat
, srcType
, srcAddr
,
1128 const GLchan
*src
= tempImage
;
1129 GLint img
, row
, col
;
1132 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1133 for (img
= 0; img
< srcDepth
; img
++) {
1134 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1135 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1136 + dstYoffset
* dstRowStride
1137 + dstXoffset
* dstFormat
->TexelBytes
;
1138 for (row
= 0; row
< srcHeight
; row
++) {
1139 GLushort
*dstUS
= (GLushort
*) dstRow
;
1140 /* check for byteswapped format */
1141 if (dstFormat
== &_mesa_texformat_rgb565
) {
1142 for (col
= 0; col
< srcWidth
; col
++) {
1143 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1144 CHAN_TO_UBYTE(src
[GCOMP
]),
1145 CHAN_TO_UBYTE(src
[BCOMP
]) );
1150 for (col
= 0; col
< srcWidth
; col
++) {
1151 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1152 CHAN_TO_UBYTE(src
[GCOMP
]),
1153 CHAN_TO_UBYTE(src
[BCOMP
]) );
1157 dstRow
+= dstRowStride
;
1160 _mesa_free((void *) tempImage
);
1167 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1169 const GLuint ui
= 1;
1170 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1173 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1174 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1175 ASSERT(dstFormat
->TexelBytes
== 4);
1177 if (!ctx
->_ImageTransferState
&&
1178 !srcPacking
->SwapBytes
&&
1179 dstFormat
== &_mesa_texformat_rgba8888
&&
1180 baseInternalFormat
== GL_RGBA
&&
1181 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1182 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1183 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1184 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
))) {
1185 /* simple memcpy path */
1186 memcpy_texture(ctx
, dims
,
1187 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1190 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1191 srcAddr
, srcPacking
);
1193 else if (!ctx
->_ImageTransferState
&&
1194 !srcPacking
->SwapBytes
&&
1195 dstFormat
== &_mesa_texformat_rgba8888_rev
&&
1196 baseInternalFormat
== GL_RGBA
&&
1197 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
1198 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1199 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1200 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
))) {
1201 /* simple memcpy path */
1202 memcpy_texture(ctx
, dims
,
1203 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1206 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1207 srcAddr
, srcPacking
);
1209 else if (!ctx
->_ImageTransferState
&&
1210 (srcType
== GL_UNSIGNED_BYTE
||
1211 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1212 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1213 can_swizzle(baseInternalFormat
) &&
1214 can_swizzle(srcFormat
)) {
1218 /* dstmap - how to swizzle from RGBA to dst format:
1220 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1233 _mesa_swizzle_ubyte_image(ctx
, dims
,
1239 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1240 dstRowStride
, dstImageOffsets
,
1241 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1246 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1248 dstFormat
->BaseFormat
,
1249 srcWidth
, srcHeight
, srcDepth
,
1250 srcFormat
, srcType
, srcAddr
,
1252 const GLchan
*src
= tempImage
;
1253 GLint img
, row
, col
;
1256 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1257 for (img
= 0; img
< srcDepth
; img
++) {
1258 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1259 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1260 + dstYoffset
* dstRowStride
1261 + dstXoffset
* dstFormat
->TexelBytes
;
1262 for (row
= 0; row
< srcHeight
; row
++) {
1263 GLuint
*dstUI
= (GLuint
*) dstRow
;
1264 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1265 for (col
= 0; col
< srcWidth
; col
++) {
1266 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1267 CHAN_TO_UBYTE(src
[GCOMP
]),
1268 CHAN_TO_UBYTE(src
[BCOMP
]),
1269 CHAN_TO_UBYTE(src
[ACOMP
]) );
1274 for (col
= 0; col
< srcWidth
; col
++) {
1275 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1276 CHAN_TO_UBYTE(src
[GCOMP
]),
1277 CHAN_TO_UBYTE(src
[BCOMP
]),
1278 CHAN_TO_UBYTE(src
[ACOMP
]) );
1282 dstRow
+= dstRowStride
;
1285 _mesa_free((void *) tempImage
);
1292 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1294 const GLuint ui
= 1;
1295 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1297 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1298 dstFormat
== &_mesa_texformat_argb8888_rev
);
1299 ASSERT(dstFormat
->TexelBytes
== 4);
1301 if (!ctx
->_ImageTransferState
&&
1302 !srcPacking
->SwapBytes
&&
1303 dstFormat
== &_mesa_texformat_argb8888
&&
1304 baseInternalFormat
== GL_RGBA
&&
1305 srcFormat
== GL_BGRA
&&
1306 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1307 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1308 /* simple memcpy path (little endian) */
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
&&
1317 !srcPacking
->SwapBytes
&&
1318 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1319 baseInternalFormat
== GL_RGBA
&&
1320 srcFormat
== GL_BGRA
&&
1321 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1322 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1323 /* simple memcpy path (big endian) */
1324 memcpy_texture(ctx
, dims
,
1325 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1328 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1329 srcAddr
, srcPacking
);
1331 else if (!ctx
->_ImageTransferState
&&
1332 !srcPacking
->SwapBytes
&&
1333 dstFormat
== &_mesa_texformat_argb8888
&&
1334 srcFormat
== GL_RGB
&&
1335 (baseInternalFormat
== GL_RGBA
||
1336 baseInternalFormat
== GL_RGB
) &&
1337 srcType
== GL_UNSIGNED_BYTE
) {
1340 for (img
= 0; img
< srcDepth
; img
++) {
1341 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1342 srcWidth
, srcFormat
, srcType
);
1343 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1344 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1345 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1346 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1347 + dstYoffset
* dstRowStride
1348 + dstXoffset
* dstFormat
->TexelBytes
;
1349 for (row
= 0; row
< srcHeight
; row
++) {
1350 for (col
= 0; col
< srcWidth
; col
++) {
1351 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1352 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1353 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1354 dstRow
[col
* 4 + 3] = 0xff;
1356 dstRow
+= dstRowStride
;
1357 srcRow
+= srcRowStride
;
1361 else if (!ctx
->_ImageTransferState
&&
1362 !srcPacking
->SwapBytes
&&
1363 dstFormat
== &_mesa_texformat_argb8888
&&
1364 srcFormat
== GL_RGBA
&&
1365 baseInternalFormat
== GL_RGBA
&&
1366 (srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
1367 GLint img
, row
, col
;
1368 /* For some reason, streaming copies to write-combined regions
1369 * are extremely sensitive to the characteristics of how the
1370 * source data is retrieved. By reordering the source reads to
1371 * be in-order, the speed of this operation increases by half.
1372 * Strangely the same isn't required for the RGB path, above.
1374 for (img
= 0; img
< srcDepth
; img
++) {
1375 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1376 srcWidth
, srcFormat
, srcType
);
1377 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1378 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1379 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1380 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1381 + dstYoffset
* dstRowStride
1382 + dstXoffset
* dstFormat
->TexelBytes
;
1384 for (row
= 0; row
< srcHeight
; row
++) {
1385 for (col
= 0; col
< srcWidth
; col
++) {
1386 *(GLuint
*)(dstRow
+ col
* 4) = (srcRow
[col
* 4 + RCOMP
] << 16 |
1387 srcRow
[col
* 4 + GCOMP
] << 8 |
1388 srcRow
[col
* 4 + BCOMP
] << 0 |
1389 srcRow
[col
* 4 + ACOMP
] << 24);
1391 dstRow
+= dstRowStride
;
1392 srcRow
+= srcRowStride
;
1396 else if (!ctx
->_ImageTransferState
&&
1397 !srcPacking
->SwapBytes
&&
1398 dstFormat
== &_mesa_texformat_argb8888
&&
1399 srcFormat
== GL_RGBA
&&
1400 baseInternalFormat
== GL_RGBA
&&
1401 srcType
== GL_UNSIGNED_BYTE
) {
1403 GLint img
, row
, col
;
1404 for (img
= 0; img
< srcDepth
; img
++) {
1405 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1406 srcWidth
, srcFormat
, srcType
);
1407 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1408 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1409 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1410 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1411 + dstYoffset
* dstRowStride
1412 + dstXoffset
* dstFormat
->TexelBytes
;
1413 for (row
= 0; row
< srcHeight
; row
++) {
1414 for (col
= 0; col
< srcWidth
; col
++) {
1415 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1416 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1417 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1418 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1420 dstRow
+= dstRowStride
;
1421 srcRow
+= srcRowStride
;
1425 else if (!ctx
->_ImageTransferState
&&
1426 (srcType
== GL_UNSIGNED_BYTE
||
1427 srcType
== GL_UNSIGNED_INT_8_8_8_8
||
1428 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) &&
1429 can_swizzle(baseInternalFormat
) &&
1430 can_swizzle(srcFormat
)) {
1434 /* dstmap - how to swizzle from RGBA to dst format:
1436 if (dstFormat
== &_mesa_texformat_argb8888
) {
1437 dstmap
[3] = 3; /* alpha */
1438 dstmap
[2] = 0; /* red */
1439 dstmap
[1] = 1; /* green */
1440 dstmap
[0] = 2; /* blue */
1443 assert(dstFormat
== &_mesa_texformat_argb8888_rev
);
1450 _mesa_swizzle_ubyte_image(ctx
, dims
,
1457 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1460 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1465 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1467 dstFormat
->BaseFormat
,
1468 srcWidth
, srcHeight
, srcDepth
,
1469 srcFormat
, srcType
, srcAddr
,
1471 const GLchan
*src
= tempImage
;
1472 GLint img
, row
, col
;
1475 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1476 for (img
= 0; img
< srcDepth
; img
++) {
1477 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1478 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1479 + dstYoffset
* dstRowStride
1480 + dstXoffset
* dstFormat
->TexelBytes
;
1481 for (row
= 0; row
< srcHeight
; row
++) {
1482 GLuint
*dstUI
= (GLuint
*) dstRow
;
1483 if (dstFormat
== &_mesa_texformat_argb8888
) {
1484 for (col
= 0; col
< srcWidth
; col
++) {
1485 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1486 CHAN_TO_UBYTE(src
[RCOMP
]),
1487 CHAN_TO_UBYTE(src
[GCOMP
]),
1488 CHAN_TO_UBYTE(src
[BCOMP
]) );
1493 for (col
= 0; col
< srcWidth
; col
++) {
1494 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1495 CHAN_TO_UBYTE(src
[RCOMP
]),
1496 CHAN_TO_UBYTE(src
[GCOMP
]),
1497 CHAN_TO_UBYTE(src
[BCOMP
]) );
1501 dstRow
+= dstRowStride
;
1504 _mesa_free((void *) tempImage
);
1511 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1513 const GLuint ui
= 1;
1514 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1516 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1517 ASSERT(dstFormat
->TexelBytes
== 3);
1519 if (!ctx
->_ImageTransferState
&&
1520 !srcPacking
->SwapBytes
&&
1521 baseInternalFormat
== GL_RGB
&&
1522 srcFormat
== GL_BGR
&&
1523 srcType
== GL_UNSIGNED_BYTE
&&
1525 /* simple memcpy path */
1526 memcpy_texture(ctx
, dims
,
1527 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1530 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1531 srcAddr
, srcPacking
);
1533 else if (!ctx
->_ImageTransferState
&&
1534 !srcPacking
->SwapBytes
&&
1535 srcFormat
== GL_RGBA
&&
1536 srcType
== GL_UNSIGNED_BYTE
) {
1537 /* extract RGB from RGBA */
1538 GLint img
, row
, col
;
1539 for (img
= 0; img
< srcDepth
; img
++) {
1540 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1541 srcWidth
, srcFormat
, srcType
);
1542 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1543 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1544 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1545 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1546 + dstYoffset
* dstRowStride
1547 + dstXoffset
* dstFormat
->TexelBytes
;
1548 for (row
= 0; row
< srcHeight
; row
++) {
1549 for (col
= 0; col
< srcWidth
; col
++) {
1550 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1551 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1552 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1554 dstRow
+= dstRowStride
;
1555 srcRow
+= srcRowStride
;
1561 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1563 dstFormat
->BaseFormat
,
1564 srcWidth
, srcHeight
, srcDepth
,
1565 srcFormat
, srcType
, srcAddr
,
1567 const GLchan
*src
= (const GLchan
*) tempImage
;
1568 GLint img
, row
, col
;
1571 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1572 for (img
= 0; img
< srcDepth
; img
++) {
1573 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1574 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1575 + dstYoffset
* dstRowStride
1576 + dstXoffset
* dstFormat
->TexelBytes
;
1577 for (row
= 0; row
< srcHeight
; row
++) {
1580 for (col
= 0; col
< srcWidth
; col
++) {
1581 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1582 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1583 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1588 for (col
= 0; col
< srcWidth
; col
++) {
1589 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1590 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1591 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1596 for (col
= 0; col
< srcWidth
; col
++) {
1597 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1598 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1599 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1603 dstRow
+= dstRowStride
;
1606 _mesa_free((void *) tempImage
);
1613 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1615 const GLuint ui
= 1;
1616 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1618 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1619 ASSERT(dstFormat
->TexelBytes
== 3);
1621 if (!ctx
->_ImageTransferState
&&
1622 !srcPacking
->SwapBytes
&&
1623 baseInternalFormat
== GL_RGB
&&
1624 srcFormat
== GL_RGB
&&
1625 srcType
== GL_UNSIGNED_BYTE
&&
1627 /* simple memcpy path */
1628 memcpy_texture(ctx
, dims
,
1629 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1632 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1633 srcAddr
, srcPacking
);
1635 else if (!ctx
->_ImageTransferState
&&
1636 !srcPacking
->SwapBytes
&&
1637 srcFormat
== GL_RGBA
&&
1638 srcType
== GL_UNSIGNED_BYTE
) {
1639 /* extract BGR from RGBA */
1641 for (img
= 0; img
< srcDepth
; img
++) {
1642 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1643 srcWidth
, srcFormat
, srcType
);
1644 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1645 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1646 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1647 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1648 + dstYoffset
* dstRowStride
1649 + dstXoffset
* dstFormat
->TexelBytes
;
1650 for (row
= 0; row
< srcHeight
; row
++) {
1651 for (col
= 0; col
< srcWidth
; col
++) {
1652 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1653 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1654 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1656 dstRow
+= dstRowStride
;
1657 srcRow
+= srcRowStride
;
1663 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1665 dstFormat
->BaseFormat
,
1666 srcWidth
, srcHeight
, srcDepth
,
1667 srcFormat
, srcType
, srcAddr
,
1669 const GLchan
*src
= (const GLchan
*) tempImage
;
1670 GLint img
, row
, col
;
1673 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1674 for (img
= 0; img
< srcDepth
; img
++) {
1675 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1676 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1677 + dstYoffset
* dstRowStride
1678 + dstXoffset
* dstFormat
->TexelBytes
;
1679 for (row
= 0; row
< srcHeight
; row
++) {
1680 for (col
= 0; col
< srcWidth
; col
++) {
1681 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1682 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1683 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1686 dstRow
+= dstRowStride
;
1689 _mesa_free((void *) tempImage
);
1696 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1698 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1699 dstFormat
== &_mesa_texformat_argb4444_rev
);
1700 ASSERT(dstFormat
->TexelBytes
== 2);
1702 if (!ctx
->_ImageTransferState
&&
1703 !srcPacking
->SwapBytes
&&
1704 dstFormat
== &_mesa_texformat_argb4444
&&
1705 baseInternalFormat
== GL_RGBA
&&
1706 srcFormat
== GL_BGRA
&&
1707 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1708 /* simple memcpy path */
1709 memcpy_texture(ctx
, dims
,
1710 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1713 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1714 srcAddr
, srcPacking
);
1718 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1720 dstFormat
->BaseFormat
,
1721 srcWidth
, srcHeight
, srcDepth
,
1722 srcFormat
, srcType
, srcAddr
,
1724 const GLchan
*src
= tempImage
;
1725 GLint img
, row
, col
;
1728 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1729 for (img
= 0; img
< srcDepth
; img
++) {
1730 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1731 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1732 + dstYoffset
* dstRowStride
1733 + dstXoffset
* dstFormat
->TexelBytes
;
1734 for (row
= 0; row
< srcHeight
; row
++) {
1735 GLushort
*dstUS
= (GLushort
*) dstRow
;
1736 if (dstFormat
== &_mesa_texformat_argb4444
) {
1737 for (col
= 0; col
< srcWidth
; col
++) {
1738 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1739 CHAN_TO_UBYTE(src
[RCOMP
]),
1740 CHAN_TO_UBYTE(src
[GCOMP
]),
1741 CHAN_TO_UBYTE(src
[BCOMP
]) );
1746 for (col
= 0; col
< srcWidth
; col
++) {
1747 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1748 CHAN_TO_UBYTE(src
[RCOMP
]),
1749 CHAN_TO_UBYTE(src
[GCOMP
]),
1750 CHAN_TO_UBYTE(src
[BCOMP
]) );
1754 dstRow
+= dstRowStride
;
1757 _mesa_free((void *) tempImage
);
1765 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1767 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1768 dstFormat
== &_mesa_texformat_argb1555_rev
);
1769 ASSERT(dstFormat
->TexelBytes
== 2);
1771 if (!ctx
->_ImageTransferState
&&
1772 !srcPacking
->SwapBytes
&&
1773 dstFormat
== &_mesa_texformat_argb1555
&&
1774 baseInternalFormat
== GL_RGBA
&&
1775 srcFormat
== GL_BGRA
&&
1776 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1777 /* simple memcpy path */
1778 memcpy_texture(ctx
, dims
,
1779 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1782 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1783 srcAddr
, srcPacking
);
1787 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1789 dstFormat
->BaseFormat
,
1790 srcWidth
, srcHeight
, srcDepth
,
1791 srcFormat
, srcType
, srcAddr
,
1793 const GLchan
*src
=tempImage
;
1794 GLint img
, row
, col
;
1797 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1798 for (img
= 0; img
< srcDepth
; img
++) {
1799 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1800 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1801 + dstYoffset
* dstRowStride
1802 + dstXoffset
* dstFormat
->TexelBytes
;
1803 for (row
= 0; row
< srcHeight
; row
++) {
1804 GLushort
*dstUS
= (GLushort
*) dstRow
;
1805 if (dstFormat
== &_mesa_texformat_argb1555
) {
1806 for (col
= 0; col
< srcWidth
; col
++) {
1807 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1808 CHAN_TO_UBYTE(src
[RCOMP
]),
1809 CHAN_TO_UBYTE(src
[GCOMP
]),
1810 CHAN_TO_UBYTE(src
[BCOMP
]) );
1815 for (col
= 0; col
< srcWidth
; col
++) {
1816 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1817 CHAN_TO_UBYTE(src
[RCOMP
]),
1818 CHAN_TO_UBYTE(src
[GCOMP
]),
1819 CHAN_TO_UBYTE(src
[BCOMP
]) );
1823 dstRow
+= dstRowStride
;
1826 _mesa_free((void *) tempImage
);
1833 _mesa_texstore_al88(TEXSTORE_PARAMS
)
1835 const GLuint ui
= 1;
1836 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1838 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1839 dstFormat
== &_mesa_texformat_al88_rev
);
1840 ASSERT(dstFormat
->TexelBytes
== 2);
1842 if (!ctx
->_ImageTransferState
&&
1843 !srcPacking
->SwapBytes
&&
1844 dstFormat
== &_mesa_texformat_al88
&&
1845 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1846 srcFormat
== GL_LUMINANCE_ALPHA
&&
1847 srcType
== GL_UNSIGNED_BYTE
&&
1849 /* simple memcpy path */
1850 memcpy_texture(ctx
, dims
,
1851 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1854 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1855 srcAddr
, srcPacking
);
1859 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1861 dstFormat
->BaseFormat
,
1862 srcWidth
, srcHeight
, srcDepth
,
1863 srcFormat
, srcType
, srcAddr
,
1865 const GLchan
*src
= tempImage
;
1866 GLint img
, row
, col
;
1869 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1870 for (img
= 0; img
< srcDepth
; img
++) {
1871 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1872 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1873 + dstYoffset
* dstRowStride
1874 + dstXoffset
* dstFormat
->TexelBytes
;
1875 for (row
= 0; row
< srcHeight
; row
++) {
1876 GLushort
*dstUS
= (GLushort
*) dstRow
;
1877 if (dstFormat
== &_mesa_texformat_al88
) {
1878 for (col
= 0; col
< srcWidth
; col
++) {
1879 /* src[0] is luminance, src[1] is alpha */
1880 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1881 CHAN_TO_UBYTE(src
[0]) );
1886 for (col
= 0; col
< srcWidth
; col
++) {
1887 /* src[0] is luminance, src[1] is alpha */
1888 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1889 CHAN_TO_UBYTE(src
[0]) );
1893 dstRow
+= dstRowStride
;
1896 _mesa_free((void *) tempImage
);
1903 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
1905 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1906 ASSERT(dstFormat
->TexelBytes
== 1);
1908 if (!ctx
->_ImageTransferState
&&
1909 !srcPacking
->SwapBytes
&&
1910 baseInternalFormat
== GL_RGB
&&
1911 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1912 /* simple memcpy path */
1913 memcpy_texture(ctx
, dims
,
1914 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1917 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1918 srcAddr
, srcPacking
);
1922 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1924 dstFormat
->BaseFormat
,
1925 srcWidth
, srcHeight
, srcDepth
,
1926 srcFormat
, srcType
, srcAddr
,
1928 const GLchan
*src
= tempImage
;
1929 GLint img
, row
, col
;
1932 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1933 for (img
= 0; img
< srcDepth
; img
++) {
1934 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1935 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1936 + dstYoffset
* dstRowStride
1937 + dstXoffset
* dstFormat
->TexelBytes
;
1938 for (row
= 0; row
< srcHeight
; row
++) {
1939 for (col
= 0; col
< srcWidth
; col
++) {
1940 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1941 CHAN_TO_UBYTE(src
[GCOMP
]),
1942 CHAN_TO_UBYTE(src
[BCOMP
]) );
1945 dstRow
+= dstRowStride
;
1948 _mesa_free((void *) tempImage
);
1955 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1958 _mesa_texstore_a8(TEXSTORE_PARAMS
)
1960 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1961 dstFormat
== &_mesa_texformat_l8
||
1962 dstFormat
== &_mesa_texformat_i8
);
1963 ASSERT(dstFormat
->TexelBytes
== 1);
1965 if (!ctx
->_ImageTransferState
&&
1966 !srcPacking
->SwapBytes
&&
1967 baseInternalFormat
== srcFormat
&&
1968 srcType
== GL_UNSIGNED_BYTE
) {
1969 /* simple memcpy path */
1970 memcpy_texture(ctx
, dims
,
1971 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1974 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1975 srcAddr
, srcPacking
);
1979 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1981 dstFormat
->BaseFormat
,
1982 srcWidth
, srcHeight
, srcDepth
,
1983 srcFormat
, srcType
, srcAddr
,
1985 const GLchan
*src
= tempImage
;
1986 GLint img
, row
, col
;
1989 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1990 for (img
= 0; img
< srcDepth
; img
++) {
1991 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1992 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1993 + dstYoffset
* dstRowStride
1994 + dstXoffset
* dstFormat
->TexelBytes
;
1995 for (row
= 0; row
< srcHeight
; row
++) {
1996 for (col
= 0; col
< srcWidth
; col
++) {
1997 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1999 dstRow
+= dstRowStride
;
2003 _mesa_free((void *) tempImage
);
2011 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
2013 (void) dims
; (void) baseInternalFormat
;
2014 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
2015 ASSERT(dstFormat
->TexelBytes
== 1);
2016 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
2018 if (!ctx
->_ImageTransferState
&&
2019 !srcPacking
->SwapBytes
&&
2020 srcFormat
== GL_COLOR_INDEX
&&
2021 srcType
== GL_UNSIGNED_BYTE
) {
2022 /* simple memcpy path */
2023 memcpy_texture(ctx
, dims
,
2024 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2027 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2028 srcAddr
, srcPacking
);
2033 for (img
= 0; img
< srcDepth
; img
++) {
2034 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2035 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2036 + dstYoffset
* dstRowStride
2037 + dstXoffset
* dstFormat
->TexelBytes
;
2038 for (row
= 0; row
< srcHeight
; row
++) {
2039 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
2040 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
2041 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
2042 srcType
, src
, srcPacking
,
2043 ctx
->_ImageTransferState
);
2044 dstRow
+= dstRowStride
;
2053 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2056 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
2058 const GLuint ui
= 1;
2059 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
2060 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
2062 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
2063 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
2064 ASSERT(dstFormat
->TexelBytes
== 2);
2065 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
2066 ASSERT(srcFormat
== GL_YCBCR_MESA
);
2067 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
2068 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
2069 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
2071 /* always just memcpy since no pixel transfer ops apply */
2072 memcpy_texture(ctx
, dims
,
2073 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2076 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2077 srcAddr
, srcPacking
);
2079 /* Check if we need byte swapping */
2080 /* XXX the logic here _might_ be wrong */
2081 if (srcPacking
->SwapBytes
^
2082 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
2083 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
2086 for (img
= 0; img
< srcDepth
; img
++) {
2087 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2088 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2089 + dstYoffset
* dstRowStride
2090 + dstXoffset
* dstFormat
->TexelBytes
;
2091 for (row
= 0; row
< srcHeight
; row
++) {
2092 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
2093 dstRow
+= dstRowStride
;
2103 * Store a combined depth/stencil texture image.
2106 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
2108 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
2109 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
2110 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
2112 if (!ctx
->_ImageTransferState
&&
2113 !srcPacking
->SwapBytes
) {
2115 memcpy_texture(ctx
, dims
,
2116 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2119 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2120 srcAddr
, srcPacking
);
2124 const GLint srcRowStride
2125 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2129 for (img
= 0; img
< srcDepth
; img
++) {
2130 GLuint
*dstRow
= (GLuint
*) dstAddr
2131 + dstImageOffsets
[dstZoffset
+ img
]
2132 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
2135 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2136 srcWidth
, srcHeight
,
2139 for (row
= 0; row
< srcHeight
; row
++) {
2140 GLubyte stencil
[MAX_WIDTH
];
2142 /* the 24 depth bits will be in the high position: */
2143 _mesa_unpack_depth_span(ctx
, srcWidth
,
2144 GL_UNSIGNED_INT
, /* dst type */
2145 dstRow
, /* dst addr */
2146 (GLfloat
) 0xffffff, /* depthScale */
2147 srcType
, src
, srcPacking
);
2148 /* get the 8-bit stencil values */
2149 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2150 GL_UNSIGNED_BYTE
, /* dst type */
2151 stencil
, /* dst addr */
2152 srcType
, src
, srcPacking
,
2153 ctx
->_ImageTransferState
);
2154 /* merge stencil values into depth values */
2155 for (i
= 0; i
< srcWidth
; i
++)
2156 dstRow
[i
] |= stencil
[i
];
2158 src
+= srcRowStride
;
2159 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2169 * Store an image in any of the formats:
2170 * _mesa_texformat_rgba_float32
2171 * _mesa_texformat_rgb_float32
2172 * _mesa_texformat_alpha_float32
2173 * _mesa_texformat_luminance_float32
2174 * _mesa_texformat_luminance_alpha_float32
2175 * _mesa_texformat_intensity_float32
2178 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2180 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2182 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2183 dstFormat
== &_mesa_texformat_rgb_float32
||
2184 dstFormat
== &_mesa_texformat_alpha_float32
||
2185 dstFormat
== &_mesa_texformat_luminance_float32
||
2186 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2187 dstFormat
== &_mesa_texformat_intensity_float32
);
2188 ASSERT(baseInternalFormat
== GL_RGBA
||
2189 baseInternalFormat
== GL_RGB
||
2190 baseInternalFormat
== GL_ALPHA
||
2191 baseInternalFormat
== GL_LUMINANCE
||
2192 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2193 baseInternalFormat
== GL_INTENSITY
);
2194 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2196 if (!ctx
->_ImageTransferState
&&
2197 !srcPacking
->SwapBytes
&&
2198 baseInternalFormat
== srcFormat
&&
2199 srcType
== GL_FLOAT
) {
2200 /* simple memcpy path */
2201 memcpy_texture(ctx
, dims
,
2202 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2205 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2206 srcAddr
, srcPacking
);
2210 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2212 dstFormat
->BaseFormat
,
2213 srcWidth
, srcHeight
, srcDepth
,
2214 srcFormat
, srcType
, srcAddr
,
2216 const GLfloat
*srcRow
= tempImage
;
2221 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2222 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2223 for (img
= 0; img
< srcDepth
; img
++) {
2224 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2225 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2226 + dstYoffset
* dstRowStride
2227 + dstXoffset
* dstFormat
->TexelBytes
;
2228 for (row
= 0; row
< srcHeight
; row
++) {
2229 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2230 dstRow
+= dstRowStride
;
2231 srcRow
+= srcWidth
* components
;
2235 _mesa_free((void *) tempImage
);
2242 * As above, but store 16-bit floats.
2245 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2247 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2249 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2250 dstFormat
== &_mesa_texformat_rgb_float16
||
2251 dstFormat
== &_mesa_texformat_alpha_float16
||
2252 dstFormat
== &_mesa_texformat_luminance_float16
||
2253 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2254 dstFormat
== &_mesa_texformat_intensity_float16
);
2255 ASSERT(baseInternalFormat
== GL_RGBA
||
2256 baseInternalFormat
== GL_RGB
||
2257 baseInternalFormat
== GL_ALPHA
||
2258 baseInternalFormat
== GL_LUMINANCE
||
2259 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2260 baseInternalFormat
== GL_INTENSITY
);
2261 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2263 if (!ctx
->_ImageTransferState
&&
2264 !srcPacking
->SwapBytes
&&
2265 baseInternalFormat
== srcFormat
&&
2266 srcType
== GL_HALF_FLOAT_ARB
) {
2267 /* simple memcpy path */
2268 memcpy_texture(ctx
, dims
,
2269 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2272 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2273 srcAddr
, srcPacking
);
2277 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2279 dstFormat
->BaseFormat
,
2280 srcWidth
, srcHeight
, srcDepth
,
2281 srcFormat
, srcType
, srcAddr
,
2283 const GLfloat
*src
= tempImage
;
2287 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2288 for (img
= 0; img
< srcDepth
; img
++) {
2289 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2290 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2291 + dstYoffset
* dstRowStride
2292 + dstXoffset
* dstFormat
->TexelBytes
;
2293 for (row
= 0; row
< srcHeight
; row
++) {
2294 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2296 for (i
= 0; i
< srcWidth
* components
; i
++) {
2297 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2299 dstRow
+= dstRowStride
;
2300 src
+= srcWidth
* components
;
2304 _mesa_free((void *) tempImage
);
2310 #if FEATURE_EXT_texture_sRGB
2312 _mesa_texstore_srgb8(TEXSTORE_PARAMS
)
2314 const GLuint ui
= 1;
2315 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
2316 const struct gl_texture_format
*newDstFormat
;
2317 StoreTexImageFunc store
;
2320 ASSERT(dstFormat
== &_mesa_texformat_srgb8
);
2322 /* reuse normal rgb texstore code */
2324 newDstFormat
= &_mesa_texformat_bgr888
;
2325 store
= _mesa_texstore_bgr888
;
2328 newDstFormat
= &_mesa_texformat_rgb888
;
2329 store
= _mesa_texstore_rgb888
;
2332 k
= store(ctx
, dims
, baseInternalFormat
,
2333 newDstFormat
, dstAddr
,
2334 dstXoffset
, dstYoffset
, dstZoffset
,
2335 dstRowStride
, dstImageOffsets
,
2336 srcWidth
, srcHeight
, srcDepth
,
2338 srcAddr
, srcPacking
);
2344 _mesa_texstore_srgba8(TEXSTORE_PARAMS
)
2346 const GLuint ui
= 1;
2347 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
2348 const struct gl_texture_format
*newDstFormat
;
2351 ASSERT(dstFormat
== &_mesa_texformat_srgba8
);
2353 /* reuse normal rgba texstore code */
2355 newDstFormat
= &_mesa_texformat_rgba8888_rev
;
2357 newDstFormat
= &_mesa_texformat_rgba8888
;
2359 k
= _mesa_texstore_rgba8888(ctx
, dims
, baseInternalFormat
,
2360 newDstFormat
, dstAddr
,
2361 dstXoffset
, dstYoffset
, dstZoffset
,
2362 dstRowStride
, dstImageOffsets
,
2363 srcWidth
, srcHeight
, srcDepth
,
2365 srcAddr
, srcPacking
);
2371 _mesa_texstore_sl8(TEXSTORE_PARAMS
)
2373 const struct gl_texture_format
*newDstFormat
;
2376 ASSERT(dstFormat
== &_mesa_texformat_sl8
);
2378 newDstFormat
= &_mesa_texformat_l8
;
2380 /* _mesa_textore_a8 handles luminance8 too */
2381 k
= _mesa_texstore_a8(ctx
, dims
, baseInternalFormat
,
2382 newDstFormat
, dstAddr
,
2383 dstXoffset
, dstYoffset
, dstZoffset
,
2384 dstRowStride
, dstImageOffsets
,
2385 srcWidth
, srcHeight
, srcDepth
,
2387 srcAddr
, srcPacking
);
2393 _mesa_texstore_sla8(TEXSTORE_PARAMS
)
2395 const GLuint ui
= 1;
2396 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
2397 const struct gl_texture_format
*newDstFormat
;
2400 ASSERT(dstFormat
== &_mesa_texformat_sla8
);
2402 /* reuse normal luminance/alpha texstore code */
2404 newDstFormat
= &_mesa_texformat_al88
;
2406 newDstFormat
= &_mesa_texformat_al88_rev
;
2408 k
= _mesa_texstore_al88(ctx
, dims
, baseInternalFormat
,
2409 newDstFormat
, dstAddr
,
2410 dstXoffset
, dstYoffset
, dstZoffset
,
2411 dstRowStride
, dstImageOffsets
,
2412 srcWidth
, srcHeight
, srcDepth
,
2414 srcAddr
, srcPacking
);
2418 #endif /* FEATURE_EXT_texture_sRGB */
2422 * Check if an unpack PBO is active prior to fetching a texture image.
2423 * If so, do bounds checking and map the buffer into main memory.
2424 * Any errors detected will be recorded.
2425 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2428 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2429 GLsizei width
, GLsizei height
, GLsizei depth
,
2430 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2431 const struct gl_pixelstore_attrib
*unpack
,
2432 const char *funcName
)
2436 if (unpack
->BufferObj
->Name
== 0) {
2440 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2441 format
, type
, pixels
)) {
2442 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2446 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2447 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2449 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2453 return ADD_POINTERS(buf
, pixels
);
2458 * Check if an unpack PBO is active prior to fetching a compressed texture
2460 * If so, do bounds checking and map the buffer into main memory.
2461 * Any errors detected will be recorded.
2462 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2465 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2466 GLsizei imageSize
, const GLvoid
*pixels
,
2467 const struct gl_pixelstore_attrib
*packing
,
2468 const char *funcName
)
2472 if (packing
->BufferObj
->Name
== 0) {
2473 /* not using a PBO - return pointer unchanged */
2476 if ((const GLubyte
*) pixels
+ imageSize
>
2477 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2478 /* out of bounds read! */
2479 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2483 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2484 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2486 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2490 return ADD_POINTERS(buf
, pixels
);
2495 * This function must be called after either of the validate_pbo_*_teximage()
2496 * functions. It unmaps the PBO buffer if it was mapped earlier.
2499 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2500 const struct gl_pixelstore_attrib
*unpack
)
2502 if (unpack
->BufferObj
->Name
) {
2503 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2511 * Adaptor for fetching a GLchan texel from a float-valued texture.
2514 FetchTexelFloatToChan( const struct gl_texture_image
*texImage
,
2515 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2518 ASSERT(texImage
->FetchTexelf
);
2519 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2520 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2521 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2522 /* just one channel */
2523 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2527 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2528 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2529 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2530 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2536 * Adaptor for fetching a float texel from a GLchan-valued texture.
2539 FetchTexelChanToFloat( const struct gl_texture_image
*texImage
,
2540 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2543 ASSERT(texImage
->FetchTexelc
);
2544 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2545 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2546 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2547 /* just one channel */
2548 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2552 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2553 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2554 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2555 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2561 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2564 set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2566 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2567 ASSERT(texImage
->TexFormat
);
2571 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2572 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2575 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2576 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2579 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2580 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2586 /* now check if we need to use a float/chan adaptor */
2587 if (!texImage
->FetchTexelc
) {
2588 texImage
->FetchTexelc
= FetchTexelFloatToChan
;
2590 else if (!texImage
->FetchTexelf
) {
2591 texImage
->FetchTexelf
= FetchTexelChanToFloat
;
2595 ASSERT(texImage
->FetchTexelc
);
2596 ASSERT(texImage
->FetchTexelf
);
2601 * Choose the actual storage format for a new texture image.
2602 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2603 * Also set some other texImage fields related to texture compression, etc.
2604 * \param ctx rendering context
2605 * \param texImage the gl_texture_image
2606 * \param dims texture dimensions (1, 2 or 3)
2607 * \param format the user-specified format parameter
2608 * \param type the user-specified type parameter
2609 * \param internalFormat the user-specified internal format hint
2612 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2614 GLenum format
, GLenum type
, GLint internalFormat
)
2616 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2617 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2620 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2622 ASSERT(texImage
->TexFormat
);
2624 set_fetch_functions(texImage
, dims
);
2626 if (texImage
->TexFormat
->TexelBytes
== 0) {
2627 /* must be a compressed format */
2628 texImage
->IsCompressed
= GL_TRUE
;
2629 texImage
->CompressedSize
=
2630 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2631 texImage
->Height
, texImage
->Depth
,
2632 texImage
->TexFormat
->MesaFormat
);
2635 /* non-compressed format */
2636 texImage
->IsCompressed
= GL_FALSE
;
2637 texImage
->CompressedSize
= 0;
2644 * This is the software fallback for Driver.TexImage1D()
2645 * and Driver.CopyTexImage1D().
2646 * \sa _mesa_store_teximage2d()
2649 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2650 GLint internalFormat
,
2651 GLint width
, GLint border
,
2652 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2653 const struct gl_pixelstore_attrib
*packing
,
2654 struct gl_texture_object
*texObj
,
2655 struct gl_texture_image
*texImage
)
2657 GLint postConvWidth
= width
;
2661 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2662 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2665 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2667 /* allocate memory */
2668 if (texImage
->IsCompressed
)
2669 sizeInBytes
= texImage
->CompressedSize
;
2671 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2672 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2673 if (!texImage
->Data
) {
2674 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2678 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2679 pixels
, packing
, "glTexImage1D");
2681 /* Note: we check for a NULL image pointer here, _after_ we allocated
2682 * memory for the texture. That's what the GL spec calls for.
2687 const GLint dstRowStride
= 0;
2689 ASSERT(texImage
->TexFormat
->StoreImage
);
2690 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2691 texImage
->TexFormat
,
2693 0, 0, 0, /* dstX/Y/Zoffset */
2695 texImage
->ImageOffsets
,
2697 format
, type
, pixels
, packing
);
2699 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2703 /* GL_SGIS_generate_mipmap */
2704 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2705 _mesa_generate_mipmap(ctx
, target
,
2706 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2710 _mesa_unmap_teximage_pbo(ctx
, packing
);
2715 * This is the software fallback for Driver.TexImage2D()
2716 * and Driver.CopyTexImage2D().
2718 * This function is oriented toward storing images in main memory, rather
2719 * than VRAM. Device driver's can easily plug in their own replacement.
2721 * Note: width and height may be pre-convolved dimensions, but
2722 * texImage->Width and texImage->Height will be post-convolved dimensions.
2725 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2726 GLint internalFormat
,
2727 GLint width
, GLint height
, GLint border
,
2728 GLenum format
, GLenum type
, const void *pixels
,
2729 const struct gl_pixelstore_attrib
*packing
,
2730 struct gl_texture_object
*texObj
,
2731 struct gl_texture_image
*texImage
)
2733 GLint postConvWidth
= width
, postConvHeight
= height
;
2734 GLint texelBytes
, sizeInBytes
;
2737 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2738 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2742 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2744 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2746 /* allocate memory */
2747 if (texImage
->IsCompressed
)
2748 sizeInBytes
= texImage
->CompressedSize
;
2750 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2751 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2752 if (!texImage
->Data
) {
2753 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2757 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2758 pixels
, packing
, "glTexImage2D");
2760 /* Note: we check for a NULL image pointer here, _after_ we allocated
2761 * memory for the texture. That's what the GL spec calls for.
2768 if (texImage
->IsCompressed
) {
2770 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2773 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2775 ASSERT(texImage
->TexFormat
->StoreImage
);
2776 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2777 texImage
->TexFormat
,
2779 0, 0, 0, /* dstX/Y/Zoffset */
2781 texImage
->ImageOffsets
,
2783 format
, type
, pixels
, packing
);
2785 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2789 /* GL_SGIS_generate_mipmap */
2790 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2791 _mesa_generate_mipmap(ctx
, target
,
2792 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2796 _mesa_unmap_teximage_pbo(ctx
, packing
);
2802 * This is the software fallback for Driver.TexImage3D()
2803 * and Driver.CopyTexImage3D().
2804 * \sa _mesa_store_teximage2d()
2807 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2808 GLint internalFormat
,
2809 GLint width
, GLint height
, GLint depth
, GLint border
,
2810 GLenum format
, GLenum type
, const void *pixels
,
2811 const struct gl_pixelstore_attrib
*packing
,
2812 struct gl_texture_object
*texObj
,
2813 struct gl_texture_image
*texImage
)
2815 GLint texelBytes
, sizeInBytes
;
2818 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
2820 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2822 /* allocate memory */
2823 if (texImage
->IsCompressed
)
2824 sizeInBytes
= texImage
->CompressedSize
;
2826 sizeInBytes
= width
* height
* depth
* texelBytes
;
2827 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2828 if (!texImage
->Data
) {
2829 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2833 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2834 type
, pixels
, packing
, "glTexImage3D");
2836 /* Note: we check for a NULL image pointer here, _after_ we allocated
2837 * memory for the texture. That's what the GL spec calls for.
2844 if (texImage
->IsCompressed
) {
2846 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2849 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2851 ASSERT(texImage
->TexFormat
->StoreImage
);
2852 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2853 texImage
->TexFormat
,
2855 0, 0, 0, /* dstX/Y/Zoffset */
2857 texImage
->ImageOffsets
,
2858 width
, height
, depth
,
2859 format
, type
, pixels
, packing
);
2861 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2865 /* GL_SGIS_generate_mipmap */
2866 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2867 _mesa_generate_mipmap(ctx
, target
,
2868 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2872 _mesa_unmap_teximage_pbo(ctx
, packing
);
2879 * This is the software fallback for Driver.TexSubImage1D()
2880 * and Driver.CopyTexSubImage1D().
2883 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2884 GLint xoffset
, GLint width
,
2885 GLenum format
, GLenum type
, const void *pixels
,
2886 const struct gl_pixelstore_attrib
*packing
,
2887 struct gl_texture_object
*texObj
,
2888 struct gl_texture_image
*texImage
)
2890 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2891 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2892 pixels
, packing
, "glTexSubImage1D");
2897 const GLint dstRowStride
= 0;
2899 ASSERT(texImage
->TexFormat
->StoreImage
);
2900 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2901 texImage
->TexFormat
,
2903 xoffset
, 0, 0, /* offsets */
2905 texImage
->ImageOffsets
,
2907 format
, type
, pixels
, packing
);
2909 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
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
);
2926 * This is the software fallback for Driver.TexSubImage2D()
2927 * and Driver.CopyTexSubImage2D().
2930 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2931 GLint xoffset
, GLint yoffset
,
2932 GLint width
, GLint height
,
2933 GLenum format
, GLenum type
, const void *pixels
,
2934 const struct gl_pixelstore_attrib
*packing
,
2935 struct gl_texture_object
*texObj
,
2936 struct gl_texture_image
*texImage
)
2938 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2939 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2940 pixels
, packing
, "glTexSubImage2D");
2945 GLint dstRowStride
= 0;
2947 if (texImage
->IsCompressed
) {
2948 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
2952 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2954 ASSERT(texImage
->TexFormat
->StoreImage
);
2955 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2956 texImage
->TexFormat
,
2958 xoffset
, yoffset
, 0,
2960 texImage
->ImageOffsets
,
2962 format
, type
, pixels
, packing
);
2964 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2968 /* GL_SGIS_generate_mipmap */
2969 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2970 _mesa_generate_mipmap(ctx
, target
,
2971 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2975 _mesa_unmap_teximage_pbo(ctx
, packing
);
2980 * This is the software fallback for Driver.TexSubImage3D().
2981 * and Driver.CopyTexSubImage3D().
2984 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2985 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2986 GLint width
, GLint height
, GLint depth
,
2987 GLenum format
, GLenum type
, const void *pixels
,
2988 const struct gl_pixelstore_attrib
*packing
,
2989 struct gl_texture_object
*texObj
,
2990 struct gl_texture_image
*texImage
)
2992 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2993 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2994 type
, pixels
, packing
,
3002 if (texImage
->IsCompressed
) {
3003 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
3007 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
3009 ASSERT(texImage
->TexFormat
->StoreImage
);
3010 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
3011 texImage
->TexFormat
,
3013 xoffset
, yoffset
, zoffset
,
3015 texImage
->ImageOffsets
,
3016 width
, height
, depth
,
3017 format
, type
, pixels
, packing
);
3019 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
3023 /* GL_SGIS_generate_mipmap */
3024 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3025 _mesa_generate_mipmap(ctx
, target
,
3026 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3030 _mesa_unmap_teximage_pbo(ctx
, packing
);
3035 * Fallback for Driver.CompressedTexImage1D()
3038 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
3039 GLint internalFormat
,
3040 GLint width
, GLint border
,
3041 GLsizei imageSize
, const GLvoid
*data
,
3042 struct gl_texture_object
*texObj
,
3043 struct gl_texture_image
*texImage
)
3045 /* this space intentionally left blank */
3047 (void) target
; (void) level
;
3048 (void) internalFormat
;
3049 (void) width
; (void) border
;
3050 (void) imageSize
; (void) data
;
3058 * Fallback for Driver.CompressedTexImage2D()
3061 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
3062 GLint internalFormat
,
3063 GLint width
, GLint height
, GLint border
,
3064 GLsizei imageSize
, const GLvoid
*data
,
3065 struct gl_texture_object
*texObj
,
3066 struct gl_texture_image
*texImage
)
3068 (void) width
; (void) height
; (void) border
;
3070 /* This is pretty simple, basically just do a memcpy without worrying
3071 * about the usual image unpacking or image transfer operations.
3075 ASSERT(texImage
->Width
> 0);
3076 ASSERT(texImage
->Height
> 0);
3077 ASSERT(texImage
->Depth
== 1);
3078 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
3080 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
3082 /* allocate storage */
3083 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
3084 if (!texImage
->Data
) {
3085 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3089 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3091 "glCompressedTexImage2D");
3096 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
3097 MEMCPY(texImage
->Data
, data
, imageSize
);
3099 /* GL_SGIS_generate_mipmap */
3100 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3101 _mesa_generate_mipmap(ctx
, target
,
3102 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3106 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3112 * Fallback for Driver.CompressedTexImage3D()
3115 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
3116 GLint internalFormat
,
3117 GLint width
, GLint height
, GLint depth
,
3119 GLsizei imageSize
, const GLvoid
*data
,
3120 struct gl_texture_object
*texObj
,
3121 struct gl_texture_image
*texImage
)
3123 /* this space intentionally left blank */
3125 (void) target
; (void) level
;
3126 (void) internalFormat
;
3127 (void) width
; (void) height
; (void) depth
;
3129 (void) imageSize
; (void) data
;
3137 * Fallback for Driver.CompressedTexSubImage1D()
3140 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
3142 GLint xoffset
, GLsizei width
,
3144 GLsizei imageSize
, const GLvoid
*data
,
3145 struct gl_texture_object
*texObj
,
3146 struct gl_texture_image
*texImage
)
3148 /* there are no compressed 1D texture formats yet */
3150 (void) target
; (void) level
;
3151 (void) xoffset
; (void) width
;
3153 (void) imageSize
; (void) data
;
3160 * Fallback for Driver.CompressedTexSubImage2D()
3163 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
3165 GLint xoffset
, GLint yoffset
,
3166 GLsizei width
, GLsizei height
,
3168 GLsizei imageSize
, const GLvoid
*data
,
3169 struct gl_texture_object
*texObj
,
3170 struct gl_texture_image
*texImage
)
3172 GLint bytesPerRow
, destRowStride
, srcRowStride
;
3176 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
3180 /* these should have been caught sooner */
3181 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
3182 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
3183 ASSERT((xoffset
& 3) == 0);
3184 ASSERT((yoffset
& 3) == 0);
3186 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3187 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
3189 "glCompressedTexSubImage2D");
3193 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
3194 src
= (const GLubyte
*) data
;
3196 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
3197 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
3198 texImage
->TexFormat
->MesaFormat
,
3200 (GLubyte
*) texImage
->Data
);
3202 bytesPerRow
= srcRowStride
;
3205 for (i
= 0; i
< rows
; i
++) {
3206 MEMCPY(dest
, src
, bytesPerRow
);
3207 dest
+= destRowStride
;
3208 src
+= srcRowStride
;
3211 /* GL_SGIS_generate_mipmap */
3212 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
3213 _mesa_generate_mipmap(ctx
, target
,
3214 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
3218 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
3223 * Fallback for Driver.CompressedTexSubImage3D()
3226 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
3228 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3229 GLsizei width
, GLsizei height
, GLsizei depth
,
3231 GLsizei imageSize
, const GLvoid
*data
,
3232 struct gl_texture_object
*texObj
,
3233 struct gl_texture_image
*texImage
)
3235 /* there are no compressed 3D texture formats yet */
3237 (void) target
; (void) level
;
3238 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3239 (void) width
; (void) height
; (void) depth
;
3241 (void) imageSize
; (void) data
;
3248 * Average together two rows of a source image to produce a single new
3249 * row in the dest image. It's legal for the two source rows to point
3250 * to the same data. The source width must be equal to either the
3251 * dest width or two times the dest width.
3254 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
3255 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
3256 GLint dstWidth
, GLvoid
*dstRow
)
3258 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
3259 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
3261 /* This assertion is no longer valid with non-power-of-2 textures
3262 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
3265 switch (format
->MesaFormat
) {
3266 case MESA_FORMAT_RGBA
:
3269 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
3270 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
3271 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
3272 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3273 i
++, j
+= colStride
, k
+= colStride
) {
3274 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3275 rowB
[j
][0] + rowB
[k
][0]) / 4;
3276 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3277 rowB
[j
][1] + rowB
[k
][1]) / 4;
3278 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3279 rowB
[j
][2] + rowB
[k
][2]) / 4;
3280 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3281 rowB
[j
][3] + rowB
[k
][3]) / 4;
3285 case MESA_FORMAT_RGB
:
3288 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
3289 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
3290 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
3291 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3292 i
++, j
+= colStride
, k
+= colStride
) {
3293 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3294 rowB
[j
][0] + rowB
[k
][0]) / 4;
3295 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3296 rowB
[j
][1] + rowB
[k
][1]) / 4;
3297 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3298 rowB
[j
][2] + rowB
[k
][2]) / 4;
3302 case MESA_FORMAT_ALPHA
:
3303 case MESA_FORMAT_LUMINANCE
:
3304 case MESA_FORMAT_INTENSITY
:
3307 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
3308 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
3309 GLchan
*dst
= (GLchan
*) dstRow
;
3310 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3311 i
++, j
+= colStride
, k
+= colStride
) {
3312 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3316 case MESA_FORMAT_LUMINANCE_ALPHA
:
3319 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
3320 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
3321 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
3322 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3323 i
++, j
+= colStride
, k
+= colStride
) {
3324 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3325 rowB
[j
][0] + rowB
[k
][0]) / 4;
3326 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3327 rowB
[j
][1] + rowB
[k
][1]) / 4;
3331 case MESA_FORMAT_Z32
:
3334 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
3335 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
3336 GLfloat
*dst
= (GLfloat
*) dstRow
;
3337 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3338 i
++, j
+= colStride
, k
+= colStride
) {
3339 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
3343 case MESA_FORMAT_Z16
:
3346 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3347 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3348 GLushort
*dst
= (GLushort
*) dstRow
;
3349 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3350 i
++, j
+= colStride
, k
+= colStride
) {
3351 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3355 /* Begin hardware formats */
3356 case MESA_FORMAT_RGBA8888
:
3357 case MESA_FORMAT_RGBA8888_REV
:
3358 case MESA_FORMAT_ARGB8888
:
3359 case MESA_FORMAT_ARGB8888_REV
:
3360 #if FEATURE_EXT_texture_sRGB
3361 case MESA_FORMAT_SRGBA8
:
3365 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
3366 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
3367 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
3368 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3369 i
++, j
+= colStride
, k
+= colStride
) {
3370 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3371 rowB
[j
][0] + rowB
[k
][0]) / 4;
3372 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3373 rowB
[j
][1] + rowB
[k
][1]) / 4;
3374 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3375 rowB
[j
][2] + rowB
[k
][2]) / 4;
3376 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3377 rowB
[j
][3] + rowB
[k
][3]) / 4;
3381 case MESA_FORMAT_RGB888
:
3382 case MESA_FORMAT_BGR888
:
3383 #if FEATURE_EXT_texture_sRGB
3384 case MESA_FORMAT_SRGB8
:
3388 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
3389 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
3390 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
3391 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3392 i
++, j
+= colStride
, k
+= colStride
) {
3393 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3394 rowB
[j
][0] + rowB
[k
][0]) / 4;
3395 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3396 rowB
[j
][1] + rowB
[k
][1]) / 4;
3397 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3398 rowB
[j
][2] + rowB
[k
][2]) / 4;
3402 case MESA_FORMAT_RGB565
:
3403 case MESA_FORMAT_RGB565_REV
:
3406 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3407 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3408 GLushort
*dst
= (GLushort
*) dstRow
;
3409 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3410 i
++, j
+= colStride
, k
+= colStride
) {
3411 const GLint rowAr0
= rowA
[j
] & 0x1f;
3412 const GLint rowAr1
= rowA
[k
] & 0x1f;
3413 const GLint rowBr0
= rowB
[j
] & 0x1f;
3414 const GLint rowBr1
= rowB
[k
] & 0x1f;
3415 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
3416 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
3417 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
3418 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
3419 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
3420 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
3421 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
3422 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
3423 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3424 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3425 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3426 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
3430 case MESA_FORMAT_ARGB4444
:
3431 case MESA_FORMAT_ARGB4444_REV
:
3434 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3435 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3436 GLushort
*dst
= (GLushort
*) dstRow
;
3437 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3438 i
++, j
+= colStride
, k
+= colStride
) {
3439 const GLint rowAr0
= rowA
[j
] & 0xf;
3440 const GLint rowAr1
= rowA
[k
] & 0xf;
3441 const GLint rowBr0
= rowB
[j
] & 0xf;
3442 const GLint rowBr1
= rowB
[k
] & 0xf;
3443 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
3444 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
3445 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
3446 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
3447 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
3448 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
3449 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
3450 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
3451 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
3452 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
3453 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
3454 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
3455 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3456 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3457 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3458 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3459 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
3463 case MESA_FORMAT_ARGB1555
:
3464 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
3467 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3468 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3469 GLushort
*dst
= (GLushort
*) dstRow
;
3470 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3471 i
++, j
+= colStride
, k
+= colStride
) {
3472 const GLint rowAr0
= rowA
[j
] & 0x1f;
3473 const GLint rowAr1
= rowA
[k
] & 0x1f;
3474 const GLint rowBr0
= rowB
[j
] & 0x1f;
3475 const GLint rowBr1
= rowB
[k
] & 0xf;
3476 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
3477 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
3478 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
3479 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
3480 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
3481 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3482 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3483 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3484 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3485 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3486 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3487 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3488 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3489 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3490 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3491 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3492 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3496 case MESA_FORMAT_AL88
:
3497 case MESA_FORMAT_AL88_REV
:
3498 #if FEATURE_EXT_texture_sRGB
3499 case MESA_FORMAT_SLA8
:
3503 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3504 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3505 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3506 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3507 i
++, j
+= colStride
, k
+= colStride
) {
3508 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3509 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3510 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3511 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3515 case MESA_FORMAT_RGB332
:
3518 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3519 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3520 GLubyte
*dst
= (GLubyte
*) dstRow
;
3521 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3522 i
++, j
+= colStride
, k
+= colStride
) {
3523 const GLint rowAr0
= rowA
[j
] & 0x3;
3524 const GLint rowAr1
= rowA
[k
] & 0x3;
3525 const GLint rowBr0
= rowB
[j
] & 0x3;
3526 const GLint rowBr1
= rowB
[k
] & 0x3;
3527 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3528 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3529 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3530 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3531 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3532 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3533 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3534 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3535 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3536 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3537 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3538 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3542 case MESA_FORMAT_A8
:
3543 case MESA_FORMAT_L8
:
3544 case MESA_FORMAT_I8
:
3545 case MESA_FORMAT_CI8
:
3546 #if FEATURE_EXT_texture_sRGB
3547 case MESA_FORMAT_SL8
:
3551 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3552 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3553 GLubyte
*dst
= (GLubyte
*) dstRow
;
3554 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3555 i
++, j
+= colStride
, k
+= colStride
) {
3556 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
3560 case MESA_FORMAT_RGBA_FLOAT32
:
3563 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3564 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3565 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
3566 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3567 i
++, j
+= colStride
, k
+= colStride
) {
3568 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3569 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3570 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3571 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3572 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3573 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3574 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3575 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3579 case MESA_FORMAT_RGBA_FLOAT16
:
3581 GLuint i
, j
, k
, comp
;
3582 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3583 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3584 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3585 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3586 i
++, j
+= colStride
, k
+= colStride
) {
3587 for (comp
= 0; comp
< 4; comp
++) {
3588 GLfloat aj
, ak
, bj
, bk
;
3589 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3590 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3591 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3592 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3593 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3598 case MESA_FORMAT_RGB_FLOAT32
:
3601 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3602 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3603 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3604 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3605 i
++, j
+= colStride
, k
+= colStride
) {
3606 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3607 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3608 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3609 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3610 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3611 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3615 case MESA_FORMAT_RGB_FLOAT16
:
3617 GLuint i
, j
, k
, comp
;
3618 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3619 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3620 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3621 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3622 i
++, j
+= colStride
, k
+= colStride
) {
3623 for (comp
= 0; comp
< 3; comp
++) {
3624 GLfloat aj
, ak
, bj
, bk
;
3625 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3626 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3627 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3628 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3629 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3634 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3637 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3638 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3639 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3640 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3641 i
++, j
+= colStride
, k
+= colStride
) {
3642 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3643 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3644 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3645 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3649 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3651 GLuint i
, j
, k
, comp
;
3652 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3653 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3654 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3655 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3656 i
++, j
+= colStride
, k
+= colStride
) {
3657 for (comp
= 0; comp
< 2; comp
++) {
3658 GLfloat aj
, ak
, bj
, bk
;
3659 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3660 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3661 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3662 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3663 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3668 case MESA_FORMAT_ALPHA_FLOAT32
:
3669 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3670 case MESA_FORMAT_INTENSITY_FLOAT32
:
3673 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3674 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3675 GLfloat
*dst
= (GLfloat
*) dstRow
;
3676 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3677 i
++, j
+= colStride
, k
+= colStride
) {
3678 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3682 case MESA_FORMAT_ALPHA_FLOAT16
:
3683 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3684 case MESA_FORMAT_INTENSITY_FLOAT16
:
3687 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3688 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3689 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3690 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3691 i
++, j
+= colStride
, k
+= colStride
) {
3692 GLfloat aj
, ak
, bj
, bk
;
3693 aj
= _mesa_half_to_float(rowA
[j
]);
3694 ak
= _mesa_half_to_float(rowA
[k
]);
3695 bj
= _mesa_half_to_float(rowB
[j
]);
3696 bk
= _mesa_half_to_float(rowB
[k
]);
3697 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3703 _mesa_problem(NULL
, "bad format in do_row()");
3709 * These functions generate a 1/2-size mipmap image from a source image.
3710 * Texture borders are handled by copying or averaging the source image's
3711 * border texels, depending on the scale-down factor.
3715 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3716 GLint srcWidth
, const GLubyte
*srcPtr
,
3717 GLint dstWidth
, GLubyte
*dstPtr
)
3719 const GLint bpt
= format
->TexelBytes
;
3723 /* skip the border pixel, if any */
3724 src
= srcPtr
+ border
* bpt
;
3725 dst
= dstPtr
+ border
* bpt
;
3727 /* we just duplicate the input row, kind of hack, saves code */
3728 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3729 dstWidth
- 2 * border
, dst
);
3732 /* copy left-most pixel from source */
3733 MEMCPY(dstPtr
, srcPtr
, bpt
);
3734 /* copy right-most pixel from source */
3735 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3736 srcPtr
+ (srcWidth
- 1) * bpt
,
3743 * XXX need to use the tex image's row stride!
3746 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3747 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3748 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3750 const GLint bpt
= format
->TexelBytes
;
3751 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3752 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3753 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3754 const GLint srcRowStride
= bpt
* srcWidth
;
3755 const GLint dstRowStride
= bpt
* dstWidth
;
3756 const GLubyte
*srcA
, *srcB
;
3760 /* Compute src and dst pointers, skipping any border */
3761 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3763 srcB
= srcA
+ srcRowStride
;
3766 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3768 for (row
= 0; row
< dstHeightNB
; row
++) {
3769 do_row(format
, srcWidthNB
, srcA
, srcB
,
3771 srcA
+= 2 * srcRowStride
;
3772 srcB
+= 2 * srcRowStride
;
3773 dst
+= dstRowStride
;
3776 /* This is ugly but probably won't be used much */
3778 /* fill in dest border */
3779 /* lower-left border pixel */
3780 MEMCPY(dstPtr
, srcPtr
, bpt
);
3781 /* lower-right border pixel */
3782 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3783 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3784 /* upper-left border pixel */
3785 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3786 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3787 /* upper-right border pixel */
3788 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3789 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3791 do_row(format
, srcWidthNB
,
3794 dstWidthNB
, dstPtr
+ bpt
);
3796 do_row(format
, srcWidthNB
,
3797 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3798 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3800 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3801 /* left and right borders */
3802 if (srcHeight
== dstHeight
) {
3803 /* copy border pixel from src to dst */
3804 for (row
= 1; row
< srcHeight
; row
++) {
3805 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3806 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3807 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3808 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3812 /* average two src pixels each dest pixel */
3813 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3815 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3816 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3817 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3819 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3820 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3821 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3829 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3830 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3831 const GLubyte
*srcPtr
,
3832 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3835 const GLint bpt
= format
->TexelBytes
;
3836 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3837 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3838 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3839 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3840 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3841 GLvoid
*tmpRowA
, *tmpRowB
;
3843 GLint bytesPerSrcImage
, bytesPerDstImage
;
3844 GLint bytesPerSrcRow
, bytesPerDstRow
;
3845 GLint srcImageOffset
, srcRowOffset
;
3847 (void) srcDepthNB
; /* silence warnings */
3849 /* Need two temporary row buffers */
3850 tmpRowA
= _mesa_malloc(srcWidth
* bpt
);
3853 tmpRowB
= _mesa_malloc(srcWidth
* bpt
);
3855 _mesa_free(tmpRowA
);
3859 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3860 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3862 bytesPerSrcRow
= srcWidth
* bpt
;
3863 bytesPerDstRow
= dstWidth
* bpt
;
3865 /* Offset between adjacent src images to be averaged together */
3866 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3868 /* Offset between adjacent src rows to be averaged together */
3869 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3872 * Need to average together up to 8 src pixels for each dest pixel.
3873 * Break that down into 3 operations:
3874 * 1. take two rows from source image and average them together.
3875 * 2. take two rows from next source image and average them together.
3876 * 3. take the two averaged rows and average them for the final dst row.
3880 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3881 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3884 for (img
= 0; img
< dstDepthNB
; img
++) {
3885 /* first source image pointer, skipping border */
3886 const GLubyte
*imgSrcA
= srcPtr
3887 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3888 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3889 /* second source image pointer, skipping border */
3890 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3891 /* address of the dest image, skipping border */
3892 GLubyte
*imgDst
= dstPtr
3893 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3894 + img
* bytesPerDstImage
;
3896 /* setup the four source row pointers and the dest row pointer */
3897 const GLubyte
*srcImgARowA
= imgSrcA
;
3898 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3899 const GLubyte
*srcImgBRowA
= imgSrcB
;
3900 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3901 GLubyte
*dstImgRow
= imgDst
;
3903 for (row
= 0; row
< dstHeightNB
; row
++) {
3904 /* Average together two rows from first src image */
3905 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3906 srcWidthNB
, tmpRowA
);
3907 /* Average together two rows from second src image */
3908 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3909 srcWidthNB
, tmpRowB
);
3910 /* Average together the temp rows to make the final row */
3911 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3912 dstWidthNB
, dstImgRow
);
3913 /* advance to next rows */
3914 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3915 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3916 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3917 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3918 dstImgRow
+= bytesPerDstRow
;
3922 _mesa_free(tmpRowA
);
3923 _mesa_free(tmpRowB
);
3925 /* Luckily we can leverage the make_2d_mipmap() function here! */
3927 /* do front border image */
3928 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3929 dstWidth
, dstHeight
, dstPtr
);
3930 /* do back border image */
3931 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3932 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3933 dstWidth
, dstHeight
,
3934 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3935 /* do four remaining border edges that span the image slices */
3936 if (srcDepth
== dstDepth
) {
3937 /* just copy border pixels from src to dst */
3938 for (img
= 0; img
< dstDepthNB
; img
++) {
3942 /* do border along [img][row=0][col=0] */
3943 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3944 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3945 MEMCPY(dst
, src
, bpt
);
3947 /* do border along [img][row=dstHeight-1][col=0] */
3948 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3949 + (srcHeight
- 1) * bytesPerSrcRow
;
3950 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3951 + (dstHeight
- 1) * bytesPerDstRow
;
3952 MEMCPY(dst
, src
, bpt
);
3954 /* do border along [img][row=0][col=dstWidth-1] */
3955 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3956 + (srcWidth
- 1) * bpt
;
3957 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3958 + (dstWidth
- 1) * bpt
;
3959 MEMCPY(dst
, src
, bpt
);
3961 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3962 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3963 + (bytesPerSrcImage
- bpt
);
3964 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3965 + (bytesPerDstImage
- bpt
);
3966 MEMCPY(dst
, src
, bpt
);
3970 /* average border pixels from adjacent src image pairs */
3971 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3972 for (img
= 0; img
< dstDepthNB
; img
++) {
3976 /* do border along [img][row=0][col=0] */
3977 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3978 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3979 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3981 /* do border along [img][row=dstHeight-1][col=0] */
3982 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3983 + (srcHeight
- 1) * bytesPerSrcRow
;
3984 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3985 + (dstHeight
- 1) * bytesPerDstRow
;
3986 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3988 /* do border along [img][row=0][col=dstWidth-1] */
3989 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3990 + (srcWidth
- 1) * bpt
;
3991 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3992 + (dstWidth
- 1) * bpt
;
3993 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3995 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3996 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3997 + (bytesPerSrcImage
- bpt
);
3998 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3999 + (bytesPerDstImage
- bpt
);
4000 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
4008 * For GL_SGIX_generate_mipmap:
4009 * Generate a complete set of mipmaps from texObj's base-level image.
4010 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
4013 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
4014 const struct gl_texture_unit
*texUnit
,
4015 struct gl_texture_object
*texObj
)
4017 const struct gl_texture_image
*srcImage
;
4018 const struct gl_texture_format
*convertFormat
;
4019 const GLubyte
*srcData
= NULL
;
4020 GLubyte
*dstData
= NULL
;
4021 GLint level
, maxLevels
;
4024 /* XXX choose cube map face here??? */
4025 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
4028 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
4029 ASSERT(maxLevels
> 0); /* bad target */
4031 /* Find convertFormat - the format that do_row() will process */
4032 if (srcImage
->IsCompressed
) {
4033 /* setup for compressed textures */
4035 GLint components
, size
;
4038 assert(texObj
->Target
== GL_TEXTURE_2D
);
4040 if (srcImage
->_BaseFormat
== GL_RGB
) {
4041 convertFormat
= &_mesa_texformat_rgb
;
4044 else if (srcImage
->_BaseFormat
== GL_RGBA
) {
4045 convertFormat
= &_mesa_texformat_rgba
;
4049 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
4053 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
4054 size
= _mesa_bytes_per_pixel(srcImage
->_BaseFormat
, CHAN_TYPE
)
4055 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
4056 /* 20 extra bytes, just be safe when calling last FetchTexel */
4057 srcData
= (GLubyte
*) _mesa_malloc(size
);
4059 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
4062 dstData
= (GLubyte
*) _mesa_malloc(size
/ 2); /* 1/4 would probably be OK */
4064 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
4065 _mesa_free((void *) srcData
);
4069 /* decompress base image here */
4070 dst
= (GLchan
*) srcData
;
4071 for (row
= 0; row
< srcImage
->Height
; row
++) {
4073 for (col
= 0; col
< srcImage
->Width
; col
++) {
4074 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
4081 convertFormat
= srcImage
->TexFormat
;
4084 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
4085 && level
< maxLevels
- 1; level
++) {
4086 /* generate image[level+1] from image[level] */
4087 const struct gl_texture_image
*srcImage
;
4088 struct gl_texture_image
*dstImage
;
4089 GLint srcWidth
, srcHeight
, srcDepth
;
4090 GLint dstWidth
, dstHeight
, dstDepth
;
4091 GLint border
, bytesPerTexel
;
4093 /* get src image parameters */
4094 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
4096 srcWidth
= srcImage
->Width
;
4097 srcHeight
= srcImage
->Height
;
4098 srcDepth
= srcImage
->Depth
;
4099 border
= srcImage
->Border
;
4101 /* compute next (level+1) image size */
4102 if (srcWidth
- 2 * border
> 1) {
4103 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
4106 dstWidth
= srcWidth
; /* can't go smaller */
4108 if (srcHeight
- 2 * border
> 1) {
4109 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
4112 dstHeight
= srcHeight
; /* can't go smaller */
4114 if (srcDepth
- 2 * border
> 1) {
4115 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
4118 dstDepth
= srcDepth
; /* can't go smaller */
4121 if (dstWidth
== srcWidth
&&
4122 dstHeight
== srcHeight
&&
4123 dstDepth
== srcDepth
) {
4125 if (srcImage
->IsCompressed
) {
4126 _mesa_free((void *) srcData
);
4127 _mesa_free(dstData
);
4132 /* get dest gl_texture_image */
4133 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
4135 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
4139 /* Free old image data */
4141 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
4143 /* initialize new image */
4144 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
4145 dstDepth
, border
, srcImage
->InternalFormat
);
4146 dstImage
->DriverData
= NULL
;
4147 dstImage
->TexFormat
= srcImage
->TexFormat
;
4148 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
4149 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
4150 dstImage
->IsCompressed
= srcImage
->IsCompressed
;
4151 if (dstImage
->IsCompressed
) {
4152 dstImage
->CompressedSize
4153 = ctx
->Driver
.CompressedTextureSize(ctx
, dstImage
->Width
,
4156 dstImage
->TexFormat
->MesaFormat
);
4157 ASSERT(dstImage
->CompressedSize
> 0);
4160 ASSERT(dstImage
->TexFormat
);
4161 ASSERT(dstImage
->FetchTexelc
);
4162 ASSERT(dstImage
->FetchTexelf
);
4164 /* Alloc new teximage data buffer.
4165 * Setup src and dest data pointers.
4167 if (dstImage
->IsCompressed
) {
4168 dstImage
->Data
= _mesa_alloc_texmemory(dstImage
->CompressedSize
);
4169 if (!dstImage
->Data
) {
4170 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
4173 /* srcData and dstData are already set */
4178 bytesPerTexel
= dstImage
->TexFormat
->TexelBytes
;
4179 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
4180 dstImage
->Data
= _mesa_alloc_texmemory(dstWidth
* dstHeight
4181 * dstDepth
* bytesPerTexel
);
4182 if (!dstImage
->Data
) {
4183 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
4186 srcData
= (const GLubyte
*) srcImage
->Data
;
4187 dstData
= (GLubyte
*) dstImage
->Data
;
4191 * We use simple 2x2 averaging to compute the next mipmap level.
4195 make_1d_mipmap(convertFormat
, border
,
4200 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
4201 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
4202 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4203 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4204 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4205 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4206 make_2d_mipmap(convertFormat
, border
,
4207 srcWidth
, srcHeight
, srcData
,
4208 dstWidth
, dstHeight
, dstData
);
4211 make_3d_mipmap(convertFormat
, border
,
4212 srcWidth
, srcHeight
, srcDepth
, srcData
,
4213 dstWidth
, dstHeight
, dstDepth
, dstData
);
4215 case GL_TEXTURE_RECTANGLE_NV
:
4216 /* no mipmaps, do nothing */
4219 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
4223 if (dstImage
->IsCompressed
) {
4225 /* compress image from dstData into dstImage->Data */
4226 const GLenum srcFormat
= convertFormat
->BaseFormat
;
4228 = _mesa_compressed_row_stride(dstImage
->TexFormat
->MesaFormat
, dstWidth
);
4229 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
4230 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->_BaseFormat
,
4231 dstImage
->TexFormat
,
4233 0, 0, 0, /* dstX/Y/Zoffset */
4234 dstRowStride
, 0, /* strides */
4235 dstWidth
, dstHeight
, 1, /* size */
4236 srcFormat
, CHAN_TYPE
,
4237 dstData
, /* src data, actually */
4238 &ctx
->DefaultPacking
);
4239 /* swap src and dest pointers */
4240 temp
= (GLubyte
*) srcData
;
4245 } /* loop over mipmap levels */
4250 * Helper function for drivers which need to rescale texture images to
4251 * certain aspect ratios.
4252 * Nearest filtering only (for broken hardware that can't support
4253 * all aspect ratios). This can be made a lot faster, but I don't
4254 * really care enough...
4257 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
4258 GLuint srcStrideInPixels
,
4259 GLuint dstRowStride
,
4260 GLint srcWidth
, GLint srcHeight
,
4261 GLint dstWidth
, GLint dstHeight
,
4262 const GLvoid
*srcImage
, GLvoid
*dstImage
)
4266 #define INNER_LOOP( TYPE, HOP, WOP ) \
4267 for ( row = 0 ; row < dstHeight ; row++ ) { \
4268 GLint srcRow = row HOP hScale; \
4269 for ( col = 0 ; col < dstWidth ; col++ ) { \
4270 GLint srcCol = col WOP wScale; \
4271 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
4273 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
4276 #define RESCALE_IMAGE( TYPE ) \
4278 const TYPE *src = (const TYPE *)srcImage; \
4279 TYPE *dst = (TYPE *)dstImage; \
4281 if ( srcHeight < dstHeight ) { \
4282 const GLint hScale = dstHeight / srcHeight; \
4283 if ( srcWidth < dstWidth ) { \
4284 const GLint wScale = dstWidth / srcWidth; \
4285 INNER_LOOP( TYPE, /, / ); \
4288 const GLint wScale = srcWidth / dstWidth; \
4289 INNER_LOOP( TYPE, /, * ); \
4293 const GLint hScale = srcHeight / dstHeight; \
4294 if ( srcWidth < dstWidth ) { \
4295 const GLint wScale = dstWidth / srcWidth; \
4296 INNER_LOOP( TYPE, *, / ); \
4299 const GLint wScale = srcWidth / dstWidth; \
4300 INNER_LOOP( TYPE, *, * ); \
4305 switch ( bytesPerPixel
) {
4307 RESCALE_IMAGE( GLuint
);
4311 RESCALE_IMAGE( GLushort
);
4315 RESCALE_IMAGE( GLubyte
);
4318 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
4324 * Upscale an image by replication, not (typical) stretching.
4325 * We use this when the image width or height is less than a
4326 * certain size (4, 8) and we need to upscale an image.
4329 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
4330 GLsizei outWidth
, GLsizei outHeight
,
4331 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
4336 ASSERT(outWidth
>= inWidth
);
4337 ASSERT(outHeight
>= inHeight
);
4339 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
4340 ASSERT((outWidth
& 3) == 0);
4341 ASSERT((outHeight
& 3) == 0);
4344 for (i
= 0; i
< outHeight
; i
++) {
4345 const GLint ii
= i
% inHeight
;
4346 for (j
= 0; j
< outWidth
; j
++) {
4347 const GLint jj
= j
% inWidth
;
4348 for (k
= 0; k
< comps
; k
++) {
4349 dest
[(i
* outWidth
+ j
) * comps
+ k
]
4350 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
4357 #if FEATURE_EXT_texture_sRGB
4360 * Test if given texture image is an sRGB format.
4363 is_srgb_teximage(const struct gl_texture_image
*texImage
)
4365 switch (texImage
->TexFormat
->MesaFormat
) {
4366 case MESA_FORMAT_SRGB8
:
4367 case MESA_FORMAT_SRGBA8
:
4368 case MESA_FORMAT_SL8
:
4369 case MESA_FORMAT_SLA8
:
4376 #endif /* FEATURE_EXT_texture_sRGB */
4380 * This is the software fallback for Driver.GetTexImage().
4381 * All error checking will have been done before this routine is called.
4384 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4385 GLenum format
, GLenum type
, GLvoid
*pixels
,
4386 struct gl_texture_object
*texObj
,
4387 struct gl_texture_image
*texImage
)
4389 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
4391 if (ctx
->Pack
.BufferObj
->Name
) {
4392 /* Packing texture image into a PBO.
4393 * Map the (potentially) VRAM-based buffer into our process space so
4394 * we can write into it with the code below.
4395 * A hardware driver might use a sophisticated blit to move the
4396 * texture data to the PBO if the PBO is in VRAM along with the texture.
4398 GLubyte
*buf
= (GLubyte
*)
4399 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4400 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
4402 /* buffer is already mapped - that's an error */
4403 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
4406 /* <pixels> was an offset into the PBO.
4407 * Now make it a real, client-side pointer inside the mapped region.
4409 pixels
= ADD_POINTERS(buf
, pixels
);
4417 const GLint width
= texImage
->Width
;
4418 const GLint height
= texImage
->Height
;
4419 const GLint depth
= texImage
->Depth
;
4421 for (img
= 0; img
< depth
; img
++) {
4422 for (row
= 0; row
< height
; row
++) {
4423 /* compute destination address in client memory */
4424 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
4425 width
, height
, format
, type
,
4429 if (format
== GL_COLOR_INDEX
) {
4430 GLuint indexRow
[MAX_WIDTH
];
4432 /* Can't use FetchTexel here because that returns RGBA */
4433 if (texImage
->TexFormat
->IndexBits
== 8) {
4434 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
4435 src
+= width
* (img
* texImage
->Height
+ row
);
4436 for (col
= 0; col
< width
; col
++) {
4437 indexRow
[col
] = src
[col
];
4440 else if (texImage
->TexFormat
->IndexBits
== 16) {
4441 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
4442 src
+= width
* (img
* texImage
->Height
+ row
);
4443 for (col
= 0; col
< width
; col
++) {
4444 indexRow
[col
] = src
[col
];
4449 "Color index problem in _mesa_GetTexImage");
4451 _mesa_pack_index_span(ctx
, width
, type
, dest
,
4452 indexRow
, &ctx
->Pack
,
4453 0 /* no image transfer */);
4455 else if (format
== GL_DEPTH_COMPONENT
) {
4456 GLfloat depthRow
[MAX_WIDTH
];
4458 for (col
= 0; col
< width
; col
++) {
4459 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
4462 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
4463 depthRow
, &ctx
->Pack
);
4465 else if (format
== GL_DEPTH_STENCIL_EXT
) {
4466 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4467 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
4468 src
+= width
* row
+ width
* height
* img
;
4469 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
4470 if (ctx
->Pack
.SwapBytes
) {
4471 _mesa_swap4((GLuint
*) dest
, width
);
4474 else if (format
== GL_YCBCR_MESA
) {
4475 /* No pixel transfer */
4476 const GLint rowstride
= texImage
->RowStride
;
4478 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
4479 width
* sizeof(GLushort
));
4480 /* check for byte swapping */
4481 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
4482 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
4483 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
4484 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
4485 if (!ctx
->Pack
.SwapBytes
)
4486 _mesa_swap2((GLushort
*) dest
, width
);
4488 else if (ctx
->Pack
.SwapBytes
) {
4489 _mesa_swap2((GLushort
*) dest
, width
);
4492 #if FEATURE_EXT_texture_sRGB
4493 else if (is_srgb_teximage(texImage
)) {
4494 /* no pixel transfer and no non-linear to linear conversion */
4495 const GLint comps
= texImage
->TexFormat
->TexelBytes
;
4496 const GLint rowstride
= comps
* texImage
->RowStride
;
4498 (const GLubyte
*) texImage
->Data
+ row
* rowstride
,
4499 comps
* width
* sizeof(GLubyte
));
4501 #endif /* FEATURE_EXT_texture_sRGB */
4503 /* general case: convert row to RGBA format */
4504 GLfloat rgba
[MAX_WIDTH
][4];
4506 for (col
= 0; col
< width
; col
++) {
4507 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
4509 _mesa_pack_rgba_span_float(ctx
, width
,
4510 (const GLfloat (*)[4]) rgba
,
4511 format
, type
, dest
, &ctx
->Pack
,
4512 0 /* no image transfer */);
4518 if (ctx
->Pack
.BufferObj
->Name
) {
4519 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4520 ctx
->Pack
.BufferObj
);
4527 * This is the software fallback for Driver.GetCompressedTexImage().
4528 * All error checking will have been done before this routine is called.
4531 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4533 const struct gl_texture_object
*texObj
,
4534 const struct gl_texture_image
*texImage
)
4538 if (ctx
->Pack
.BufferObj
->Name
) {
4539 /* pack texture image into a PBO */
4541 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4542 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4543 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4544 "glGetCompressedTexImage(invalid PBO access)");
4547 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4549 ctx
->Pack
.BufferObj
);
4551 /* buffer is already mapped - that's an error */
4552 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4553 "glGetCompressedTexImage(PBO is mapped)");
4556 img
= ADD_POINTERS(buf
, img
);
4563 /* don't use texImage->CompressedSize since that may be padded out */
4564 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
4566 texImage
->TexFormat
->MesaFormat
);
4568 /* just memcpy, no pixelstore or pixel transfer */
4569 _mesa_memcpy(img
, texImage
->Data
, size
);
4571 if (ctx
->Pack
.BufferObj
->Name
) {
4572 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4573 ctx
->Pack
.BufferObj
);