2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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
, (GLfloat
*) dstRow
,
885 srcType
, src
, srcPacking
);
886 dstRow
+= dstRowStride
;
888 dstImage
+= dstImageStride
;
896 * Store a 16-bit integer depth component texture image.
899 _mesa_texstore_depth_component16(STORE_PARAMS
)
902 ASSERT(dstFormat
== &_mesa_texformat_depth_component16
);
903 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
905 if (!ctx
->_ImageTransferState
&&
906 !srcPacking
->SwapBytes
&&
907 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
908 srcFormat
== GL_DEPTH_COMPONENT
&&
909 srcType
== GL_UNSIGNED_SHORT
) {
910 /* simple memcpy path */
911 memcpy_texture(ctx
, dims
,
912 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
913 dstRowStride
, dstImageStride
,
914 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
915 srcAddr
, srcPacking
);
919 GLubyte
*dstImage
= (GLubyte
*) dstAddr
920 + dstZoffset
* dstImageStride
921 + dstYoffset
* dstRowStride
922 + dstXoffset
* dstFormat
->TexelBytes
;
924 for (img
= 0; img
< srcDepth
; img
++) {
925 GLubyte
*dstRow
= dstImage
;
926 for (row
= 0; row
< srcHeight
; row
++) {
927 GLfloat depthTemp
[MAX_WIDTH
];
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
, depthTemp
,
932 srcType
, src
, srcPacking
);
933 for (col
= 0; col
< srcWidth
; col
++) {
934 dst16
[col
] = (GLushort
) (depthTemp
[col
] * 65535.0F
);
936 dstRow
+= dstRowStride
;
938 dstImage
+= dstImageStride
;
946 * Store an rgb565 or rgb565_rev texture image.
949 _mesa_texstore_rgb565(STORE_PARAMS
)
951 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
952 dstFormat
== &_mesa_texformat_rgb565_rev
);
953 ASSERT(dstFormat
->TexelBytes
== 2);
955 if (!ctx
->_ImageTransferState
&&
956 !srcPacking
->SwapBytes
&&
957 dstFormat
== &_mesa_texformat_rgb565
&&
958 baseInternalFormat
== GL_RGB
&&
959 srcFormat
== GL_RGB
&&
960 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
961 /* simple memcpy path */
962 memcpy_texture(ctx
, dims
,
963 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
964 dstRowStride
, dstImageStride
,
965 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
966 srcAddr
, srcPacking
);
968 else if (!ctx
->_ImageTransferState
&&
969 !srcPacking
->SwapBytes
&&
970 baseInternalFormat
== GL_RGB
&&
971 srcFormat
== GL_RGB
&&
972 srcType
== GL_UNSIGNED_BYTE
&&
974 /* do optimized tex store */
975 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
977 const GLubyte
*src
= (const GLubyte
*)
978 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
979 srcFormat
, srcType
, 0, 0, 0);
980 GLubyte
*dst
= (GLubyte
*) dstAddr
981 + dstZoffset
* dstImageStride
982 + dstYoffset
* dstRowStride
983 + dstXoffset
* dstFormat
->TexelBytes
;
985 for (row
= 0; row
< srcHeight
; row
++) {
986 const GLubyte
*srcUB
= (const GLubyte
*) src
;
987 GLushort
*dstUS
= (GLushort
*) dst
;
988 /* check for byteswapped format */
989 if (dstFormat
== &_mesa_texformat_rgb565
) {
990 for (col
= 0; col
< srcWidth
; col
++) {
991 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
996 for (col
= 0; col
< srcWidth
; col
++) {
997 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1001 dst
+= dstRowStride
;
1002 src
+= srcRowStride
;
1007 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1009 dstFormat
->BaseFormat
,
1010 srcWidth
, srcHeight
, srcDepth
,
1011 srcFormat
, srcType
, srcAddr
,
1013 const GLchan
*src
= tempImage
;
1014 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1015 + dstZoffset
* dstImageStride
1016 + dstYoffset
* dstRowStride
1017 + dstXoffset
* dstFormat
->TexelBytes
;
1018 GLint img
, row
, col
;
1021 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1022 for (img
= 0; img
< srcDepth
; img
++) {
1023 GLubyte
*dstRow
= dstImage
;
1024 for (row
= 0; row
< srcHeight
; row
++) {
1025 GLushort
*dstUS
= (GLushort
*) dstRow
;
1026 /* check for byteswapped format */
1027 if (dstFormat
== &_mesa_texformat_rgb565
) {
1028 for (col
= 0; col
< srcWidth
; col
++) {
1029 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1030 CHAN_TO_UBYTE(src
[GCOMP
]),
1031 CHAN_TO_UBYTE(src
[BCOMP
]) );
1036 for (col
= 0; col
< srcWidth
; col
++) {
1037 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1038 CHAN_TO_UBYTE(src
[GCOMP
]),
1039 CHAN_TO_UBYTE(src
[BCOMP
]) );
1043 dstRow
+= dstRowStride
;
1045 dstImage
+= dstImageStride
;
1047 _mesa_free((void *) tempImage
);
1054 _mesa_texstore_rgba8888(STORE_PARAMS
)
1056 const GLuint ui
= 1;
1057 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1060 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1061 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1062 ASSERT(dstFormat
->TexelBytes
== 4);
1064 if (!ctx
->_ImageTransferState
&&
1065 !srcPacking
->SwapBytes
&&
1066 dstFormat
== &_mesa_texformat_rgba8888
&&
1067 baseInternalFormat
== GL_RGBA
&&
1068 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1069 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
1070 /* simple memcpy path */
1071 memcpy_texture(ctx
, dims
,
1072 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1073 dstRowStride
, dstImageStride
,
1074 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1075 srcAddr
, srcPacking
);
1078 else if (!ctx
->_ImageTransferState
&&
1079 !srcPacking
->SwapBytes
&&
1080 srcType
== GL_UNSIGNED_BYTE
&&
1081 dstFormat
== &_mesa_texformat_rgba8888
&&
1083 /* Three texture formats involved: srcFormat,
1084 * baseInternalFormat and destFormat (GL_RGBA). Only two
1085 * may differ. _mesa_swizzle_ubyte_image can't handle two
1086 * propagations at once correctly. */
1087 (srcFormat
== baseInternalFormat
||
1088 baseInternalFormat
== GL_RGBA
) &&
1089 can_swizzle(srcFormat
)) {
1092 /* dstmap - how to swizzle from GL_RGBA to dst format:
1094 * FIXME - add !litteEndian and _rev varients:
1101 _mesa_swizzle_ubyte_image(ctx
, dims
,
1104 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1105 dstRowStride
, dstImageStride
,
1106 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1112 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1114 dstFormat
->BaseFormat
,
1115 srcWidth
, srcHeight
, srcDepth
,
1116 srcFormat
, srcType
, srcAddr
,
1118 const GLchan
*src
= tempImage
;
1119 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1120 + dstZoffset
* dstImageStride
1121 + dstYoffset
* dstRowStride
1122 + dstXoffset
* dstFormat
->TexelBytes
;
1123 GLint img
, row
, col
;
1126 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1127 for (img
= 0; img
< srcDepth
; img
++) {
1128 GLubyte
*dstRow
= dstImage
;
1129 for (row
= 0; row
< srcHeight
; row
++) {
1130 GLuint
*dstUI
= (GLuint
*) dstRow
;
1131 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1132 for (col
= 0; col
< srcWidth
; col
++) {
1133 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1134 CHAN_TO_UBYTE(src
[GCOMP
]),
1135 CHAN_TO_UBYTE(src
[BCOMP
]),
1136 CHAN_TO_UBYTE(src
[ACOMP
]) );
1141 for (col
= 0; col
< srcWidth
; col
++) {
1142 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1143 CHAN_TO_UBYTE(src
[GCOMP
]),
1144 CHAN_TO_UBYTE(src
[BCOMP
]),
1145 CHAN_TO_UBYTE(src
[ACOMP
]) );
1149 dstRow
+= dstRowStride
;
1151 dstImage
+= dstImageStride
;
1153 _mesa_free((void *) tempImage
);
1160 _mesa_texstore_argb8888(STORE_PARAMS
)
1162 const GLuint ui
= 1;
1163 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1165 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1166 dstFormat
== &_mesa_texformat_argb8888_rev
);
1167 ASSERT(dstFormat
->TexelBytes
== 4);
1169 if (!ctx
->_ImageTransferState
&&
1170 !srcPacking
->SwapBytes
&&
1171 dstFormat
== &_mesa_texformat_argb8888
&&
1172 baseInternalFormat
== GL_RGBA
&&
1173 srcFormat
== GL_BGRA
&&
1174 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1175 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1176 /* simple memcpy path (little endian) */
1177 memcpy_texture(ctx
, dims
,
1178 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1179 dstRowStride
, dstImageStride
,
1180 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1181 srcAddr
, srcPacking
);
1183 else if (!ctx
->_ImageTransferState
&&
1184 !srcPacking
->SwapBytes
&&
1185 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1186 baseInternalFormat
== GL_RGBA
&&
1187 srcFormat
== GL_BGRA
&&
1188 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1189 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1190 /* simple memcpy path (big endian) */
1191 memcpy_texture(ctx
, dims
,
1192 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1193 dstRowStride
, dstImageStride
,
1194 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1195 srcAddr
, srcPacking
);
1197 else if (!ctx
->_ImageTransferState
&&
1198 !srcPacking
->SwapBytes
&&
1199 dstFormat
== &_mesa_texformat_argb8888
&&
1200 srcFormat
== GL_RGB
&&
1201 srcType
== GL_UNSIGNED_BYTE
) {
1204 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1205 + dstZoffset
* dstImageStride
1206 + dstYoffset
* dstRowStride
1207 + dstXoffset
* dstFormat
->TexelBytes
;
1208 for (img
= 0; img
< srcDepth
; img
++) {
1209 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1210 srcWidth
, srcFormat
, srcType
);
1211 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1212 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1213 GLubyte
*dstRow
= dstImage
;
1214 for (row
= 0; row
< srcHeight
; row
++) {
1215 for (col
= 0; col
< srcWidth
; col
++) {
1216 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1217 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1218 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1219 dstRow
[col
* 4 + 3] = 0xff;
1221 dstRow
+= dstRowStride
;
1222 srcRow
+= srcRowStride
;
1224 dstImage
+= dstImageStride
;
1227 else if (!ctx
->_ImageTransferState
&&
1228 !srcPacking
->SwapBytes
&&
1229 dstFormat
== &_mesa_texformat_argb8888
&&
1230 srcFormat
== GL_RGBA
&&
1231 srcType
== GL_UNSIGNED_BYTE
) {
1234 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1235 + dstZoffset
* dstImageStride
1236 + dstYoffset
* dstRowStride
1237 + dstXoffset
* dstFormat
->TexelBytes
;
1238 for (img
= 0; img
< srcDepth
; img
++) {
1239 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1240 srcWidth
, srcFormat
, srcType
);
1241 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1242 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1243 GLubyte
*dstRow
= dstImage
;
1244 for (row
= 0; row
< srcHeight
; row
++) {
1245 for (col
= 0; col
< srcWidth
; col
++) {
1246 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1247 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1248 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1249 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1251 dstRow
+= dstRowStride
;
1252 srcRow
+= srcRowStride
;
1254 dstImage
+= dstImageStride
;
1257 else if (!ctx
->_ImageTransferState
&&
1258 !srcPacking
->SwapBytes
&&
1259 dstFormat
== &_mesa_texformat_argb8888
&&
1260 srcType
== GL_UNSIGNED_BYTE
&&
1262 /* Three texture formats involved: srcFormat,
1263 * baseInternalFormat and destFormat (GL_RGBA). Only two
1264 * may differ. _mesa_swizzle_ubyte_image can't handle two
1265 * propagations at once correctly. */
1266 (srcFormat
== baseInternalFormat
||
1267 baseInternalFormat
== GL_RGBA
) &&
1268 can_swizzle(srcFormat
)) {
1272 /* dstmap - how to swizzle from GL_RGBA to dst format:
1274 dstmap
[3] = 3; /* alpha */
1275 dstmap
[2] = 0; /* red */
1276 dstmap
[1] = 1; /* green */
1277 dstmap
[0] = 2; /* blue */
1279 _mesa_swizzle_ubyte_image(ctx
, dims
,
1282 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1283 dstRowStride
, dstImageStride
,
1284 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1289 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1291 dstFormat
->BaseFormat
,
1292 srcWidth
, srcHeight
, srcDepth
,
1293 srcFormat
, srcType
, srcAddr
,
1295 const GLchan
*src
= tempImage
;
1296 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1297 + dstZoffset
* dstImageStride
1298 + dstYoffset
* dstRowStride
1299 + dstXoffset
* dstFormat
->TexelBytes
;
1300 GLint img
, row
, col
;
1303 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1304 for (img
= 0; img
< srcDepth
; img
++) {
1305 GLubyte
*dstRow
= dstImage
;
1306 for (row
= 0; row
< srcHeight
; row
++) {
1307 GLuint
*dstUI
= (GLuint
*) dstRow
;
1308 if (dstFormat
== &_mesa_texformat_argb8888
) {
1309 for (col
= 0; col
< srcWidth
; col
++) {
1310 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1311 CHAN_TO_UBYTE(src
[RCOMP
]),
1312 CHAN_TO_UBYTE(src
[GCOMP
]),
1313 CHAN_TO_UBYTE(src
[BCOMP
]) );
1318 for (col
= 0; col
< srcWidth
; col
++) {
1319 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1320 CHAN_TO_UBYTE(src
[RCOMP
]),
1321 CHAN_TO_UBYTE(src
[GCOMP
]),
1322 CHAN_TO_UBYTE(src
[BCOMP
]) );
1326 dstRow
+= dstRowStride
;
1328 dstImage
+= dstImageStride
;
1330 _mesa_free((void *) tempImage
);
1337 _mesa_texstore_rgb888(STORE_PARAMS
)
1339 const GLuint ui
= 1;
1340 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1342 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1343 ASSERT(dstFormat
->TexelBytes
== 3);
1345 if (!ctx
->_ImageTransferState
&&
1346 !srcPacking
->SwapBytes
&&
1347 baseInternalFormat
== GL_RGB
&&
1348 srcFormat
== GL_BGR
&&
1349 srcType
== GL_UNSIGNED_BYTE
&&
1351 /* simple memcpy path */
1352 memcpy_texture(ctx
, dims
,
1353 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1354 dstRowStride
, dstImageStride
,
1355 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1356 srcAddr
, srcPacking
);
1358 else if (!ctx
->_ImageTransferState
&&
1359 !srcPacking
->SwapBytes
&&
1360 srcFormat
== GL_RGBA
&&
1361 srcType
== GL_UNSIGNED_BYTE
) {
1362 /* extract RGB from RGBA */
1364 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1365 + dstZoffset
* dstImageStride
1366 + dstYoffset
* dstRowStride
1367 + dstXoffset
* dstFormat
->TexelBytes
;
1368 for (img
= 0; img
< srcDepth
; img
++) {
1369 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1370 srcWidth
, srcFormat
, srcType
);
1371 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1372 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1373 GLubyte
*dstRow
= dstImage
;
1374 for (row
= 0; row
< srcHeight
; row
++) {
1375 for (col
= 0; col
< srcWidth
; col
++) {
1376 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1377 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1378 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1380 dstRow
+= dstRowStride
;
1381 srcRow
+= srcRowStride
;
1383 dstImage
+= dstImageStride
;
1388 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1390 dstFormat
->BaseFormat
,
1391 srcWidth
, srcHeight
, srcDepth
,
1392 srcFormat
, srcType
, srcAddr
,
1394 const GLchan
*src
= (const GLchan
*) tempImage
;
1395 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1396 + dstZoffset
* dstImageStride
1397 + dstYoffset
* dstRowStride
1398 + dstXoffset
* dstFormat
->TexelBytes
;
1399 GLint img
, row
, col
;
1402 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1403 for (img
= 0; img
< srcDepth
; img
++) {
1404 GLubyte
*dstRow
= dstImage
;
1405 for (row
= 0; row
< srcHeight
; row
++) {
1408 for (col
= 0; col
< srcWidth
; col
++) {
1409 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1410 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1411 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1416 for (col
= 0; col
< srcWidth
; col
++) {
1417 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1418 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1419 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1424 for (col
= 0; col
< srcWidth
; col
++) {
1425 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1426 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1427 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1431 dstRow
+= dstRowStride
;
1433 dstImage
+= dstImageStride
;
1435 _mesa_free((void *) tempImage
);
1442 _mesa_texstore_bgr888(STORE_PARAMS
)
1444 const GLuint ui
= 1;
1445 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1447 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1448 ASSERT(dstFormat
->TexelBytes
== 3);
1450 if (!ctx
->_ImageTransferState
&&
1451 !srcPacking
->SwapBytes
&&
1452 baseInternalFormat
== GL_RGB
&&
1453 srcFormat
== GL_RGB
&&
1454 srcType
== GL_UNSIGNED_BYTE
&&
1456 /* simple memcpy path */
1457 memcpy_texture(ctx
, dims
,
1458 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1459 dstRowStride
, dstImageStride
,
1460 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1461 srcAddr
, srcPacking
);
1463 else if (!ctx
->_ImageTransferState
&&
1464 !srcPacking
->SwapBytes
&&
1465 srcFormat
== GL_RGBA
&&
1466 srcType
== GL_UNSIGNED_BYTE
) {
1467 /* extract BGR from RGBA */
1469 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1470 + dstZoffset
* dstImageStride
1471 + dstYoffset
* dstRowStride
1472 + dstXoffset
* dstFormat
->TexelBytes
;
1473 for (img
= 0; img
< srcDepth
; img
++) {
1474 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1475 srcWidth
, srcFormat
, srcType
);
1476 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1477 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1478 GLubyte
*dstRow
= dstImage
;
1479 for (row
= 0; row
< srcHeight
; row
++) {
1480 for (col
= 0; col
< srcWidth
; col
++) {
1481 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1482 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1483 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1485 dstRow
+= dstRowStride
;
1486 srcRow
+= srcRowStride
;
1488 dstImage
+= dstImageStride
;
1493 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1495 dstFormat
->BaseFormat
,
1496 srcWidth
, srcHeight
, srcDepth
,
1497 srcFormat
, srcType
, srcAddr
,
1499 const GLchan
*src
= (const GLchan
*) tempImage
;
1500 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1501 + dstZoffset
* dstImageStride
1502 + dstYoffset
* dstRowStride
1503 + dstXoffset
* dstFormat
->TexelBytes
;
1504 GLint img
, row
, col
;
1507 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1508 for (img
= 0; img
< srcDepth
; img
++) {
1509 GLubyte
*dstRow
= dstImage
;
1510 for (row
= 0; row
< srcHeight
; row
++) {
1511 for (col
= 0; col
< srcWidth
; col
++) {
1512 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1513 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1514 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1517 dstRow
+= dstRowStride
;
1519 dstImage
+= dstImageStride
;
1521 _mesa_free((void *) tempImage
);
1528 _mesa_texstore_argb4444(STORE_PARAMS
)
1530 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1531 dstFormat
== &_mesa_texformat_argb4444_rev
);
1532 ASSERT(dstFormat
->TexelBytes
== 2);
1534 if (!ctx
->_ImageTransferState
&&
1535 !srcPacking
->SwapBytes
&&
1536 dstFormat
== &_mesa_texformat_argb4444
&&
1537 baseInternalFormat
== GL_RGBA
&&
1538 srcFormat
== GL_BGRA
&&
1539 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1540 /* simple memcpy path */
1541 memcpy_texture(ctx
, dims
,
1542 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1543 dstRowStride
, dstImageStride
,
1544 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1545 srcAddr
, srcPacking
);
1549 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1551 dstFormat
->BaseFormat
,
1552 srcWidth
, srcHeight
, srcDepth
,
1553 srcFormat
, srcType
, srcAddr
,
1555 const GLchan
*src
= tempImage
;
1556 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1557 + dstZoffset
* dstImageStride
1558 + dstYoffset
* dstRowStride
1559 + dstXoffset
* dstFormat
->TexelBytes
;
1560 GLint img
, row
, col
;
1563 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1564 for (img
= 0; img
< srcDepth
; img
++) {
1565 GLubyte
*dstRow
= dstImage
;
1566 for (row
= 0; row
< srcHeight
; row
++) {
1567 GLushort
*dstUS
= (GLushort
*) dstRow
;
1568 if (dstFormat
== &_mesa_texformat_argb4444
) {
1569 for (col
= 0; col
< srcWidth
; col
++) {
1570 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1571 CHAN_TO_UBYTE(src
[RCOMP
]),
1572 CHAN_TO_UBYTE(src
[GCOMP
]),
1573 CHAN_TO_UBYTE(src
[BCOMP
]) );
1578 for (col
= 0; col
< srcWidth
; col
++) {
1579 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1580 CHAN_TO_UBYTE(src
[RCOMP
]),
1581 CHAN_TO_UBYTE(src
[GCOMP
]),
1582 CHAN_TO_UBYTE(src
[BCOMP
]) );
1586 dstRow
+= dstRowStride
;
1588 dstImage
+= dstImageStride
;
1590 _mesa_free((void *) tempImage
);
1598 _mesa_texstore_argb1555(STORE_PARAMS
)
1600 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1601 dstFormat
== &_mesa_texformat_argb1555_rev
);
1602 ASSERT(dstFormat
->TexelBytes
== 2);
1604 if (!ctx
->_ImageTransferState
&&
1605 !srcPacking
->SwapBytes
&&
1606 dstFormat
== &_mesa_texformat_argb1555
&&
1607 baseInternalFormat
== GL_RGBA
&&
1608 srcFormat
== GL_BGRA
&&
1609 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1610 /* simple memcpy path */
1611 memcpy_texture(ctx
, dims
,
1612 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1613 dstRowStride
, dstImageStride
,
1614 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1615 srcAddr
, srcPacking
);
1619 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1621 dstFormat
->BaseFormat
,
1622 srcWidth
, srcHeight
, srcDepth
,
1623 srcFormat
, srcType
, srcAddr
,
1625 const GLchan
*src
=tempImage
;
1626 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1627 + dstZoffset
* dstImageStride
1628 + dstYoffset
* dstRowStride
1629 + dstXoffset
* dstFormat
->TexelBytes
;
1630 GLint img
, row
, col
;
1633 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1634 for (img
= 0; img
< srcDepth
; img
++) {
1635 GLubyte
*dstRow
= dstImage
;
1636 for (row
= 0; row
< srcHeight
; row
++) {
1637 GLushort
*dstUS
= (GLushort
*) dstRow
;
1638 if (dstFormat
== &_mesa_texformat_argb1555
) {
1639 for (col
= 0; col
< srcWidth
; col
++) {
1640 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1641 CHAN_TO_UBYTE(src
[RCOMP
]),
1642 CHAN_TO_UBYTE(src
[GCOMP
]),
1643 CHAN_TO_UBYTE(src
[BCOMP
]) );
1648 for (col
= 0; col
< srcWidth
; col
++) {
1649 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1650 CHAN_TO_UBYTE(src
[RCOMP
]),
1651 CHAN_TO_UBYTE(src
[GCOMP
]),
1652 CHAN_TO_UBYTE(src
[BCOMP
]) );
1656 dstRow
+= dstRowStride
;
1658 dstImage
+= dstImageStride
;
1660 _mesa_free((void *) tempImage
);
1667 _mesa_texstore_al88(STORE_PARAMS
)
1669 const GLuint ui
= 1;
1670 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1672 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1673 dstFormat
== &_mesa_texformat_al88_rev
);
1674 ASSERT(dstFormat
->TexelBytes
== 2);
1676 if (!ctx
->_ImageTransferState
&&
1677 !srcPacking
->SwapBytes
&&
1678 dstFormat
== &_mesa_texformat_al88
&&
1679 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1680 srcFormat
== GL_LUMINANCE_ALPHA
&&
1681 srcType
== GL_UNSIGNED_BYTE
&&
1683 /* simple memcpy path */
1684 memcpy_texture(ctx
, dims
,
1685 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1686 dstRowStride
, dstImageStride
,
1687 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1688 srcAddr
, srcPacking
);
1692 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1694 dstFormat
->BaseFormat
,
1695 srcWidth
, srcHeight
, srcDepth
,
1696 srcFormat
, srcType
, srcAddr
,
1698 const GLchan
*src
= tempImage
;
1699 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1700 + dstZoffset
* dstImageStride
1701 + dstYoffset
* dstRowStride
1702 + dstXoffset
* dstFormat
->TexelBytes
;
1703 GLint img
, row
, col
;
1706 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1707 for (img
= 0; img
< srcDepth
; img
++) {
1708 GLubyte
*dstRow
= dstImage
;
1709 for (row
= 0; row
< srcHeight
; row
++) {
1710 GLushort
*dstUS
= (GLushort
*) dstRow
;
1711 if (dstFormat
== &_mesa_texformat_al88
) {
1712 for (col
= 0; col
< srcWidth
; col
++) {
1713 /* src[0] is luminance, src[1] is alpha */
1714 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1715 CHAN_TO_UBYTE(src
[0]) );
1720 for (col
= 0; col
< srcWidth
; col
++) {
1721 /* src[0] is luminance, src[1] is alpha */
1722 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1723 CHAN_TO_UBYTE(src
[0]) );
1727 dstRow
+= dstRowStride
;
1729 dstImage
+= dstImageStride
;
1731 _mesa_free((void *) tempImage
);
1738 _mesa_texstore_rgb332(STORE_PARAMS
)
1740 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1741 ASSERT(dstFormat
->TexelBytes
== 1);
1743 if (!ctx
->_ImageTransferState
&&
1744 !srcPacking
->SwapBytes
&&
1745 baseInternalFormat
== GL_RGB
&&
1746 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1747 /* simple memcpy path */
1748 memcpy_texture(ctx
, dims
,
1749 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1750 dstRowStride
, dstImageStride
,
1751 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1752 srcAddr
, srcPacking
);
1756 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1758 dstFormat
->BaseFormat
,
1759 srcWidth
, srcHeight
, srcDepth
,
1760 srcFormat
, srcType
, srcAddr
,
1762 const GLchan
*src
= tempImage
;
1763 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1764 + dstZoffset
* dstImageStride
1765 + dstYoffset
* dstRowStride
1766 + dstXoffset
* dstFormat
->TexelBytes
;
1767 GLint img
, row
, col
;
1770 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1771 for (img
= 0; img
< srcDepth
; img
++) {
1772 GLubyte
*dstRow
= dstImage
;
1773 for (row
= 0; row
< srcHeight
; row
++) {
1774 for (col
= 0; col
< srcWidth
; col
++) {
1775 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1776 CHAN_TO_UBYTE(src
[GCOMP
]),
1777 CHAN_TO_UBYTE(src
[BCOMP
]) );
1780 dstRow
+= dstRowStride
;
1782 dstImage
+= dstImageStride
;
1784 _mesa_free((void *) tempImage
);
1791 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1794 _mesa_texstore_a8(STORE_PARAMS
)
1796 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1797 dstFormat
== &_mesa_texformat_l8
||
1798 dstFormat
== &_mesa_texformat_i8
);
1799 ASSERT(dstFormat
->TexelBytes
== 1);
1801 if (!ctx
->_ImageTransferState
&&
1802 !srcPacking
->SwapBytes
&&
1803 baseInternalFormat
== srcFormat
&&
1804 srcType
== GL_UNSIGNED_BYTE
) {
1805 /* simple memcpy path */
1806 memcpy_texture(ctx
, dims
,
1807 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1808 dstRowStride
, dstImageStride
,
1809 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1810 srcAddr
, srcPacking
);
1814 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1816 dstFormat
->BaseFormat
,
1817 srcWidth
, srcHeight
, srcDepth
,
1818 srcFormat
, srcType
, srcAddr
,
1820 const GLchan
*src
= tempImage
;
1821 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1822 + dstZoffset
* dstImageStride
1823 + dstYoffset
* dstRowStride
1824 + dstXoffset
* dstFormat
->TexelBytes
;
1825 GLint img
, row
, col
;
1828 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1829 for (img
= 0; img
< srcDepth
; img
++) {
1830 GLubyte
*dstRow
= dstImage
;
1831 for (row
= 0; row
< srcHeight
; row
++) {
1832 for (col
= 0; col
< srcWidth
; col
++) {
1833 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1835 dstRow
+= dstRowStride
;
1838 dstImage
+= dstImageStride
;
1840 _mesa_free((void *) tempImage
);
1848 _mesa_texstore_ci8(STORE_PARAMS
)
1850 (void) dims
; (void) baseInternalFormat
;
1851 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1852 ASSERT(dstFormat
->TexelBytes
== 1);
1853 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1855 if (!ctx
->_ImageTransferState
&&
1856 !srcPacking
->SwapBytes
&&
1857 srcFormat
== GL_COLOR_INDEX
&&
1858 srcType
== GL_UNSIGNED_BYTE
) {
1859 /* simple memcpy path */
1860 memcpy_texture(ctx
, dims
,
1861 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1862 dstRowStride
, dstImageStride
,
1863 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1864 srcAddr
, srcPacking
);
1868 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1869 + dstZoffset
* dstImageStride
1870 + dstYoffset
* dstRowStride
1871 + dstXoffset
* dstFormat
->TexelBytes
;
1873 for (img
= 0; img
< srcDepth
; img
++) {
1874 GLubyte
*dstRow
= dstImage
;
1875 for (row
= 0; row
< srcHeight
; row
++) {
1876 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1877 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1878 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1879 srcType
, src
, srcPacking
,
1880 ctx
->_ImageTransferState
);
1881 dstRow
+= dstRowStride
;
1883 dstImage
+= dstImageStride
;
1891 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1894 _mesa_texstore_ycbcr(STORE_PARAMS
)
1896 const GLuint ui
= 1;
1897 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1898 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
1900 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1901 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1902 ASSERT(dstFormat
->TexelBytes
== 2);
1903 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1904 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1905 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1906 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1907 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1909 /* always just memcpy since no pixel transfer ops apply */
1910 memcpy_texture(ctx
, dims
,
1911 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1912 dstRowStride
, dstImageStride
,
1913 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1914 srcAddr
, srcPacking
);
1916 /* Check if we need byte swapping */
1917 /* XXX the logic here _might_ be wrong */
1918 if (srcPacking
->SwapBytes
^
1919 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1920 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1922 GLushort
*pImage
= (GLushort
*) ((GLubyte
*) dstAddr
1923 + dstZoffset
* dstImageStride
1924 + dstYoffset
* dstRowStride
1925 + dstXoffset
* dstFormat
->TexelBytes
);
1927 for (img
= 0; img
< srcDepth
; img
++) {
1928 GLushort
*pRow
= pImage
;
1929 for (row
= 0; row
< srcHeight
; row
++) {
1930 _mesa_swap2(pRow
, srcWidth
);
1931 pRow
+= dstRowStride
;
1933 pImage
+= dstImageStride
;
1943 * Store an image in any of the formats:
1944 * _mesa_texformat_rgba_float32
1945 * _mesa_texformat_rgb_float32
1946 * _mesa_texformat_alpha_float32
1947 * _mesa_texformat_luminance_float32
1948 * _mesa_texformat_luminance_alpha_float32
1949 * _mesa_texformat_intensity_float32
1952 _mesa_texstore_rgba_float32(STORE_PARAMS
)
1954 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1956 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
1957 dstFormat
== &_mesa_texformat_rgb_float32
||
1958 dstFormat
== &_mesa_texformat_alpha_float32
||
1959 dstFormat
== &_mesa_texformat_luminance_float32
||
1960 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
1961 dstFormat
== &_mesa_texformat_intensity_float32
);
1962 ASSERT(baseInternalFormat
== GL_RGBA
||
1963 baseInternalFormat
== GL_RGB
||
1964 baseInternalFormat
== GL_ALPHA
||
1965 baseInternalFormat
== GL_LUMINANCE
||
1966 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1967 baseInternalFormat
== GL_INTENSITY
);
1968 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
1970 if (!ctx
->_ImageTransferState
&&
1971 !srcPacking
->SwapBytes
&&
1972 baseInternalFormat
== srcFormat
&&
1973 srcType
== GL_FLOAT
) {
1974 /* simple memcpy path */
1975 memcpy_texture(ctx
, dims
,
1976 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1977 dstRowStride
, dstImageStride
,
1978 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1979 srcAddr
, srcPacking
);
1983 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1985 dstFormat
->BaseFormat
,
1986 srcWidth
, srcHeight
, srcDepth
,
1987 srcFormat
, srcType
, srcAddr
,
1989 const GLfloat
*src
= tempImage
;
1991 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1992 + dstZoffset
* dstImageStride
1993 + dstYoffset
* dstRowStride
1994 + dstXoffset
* dstFormat
->TexelBytes
;
1998 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1999 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2000 for (img
= 0; img
< srcDepth
; img
++) {
2001 GLubyte
*dst
= dstImage
;
2002 for (row
= 0; row
< srcHeight
; row
++) {
2003 _mesa_memcpy(dst
, src
, bytesPerRow
);
2004 dst
+= dstRowStride
;
2005 src
+= srcWidth
* components
;
2007 dstImage
+= dstImageStride
;
2010 _mesa_free((void *) tempImage
);
2017 * As above, but store 16-bit floats.
2020 _mesa_texstore_rgba_float16(STORE_PARAMS
)
2022 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
2024 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2025 dstFormat
== &_mesa_texformat_rgb_float16
||
2026 dstFormat
== &_mesa_texformat_alpha_float16
||
2027 dstFormat
== &_mesa_texformat_luminance_float16
||
2028 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2029 dstFormat
== &_mesa_texformat_intensity_float16
);
2030 ASSERT(baseInternalFormat
== GL_RGBA
||
2031 baseInternalFormat
== GL_RGB
||
2032 baseInternalFormat
== GL_ALPHA
||
2033 baseInternalFormat
== GL_LUMINANCE
||
2034 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2035 baseInternalFormat
== GL_INTENSITY
);
2036 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2038 if (!ctx
->_ImageTransferState
&&
2039 !srcPacking
->SwapBytes
&&
2040 baseInternalFormat
== srcFormat
&&
2041 srcType
== GL_HALF_FLOAT_ARB
) {
2042 /* simple memcpy path */
2043 memcpy_texture(ctx
, dims
,
2044 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2045 dstRowStride
, dstImageStride
,
2046 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2047 srcAddr
, srcPacking
);
2051 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2053 dstFormat
->BaseFormat
,
2054 srcWidth
, srcHeight
, srcDepth
,
2055 srcFormat
, srcType
, srcAddr
,
2057 const GLfloat
*src
= tempImage
;
2058 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2059 + dstZoffset
* dstImageStride
2060 + dstYoffset
* dstRowStride
2061 + dstXoffset
* dstFormat
->TexelBytes
;
2065 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2066 for (img
= 0; img
< srcDepth
; img
++) {
2067 GLubyte
*dstRow
= dstImage
;
2068 for (row
= 0; row
< srcHeight
; row
++) {
2069 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2071 for (i
= 0; i
< srcWidth
* components
; i
++) {
2072 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2074 dstRow
+= dstRowStride
;
2075 src
+= srcWidth
* components
;
2077 dstImage
+= dstImageStride
;
2080 _mesa_free((void *) tempImage
);
2088 * Check if an unpack PBO is active prior to fetching a texture image.
2089 * If so, do bounds checking and map the buffer into main memory.
2090 * Any errors detected will be recorded.
2091 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2094 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2095 GLsizei width
, GLsizei height
, GLsizei depth
,
2096 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2097 const struct gl_pixelstore_attrib
*unpack
,
2098 const char *funcName
)
2102 if (unpack
->BufferObj
->Name
== 0) {
2106 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2107 format
, type
, pixels
)) {
2108 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2112 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2113 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2115 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2119 return ADD_POINTERS(buf
, pixels
);
2124 * Check if an unpack PBO is active prior to fetching a compressed texture
2126 * If so, do bounds checking and map the buffer into main memory.
2127 * Any errors detected will be recorded.
2128 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2131 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2132 GLsizei imageSize
, const GLvoid
*pixels
,
2133 const struct gl_pixelstore_attrib
*packing
,
2134 const char *funcName
)
2138 if (packing
->BufferObj
->Name
== 0) {
2139 /* not using a PBO - return pointer unchanged */
2142 if ((const GLubyte
*) pixels
+ imageSize
>
2143 (const GLubyte
*)(uintptr_t) packing
->BufferObj
->Size
) {
2144 /* out of bounds read! */
2145 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2149 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2150 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2152 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2156 return ADD_POINTERS(buf
, pixels
);
2161 * This function must be called after either of the validate_pbo_*_teximage()
2162 * functions. It unmaps the PBO buffer if it was mapped earlier.
2165 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2166 const struct gl_pixelstore_attrib
*unpack
)
2168 if (unpack
->BufferObj
->Name
) {
2169 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2176 * This is the software fallback for Driver.TexImage1D()
2177 * and Driver.CopyTexImage1D().
2178 * \sa _mesa_store_teximage2d()
2181 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2182 GLint internalFormat
,
2183 GLint width
, GLint border
,
2184 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2185 const struct gl_pixelstore_attrib
*packing
,
2186 struct gl_texture_object
*texObj
,
2187 struct gl_texture_image
*texImage
)
2189 GLint postConvWidth
= width
;
2193 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2194 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2197 /* choose the texture format */
2198 assert(ctx
->Driver
.ChooseTextureFormat
);
2199 texImage
->TexFormat
= ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
,
2201 assert(texImage
->TexFormat
);
2202 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2203 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2205 /* allocate memory */
2206 if (texImage
->IsCompressed
)
2207 sizeInBytes
= texImage
->CompressedSize
;
2209 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2210 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2211 if (!texImage
->Data
) {
2212 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2216 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2217 pixels
, packing
, "glTexImage1D");
2219 /* Note: we check for a NULL image pointer here, _after_ we allocated
2220 * memory for the texture. That's what the GL spec calls for.
2225 const GLint dstRowStride
= 0, dstImageStride
= 0;
2227 ASSERT(texImage
->TexFormat
->StoreImage
);
2228 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2229 texImage
->TexFormat
,
2231 0, 0, 0, /* dstX/Y/Zoffset */
2232 dstRowStride
, dstImageStride
,
2234 format
, type
, pixels
, packing
);
2236 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2240 /* GL_SGIS_generate_mipmap */
2241 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2242 _mesa_generate_mipmap(ctx
, target
,
2243 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2247 _mesa_unmap_teximage_pbo(ctx
, packing
);
2252 * This is the software fallback for Driver.TexImage2D()
2253 * and Driver.CopyTexImage2D().
2254 * We store the image in heap memory. We know nothing about on-board
2255 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2256 * textures in main memory, this routine will typically be used by
2257 * hardware drivers too.
2259 * Reasons why a driver might override this function:
2260 * - Special memory allocation needs (VRAM, AGP, etc)
2261 * - Unusual row/image strides or padding
2262 * - Special housekeeping
2263 * - Using VRAM-based Pixel Buffer Objects
2266 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2267 GLint internalFormat
,
2268 GLint width
, GLint height
, GLint border
,
2269 GLenum format
, GLenum type
, const void *pixels
,
2270 const struct gl_pixelstore_attrib
*packing
,
2271 struct gl_texture_object
*texObj
,
2272 struct gl_texture_image
*texImage
)
2274 GLint postConvWidth
= width
, postConvHeight
= height
;
2275 GLint texelBytes
, sizeInBytes
;
2278 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2279 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2283 /* choose the texture format */
2284 assert(ctx
->Driver
.ChooseTextureFormat
);
2285 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2286 internalFormat
, format
, type
);
2287 assert(texImage
->TexFormat
);
2288 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2289 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2291 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2293 /* allocate memory */
2294 if (texImage
->IsCompressed
)
2295 sizeInBytes
= texImage
->CompressedSize
;
2297 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2298 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2299 if (!texImage
->Data
) {
2300 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2304 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2305 pixels
, packing
, "glTexImage2D");
2307 /* Note: we check for a NULL image pointer here, _after_ we allocated
2308 * memory for the texture. That's what the GL spec calls for.
2313 GLint dstRowStride
, dstImageStride
= 0;
2315 if (texImage
->IsCompressed
) {
2316 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2319 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2321 ASSERT(texImage
->TexFormat
->StoreImage
);
2322 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2323 texImage
->TexFormat
,
2325 0, 0, 0, /* dstX/Y/Zoffset */
2326 dstRowStride
, dstImageStride
,
2328 format
, type
, pixels
, packing
);
2330 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2334 /* GL_SGIS_generate_mipmap */
2335 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2336 _mesa_generate_mipmap(ctx
, target
,
2337 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2341 _mesa_unmap_teximage_pbo(ctx
, packing
);
2347 * This is the software fallback for Driver.TexImage3D()
2348 * and Driver.CopyTexImage3D().
2349 * \sa _mesa_store_teximage2d()
2352 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2353 GLint internalFormat
,
2354 GLint width
, GLint height
, GLint depth
, GLint border
,
2355 GLenum format
, GLenum type
, const void *pixels
,
2356 const struct gl_pixelstore_attrib
*packing
,
2357 struct gl_texture_object
*texObj
,
2358 struct gl_texture_image
*texImage
)
2360 GLint texelBytes
, sizeInBytes
;
2363 /* choose the texture format */
2364 assert(ctx
->Driver
.ChooseTextureFormat
);
2365 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2366 internalFormat
, format
, type
);
2367 assert(texImage
->TexFormat
);
2368 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2369 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2371 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2373 /* allocate memory */
2374 if (texImage
->IsCompressed
)
2375 sizeInBytes
= texImage
->CompressedSize
;
2377 sizeInBytes
= width
* height
* depth
* texelBytes
;
2378 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2379 if (!texImage
->Data
) {
2380 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2384 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2385 type
, pixels
, packing
, "glTexImage3D");
2387 /* Note: we check for a NULL image pointer here, _after_ we allocated
2388 * memory for the texture. That's what the GL spec calls for.
2393 GLint dstRowStride
, dstImageStride
;
2395 if (texImage
->IsCompressed
) {
2396 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2400 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2401 dstImageStride
= dstRowStride
* height
;
2403 ASSERT(texImage
->TexFormat
->StoreImage
);
2404 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2405 texImage
->TexFormat
,
2407 0, 0, 0, /* dstX/Y/Zoffset */
2408 dstRowStride
, dstImageStride
,
2409 width
, height
, depth
,
2410 format
, type
, pixels
, packing
);
2412 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2416 /* GL_SGIS_generate_mipmap */
2417 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2418 _mesa_generate_mipmap(ctx
, target
,
2419 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2423 _mesa_unmap_teximage_pbo(ctx
, packing
);
2430 * This is the software fallback for Driver.TexSubImage1D()
2431 * and Driver.CopyTexSubImage1D().
2434 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2435 GLint xoffset
, GLint width
,
2436 GLenum format
, GLenum type
, const void *pixels
,
2437 const struct gl_pixelstore_attrib
*packing
,
2438 struct gl_texture_object
*texObj
,
2439 struct gl_texture_image
*texImage
)
2441 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2442 pixels
, packing
, "glTexSubImage1D");
2447 const GLint dstRowStride
= 0, dstImageStride
= 0;
2449 ASSERT(texImage
->TexFormat
->StoreImage
);
2450 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2451 texImage
->TexFormat
,
2453 xoffset
, 0, 0, /* offsets */
2454 dstRowStride
, dstImageStride
,
2456 format
, type
, pixels
, packing
);
2458 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2462 /* GL_SGIS_generate_mipmap */
2463 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2464 _mesa_generate_mipmap(ctx
, target
,
2465 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2469 _mesa_unmap_teximage_pbo(ctx
, packing
);
2475 * This is the software fallback for Driver.TexSubImage2D()
2476 * and Driver.CopyTexSubImage2D().
2479 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2480 GLint xoffset
, GLint yoffset
,
2481 GLint width
, GLint height
,
2482 GLenum format
, GLenum type
, const void *pixels
,
2483 const struct gl_pixelstore_attrib
*packing
,
2484 struct gl_texture_object
*texObj
,
2485 struct gl_texture_image
*texImage
)
2487 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2488 pixels
, packing
, "glTexSubImage2D");
2493 GLint dstRowStride
= 0, dstImageStride
= 0;
2495 if (texImage
->IsCompressed
) {
2496 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2500 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2502 ASSERT(texImage
->TexFormat
->StoreImage
);
2503 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2504 texImage
->TexFormat
,
2506 xoffset
, yoffset
, 0,
2507 dstRowStride
, dstImageStride
,
2509 format
, type
, pixels
, packing
);
2511 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2515 /* GL_SGIS_generate_mipmap */
2516 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2517 _mesa_generate_mipmap(ctx
, target
,
2518 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2522 _mesa_unmap_teximage_pbo(ctx
, packing
);
2527 * This is the software fallback for Driver.TexSubImage3D().
2528 * and Driver.CopyTexSubImage3D().
2531 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2532 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2533 GLint width
, GLint height
, GLint depth
,
2534 GLenum format
, GLenum type
, const void *pixels
,
2535 const struct gl_pixelstore_attrib
*packing
,
2536 struct gl_texture_object
*texObj
,
2537 struct gl_texture_image
*texImage
)
2539 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2540 type
, pixels
, packing
,
2546 GLint dstRowStride
, dstImageStride
;
2548 if (texImage
->IsCompressed
) {
2549 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2551 dstImageStride
= 0; /* XXX fix */
2554 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2555 dstImageStride
= dstRowStride
* texImage
->Height
;
2557 ASSERT(texImage
->TexFormat
->StoreImage
);
2558 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2559 texImage
->TexFormat
,
2561 xoffset
, yoffset
, zoffset
,
2562 dstRowStride
, dstImageStride
,
2563 width
, height
, depth
,
2564 format
, type
, pixels
, packing
);
2566 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2570 /* GL_SGIS_generate_mipmap */
2571 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2572 _mesa_generate_mipmap(ctx
, target
,
2573 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2577 _mesa_unmap_teximage_pbo(ctx
, packing
);
2582 * Fallback for Driver.CompressedTexImage1D()
2585 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2586 GLint internalFormat
,
2587 GLint width
, GLint border
,
2588 GLsizei imageSize
, const GLvoid
*data
,
2589 struct gl_texture_object
*texObj
,
2590 struct gl_texture_image
*texImage
)
2592 /* this space intentionally left blank */
2594 (void) target
; (void) level
;
2595 (void) internalFormat
;
2596 (void) width
; (void) border
;
2597 (void) imageSize
; (void) data
;
2605 * Fallback for Driver.CompressedTexImage2D()
2608 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2609 GLint internalFormat
,
2610 GLint width
, GLint height
, GLint border
,
2611 GLsizei imageSize
, const GLvoid
*data
,
2612 struct gl_texture_object
*texObj
,
2613 struct gl_texture_image
*texImage
)
2615 (void) width
; (void) height
; (void) border
;
2617 /* This is pretty simple, basically just do a memcpy without worrying
2618 * about the usual image unpacking or image transfer operations.
2622 ASSERT(texImage
->Width
> 0);
2623 ASSERT(texImage
->Height
> 0);
2624 ASSERT(texImage
->Depth
== 1);
2625 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2627 /* choose the texture format */
2628 assert(ctx
->Driver
.ChooseTextureFormat
);
2629 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2630 internalFormat
, 0, 0);
2631 assert(texImage
->TexFormat
);
2632 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2633 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2635 /* allocate storage */
2636 texImage
->Data
= MESA_PBUFFER_ALLOC(imageSize
);
2637 if (!texImage
->Data
) {
2638 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2642 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2644 "glCompressedTexImage2D");
2649 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2650 MEMCPY(texImage
->Data
, data
, imageSize
);
2652 /* GL_SGIS_generate_mipmap */
2653 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2654 _mesa_generate_mipmap(ctx
, target
,
2655 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2659 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2665 * Fallback for Driver.CompressedTexImage3D()
2668 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2669 GLint internalFormat
,
2670 GLint width
, GLint height
, GLint depth
,
2672 GLsizei imageSize
, const GLvoid
*data
,
2673 struct gl_texture_object
*texObj
,
2674 struct gl_texture_image
*texImage
)
2676 /* this space intentionally left blank */
2678 (void) target
; (void) level
;
2679 (void) internalFormat
;
2680 (void) width
; (void) height
; (void) depth
;
2682 (void) imageSize
; (void) data
;
2690 * Fallback for Driver.CompressedTexSubImage1D()
2693 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2695 GLint xoffset
, GLsizei width
,
2697 GLsizei imageSize
, const GLvoid
*data
,
2698 struct gl_texture_object
*texObj
,
2699 struct gl_texture_image
*texImage
)
2701 /* this space intentionally left blank */
2703 (void) target
; (void) level
;
2704 (void) xoffset
; (void) width
;
2706 (void) imageSize
; (void) data
;
2713 * Fallback for Driver.CompressedTexSubImage2D()
2716 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2718 GLint xoffset
, GLint yoffset
,
2719 GLsizei width
, GLsizei height
,
2721 GLsizei imageSize
, const GLvoid
*data
,
2722 struct gl_texture_object
*texObj
,
2723 struct gl_texture_image
*texImage
)
2725 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2731 /* these should have been caught sooner */
2732 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2733 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2734 ASSERT((xoffset
& 3) == 0);
2735 ASSERT((yoffset
& 3) == 0);
2737 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2739 "glCompressedTexSubImage2D");
2743 srcRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
, width
);
2744 src
= (const GLubyte
*) data
;
2746 destRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2748 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2749 texImage
->IntFormat
,
2751 (GLubyte
*) texImage
->Data
);
2753 bytesPerRow
= srcRowStride
;
2756 for (i
= 0; i
< rows
; i
++) {
2757 MEMCPY(dest
, src
, bytesPerRow
);
2758 dest
+= destRowStride
;
2759 src
+= srcRowStride
;
2762 /* GL_SGIS_generate_mipmap */
2763 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2764 _mesa_generate_mipmap(ctx
, target
,
2765 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2769 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2774 * Fallback for Driver.CompressedTexSubImage3D()
2777 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2779 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2780 GLsizei width
, GLsizei height
, GLsizei depth
,
2782 GLsizei imageSize
, const GLvoid
*data
,
2783 struct gl_texture_object
*texObj
,
2784 struct gl_texture_image
*texImage
)
2786 /* this space intentionally left blank */
2788 (void) target
; (void) level
;
2789 (void) xoffset
; (void) yoffset
; (void) zoffset
;
2790 (void) width
; (void) height
; (void) depth
;
2792 (void) imageSize
; (void) data
;
2799 * Average together two rows of a source image to produce a single new
2800 * row in the dest image. It's legal for the two source rows to point
2801 * to the same data. The source width must be equal to either the
2802 * dest width or two times the dest width.
2805 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
2806 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
2807 GLint dstWidth
, GLvoid
*dstRow
)
2809 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
2810 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
2812 /* This assertion is no longer valid with non-power-of-2 textures
2813 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2816 switch (format
->MesaFormat
) {
2817 case MESA_FORMAT_RGBA
:
2820 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
2821 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
2822 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
2823 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2824 i
++, j
+= colStride
, k
+= colStride
) {
2825 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2826 rowB
[j
][0] + rowB
[k
][0]) / 4;
2827 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2828 rowB
[j
][1] + rowB
[k
][1]) / 4;
2829 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2830 rowB
[j
][2] + rowB
[k
][2]) / 4;
2831 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2832 rowB
[j
][3] + rowB
[k
][3]) / 4;
2836 case MESA_FORMAT_RGB
:
2839 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
2840 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
2841 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
2842 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2843 i
++, j
+= colStride
, k
+= colStride
) {
2844 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2845 rowB
[j
][0] + rowB
[k
][0]) / 4;
2846 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2847 rowB
[j
][1] + rowB
[k
][1]) / 4;
2848 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2849 rowB
[j
][2] + rowB
[k
][2]) / 4;
2853 case MESA_FORMAT_ALPHA
:
2854 case MESA_FORMAT_LUMINANCE
:
2855 case MESA_FORMAT_INTENSITY
:
2858 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
2859 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
2860 GLchan
*dst
= (GLchan
*) dstRow
;
2861 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2862 i
++, j
+= colStride
, k
+= colStride
) {
2863 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2867 case MESA_FORMAT_LUMINANCE_ALPHA
:
2870 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
2871 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
2872 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
2873 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2874 i
++, j
+= colStride
, k
+= colStride
) {
2875 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2876 rowB
[j
][0] + rowB
[k
][0]) / 4;
2877 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2878 rowB
[j
][1] + rowB
[k
][1]) / 4;
2882 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32
:
2885 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2886 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2887 GLfloat
*dst
= (GLfloat
*) dstRow
;
2888 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2889 i
++, j
+= colStride
, k
+= colStride
) {
2890 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
2894 case MESA_FORMAT_DEPTH_COMPONENT16
:
2897 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2898 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2899 GLushort
*dst
= (GLushort
*) dstRow
;
2900 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2901 i
++, j
+= colStride
, k
+= colStride
) {
2902 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2906 /* Begin hardware formats */
2907 case MESA_FORMAT_RGBA8888
:
2908 case MESA_FORMAT_RGBA8888_REV
:
2909 case MESA_FORMAT_ARGB8888
:
2910 case MESA_FORMAT_ARGB8888_REV
:
2913 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
2914 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
2915 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
2916 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2917 i
++, j
+= colStride
, k
+= colStride
) {
2918 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2919 rowB
[j
][0] + rowB
[k
][0]) / 4;
2920 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2921 rowB
[j
][1] + rowB
[k
][1]) / 4;
2922 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2923 rowB
[j
][2] + rowB
[k
][2]) / 4;
2924 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2925 rowB
[j
][3] + rowB
[k
][3]) / 4;
2929 case MESA_FORMAT_RGB888
:
2930 case MESA_FORMAT_BGR888
:
2933 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
2934 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
2935 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
2936 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2937 i
++, j
+= colStride
, k
+= colStride
) {
2938 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2939 rowB
[j
][0] + rowB
[k
][0]) / 4;
2940 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2941 rowB
[j
][1] + rowB
[k
][1]) / 4;
2942 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2943 rowB
[j
][2] + rowB
[k
][2]) / 4;
2947 case MESA_FORMAT_RGB565
:
2948 case MESA_FORMAT_RGB565_REV
:
2951 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2952 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2953 GLushort
*dst
= (GLushort
*) dstRow
;
2954 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2955 i
++, j
+= colStride
, k
+= colStride
) {
2956 const GLint rowAr0
= rowA
[j
] & 0x1f;
2957 const GLint rowAr1
= rowA
[k
] & 0x1f;
2958 const GLint rowBr0
= rowB
[j
] & 0x1f;
2959 const GLint rowBr1
= rowB
[k
] & 0x1f;
2960 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
2961 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
2962 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
2963 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
2964 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
2965 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
2966 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
2967 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
2968 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2969 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2970 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2971 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
2975 case MESA_FORMAT_ARGB4444
:
2976 case MESA_FORMAT_ARGB4444_REV
:
2979 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2980 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2981 GLushort
*dst
= (GLushort
*) dstRow
;
2982 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2983 i
++, j
+= colStride
, k
+= colStride
) {
2984 const GLint rowAr0
= rowA
[j
] & 0xf;
2985 const GLint rowAr1
= rowA
[k
] & 0xf;
2986 const GLint rowBr0
= rowB
[j
] & 0xf;
2987 const GLint rowBr1
= rowB
[k
] & 0xf;
2988 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
2989 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
2990 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
2991 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
2992 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
2993 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
2994 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
2995 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
2996 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
2997 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
2998 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
2999 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
3000 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3001 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3002 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3003 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3004 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
3008 case MESA_FORMAT_ARGB1555
:
3009 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
3012 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3013 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3014 GLushort
*dst
= (GLushort
*) dstRow
;
3015 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3016 i
++, j
+= colStride
, k
+= colStride
) {
3017 const GLint rowAr0
= rowA
[j
] & 0x1f;
3018 const GLint rowAr1
= rowA
[k
] & 0x1f;
3019 const GLint rowBr0
= rowB
[j
] & 0x1f;
3020 const GLint rowBr1
= rowB
[k
] & 0xf;
3021 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
3022 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
3023 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
3024 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
3025 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
3026 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3027 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3028 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3029 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3030 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3031 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3032 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3033 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3034 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3035 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3036 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3037 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3041 case MESA_FORMAT_AL88
:
3042 case MESA_FORMAT_AL88_REV
:
3045 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3046 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3047 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3048 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3049 i
++, j
+= colStride
, k
+= colStride
) {
3050 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3051 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3052 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3053 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3057 case MESA_FORMAT_RGB332
:
3060 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3061 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3062 GLubyte
*dst
= (GLubyte
*) dstRow
;
3063 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3064 i
++, j
+= colStride
, k
+= colStride
) {
3065 const GLint rowAr0
= rowA
[j
] & 0x3;
3066 const GLint rowAr1
= rowA
[k
] & 0x3;
3067 const GLint rowBr0
= rowB
[j
] & 0x3;
3068 const GLint rowBr1
= rowB
[k
] & 0x3;
3069 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3070 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3071 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3072 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3073 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3074 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3075 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3076 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3077 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3078 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3079 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3080 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3084 case MESA_FORMAT_A8
:
3085 case MESA_FORMAT_L8
:
3086 case MESA_FORMAT_I8
:
3087 case MESA_FORMAT_CI8
:
3090 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3091 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3092 GLubyte
*dst
= (GLubyte
*) dstRow
;
3093 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3094 i
++, j
+= colStride
, k
+= colStride
) {
3095 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
3099 case MESA_FORMAT_RGBA_FLOAT32
:
3102 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3103 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3104 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
3105 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3106 i
++, j
+= colStride
, k
+= colStride
) {
3107 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3108 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3109 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3110 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3111 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3112 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3113 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3114 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3118 case MESA_FORMAT_RGBA_FLOAT16
:
3120 GLuint i
, j
, k
, comp
;
3121 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3122 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3123 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3124 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3125 i
++, j
+= colStride
, k
+= colStride
) {
3126 for (comp
= 0; comp
< 4; comp
++) {
3127 GLfloat aj
, ak
, bj
, bk
;
3128 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3129 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3130 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3131 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3132 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3137 case MESA_FORMAT_RGB_FLOAT32
:
3140 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3141 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3142 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3143 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3144 i
++, j
+= colStride
, k
+= colStride
) {
3145 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3146 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3147 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3148 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3149 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3150 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3154 case MESA_FORMAT_RGB_FLOAT16
:
3156 GLuint i
, j
, k
, comp
;
3157 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3158 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3159 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3160 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3161 i
++, j
+= colStride
, k
+= colStride
) {
3162 for (comp
= 0; comp
< 3; comp
++) {
3163 GLfloat aj
, ak
, bj
, bk
;
3164 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3165 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3166 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3167 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3168 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3173 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3176 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3177 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3178 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3179 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3180 i
++, j
+= colStride
, k
+= colStride
) {
3181 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3182 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3183 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3184 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3188 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3190 GLuint i
, j
, k
, comp
;
3191 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3192 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3193 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3194 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3195 i
++, j
+= colStride
, k
+= colStride
) {
3196 for (comp
= 0; comp
< 2; comp
++) {
3197 GLfloat aj
, ak
, bj
, bk
;
3198 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3199 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3200 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3201 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3202 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3207 case MESA_FORMAT_ALPHA_FLOAT32
:
3208 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3209 case MESA_FORMAT_INTENSITY_FLOAT32
:
3212 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3213 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3214 GLfloat
*dst
= (GLfloat
*) dstRow
;
3215 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3216 i
++, j
+= colStride
, k
+= colStride
) {
3217 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3221 case MESA_FORMAT_ALPHA_FLOAT16
:
3222 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3223 case MESA_FORMAT_INTENSITY_FLOAT16
:
3226 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3227 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3228 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3229 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3230 i
++, j
+= colStride
, k
+= colStride
) {
3231 GLfloat aj
, ak
, bj
, bk
;
3232 aj
= _mesa_half_to_float(rowA
[j
]);
3233 ak
= _mesa_half_to_float(rowA
[k
]);
3234 bj
= _mesa_half_to_float(rowB
[j
]);
3235 bk
= _mesa_half_to_float(rowB
[k
]);
3236 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3242 _mesa_problem(NULL
, "bad format in do_row()");
3248 * These functions generate a 1/2-size mipmap image from a source image.
3249 * Texture borders are handled by copying or averaging the source image's
3250 * border texels, depending on the scale-down factor.
3254 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3255 GLint srcWidth
, const GLubyte
*srcPtr
,
3256 GLint dstWidth
, GLubyte
*dstPtr
)
3258 const GLint bpt
= format
->TexelBytes
;
3262 /* skip the border pixel, if any */
3263 src
= srcPtr
+ border
* bpt
;
3264 dst
= dstPtr
+ border
* bpt
;
3266 /* we just duplicate the input row, kind of hack, saves code */
3267 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3268 dstWidth
- 2 * border
, dst
);
3271 /* copy left-most pixel from source */
3272 MEMCPY(dstPtr
, srcPtr
, bpt
);
3273 /* copy right-most pixel from source */
3274 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3275 srcPtr
+ (srcWidth
- 1) * bpt
,
3282 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3283 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3284 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3286 const GLint bpt
= format
->TexelBytes
;
3287 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3288 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3289 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3290 const GLint srcRowStride
= bpt
* srcWidth
;
3291 const GLint dstRowStride
= bpt
* dstWidth
;
3292 const GLubyte
*srcA
, *srcB
;
3296 /* Compute src and dst pointers, skipping any border */
3297 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3299 srcB
= srcA
+ srcRowStride
;
3302 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3304 for (row
= 0; row
< dstHeightNB
; row
++) {
3305 do_row(format
, srcWidthNB
, srcA
, srcB
,
3307 srcA
+= 2 * srcRowStride
;
3308 srcB
+= 2 * srcRowStride
;
3309 dst
+= dstRowStride
;
3312 /* This is ugly but probably won't be used much */
3314 /* fill in dest border */
3315 /* lower-left border pixel */
3316 MEMCPY(dstPtr
, srcPtr
, bpt
);
3317 /* lower-right border pixel */
3318 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3319 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3320 /* upper-left border pixel */
3321 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3322 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3323 /* upper-right border pixel */
3324 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3325 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3327 do_row(format
, srcWidthNB
,
3330 dstWidthNB
, dstPtr
+ bpt
);
3332 do_row(format
, srcWidthNB
,
3333 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3334 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3336 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3337 /* left and right borders */
3338 if (srcHeight
== dstHeight
) {
3339 /* copy border pixel from src to dst */
3340 for (row
= 1; row
< srcHeight
; row
++) {
3341 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3342 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3343 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3344 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3348 /* average two src pixels each dest pixel */
3349 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3351 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3352 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3353 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3355 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3356 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3357 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3365 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3366 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3367 const GLubyte
*srcPtr
,
3368 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3371 const GLint bpt
= format
->TexelBytes
;
3372 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3373 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3374 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3375 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3376 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3377 GLvoid
*tmpRowA
, *tmpRowB
;
3379 GLint bytesPerSrcImage
, bytesPerDstImage
;
3380 GLint bytesPerSrcRow
, bytesPerDstRow
;
3381 GLint srcImageOffset
, srcRowOffset
;
3383 (void) srcDepthNB
; /* silence warnings */
3385 /* Need two temporary row buffers */
3386 tmpRowA
= MALLOC(srcWidth
* bpt
);
3389 tmpRowB
= MALLOC(srcWidth
* bpt
);
3395 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3396 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3398 bytesPerSrcRow
= srcWidth
* bpt
;
3399 bytesPerDstRow
= dstWidth
* bpt
;
3401 /* Offset between adjacent src images to be averaged together */
3402 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3404 /* Offset between adjacent src rows to be averaged together */
3405 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3408 * Need to average together up to 8 src pixels for each dest pixel.
3409 * Break that down into 3 operations:
3410 * 1. take two rows from source image and average them together.
3411 * 2. take two rows from next source image and average them together.
3412 * 3. take the two averaged rows and average them for the final dst row.
3416 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3417 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3420 for (img
= 0; img
< dstDepthNB
; img
++) {
3421 /* first source image pointer, skipping border */
3422 const GLubyte
*imgSrcA
= srcPtr
3423 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3424 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3425 /* second source image pointer, skipping border */
3426 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3427 /* address of the dest image, skipping border */
3428 GLubyte
*imgDst
= dstPtr
3429 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3430 + img
* bytesPerDstImage
;
3432 /* setup the four source row pointers and the dest row pointer */
3433 const GLubyte
*srcImgARowA
= imgSrcA
;
3434 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3435 const GLubyte
*srcImgBRowA
= imgSrcB
;
3436 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3437 GLubyte
*dstImgRow
= imgDst
;
3439 for (row
= 0; row
< dstHeightNB
; row
++) {
3440 /* Average together two rows from first src image */
3441 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3442 srcWidthNB
, tmpRowA
);
3443 /* Average together two rows from second src image */
3444 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3445 srcWidthNB
, tmpRowB
);
3446 /* Average together the temp rows to make the final row */
3447 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3448 dstWidthNB
, dstImgRow
);
3449 /* advance to next rows */
3450 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3451 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3452 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3453 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3454 dstImgRow
+= bytesPerDstRow
;
3461 /* Luckily we can leverage the make_2d_mipmap() function here! */
3463 /* do front border image */
3464 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3465 dstWidth
, dstHeight
, dstPtr
);
3466 /* do back border image */
3467 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3468 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3469 dstWidth
, dstHeight
,
3470 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3471 /* do four remaining border edges that span the image slices */
3472 if (srcDepth
== dstDepth
) {
3473 /* just copy border pixels from src to dst */
3474 for (img
= 0; img
< dstDepthNB
; img
++) {
3478 /* do border along [img][row=0][col=0] */
3479 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3480 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3481 MEMCPY(dst
, src
, bpt
);
3483 /* do border along [img][row=dstHeight-1][col=0] */
3484 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3485 + (srcHeight
- 1) * bytesPerSrcRow
;
3486 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3487 + (dstHeight
- 1) * bytesPerDstRow
;
3488 MEMCPY(dst
, src
, bpt
);
3490 /* do border along [img][row=0][col=dstWidth-1] */
3491 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3492 + (srcWidth
- 1) * bpt
;
3493 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3494 + (dstWidth
- 1) * bpt
;
3495 MEMCPY(dst
, src
, bpt
);
3497 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3498 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3499 + (bytesPerSrcImage
- bpt
);
3500 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3501 + (bytesPerDstImage
- bpt
);
3502 MEMCPY(dst
, src
, bpt
);
3506 /* average border pixels from adjacent src image pairs */
3507 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3508 for (img
= 0; img
< dstDepthNB
; img
++) {
3512 /* do border along [img][row=0][col=0] */
3513 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3514 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3515 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3517 /* do border along [img][row=dstHeight-1][col=0] */
3518 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3519 + (srcHeight
- 1) * bytesPerSrcRow
;
3520 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3521 + (dstHeight
- 1) * bytesPerDstRow
;
3522 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3524 /* do border along [img][row=0][col=dstWidth-1] */
3525 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3526 + (srcWidth
- 1) * bpt
;
3527 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3528 + (dstWidth
- 1) * bpt
;
3529 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3531 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3532 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3533 + (bytesPerSrcImage
- bpt
);
3534 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3535 + (bytesPerDstImage
- bpt
);
3536 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3544 * For GL_SGIX_generate_mipmap:
3545 * Generate a complete set of mipmaps from texObj's base-level image.
3546 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3549 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3550 const struct gl_texture_unit
*texUnit
,
3551 struct gl_texture_object
*texObj
)
3553 const struct gl_texture_image
*srcImage
;
3554 const struct gl_texture_format
*convertFormat
;
3555 const GLubyte
*srcData
= NULL
;
3556 GLubyte
*dstData
= NULL
;
3557 GLint level
, maxLevels
;
3560 /* XXX choose cube map face here??? */
3561 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3564 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3565 ASSERT(maxLevels
> 0); /* bad target */
3567 /* Find convertFormat - the format that do_row() will process */
3568 if (srcImage
->IsCompressed
) {
3569 /* setup for compressed textures */
3571 GLint components
, size
;
3574 assert(texObj
->Target
== GL_TEXTURE_2D
);
3576 if (srcImage
->Format
== GL_RGB
) {
3577 convertFormat
= &_mesa_texformat_rgb
;
3580 else if (srcImage
->Format
== GL_RGBA
) {
3581 convertFormat
= &_mesa_texformat_rgba
;
3585 _mesa_problem(ctx
, "bad srcImage->Format in _mesa_generate_mipmaps");
3589 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3590 size
= _mesa_bytes_per_pixel(srcImage
->Format
, CHAN_TYPE
)
3591 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3592 /* 20 extra bytes, just be safe when calling last FetchTexel */
3593 srcData
= (GLubyte
*) MALLOC(size
);
3595 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3598 dstData
= (GLubyte
*) MALLOC(size
/ 2); /* 1/4 would probably be OK */
3600 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3601 FREE((void *) srcData
);
3605 /* decompress base image here */
3606 dst
= (GLchan
*) srcData
;
3607 for (row
= 0; row
< srcImage
->Height
; row
++) {
3609 for (col
= 0; col
< srcImage
->Width
; col
++) {
3610 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3617 convertFormat
= srcImage
->TexFormat
;
3620 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3621 && level
< maxLevels
- 1; level
++) {
3622 /* generate image[level+1] from image[level] */
3623 const struct gl_texture_image
*srcImage
;
3624 struct gl_texture_image
*dstImage
;
3625 GLint srcWidth
, srcHeight
, srcDepth
;
3626 GLint dstWidth
, dstHeight
, dstDepth
;
3627 GLint border
, bytesPerTexel
;
3629 /* get src image parameters */
3630 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3632 srcWidth
= srcImage
->Width
;
3633 srcHeight
= srcImage
->Height
;
3634 srcDepth
= srcImage
->Depth
;
3635 border
= srcImage
->Border
;
3637 /* compute next (level+1) image size */
3638 if (srcWidth
- 2 * border
> 1) {
3639 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3642 dstWidth
= srcWidth
; /* can't go smaller */
3644 if (srcHeight
- 2 * border
> 1) {
3645 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3648 dstHeight
= srcHeight
; /* can't go smaller */
3650 if (srcDepth
- 2 * border
> 1) {
3651 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3654 dstDepth
= srcDepth
; /* can't go smaller */
3657 if (dstWidth
== srcWidth
&&
3658 dstHeight
== srcHeight
&&
3659 dstDepth
== srcDepth
) {
3661 if (srcImage
->IsCompressed
) {
3662 FREE((void *) srcData
);
3668 /* get dest gl_texture_image */
3669 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3671 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3675 /* Free old image data */
3677 MESA_PBUFFER_FREE(dstImage
->Data
);
3679 /* initialize new image */
3680 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3681 dstDepth
, border
, srcImage
->IntFormat
);
3682 dstImage
->DriverData
= NULL
;
3683 dstImage
->TexFormat
= srcImage
->TexFormat
;
3684 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3685 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3686 ASSERT(dstImage
->TexFormat
);
3687 ASSERT(dstImage
->FetchTexelc
);
3688 ASSERT(dstImage
->FetchTexelf
);
3690 /* Alloc new teximage data buffer.
3691 * Setup src and dest data pointers.
3693 if (dstImage
->IsCompressed
) {
3694 ASSERT(dstImage
->CompressedSize
> 0); /* set by init_teximage_fields*/
3695 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstImage
->CompressedSize
);
3696 if (!dstImage
->Data
) {
3697 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3700 /* srcData and dstData are already set */
3705 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
3706 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3707 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstWidth
* dstHeight
* dstDepth
3709 if (!dstImage
->Data
) {
3710 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3713 srcData
= (const GLubyte
*) srcImage
->Data
;
3714 dstData
= (GLubyte
*) dstImage
->Data
;
3718 * We use simple 2x2 averaging to compute the next mipmap level.
3722 make_1d_mipmap(convertFormat
, border
,
3727 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3729 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3730 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3731 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3733 make_2d_mipmap(convertFormat
, border
,
3734 srcWidth
, srcHeight
, srcData
,
3735 dstWidth
, dstHeight
, dstData
);
3738 make_3d_mipmap(convertFormat
, border
,
3739 srcWidth
, srcHeight
, srcDepth
, srcData
,
3740 dstWidth
, dstHeight
, dstDepth
, dstData
);
3742 case GL_TEXTURE_RECTANGLE_NV
:
3743 /* no mipmaps, do nothing */
3746 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3750 if (dstImage
->IsCompressed
) {
3752 /* compress image from dstData into dstImage->Data */
3753 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3754 GLint dstRowStride
= _mesa_compressed_row_stride(srcImage
->IntFormat
,
3756 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3757 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->Format
,
3758 dstImage
->TexFormat
,
3760 0, 0, 0, /* dstX/Y/Zoffset */
3761 dstRowStride
, 0, /* strides */
3762 dstWidth
, dstHeight
, 1, /* size */
3763 srcFormat
, CHAN_TYPE
,
3764 dstData
, /* src data, actually */
3765 &ctx
->DefaultPacking
);
3766 /* swap src and dest pointers */
3767 temp
= (GLubyte
*) srcData
;
3772 } /* loop over mipmap levels */
3777 * Helper function for drivers which need to rescale texture images to
3778 * certain aspect ratios.
3779 * Nearest filtering only (for broken hardware that can't support
3780 * all aspect ratios). This can be made a lot faster, but I don't
3781 * really care enough...
3784 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
3785 GLuint srcStrideInPixels
,
3786 GLuint dstRowStride
,
3787 GLint srcWidth
, GLint srcHeight
,
3788 GLint dstWidth
, GLint dstHeight
,
3789 const GLvoid
*srcImage
, GLvoid
*dstImage
)
3793 #define INNER_LOOP( TYPE, HOP, WOP ) \
3794 for ( row = 0 ; row < dstHeight ; row++ ) { \
3795 GLint srcRow = row HOP hScale; \
3796 for ( col = 0 ; col < dstWidth ; col++ ) { \
3797 GLint srcCol = col WOP wScale; \
3798 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3800 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3803 #define RESCALE_IMAGE( TYPE ) \
3805 const TYPE *src = (const TYPE *)srcImage; \
3806 TYPE *dst = (TYPE *)dstImage; \
3808 if ( srcHeight < dstHeight ) { \
3809 const GLint hScale = dstHeight / srcHeight; \
3810 if ( srcWidth < dstWidth ) { \
3811 const GLint wScale = dstWidth / srcWidth; \
3812 INNER_LOOP( TYPE, /, / ); \
3815 const GLint wScale = srcWidth / dstWidth; \
3816 INNER_LOOP( TYPE, /, * ); \
3820 const GLint hScale = srcHeight / dstHeight; \
3821 if ( srcWidth < dstWidth ) { \
3822 const GLint wScale = dstWidth / srcWidth; \
3823 INNER_LOOP( TYPE, *, / ); \
3826 const GLint wScale = srcWidth / dstWidth; \
3827 INNER_LOOP( TYPE, *, * ); \
3832 switch ( bytesPerPixel
) {
3834 RESCALE_IMAGE( GLuint
);
3838 RESCALE_IMAGE( GLushort
);
3842 RESCALE_IMAGE( GLubyte
);
3845 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3851 * Upscale an image by replication, not (typical) stretching.
3852 * We use this when the image width or height is less than a
3853 * certain size (4, 8) and we need to upscale an image.
3856 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
3857 GLsizei outWidth
, GLsizei outHeight
,
3858 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
3863 ASSERT(outWidth
>= inWidth
);
3864 ASSERT(outHeight
>= inHeight
);
3866 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
3867 ASSERT((outWidth
& 3) == 0);
3868 ASSERT((outHeight
& 3) == 0);
3871 for (i
= 0; i
< outHeight
; i
++) {
3872 const GLint ii
= i
% inHeight
;
3873 for (j
= 0; j
< outWidth
; j
++) {
3874 const GLint jj
= j
% inWidth
;
3875 for (k
= 0; k
< comps
; k
++) {
3876 dest
[(i
* outWidth
+ j
) * comps
+ k
]
3877 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
3886 * This is the software fallback for Driver.GetTexImage().
3887 * All error checking will have been done before this routine is called.
3890 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3891 GLenum format
, GLenum type
, GLvoid
*pixels
,
3892 const struct gl_texture_object
*texObj
,
3893 const struct gl_texture_image
*texImage
)
3895 GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3897 if (ctx
->Pack
.BufferObj
->Name
) {
3898 /* pack texture image into a PBO */
3900 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
3901 texImage
->Height
, texImage
->Depth
,
3902 format
, type
, pixels
)) {
3903 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3904 "glGetTexImage(invalid PBO access)");
3907 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3909 ctx
->Pack
.BufferObj
);
3911 /* buffer is already mapped - that's an error */
3912 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3915 pixels
= ADD_POINTERS(buf
, pixels
);
3923 const GLint width
= texImage
->Width
;
3924 const GLint height
= texImage
->Height
;
3925 const GLint depth
= texImage
->Depth
;
3927 for (img
= 0; img
< depth
; img
++) {
3928 for (row
= 0; row
< height
; row
++) {
3929 /* compute destination address in client memory */
3930 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3931 width
, height
, format
, type
,
3935 if (format
== GL_COLOR_INDEX
) {
3936 GLuint indexRow
[MAX_WIDTH
];
3938 /* Can't use FetchTexel here because that returns RGBA */
3939 if (texImage
->TexFormat
->IndexBits
== 8) {
3940 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3941 for (col
= 0; col
< width
; col
++) {
3942 indexRow
[col
] = src
[texImage
->Width
*
3943 (img
* texImage
->Height
+ row
) + col
];
3946 else if (texImage
->TexFormat
->IndexBits
== 16) {
3947 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3948 for (col
= 0; col
< width
; col
++) {
3949 indexRow
[col
] = src
[texImage
->Width
*
3950 (img
* texImage
->Height
+ row
) + col
];
3955 "Color index problem in _mesa_GetTexImage");
3957 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3958 indexRow
, &ctx
->Pack
,
3959 0 /* no image transfer */);
3961 else if (format
== GL_DEPTH_COMPONENT
) {
3962 GLfloat depthRow
[MAX_WIDTH
];
3964 for (col
= 0; col
< width
; col
++) {
3965 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3968 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3969 depthRow
, &ctx
->Pack
);
3971 else if (format
== GL_YCBCR_MESA
) {
3972 /* No pixel transfer */
3973 const GLint rowstride
= texImage
->RowStride
;
3975 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3976 width
* sizeof(GLushort
));
3977 /* check for byte swapping */
3978 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3979 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3980 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3981 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3982 if (!ctx
->Pack
.SwapBytes
)
3983 _mesa_swap2((GLushort
*) dest
, width
);
3985 else if (ctx
->Pack
.SwapBytes
) {
3986 _mesa_swap2((GLushort
*) dest
, width
);
3990 /* general case: convert row to RGBA format */
3991 GLfloat rgba
[MAX_WIDTH
][4];
3993 for (col
= 0; col
< width
; col
++) {
3994 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3996 _mesa_pack_rgba_span_float(ctx
, width
,
3997 (const GLfloat (*)[4]) rgba
,
3998 format
, type
, dest
, &ctx
->Pack
,
3999 0 /* no image transfer */);
4005 if (ctx
->Pack
.BufferObj
->Name
) {
4006 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4007 ctx
->Pack
.BufferObj
);
4014 * This is the software fallback for Driver.GetCompressedTexImage().
4015 * All error checking will have been done before this routine is called.
4018 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4020 const struct gl_texture_object
*texObj
,
4021 const struct gl_texture_image
*texImage
)
4023 if (ctx
->Pack
.BufferObj
->Name
) {
4024 /* pack texture image into a PBO */
4026 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4027 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4028 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4029 "glGetCompressedTexImage(invalid PBO access)");
4032 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4034 ctx
->Pack
.BufferObj
);
4036 /* buffer is already mapped - that's an error */
4037 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4038 "glGetCompressedTexImage(PBO is mapped)");
4041 img
= ADD_POINTERS(buf
, img
);
4048 /* just memcpy, no pixelstore or pixel transfer */
4049 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);
4051 if (ctx
->Pack
.BufferObj
->Name
) {
4052 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4053 ctx
->Pack
.BufferObj
);