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"
68 static const GLint ZERO
= 4, ONE
= 5;
70 static GLboolean
can_swizzle(GLenum logicalBaseFormat
)
72 switch (logicalBaseFormat
) {
75 case GL_LUMINANCE_ALPHA
:
87 * When promoting texture formats (see below) we need to compute the
88 * mapping of dest components back to source components.
89 * This function does that.
90 * \param logicalBaseFormat the logical format of the texture
91 * \param textureBaseFormat the final texture format
92 * \return map[4] the four mapping values
95 compute_component_mapping(GLenum logicalBaseFormat
, GLenum textureBaseFormat
,
101 /* compute mapping from dest components back to src components */
102 switch (textureBaseFormat
) {
105 switch (logicalBaseFormat
) {
107 map
[0] = map
[1] = map
[2] = 0;
108 if (textureBaseFormat
== GL_RGBA
)
112 ASSERT(textureBaseFormat
== GL_RGBA
);
113 map
[0] = map
[1] = map
[2] = ZERO
;
117 map
[0] = map
[1] = map
[2] = 0;
118 if (textureBaseFormat
== GL_RGBA
)
121 case GL_LUMINANCE_ALPHA
:
122 ASSERT(textureBaseFormat
== GL_RGBA
);
123 map
[0] = map
[1] = map
[2] = 0;
127 ASSERT(textureBaseFormat
== GL_RGBA
);
134 ASSERT(textureBaseFormat
== GL_RGBA
);
141 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
142 map
[0] = map
[1] = map
[2] = map
[3] = 0;
145 case GL_LUMINANCE_ALPHA
:
146 switch (logicalBaseFormat
) {
160 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
165 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
173 * Make a temporary (color) texture image with GLfloat components.
174 * Apply all needed pixel unpacking and pixel transfer operations.
175 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
176 * Suppose the user specifies GL_LUMINANCE as the internal texture format
177 * but the graphics hardware doesn't support luminance textures. So, might
178 * use an RGB hardware format instead.
179 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
181 * \param ctx the rendering context
182 * \param dims image dimensions: 1, 2 or 3
183 * \param logicalBaseFormat basic texture derived from the user's
184 * internal texture format value
185 * \param textureBaseFormat the actual basic format of the texture
186 * \param srcWidth source image width
187 * \param srcHeight source image height
188 * \param srcDepth source image depth
189 * \param srcFormat source image format
190 * \param srcType source image type
191 * \param srcAddr source image address
192 * \param srcPacking source image pixel packing
193 * \return resulting image with format = textureBaseFormat and type = GLfloat.
196 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
197 GLenum logicalBaseFormat
,
198 GLenum textureBaseFormat
,
199 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
200 GLenum srcFormat
, GLenum srcType
,
201 const GLvoid
*srcAddr
,
202 const struct gl_pixelstore_attrib
*srcPacking
)
204 GLuint transferOps
= ctx
->_ImageTransferState
;
207 ASSERT(dims
>= 1 && dims
<= 3);
209 ASSERT(logicalBaseFormat
== GL_RGBA
||
210 logicalBaseFormat
== GL_RGB
||
211 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
212 logicalBaseFormat
== GL_LUMINANCE
||
213 logicalBaseFormat
== GL_ALPHA
||
214 logicalBaseFormat
== GL_INTENSITY
||
215 logicalBaseFormat
== GL_COLOR_INDEX
||
216 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
218 ASSERT(textureBaseFormat
== GL_RGBA
||
219 textureBaseFormat
== GL_RGB
||
220 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
221 textureBaseFormat
== GL_LUMINANCE
||
222 textureBaseFormat
== GL_ALPHA
||
223 textureBaseFormat
== GL_INTENSITY
||
224 textureBaseFormat
== GL_COLOR_INDEX
||
225 textureBaseFormat
== GL_DEPTH_COMPONENT
);
227 /* conventional color image */
229 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
230 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
231 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
232 /* need image convolution */
233 const GLuint preConvTransferOps
234 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
235 const GLuint postConvTransferOps
236 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
238 GLint convWidth
, convHeight
;
241 /* pre-convolution image buffer (3D) */
242 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
243 * 4 * sizeof(GLfloat
));
247 /* post-convolution image buffer (2D) */
248 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
249 * 4 * sizeof(GLfloat
));
251 _mesa_free(tempImage
);
255 /* loop over 3D image slices */
256 for (img
= 0; img
< srcDepth
; img
++) {
257 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
259 /* unpack and do transfer ops up to convolution */
260 for (row
= 0; row
< srcHeight
; row
++) {
261 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
262 srcAddr
, srcWidth
, srcHeight
,
263 srcFormat
, srcType
, img
, row
, 0);
264 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
265 srcFormat
, srcType
, src
,
273 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
274 convWidth
= srcWidth
;
275 convHeight
= srcHeight
;
277 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
278 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
281 if (ctx
->Pixel
.Convolution2DEnabled
) {
282 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
286 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
287 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
293 /* do post-convolution transfer and pack into tempImage */
295 const GLint logComponents
296 = _mesa_components_in_format(logicalBaseFormat
);
297 const GLfloat
*src
= convImage
;
298 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
299 for (row
= 0; row
< convHeight
; row
++) {
300 _mesa_pack_rgba_span_float(ctx
, convWidth
,
301 (const GLfloat (*)[4]) src
,
302 logicalBaseFormat
, GL_FLOAT
,
303 dst
, &ctx
->DefaultPacking
,
304 postConvTransferOps
);
305 src
+= convWidth
* 4;
306 dst
+= convWidth
* logComponents
;
309 } /* loop over 3D image slices */
311 _mesa_free(convImage
);
313 /* might need these below */
314 srcWidth
= convWidth
;
315 srcHeight
= convHeight
;
319 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
320 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
321 srcWidth
, srcFormat
, srcType
);
325 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
326 * components
* sizeof(GLfloat
));
331 for (img
= 0; img
< srcDepth
; img
++) {
333 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
337 for (row
= 0; row
< srcHeight
; row
++) {
338 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
339 dst
, srcFormat
, srcType
, src
,
340 srcPacking
, transferOps
);
341 dst
+= srcWidth
* components
;
347 if (logicalBaseFormat
!= textureBaseFormat
) {
349 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
350 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
355 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
356 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
357 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
359 /* The actual texture format should have at least as many components
360 * as the logical texture format.
362 ASSERT(texComponents
>= logComponents
);
364 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
365 * texComponents
* sizeof(GLfloat
));
367 _mesa_free(tempImage
);
371 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
373 n
= srcWidth
* srcHeight
* srcDepth
;
374 for (i
= 0; i
< n
; i
++) {
376 for (k
= 0; k
< texComponents
; k
++) {
379 newImage
[i
* texComponents
+ k
] = 0.0F
;
381 newImage
[i
* texComponents
+ k
] = 1.0F
;
383 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
387 _mesa_free(tempImage
);
388 tempImage
= newImage
;
396 * Make a temporary (color) texture image with GLchan components.
397 * Apply all needed pixel unpacking and pixel transfer operations.
398 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
399 * Suppose the user specifies GL_LUMINANCE as the internal texture format
400 * but the graphics hardware doesn't support luminance textures. So, might
401 * use an RGB hardware format instead.
402 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
404 * \param ctx the rendering context
405 * \param dims image dimensions: 1, 2 or 3
406 * \param logicalBaseFormat basic texture derived from the user's
407 * internal texture format value
408 * \param textureBaseFormat the actual basic format of the texture
409 * \param srcWidth source image width
410 * \param srcHeight source image height
411 * \param srcDepth source image depth
412 * \param srcFormat source image format
413 * \param srcType source image type
414 * \param srcAddr source image address
415 * \param srcPacking source image pixel packing
416 * \return resulting image with format = textureBaseFormat and type = GLchan.
419 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
420 GLenum logicalBaseFormat
,
421 GLenum textureBaseFormat
,
422 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
423 GLenum srcFormat
, GLenum srcType
,
424 const GLvoid
*srcAddr
,
425 const struct gl_pixelstore_attrib
*srcPacking
)
427 GLuint transferOps
= ctx
->_ImageTransferState
;
428 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
429 GLboolean freeSrcImage
= GL_FALSE
;
431 GLchan
*tempImage
, *dst
;
433 ASSERT(dims
>= 1 && dims
<= 3);
435 ASSERT(logicalBaseFormat
== GL_RGBA
||
436 logicalBaseFormat
== GL_RGB
||
437 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
438 logicalBaseFormat
== GL_LUMINANCE
||
439 logicalBaseFormat
== GL_ALPHA
||
440 logicalBaseFormat
== GL_INTENSITY
);
442 ASSERT(textureBaseFormat
== GL_RGBA
||
443 textureBaseFormat
== GL_RGB
||
444 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
445 textureBaseFormat
== GL_LUMINANCE
||
446 textureBaseFormat
== GL_ALPHA
||
447 textureBaseFormat
== GL_INTENSITY
);
449 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
450 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
451 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
452 /* get convolved image */
453 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
456 srcWidth
, srcHeight
, srcDepth
,
458 srcAddr
, srcPacking
);
461 /* the convolved image is our new source image */
463 srcFormat
= logicalBaseFormat
;
465 srcPacking
= &ctx
->DefaultPacking
;
466 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
468 freeSrcImage
= GL_TRUE
;
471 /* unpack and transfer the source image */
472 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
473 * components
* sizeof(GLchan
));
478 for (img
= 0; img
< srcDepth
; img
++) {
479 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
483 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
487 for (row
= 0; row
< srcHeight
; row
++) {
488 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
489 srcFormat
, srcType
, src
, srcPacking
,
491 dst
+= srcWidth
* components
;
496 /* If we made a temporary image for convolution, free it here */
498 _mesa_free((void *) srcAddr
);
501 if (logicalBaseFormat
!= textureBaseFormat
) {
502 /* one more conversion step */
503 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
504 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
509 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
510 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
511 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
513 /* The actual texture format should have at least as many components
514 * as the logical texture format.
516 ASSERT(texComponents
>= logComponents
);
518 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
519 * texComponents
* sizeof(GLchan
));
521 _mesa_free(tempImage
);
525 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
527 n
= srcWidth
* srcHeight
* srcDepth
;
528 for (i
= 0; i
< n
; i
++) {
530 for (k
= 0; k
< texComponents
; k
++) {
533 newImage
[i
* texComponents
+ k
] = 0;
535 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
537 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
541 _mesa_free(tempImage
);
542 tempImage
= newImage
;
550 * Copy GLubyte pixels from <src> to <dst> with swizzling.
551 * \param dst destination pixels
552 * \param dstComponents number of color components in destination pixels
553 * \param src source pixels
554 * \param srcComponents number of color components in source pixels
555 * \param map the swizzle mapping
556 * \param count number of pixels to copy/swizzle.
559 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
560 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
568 switch (dstComponents
) {
570 for (i
= 0; i
< count
; i
++) {
572 src
+= srcComponents
;
573 dst
[0] = tmp
[map
[0]];
574 dst
[1] = tmp
[map
[1]];
575 dst
[2] = tmp
[map
[2]];
576 dst
[3] = tmp
[map
[3]];
581 for (i
= 0; i
< count
; i
++) {
583 src
+= srcComponents
;
584 dst
[0] = tmp
[map
[0]];
585 dst
[1] = tmp
[map
[1]];
586 dst
[2] = tmp
[map
[2]];
591 for (i
= 0; i
< count
; i
++) {
593 src
+= srcComponents
;
594 dst
[0] = tmp
[map
[0]];
595 dst
[1] = tmp
[map
[1]];
604 * Transfer a GLubyte texture image with component swizzling.
607 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
610 const GLubyte
*dstmap
, GLint dstComponents
,
613 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
614 GLint dstRowStride
, GLint dstImageStride
,
616 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
617 const GLvoid
*srcAddr
,
618 const struct gl_pixelstore_attrib
*srcPacking
)
620 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
621 GLubyte srcmap
[6], map
[4];
624 const GLint srcRowStride
=
625 _mesa_image_row_stride(srcPacking
, srcWidth
,
626 srcFormat
, GL_UNSIGNED_BYTE
);
627 const GLint srcImageStride
628 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
630 const GLubyte
*srcImage
631 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
632 srcWidth
, srcHeight
, srcFormat
,
633 GL_UNSIGNED_BYTE
, 0, 0, 0);
635 GLubyte
*dstImage
= (GLubyte
*) dstAddr
636 + dstZoffset
* dstImageStride
637 + dstYoffset
* dstRowStride
638 + dstXoffset
* dstComponents
;
642 compute_component_mapping(srcFormat
, GL_RGBA
, srcmap
);
644 for (i
= 0; i
< 4; i
++)
645 map
[i
] = srcmap
[dstmap
[i
]];
647 if (srcRowStride
== srcWidth
* srcComponents
&&
648 (srcImageStride
== srcWidth
* srcHeight
* srcComponents
||
650 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
651 srcWidth
* srcHeight
* srcDepth
);
655 for (img
= 0; img
< srcDepth
; img
++) {
656 const GLubyte
*srcRow
= srcImage
;
657 GLubyte
*dstRow
= dstImage
;
658 for (row
= 0; row
< srcHeight
; row
++) {
659 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
660 dstRow
+= dstRowStride
;
661 srcRow
+= srcRowStride
;
663 srcImage
+= srcImageStride
;
664 dstImage
+= dstImageStride
;
671 * Teximage storage routine for when a simple memcpy will do.
672 * No pixel transfer operations or special texel encodings allowed.
673 * 1D, 2D and 3D images supported.
676 memcpy_texture(GLcontext
*ctx
,
678 const struct gl_texture_format
*dstFormat
,
680 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
681 GLint dstRowStride
, GLint dstImageStride
,
682 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
683 GLenum srcFormat
, GLenum srcType
,
684 const GLvoid
*srcAddr
,
685 const struct gl_pixelstore_attrib
*srcPacking
)
687 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
689 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
690 srcWidth
, srcHeight
, srcFormat
, srcType
);
691 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
692 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
693 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
694 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
695 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
696 GLubyte
*dstImage
= (GLubyte
*) dstAddr
697 + dstZoffset
* dstImageStride
698 + dstYoffset
* dstRowStride
699 + dstXoffset
* dstFormat
->TexelBytes
;
701 if (dstRowStride
== srcRowStride
&&
702 dstRowStride
== bytesPerRow
&&
703 ((dstImageStride
== srcImageStride
&&
704 dstImageStride
== bytesPerImage
) ||
707 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
711 for (img
= 0; img
< srcDepth
; img
++) {
712 const GLubyte
*srcRow
= srcImage
;
713 GLubyte
*dstRow
= dstImage
;
714 for (row
= 0; row
< srcHeight
; row
++) {
715 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
716 dstRow
+= dstRowStride
;
717 srcRow
+= srcRowStride
;
719 srcImage
+= srcImageStride
;
720 dstImage
+= dstImageStride
;
728 * Store an image in any of the formats:
729 * _mesa_texformat_rgba
730 * _mesa_texformat_rgb
731 * _mesa_texformat_alpha
732 * _mesa_texformat_luminance
733 * _mesa_texformat_luminance_alpha
734 * _mesa_texformat_intensity
736 * \param dims either 1 or 2 or 3
737 * \param baseInternalFormat user-specified base internal format
738 * \param dstFormat destination Mesa texture format
739 * \param dstAddr destination image address
740 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
741 * \param dstRowStride destination image row stride, in bytes
742 * \param dstImageStride destination image layer stride, in bytes
743 * \param srcWidth/Height/Depth source image size, in pixels
744 * \param srcFormat incoming image format
745 * \param srcType incoming image data type
746 * \param srcAddr source image address
747 * \param srcPacking source image packing parameters
750 _mesa_texstore_rgba(GLcontext
*ctx
, GLuint dims
,
751 GLenum baseInternalFormat
,
752 const struct gl_texture_format
*dstFormat
,
754 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
755 GLint dstRowStride
, GLint dstImageStride
,
756 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
757 GLenum srcFormat
, GLenum srcType
,
758 const GLvoid
*srcAddr
,
759 const struct gl_pixelstore_attrib
*srcPacking
)
761 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
763 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
764 dstFormat
== &_mesa_texformat_rgb
||
765 dstFormat
== &_mesa_texformat_alpha
||
766 dstFormat
== &_mesa_texformat_luminance
||
767 dstFormat
== &_mesa_texformat_luminance_alpha
||
768 dstFormat
== &_mesa_texformat_intensity
);
769 ASSERT(baseInternalFormat
== GL_RGBA
||
770 baseInternalFormat
== GL_RGB
||
771 baseInternalFormat
== GL_ALPHA
||
772 baseInternalFormat
== GL_LUMINANCE
||
773 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
774 baseInternalFormat
== GL_INTENSITY
);
775 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
777 if (!ctx
->_ImageTransferState
&&
778 !srcPacking
->SwapBytes
&&
779 baseInternalFormat
== srcFormat
&&
780 srcType
== CHAN_TYPE
) {
781 /* simple memcpy path */
782 memcpy_texture(ctx
, dims
,
783 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
784 dstRowStride
, dstImageStride
,
785 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
786 srcAddr
, srcPacking
);
788 else if (!ctx
->_ImageTransferState
&&
789 !srcPacking
->SwapBytes
&&
790 dstFormat
== &_mesa_texformat_rgb
&&
791 srcFormat
== GL_RGBA
&&
792 srcType
== CHAN_TYPE
) {
793 /* extract RGB from RGBA */
795 GLchan
*dstImage
= (GLchan
*) ((GLubyte
*) dstAddr
796 + dstZoffset
* dstImageStride
797 + dstYoffset
* dstRowStride
798 + dstXoffset
* dstFormat
->TexelBytes
);
799 for (img
= 0; img
< srcDepth
; img
++) {
800 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
801 srcWidth
, srcFormat
, srcType
);
802 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
803 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
804 GLchan
*dstRow
= dstImage
;
805 for (row
= 0; row
< srcHeight
; row
++) {
806 for (col
= 0; col
< srcWidth
; col
++) {
807 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
808 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
809 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
811 dstRow
+= dstRowStride
/ sizeof(GLchan
);
812 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
814 dstImage
+= dstImageStride
/ sizeof(GLchan
);
819 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
821 dstFormat
->BaseFormat
,
822 srcWidth
, srcHeight
, srcDepth
,
823 srcFormat
, srcType
, srcAddr
,
825 const GLchan
*src
= tempImage
;
827 GLubyte
*dstImage
= (GLubyte
*) dstAddr
828 + dstZoffset
* dstImageStride
829 + dstYoffset
* dstRowStride
830 + dstXoffset
* dstFormat
->TexelBytes
;
834 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
835 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
836 for (img
= 0; img
< srcDepth
; img
++) {
837 GLubyte
*dstRow
= dstImage
;
838 for (row
= 0; row
< srcHeight
; row
++) {
839 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
840 dstRow
+= dstRowStride
;
841 src
+= srcWidth
* components
;
843 dstImage
+= dstImageStride
;
846 _mesa_free((void *) tempImage
);
853 * Store a 32-bit integer depth component texture image.
856 _mesa_texstore_z32(STORE_PARAMS
)
858 const GLfloat depthScale
= (GLfloat
) 0xffffffff;
860 ASSERT(dstFormat
== &_mesa_texformat_z32
);
861 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
863 if (!ctx
->_ImageTransferState
&&
864 !srcPacking
->SwapBytes
&&
865 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
866 srcFormat
== GL_DEPTH_COMPONENT
&&
867 srcType
== GL_UNSIGNED_INT
) {
868 /* simple memcpy path */
869 memcpy_texture(ctx
, dims
,
870 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
871 dstRowStride
, dstImageStride
,
872 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
873 srcAddr
, srcPacking
);
877 GLubyte
*dstImage
= (GLubyte
*) dstAddr
878 + dstZoffset
* dstImageStride
879 + dstYoffset
* dstRowStride
880 + dstXoffset
* dstFormat
->TexelBytes
;
882 for (img
= 0; img
< srcDepth
; img
++) {
883 GLubyte
*dstRow
= dstImage
;
884 for (row
= 0; row
< srcHeight
; row
++) {
885 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
886 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
887 _mesa_unpack_depth_span(ctx
, srcWidth
,
888 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
889 depthScale
, srcType
, src
, srcPacking
);
890 dstRow
+= dstRowStride
;
892 dstImage
+= dstImageStride
;
900 * Store a 16-bit integer depth component texture image.
903 _mesa_texstore_z16(STORE_PARAMS
)
905 const GLfloat depthScale
= 65535.0f
;
907 ASSERT(dstFormat
== &_mesa_texformat_z16
);
908 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
910 if (!ctx
->_ImageTransferState
&&
911 !srcPacking
->SwapBytes
&&
912 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
913 srcFormat
== GL_DEPTH_COMPONENT
&&
914 srcType
== GL_UNSIGNED_SHORT
) {
915 /* simple memcpy path */
916 memcpy_texture(ctx
, dims
,
917 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
918 dstRowStride
, dstImageStride
,
919 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
920 srcAddr
, srcPacking
);
924 GLubyte
*dstImage
= (GLubyte
*) dstAddr
925 + dstZoffset
* dstImageStride
926 + dstYoffset
* dstRowStride
927 + dstXoffset
* dstFormat
->TexelBytes
;
929 for (img
= 0; img
< srcDepth
; img
++) {
930 GLubyte
*dstRow
= dstImage
;
931 for (row
= 0; row
< srcHeight
; row
++) {
932 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
933 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
934 GLushort
*dst16
= (GLushort
*) dstRow
;
935 _mesa_unpack_depth_span(ctx
, srcWidth
,
936 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
937 srcType
, src
, srcPacking
);
938 dstRow
+= dstRowStride
;
940 dstImage
+= dstImageStride
;
948 * Store an rgb565 or rgb565_rev texture image.
951 _mesa_texstore_rgb565(STORE_PARAMS
)
953 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
954 dstFormat
== &_mesa_texformat_rgb565_rev
);
955 ASSERT(dstFormat
->TexelBytes
== 2);
957 if (!ctx
->_ImageTransferState
&&
958 !srcPacking
->SwapBytes
&&
959 dstFormat
== &_mesa_texformat_rgb565
&&
960 baseInternalFormat
== GL_RGB
&&
961 srcFormat
== GL_RGB
&&
962 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
963 /* simple memcpy path */
964 memcpy_texture(ctx
, dims
,
965 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
966 dstRowStride
, dstImageStride
,
967 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
968 srcAddr
, srcPacking
);
970 else if (!ctx
->_ImageTransferState
&&
971 !srcPacking
->SwapBytes
&&
972 baseInternalFormat
== GL_RGB
&&
973 srcFormat
== GL_RGB
&&
974 srcType
== GL_UNSIGNED_BYTE
&&
976 /* do optimized tex store */
977 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
979 const GLubyte
*src
= (const GLubyte
*)
980 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
981 srcFormat
, srcType
, 0, 0, 0);
982 GLubyte
*dst
= (GLubyte
*) dstAddr
983 + dstZoffset
* dstImageStride
984 + dstYoffset
* dstRowStride
985 + dstXoffset
* dstFormat
->TexelBytes
;
987 for (row
= 0; row
< srcHeight
; row
++) {
988 const GLubyte
*srcUB
= (const GLubyte
*) src
;
989 GLushort
*dstUS
= (GLushort
*) dst
;
990 /* check for byteswapped format */
991 if (dstFormat
== &_mesa_texformat_rgb565
) {
992 for (col
= 0; col
< srcWidth
; col
++) {
993 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
998 for (col
= 0; col
< srcWidth
; col
++) {
999 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1003 dst
+= dstRowStride
;
1004 src
+= srcRowStride
;
1009 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1011 dstFormat
->BaseFormat
,
1012 srcWidth
, srcHeight
, srcDepth
,
1013 srcFormat
, srcType
, srcAddr
,
1015 const GLchan
*src
= tempImage
;
1016 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1017 + dstZoffset
* dstImageStride
1018 + dstYoffset
* dstRowStride
1019 + dstXoffset
* dstFormat
->TexelBytes
;
1020 GLint img
, row
, col
;
1023 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1024 for (img
= 0; img
< srcDepth
; img
++) {
1025 GLubyte
*dstRow
= dstImage
;
1026 for (row
= 0; row
< srcHeight
; row
++) {
1027 GLushort
*dstUS
= (GLushort
*) dstRow
;
1028 /* check for byteswapped format */
1029 if (dstFormat
== &_mesa_texformat_rgb565
) {
1030 for (col
= 0; col
< srcWidth
; col
++) {
1031 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1032 CHAN_TO_UBYTE(src
[GCOMP
]),
1033 CHAN_TO_UBYTE(src
[BCOMP
]) );
1038 for (col
= 0; col
< srcWidth
; col
++) {
1039 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1040 CHAN_TO_UBYTE(src
[GCOMP
]),
1041 CHAN_TO_UBYTE(src
[BCOMP
]) );
1045 dstRow
+= dstRowStride
;
1047 dstImage
+= dstImageStride
;
1049 _mesa_free((void *) tempImage
);
1056 _mesa_texstore_rgba8888(STORE_PARAMS
)
1058 const GLuint ui
= 1;
1059 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1062 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1063 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1064 ASSERT(dstFormat
->TexelBytes
== 4);
1066 if (!ctx
->_ImageTransferState
&&
1067 !srcPacking
->SwapBytes
&&
1068 dstFormat
== &_mesa_texformat_rgba8888
&&
1069 baseInternalFormat
== GL_RGBA
&&
1070 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1071 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
1072 /* simple memcpy path */
1073 memcpy_texture(ctx
, dims
,
1074 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1075 dstRowStride
, dstImageStride
,
1076 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1077 srcAddr
, srcPacking
);
1080 else if (!ctx
->_ImageTransferState
&&
1081 !srcPacking
->SwapBytes
&&
1082 srcType
== GL_UNSIGNED_BYTE
&&
1083 dstFormat
== &_mesa_texformat_rgba8888
&&
1085 /* Three texture formats involved: srcFormat,
1086 * baseInternalFormat and destFormat (GL_RGBA). Only two
1087 * may differ. _mesa_swizzle_ubyte_image can't handle two
1088 * propagations at once correctly. */
1089 (srcFormat
== baseInternalFormat
||
1090 baseInternalFormat
== GL_RGBA
) &&
1091 can_swizzle(srcFormat
)) {
1094 /* dstmap - how to swizzle from GL_RGBA to dst format:
1096 * FIXME - add !litteEndian and _rev varients:
1103 _mesa_swizzle_ubyte_image(ctx
, dims
,
1106 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1107 dstRowStride
, dstImageStride
,
1108 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1114 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1116 dstFormat
->BaseFormat
,
1117 srcWidth
, srcHeight
, srcDepth
,
1118 srcFormat
, srcType
, srcAddr
,
1120 const GLchan
*src
= tempImage
;
1121 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1122 + dstZoffset
* dstImageStride
1123 + dstYoffset
* dstRowStride
1124 + dstXoffset
* dstFormat
->TexelBytes
;
1125 GLint img
, row
, col
;
1128 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1129 for (img
= 0; img
< srcDepth
; img
++) {
1130 GLubyte
*dstRow
= dstImage
;
1131 for (row
= 0; row
< srcHeight
; row
++) {
1132 GLuint
*dstUI
= (GLuint
*) dstRow
;
1133 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1134 for (col
= 0; col
< srcWidth
; col
++) {
1135 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1136 CHAN_TO_UBYTE(src
[GCOMP
]),
1137 CHAN_TO_UBYTE(src
[BCOMP
]),
1138 CHAN_TO_UBYTE(src
[ACOMP
]) );
1143 for (col
= 0; col
< srcWidth
; col
++) {
1144 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1145 CHAN_TO_UBYTE(src
[GCOMP
]),
1146 CHAN_TO_UBYTE(src
[BCOMP
]),
1147 CHAN_TO_UBYTE(src
[ACOMP
]) );
1151 dstRow
+= dstRowStride
;
1153 dstImage
+= dstImageStride
;
1155 _mesa_free((void *) tempImage
);
1162 _mesa_texstore_argb8888(STORE_PARAMS
)
1164 const GLuint ui
= 1;
1165 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1167 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1168 dstFormat
== &_mesa_texformat_argb8888_rev
);
1169 ASSERT(dstFormat
->TexelBytes
== 4);
1171 if (!ctx
->_ImageTransferState
&&
1172 !srcPacking
->SwapBytes
&&
1173 dstFormat
== &_mesa_texformat_argb8888
&&
1174 baseInternalFormat
== GL_RGBA
&&
1175 srcFormat
== GL_BGRA
&&
1176 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1177 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1178 /* simple memcpy path (little endian) */
1179 memcpy_texture(ctx
, dims
,
1180 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1181 dstRowStride
, dstImageStride
,
1182 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1183 srcAddr
, srcPacking
);
1185 else if (!ctx
->_ImageTransferState
&&
1186 !srcPacking
->SwapBytes
&&
1187 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1188 baseInternalFormat
== GL_RGBA
&&
1189 srcFormat
== GL_BGRA
&&
1190 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1191 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1192 /* simple memcpy path (big endian) */
1193 memcpy_texture(ctx
, dims
,
1194 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1195 dstRowStride
, dstImageStride
,
1196 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1197 srcAddr
, srcPacking
);
1199 else if (!ctx
->_ImageTransferState
&&
1200 !srcPacking
->SwapBytes
&&
1201 dstFormat
== &_mesa_texformat_argb8888
&&
1202 srcFormat
== GL_RGB
&&
1203 srcType
== GL_UNSIGNED_BYTE
) {
1206 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1207 + dstZoffset
* dstImageStride
1208 + dstYoffset
* dstRowStride
1209 + dstXoffset
* dstFormat
->TexelBytes
;
1210 for (img
= 0; img
< srcDepth
; img
++) {
1211 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1212 srcWidth
, srcFormat
, srcType
);
1213 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1214 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1215 GLubyte
*dstRow
= dstImage
;
1216 for (row
= 0; row
< srcHeight
; row
++) {
1217 for (col
= 0; col
< srcWidth
; col
++) {
1218 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1219 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1220 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1221 dstRow
[col
* 4 + 3] = 0xff;
1223 dstRow
+= dstRowStride
;
1224 srcRow
+= srcRowStride
;
1226 dstImage
+= dstImageStride
;
1229 else if (!ctx
->_ImageTransferState
&&
1230 !srcPacking
->SwapBytes
&&
1231 dstFormat
== &_mesa_texformat_argb8888
&&
1232 srcFormat
== GL_RGBA
&&
1233 (srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
1236 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1237 + dstZoffset
* dstImageStride
1238 + dstYoffset
* dstRowStride
1239 + dstXoffset
* dstFormat
->TexelBytes
;
1241 /* For some reason, streaming copies to write-combined regions
1242 * are extremely sensitive to the characteristics of how the
1243 * source data is retrieved. By reordering the source reads to
1244 * be in-order, the speed of this operation increases by half.
1245 * Strangely the same isn't required for the RGB path, above.
1247 for (img
= 0; img
< srcDepth
; img
++) {
1248 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1249 srcWidth
, srcFormat
, srcType
);
1250 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1251 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1252 GLubyte
*dstRow
= dstImage
;
1253 for (row
= 0; row
< srcHeight
; row
++) {
1254 for (col
= 0; col
< srcWidth
; col
++) {
1255 *(GLuint
*)(dstRow
+ col
* 4) = (srcRow
[col
* 4 + RCOMP
] << 16 |
1256 srcRow
[col
* 4 + GCOMP
] << 8 |
1257 srcRow
[col
* 4 + BCOMP
] << 0 |
1258 srcRow
[col
* 4 + ACOMP
] << 24);
1260 dstRow
+= dstRowStride
;
1261 srcRow
+= srcRowStride
;
1263 dstImage
+= dstImageStride
;
1266 else if (!ctx
->_ImageTransferState
&&
1267 !srcPacking
->SwapBytes
&&
1268 dstFormat
== &_mesa_texformat_argb8888
&&
1269 srcFormat
== GL_RGBA
&&
1270 srcType
== GL_UNSIGNED_BYTE
) {
1273 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1274 + dstZoffset
* dstImageStride
1275 + dstYoffset
* dstRowStride
1276 + dstXoffset
* dstFormat
->TexelBytes
;
1277 for (img
= 0; img
< srcDepth
; img
++) {
1278 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1279 srcWidth
, srcFormat
, srcType
);
1280 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1281 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1282 GLubyte
*dstRow
= dstImage
;
1283 for (row
= 0; row
< srcHeight
; row
++) {
1284 for (col
= 0; col
< srcWidth
; col
++) {
1285 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1286 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1287 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1288 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1290 dstRow
+= dstRowStride
;
1291 srcRow
+= srcRowStride
;
1293 dstImage
+= dstImageStride
;
1296 else if (!ctx
->_ImageTransferState
&&
1297 !srcPacking
->SwapBytes
&&
1298 dstFormat
== &_mesa_texformat_argb8888
&&
1299 srcType
== GL_UNSIGNED_BYTE
&&
1301 /* Three texture formats involved: srcFormat,
1302 * baseInternalFormat and destFormat (GL_RGBA). Only two
1303 * may differ. _mesa_swizzle_ubyte_image can't handle two
1304 * propagations at once correctly. */
1305 (srcFormat
== baseInternalFormat
||
1306 baseInternalFormat
== GL_RGBA
) &&
1307 can_swizzle(srcFormat
)) {
1311 /* dstmap - how to swizzle from GL_RGBA to dst format:
1313 dstmap
[3] = 3; /* alpha */
1314 dstmap
[2] = 0; /* red */
1315 dstmap
[1] = 1; /* green */
1316 dstmap
[0] = 2; /* blue */
1318 _mesa_swizzle_ubyte_image(ctx
, dims
,
1321 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1322 dstRowStride
, dstImageStride
,
1323 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1328 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1330 dstFormat
->BaseFormat
,
1331 srcWidth
, srcHeight
, srcDepth
,
1332 srcFormat
, srcType
, srcAddr
,
1334 const GLchan
*src
= tempImage
;
1335 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1336 + dstZoffset
* dstImageStride
1337 + dstYoffset
* dstRowStride
1338 + dstXoffset
* dstFormat
->TexelBytes
;
1339 GLint img
, row
, col
;
1342 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1343 for (img
= 0; img
< srcDepth
; img
++) {
1344 GLubyte
*dstRow
= dstImage
;
1345 for (row
= 0; row
< srcHeight
; row
++) {
1346 GLuint
*dstUI
= (GLuint
*) dstRow
;
1347 if (dstFormat
== &_mesa_texformat_argb8888
) {
1348 for (col
= 0; col
< srcWidth
; col
++) {
1349 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1350 CHAN_TO_UBYTE(src
[RCOMP
]),
1351 CHAN_TO_UBYTE(src
[GCOMP
]),
1352 CHAN_TO_UBYTE(src
[BCOMP
]) );
1357 for (col
= 0; col
< srcWidth
; col
++) {
1358 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1359 CHAN_TO_UBYTE(src
[RCOMP
]),
1360 CHAN_TO_UBYTE(src
[GCOMP
]),
1361 CHAN_TO_UBYTE(src
[BCOMP
]) );
1365 dstRow
+= dstRowStride
;
1367 dstImage
+= dstImageStride
;
1369 _mesa_free((void *) tempImage
);
1376 _mesa_texstore_rgb888(STORE_PARAMS
)
1378 const GLuint ui
= 1;
1379 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1381 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1382 ASSERT(dstFormat
->TexelBytes
== 3);
1384 if (!ctx
->_ImageTransferState
&&
1385 !srcPacking
->SwapBytes
&&
1386 baseInternalFormat
== GL_RGB
&&
1387 srcFormat
== GL_BGR
&&
1388 srcType
== GL_UNSIGNED_BYTE
&&
1390 /* simple memcpy path */
1391 memcpy_texture(ctx
, dims
,
1392 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1393 dstRowStride
, dstImageStride
,
1394 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1395 srcAddr
, srcPacking
);
1397 else if (!ctx
->_ImageTransferState
&&
1398 !srcPacking
->SwapBytes
&&
1399 srcFormat
== GL_RGBA
&&
1400 srcType
== GL_UNSIGNED_BYTE
) {
1401 /* extract RGB from RGBA */
1403 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1404 + dstZoffset
* dstImageStride
1405 + dstYoffset
* dstRowStride
1406 + dstXoffset
* dstFormat
->TexelBytes
;
1407 for (img
= 0; img
< srcDepth
; img
++) {
1408 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1409 srcWidth
, srcFormat
, srcType
);
1410 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1411 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1412 GLubyte
*dstRow
= dstImage
;
1413 for (row
= 0; row
< srcHeight
; row
++) {
1414 for (col
= 0; col
< srcWidth
; col
++) {
1415 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1416 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1417 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1419 dstRow
+= dstRowStride
;
1420 srcRow
+= srcRowStride
;
1422 dstImage
+= dstImageStride
;
1427 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1429 dstFormat
->BaseFormat
,
1430 srcWidth
, srcHeight
, srcDepth
,
1431 srcFormat
, srcType
, srcAddr
,
1433 const GLchan
*src
= (const GLchan
*) tempImage
;
1434 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1435 + dstZoffset
* dstImageStride
1436 + dstYoffset
* dstRowStride
1437 + dstXoffset
* dstFormat
->TexelBytes
;
1438 GLint img
, row
, col
;
1441 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1442 for (img
= 0; img
< srcDepth
; img
++) {
1443 GLubyte
*dstRow
= dstImage
;
1444 for (row
= 0; row
< srcHeight
; row
++) {
1447 for (col
= 0; col
< srcWidth
; col
++) {
1448 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1449 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1450 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1455 for (col
= 0; col
< srcWidth
; col
++) {
1456 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1457 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1458 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1463 for (col
= 0; col
< srcWidth
; col
++) {
1464 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1465 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1466 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1470 dstRow
+= dstRowStride
;
1472 dstImage
+= dstImageStride
;
1474 _mesa_free((void *) tempImage
);
1481 _mesa_texstore_bgr888(STORE_PARAMS
)
1483 const GLuint ui
= 1;
1484 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1486 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1487 ASSERT(dstFormat
->TexelBytes
== 3);
1489 if (!ctx
->_ImageTransferState
&&
1490 !srcPacking
->SwapBytes
&&
1491 baseInternalFormat
== GL_RGB
&&
1492 srcFormat
== GL_RGB
&&
1493 srcType
== GL_UNSIGNED_BYTE
&&
1495 /* simple memcpy path */
1496 memcpy_texture(ctx
, dims
,
1497 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1498 dstRowStride
, dstImageStride
,
1499 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1500 srcAddr
, srcPacking
);
1502 else if (!ctx
->_ImageTransferState
&&
1503 !srcPacking
->SwapBytes
&&
1504 srcFormat
== GL_RGBA
&&
1505 srcType
== GL_UNSIGNED_BYTE
) {
1506 /* extract BGR from RGBA */
1508 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1509 + dstZoffset
* dstImageStride
1510 + dstYoffset
* dstRowStride
1511 + dstXoffset
* dstFormat
->TexelBytes
;
1512 for (img
= 0; img
< srcDepth
; img
++) {
1513 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1514 srcWidth
, srcFormat
, srcType
);
1515 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1516 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1517 GLubyte
*dstRow
= dstImage
;
1518 for (row
= 0; row
< srcHeight
; row
++) {
1519 for (col
= 0; col
< srcWidth
; col
++) {
1520 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1521 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1522 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1524 dstRow
+= dstRowStride
;
1525 srcRow
+= srcRowStride
;
1527 dstImage
+= dstImageStride
;
1532 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1534 dstFormat
->BaseFormat
,
1535 srcWidth
, srcHeight
, srcDepth
,
1536 srcFormat
, srcType
, srcAddr
,
1538 const GLchan
*src
= (const GLchan
*) tempImage
;
1539 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1540 + dstZoffset
* dstImageStride
1541 + dstYoffset
* dstRowStride
1542 + dstXoffset
* dstFormat
->TexelBytes
;
1543 GLint img
, row
, col
;
1546 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1547 for (img
= 0; img
< srcDepth
; img
++) {
1548 GLubyte
*dstRow
= dstImage
;
1549 for (row
= 0; row
< srcHeight
; row
++) {
1550 for (col
= 0; col
< srcWidth
; col
++) {
1551 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1552 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1553 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1556 dstRow
+= dstRowStride
;
1558 dstImage
+= dstImageStride
;
1560 _mesa_free((void *) tempImage
);
1567 _mesa_texstore_argb4444(STORE_PARAMS
)
1569 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1570 dstFormat
== &_mesa_texformat_argb4444_rev
);
1571 ASSERT(dstFormat
->TexelBytes
== 2);
1573 if (!ctx
->_ImageTransferState
&&
1574 !srcPacking
->SwapBytes
&&
1575 dstFormat
== &_mesa_texformat_argb4444
&&
1576 baseInternalFormat
== GL_RGBA
&&
1577 srcFormat
== GL_BGRA
&&
1578 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1579 /* simple memcpy path */
1580 memcpy_texture(ctx
, dims
,
1581 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1582 dstRowStride
, dstImageStride
,
1583 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1584 srcAddr
, srcPacking
);
1588 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1590 dstFormat
->BaseFormat
,
1591 srcWidth
, srcHeight
, srcDepth
,
1592 srcFormat
, srcType
, srcAddr
,
1594 const GLchan
*src
= tempImage
;
1595 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1596 + dstZoffset
* dstImageStride
1597 + dstYoffset
* dstRowStride
1598 + dstXoffset
* dstFormat
->TexelBytes
;
1599 GLint img
, row
, col
;
1602 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1603 for (img
= 0; img
< srcDepth
; img
++) {
1604 GLubyte
*dstRow
= dstImage
;
1605 for (row
= 0; row
< srcHeight
; row
++) {
1606 GLushort
*dstUS
= (GLushort
*) dstRow
;
1607 if (dstFormat
== &_mesa_texformat_argb4444
) {
1608 for (col
= 0; col
< srcWidth
; col
++) {
1609 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1610 CHAN_TO_UBYTE(src
[RCOMP
]),
1611 CHAN_TO_UBYTE(src
[GCOMP
]),
1612 CHAN_TO_UBYTE(src
[BCOMP
]) );
1617 for (col
= 0; col
< srcWidth
; col
++) {
1618 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1619 CHAN_TO_UBYTE(src
[RCOMP
]),
1620 CHAN_TO_UBYTE(src
[GCOMP
]),
1621 CHAN_TO_UBYTE(src
[BCOMP
]) );
1625 dstRow
+= dstRowStride
;
1627 dstImage
+= dstImageStride
;
1629 _mesa_free((void *) tempImage
);
1637 _mesa_texstore_argb1555(STORE_PARAMS
)
1639 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1640 dstFormat
== &_mesa_texformat_argb1555_rev
);
1641 ASSERT(dstFormat
->TexelBytes
== 2);
1643 if (!ctx
->_ImageTransferState
&&
1644 !srcPacking
->SwapBytes
&&
1645 dstFormat
== &_mesa_texformat_argb1555
&&
1646 baseInternalFormat
== GL_RGBA
&&
1647 srcFormat
== GL_BGRA
&&
1648 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1649 /* simple memcpy path */
1650 memcpy_texture(ctx
, dims
,
1651 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1652 dstRowStride
, dstImageStride
,
1653 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1654 srcAddr
, srcPacking
);
1658 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1660 dstFormat
->BaseFormat
,
1661 srcWidth
, srcHeight
, srcDepth
,
1662 srcFormat
, srcType
, srcAddr
,
1664 const GLchan
*src
=tempImage
;
1665 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1666 + dstZoffset
* dstImageStride
1667 + dstYoffset
* dstRowStride
1668 + dstXoffset
* dstFormat
->TexelBytes
;
1669 GLint img
, row
, col
;
1672 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1673 for (img
= 0; img
< srcDepth
; img
++) {
1674 GLubyte
*dstRow
= dstImage
;
1675 for (row
= 0; row
< srcHeight
; row
++) {
1676 GLushort
*dstUS
= (GLushort
*) dstRow
;
1677 if (dstFormat
== &_mesa_texformat_argb1555
) {
1678 for (col
= 0; col
< srcWidth
; col
++) {
1679 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1680 CHAN_TO_UBYTE(src
[RCOMP
]),
1681 CHAN_TO_UBYTE(src
[GCOMP
]),
1682 CHAN_TO_UBYTE(src
[BCOMP
]) );
1687 for (col
= 0; col
< srcWidth
; col
++) {
1688 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1689 CHAN_TO_UBYTE(src
[RCOMP
]),
1690 CHAN_TO_UBYTE(src
[GCOMP
]),
1691 CHAN_TO_UBYTE(src
[BCOMP
]) );
1695 dstRow
+= dstRowStride
;
1697 dstImage
+= dstImageStride
;
1699 _mesa_free((void *) tempImage
);
1706 _mesa_texstore_al88(STORE_PARAMS
)
1708 const GLuint ui
= 1;
1709 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1711 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1712 dstFormat
== &_mesa_texformat_al88_rev
);
1713 ASSERT(dstFormat
->TexelBytes
== 2);
1715 if (!ctx
->_ImageTransferState
&&
1716 !srcPacking
->SwapBytes
&&
1717 dstFormat
== &_mesa_texformat_al88
&&
1718 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1719 srcFormat
== GL_LUMINANCE_ALPHA
&&
1720 srcType
== GL_UNSIGNED_BYTE
&&
1722 /* simple memcpy path */
1723 memcpy_texture(ctx
, dims
,
1724 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1725 dstRowStride
, dstImageStride
,
1726 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1727 srcAddr
, srcPacking
);
1731 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1733 dstFormat
->BaseFormat
,
1734 srcWidth
, srcHeight
, srcDepth
,
1735 srcFormat
, srcType
, srcAddr
,
1737 const GLchan
*src
= tempImage
;
1738 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1739 + dstZoffset
* dstImageStride
1740 + dstYoffset
* dstRowStride
1741 + dstXoffset
* dstFormat
->TexelBytes
;
1742 GLint img
, row
, col
;
1745 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1746 for (img
= 0; img
< srcDepth
; img
++) {
1747 GLubyte
*dstRow
= dstImage
;
1748 for (row
= 0; row
< srcHeight
; row
++) {
1749 GLushort
*dstUS
= (GLushort
*) dstRow
;
1750 if (dstFormat
== &_mesa_texformat_al88
) {
1751 for (col
= 0; col
< srcWidth
; col
++) {
1752 /* src[0] is luminance, src[1] is alpha */
1753 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1754 CHAN_TO_UBYTE(src
[0]) );
1759 for (col
= 0; col
< srcWidth
; col
++) {
1760 /* src[0] is luminance, src[1] is alpha */
1761 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1762 CHAN_TO_UBYTE(src
[0]) );
1766 dstRow
+= dstRowStride
;
1768 dstImage
+= dstImageStride
;
1770 _mesa_free((void *) tempImage
);
1777 _mesa_texstore_rgb332(STORE_PARAMS
)
1779 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1780 ASSERT(dstFormat
->TexelBytes
== 1);
1782 if (!ctx
->_ImageTransferState
&&
1783 !srcPacking
->SwapBytes
&&
1784 baseInternalFormat
== GL_RGB
&&
1785 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1786 /* simple memcpy path */
1787 memcpy_texture(ctx
, dims
,
1788 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1789 dstRowStride
, dstImageStride
,
1790 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1791 srcAddr
, srcPacking
);
1795 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1797 dstFormat
->BaseFormat
,
1798 srcWidth
, srcHeight
, srcDepth
,
1799 srcFormat
, srcType
, srcAddr
,
1801 const GLchan
*src
= tempImage
;
1802 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1803 + dstZoffset
* dstImageStride
1804 + dstYoffset
* dstRowStride
1805 + dstXoffset
* dstFormat
->TexelBytes
;
1806 GLint img
, row
, col
;
1809 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1810 for (img
= 0; img
< srcDepth
; img
++) {
1811 GLubyte
*dstRow
= dstImage
;
1812 for (row
= 0; row
< srcHeight
; row
++) {
1813 for (col
= 0; col
< srcWidth
; col
++) {
1814 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1815 CHAN_TO_UBYTE(src
[GCOMP
]),
1816 CHAN_TO_UBYTE(src
[BCOMP
]) );
1819 dstRow
+= dstRowStride
;
1821 dstImage
+= dstImageStride
;
1823 _mesa_free((void *) tempImage
);
1830 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1833 _mesa_texstore_a8(STORE_PARAMS
)
1835 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1836 dstFormat
== &_mesa_texformat_l8
||
1837 dstFormat
== &_mesa_texformat_i8
);
1838 ASSERT(dstFormat
->TexelBytes
== 1);
1840 if (!ctx
->_ImageTransferState
&&
1841 !srcPacking
->SwapBytes
&&
1842 baseInternalFormat
== srcFormat
&&
1843 srcType
== GL_UNSIGNED_BYTE
) {
1844 /* simple memcpy path */
1845 memcpy_texture(ctx
, dims
,
1846 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1847 dstRowStride
, dstImageStride
,
1848 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1849 srcAddr
, srcPacking
);
1853 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1855 dstFormat
->BaseFormat
,
1856 srcWidth
, srcHeight
, srcDepth
,
1857 srcFormat
, srcType
, srcAddr
,
1859 const GLchan
*src
= tempImage
;
1860 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1861 + dstZoffset
* dstImageStride
1862 + dstYoffset
* dstRowStride
1863 + dstXoffset
* dstFormat
->TexelBytes
;
1864 GLint img
, row
, col
;
1867 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1868 for (img
= 0; img
< srcDepth
; img
++) {
1869 GLubyte
*dstRow
= dstImage
;
1870 for (row
= 0; row
< srcHeight
; row
++) {
1871 for (col
= 0; col
< srcWidth
; col
++) {
1872 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1874 dstRow
+= dstRowStride
;
1877 dstImage
+= dstImageStride
;
1879 _mesa_free((void *) tempImage
);
1887 _mesa_texstore_ci8(STORE_PARAMS
)
1889 (void) dims
; (void) baseInternalFormat
;
1890 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1891 ASSERT(dstFormat
->TexelBytes
== 1);
1892 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1894 if (!ctx
->_ImageTransferState
&&
1895 !srcPacking
->SwapBytes
&&
1896 srcFormat
== GL_COLOR_INDEX
&&
1897 srcType
== GL_UNSIGNED_BYTE
) {
1898 /* simple memcpy path */
1899 memcpy_texture(ctx
, dims
,
1900 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1901 dstRowStride
, dstImageStride
,
1902 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1903 srcAddr
, srcPacking
);
1907 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1908 + dstZoffset
* dstImageStride
1909 + dstYoffset
* dstRowStride
1910 + dstXoffset
* dstFormat
->TexelBytes
;
1912 for (img
= 0; img
< srcDepth
; img
++) {
1913 GLubyte
*dstRow
= dstImage
;
1914 for (row
= 0; row
< srcHeight
; row
++) {
1915 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1916 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1917 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1918 srcType
, src
, srcPacking
,
1919 ctx
->_ImageTransferState
);
1920 dstRow
+= dstRowStride
;
1922 dstImage
+= dstImageStride
;
1930 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1933 _mesa_texstore_ycbcr(STORE_PARAMS
)
1935 const GLuint ui
= 1;
1936 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1937 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
1939 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1940 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1941 ASSERT(dstFormat
->TexelBytes
== 2);
1942 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1943 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1944 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1945 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1946 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1948 /* always just memcpy since no pixel transfer ops apply */
1949 memcpy_texture(ctx
, dims
,
1950 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1951 dstRowStride
, dstImageStride
,
1952 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1953 srcAddr
, srcPacking
);
1955 /* Check if we need byte swapping */
1956 /* XXX the logic here _might_ be wrong */
1957 if (srcPacking
->SwapBytes
^
1958 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1959 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1961 GLubyte
*pImage
= (GLubyte
*) dstAddr
1962 + dstZoffset
* dstImageStride
1963 + dstYoffset
* dstRowStride
1964 + dstXoffset
* dstFormat
->TexelBytes
;
1966 for (img
= 0; img
< srcDepth
; img
++) {
1967 GLubyte
*pRow
= pImage
;
1968 for (row
= 0; row
< srcHeight
; row
++) {
1969 _mesa_swap2((GLushort
*) pRow
, srcWidth
);
1970 pRow
+= dstRowStride
;
1972 pImage
+= dstImageStride
;
1981 * Store a combined depth/stencil texture image.
1984 _mesa_texstore_z24_s8(STORE_PARAMS
)
1986 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
1987 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
1988 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
1990 if (!ctx
->_ImageTransferState
&&
1991 !srcPacking
->SwapBytes
) {
1993 memcpy_texture(ctx
, dims
,
1994 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1995 dstRowStride
, dstImageStride
,
1996 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1997 srcAddr
, srcPacking
);
2001 const GLint srcRowStride
2002 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2004 GLuint
*dstImage
= (GLuint
*) dstAddr
;
2007 for (img
= 0; img
< srcDepth
; img
++) {
2008 GLuint
*dst
= dstImage
;
2010 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2011 srcWidth
, srcHeight
,
2014 for (row
= 0; row
< srcHeight
; row
++) {
2015 GLubyte stencil
[MAX_WIDTH
];
2017 /* the 24 depth bits will be in the high position: */
2018 _mesa_unpack_depth_span(ctx
, srcWidth
,
2019 GL_UNSIGNED_INT
, /* dst type */
2021 (GLfloat
) 0xffffff, /* depthScale */
2022 srcType
, src
, srcPacking
);
2023 /* get the 8-bit stencil values */
2024 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2025 GL_UNSIGNED_BYTE
, /* dst type */
2026 stencil
, /* dst addr */
2027 srcType
, src
, srcPacking
,
2028 ctx
->_ImageTransferState
);
2029 /* merge stencil values into depth values */
2030 for (i
= 0; i
< srcWidth
; i
++)
2031 dst
[i
] |= stencil
[i
];
2033 src
+= srcRowStride
;
2034 dst
+= dstRowStride
/ sizeof(GLuint
);
2036 dstImage
+= dstImageStride
/ sizeof(GLuint
);
2047 * Store an image in any of the formats:
2048 * _mesa_texformat_rgba_float32
2049 * _mesa_texformat_rgb_float32
2050 * _mesa_texformat_alpha_float32
2051 * _mesa_texformat_luminance_float32
2052 * _mesa_texformat_luminance_alpha_float32
2053 * _mesa_texformat_intensity_float32
2056 _mesa_texstore_rgba_float32(STORE_PARAMS
)
2058 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2060 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2061 dstFormat
== &_mesa_texformat_rgb_float32
||
2062 dstFormat
== &_mesa_texformat_alpha_float32
||
2063 dstFormat
== &_mesa_texformat_luminance_float32
||
2064 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2065 dstFormat
== &_mesa_texformat_intensity_float32
);
2066 ASSERT(baseInternalFormat
== GL_RGBA
||
2067 baseInternalFormat
== GL_RGB
||
2068 baseInternalFormat
== GL_ALPHA
||
2069 baseInternalFormat
== GL_LUMINANCE
||
2070 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2071 baseInternalFormat
== GL_INTENSITY
);
2072 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2074 if (!ctx
->_ImageTransferState
&&
2075 !srcPacking
->SwapBytes
&&
2076 baseInternalFormat
== srcFormat
&&
2077 srcType
== GL_FLOAT
) {
2078 /* simple memcpy path */
2079 memcpy_texture(ctx
, dims
,
2080 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2081 dstRowStride
, dstImageStride
,
2082 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2083 srcAddr
, srcPacking
);
2087 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2089 dstFormat
->BaseFormat
,
2090 srcWidth
, srcHeight
, srcDepth
,
2091 srcFormat
, srcType
, srcAddr
,
2093 const GLfloat
*src
= tempImage
;
2095 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2096 + dstZoffset
* dstImageStride
2097 + dstYoffset
* dstRowStride
2098 + dstXoffset
* dstFormat
->TexelBytes
;
2102 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2103 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2104 for (img
= 0; img
< srcDepth
; img
++) {
2105 GLubyte
*dst
= dstImage
;
2106 for (row
= 0; row
< srcHeight
; row
++) {
2107 _mesa_memcpy(dst
, src
, bytesPerRow
);
2108 dst
+= dstRowStride
;
2109 src
+= srcWidth
* components
;
2111 dstImage
+= dstImageStride
;
2114 _mesa_free((void *) tempImage
);
2121 * As above, but store 16-bit floats.
2124 _mesa_texstore_rgba_float16(STORE_PARAMS
)
2126 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2128 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2129 dstFormat
== &_mesa_texformat_rgb_float16
||
2130 dstFormat
== &_mesa_texformat_alpha_float16
||
2131 dstFormat
== &_mesa_texformat_luminance_float16
||
2132 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2133 dstFormat
== &_mesa_texformat_intensity_float16
);
2134 ASSERT(baseInternalFormat
== GL_RGBA
||
2135 baseInternalFormat
== GL_RGB
||
2136 baseInternalFormat
== GL_ALPHA
||
2137 baseInternalFormat
== GL_LUMINANCE
||
2138 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2139 baseInternalFormat
== GL_INTENSITY
);
2140 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2142 if (!ctx
->_ImageTransferState
&&
2143 !srcPacking
->SwapBytes
&&
2144 baseInternalFormat
== srcFormat
&&
2145 srcType
== GL_HALF_FLOAT_ARB
) {
2146 /* simple memcpy path */
2147 memcpy_texture(ctx
, dims
,
2148 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2149 dstRowStride
, dstImageStride
,
2150 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2151 srcAddr
, srcPacking
);
2155 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2157 dstFormat
->BaseFormat
,
2158 srcWidth
, srcHeight
, srcDepth
,
2159 srcFormat
, srcType
, srcAddr
,
2161 const GLfloat
*src
= tempImage
;
2162 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2163 + dstZoffset
* dstImageStride
2164 + dstYoffset
* dstRowStride
2165 + dstXoffset
* dstFormat
->TexelBytes
;
2169 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2170 for (img
= 0; img
< srcDepth
; img
++) {
2171 GLubyte
*dstRow
= dstImage
;
2172 for (row
= 0; row
< srcHeight
; row
++) {
2173 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2175 for (i
= 0; i
< srcWidth
* components
; i
++) {
2176 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2178 dstRow
+= dstRowStride
;
2179 src
+= srcWidth
* components
;
2181 dstImage
+= dstImageStride
;
2184 _mesa_free((void *) tempImage
);
2192 * Check if an unpack PBO is active prior to fetching a texture image.
2193 * If so, do bounds checking and map the buffer into main memory.
2194 * Any errors detected will be recorded.
2195 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2198 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2199 GLsizei width
, GLsizei height
, GLsizei depth
,
2200 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2201 const struct gl_pixelstore_attrib
*unpack
,
2202 const char *funcName
)
2206 if (unpack
->BufferObj
->Name
== 0) {
2210 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2211 format
, type
, pixels
)) {
2212 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2216 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2217 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2219 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2223 return ADD_POINTERS(buf
, pixels
);
2228 * Check if an unpack PBO is active prior to fetching a compressed texture
2230 * If so, do bounds checking and map the buffer into main memory.
2231 * Any errors detected will be recorded.
2232 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2235 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2236 GLsizei imageSize
, const GLvoid
*pixels
,
2237 const struct gl_pixelstore_attrib
*packing
,
2238 const char *funcName
)
2242 if (packing
->BufferObj
->Name
== 0) {
2243 /* not using a PBO - return pointer unchanged */
2246 if ((const GLubyte
*) pixels
+ imageSize
>
2247 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2248 /* out of bounds read! */
2249 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2253 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2254 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2256 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2260 return ADD_POINTERS(buf
, pixels
);
2265 * This function must be called after either of the validate_pbo_*_teximage()
2266 * functions. It unmaps the PBO buffer if it was mapped earlier.
2269 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2270 const struct gl_pixelstore_attrib
*unpack
)
2272 if (unpack
->BufferObj
->Name
) {
2273 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2281 * Adaptor for fetching a GLchan texel from a float-valued texture.
2284 FetchTexelFloatToChan( const struct gl_texture_image
*texImage
,
2285 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2288 ASSERT(texImage
->FetchTexelf
);
2289 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2290 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2291 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2292 /* just one channel */
2293 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2297 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2298 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2299 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2300 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2306 * Adaptor for fetching a float texel from a GLchan-valued texture.
2309 FetchTexelChanToFloat( const struct gl_texture_image
*texImage
,
2310 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2313 ASSERT(texImage
->FetchTexelc
);
2314 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2315 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2316 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2317 /* just one channel */
2318 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2322 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2323 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2324 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2325 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2331 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2334 set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2336 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2337 ASSERT(texImage
->TexFormat
);
2341 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2342 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2345 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2346 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2349 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2350 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2356 /* now check if we need to use a float/chan adaptor */
2357 if (!texImage
->FetchTexelc
) {
2358 texImage
->FetchTexelc
= FetchTexelFloatToChan
;
2360 else if (!texImage
->FetchTexelf
) {
2361 texImage
->FetchTexelf
= FetchTexelChanToFloat
;
2365 ASSERT(texImage
->FetchTexelc
);
2366 ASSERT(texImage
->FetchTexelf
);
2371 * Choose the actual storage format for a new texture image.
2372 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2373 * Also set some other texImage fields related to texture compression, etc.
2374 * \param ctx rendering context
2375 * \param texImage the gl_texture_image
2376 * \param dims texture dimensions (1, 2 or 3)
2377 * \param format the user-specified format parameter
2378 * \param type the user-specified type parameter
2379 * \param internalFormat the user-specified internal format hint
2382 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2384 GLenum format
, GLenum type
, GLint internalFormat
)
2386 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2387 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2390 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2392 ASSERT(texImage
->TexFormat
);
2394 set_fetch_functions(texImage
, dims
);
2396 if (texImage
->TexFormat
->TexelBytes
== 0) {
2397 /* must be a compressed format */
2398 texImage
->IsCompressed
= GL_TRUE
;
2399 texImage
->CompressedSize
=
2400 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2401 texImage
->Height
, texImage
->Depth
,
2402 texImage
->TexFormat
->MesaFormat
);
2405 /* non-compressed format */
2406 texImage
->IsCompressed
= GL_FALSE
;
2407 texImage
->CompressedSize
= 0;
2414 * This is the software fallback for Driver.TexImage1D()
2415 * and Driver.CopyTexImage1D().
2416 * \sa _mesa_store_teximage2d()
2419 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2420 GLint internalFormat
,
2421 GLint width
, GLint border
,
2422 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2423 const struct gl_pixelstore_attrib
*packing
,
2424 struct gl_texture_object
*texObj
,
2425 struct gl_texture_image
*texImage
)
2427 GLint postConvWidth
= width
;
2431 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2432 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2435 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2437 /* allocate memory */
2438 if (texImage
->IsCompressed
)
2439 sizeInBytes
= texImage
->CompressedSize
;
2441 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2442 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2443 if (!texImage
->Data
) {
2444 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2448 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2449 pixels
, packing
, "glTexImage1D");
2451 /* Note: we check for a NULL image pointer here, _after_ we allocated
2452 * memory for the texture. That's what the GL spec calls for.
2457 const GLint dstRowStride
= 0, dstImageStride
= 0;
2459 ASSERT(texImage
->TexFormat
->StoreImage
);
2460 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2461 texImage
->TexFormat
,
2463 0, 0, 0, /* dstX/Y/Zoffset */
2464 dstRowStride
, dstImageStride
,
2466 format
, type
, pixels
, packing
);
2468 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2472 /* GL_SGIS_generate_mipmap */
2473 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2474 _mesa_generate_mipmap(ctx
, target
,
2475 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2479 _mesa_unmap_teximage_pbo(ctx
, packing
);
2484 * This is the software fallback for Driver.TexImage2D()
2485 * and Driver.CopyTexImage2D().
2486 * We store the image in heap memory. We know nothing about on-board
2487 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2488 * textures in main memory, this routine will typically be used by
2489 * hardware drivers too.
2491 * Reasons why a driver might override this function:
2492 * - Special memory allocation needs (VRAM, AGP, etc)
2493 * - Unusual row/image strides or padding
2494 * - Special housekeeping
2495 * - Using VRAM-based Pixel Buffer Objects
2498 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2499 GLint internalFormat
,
2500 GLint width
, GLint height
, GLint border
,
2501 GLenum format
, GLenum type
, const void *pixels
,
2502 const struct gl_pixelstore_attrib
*packing
,
2503 struct gl_texture_object
*texObj
,
2504 struct gl_texture_image
*texImage
)
2506 GLint postConvWidth
= width
, postConvHeight
= height
;
2507 GLint texelBytes
, sizeInBytes
;
2510 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2511 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2515 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2517 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2519 /* allocate memory */
2520 if (texImage
->IsCompressed
)
2521 sizeInBytes
= texImage
->CompressedSize
;
2523 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2524 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2525 if (!texImage
->Data
) {
2526 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2530 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2531 pixels
, packing
, "glTexImage2D");
2533 /* Note: we check for a NULL image pointer here, _after_ we allocated
2534 * memory for the texture. That's what the GL spec calls for.
2539 GLint dstRowStride
, dstImageStride
= 0;
2541 if (texImage
->IsCompressed
) {
2543 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2546 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2548 ASSERT(texImage
->TexFormat
->StoreImage
);
2549 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2550 texImage
->TexFormat
,
2552 0, 0, 0, /* dstX/Y/Zoffset */
2553 dstRowStride
, dstImageStride
,
2555 format
, type
, pixels
, packing
);
2557 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2561 /* GL_SGIS_generate_mipmap */
2562 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2563 _mesa_generate_mipmap(ctx
, target
,
2564 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2568 _mesa_unmap_teximage_pbo(ctx
, packing
);
2574 * This is the software fallback for Driver.TexImage3D()
2575 * and Driver.CopyTexImage3D().
2576 * \sa _mesa_store_teximage2d()
2579 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2580 GLint internalFormat
,
2581 GLint width
, GLint height
, GLint depth
, GLint border
,
2582 GLenum format
, GLenum type
, const void *pixels
,
2583 const struct gl_pixelstore_attrib
*packing
,
2584 struct gl_texture_object
*texObj
,
2585 struct gl_texture_image
*texImage
)
2587 GLint texelBytes
, sizeInBytes
;
2590 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
2592 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2594 /* allocate memory */
2595 if (texImage
->IsCompressed
)
2596 sizeInBytes
= texImage
->CompressedSize
;
2598 sizeInBytes
= width
* height
* depth
* texelBytes
;
2599 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2600 if (!texImage
->Data
) {
2601 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2605 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2606 type
, pixels
, packing
, "glTexImage3D");
2608 /* Note: we check for a NULL image pointer here, _after_ we allocated
2609 * memory for the texture. That's what the GL spec calls for.
2614 GLint dstRowStride
, dstImageStride
;
2616 if (texImage
->IsCompressed
) {
2618 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2622 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2623 dstImageStride
= dstRowStride
* height
;
2625 ASSERT(texImage
->TexFormat
->StoreImage
);
2626 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2627 texImage
->TexFormat
,
2629 0, 0, 0, /* dstX/Y/Zoffset */
2630 dstRowStride
, dstImageStride
,
2631 width
, height
, depth
,
2632 format
, type
, pixels
, packing
);
2634 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2638 /* GL_SGIS_generate_mipmap */
2639 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2640 _mesa_generate_mipmap(ctx
, target
,
2641 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2645 _mesa_unmap_teximage_pbo(ctx
, packing
);
2652 * This is the software fallback for Driver.TexSubImage1D()
2653 * and Driver.CopyTexSubImage1D().
2656 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2657 GLint xoffset
, GLint width
,
2658 GLenum format
, GLenum type
, const void *pixels
,
2659 const struct gl_pixelstore_attrib
*packing
,
2660 struct gl_texture_object
*texObj
,
2661 struct gl_texture_image
*texImage
)
2663 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2664 pixels
, packing
, "glTexSubImage1D");
2669 const GLint dstRowStride
= 0, dstImageStride
= 0;
2671 ASSERT(texImage
->TexFormat
->StoreImage
);
2672 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2673 texImage
->TexFormat
,
2675 xoffset
, 0, 0, /* offsets */
2676 dstRowStride
, dstImageStride
,
2678 format
, type
, pixels
, packing
);
2680 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2684 /* GL_SGIS_generate_mipmap */
2685 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2686 _mesa_generate_mipmap(ctx
, target
,
2687 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2691 _mesa_unmap_teximage_pbo(ctx
, packing
);
2697 * This is the software fallback for Driver.TexSubImage2D()
2698 * and Driver.CopyTexSubImage2D().
2701 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2702 GLint xoffset
, GLint yoffset
,
2703 GLint width
, GLint height
,
2704 GLenum format
, GLenum type
, const void *pixels
,
2705 const struct gl_pixelstore_attrib
*packing
,
2706 struct gl_texture_object
*texObj
,
2707 struct gl_texture_image
*texImage
)
2709 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2710 pixels
, packing
, "glTexSubImage2D");
2715 GLint dstRowStride
= 0, dstImageStride
= 0;
2717 if (texImage
->IsCompressed
) {
2718 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
2722 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2724 ASSERT(texImage
->TexFormat
->StoreImage
);
2725 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2726 texImage
->TexFormat
,
2728 xoffset
, yoffset
, 0,
2729 dstRowStride
, dstImageStride
,
2731 format
, type
, pixels
, packing
);
2733 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2737 /* GL_SGIS_generate_mipmap */
2738 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2739 _mesa_generate_mipmap(ctx
, target
,
2740 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2744 _mesa_unmap_teximage_pbo(ctx
, packing
);
2749 * This is the software fallback for Driver.TexSubImage3D().
2750 * and Driver.CopyTexSubImage3D().
2753 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2754 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2755 GLint width
, GLint height
, GLint depth
,
2756 GLenum format
, GLenum type
, const void *pixels
,
2757 const struct gl_pixelstore_attrib
*packing
,
2758 struct gl_texture_object
*texObj
,
2759 struct gl_texture_image
*texImage
)
2761 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2762 type
, pixels
, packing
,
2768 GLint dstRowStride
, dstImageStride
;
2770 if (texImage
->IsCompressed
) {
2771 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
2773 dstImageStride
= 0; /* XXX fix */
2776 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2777 dstImageStride
= dstRowStride
* texImage
->Height
;
2779 ASSERT(texImage
->TexFormat
->StoreImage
);
2780 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2781 texImage
->TexFormat
,
2783 xoffset
, yoffset
, zoffset
,
2784 dstRowStride
, dstImageStride
,
2785 width
, height
, depth
,
2786 format
, type
, pixels
, packing
);
2788 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2792 /* GL_SGIS_generate_mipmap */
2793 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2794 _mesa_generate_mipmap(ctx
, target
,
2795 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2799 _mesa_unmap_teximage_pbo(ctx
, packing
);
2804 * Fallback for Driver.CompressedTexImage1D()
2807 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2808 GLint internalFormat
,
2809 GLint width
, GLint border
,
2810 GLsizei imageSize
, const GLvoid
*data
,
2811 struct gl_texture_object
*texObj
,
2812 struct gl_texture_image
*texImage
)
2814 /* this space intentionally left blank */
2816 (void) target
; (void) level
;
2817 (void) internalFormat
;
2818 (void) width
; (void) border
;
2819 (void) imageSize
; (void) data
;
2827 * Fallback for Driver.CompressedTexImage2D()
2830 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2831 GLint internalFormat
,
2832 GLint width
, GLint height
, GLint border
,
2833 GLsizei imageSize
, const GLvoid
*data
,
2834 struct gl_texture_object
*texObj
,
2835 struct gl_texture_image
*texImage
)
2837 (void) width
; (void) height
; (void) border
;
2839 /* This is pretty simple, basically just do a memcpy without worrying
2840 * about the usual image unpacking or image transfer operations.
2844 ASSERT(texImage
->Width
> 0);
2845 ASSERT(texImage
->Height
> 0);
2846 ASSERT(texImage
->Depth
== 1);
2847 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2849 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
2851 /* allocate storage */
2852 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
2853 if (!texImage
->Data
) {
2854 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2858 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2860 "glCompressedTexImage2D");
2865 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2866 MEMCPY(texImage
->Data
, data
, imageSize
);
2868 /* GL_SGIS_generate_mipmap */
2869 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2870 _mesa_generate_mipmap(ctx
, target
,
2871 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2875 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2881 * Fallback for Driver.CompressedTexImage3D()
2884 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2885 GLint internalFormat
,
2886 GLint width
, GLint height
, GLint depth
,
2888 GLsizei imageSize
, const GLvoid
*data
,
2889 struct gl_texture_object
*texObj
,
2890 struct gl_texture_image
*texImage
)
2892 /* this space intentionally left blank */
2894 (void) target
; (void) level
;
2895 (void) internalFormat
;
2896 (void) width
; (void) height
; (void) depth
;
2898 (void) imageSize
; (void) data
;
2906 * Fallback for Driver.CompressedTexSubImage1D()
2909 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2911 GLint xoffset
, GLsizei width
,
2913 GLsizei imageSize
, const GLvoid
*data
,
2914 struct gl_texture_object
*texObj
,
2915 struct gl_texture_image
*texImage
)
2917 /* there are no compressed 1D texture formats yet */
2919 (void) target
; (void) level
;
2920 (void) xoffset
; (void) width
;
2922 (void) imageSize
; (void) data
;
2929 * Fallback for Driver.CompressedTexSubImage2D()
2932 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2934 GLint xoffset
, GLint yoffset
,
2935 GLsizei width
, GLsizei height
,
2937 GLsizei imageSize
, const GLvoid
*data
,
2938 struct gl_texture_object
*texObj
,
2939 struct gl_texture_image
*texImage
)
2941 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2945 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
2949 /* these should have been caught sooner */
2950 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2951 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2952 ASSERT((xoffset
& 3) == 0);
2953 ASSERT((yoffset
& 3) == 0);
2955 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2957 "glCompressedTexSubImage2D");
2961 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
2962 src
= (const GLubyte
*) data
;
2964 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
2965 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2966 texImage
->InternalFormat
,
2968 (GLubyte
*) texImage
->Data
);
2970 bytesPerRow
= srcRowStride
;
2973 for (i
= 0; i
< rows
; i
++) {
2974 MEMCPY(dest
, src
, bytesPerRow
);
2975 dest
+= destRowStride
;
2976 src
+= srcRowStride
;
2979 /* GL_SGIS_generate_mipmap */
2980 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2981 _mesa_generate_mipmap(ctx
, target
,
2982 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2986 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2991 * Fallback for Driver.CompressedTexSubImage3D()
2994 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2996 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2997 GLsizei width
, GLsizei height
, GLsizei depth
,
2999 GLsizei imageSize
, const GLvoid
*data
,
3000 struct gl_texture_object
*texObj
,
3001 struct gl_texture_image
*texImage
)
3003 /* there are no compressed 3D texture formats yet */
3005 (void) target
; (void) level
;
3006 (void) xoffset
; (void) yoffset
; (void) zoffset
;
3007 (void) width
; (void) height
; (void) depth
;
3009 (void) imageSize
; (void) data
;
3016 * Average together two rows of a source image to produce a single new
3017 * row in the dest image. It's legal for the two source rows to point
3018 * to the same data. The source width must be equal to either the
3019 * dest width or two times the dest width.
3022 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
3023 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
3024 GLint dstWidth
, GLvoid
*dstRow
)
3026 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
3027 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
3029 /* This assertion is no longer valid with non-power-of-2 textures
3030 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
3033 switch (format
->MesaFormat
) {
3034 case MESA_FORMAT_RGBA
:
3037 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
3038 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
3039 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
3040 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3041 i
++, j
+= colStride
, k
+= colStride
) {
3042 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3043 rowB
[j
][0] + rowB
[k
][0]) / 4;
3044 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3045 rowB
[j
][1] + rowB
[k
][1]) / 4;
3046 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3047 rowB
[j
][2] + rowB
[k
][2]) / 4;
3048 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3049 rowB
[j
][3] + rowB
[k
][3]) / 4;
3053 case MESA_FORMAT_RGB
:
3056 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
3057 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
3058 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
3059 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3060 i
++, j
+= colStride
, k
+= colStride
) {
3061 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3062 rowB
[j
][0] + rowB
[k
][0]) / 4;
3063 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3064 rowB
[j
][1] + rowB
[k
][1]) / 4;
3065 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3066 rowB
[j
][2] + rowB
[k
][2]) / 4;
3070 case MESA_FORMAT_ALPHA
:
3071 case MESA_FORMAT_LUMINANCE
:
3072 case MESA_FORMAT_INTENSITY
:
3075 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
3076 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
3077 GLchan
*dst
= (GLchan
*) dstRow
;
3078 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3079 i
++, j
+= colStride
, k
+= colStride
) {
3080 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3084 case MESA_FORMAT_LUMINANCE_ALPHA
:
3087 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
3088 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
3089 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
3090 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3091 i
++, j
+= colStride
, k
+= colStride
) {
3092 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3093 rowB
[j
][0] + rowB
[k
][0]) / 4;
3094 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3095 rowB
[j
][1] + rowB
[k
][1]) / 4;
3099 case MESA_FORMAT_Z32
:
3102 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
3103 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
3104 GLfloat
*dst
= (GLfloat
*) dstRow
;
3105 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3106 i
++, j
+= colStride
, k
+= colStride
) {
3107 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
3111 case MESA_FORMAT_Z16
:
3114 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3115 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3116 GLushort
*dst
= (GLushort
*) dstRow
;
3117 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3118 i
++, j
+= colStride
, k
+= colStride
) {
3119 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3123 /* Begin hardware formats */
3124 case MESA_FORMAT_RGBA8888
:
3125 case MESA_FORMAT_RGBA8888_REV
:
3126 case MESA_FORMAT_ARGB8888
:
3127 case MESA_FORMAT_ARGB8888_REV
:
3130 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
3131 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
3132 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
3133 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3134 i
++, j
+= colStride
, k
+= colStride
) {
3135 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3136 rowB
[j
][0] + rowB
[k
][0]) / 4;
3137 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3138 rowB
[j
][1] + rowB
[k
][1]) / 4;
3139 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3140 rowB
[j
][2] + rowB
[k
][2]) / 4;
3141 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3142 rowB
[j
][3] + rowB
[k
][3]) / 4;
3146 case MESA_FORMAT_RGB888
:
3147 case MESA_FORMAT_BGR888
:
3150 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
3151 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
3152 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
3153 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3154 i
++, j
+= colStride
, k
+= colStride
) {
3155 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3156 rowB
[j
][0] + rowB
[k
][0]) / 4;
3157 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3158 rowB
[j
][1] + rowB
[k
][1]) / 4;
3159 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3160 rowB
[j
][2] + rowB
[k
][2]) / 4;
3164 case MESA_FORMAT_RGB565
:
3165 case MESA_FORMAT_RGB565_REV
:
3168 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3169 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3170 GLushort
*dst
= (GLushort
*) dstRow
;
3171 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3172 i
++, j
+= colStride
, k
+= colStride
) {
3173 const GLint rowAr0
= rowA
[j
] & 0x1f;
3174 const GLint rowAr1
= rowA
[k
] & 0x1f;
3175 const GLint rowBr0
= rowB
[j
] & 0x1f;
3176 const GLint rowBr1
= rowB
[k
] & 0x1f;
3177 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
3178 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
3179 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
3180 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
3181 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
3182 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
3183 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
3184 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
3185 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3186 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3187 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3188 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
3192 case MESA_FORMAT_ARGB4444
:
3193 case MESA_FORMAT_ARGB4444_REV
:
3196 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3197 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3198 GLushort
*dst
= (GLushort
*) dstRow
;
3199 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3200 i
++, j
+= colStride
, k
+= colStride
) {
3201 const GLint rowAr0
= rowA
[j
] & 0xf;
3202 const GLint rowAr1
= rowA
[k
] & 0xf;
3203 const GLint rowBr0
= rowB
[j
] & 0xf;
3204 const GLint rowBr1
= rowB
[k
] & 0xf;
3205 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
3206 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
3207 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
3208 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
3209 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
3210 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
3211 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
3212 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
3213 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
3214 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
3215 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
3216 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
3217 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3218 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3219 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3220 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3221 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
3225 case MESA_FORMAT_ARGB1555
:
3226 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
3229 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3230 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3231 GLushort
*dst
= (GLushort
*) dstRow
;
3232 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3233 i
++, j
+= colStride
, k
+= colStride
) {
3234 const GLint rowAr0
= rowA
[j
] & 0x1f;
3235 const GLint rowAr1
= rowA
[k
] & 0x1f;
3236 const GLint rowBr0
= rowB
[j
] & 0x1f;
3237 const GLint rowBr1
= rowB
[k
] & 0xf;
3238 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
3239 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
3240 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
3241 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
3242 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
3243 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3244 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3245 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3246 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3247 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3248 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3249 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3250 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3251 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3252 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3253 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3254 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3258 case MESA_FORMAT_AL88
:
3259 case MESA_FORMAT_AL88_REV
:
3262 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3263 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3264 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3265 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3266 i
++, j
+= colStride
, k
+= colStride
) {
3267 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3268 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3269 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3270 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3274 case MESA_FORMAT_RGB332
:
3277 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3278 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3279 GLubyte
*dst
= (GLubyte
*) dstRow
;
3280 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3281 i
++, j
+= colStride
, k
+= colStride
) {
3282 const GLint rowAr0
= rowA
[j
] & 0x3;
3283 const GLint rowAr1
= rowA
[k
] & 0x3;
3284 const GLint rowBr0
= rowB
[j
] & 0x3;
3285 const GLint rowBr1
= rowB
[k
] & 0x3;
3286 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3287 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3288 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3289 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3290 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3291 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3292 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3293 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3294 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3295 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3296 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3297 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3301 case MESA_FORMAT_A8
:
3302 case MESA_FORMAT_L8
:
3303 case MESA_FORMAT_I8
:
3304 case MESA_FORMAT_CI8
:
3307 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3308 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3309 GLubyte
*dst
= (GLubyte
*) 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
]) >> 2;
3316 case MESA_FORMAT_RGBA_FLOAT32
:
3319 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3320 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3321 GLfloat (*dst
)[4] = (GLfloat (*)[4]) 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]) * 0.25F
;
3326 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3327 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3328 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3329 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3330 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3331 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3335 case MESA_FORMAT_RGBA_FLOAT16
:
3337 GLuint i
, j
, k
, comp
;
3338 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3339 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3340 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3341 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3342 i
++, j
+= colStride
, k
+= colStride
) {
3343 for (comp
= 0; comp
< 4; comp
++) {
3344 GLfloat aj
, ak
, bj
, bk
;
3345 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3346 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3347 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3348 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3349 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3354 case MESA_FORMAT_RGB_FLOAT32
:
3357 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3358 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3359 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3360 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3361 i
++, j
+= colStride
, k
+= colStride
) {
3362 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3363 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3364 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3365 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3366 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3367 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3371 case MESA_FORMAT_RGB_FLOAT16
:
3373 GLuint i
, j
, k
, comp
;
3374 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3375 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3376 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3377 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3378 i
++, j
+= colStride
, k
+= colStride
) {
3379 for (comp
= 0; comp
< 3; comp
++) {
3380 GLfloat aj
, ak
, bj
, bk
;
3381 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3382 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3383 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3384 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3385 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3390 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3393 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3394 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3395 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3396 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3397 i
++, j
+= colStride
, k
+= colStride
) {
3398 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3399 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3400 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3401 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3405 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3407 GLuint i
, j
, k
, comp
;
3408 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3409 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3410 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3411 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3412 i
++, j
+= colStride
, k
+= colStride
) {
3413 for (comp
= 0; comp
< 2; comp
++) {
3414 GLfloat aj
, ak
, bj
, bk
;
3415 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3416 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3417 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3418 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3419 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3424 case MESA_FORMAT_ALPHA_FLOAT32
:
3425 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3426 case MESA_FORMAT_INTENSITY_FLOAT32
:
3429 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3430 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3431 GLfloat
*dst
= (GLfloat
*) dstRow
;
3432 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3433 i
++, j
+= colStride
, k
+= colStride
) {
3434 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3438 case MESA_FORMAT_ALPHA_FLOAT16
:
3439 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3440 case MESA_FORMAT_INTENSITY_FLOAT16
:
3443 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3444 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3445 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3446 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3447 i
++, j
+= colStride
, k
+= colStride
) {
3448 GLfloat aj
, ak
, bj
, bk
;
3449 aj
= _mesa_half_to_float(rowA
[j
]);
3450 ak
= _mesa_half_to_float(rowA
[k
]);
3451 bj
= _mesa_half_to_float(rowB
[j
]);
3452 bk
= _mesa_half_to_float(rowB
[k
]);
3453 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3459 _mesa_problem(NULL
, "bad format in do_row()");
3465 * These functions generate a 1/2-size mipmap image from a source image.
3466 * Texture borders are handled by copying or averaging the source image's
3467 * border texels, depending on the scale-down factor.
3471 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3472 GLint srcWidth
, const GLubyte
*srcPtr
,
3473 GLint dstWidth
, GLubyte
*dstPtr
)
3475 const GLint bpt
= format
->TexelBytes
;
3479 /* skip the border pixel, if any */
3480 src
= srcPtr
+ border
* bpt
;
3481 dst
= dstPtr
+ border
* bpt
;
3483 /* we just duplicate the input row, kind of hack, saves code */
3484 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3485 dstWidth
- 2 * border
, dst
);
3488 /* copy left-most pixel from source */
3489 MEMCPY(dstPtr
, srcPtr
, bpt
);
3490 /* copy right-most pixel from source */
3491 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3492 srcPtr
+ (srcWidth
- 1) * bpt
,
3499 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3500 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3501 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3503 const GLint bpt
= format
->TexelBytes
;
3504 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3505 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3506 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3507 const GLint srcRowStride
= bpt
* srcWidth
;
3508 const GLint dstRowStride
= bpt
* dstWidth
;
3509 const GLubyte
*srcA
, *srcB
;
3513 /* Compute src and dst pointers, skipping any border */
3514 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3516 srcB
= srcA
+ srcRowStride
;
3519 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3521 for (row
= 0; row
< dstHeightNB
; row
++) {
3522 do_row(format
, srcWidthNB
, srcA
, srcB
,
3524 srcA
+= 2 * srcRowStride
;
3525 srcB
+= 2 * srcRowStride
;
3526 dst
+= dstRowStride
;
3529 /* This is ugly but probably won't be used much */
3531 /* fill in dest border */
3532 /* lower-left border pixel */
3533 MEMCPY(dstPtr
, srcPtr
, bpt
);
3534 /* lower-right border pixel */
3535 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3536 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3537 /* upper-left border pixel */
3538 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3539 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3540 /* upper-right border pixel */
3541 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3542 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3544 do_row(format
, srcWidthNB
,
3547 dstWidthNB
, dstPtr
+ bpt
);
3549 do_row(format
, srcWidthNB
,
3550 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3551 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3553 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3554 /* left and right borders */
3555 if (srcHeight
== dstHeight
) {
3556 /* copy border pixel from src to dst */
3557 for (row
= 1; row
< srcHeight
; row
++) {
3558 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3559 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3560 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3561 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3565 /* average two src pixels each dest pixel */
3566 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3568 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3569 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3570 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3572 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3573 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3574 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3582 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3583 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3584 const GLubyte
*srcPtr
,
3585 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3588 const GLint bpt
= format
->TexelBytes
;
3589 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3590 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3591 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3592 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3593 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3594 GLvoid
*tmpRowA
, *tmpRowB
;
3596 GLint bytesPerSrcImage
, bytesPerDstImage
;
3597 GLint bytesPerSrcRow
, bytesPerDstRow
;
3598 GLint srcImageOffset
, srcRowOffset
;
3600 (void) srcDepthNB
; /* silence warnings */
3602 /* Need two temporary row buffers */
3603 tmpRowA
= _mesa_malloc(srcWidth
* bpt
);
3606 tmpRowB
= _mesa_malloc(srcWidth
* bpt
);
3608 _mesa_free(tmpRowA
);
3612 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3613 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3615 bytesPerSrcRow
= srcWidth
* bpt
;
3616 bytesPerDstRow
= dstWidth
* bpt
;
3618 /* Offset between adjacent src images to be averaged together */
3619 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3621 /* Offset between adjacent src rows to be averaged together */
3622 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3625 * Need to average together up to 8 src pixels for each dest pixel.
3626 * Break that down into 3 operations:
3627 * 1. take two rows from source image and average them together.
3628 * 2. take two rows from next source image and average them together.
3629 * 3. take the two averaged rows and average them for the final dst row.
3633 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3634 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3637 for (img
= 0; img
< dstDepthNB
; img
++) {
3638 /* first source image pointer, skipping border */
3639 const GLubyte
*imgSrcA
= srcPtr
3640 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3641 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3642 /* second source image pointer, skipping border */
3643 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3644 /* address of the dest image, skipping border */
3645 GLubyte
*imgDst
= dstPtr
3646 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3647 + img
* bytesPerDstImage
;
3649 /* setup the four source row pointers and the dest row pointer */
3650 const GLubyte
*srcImgARowA
= imgSrcA
;
3651 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3652 const GLubyte
*srcImgBRowA
= imgSrcB
;
3653 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3654 GLubyte
*dstImgRow
= imgDst
;
3656 for (row
= 0; row
< dstHeightNB
; row
++) {
3657 /* Average together two rows from first src image */
3658 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3659 srcWidthNB
, tmpRowA
);
3660 /* Average together two rows from second src image */
3661 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3662 srcWidthNB
, tmpRowB
);
3663 /* Average together the temp rows to make the final row */
3664 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3665 dstWidthNB
, dstImgRow
);
3666 /* advance to next rows */
3667 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3668 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3669 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3670 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3671 dstImgRow
+= bytesPerDstRow
;
3675 _mesa_free(tmpRowA
);
3676 _mesa_free(tmpRowB
);
3678 /* Luckily we can leverage the make_2d_mipmap() function here! */
3680 /* do front border image */
3681 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3682 dstWidth
, dstHeight
, dstPtr
);
3683 /* do back border image */
3684 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3685 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3686 dstWidth
, dstHeight
,
3687 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3688 /* do four remaining border edges that span the image slices */
3689 if (srcDepth
== dstDepth
) {
3690 /* just copy border pixels from src to dst */
3691 for (img
= 0; img
< dstDepthNB
; img
++) {
3695 /* do border along [img][row=0][col=0] */
3696 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3697 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3698 MEMCPY(dst
, src
, bpt
);
3700 /* do border along [img][row=dstHeight-1][col=0] */
3701 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3702 + (srcHeight
- 1) * bytesPerSrcRow
;
3703 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3704 + (dstHeight
- 1) * bytesPerDstRow
;
3705 MEMCPY(dst
, src
, bpt
);
3707 /* do border along [img][row=0][col=dstWidth-1] */
3708 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3709 + (srcWidth
- 1) * bpt
;
3710 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3711 + (dstWidth
- 1) * bpt
;
3712 MEMCPY(dst
, src
, bpt
);
3714 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3715 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3716 + (bytesPerSrcImage
- bpt
);
3717 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3718 + (bytesPerDstImage
- bpt
);
3719 MEMCPY(dst
, src
, bpt
);
3723 /* average border pixels from adjacent src image pairs */
3724 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3725 for (img
= 0; img
< dstDepthNB
; img
++) {
3729 /* do border along [img][row=0][col=0] */
3730 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3731 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3732 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3734 /* do border along [img][row=dstHeight-1][col=0] */
3735 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3736 + (srcHeight
- 1) * bytesPerSrcRow
;
3737 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3738 + (dstHeight
- 1) * bytesPerDstRow
;
3739 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3741 /* do border along [img][row=0][col=dstWidth-1] */
3742 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3743 + (srcWidth
- 1) * bpt
;
3744 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3745 + (dstWidth
- 1) * bpt
;
3746 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3748 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3749 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3750 + (bytesPerSrcImage
- bpt
);
3751 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3752 + (bytesPerDstImage
- bpt
);
3753 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3761 * For GL_SGIX_generate_mipmap:
3762 * Generate a complete set of mipmaps from texObj's base-level image.
3763 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3766 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3767 const struct gl_texture_unit
*texUnit
,
3768 struct gl_texture_object
*texObj
)
3770 const struct gl_texture_image
*srcImage
;
3771 const struct gl_texture_format
*convertFormat
;
3772 const GLubyte
*srcData
= NULL
;
3773 GLubyte
*dstData
= NULL
;
3774 GLint level
, maxLevels
;
3777 /* XXX choose cube map face here??? */
3778 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3781 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3782 ASSERT(maxLevels
> 0); /* bad target */
3784 /* Find convertFormat - the format that do_row() will process */
3785 if (srcImage
->IsCompressed
) {
3786 /* setup for compressed textures */
3788 GLint components
, size
;
3791 assert(texObj
->Target
== GL_TEXTURE_2D
);
3793 if (srcImage
->_BaseFormat
== GL_RGB
) {
3794 convertFormat
= &_mesa_texformat_rgb
;
3797 else if (srcImage
->_BaseFormat
== GL_RGBA
) {
3798 convertFormat
= &_mesa_texformat_rgba
;
3802 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
3806 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3807 size
= _mesa_bytes_per_pixel(srcImage
->_BaseFormat
, CHAN_TYPE
)
3808 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3809 /* 20 extra bytes, just be safe when calling last FetchTexel */
3810 srcData
= (GLubyte
*) _mesa_malloc(size
);
3812 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3815 dstData
= (GLubyte
*) _mesa_malloc(size
/ 2); /* 1/4 would probably be OK */
3817 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3818 _mesa_free((void *) srcData
);
3822 /* decompress base image here */
3823 dst
= (GLchan
*) srcData
;
3824 for (row
= 0; row
< srcImage
->Height
; row
++) {
3826 for (col
= 0; col
< srcImage
->Width
; col
++) {
3827 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3834 convertFormat
= srcImage
->TexFormat
;
3837 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3838 && level
< maxLevels
- 1; level
++) {
3839 /* generate image[level+1] from image[level] */
3840 const struct gl_texture_image
*srcImage
;
3841 struct gl_texture_image
*dstImage
;
3842 GLint srcWidth
, srcHeight
, srcDepth
;
3843 GLint dstWidth
, dstHeight
, dstDepth
;
3844 GLint border
, bytesPerTexel
;
3846 /* get src image parameters */
3847 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3849 srcWidth
= srcImage
->Width
;
3850 srcHeight
= srcImage
->Height
;
3851 srcDepth
= srcImage
->Depth
;
3852 border
= srcImage
->Border
;
3854 /* compute next (level+1) image size */
3855 if (srcWidth
- 2 * border
> 1) {
3856 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3859 dstWidth
= srcWidth
; /* can't go smaller */
3861 if (srcHeight
- 2 * border
> 1) {
3862 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3865 dstHeight
= srcHeight
; /* can't go smaller */
3867 if (srcDepth
- 2 * border
> 1) {
3868 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3871 dstDepth
= srcDepth
; /* can't go smaller */
3874 if (dstWidth
== srcWidth
&&
3875 dstHeight
== srcHeight
&&
3876 dstDepth
== srcDepth
) {
3878 if (srcImage
->IsCompressed
) {
3879 _mesa_free((void *) srcData
);
3880 _mesa_free(dstData
);
3885 /* get dest gl_texture_image */
3886 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3888 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3892 /* Free old image data */
3894 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
3896 /* initialize new image */
3897 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3898 dstDepth
, border
, srcImage
->InternalFormat
);
3899 dstImage
->DriverData
= NULL
;
3900 dstImage
->TexFormat
= srcImage
->TexFormat
;
3901 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3902 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3903 dstImage
->IsCompressed
= srcImage
->IsCompressed
;
3904 if (dstImage
->IsCompressed
) {
3905 dstImage
->CompressedSize
3906 = ctx
->Driver
.CompressedTextureSize(ctx
, dstImage
->Width
,
3909 dstImage
->TexFormat
->MesaFormat
);
3910 ASSERT(dstImage
->CompressedSize
> 0);
3913 ASSERT(dstImage
->TexFormat
);
3914 ASSERT(dstImage
->FetchTexelc
);
3915 ASSERT(dstImage
->FetchTexelf
);
3917 /* Alloc new teximage data buffer.
3918 * Setup src and dest data pointers.
3920 if (dstImage
->IsCompressed
) {
3921 dstImage
->Data
= _mesa_alloc_texmemory(dstImage
->CompressedSize
);
3922 if (!dstImage
->Data
) {
3923 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3926 /* srcData and dstData are already set */
3931 bytesPerTexel
= dstImage
->TexFormat
->TexelBytes
;
3932 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3933 dstImage
->Data
= _mesa_alloc_texmemory(dstWidth
* dstHeight
3934 * dstDepth
* bytesPerTexel
);
3935 if (!dstImage
->Data
) {
3936 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3939 srcData
= (const GLubyte
*) srcImage
->Data
;
3940 dstData
= (GLubyte
*) dstImage
->Data
;
3944 * We use simple 2x2 averaging to compute the next mipmap level.
3948 make_1d_mipmap(convertFormat
, border
,
3953 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3954 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3955 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3956 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3957 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3958 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3959 make_2d_mipmap(convertFormat
, border
,
3960 srcWidth
, srcHeight
, srcData
,
3961 dstWidth
, dstHeight
, dstData
);
3964 make_3d_mipmap(convertFormat
, border
,
3965 srcWidth
, srcHeight
, srcDepth
, srcData
,
3966 dstWidth
, dstHeight
, dstDepth
, dstData
);
3968 case GL_TEXTURE_RECTANGLE_NV
:
3969 /* no mipmaps, do nothing */
3972 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3976 if (dstImage
->IsCompressed
) {
3978 /* compress image from dstData into dstImage->Data */
3979 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3981 = _mesa_compressed_row_stride(dstImage
->TexFormat
->MesaFormat
, dstWidth
);
3982 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3983 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->_BaseFormat
,
3984 dstImage
->TexFormat
,
3986 0, 0, 0, /* dstX/Y/Zoffset */
3987 dstRowStride
, 0, /* strides */
3988 dstWidth
, dstHeight
, 1, /* size */
3989 srcFormat
, CHAN_TYPE
,
3990 dstData
, /* src data, actually */
3991 &ctx
->DefaultPacking
);
3992 /* swap src and dest pointers */
3993 temp
= (GLubyte
*) srcData
;
3998 } /* loop over mipmap levels */
4003 * Helper function for drivers which need to rescale texture images to
4004 * certain aspect ratios.
4005 * Nearest filtering only (for broken hardware that can't support
4006 * all aspect ratios). This can be made a lot faster, but I don't
4007 * really care enough...
4010 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
4011 GLuint srcStrideInPixels
,
4012 GLuint dstRowStride
,
4013 GLint srcWidth
, GLint srcHeight
,
4014 GLint dstWidth
, GLint dstHeight
,
4015 const GLvoid
*srcImage
, GLvoid
*dstImage
)
4019 #define INNER_LOOP( TYPE, HOP, WOP ) \
4020 for ( row = 0 ; row < dstHeight ; row++ ) { \
4021 GLint srcRow = row HOP hScale; \
4022 for ( col = 0 ; col < dstWidth ; col++ ) { \
4023 GLint srcCol = col WOP wScale; \
4024 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
4026 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
4029 #define RESCALE_IMAGE( TYPE ) \
4031 const TYPE *src = (const TYPE *)srcImage; \
4032 TYPE *dst = (TYPE *)dstImage; \
4034 if ( srcHeight < dstHeight ) { \
4035 const GLint hScale = dstHeight / srcHeight; \
4036 if ( srcWidth < dstWidth ) { \
4037 const GLint wScale = dstWidth / srcWidth; \
4038 INNER_LOOP( TYPE, /, / ); \
4041 const GLint wScale = srcWidth / dstWidth; \
4042 INNER_LOOP( TYPE, /, * ); \
4046 const GLint hScale = srcHeight / dstHeight; \
4047 if ( srcWidth < dstWidth ) { \
4048 const GLint wScale = dstWidth / srcWidth; \
4049 INNER_LOOP( TYPE, *, / ); \
4052 const GLint wScale = srcWidth / dstWidth; \
4053 INNER_LOOP( TYPE, *, * ); \
4058 switch ( bytesPerPixel
) {
4060 RESCALE_IMAGE( GLuint
);
4064 RESCALE_IMAGE( GLushort
);
4068 RESCALE_IMAGE( GLubyte
);
4071 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
4077 * Upscale an image by replication, not (typical) stretching.
4078 * We use this when the image width or height is less than a
4079 * certain size (4, 8) and we need to upscale an image.
4082 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
4083 GLsizei outWidth
, GLsizei outHeight
,
4084 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
4089 ASSERT(outWidth
>= inWidth
);
4090 ASSERT(outHeight
>= inHeight
);
4092 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
4093 ASSERT((outWidth
& 3) == 0);
4094 ASSERT((outHeight
& 3) == 0);
4097 for (i
= 0; i
< outHeight
; i
++) {
4098 const GLint ii
= i
% inHeight
;
4099 for (j
= 0; j
< outWidth
; j
++) {
4100 const GLint jj
= j
% inWidth
;
4101 for (k
= 0; k
< comps
; k
++) {
4102 dest
[(i
* outWidth
+ j
) * comps
+ k
]
4103 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
4112 * This is the software fallback for Driver.GetTexImage().
4113 * All error checking will have been done before this routine is called.
4116 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4117 GLenum format
, GLenum type
, GLvoid
*pixels
,
4118 struct gl_texture_object
*texObj
,
4119 struct gl_texture_image
*texImage
)
4121 GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
4123 if (ctx
->Pack
.BufferObj
->Name
) {
4124 /* pack texture image into a PBO */
4126 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
4127 texImage
->Height
, texImage
->Depth
,
4128 format
, type
, pixels
)) {
4129 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4130 "glGetTexImage(invalid PBO access)");
4133 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4135 ctx
->Pack
.BufferObj
);
4137 /* buffer is already mapped - that's an error */
4138 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
4141 pixels
= ADD_POINTERS(buf
, pixels
);
4149 const GLint width
= texImage
->Width
;
4150 const GLint height
= texImage
->Height
;
4151 const GLint depth
= texImage
->Depth
;
4153 for (img
= 0; img
< depth
; img
++) {
4154 for (row
= 0; row
< height
; row
++) {
4155 /* compute destination address in client memory */
4156 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
4157 width
, height
, format
, type
,
4161 if (format
== GL_COLOR_INDEX
) {
4162 GLuint indexRow
[MAX_WIDTH
];
4164 /* Can't use FetchTexel here because that returns RGBA */
4165 if (texImage
->TexFormat
->IndexBits
== 8) {
4166 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
4167 src
+= width
* (img
* texImage
->Height
+ row
);
4168 for (col
= 0; col
< width
; col
++) {
4169 indexRow
[col
] = src
[col
];
4172 else if (texImage
->TexFormat
->IndexBits
== 16) {
4173 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
4174 src
+= width
* (img
* texImage
->Height
+ row
);
4175 for (col
= 0; col
< width
; col
++) {
4176 indexRow
[col
] = src
[col
];
4181 "Color index problem in _mesa_GetTexImage");
4183 _mesa_pack_index_span(ctx
, width
, type
, dest
,
4184 indexRow
, &ctx
->Pack
,
4185 0 /* no image transfer */);
4187 else if (format
== GL_DEPTH_COMPONENT
) {
4188 GLfloat depthRow
[MAX_WIDTH
];
4190 for (col
= 0; col
< width
; col
++) {
4191 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
4194 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
4195 depthRow
, &ctx
->Pack
);
4197 else if (format
== GL_DEPTH_STENCIL_EXT
) {
4198 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4199 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
4200 src
+= width
* row
+ width
* height
* img
;
4201 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
4202 if (ctx
->Pack
.SwapBytes
) {
4203 _mesa_swap4((GLuint
*) dest
, width
);
4206 else if (format
== GL_YCBCR_MESA
) {
4207 /* No pixel transfer */
4208 const GLint rowstride
= texImage
->RowStride
;
4210 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
4211 width
* sizeof(GLushort
));
4212 /* check for byte swapping */
4213 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
4214 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
4215 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
4216 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
4217 if (!ctx
->Pack
.SwapBytes
)
4218 _mesa_swap2((GLushort
*) dest
, width
);
4220 else if (ctx
->Pack
.SwapBytes
) {
4221 _mesa_swap2((GLushort
*) dest
, width
);
4225 /* general case: convert row to RGBA format */
4226 GLfloat rgba
[MAX_WIDTH
][4];
4228 for (col
= 0; col
< width
; col
++) {
4229 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
4231 _mesa_pack_rgba_span_float(ctx
, width
,
4232 (const GLfloat (*)[4]) rgba
,
4233 format
, type
, dest
, &ctx
->Pack
,
4234 0 /* no image transfer */);
4240 if (ctx
->Pack
.BufferObj
->Name
) {
4241 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4242 ctx
->Pack
.BufferObj
);
4249 * This is the software fallback for Driver.GetCompressedTexImage().
4250 * All error checking will have been done before this routine is called.
4253 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4255 const struct gl_texture_object
*texObj
,
4256 const struct gl_texture_image
*texImage
)
4258 if (ctx
->Pack
.BufferObj
->Name
) {
4259 /* pack texture image into a PBO */
4261 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4262 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4263 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4264 "glGetCompressedTexImage(invalid PBO access)");
4267 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4269 ctx
->Pack
.BufferObj
);
4271 /* buffer is already mapped - that's an error */
4272 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4273 "glGetCompressedTexImage(PBO is mapped)");
4276 img
= ADD_POINTERS(buf
, img
);
4283 /* just memcpy, no pixelstore or pixel transfer */
4284 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);
4286 if (ctx
->Pack
.BufferObj
->Name
) {
4287 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4288 ctx
->Pack
.BufferObj
);