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
;
640 compute_component_mapping(srcFormat
, GL_RGBA
, srcmap
);
642 for (i
= 0; i
< 4; i
++)
643 map
[i
] = srcmap
[dstmap
[i
]];
645 if (srcRowStride
== srcWidth
* srcComponents
&&
646 (srcImageStride
== srcWidth
* srcHeight
* srcComponents
||
648 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
649 srcWidth
* srcHeight
* srcDepth
);
653 for (img
= 0; img
< srcDepth
; img
++) {
654 const GLubyte
*srcRow
= srcImage
;
655 GLubyte
*dstRow
= dstImage
;
656 for (row
= 0; row
< srcHeight
; row
++) {
657 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
658 dstRow
+= dstRowStride
;
659 srcRow
+= srcRowStride
;
661 srcImage
+= srcImageStride
;
662 dstImage
+= dstImageStride
;
669 * Teximage storage routine for when a simple memcpy will do.
670 * No pixel transfer operations or special texel encodings allowed.
671 * 1D, 2D and 3D images supported.
674 memcpy_texture(GLcontext
*ctx
,
676 const struct gl_texture_format
*dstFormat
,
678 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
679 GLint dstRowStride
, GLint dstImageStride
,
680 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
681 GLenum srcFormat
, GLenum srcType
,
682 const GLvoid
*srcAddr
,
683 const struct gl_pixelstore_attrib
*srcPacking
)
685 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
687 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
688 srcWidth
, srcHeight
, srcFormat
, srcType
);
689 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
690 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
691 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
692 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
693 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
694 GLubyte
*dstImage
= (GLubyte
*) dstAddr
695 + dstZoffset
* dstImageStride
696 + dstYoffset
* dstRowStride
697 + dstXoffset
* dstFormat
->TexelBytes
;
699 if (dstRowStride
== srcRowStride
&&
700 dstRowStride
== bytesPerRow
&&
701 ((dstImageStride
== srcImageStride
&&
702 dstImageStride
== bytesPerImage
) ||
705 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
709 for (img
= 0; img
< srcDepth
; img
++) {
710 const GLubyte
*srcRow
= srcImage
;
711 GLubyte
*dstRow
= dstImage
;
712 for (row
= 0; row
< srcHeight
; row
++) {
713 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
714 dstRow
+= dstRowStride
;
715 srcRow
+= srcRowStride
;
717 srcImage
+= srcImageStride
;
718 dstImage
+= dstImageStride
;
726 * Store an image in any of the formats:
727 * _mesa_texformat_rgba
728 * _mesa_texformat_rgb
729 * _mesa_texformat_alpha
730 * _mesa_texformat_luminance
731 * _mesa_texformat_luminance_alpha
732 * _mesa_texformat_intensity
734 * \param dims either 1 or 2 or 3
735 * \param baseInternalFormat user-specified base internal format
736 * \param dstFormat destination Mesa texture format
737 * \param dstAddr destination image address
738 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
739 * \param dstRowStride destination image row stride, in bytes
740 * \param dstImageStride destination image layer stride, in bytes
741 * \param srcWidth/Height/Depth source image size, in pixels
742 * \param srcFormat incoming image format
743 * \param srcType incoming image data type
744 * \param srcAddr source image address
745 * \param srcPacking source image packing parameters
748 _mesa_texstore_rgba(GLcontext
*ctx
, GLuint dims
,
749 GLenum baseInternalFormat
,
750 const struct gl_texture_format
*dstFormat
,
752 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
753 GLint dstRowStride
, GLint dstImageStride
,
754 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
755 GLenum srcFormat
, GLenum srcType
,
756 const GLvoid
*srcAddr
,
757 const struct gl_pixelstore_attrib
*srcPacking
)
759 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
761 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
762 dstFormat
== &_mesa_texformat_rgb
||
763 dstFormat
== &_mesa_texformat_alpha
||
764 dstFormat
== &_mesa_texformat_luminance
||
765 dstFormat
== &_mesa_texformat_luminance_alpha
||
766 dstFormat
== &_mesa_texformat_intensity
);
767 ASSERT(baseInternalFormat
== GL_RGBA
||
768 baseInternalFormat
== GL_RGB
||
769 baseInternalFormat
== GL_ALPHA
||
770 baseInternalFormat
== GL_LUMINANCE
||
771 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
772 baseInternalFormat
== GL_INTENSITY
);
773 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
775 if (!ctx
->_ImageTransferState
&&
776 !srcPacking
->SwapBytes
&&
777 baseInternalFormat
== srcFormat
&&
778 srcType
== CHAN_TYPE
) {
779 /* simple memcpy path */
780 memcpy_texture(ctx
, dims
,
781 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
782 dstRowStride
, dstImageStride
,
783 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
784 srcAddr
, srcPacking
);
786 else if (!ctx
->_ImageTransferState
&&
787 !srcPacking
->SwapBytes
&&
788 dstFormat
== &_mesa_texformat_rgb
&&
789 srcFormat
== GL_RGBA
&&
790 srcType
== CHAN_TYPE
) {
791 /* extract RGB from RGBA */
793 GLchan
*dstImage
= (GLchan
*) (GLubyte
*) dstAddr
794 + dstZoffset
* dstImageStride
795 + dstYoffset
* dstRowStride
796 + dstXoffset
* dstFormat
->TexelBytes
;
797 for (img
= 0; img
< srcDepth
; img
++) {
798 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
799 srcWidth
, srcFormat
, srcType
);
800 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
801 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
802 GLchan
*dstRow
= dstImage
;
803 for (row
= 0; row
< srcHeight
; row
++) {
804 for (col
= 0; col
< srcWidth
; col
++) {
805 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
806 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
807 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
809 dstRow
+= dstRowStride
;
810 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
812 dstImage
+= dstImageStride
;
817 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
819 dstFormat
->BaseFormat
,
820 srcWidth
, srcHeight
, srcDepth
,
821 srcFormat
, srcType
, srcAddr
,
823 const GLchan
*src
= tempImage
;
825 GLubyte
*dstImage
= (GLubyte
*) dstAddr
826 + dstZoffset
* dstImageStride
827 + dstYoffset
* dstRowStride
828 + dstXoffset
* dstFormat
->TexelBytes
;
832 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
833 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
834 for (img
= 0; img
< srcDepth
; img
++) {
835 GLubyte
*dstRow
= dstImage
;
836 for (row
= 0; row
< srcHeight
; row
++) {
837 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
838 dstRow
+= dstRowStride
;
839 src
+= srcWidth
* components
;
841 dstImage
+= dstImageStride
;
844 _mesa_free((void *) tempImage
);
851 * Store a floating point depth component texture image.
854 _mesa_texstore_depth_component_float32(STORE_PARAMS
)
857 ASSERT(dstFormat
== &_mesa_texformat_depth_component_float32
);
858 ASSERT(dstFormat
->TexelBytes
== sizeof(GLfloat
));
860 if (!ctx
->_ImageTransferState
&&
861 !srcPacking
->SwapBytes
&&
862 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
863 srcFormat
== GL_DEPTH_COMPONENT
&&
864 srcType
== GL_FLOAT
) {
865 /* simple memcpy path */
866 memcpy_texture(ctx
, dims
,
867 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
868 dstRowStride
, dstImageStride
,
869 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
870 srcAddr
, srcPacking
);
874 GLubyte
*dstImage
= (GLubyte
*) dstAddr
875 + dstZoffset
* dstImageStride
876 + dstYoffset
* dstRowStride
877 + dstXoffset
* dstFormat
->TexelBytes
;
879 for (img
= 0; img
< srcDepth
; img
++) {
880 GLubyte
*dstRow
= dstImage
;
881 for (row
= 0; row
< srcHeight
; row
++) {
882 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
883 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
884 _mesa_unpack_depth_span(ctx
, srcWidth
,
885 GL_FLOAT
, (GLfloat
*) dstRow
, 1.0F
,
886 srcType
, src
, srcPacking
);
887 dstRow
+= dstRowStride
;
889 dstImage
+= dstImageStride
;
897 * Store a 16-bit integer depth component texture image.
900 _mesa_texstore_depth_component16(STORE_PARAMS
)
903 ASSERT(dstFormat
== &_mesa_texformat_depth_component16
);
904 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
906 if (!ctx
->_ImageTransferState
&&
907 !srcPacking
->SwapBytes
&&
908 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
909 srcFormat
== GL_DEPTH_COMPONENT
&&
910 srcType
== GL_UNSIGNED_SHORT
) {
911 /* simple memcpy path */
912 memcpy_texture(ctx
, dims
,
913 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
914 dstRowStride
, dstImageStride
,
915 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
916 srcAddr
, srcPacking
);
920 GLubyte
*dstImage
= (GLubyte
*) dstAddr
921 + dstZoffset
* dstImageStride
922 + dstYoffset
* dstRowStride
923 + dstXoffset
* dstFormat
->TexelBytes
;
925 for (img
= 0; img
< srcDepth
; img
++) {
926 GLubyte
*dstRow
= dstImage
;
927 for (row
= 0; row
< srcHeight
; row
++) {
928 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
929 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
930 GLushort
*dst16
= (GLushort
*) dstRow
;
931 _mesa_unpack_depth_span(ctx
, srcWidth
,
932 GL_UNSIGNED_SHORT
, dst16
, 65535.0F
,
933 srcType
, src
, srcPacking
);
934 dstRow
+= dstRowStride
;
936 dstImage
+= dstImageStride
;
944 * Store an rgb565 or rgb565_rev texture image.
947 _mesa_texstore_rgb565(STORE_PARAMS
)
949 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
950 dstFormat
== &_mesa_texformat_rgb565_rev
);
951 ASSERT(dstFormat
->TexelBytes
== 2);
953 if (!ctx
->_ImageTransferState
&&
954 !srcPacking
->SwapBytes
&&
955 dstFormat
== &_mesa_texformat_rgb565
&&
956 baseInternalFormat
== GL_RGB
&&
957 srcFormat
== GL_RGB
&&
958 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
959 /* simple memcpy path */
960 memcpy_texture(ctx
, dims
,
961 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
962 dstRowStride
, dstImageStride
,
963 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
964 srcAddr
, srcPacking
);
966 else if (!ctx
->_ImageTransferState
&&
967 !srcPacking
->SwapBytes
&&
968 baseInternalFormat
== GL_RGB
&&
969 srcFormat
== GL_RGB
&&
970 srcType
== GL_UNSIGNED_BYTE
&&
972 /* do optimized tex store */
973 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
975 const GLubyte
*src
= (const GLubyte
*)
976 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
977 srcFormat
, srcType
, 0, 0, 0);
978 GLubyte
*dst
= (GLubyte
*) dstAddr
979 + dstZoffset
* dstImageStride
980 + dstYoffset
* dstRowStride
981 + dstXoffset
* dstFormat
->TexelBytes
;
983 for (row
= 0; row
< srcHeight
; row
++) {
984 const GLubyte
*srcUB
= (const GLubyte
*) src
;
985 GLushort
*dstUS
= (GLushort
*) dst
;
986 /* check for byteswapped format */
987 if (dstFormat
== &_mesa_texformat_rgb565
) {
988 for (col
= 0; col
< srcWidth
; col
++) {
989 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
994 for (col
= 0; col
< srcWidth
; col
++) {
995 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1000 src
+= srcRowStride
;
1005 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1007 dstFormat
->BaseFormat
,
1008 srcWidth
, srcHeight
, srcDepth
,
1009 srcFormat
, srcType
, srcAddr
,
1011 const GLchan
*src
= tempImage
;
1012 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1013 + dstZoffset
* dstImageStride
1014 + dstYoffset
* dstRowStride
1015 + dstXoffset
* dstFormat
->TexelBytes
;
1016 GLint img
, row
, col
;
1019 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1020 for (img
= 0; img
< srcDepth
; img
++) {
1021 GLubyte
*dstRow
= dstImage
;
1022 for (row
= 0; row
< srcHeight
; row
++) {
1023 GLushort
*dstUS
= (GLushort
*) dstRow
;
1024 /* check for byteswapped format */
1025 if (dstFormat
== &_mesa_texformat_rgb565
) {
1026 for (col
= 0; col
< srcWidth
; col
++) {
1027 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1028 CHAN_TO_UBYTE(src
[GCOMP
]),
1029 CHAN_TO_UBYTE(src
[BCOMP
]) );
1034 for (col
= 0; col
< srcWidth
; col
++) {
1035 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1036 CHAN_TO_UBYTE(src
[GCOMP
]),
1037 CHAN_TO_UBYTE(src
[BCOMP
]) );
1041 dstRow
+= dstRowStride
;
1043 dstImage
+= dstImageStride
;
1045 _mesa_free((void *) tempImage
);
1052 _mesa_texstore_rgba8888(STORE_PARAMS
)
1054 const GLuint ui
= 1;
1055 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1058 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1059 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1060 ASSERT(dstFormat
->TexelBytes
== 4);
1062 if (!ctx
->_ImageTransferState
&&
1063 !srcPacking
->SwapBytes
&&
1064 dstFormat
== &_mesa_texformat_rgba8888
&&
1065 baseInternalFormat
== GL_RGBA
&&
1066 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1067 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
1068 /* simple memcpy path */
1069 memcpy_texture(ctx
, dims
,
1070 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1071 dstRowStride
, dstImageStride
,
1072 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1073 srcAddr
, srcPacking
);
1076 else if (!ctx
->_ImageTransferState
&&
1077 !srcPacking
->SwapBytes
&&
1078 srcType
== GL_UNSIGNED_BYTE
&&
1079 dstFormat
== &_mesa_texformat_rgba8888
&&
1081 /* Three texture formats involved: srcFormat,
1082 * baseInternalFormat and destFormat (GL_RGBA). Only two
1083 * may differ. _mesa_swizzle_ubyte_image can't handle two
1084 * propagations at once correctly. */
1085 (srcFormat
== baseInternalFormat
||
1086 baseInternalFormat
== GL_RGBA
) &&
1087 can_swizzle(srcFormat
)) {
1090 /* dstmap - how to swizzle from GL_RGBA to dst format:
1092 * FIXME - add !litteEndian and _rev varients:
1099 _mesa_swizzle_ubyte_image(ctx
, dims
,
1102 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1103 dstRowStride
, dstImageStride
,
1104 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1110 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1112 dstFormat
->BaseFormat
,
1113 srcWidth
, srcHeight
, srcDepth
,
1114 srcFormat
, srcType
, srcAddr
,
1116 const GLchan
*src
= tempImage
;
1117 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1118 + dstZoffset
* dstImageStride
1119 + dstYoffset
* dstRowStride
1120 + dstXoffset
* dstFormat
->TexelBytes
;
1121 GLint img
, row
, col
;
1124 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1125 for (img
= 0; img
< srcDepth
; img
++) {
1126 GLubyte
*dstRow
= dstImage
;
1127 for (row
= 0; row
< srcHeight
; row
++) {
1128 GLuint
*dstUI
= (GLuint
*) dstRow
;
1129 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1130 for (col
= 0; col
< srcWidth
; col
++) {
1131 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1132 CHAN_TO_UBYTE(src
[GCOMP
]),
1133 CHAN_TO_UBYTE(src
[BCOMP
]),
1134 CHAN_TO_UBYTE(src
[ACOMP
]) );
1139 for (col
= 0; col
< srcWidth
; col
++) {
1140 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1141 CHAN_TO_UBYTE(src
[GCOMP
]),
1142 CHAN_TO_UBYTE(src
[BCOMP
]),
1143 CHAN_TO_UBYTE(src
[ACOMP
]) );
1147 dstRow
+= dstRowStride
;
1149 dstImage
+= dstImageStride
;
1151 _mesa_free((void *) tempImage
);
1158 _mesa_texstore_argb8888(STORE_PARAMS
)
1160 const GLuint ui
= 1;
1161 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1163 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1164 dstFormat
== &_mesa_texformat_argb8888_rev
);
1165 ASSERT(dstFormat
->TexelBytes
== 4);
1167 if (!ctx
->_ImageTransferState
&&
1168 !srcPacking
->SwapBytes
&&
1169 dstFormat
== &_mesa_texformat_argb8888
&&
1170 baseInternalFormat
== GL_RGBA
&&
1171 srcFormat
== GL_BGRA
&&
1172 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1173 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1174 /* simple memcpy path (little endian) */
1175 memcpy_texture(ctx
, dims
,
1176 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1177 dstRowStride
, dstImageStride
,
1178 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1179 srcAddr
, srcPacking
);
1181 else if (!ctx
->_ImageTransferState
&&
1182 !srcPacking
->SwapBytes
&&
1183 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1184 baseInternalFormat
== GL_RGBA
&&
1185 srcFormat
== GL_BGRA
&&
1186 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1187 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1188 /* simple memcpy path (big endian) */
1189 memcpy_texture(ctx
, dims
,
1190 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1191 dstRowStride
, dstImageStride
,
1192 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1193 srcAddr
, srcPacking
);
1195 else if (!ctx
->_ImageTransferState
&&
1196 !srcPacking
->SwapBytes
&&
1197 dstFormat
== &_mesa_texformat_argb8888
&&
1198 srcFormat
== GL_RGB
&&
1199 srcType
== GL_UNSIGNED_BYTE
) {
1202 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1203 + dstZoffset
* dstImageStride
1204 + dstYoffset
* dstRowStride
1205 + dstXoffset
* dstFormat
->TexelBytes
;
1206 for (img
= 0; img
< srcDepth
; img
++) {
1207 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1208 srcWidth
, srcFormat
, srcType
);
1209 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1210 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1211 GLubyte
*dstRow
= dstImage
;
1212 for (row
= 0; row
< srcHeight
; row
++) {
1213 for (col
= 0; col
< srcWidth
; col
++) {
1214 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1215 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1216 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1217 dstRow
[col
* 4 + 3] = 0xff;
1219 dstRow
+= dstRowStride
;
1220 srcRow
+= srcRowStride
;
1222 dstImage
+= dstImageStride
;
1225 else if (!ctx
->_ImageTransferState
&&
1226 !srcPacking
->SwapBytes
&&
1227 dstFormat
== &_mesa_texformat_argb8888
&&
1228 srcFormat
== GL_RGBA
&&
1229 (srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
1232 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1233 + dstZoffset
* dstImageStride
1234 + dstYoffset
* dstRowStride
1235 + dstXoffset
* dstFormat
->TexelBytes
;
1237 /* For some reason, streaming copies to write-combined regions
1238 * are extremely sensitive to the characteristics of how the
1239 * source data is retrieved. By reordering the source reads to
1240 * be in-order, the speed of this operation increases by half.
1241 * Strangely the same isn't required for the RGB path, above.
1243 for (img
= 0; img
< srcDepth
; img
++) {
1244 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1245 srcWidth
, srcFormat
, srcType
);
1246 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1247 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1248 GLubyte
*dstRow
= dstImage
;
1249 for (row
= 0; row
< srcHeight
; row
++) {
1250 for (col
= 0; col
< srcWidth
; col
++) {
1251 *(GLuint
*)(dstRow
+ col
* 4) = (srcRow
[col
* 4 + RCOMP
] << 16 |
1252 srcRow
[col
* 4 + GCOMP
] << 8 |
1253 srcRow
[col
* 4 + BCOMP
] << 0 |
1254 srcRow
[col
* 4 + ACOMP
] << 24);
1256 dstRow
+= dstRowStride
;
1257 srcRow
+= srcRowStride
;
1259 dstImage
+= dstImageStride
;
1262 else if (!ctx
->_ImageTransferState
&&
1263 !srcPacking
->SwapBytes
&&
1264 dstFormat
== &_mesa_texformat_argb8888
&&
1265 srcFormat
== GL_RGBA
&&
1266 srcType
== GL_UNSIGNED_BYTE
) {
1269 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1270 + dstZoffset
* dstImageStride
1271 + dstYoffset
* dstRowStride
1272 + dstXoffset
* dstFormat
->TexelBytes
;
1273 for (img
= 0; img
< srcDepth
; img
++) {
1274 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1275 srcWidth
, srcFormat
, srcType
);
1276 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1277 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1278 GLubyte
*dstRow
= dstImage
;
1279 for (row
= 0; row
< srcHeight
; row
++) {
1280 for (col
= 0; col
< srcWidth
; col
++) {
1281 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1282 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1283 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1284 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1286 dstRow
+= dstRowStride
;
1287 srcRow
+= srcRowStride
;
1289 dstImage
+= dstImageStride
;
1292 else if (!ctx
->_ImageTransferState
&&
1293 !srcPacking
->SwapBytes
&&
1294 dstFormat
== &_mesa_texformat_argb8888
&&
1295 srcType
== GL_UNSIGNED_BYTE
&&
1297 /* Three texture formats involved: srcFormat,
1298 * baseInternalFormat and destFormat (GL_RGBA). Only two
1299 * may differ. _mesa_swizzle_ubyte_image can't handle two
1300 * propagations at once correctly. */
1301 (srcFormat
== baseInternalFormat
||
1302 baseInternalFormat
== GL_RGBA
) &&
1303 can_swizzle(srcFormat
)) {
1307 /* dstmap - how to swizzle from GL_RGBA to dst format:
1309 dstmap
[3] = 3; /* alpha */
1310 dstmap
[2] = 0; /* red */
1311 dstmap
[1] = 1; /* green */
1312 dstmap
[0] = 2; /* blue */
1314 _mesa_swizzle_ubyte_image(ctx
, dims
,
1317 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1318 dstRowStride
, dstImageStride
,
1319 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1324 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1326 dstFormat
->BaseFormat
,
1327 srcWidth
, srcHeight
, srcDepth
,
1328 srcFormat
, srcType
, srcAddr
,
1330 const GLchan
*src
= tempImage
;
1331 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1332 + dstZoffset
* dstImageStride
1333 + dstYoffset
* dstRowStride
1334 + dstXoffset
* dstFormat
->TexelBytes
;
1335 GLint img
, row
, col
;
1338 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1339 for (img
= 0; img
< srcDepth
; img
++) {
1340 GLubyte
*dstRow
= dstImage
;
1341 for (row
= 0; row
< srcHeight
; row
++) {
1342 GLuint
*dstUI
= (GLuint
*) dstRow
;
1343 if (dstFormat
== &_mesa_texformat_argb8888
) {
1344 for (col
= 0; col
< srcWidth
; col
++) {
1345 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1346 CHAN_TO_UBYTE(src
[RCOMP
]),
1347 CHAN_TO_UBYTE(src
[GCOMP
]),
1348 CHAN_TO_UBYTE(src
[BCOMP
]) );
1353 for (col
= 0; col
< srcWidth
; col
++) {
1354 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1355 CHAN_TO_UBYTE(src
[RCOMP
]),
1356 CHAN_TO_UBYTE(src
[GCOMP
]),
1357 CHAN_TO_UBYTE(src
[BCOMP
]) );
1361 dstRow
+= dstRowStride
;
1363 dstImage
+= dstImageStride
;
1365 _mesa_free((void *) tempImage
);
1372 _mesa_texstore_rgb888(STORE_PARAMS
)
1374 const GLuint ui
= 1;
1375 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1377 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1378 ASSERT(dstFormat
->TexelBytes
== 3);
1380 if (!ctx
->_ImageTransferState
&&
1381 !srcPacking
->SwapBytes
&&
1382 baseInternalFormat
== GL_RGB
&&
1383 srcFormat
== GL_BGR
&&
1384 srcType
== GL_UNSIGNED_BYTE
&&
1386 /* simple memcpy path */
1387 memcpy_texture(ctx
, dims
,
1388 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1389 dstRowStride
, dstImageStride
,
1390 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1391 srcAddr
, srcPacking
);
1393 else if (!ctx
->_ImageTransferState
&&
1394 !srcPacking
->SwapBytes
&&
1395 srcFormat
== GL_RGBA
&&
1396 srcType
== GL_UNSIGNED_BYTE
) {
1397 /* extract RGB from RGBA */
1399 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1400 + dstZoffset
* dstImageStride
1401 + dstYoffset
* dstRowStride
1402 + dstXoffset
* dstFormat
->TexelBytes
;
1403 for (img
= 0; img
< srcDepth
; img
++) {
1404 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1405 srcWidth
, srcFormat
, srcType
);
1406 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1407 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1408 GLubyte
*dstRow
= dstImage
;
1409 for (row
= 0; row
< srcHeight
; row
++) {
1410 for (col
= 0; col
< srcWidth
; col
++) {
1411 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1412 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1413 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1415 dstRow
+= dstRowStride
;
1416 srcRow
+= srcRowStride
;
1418 dstImage
+= dstImageStride
;
1423 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1425 dstFormat
->BaseFormat
,
1426 srcWidth
, srcHeight
, srcDepth
,
1427 srcFormat
, srcType
, srcAddr
,
1429 const GLchan
*src
= (const GLchan
*) tempImage
;
1430 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1431 + dstZoffset
* dstImageStride
1432 + dstYoffset
* dstRowStride
1433 + dstXoffset
* dstFormat
->TexelBytes
;
1434 GLint img
, row
, col
;
1437 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1438 for (img
= 0; img
< srcDepth
; img
++) {
1439 GLubyte
*dstRow
= dstImage
;
1440 for (row
= 0; row
< srcHeight
; row
++) {
1443 for (col
= 0; col
< srcWidth
; col
++) {
1444 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1445 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1446 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1451 for (col
= 0; col
< srcWidth
; col
++) {
1452 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1453 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1454 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1459 for (col
= 0; col
< srcWidth
; col
++) {
1460 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1461 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1462 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1466 dstRow
+= dstRowStride
;
1468 dstImage
+= dstImageStride
;
1470 _mesa_free((void *) tempImage
);
1477 _mesa_texstore_bgr888(STORE_PARAMS
)
1479 const GLuint ui
= 1;
1480 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1482 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1483 ASSERT(dstFormat
->TexelBytes
== 3);
1485 if (!ctx
->_ImageTransferState
&&
1486 !srcPacking
->SwapBytes
&&
1487 baseInternalFormat
== GL_RGB
&&
1488 srcFormat
== GL_RGB
&&
1489 srcType
== GL_UNSIGNED_BYTE
&&
1491 /* simple memcpy path */
1492 memcpy_texture(ctx
, dims
,
1493 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1494 dstRowStride
, dstImageStride
,
1495 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1496 srcAddr
, srcPacking
);
1498 else if (!ctx
->_ImageTransferState
&&
1499 !srcPacking
->SwapBytes
&&
1500 srcFormat
== GL_RGBA
&&
1501 srcType
== GL_UNSIGNED_BYTE
) {
1502 /* extract BGR from RGBA */
1504 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1505 + dstZoffset
* dstImageStride
1506 + dstYoffset
* dstRowStride
1507 + dstXoffset
* dstFormat
->TexelBytes
;
1508 for (img
= 0; img
< srcDepth
; img
++) {
1509 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1510 srcWidth
, srcFormat
, srcType
);
1511 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1512 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1513 GLubyte
*dstRow
= dstImage
;
1514 for (row
= 0; row
< srcHeight
; row
++) {
1515 for (col
= 0; col
< srcWidth
; col
++) {
1516 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1517 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1518 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1520 dstRow
+= dstRowStride
;
1521 srcRow
+= srcRowStride
;
1523 dstImage
+= dstImageStride
;
1528 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1530 dstFormat
->BaseFormat
,
1531 srcWidth
, srcHeight
, srcDepth
,
1532 srcFormat
, srcType
, srcAddr
,
1534 const GLchan
*src
= (const GLchan
*) tempImage
;
1535 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1536 + dstZoffset
* dstImageStride
1537 + dstYoffset
* dstRowStride
1538 + dstXoffset
* dstFormat
->TexelBytes
;
1539 GLint img
, row
, col
;
1542 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1543 for (img
= 0; img
< srcDepth
; img
++) {
1544 GLubyte
*dstRow
= dstImage
;
1545 for (row
= 0; row
< srcHeight
; row
++) {
1546 for (col
= 0; col
< srcWidth
; col
++) {
1547 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1548 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1549 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1552 dstRow
+= dstRowStride
;
1554 dstImage
+= dstImageStride
;
1556 _mesa_free((void *) tempImage
);
1563 _mesa_texstore_argb4444(STORE_PARAMS
)
1565 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1566 dstFormat
== &_mesa_texformat_argb4444_rev
);
1567 ASSERT(dstFormat
->TexelBytes
== 2);
1569 if (!ctx
->_ImageTransferState
&&
1570 !srcPacking
->SwapBytes
&&
1571 dstFormat
== &_mesa_texformat_argb4444
&&
1572 baseInternalFormat
== GL_RGBA
&&
1573 srcFormat
== GL_BGRA
&&
1574 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1575 /* simple memcpy path */
1576 memcpy_texture(ctx
, dims
,
1577 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1578 dstRowStride
, dstImageStride
,
1579 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1580 srcAddr
, srcPacking
);
1584 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1586 dstFormat
->BaseFormat
,
1587 srcWidth
, srcHeight
, srcDepth
,
1588 srcFormat
, srcType
, srcAddr
,
1590 const GLchan
*src
= tempImage
;
1591 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1592 + dstZoffset
* dstImageStride
1593 + dstYoffset
* dstRowStride
1594 + dstXoffset
* dstFormat
->TexelBytes
;
1595 GLint img
, row
, col
;
1598 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1599 for (img
= 0; img
< srcDepth
; img
++) {
1600 GLubyte
*dstRow
= dstImage
;
1601 for (row
= 0; row
< srcHeight
; row
++) {
1602 GLushort
*dstUS
= (GLushort
*) dstRow
;
1603 if (dstFormat
== &_mesa_texformat_argb4444
) {
1604 for (col
= 0; col
< srcWidth
; col
++) {
1605 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1606 CHAN_TO_UBYTE(src
[RCOMP
]),
1607 CHAN_TO_UBYTE(src
[GCOMP
]),
1608 CHAN_TO_UBYTE(src
[BCOMP
]) );
1613 for (col
= 0; col
< srcWidth
; col
++) {
1614 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1615 CHAN_TO_UBYTE(src
[RCOMP
]),
1616 CHAN_TO_UBYTE(src
[GCOMP
]),
1617 CHAN_TO_UBYTE(src
[BCOMP
]) );
1621 dstRow
+= dstRowStride
;
1623 dstImage
+= dstImageStride
;
1625 _mesa_free((void *) tempImage
);
1633 _mesa_texstore_argb1555(STORE_PARAMS
)
1635 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1636 dstFormat
== &_mesa_texformat_argb1555_rev
);
1637 ASSERT(dstFormat
->TexelBytes
== 2);
1639 if (!ctx
->_ImageTransferState
&&
1640 !srcPacking
->SwapBytes
&&
1641 dstFormat
== &_mesa_texformat_argb1555
&&
1642 baseInternalFormat
== GL_RGBA
&&
1643 srcFormat
== GL_BGRA
&&
1644 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1645 /* simple memcpy path */
1646 memcpy_texture(ctx
, dims
,
1647 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1648 dstRowStride
, dstImageStride
,
1649 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1650 srcAddr
, srcPacking
);
1654 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1656 dstFormat
->BaseFormat
,
1657 srcWidth
, srcHeight
, srcDepth
,
1658 srcFormat
, srcType
, srcAddr
,
1660 const GLchan
*src
=tempImage
;
1661 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1662 + dstZoffset
* dstImageStride
1663 + dstYoffset
* dstRowStride
1664 + dstXoffset
* dstFormat
->TexelBytes
;
1665 GLint img
, row
, col
;
1668 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1669 for (img
= 0; img
< srcDepth
; img
++) {
1670 GLubyte
*dstRow
= dstImage
;
1671 for (row
= 0; row
< srcHeight
; row
++) {
1672 GLushort
*dstUS
= (GLushort
*) dstRow
;
1673 if (dstFormat
== &_mesa_texformat_argb1555
) {
1674 for (col
= 0; col
< srcWidth
; col
++) {
1675 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1676 CHAN_TO_UBYTE(src
[RCOMP
]),
1677 CHAN_TO_UBYTE(src
[GCOMP
]),
1678 CHAN_TO_UBYTE(src
[BCOMP
]) );
1683 for (col
= 0; col
< srcWidth
; col
++) {
1684 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1685 CHAN_TO_UBYTE(src
[RCOMP
]),
1686 CHAN_TO_UBYTE(src
[GCOMP
]),
1687 CHAN_TO_UBYTE(src
[BCOMP
]) );
1691 dstRow
+= dstRowStride
;
1693 dstImage
+= dstImageStride
;
1695 _mesa_free((void *) tempImage
);
1702 _mesa_texstore_al88(STORE_PARAMS
)
1704 const GLuint ui
= 1;
1705 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1707 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1708 dstFormat
== &_mesa_texformat_al88_rev
);
1709 ASSERT(dstFormat
->TexelBytes
== 2);
1711 if (!ctx
->_ImageTransferState
&&
1712 !srcPacking
->SwapBytes
&&
1713 dstFormat
== &_mesa_texformat_al88
&&
1714 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1715 srcFormat
== GL_LUMINANCE_ALPHA
&&
1716 srcType
== GL_UNSIGNED_BYTE
&&
1718 /* simple memcpy path */
1719 memcpy_texture(ctx
, dims
,
1720 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1721 dstRowStride
, dstImageStride
,
1722 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1723 srcAddr
, srcPacking
);
1727 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1729 dstFormat
->BaseFormat
,
1730 srcWidth
, srcHeight
, srcDepth
,
1731 srcFormat
, srcType
, srcAddr
,
1733 const GLchan
*src
= tempImage
;
1734 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1735 + dstZoffset
* dstImageStride
1736 + dstYoffset
* dstRowStride
1737 + dstXoffset
* dstFormat
->TexelBytes
;
1738 GLint img
, row
, col
;
1741 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1742 for (img
= 0; img
< srcDepth
; img
++) {
1743 GLubyte
*dstRow
= dstImage
;
1744 for (row
= 0; row
< srcHeight
; row
++) {
1745 GLushort
*dstUS
= (GLushort
*) dstRow
;
1746 if (dstFormat
== &_mesa_texformat_al88
) {
1747 for (col
= 0; col
< srcWidth
; col
++) {
1748 /* src[0] is luminance, src[1] is alpha */
1749 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1750 CHAN_TO_UBYTE(src
[0]) );
1755 for (col
= 0; col
< srcWidth
; col
++) {
1756 /* src[0] is luminance, src[1] is alpha */
1757 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1758 CHAN_TO_UBYTE(src
[0]) );
1762 dstRow
+= dstRowStride
;
1764 dstImage
+= dstImageStride
;
1766 _mesa_free((void *) tempImage
);
1773 _mesa_texstore_rgb332(STORE_PARAMS
)
1775 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1776 ASSERT(dstFormat
->TexelBytes
== 1);
1778 if (!ctx
->_ImageTransferState
&&
1779 !srcPacking
->SwapBytes
&&
1780 baseInternalFormat
== GL_RGB
&&
1781 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1782 /* simple memcpy path */
1783 memcpy_texture(ctx
, dims
,
1784 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1785 dstRowStride
, dstImageStride
,
1786 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1787 srcAddr
, srcPacking
);
1791 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1793 dstFormat
->BaseFormat
,
1794 srcWidth
, srcHeight
, srcDepth
,
1795 srcFormat
, srcType
, srcAddr
,
1797 const GLchan
*src
= tempImage
;
1798 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1799 + dstZoffset
* dstImageStride
1800 + dstYoffset
* dstRowStride
1801 + dstXoffset
* dstFormat
->TexelBytes
;
1802 GLint img
, row
, col
;
1805 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1806 for (img
= 0; img
< srcDepth
; img
++) {
1807 GLubyte
*dstRow
= dstImage
;
1808 for (row
= 0; row
< srcHeight
; row
++) {
1809 for (col
= 0; col
< srcWidth
; col
++) {
1810 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1811 CHAN_TO_UBYTE(src
[GCOMP
]),
1812 CHAN_TO_UBYTE(src
[BCOMP
]) );
1815 dstRow
+= dstRowStride
;
1817 dstImage
+= dstImageStride
;
1819 _mesa_free((void *) tempImage
);
1826 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1829 _mesa_texstore_a8(STORE_PARAMS
)
1831 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1832 dstFormat
== &_mesa_texformat_l8
||
1833 dstFormat
== &_mesa_texformat_i8
);
1834 ASSERT(dstFormat
->TexelBytes
== 1);
1836 if (!ctx
->_ImageTransferState
&&
1837 !srcPacking
->SwapBytes
&&
1838 baseInternalFormat
== srcFormat
&&
1839 srcType
== GL_UNSIGNED_BYTE
) {
1840 /* simple memcpy path */
1841 memcpy_texture(ctx
, dims
,
1842 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1843 dstRowStride
, dstImageStride
,
1844 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1845 srcAddr
, srcPacking
);
1849 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1851 dstFormat
->BaseFormat
,
1852 srcWidth
, srcHeight
, srcDepth
,
1853 srcFormat
, srcType
, srcAddr
,
1855 const GLchan
*src
= tempImage
;
1856 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1857 + dstZoffset
* dstImageStride
1858 + dstYoffset
* dstRowStride
1859 + dstXoffset
* dstFormat
->TexelBytes
;
1860 GLint img
, row
, col
;
1863 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1864 for (img
= 0; img
< srcDepth
; img
++) {
1865 GLubyte
*dstRow
= dstImage
;
1866 for (row
= 0; row
< srcHeight
; row
++) {
1867 for (col
= 0; col
< srcWidth
; col
++) {
1868 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1870 dstRow
+= dstRowStride
;
1873 dstImage
+= dstImageStride
;
1875 _mesa_free((void *) tempImage
);
1883 _mesa_texstore_ci8(STORE_PARAMS
)
1885 (void) dims
; (void) baseInternalFormat
;
1886 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1887 ASSERT(dstFormat
->TexelBytes
== 1);
1888 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1890 if (!ctx
->_ImageTransferState
&&
1891 !srcPacking
->SwapBytes
&&
1892 srcFormat
== GL_COLOR_INDEX
&&
1893 srcType
== GL_UNSIGNED_BYTE
) {
1894 /* simple memcpy path */
1895 memcpy_texture(ctx
, dims
,
1896 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1897 dstRowStride
, dstImageStride
,
1898 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1899 srcAddr
, srcPacking
);
1903 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1904 + dstZoffset
* dstImageStride
1905 + dstYoffset
* dstRowStride
1906 + dstXoffset
* dstFormat
->TexelBytes
;
1908 for (img
= 0; img
< srcDepth
; img
++) {
1909 GLubyte
*dstRow
= dstImage
;
1910 for (row
= 0; row
< srcHeight
; row
++) {
1911 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1912 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1913 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1914 srcType
, src
, srcPacking
,
1915 ctx
->_ImageTransferState
);
1916 dstRow
+= dstRowStride
;
1918 dstImage
+= dstImageStride
;
1926 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1929 _mesa_texstore_ycbcr(STORE_PARAMS
)
1931 const GLuint ui
= 1;
1932 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1933 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
1935 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1936 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1937 ASSERT(dstFormat
->TexelBytes
== 2);
1938 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1939 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1940 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1941 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1942 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1944 /* always just memcpy since no pixel transfer ops apply */
1945 memcpy_texture(ctx
, dims
,
1946 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1947 dstRowStride
, dstImageStride
,
1948 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1949 srcAddr
, srcPacking
);
1951 /* Check if we need byte swapping */
1952 /* XXX the logic here _might_ be wrong */
1953 if (srcPacking
->SwapBytes
^
1954 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1955 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1957 GLubyte
*pImage
= (GLubyte
*) dstAddr
1958 + dstZoffset
* dstImageStride
1959 + dstYoffset
* dstRowStride
1960 + dstXoffset
* dstFormat
->TexelBytes
;
1962 for (img
= 0; img
< srcDepth
; img
++) {
1963 GLubyte
*pRow
= pImage
;
1964 for (row
= 0; row
< srcHeight
; row
++) {
1965 _mesa_swap2((GLushort
*) pRow
, srcWidth
);
1966 pRow
+= dstRowStride
;
1968 pImage
+= dstImageStride
;
1977 * Store a combined depth/stencil texture image.
1980 _mesa_texstore_z24_s8(STORE_PARAMS
)
1982 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
1983 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
1984 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
1986 if (!ctx
->_ImageTransferState
&&
1987 !srcPacking
->SwapBytes
) {
1989 memcpy_texture(ctx
, dims
,
1990 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1991 dstRowStride
, dstImageStride
,
1992 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1993 srcAddr
, srcPacking
);
1997 const GLint srcRowStride
1998 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
2000 GLuint
*dstImage
= (GLuint
*) dstAddr
;
2003 for (img
= 0; img
< srcDepth
; img
++) {
2004 GLuint
*dst
= dstImage
;
2006 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
2007 srcWidth
, srcHeight
,
2010 for (row
= 0; row
< srcHeight
; row
++) {
2011 GLubyte stencil
[MAX_WIDTH
];
2013 /* the 24 depth bits will be in the high position: */
2014 _mesa_unpack_depth_span(ctx
, srcWidth
,
2015 GL_UNSIGNED_INT
, /* dst type */
2017 (GLfloat
) 0xffffff, /* depthScale */
2018 srcType
, src
, srcPacking
);
2019 /* get the 8-bit stencil values */
2020 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2021 GL_UNSIGNED_BYTE
, /* dst type */
2022 stencil
, /* dst addr */
2023 srcType
, src
, srcPacking
,
2024 ctx
->_ImageTransferState
);
2025 /* merge stencil values into depth values */
2026 for (i
= 0; i
< srcWidth
; i
++)
2027 dst
[i
] |= stencil
[i
];
2029 src
+= srcRowStride
;
2030 dst
+= dstRowStride
/ sizeof(GLuint
);
2032 dstImage
+= dstImageStride
/ sizeof(GLuint
);
2043 * Store an image in any of the formats:
2044 * _mesa_texformat_rgba_float32
2045 * _mesa_texformat_rgb_float32
2046 * _mesa_texformat_alpha_float32
2047 * _mesa_texformat_luminance_float32
2048 * _mesa_texformat_luminance_alpha_float32
2049 * _mesa_texformat_intensity_float32
2052 _mesa_texstore_rgba_float32(STORE_PARAMS
)
2054 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
2056 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2057 dstFormat
== &_mesa_texformat_rgb_float32
||
2058 dstFormat
== &_mesa_texformat_alpha_float32
||
2059 dstFormat
== &_mesa_texformat_luminance_float32
||
2060 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2061 dstFormat
== &_mesa_texformat_intensity_float32
);
2062 ASSERT(baseInternalFormat
== GL_RGBA
||
2063 baseInternalFormat
== GL_RGB
||
2064 baseInternalFormat
== GL_ALPHA
||
2065 baseInternalFormat
== GL_LUMINANCE
||
2066 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2067 baseInternalFormat
== GL_INTENSITY
);
2068 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2070 if (!ctx
->_ImageTransferState
&&
2071 !srcPacking
->SwapBytes
&&
2072 baseInternalFormat
== srcFormat
&&
2073 srcType
== GL_FLOAT
) {
2074 /* simple memcpy path */
2075 memcpy_texture(ctx
, dims
,
2076 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2077 dstRowStride
, dstImageStride
,
2078 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2079 srcAddr
, srcPacking
);
2083 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2085 dstFormat
->BaseFormat
,
2086 srcWidth
, srcHeight
, srcDepth
,
2087 srcFormat
, srcType
, srcAddr
,
2089 const GLfloat
*src
= tempImage
;
2091 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2092 + dstZoffset
* dstImageStride
2093 + dstYoffset
* dstRowStride
2094 + dstXoffset
* dstFormat
->TexelBytes
;
2098 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2099 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2100 for (img
= 0; img
< srcDepth
; img
++) {
2101 GLubyte
*dst
= dstImage
;
2102 for (row
= 0; row
< srcHeight
; row
++) {
2103 _mesa_memcpy(dst
, src
, bytesPerRow
);
2104 dst
+= dstRowStride
;
2105 src
+= srcWidth
* components
;
2107 dstImage
+= dstImageStride
;
2110 _mesa_free((void *) tempImage
);
2117 * As above, but store 16-bit floats.
2120 _mesa_texstore_rgba_float16(STORE_PARAMS
)
2122 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
2124 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2125 dstFormat
== &_mesa_texformat_rgb_float16
||
2126 dstFormat
== &_mesa_texformat_alpha_float16
||
2127 dstFormat
== &_mesa_texformat_luminance_float16
||
2128 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2129 dstFormat
== &_mesa_texformat_intensity_float16
);
2130 ASSERT(baseInternalFormat
== GL_RGBA
||
2131 baseInternalFormat
== GL_RGB
||
2132 baseInternalFormat
== GL_ALPHA
||
2133 baseInternalFormat
== GL_LUMINANCE
||
2134 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2135 baseInternalFormat
== GL_INTENSITY
);
2136 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2138 if (!ctx
->_ImageTransferState
&&
2139 !srcPacking
->SwapBytes
&&
2140 baseInternalFormat
== srcFormat
&&
2141 srcType
== GL_HALF_FLOAT_ARB
) {
2142 /* simple memcpy path */
2143 memcpy_texture(ctx
, dims
,
2144 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2145 dstRowStride
, dstImageStride
,
2146 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2147 srcAddr
, srcPacking
);
2151 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2153 dstFormat
->BaseFormat
,
2154 srcWidth
, srcHeight
, srcDepth
,
2155 srcFormat
, srcType
, srcAddr
,
2157 const GLfloat
*src
= tempImage
;
2158 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2159 + dstZoffset
* dstImageStride
2160 + dstYoffset
* dstRowStride
2161 + dstXoffset
* dstFormat
->TexelBytes
;
2165 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2166 for (img
= 0; img
< srcDepth
; img
++) {
2167 GLubyte
*dstRow
= dstImage
;
2168 for (row
= 0; row
< srcHeight
; row
++) {
2169 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2171 for (i
= 0; i
< srcWidth
* components
; i
++) {
2172 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2174 dstRow
+= dstRowStride
;
2175 src
+= srcWidth
* components
;
2177 dstImage
+= dstImageStride
;
2180 _mesa_free((void *) tempImage
);
2188 * Check if an unpack PBO is active prior to fetching a texture image.
2189 * If so, do bounds checking and map the buffer into main memory.
2190 * Any errors detected will be recorded.
2191 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2194 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2195 GLsizei width
, GLsizei height
, GLsizei depth
,
2196 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2197 const struct gl_pixelstore_attrib
*unpack
,
2198 const char *funcName
)
2202 if (unpack
->BufferObj
->Name
== 0) {
2206 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2207 format
, type
, pixels
)) {
2208 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2212 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2213 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2215 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2219 return ADD_POINTERS(buf
, pixels
);
2224 * Check if an unpack PBO is active prior to fetching a compressed texture
2226 * If so, do bounds checking and map the buffer into main memory.
2227 * Any errors detected will be recorded.
2228 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2231 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2232 GLsizei imageSize
, const GLvoid
*pixels
,
2233 const struct gl_pixelstore_attrib
*packing
,
2234 const char *funcName
)
2238 if (packing
->BufferObj
->Name
== 0) {
2239 /* not using a PBO - return pointer unchanged */
2242 if ((const GLubyte
*) pixels
+ imageSize
>
2243 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2244 /* out of bounds read! */
2245 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2249 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2250 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2252 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2256 return ADD_POINTERS(buf
, pixels
);
2261 * This function must be called after either of the validate_pbo_*_teximage()
2262 * functions. It unmaps the PBO buffer if it was mapped earlier.
2265 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2266 const struct gl_pixelstore_attrib
*unpack
)
2268 if (unpack
->BufferObj
->Name
) {
2269 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2277 * Adaptor for fetching a GLchan texel from a float-valued texture.
2280 FetchTexelFloatToChan( const struct gl_texture_image
*texImage
,
2281 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2284 ASSERT(texImage
->FetchTexelf
);
2285 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2286 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
) {
2287 /* just one channel */
2288 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2292 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2293 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2294 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2295 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2301 * Adaptor for fetching a float texel from a GLchan-valued texture.
2304 FetchTexelChanToFloat( const struct gl_texture_image
*texImage
,
2305 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2308 ASSERT(texImage
->FetchTexelc
);
2309 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2310 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
) {
2311 /* just one channel */
2312 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2316 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2317 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2318 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2319 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2325 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2328 set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2330 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2331 ASSERT(texImage
->TexFormat
);
2335 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2336 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2339 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2340 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2343 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2344 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2350 /* now check if we need to use a float/chan adaptor */
2351 if (!texImage
->FetchTexelc
) {
2352 texImage
->FetchTexelc
= FetchTexelFloatToChan
;
2354 else if (!texImage
->FetchTexelf
) {
2355 texImage
->FetchTexelf
= FetchTexelChanToFloat
;
2359 ASSERT(texImage
->FetchTexelc
);
2360 ASSERT(texImage
->FetchTexelf
);
2365 * This is the software fallback for Driver.TexImage1D()
2366 * and Driver.CopyTexImage1D().
2367 * \sa _mesa_store_teximage2d()
2370 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2371 GLint internalFormat
,
2372 GLint width
, GLint border
,
2373 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2374 const struct gl_pixelstore_attrib
*packing
,
2375 struct gl_texture_object
*texObj
,
2376 struct gl_texture_image
*texImage
)
2378 GLint postConvWidth
= width
;
2382 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2383 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2386 /* choose the texture format */
2387 assert(ctx
->Driver
.ChooseTextureFormat
);
2388 texImage
->TexFormat
= ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
,
2390 assert(texImage
->TexFormat
);
2391 set_fetch_functions(texImage
, 1);
2393 /* allocate memory */
2394 if (texImage
->IsCompressed
)
2395 sizeInBytes
= texImage
->CompressedSize
;
2397 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2398 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2399 if (!texImage
->Data
) {
2400 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2404 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2405 pixels
, packing
, "glTexImage1D");
2407 /* Note: we check for a NULL image pointer here, _after_ we allocated
2408 * memory for the texture. That's what the GL spec calls for.
2413 const GLint dstRowStride
= 0, dstImageStride
= 0;
2415 ASSERT(texImage
->TexFormat
->StoreImage
);
2416 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2417 texImage
->TexFormat
,
2419 0, 0, 0, /* dstX/Y/Zoffset */
2420 dstRowStride
, dstImageStride
,
2422 format
, type
, pixels
, packing
);
2424 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2428 /* GL_SGIS_generate_mipmap */
2429 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2430 _mesa_generate_mipmap(ctx
, target
,
2431 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2435 _mesa_unmap_teximage_pbo(ctx
, packing
);
2440 * This is the software fallback for Driver.TexImage2D()
2441 * and Driver.CopyTexImage2D().
2442 * We store the image in heap memory. We know nothing about on-board
2443 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2444 * textures in main memory, this routine will typically be used by
2445 * hardware drivers too.
2447 * Reasons why a driver might override this function:
2448 * - Special memory allocation needs (VRAM, AGP, etc)
2449 * - Unusual row/image strides or padding
2450 * - Special housekeeping
2451 * - Using VRAM-based Pixel Buffer Objects
2454 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2455 GLint internalFormat
,
2456 GLint width
, GLint height
, GLint border
,
2457 GLenum format
, GLenum type
, const void *pixels
,
2458 const struct gl_pixelstore_attrib
*packing
,
2459 struct gl_texture_object
*texObj
,
2460 struct gl_texture_image
*texImage
)
2462 GLint postConvWidth
= width
, postConvHeight
= height
;
2463 GLint texelBytes
, sizeInBytes
;
2466 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2467 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2471 /* choose the texture format */
2472 assert(ctx
->Driver
.ChooseTextureFormat
);
2473 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2474 internalFormat
, format
, type
);
2475 assert(texImage
->TexFormat
);
2476 set_fetch_functions(texImage
, 2);
2478 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2480 /* allocate memory */
2481 if (texImage
->IsCompressed
)
2482 sizeInBytes
= texImage
->CompressedSize
;
2484 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2485 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2486 if (!texImage
->Data
) {
2487 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2491 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2492 pixels
, packing
, "glTexImage2D");
2494 /* Note: we check for a NULL image pointer here, _after_ we allocated
2495 * memory for the texture. That's what the GL spec calls for.
2500 GLint dstRowStride
, dstImageStride
= 0;
2502 if (texImage
->IsCompressed
) {
2504 = _mesa_compressed_row_stride(texImage
->InternalFormat
,width
);
2507 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2509 ASSERT(texImage
->TexFormat
->StoreImage
);
2510 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2511 texImage
->TexFormat
,
2513 0, 0, 0, /* dstX/Y/Zoffset */
2514 dstRowStride
, dstImageStride
,
2516 format
, type
, pixels
, packing
);
2518 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2522 /* GL_SGIS_generate_mipmap */
2523 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2524 _mesa_generate_mipmap(ctx
, target
,
2525 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2529 _mesa_unmap_teximage_pbo(ctx
, packing
);
2535 * This is the software fallback for Driver.TexImage3D()
2536 * and Driver.CopyTexImage3D().
2537 * \sa _mesa_store_teximage2d()
2540 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2541 GLint internalFormat
,
2542 GLint width
, GLint height
, GLint depth
, GLint border
,
2543 GLenum format
, GLenum type
, const void *pixels
,
2544 const struct gl_pixelstore_attrib
*packing
,
2545 struct gl_texture_object
*texObj
,
2546 struct gl_texture_image
*texImage
)
2548 GLint texelBytes
, sizeInBytes
;
2551 /* choose the texture format */
2552 assert(ctx
->Driver
.ChooseTextureFormat
);
2553 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2554 internalFormat
, format
, type
);
2555 assert(texImage
->TexFormat
);
2556 set_fetch_functions(texImage
, 3);
2558 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2560 /* allocate memory */
2561 if (texImage
->IsCompressed
)
2562 sizeInBytes
= texImage
->CompressedSize
;
2564 sizeInBytes
= width
* height
* depth
* texelBytes
;
2565 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2566 if (!texImage
->Data
) {
2567 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2571 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2572 type
, pixels
, packing
, "glTexImage3D");
2574 /* Note: we check for a NULL image pointer here, _after_ we allocated
2575 * memory for the texture. That's what the GL spec calls for.
2580 GLint dstRowStride
, dstImageStride
;
2582 if (texImage
->IsCompressed
) {
2584 = _mesa_compressed_row_stride(texImage
->InternalFormat
,width
);
2588 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2589 dstImageStride
= dstRowStride
* height
;
2591 ASSERT(texImage
->TexFormat
->StoreImage
);
2592 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2593 texImage
->TexFormat
,
2595 0, 0, 0, /* dstX/Y/Zoffset */
2596 dstRowStride
, dstImageStride
,
2597 width
, height
, depth
,
2598 format
, type
, pixels
, packing
);
2600 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2604 /* GL_SGIS_generate_mipmap */
2605 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2606 _mesa_generate_mipmap(ctx
, target
,
2607 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2611 _mesa_unmap_teximage_pbo(ctx
, packing
);
2618 * This is the software fallback for Driver.TexSubImage1D()
2619 * and Driver.CopyTexSubImage1D().
2622 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2623 GLint xoffset
, GLint width
,
2624 GLenum format
, GLenum type
, const void *pixels
,
2625 const struct gl_pixelstore_attrib
*packing
,
2626 struct gl_texture_object
*texObj
,
2627 struct gl_texture_image
*texImage
)
2629 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2630 pixels
, packing
, "glTexSubImage1D");
2635 const GLint dstRowStride
= 0, dstImageStride
= 0;
2637 ASSERT(texImage
->TexFormat
->StoreImage
);
2638 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2639 texImage
->TexFormat
,
2641 xoffset
, 0, 0, /* offsets */
2642 dstRowStride
, dstImageStride
,
2644 format
, type
, pixels
, packing
);
2646 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2650 /* GL_SGIS_generate_mipmap */
2651 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2652 _mesa_generate_mipmap(ctx
, target
,
2653 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2657 _mesa_unmap_teximage_pbo(ctx
, packing
);
2663 * This is the software fallback for Driver.TexSubImage2D()
2664 * and Driver.CopyTexSubImage2D().
2667 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2668 GLint xoffset
, GLint yoffset
,
2669 GLint width
, GLint height
,
2670 GLenum format
, GLenum type
, const void *pixels
,
2671 const struct gl_pixelstore_attrib
*packing
,
2672 struct gl_texture_object
*texObj
,
2673 struct gl_texture_image
*texImage
)
2675 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2676 pixels
, packing
, "glTexSubImage2D");
2681 GLint dstRowStride
= 0, dstImageStride
= 0;
2683 if (texImage
->IsCompressed
) {
2684 dstRowStride
= _mesa_compressed_row_stride(texImage
->InternalFormat
,
2688 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2690 ASSERT(texImage
->TexFormat
->StoreImage
);
2691 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2692 texImage
->TexFormat
,
2694 xoffset
, yoffset
, 0,
2695 dstRowStride
, dstImageStride
,
2697 format
, type
, pixels
, packing
);
2699 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2703 /* GL_SGIS_generate_mipmap */
2704 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2705 _mesa_generate_mipmap(ctx
, target
,
2706 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2710 _mesa_unmap_teximage_pbo(ctx
, packing
);
2715 * This is the software fallback for Driver.TexSubImage3D().
2716 * and Driver.CopyTexSubImage3D().
2719 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2720 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2721 GLint width
, GLint height
, GLint depth
,
2722 GLenum format
, GLenum type
, const void *pixels
,
2723 const struct gl_pixelstore_attrib
*packing
,
2724 struct gl_texture_object
*texObj
,
2725 struct gl_texture_image
*texImage
)
2727 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2728 type
, pixels
, packing
,
2734 GLint dstRowStride
, dstImageStride
;
2736 if (texImage
->IsCompressed
) {
2737 dstRowStride
= _mesa_compressed_row_stride(texImage
->InternalFormat
,
2739 dstImageStride
= 0; /* XXX fix */
2742 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2743 dstImageStride
= dstRowStride
* texImage
->Height
;
2745 ASSERT(texImage
->TexFormat
->StoreImage
);
2746 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2747 texImage
->TexFormat
,
2749 xoffset
, yoffset
, zoffset
,
2750 dstRowStride
, dstImageStride
,
2751 width
, height
, depth
,
2752 format
, type
, pixels
, packing
);
2754 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2758 /* GL_SGIS_generate_mipmap */
2759 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2760 _mesa_generate_mipmap(ctx
, target
,
2761 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2765 _mesa_unmap_teximage_pbo(ctx
, packing
);
2770 * Fallback for Driver.CompressedTexImage1D()
2773 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2774 GLint internalFormat
,
2775 GLint width
, GLint border
,
2776 GLsizei imageSize
, const GLvoid
*data
,
2777 struct gl_texture_object
*texObj
,
2778 struct gl_texture_image
*texImage
)
2780 /* this space intentionally left blank */
2782 (void) target
; (void) level
;
2783 (void) internalFormat
;
2784 (void) width
; (void) border
;
2785 (void) imageSize
; (void) data
;
2793 * Fallback for Driver.CompressedTexImage2D()
2796 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2797 GLint internalFormat
,
2798 GLint width
, GLint height
, GLint border
,
2799 GLsizei imageSize
, const GLvoid
*data
,
2800 struct gl_texture_object
*texObj
,
2801 struct gl_texture_image
*texImage
)
2803 (void) width
; (void) height
; (void) border
;
2805 /* This is pretty simple, basically just do a memcpy without worrying
2806 * about the usual image unpacking or image transfer operations.
2810 ASSERT(texImage
->Width
> 0);
2811 ASSERT(texImage
->Height
> 0);
2812 ASSERT(texImage
->Depth
== 1);
2813 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2815 /* choose the texture format */
2816 assert(ctx
->Driver
.ChooseTextureFormat
);
2817 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2818 internalFormat
, 0, 0);
2819 assert(texImage
->TexFormat
);
2820 set_fetch_functions(texImage
, 2);
2822 /* allocate storage */
2823 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
2824 if (!texImage
->Data
) {
2825 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2829 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2831 "glCompressedTexImage2D");
2836 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2837 MEMCPY(texImage
->Data
, data
, imageSize
);
2839 /* GL_SGIS_generate_mipmap */
2840 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2841 _mesa_generate_mipmap(ctx
, target
,
2842 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2846 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2852 * Fallback for Driver.CompressedTexImage3D()
2855 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2856 GLint internalFormat
,
2857 GLint width
, GLint height
, GLint depth
,
2859 GLsizei imageSize
, const GLvoid
*data
,
2860 struct gl_texture_object
*texObj
,
2861 struct gl_texture_image
*texImage
)
2863 /* this space intentionally left blank */
2865 (void) target
; (void) level
;
2866 (void) internalFormat
;
2867 (void) width
; (void) height
; (void) depth
;
2869 (void) imageSize
; (void) data
;
2877 * Fallback for Driver.CompressedTexSubImage1D()
2880 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2882 GLint xoffset
, GLsizei width
,
2884 GLsizei imageSize
, const GLvoid
*data
,
2885 struct gl_texture_object
*texObj
,
2886 struct gl_texture_image
*texImage
)
2888 /* this space intentionally left blank */
2890 (void) target
; (void) level
;
2891 (void) xoffset
; (void) width
;
2893 (void) imageSize
; (void) data
;
2900 * Fallback for Driver.CompressedTexSubImage2D()
2903 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2905 GLint xoffset
, GLint yoffset
,
2906 GLsizei width
, GLsizei height
,
2908 GLsizei imageSize
, const GLvoid
*data
,
2909 struct gl_texture_object
*texObj
,
2910 struct gl_texture_image
*texImage
)
2912 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2918 /* these should have been caught sooner */
2919 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2920 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2921 ASSERT((xoffset
& 3) == 0);
2922 ASSERT((yoffset
& 3) == 0);
2924 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2926 "glCompressedTexSubImage2D");
2930 srcRowStride
= _mesa_compressed_row_stride(texImage
->InternalFormat
, width
);
2931 src
= (const GLubyte
*) data
;
2933 destRowStride
= _mesa_compressed_row_stride(texImage
->InternalFormat
,
2935 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2936 texImage
->InternalFormat
,
2938 (GLubyte
*) texImage
->Data
);
2940 bytesPerRow
= srcRowStride
;
2943 for (i
= 0; i
< rows
; i
++) {
2944 MEMCPY(dest
, src
, bytesPerRow
);
2945 dest
+= destRowStride
;
2946 src
+= srcRowStride
;
2949 /* GL_SGIS_generate_mipmap */
2950 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2951 _mesa_generate_mipmap(ctx
, target
,
2952 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2956 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2961 * Fallback for Driver.CompressedTexSubImage3D()
2964 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2966 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2967 GLsizei width
, GLsizei height
, GLsizei depth
,
2969 GLsizei imageSize
, const GLvoid
*data
,
2970 struct gl_texture_object
*texObj
,
2971 struct gl_texture_image
*texImage
)
2973 /* this space intentionally left blank */
2975 (void) target
; (void) level
;
2976 (void) xoffset
; (void) yoffset
; (void) zoffset
;
2977 (void) width
; (void) height
; (void) depth
;
2979 (void) imageSize
; (void) data
;
2986 * Average together two rows of a source image to produce a single new
2987 * row in the dest image. It's legal for the two source rows to point
2988 * to the same data. The source width must be equal to either the
2989 * dest width or two times the dest width.
2992 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
2993 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
2994 GLint dstWidth
, GLvoid
*dstRow
)
2996 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
2997 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
2999 /* This assertion is no longer valid with non-power-of-2 textures
3000 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
3003 switch (format
->MesaFormat
) {
3004 case MESA_FORMAT_RGBA
:
3007 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
3008 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
3009 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
3010 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3011 i
++, j
+= colStride
, k
+= colStride
) {
3012 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3013 rowB
[j
][0] + rowB
[k
][0]) / 4;
3014 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3015 rowB
[j
][1] + rowB
[k
][1]) / 4;
3016 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3017 rowB
[j
][2] + rowB
[k
][2]) / 4;
3018 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3019 rowB
[j
][3] + rowB
[k
][3]) / 4;
3023 case MESA_FORMAT_RGB
:
3026 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
3027 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
3028 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
3029 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3030 i
++, j
+= colStride
, k
+= colStride
) {
3031 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3032 rowB
[j
][0] + rowB
[k
][0]) / 4;
3033 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3034 rowB
[j
][1] + rowB
[k
][1]) / 4;
3035 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3036 rowB
[j
][2] + rowB
[k
][2]) / 4;
3040 case MESA_FORMAT_ALPHA
:
3041 case MESA_FORMAT_LUMINANCE
:
3042 case MESA_FORMAT_INTENSITY
:
3045 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
3046 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
3047 GLchan
*dst
= (GLchan
*) dstRow
;
3048 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3049 i
++, j
+= colStride
, k
+= colStride
) {
3050 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3054 case MESA_FORMAT_LUMINANCE_ALPHA
:
3057 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
3058 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
3059 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
3060 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3061 i
++, j
+= colStride
, k
+= colStride
) {
3062 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3063 rowB
[j
][0] + rowB
[k
][0]) / 4;
3064 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3065 rowB
[j
][1] + rowB
[k
][1]) / 4;
3069 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32
:
3072 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3073 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3074 GLfloat
*dst
= (GLfloat
*) dstRow
;
3075 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3076 i
++, j
+= colStride
, k
+= colStride
) {
3077 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3081 case MESA_FORMAT_DEPTH_COMPONENT16
:
3084 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3085 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3086 GLushort
*dst
= (GLushort
*) dstRow
;
3087 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3088 i
++, j
+= colStride
, k
+= colStride
) {
3089 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3093 /* Begin hardware formats */
3094 case MESA_FORMAT_RGBA8888
:
3095 case MESA_FORMAT_RGBA8888_REV
:
3096 case MESA_FORMAT_ARGB8888
:
3097 case MESA_FORMAT_ARGB8888_REV
:
3100 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
3101 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
3102 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
3103 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3104 i
++, j
+= colStride
, k
+= colStride
) {
3105 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3106 rowB
[j
][0] + rowB
[k
][0]) / 4;
3107 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3108 rowB
[j
][1] + rowB
[k
][1]) / 4;
3109 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3110 rowB
[j
][2] + rowB
[k
][2]) / 4;
3111 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3112 rowB
[j
][3] + rowB
[k
][3]) / 4;
3116 case MESA_FORMAT_RGB888
:
3117 case MESA_FORMAT_BGR888
:
3120 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
3121 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
3122 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
3123 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3124 i
++, j
+= colStride
, k
+= colStride
) {
3125 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3126 rowB
[j
][0] + rowB
[k
][0]) / 4;
3127 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3128 rowB
[j
][1] + rowB
[k
][1]) / 4;
3129 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3130 rowB
[j
][2] + rowB
[k
][2]) / 4;
3134 case MESA_FORMAT_RGB565
:
3135 case MESA_FORMAT_RGB565_REV
:
3138 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3139 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3140 GLushort
*dst
= (GLushort
*) dstRow
;
3141 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3142 i
++, j
+= colStride
, k
+= colStride
) {
3143 const GLint rowAr0
= rowA
[j
] & 0x1f;
3144 const GLint rowAr1
= rowA
[k
] & 0x1f;
3145 const GLint rowBr0
= rowB
[j
] & 0x1f;
3146 const GLint rowBr1
= rowB
[k
] & 0x1f;
3147 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
3148 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
3149 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
3150 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
3151 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
3152 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
3153 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
3154 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
3155 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3156 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3157 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3158 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
3162 case MESA_FORMAT_ARGB4444
:
3163 case MESA_FORMAT_ARGB4444_REV
:
3166 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3167 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3168 GLushort
*dst
= (GLushort
*) dstRow
;
3169 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3170 i
++, j
+= colStride
, k
+= colStride
) {
3171 const GLint rowAr0
= rowA
[j
] & 0xf;
3172 const GLint rowAr1
= rowA
[k
] & 0xf;
3173 const GLint rowBr0
= rowB
[j
] & 0xf;
3174 const GLint rowBr1
= rowB
[k
] & 0xf;
3175 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
3176 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
3177 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
3178 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
3179 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
3180 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
3181 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
3182 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
3183 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
3184 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
3185 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
3186 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
3187 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3188 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3189 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3190 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3191 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
3195 case MESA_FORMAT_ARGB1555
:
3196 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
3199 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3200 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3201 GLushort
*dst
= (GLushort
*) dstRow
;
3202 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3203 i
++, j
+= colStride
, k
+= colStride
) {
3204 const GLint rowAr0
= rowA
[j
] & 0x1f;
3205 const GLint rowAr1
= rowA
[k
] & 0x1f;
3206 const GLint rowBr0
= rowB
[j
] & 0x1f;
3207 const GLint rowBr1
= rowB
[k
] & 0xf;
3208 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
3209 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
3210 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
3211 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
3212 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
3213 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3214 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3215 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3216 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3217 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3218 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3219 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3220 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3221 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3222 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3223 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3224 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3228 case MESA_FORMAT_AL88
:
3229 case MESA_FORMAT_AL88_REV
:
3232 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3233 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3234 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3235 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3236 i
++, j
+= colStride
, k
+= colStride
) {
3237 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3238 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3239 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3240 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3244 case MESA_FORMAT_RGB332
:
3247 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3248 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3249 GLubyte
*dst
= (GLubyte
*) dstRow
;
3250 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3251 i
++, j
+= colStride
, k
+= colStride
) {
3252 const GLint rowAr0
= rowA
[j
] & 0x3;
3253 const GLint rowAr1
= rowA
[k
] & 0x3;
3254 const GLint rowBr0
= rowB
[j
] & 0x3;
3255 const GLint rowBr1
= rowB
[k
] & 0x3;
3256 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3257 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3258 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3259 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3260 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3261 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3262 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3263 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3264 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3265 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3266 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3267 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3271 case MESA_FORMAT_A8
:
3272 case MESA_FORMAT_L8
:
3273 case MESA_FORMAT_I8
:
3274 case MESA_FORMAT_CI8
:
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 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
3286 case MESA_FORMAT_RGBA_FLOAT32
:
3289 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3290 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3291 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
3292 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3293 i
++, j
+= colStride
, k
+= colStride
) {
3294 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3295 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3296 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3297 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3298 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3299 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3300 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3301 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3305 case MESA_FORMAT_RGBA_FLOAT16
:
3307 GLuint i
, j
, k
, comp
;
3308 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3309 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3310 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3311 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3312 i
++, j
+= colStride
, k
+= colStride
) {
3313 for (comp
= 0; comp
< 4; comp
++) {
3314 GLfloat aj
, ak
, bj
, bk
;
3315 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3316 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3317 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3318 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3319 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3324 case MESA_FORMAT_RGB_FLOAT32
:
3327 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3328 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3329 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3330 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3331 i
++, j
+= colStride
, k
+= colStride
) {
3332 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3333 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3334 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3335 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3336 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3337 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3341 case MESA_FORMAT_RGB_FLOAT16
:
3343 GLuint i
, j
, k
, comp
;
3344 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3345 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3346 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3347 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3348 i
++, j
+= colStride
, k
+= colStride
) {
3349 for (comp
= 0; comp
< 3; comp
++) {
3350 GLfloat aj
, ak
, bj
, bk
;
3351 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3352 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3353 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3354 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3355 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3360 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3363 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3364 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3365 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3366 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3367 i
++, j
+= colStride
, k
+= colStride
) {
3368 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3369 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3370 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3371 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3375 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3377 GLuint i
, j
, k
, comp
;
3378 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3379 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3380 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3381 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3382 i
++, j
+= colStride
, k
+= colStride
) {
3383 for (comp
= 0; comp
< 2; comp
++) {
3384 GLfloat aj
, ak
, bj
, bk
;
3385 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3386 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3387 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3388 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3389 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3394 case MESA_FORMAT_ALPHA_FLOAT32
:
3395 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3396 case MESA_FORMAT_INTENSITY_FLOAT32
:
3399 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3400 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3401 GLfloat
*dst
= (GLfloat
*) dstRow
;
3402 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3403 i
++, j
+= colStride
, k
+= colStride
) {
3404 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3408 case MESA_FORMAT_ALPHA_FLOAT16
:
3409 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3410 case MESA_FORMAT_INTENSITY_FLOAT16
:
3413 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3414 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3415 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3416 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3417 i
++, j
+= colStride
, k
+= colStride
) {
3418 GLfloat aj
, ak
, bj
, bk
;
3419 aj
= _mesa_half_to_float(rowA
[j
]);
3420 ak
= _mesa_half_to_float(rowA
[k
]);
3421 bj
= _mesa_half_to_float(rowB
[j
]);
3422 bk
= _mesa_half_to_float(rowB
[k
]);
3423 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3429 _mesa_problem(NULL
, "bad format in do_row()");
3435 * These functions generate a 1/2-size mipmap image from a source image.
3436 * Texture borders are handled by copying or averaging the source image's
3437 * border texels, depending on the scale-down factor.
3441 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3442 GLint srcWidth
, const GLubyte
*srcPtr
,
3443 GLint dstWidth
, GLubyte
*dstPtr
)
3445 const GLint bpt
= format
->TexelBytes
;
3449 /* skip the border pixel, if any */
3450 src
= srcPtr
+ border
* bpt
;
3451 dst
= dstPtr
+ border
* bpt
;
3453 /* we just duplicate the input row, kind of hack, saves code */
3454 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3455 dstWidth
- 2 * border
, dst
);
3458 /* copy left-most pixel from source */
3459 MEMCPY(dstPtr
, srcPtr
, bpt
);
3460 /* copy right-most pixel from source */
3461 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3462 srcPtr
+ (srcWidth
- 1) * bpt
,
3469 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3470 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3471 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3473 const GLint bpt
= format
->TexelBytes
;
3474 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3475 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3476 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3477 const GLint srcRowStride
= bpt
* srcWidth
;
3478 const GLint dstRowStride
= bpt
* dstWidth
;
3479 const GLubyte
*srcA
, *srcB
;
3483 /* Compute src and dst pointers, skipping any border */
3484 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3486 srcB
= srcA
+ srcRowStride
;
3489 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3491 for (row
= 0; row
< dstHeightNB
; row
++) {
3492 do_row(format
, srcWidthNB
, srcA
, srcB
,
3494 srcA
+= 2 * srcRowStride
;
3495 srcB
+= 2 * srcRowStride
;
3496 dst
+= dstRowStride
;
3499 /* This is ugly but probably won't be used much */
3501 /* fill in dest border */
3502 /* lower-left border pixel */
3503 MEMCPY(dstPtr
, srcPtr
, bpt
);
3504 /* lower-right border pixel */
3505 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3506 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3507 /* upper-left border pixel */
3508 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3509 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3510 /* upper-right border pixel */
3511 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3512 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3514 do_row(format
, srcWidthNB
,
3517 dstWidthNB
, dstPtr
+ bpt
);
3519 do_row(format
, srcWidthNB
,
3520 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3521 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3523 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3524 /* left and right borders */
3525 if (srcHeight
== dstHeight
) {
3526 /* copy border pixel from src to dst */
3527 for (row
= 1; row
< srcHeight
; row
++) {
3528 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3529 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3530 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3531 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3535 /* average two src pixels each dest pixel */
3536 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3538 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3539 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3540 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3542 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3543 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3544 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3552 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3553 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3554 const GLubyte
*srcPtr
,
3555 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3558 const GLint bpt
= format
->TexelBytes
;
3559 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3560 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3561 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3562 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3563 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3564 GLvoid
*tmpRowA
, *tmpRowB
;
3566 GLint bytesPerSrcImage
, bytesPerDstImage
;
3567 GLint bytesPerSrcRow
, bytesPerDstRow
;
3568 GLint srcImageOffset
, srcRowOffset
;
3570 (void) srcDepthNB
; /* silence warnings */
3572 /* Need two temporary row buffers */
3573 tmpRowA
= _mesa_malloc(srcWidth
* bpt
);
3576 tmpRowB
= _mesa_malloc(srcWidth
* bpt
);
3578 _mesa_free(tmpRowA
);
3582 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3583 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3585 bytesPerSrcRow
= srcWidth
* bpt
;
3586 bytesPerDstRow
= dstWidth
* bpt
;
3588 /* Offset between adjacent src images to be averaged together */
3589 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3591 /* Offset between adjacent src rows to be averaged together */
3592 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3595 * Need to average together up to 8 src pixels for each dest pixel.
3596 * Break that down into 3 operations:
3597 * 1. take two rows from source image and average them together.
3598 * 2. take two rows from next source image and average them together.
3599 * 3. take the two averaged rows and average them for the final dst row.
3603 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3604 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3607 for (img
= 0; img
< dstDepthNB
; img
++) {
3608 /* first source image pointer, skipping border */
3609 const GLubyte
*imgSrcA
= srcPtr
3610 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3611 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3612 /* second source image pointer, skipping border */
3613 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3614 /* address of the dest image, skipping border */
3615 GLubyte
*imgDst
= dstPtr
3616 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3617 + img
* bytesPerDstImage
;
3619 /* setup the four source row pointers and the dest row pointer */
3620 const GLubyte
*srcImgARowA
= imgSrcA
;
3621 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3622 const GLubyte
*srcImgBRowA
= imgSrcB
;
3623 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3624 GLubyte
*dstImgRow
= imgDst
;
3626 for (row
= 0; row
< dstHeightNB
; row
++) {
3627 /* Average together two rows from first src image */
3628 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3629 srcWidthNB
, tmpRowA
);
3630 /* Average together two rows from second src image */
3631 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3632 srcWidthNB
, tmpRowB
);
3633 /* Average together the temp rows to make the final row */
3634 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3635 dstWidthNB
, dstImgRow
);
3636 /* advance to next rows */
3637 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3638 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3639 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3640 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3641 dstImgRow
+= bytesPerDstRow
;
3645 _mesa_free(tmpRowA
);
3646 _mesa_free(tmpRowB
);
3648 /* Luckily we can leverage the make_2d_mipmap() function here! */
3650 /* do front border image */
3651 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3652 dstWidth
, dstHeight
, dstPtr
);
3653 /* do back border image */
3654 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3655 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3656 dstWidth
, dstHeight
,
3657 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3658 /* do four remaining border edges that span the image slices */
3659 if (srcDepth
== dstDepth
) {
3660 /* just copy border pixels from src to dst */
3661 for (img
= 0; img
< dstDepthNB
; img
++) {
3665 /* do border along [img][row=0][col=0] */
3666 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3667 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3668 MEMCPY(dst
, src
, bpt
);
3670 /* do border along [img][row=dstHeight-1][col=0] */
3671 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3672 + (srcHeight
- 1) * bytesPerSrcRow
;
3673 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3674 + (dstHeight
- 1) * bytesPerDstRow
;
3675 MEMCPY(dst
, src
, bpt
);
3677 /* do border along [img][row=0][col=dstWidth-1] */
3678 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3679 + (srcWidth
- 1) * bpt
;
3680 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3681 + (dstWidth
- 1) * bpt
;
3682 MEMCPY(dst
, src
, bpt
);
3684 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3685 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3686 + (bytesPerSrcImage
- bpt
);
3687 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3688 + (bytesPerDstImage
- bpt
);
3689 MEMCPY(dst
, src
, bpt
);
3693 /* average border pixels from adjacent src image pairs */
3694 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3695 for (img
= 0; img
< dstDepthNB
; img
++) {
3699 /* do border along [img][row=0][col=0] */
3700 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3701 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3702 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3704 /* do border along [img][row=dstHeight-1][col=0] */
3705 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3706 + (srcHeight
- 1) * bytesPerSrcRow
;
3707 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3708 + (dstHeight
- 1) * bytesPerDstRow
;
3709 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3711 /* do border along [img][row=0][col=dstWidth-1] */
3712 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3713 + (srcWidth
- 1) * bpt
;
3714 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3715 + (dstWidth
- 1) * bpt
;
3716 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3718 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3719 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3720 + (bytesPerSrcImage
- bpt
);
3721 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3722 + (bytesPerDstImage
- bpt
);
3723 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3731 * For GL_SGIX_generate_mipmap:
3732 * Generate a complete set of mipmaps from texObj's base-level image.
3733 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3736 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3737 const struct gl_texture_unit
*texUnit
,
3738 struct gl_texture_object
*texObj
)
3740 const struct gl_texture_image
*srcImage
;
3741 const struct gl_texture_format
*convertFormat
;
3742 const GLubyte
*srcData
= NULL
;
3743 GLubyte
*dstData
= NULL
;
3744 GLint level
, maxLevels
;
3747 /* XXX choose cube map face here??? */
3748 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3751 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3752 ASSERT(maxLevels
> 0); /* bad target */
3754 /* Find convertFormat - the format that do_row() will process */
3755 if (srcImage
->IsCompressed
) {
3756 /* setup for compressed textures */
3758 GLint components
, size
;
3761 assert(texObj
->Target
== GL_TEXTURE_2D
);
3763 if (srcImage
->_BaseFormat
== GL_RGB
) {
3764 convertFormat
= &_mesa_texformat_rgb
;
3767 else if (srcImage
->_BaseFormat
== GL_RGBA
) {
3768 convertFormat
= &_mesa_texformat_rgba
;
3772 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
3776 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3777 size
= _mesa_bytes_per_pixel(srcImage
->_BaseFormat
, CHAN_TYPE
)
3778 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3779 /* 20 extra bytes, just be safe when calling last FetchTexel */
3780 srcData
= (GLubyte
*) _mesa_malloc(size
);
3782 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3785 dstData
= (GLubyte
*) _mesa_malloc(size
/ 2); /* 1/4 would probably be OK */
3787 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3788 _mesa_free((void *) srcData
);
3792 /* decompress base image here */
3793 dst
= (GLchan
*) srcData
;
3794 for (row
= 0; row
< srcImage
->Height
; row
++) {
3796 for (col
= 0; col
< srcImage
->Width
; col
++) {
3797 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3804 convertFormat
= srcImage
->TexFormat
;
3807 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3808 && level
< maxLevels
- 1; level
++) {
3809 /* generate image[level+1] from image[level] */
3810 const struct gl_texture_image
*srcImage
;
3811 struct gl_texture_image
*dstImage
;
3812 GLint srcWidth
, srcHeight
, srcDepth
;
3813 GLint dstWidth
, dstHeight
, dstDepth
;
3814 GLint border
, bytesPerTexel
;
3816 /* get src image parameters */
3817 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3819 srcWidth
= srcImage
->Width
;
3820 srcHeight
= srcImage
->Height
;
3821 srcDepth
= srcImage
->Depth
;
3822 border
= srcImage
->Border
;
3824 /* compute next (level+1) image size */
3825 if (srcWidth
- 2 * border
> 1) {
3826 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3829 dstWidth
= srcWidth
; /* can't go smaller */
3831 if (srcHeight
- 2 * border
> 1) {
3832 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3835 dstHeight
= srcHeight
; /* can't go smaller */
3837 if (srcDepth
- 2 * border
> 1) {
3838 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3841 dstDepth
= srcDepth
; /* can't go smaller */
3844 if (dstWidth
== srcWidth
&&
3845 dstHeight
== srcHeight
&&
3846 dstDepth
== srcDepth
) {
3848 if (srcImage
->IsCompressed
) {
3849 _mesa_free((void *) srcData
);
3850 _mesa_free(dstData
);
3855 /* get dest gl_texture_image */
3856 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3858 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3862 /* Free old image data */
3864 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
3866 /* initialize new image */
3867 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3868 dstDepth
, border
, srcImage
->InternalFormat
);
3869 dstImage
->DriverData
= NULL
;
3870 dstImage
->TexFormat
= srcImage
->TexFormat
;
3871 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3872 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3873 ASSERT(dstImage
->TexFormat
);
3874 ASSERT(dstImage
->FetchTexelc
);
3875 ASSERT(dstImage
->FetchTexelf
);
3877 /* Alloc new teximage data buffer.
3878 * Setup src and dest data pointers.
3880 if (dstImage
->IsCompressed
) {
3881 ASSERT(dstImage
->CompressedSize
> 0); /* set by init_teximage_fields*/
3882 dstImage
->Data
= _mesa_alloc_texmemory(dstImage
->CompressedSize
);
3883 if (!dstImage
->Data
) {
3884 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3887 /* srcData and dstData are already set */
3892 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
3893 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3894 dstImage
->Data
= _mesa_alloc_texmemory(dstWidth
* dstHeight
3895 * dstDepth
* bytesPerTexel
);
3896 if (!dstImage
->Data
) {
3897 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3900 srcData
= (const GLubyte
*) srcImage
->Data
;
3901 dstData
= (GLubyte
*) dstImage
->Data
;
3905 * We use simple 2x2 averaging to compute the next mipmap level.
3909 make_1d_mipmap(convertFormat
, border
,
3914 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3915 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3916 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3917 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3918 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3919 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3920 make_2d_mipmap(convertFormat
, border
,
3921 srcWidth
, srcHeight
, srcData
,
3922 dstWidth
, dstHeight
, dstData
);
3925 make_3d_mipmap(convertFormat
, border
,
3926 srcWidth
, srcHeight
, srcDepth
, srcData
,
3927 dstWidth
, dstHeight
, dstDepth
, dstData
);
3929 case GL_TEXTURE_RECTANGLE_NV
:
3930 /* no mipmaps, do nothing */
3933 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3937 if (dstImage
->IsCompressed
) {
3939 /* compress image from dstData into dstImage->Data */
3940 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3942 = _mesa_compressed_row_stride(srcImage
->InternalFormat
, dstWidth
);
3943 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3944 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->_BaseFormat
,
3945 dstImage
->TexFormat
,
3947 0, 0, 0, /* dstX/Y/Zoffset */
3948 dstRowStride
, 0, /* strides */
3949 dstWidth
, dstHeight
, 1, /* size */
3950 srcFormat
, CHAN_TYPE
,
3951 dstData
, /* src data, actually */
3952 &ctx
->DefaultPacking
);
3953 /* swap src and dest pointers */
3954 temp
= (GLubyte
*) srcData
;
3959 } /* loop over mipmap levels */
3964 * Helper function for drivers which need to rescale texture images to
3965 * certain aspect ratios.
3966 * Nearest filtering only (for broken hardware that can't support
3967 * all aspect ratios). This can be made a lot faster, but I don't
3968 * really care enough...
3971 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
3972 GLuint srcStrideInPixels
,
3973 GLuint dstRowStride
,
3974 GLint srcWidth
, GLint srcHeight
,
3975 GLint dstWidth
, GLint dstHeight
,
3976 const GLvoid
*srcImage
, GLvoid
*dstImage
)
3980 #define INNER_LOOP( TYPE, HOP, WOP ) \
3981 for ( row = 0 ; row < dstHeight ; row++ ) { \
3982 GLint srcRow = row HOP hScale; \
3983 for ( col = 0 ; col < dstWidth ; col++ ) { \
3984 GLint srcCol = col WOP wScale; \
3985 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3987 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3990 #define RESCALE_IMAGE( TYPE ) \
3992 const TYPE *src = (const TYPE *)srcImage; \
3993 TYPE *dst = (TYPE *)dstImage; \
3995 if ( srcHeight < dstHeight ) { \
3996 const GLint hScale = dstHeight / srcHeight; \
3997 if ( srcWidth < dstWidth ) { \
3998 const GLint wScale = dstWidth / srcWidth; \
3999 INNER_LOOP( TYPE, /, / ); \
4002 const GLint wScale = srcWidth / dstWidth; \
4003 INNER_LOOP( TYPE, /, * ); \
4007 const GLint hScale = srcHeight / dstHeight; \
4008 if ( srcWidth < dstWidth ) { \
4009 const GLint wScale = dstWidth / srcWidth; \
4010 INNER_LOOP( TYPE, *, / ); \
4013 const GLint wScale = srcWidth / dstWidth; \
4014 INNER_LOOP( TYPE, *, * ); \
4019 switch ( bytesPerPixel
) {
4021 RESCALE_IMAGE( GLuint
);
4025 RESCALE_IMAGE( GLushort
);
4029 RESCALE_IMAGE( GLubyte
);
4032 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
4038 * Upscale an image by replication, not (typical) stretching.
4039 * We use this when the image width or height is less than a
4040 * certain size (4, 8) and we need to upscale an image.
4043 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
4044 GLsizei outWidth
, GLsizei outHeight
,
4045 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
4050 ASSERT(outWidth
>= inWidth
);
4051 ASSERT(outHeight
>= inHeight
);
4053 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
4054 ASSERT((outWidth
& 3) == 0);
4055 ASSERT((outHeight
& 3) == 0);
4058 for (i
= 0; i
< outHeight
; i
++) {
4059 const GLint ii
= i
% inHeight
;
4060 for (j
= 0; j
< outWidth
; j
++) {
4061 const GLint jj
= j
% inWidth
;
4062 for (k
= 0; k
< comps
; k
++) {
4063 dest
[(i
* outWidth
+ j
) * comps
+ k
]
4064 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
4073 * This is the software fallback for Driver.GetTexImage().
4074 * All error checking will have been done before this routine is called.
4077 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4078 GLenum format
, GLenum type
, GLvoid
*pixels
,
4079 struct gl_texture_object
*texObj
,
4080 struct gl_texture_image
*texImage
)
4082 GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
4084 if (ctx
->Pack
.BufferObj
->Name
) {
4085 /* pack texture image into a PBO */
4087 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
4088 texImage
->Height
, texImage
->Depth
,
4089 format
, type
, pixels
)) {
4090 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4091 "glGetTexImage(invalid PBO access)");
4094 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4096 ctx
->Pack
.BufferObj
);
4098 /* buffer is already mapped - that's an error */
4099 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
4102 pixels
= ADD_POINTERS(buf
, pixels
);
4110 const GLint width
= texImage
->Width
;
4111 const GLint height
= texImage
->Height
;
4112 const GLint depth
= texImage
->Depth
;
4114 for (img
= 0; img
< depth
; img
++) {
4115 for (row
= 0; row
< height
; row
++) {
4116 /* compute destination address in client memory */
4117 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
4118 width
, height
, format
, type
,
4122 if (format
== GL_COLOR_INDEX
) {
4123 GLuint indexRow
[MAX_WIDTH
];
4125 /* Can't use FetchTexel here because that returns RGBA */
4126 if (texImage
->TexFormat
->IndexBits
== 8) {
4127 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
4128 src
+= width
* (img
* texImage
->Height
+ row
);
4129 for (col
= 0; col
< width
; col
++) {
4130 indexRow
[col
] = src
[col
];
4133 else if (texImage
->TexFormat
->IndexBits
== 16) {
4134 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
4135 src
+= width
* (img
* texImage
->Height
+ row
);
4136 for (col
= 0; col
< width
; col
++) {
4137 indexRow
[col
] = src
[col
];
4142 "Color index problem in _mesa_GetTexImage");
4144 _mesa_pack_index_span(ctx
, width
, type
, dest
,
4145 indexRow
, &ctx
->Pack
,
4146 0 /* no image transfer */);
4148 else if (format
== GL_DEPTH_COMPONENT
) {
4149 GLfloat depthRow
[MAX_WIDTH
];
4151 for (col
= 0; col
< width
; col
++) {
4152 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
4155 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
4156 depthRow
, &ctx
->Pack
);
4158 else if (format
== GL_DEPTH_STENCIL_EXT
) {
4159 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4160 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
4161 src
+= width
* row
+ width
* height
* img
;
4162 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
4163 if (ctx
->Pack
.SwapBytes
) {
4164 _mesa_swap4((GLuint
*) dest
, width
);
4167 else if (format
== GL_YCBCR_MESA
) {
4168 /* No pixel transfer */
4169 const GLint rowstride
= texImage
->RowStride
;
4171 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
4172 width
* sizeof(GLushort
));
4173 /* check for byte swapping */
4174 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
4175 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
4176 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
4177 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
4178 if (!ctx
->Pack
.SwapBytes
)
4179 _mesa_swap2((GLushort
*) dest
, width
);
4181 else if (ctx
->Pack
.SwapBytes
) {
4182 _mesa_swap2((GLushort
*) dest
, width
);
4186 /* general case: convert row to RGBA format */
4187 GLfloat rgba
[MAX_WIDTH
][4];
4189 for (col
= 0; col
< width
; col
++) {
4190 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
4192 _mesa_pack_rgba_span_float(ctx
, width
,
4193 (const GLfloat (*)[4]) rgba
,
4194 format
, type
, dest
, &ctx
->Pack
,
4195 0 /* no image transfer */);
4201 if (ctx
->Pack
.BufferObj
->Name
) {
4202 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4203 ctx
->Pack
.BufferObj
);
4210 * This is the software fallback for Driver.GetCompressedTexImage().
4211 * All error checking will have been done before this routine is called.
4214 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4216 const struct gl_texture_object
*texObj
,
4217 const struct gl_texture_image
*texImage
)
4219 if (ctx
->Pack
.BufferObj
->Name
) {
4220 /* pack texture image into a PBO */
4222 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4223 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4224 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4225 "glGetCompressedTexImage(invalid PBO access)");
4228 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4230 ctx
->Pack
.BufferObj
);
4232 /* buffer is already mapped - that's an error */
4233 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4234 "glGetCompressedTexImage(PBO is mapped)");
4237 img
= ADD_POINTERS(buf
, img
);
4244 /* just memcpy, no pixelstore or pixel transfer */
4245 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);
4247 if (ctx
->Pack
.BufferObj
->Name
) {
4248 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4249 ctx
->Pack
.BufferObj
);