2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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
;
549 static void swizzle_copy(GLubyte
*dst
,
550 GLuint dstComponents
,
552 GLuint srcComponents
,
562 switch (dstComponents
) {
564 for (i
= 0; i
< count
; i
++) {
566 src
+= srcComponents
;
567 dst
[0] = tmp
[map
[0]];
568 dst
[1] = tmp
[map
[1]];
569 dst
[2] = tmp
[map
[2]];
570 dst
[3] = tmp
[map
[3]];
575 for (i
= 0; i
< count
; i
++) {
577 src
+= srcComponents
;
578 dst
[0] = tmp
[map
[0]];
579 dst
[1] = tmp
[map
[1]];
580 dst
[2] = tmp
[map
[2]];
585 for (i
= 0; i
< count
; i
++) {
587 src
+= srcComponents
;
588 dst
[0] = tmp
[map
[0]];
589 dst
[1] = tmp
[map
[1]];
598 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
601 const GLubyte
*dstmap
, GLint dstComponents
,
604 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
605 GLint dstRowStride
, GLint dstImageStride
,
607 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
608 const GLvoid
*srcAddr
,
609 const struct gl_pixelstore_attrib
*srcPacking
)
611 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
612 GLubyte srcmap
[6], map
[4];
615 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
616 srcFormat
, GL_UNSIGNED_BYTE
);
617 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
618 srcWidth
, srcHeight
, srcFormat
, GL_UNSIGNED_BYTE
);
619 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
620 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, GL_UNSIGNED_BYTE
, 0, 0, 0);
622 GLubyte
*dstImage
= (GLubyte
*) dstAddr
623 + dstZoffset
* dstImageStride
624 + dstYoffset
* dstRowStride
625 + dstXoffset
* dstComponents
;
627 compute_component_mapping(srcFormat
, GL_RGBA
, srcmap
);
629 for (i
= 0; i
< 4; i
++)
630 map
[i
] = srcmap
[dstmap
[i
]];
632 if (srcRowStride
== srcWidth
* srcComponents
&&
633 (srcImageStride
== srcWidth
* srcHeight
* srcComponents
||
635 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
636 srcWidth
* srcHeight
* srcDepth
);
640 for (img
= 0; img
< srcDepth
; img
++) {
641 const GLubyte
*srcRow
= srcImage
;
642 GLubyte
*dstRow
= dstImage
;
643 for (row
= 0; row
< srcHeight
; row
++) {
644 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
645 dstRow
+= dstRowStride
;
646 srcRow
+= srcRowStride
;
648 srcImage
+= srcImageStride
;
649 dstImage
+= dstImageStride
;
659 * Teximage storage routine for when a simple memcpy will do.
660 * No pixel transfer operations or special texel encodings allowed.
661 * 1D, 2D and 3D images supported.
664 memcpy_texture(GLuint dimensions
,
665 const struct gl_texture_format
*dstFormat
,
667 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
668 GLint dstRowStride
, GLint dstImageStride
,
669 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
670 GLenum srcFormat
, GLenum srcType
,
671 const GLvoid
*srcAddr
,
672 const struct gl_pixelstore_attrib
*srcPacking
)
674 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
676 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
677 srcWidth
, srcHeight
, srcFormat
, srcType
);
678 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
679 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
680 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
681 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
682 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
683 GLubyte
*dstImage
= (GLubyte
*) dstAddr
684 + dstZoffset
* dstImageStride
685 + dstYoffset
* dstRowStride
686 + dstXoffset
* dstFormat
->TexelBytes
;
688 if (dstRowStride
== srcRowStride
&&
689 dstRowStride
== bytesPerRow
&&
690 ((dstImageStride
== srcImageStride
&&
691 dstImageStride
== bytesPerImage
) ||
694 _mesa_memcpy(dstImage
, srcImage
, bytesPerTexture
);
698 for (img
= 0; img
< srcDepth
; img
++) {
699 const GLubyte
*srcRow
= srcImage
;
700 GLubyte
*dstRow
= dstImage
;
701 for (row
= 0; row
< srcHeight
; row
++) {
702 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
703 dstRow
+= dstRowStride
;
704 srcRow
+= srcRowStride
;
706 srcImage
+= srcImageStride
;
707 dstImage
+= dstImageStride
;
715 * Store an image in any of the formats:
716 * _mesa_texformat_rgba
717 * _mesa_texformat_rgb
718 * _mesa_texformat_alpha
719 * _mesa_texformat_luminance
720 * _mesa_texformat_luminance_alpha
721 * _mesa_texformat_intensity
723 * \param dims either 1 or 2 or 3
724 * \param baseInternalFormat user-specified base internal format
725 * \param dstFormat destination Mesa texture format
726 * \param dstAddr destination image address
727 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
728 * \param dstRowStride destination image row stride, in bytes
729 * \param dstImageStride destination image layer stride, in bytes
730 * \param srcWidth/Height/Depth source image size, in pixels
731 * \param srcFormat incoming image format
732 * \param srcType incoming image data type
733 * \param srcAddr source image address
734 * \param srcPacking source image packing parameters
737 _mesa_texstore_rgba(GLcontext
*ctx
, GLuint dims
,
738 GLenum baseInternalFormat
,
739 const struct gl_texture_format
*dstFormat
,
741 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
742 GLint dstRowStride
, GLint dstImageStride
,
743 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
744 GLenum srcFormat
, GLenum srcType
,
745 const GLvoid
*srcAddr
,
746 const struct gl_pixelstore_attrib
*srcPacking
)
748 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
750 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
751 dstFormat
== &_mesa_texformat_rgb
||
752 dstFormat
== &_mesa_texformat_alpha
||
753 dstFormat
== &_mesa_texformat_luminance
||
754 dstFormat
== &_mesa_texformat_luminance_alpha
||
755 dstFormat
== &_mesa_texformat_intensity
);
756 ASSERT(baseInternalFormat
== GL_RGBA
||
757 baseInternalFormat
== GL_RGB
||
758 baseInternalFormat
== GL_ALPHA
||
759 baseInternalFormat
== GL_LUMINANCE
||
760 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
761 baseInternalFormat
== GL_INTENSITY
);
762 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
764 if (!ctx
->_ImageTransferState
&&
765 !srcPacking
->SwapBytes
&&
766 baseInternalFormat
== srcFormat
&&
767 srcType
== CHAN_TYPE
) {
768 /* simple memcpy path */
770 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
771 dstRowStride
, dstImageStride
,
772 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
773 srcAddr
, srcPacking
);
775 else if (!ctx
->_ImageTransferState
&&
776 !srcPacking
->SwapBytes
&&
777 dstFormat
== &_mesa_texformat_rgb
&&
778 srcFormat
== GL_RGBA
&&
779 srcType
== CHAN_TYPE
) {
780 /* extract RGB from RGBA */
782 GLchan
*dstImage
= (GLchan
*) (GLubyte
*) dstAddr
783 + dstZoffset
* dstImageStride
784 + dstYoffset
* dstRowStride
785 + dstXoffset
* dstFormat
->TexelBytes
;
786 for (img
= 0; img
< srcDepth
; img
++) {
787 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
788 srcWidth
, srcFormat
, srcType
);
789 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
790 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
791 GLchan
*dstRow
= dstImage
;
792 for (row
= 0; row
< srcHeight
; row
++) {
793 for (col
= 0; col
< srcWidth
; col
++) {
794 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
795 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
796 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
798 dstRow
+= dstRowStride
;
799 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
801 dstImage
+= dstImageStride
;
806 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
808 dstFormat
->BaseFormat
,
809 srcWidth
, srcHeight
, srcDepth
,
810 srcFormat
, srcType
, srcAddr
,
812 const GLchan
*src
= tempImage
;
814 GLubyte
*dstImage
= (GLubyte
*) dstAddr
815 + dstZoffset
* dstImageStride
816 + dstYoffset
* dstRowStride
817 + dstXoffset
* dstFormat
->TexelBytes
;
821 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
822 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
823 for (img
= 0; img
< srcDepth
; img
++) {
824 GLubyte
*dstRow
= dstImage
;
825 for (row
= 0; row
< srcHeight
; row
++) {
826 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
827 dstRow
+= dstRowStride
;
828 src
+= srcWidth
* components
;
830 dstImage
+= dstImageStride
;
833 _mesa_free((void *) tempImage
);
840 * Store a floating point depth component texture image.
843 _mesa_texstore_depth_component_float32(STORE_PARAMS
)
846 ASSERT(dstFormat
== &_mesa_texformat_depth_component_float32
);
847 ASSERT(dstFormat
->TexelBytes
== sizeof(GLfloat
));
849 if (!ctx
->_ImageTransferState
&&
850 !srcPacking
->SwapBytes
&&
851 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
852 srcFormat
== GL_DEPTH_COMPONENT
&&
853 srcType
== GL_FLOAT
) {
854 /* simple memcpy path */
856 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
857 dstRowStride
, dstImageStride
,
858 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
859 srcAddr
, srcPacking
);
863 GLubyte
*dstImage
= (GLubyte
*) dstAddr
864 + dstZoffset
* dstImageStride
865 + dstYoffset
* dstRowStride
866 + dstXoffset
* dstFormat
->TexelBytes
;
868 for (img
= 0; img
< srcDepth
; img
++) {
869 GLubyte
*dstRow
= dstImage
;
870 for (row
= 0; row
< srcHeight
; row
++) {
871 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
872 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
873 _mesa_unpack_depth_span(ctx
, srcWidth
, (GLfloat
*) dstRow
,
874 srcType
, src
, srcPacking
);
875 dstRow
+= dstRowStride
;
877 dstImage
+= dstImageStride
;
885 * Store a 16-bit integer depth component texture image.
888 _mesa_texstore_depth_component16(STORE_PARAMS
)
891 ASSERT(dstFormat
== &_mesa_texformat_depth_component16
);
892 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
894 if (!ctx
->_ImageTransferState
&&
895 !srcPacking
->SwapBytes
&&
896 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
897 srcFormat
== GL_DEPTH_COMPONENT
&&
898 srcType
== GL_UNSIGNED_SHORT
) {
899 /* simple memcpy path */
901 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
902 dstRowStride
, dstImageStride
,
903 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
904 srcAddr
, srcPacking
);
908 GLubyte
*dstImage
= (GLubyte
*) dstAddr
909 + dstZoffset
* dstImageStride
910 + dstYoffset
* dstRowStride
911 + dstXoffset
* dstFormat
->TexelBytes
;
913 for (img
= 0; img
< srcDepth
; img
++) {
914 GLubyte
*dstRow
= dstImage
;
915 for (row
= 0; row
< srcHeight
; row
++) {
916 GLfloat depthTemp
[MAX_WIDTH
];
917 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
918 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
919 GLushort
*dst16
= (GLushort
*) dstRow
;
920 _mesa_unpack_depth_span(ctx
, srcWidth
, depthTemp
,
921 srcType
, src
, srcPacking
);
922 for (col
= 0; col
< srcWidth
; col
++) {
923 dst16
[col
] = (GLushort
) (depthTemp
[col
] * 65535.0F
);
925 dstRow
+= dstRowStride
;
927 dstImage
+= dstImageStride
;
935 * Store an rgb565 or rgb565_rev texture image.
938 _mesa_texstore_rgb565(STORE_PARAMS
)
940 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
941 dstFormat
== &_mesa_texformat_rgb565_rev
);
942 ASSERT(dstFormat
->TexelBytes
== 2);
944 if (!ctx
->_ImageTransferState
&&
945 !srcPacking
->SwapBytes
&&
946 dstFormat
== &_mesa_texformat_rgb565
&&
947 baseInternalFormat
== GL_RGB
&&
948 srcFormat
== GL_RGB
&&
949 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
950 /* simple memcpy path */
952 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
953 dstRowStride
, dstImageStride
,
954 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
955 srcAddr
, srcPacking
);
957 else if (!ctx
->_ImageTransferState
&&
958 !srcPacking
->SwapBytes
&&
959 baseInternalFormat
== GL_RGB
&&
960 srcFormat
== GL_RGB
&&
961 srcType
== GL_UNSIGNED_BYTE
&&
963 /* do optimized tex store */
964 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
966 const GLubyte
*src
= (const GLubyte
*)
967 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
968 srcFormat
, srcType
, 0, 0, 0);
969 GLubyte
*dst
= (GLubyte
*) dstAddr
970 + dstZoffset
* dstImageStride
971 + dstYoffset
* dstRowStride
972 + dstXoffset
* dstFormat
->TexelBytes
;
974 for (row
= 0; row
< srcHeight
; row
++) {
975 const GLubyte
*srcUB
= (const GLubyte
*) src
;
976 GLushort
*dstUS
= (GLushort
*) dst
;
977 /* check for byteswapped format */
978 if (dstFormat
== &_mesa_texformat_rgb565
) {
979 for (col
= 0; col
< srcWidth
; col
++) {
980 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
985 for (col
= 0; col
< srcWidth
; col
++) {
986 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
996 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
998 dstFormat
->BaseFormat
,
999 srcWidth
, srcHeight
, srcDepth
,
1000 srcFormat
, srcType
, srcAddr
,
1002 const GLchan
*src
= tempImage
;
1003 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1004 + dstZoffset
* dstImageStride
1005 + dstYoffset
* dstRowStride
1006 + dstXoffset
* dstFormat
->TexelBytes
;
1007 GLint img
, row
, col
;
1010 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1011 for (img
= 0; img
< srcDepth
; img
++) {
1012 GLubyte
*dstRow
= dstImage
;
1013 for (row
= 0; row
< srcHeight
; row
++) {
1014 GLushort
*dstUS
= (GLushort
*) dstRow
;
1015 /* check for byteswapped format */
1016 if (dstFormat
== &_mesa_texformat_rgb565
) {
1017 for (col
= 0; col
< srcWidth
; col
++) {
1018 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1019 CHAN_TO_UBYTE(src
[GCOMP
]),
1020 CHAN_TO_UBYTE(src
[BCOMP
]) );
1025 for (col
= 0; col
< srcWidth
; col
++) {
1026 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1027 CHAN_TO_UBYTE(src
[GCOMP
]),
1028 CHAN_TO_UBYTE(src
[BCOMP
]) );
1032 dstRow
+= dstRowStride
;
1034 dstImage
+= dstImageStride
;
1036 _mesa_free((void *) tempImage
);
1043 _mesa_texstore_rgba8888(STORE_PARAMS
)
1045 const GLuint ui
= 1;
1046 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1049 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1050 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1051 ASSERT(dstFormat
->TexelBytes
== 4);
1053 if (!ctx
->_ImageTransferState
&&
1054 !srcPacking
->SwapBytes
&&
1055 dstFormat
== &_mesa_texformat_rgba8888
&&
1056 baseInternalFormat
== GL_RGBA
&&
1057 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1058 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
1059 /* simple memcpy path */
1060 memcpy_texture(dims
,
1061 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1062 dstRowStride
, dstImageStride
,
1063 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1064 srcAddr
, srcPacking
);
1067 else if (!ctx
->_ImageTransferState
&&
1068 !srcPacking
->SwapBytes
&&
1069 srcType
== GL_UNSIGNED_BYTE
&&
1070 dstFormat
== &_mesa_texformat_rgba8888
&&
1072 can_swizzle(srcFormat
)) {
1075 /* dstmap - how to swizzle from GL_RGBA to dst format:
1077 * FIXME - add !litteEndian and _rev varients:
1084 _mesa_swizzle_ubyte_image(ctx
, dims
,
1087 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1088 dstRowStride
, dstImageStride
,
1089 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1095 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1097 dstFormat
->BaseFormat
,
1098 srcWidth
, srcHeight
, srcDepth
,
1099 srcFormat
, srcType
, srcAddr
,
1101 const GLchan
*src
= tempImage
;
1102 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1103 + dstZoffset
* dstImageStride
1104 + dstYoffset
* dstRowStride
1105 + dstXoffset
* dstFormat
->TexelBytes
;
1106 GLint img
, row
, col
;
1109 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1110 for (img
= 0; img
< srcDepth
; img
++) {
1111 GLubyte
*dstRow
= dstImage
;
1112 for (row
= 0; row
< srcHeight
; row
++) {
1113 GLuint
*dstUI
= (GLuint
*) dstRow
;
1114 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1115 for (col
= 0; col
< srcWidth
; col
++) {
1116 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1117 CHAN_TO_UBYTE(src
[GCOMP
]),
1118 CHAN_TO_UBYTE(src
[BCOMP
]),
1119 CHAN_TO_UBYTE(src
[ACOMP
]) );
1124 for (col
= 0; col
< srcWidth
; col
++) {
1125 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1126 CHAN_TO_UBYTE(src
[GCOMP
]),
1127 CHAN_TO_UBYTE(src
[BCOMP
]),
1128 CHAN_TO_UBYTE(src
[ACOMP
]) );
1132 dstRow
+= dstRowStride
;
1134 dstImage
+= dstImageStride
;
1136 _mesa_free((void *) tempImage
);
1143 _mesa_texstore_argb8888(STORE_PARAMS
)
1145 const GLuint ui
= 1;
1146 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1148 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1149 dstFormat
== &_mesa_texformat_argb8888_rev
);
1150 ASSERT(dstFormat
->TexelBytes
== 4);
1152 if (!ctx
->_ImageTransferState
&&
1153 !srcPacking
->SwapBytes
&&
1154 dstFormat
== &_mesa_texformat_argb8888
&&
1155 baseInternalFormat
== GL_RGBA
&&
1156 srcFormat
== GL_BGRA
&&
1157 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1158 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1159 /* simple memcpy path (little endian) */
1160 memcpy_texture(dims
,
1161 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1162 dstRowStride
, dstImageStride
,
1163 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1164 srcAddr
, srcPacking
);
1166 else if (!ctx
->_ImageTransferState
&&
1167 !srcPacking
->SwapBytes
&&
1168 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1169 baseInternalFormat
== GL_RGBA
&&
1170 srcFormat
== GL_BGRA
&&
1171 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1172 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1173 /* simple memcpy path (big endian) */
1174 memcpy_texture(dims
,
1175 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1176 dstRowStride
, dstImageStride
,
1177 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1178 srcAddr
, srcPacking
);
1180 else if (!ctx
->_ImageTransferState
&&
1181 !srcPacking
->SwapBytes
&&
1182 dstFormat
== &_mesa_texformat_argb8888
&&
1183 srcFormat
== GL_RGB
&&
1184 srcType
== GL_UNSIGNED_BYTE
) {
1187 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1188 + dstZoffset
* dstImageStride
1189 + dstYoffset
* dstRowStride
1190 + dstXoffset
* dstFormat
->TexelBytes
;
1191 for (img
= 0; img
< srcDepth
; img
++) {
1192 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1193 srcWidth
, srcFormat
, srcType
);
1194 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1195 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1196 GLubyte
*dstRow
= dstImage
;
1197 for (row
= 0; row
< srcHeight
; row
++) {
1198 for (col
= 0; col
< srcWidth
; col
++) {
1199 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1200 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1201 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1202 dstRow
[col
* 4 + 3] = 0xff;
1204 dstRow
+= dstRowStride
;
1205 srcRow
+= srcRowStride
;
1207 dstImage
+= dstImageStride
;
1210 else if (!ctx
->_ImageTransferState
&&
1211 !srcPacking
->SwapBytes
&&
1212 dstFormat
== &_mesa_texformat_argb8888
&&
1213 srcFormat
== GL_RGBA
&&
1214 srcType
== GL_UNSIGNED_BYTE
) {
1217 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1218 + dstZoffset
* dstImageStride
1219 + dstYoffset
* dstRowStride
1220 + dstXoffset
* dstFormat
->TexelBytes
;
1221 for (img
= 0; img
< srcDepth
; img
++) {
1222 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1223 srcWidth
, srcFormat
, srcType
);
1224 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1225 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1226 GLubyte
*dstRow
= dstImage
;
1227 for (row
= 0; row
< srcHeight
; row
++) {
1228 for (col
= 0; col
< srcWidth
; col
++) {
1229 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1230 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1231 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1232 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1234 dstRow
+= dstRowStride
;
1235 srcRow
+= srcRowStride
;
1237 dstImage
+= dstImageStride
;
1240 else if (!ctx
->_ImageTransferState
&&
1241 !srcPacking
->SwapBytes
&&
1242 dstFormat
== &_mesa_texformat_argb8888
&&
1243 srcType
== GL_UNSIGNED_BYTE
&&
1245 can_swizzle(srcFormat
)) {
1249 /* dstmap - how to swizzle from GL_RGBA to dst format:
1251 dstmap
[3] = 3; /* alpha */
1252 dstmap
[2] = 0; /* red */
1253 dstmap
[1] = 1; /* green */
1254 dstmap
[0] = 2; /* blue */
1256 _mesa_swizzle_ubyte_image(ctx
, dims
,
1259 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1260 dstRowStride
, dstImageStride
,
1261 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1266 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1268 dstFormat
->BaseFormat
,
1269 srcWidth
, srcHeight
, srcDepth
,
1270 srcFormat
, srcType
, srcAddr
,
1272 const GLchan
*src
= tempImage
;
1273 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1274 + dstZoffset
* dstImageStride
1275 + dstYoffset
* dstRowStride
1276 + dstXoffset
* dstFormat
->TexelBytes
;
1277 GLint img
, row
, col
;
1280 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1281 for (img
= 0; img
< srcDepth
; img
++) {
1282 GLubyte
*dstRow
= dstImage
;
1283 for (row
= 0; row
< srcHeight
; row
++) {
1284 GLuint
*dstUI
= (GLuint
*) dstRow
;
1285 if (dstFormat
== &_mesa_texformat_argb8888
) {
1286 for (col
= 0; col
< srcWidth
; col
++) {
1287 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1288 CHAN_TO_UBYTE(src
[RCOMP
]),
1289 CHAN_TO_UBYTE(src
[GCOMP
]),
1290 CHAN_TO_UBYTE(src
[BCOMP
]) );
1295 for (col
= 0; col
< srcWidth
; col
++) {
1296 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1297 CHAN_TO_UBYTE(src
[RCOMP
]),
1298 CHAN_TO_UBYTE(src
[GCOMP
]),
1299 CHAN_TO_UBYTE(src
[BCOMP
]) );
1303 dstRow
+= dstRowStride
;
1305 dstImage
+= dstImageStride
;
1307 _mesa_free((void *) tempImage
);
1314 _mesa_texstore_rgb888(STORE_PARAMS
)
1316 const GLuint ui
= 1;
1317 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1319 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1320 ASSERT(dstFormat
->TexelBytes
== 3);
1322 if (!ctx
->_ImageTransferState
&&
1323 !srcPacking
->SwapBytes
&&
1324 baseInternalFormat
== GL_RGB
&&
1325 srcFormat
== GL_BGR
&&
1326 srcType
== GL_UNSIGNED_BYTE
&&
1328 /* simple memcpy path */
1329 memcpy_texture(dims
,
1330 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1331 dstRowStride
, dstImageStride
,
1332 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1333 srcAddr
, srcPacking
);
1335 else if (!ctx
->_ImageTransferState
&&
1336 !srcPacking
->SwapBytes
&&
1337 srcFormat
== GL_RGBA
&&
1338 srcType
== GL_UNSIGNED_BYTE
) {
1339 /* extract RGB from RGBA */
1341 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1342 + dstZoffset
* dstImageStride
1343 + dstYoffset
* dstRowStride
1344 + dstXoffset
* dstFormat
->TexelBytes
;
1345 for (img
= 0; img
< srcDepth
; img
++) {
1346 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1347 srcWidth
, srcFormat
, srcType
);
1348 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1349 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1350 GLubyte
*dstRow
= dstImage
;
1351 for (row
= 0; row
< srcHeight
; row
++) {
1352 for (col
= 0; col
< srcWidth
; col
++) {
1353 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1354 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1355 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1357 dstRow
+= dstRowStride
;
1358 srcRow
+= srcRowStride
;
1360 dstImage
+= dstImageStride
;
1365 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1367 dstFormat
->BaseFormat
,
1368 srcWidth
, srcHeight
, srcDepth
,
1369 srcFormat
, srcType
, srcAddr
,
1371 const GLchan
*src
= (const GLchan
*) tempImage
;
1372 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1373 + dstZoffset
* dstImageStride
1374 + dstYoffset
* dstRowStride
1375 + dstXoffset
* dstFormat
->TexelBytes
;
1376 GLint img
, row
, col
;
1379 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1380 for (img
= 0; img
< srcDepth
; img
++) {
1381 GLubyte
*dstRow
= dstImage
;
1382 for (row
= 0; row
< srcHeight
; row
++) {
1385 for (col
= 0; col
< srcWidth
; col
++) {
1386 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1387 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1388 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1393 for (col
= 0; col
< srcWidth
; col
++) {
1394 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1395 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1396 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1401 for (col
= 0; col
< srcWidth
; col
++) {
1402 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1403 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1404 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1408 dstRow
+= dstRowStride
;
1410 dstImage
+= dstImageStride
;
1412 _mesa_free((void *) tempImage
);
1419 _mesa_texstore_bgr888(STORE_PARAMS
)
1421 const GLuint ui
= 1;
1422 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1424 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1425 ASSERT(dstFormat
->TexelBytes
== 3);
1427 if (!ctx
->_ImageTransferState
&&
1428 !srcPacking
->SwapBytes
&&
1429 baseInternalFormat
== GL_RGB
&&
1430 srcFormat
== GL_RGB
&&
1431 srcType
== GL_UNSIGNED_BYTE
&&
1433 /* simple memcpy path */
1434 memcpy_texture(dims
,
1435 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1436 dstRowStride
, dstImageStride
,
1437 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1438 srcAddr
, srcPacking
);
1440 else if (!ctx
->_ImageTransferState
&&
1441 !srcPacking
->SwapBytes
&&
1442 srcFormat
== GL_RGBA
&&
1443 srcType
== GL_UNSIGNED_BYTE
) {
1444 /* extract BGR from RGBA */
1446 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1447 + dstZoffset
* dstImageStride
1448 + dstYoffset
* dstRowStride
1449 + dstXoffset
* dstFormat
->TexelBytes
;
1450 for (img
= 0; img
< srcDepth
; img
++) {
1451 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1452 srcWidth
, srcFormat
, srcType
);
1453 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1454 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1455 GLubyte
*dstRow
= dstImage
;
1456 for (row
= 0; row
< srcHeight
; row
++) {
1457 for (col
= 0; col
< srcWidth
; col
++) {
1458 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1459 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1460 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1462 dstRow
+= dstRowStride
;
1463 srcRow
+= srcRowStride
;
1465 dstImage
+= dstImageStride
;
1470 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1472 dstFormat
->BaseFormat
,
1473 srcWidth
, srcHeight
, srcDepth
,
1474 srcFormat
, srcType
, srcAddr
,
1476 const GLchan
*src
= (const GLchan
*) tempImage
;
1477 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1478 + dstZoffset
* dstImageStride
1479 + dstYoffset
* dstRowStride
1480 + dstXoffset
* dstFormat
->TexelBytes
;
1481 GLint img
, row
, col
;
1484 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1485 for (img
= 0; img
< srcDepth
; img
++) {
1486 GLubyte
*dstRow
= dstImage
;
1487 for (row
= 0; row
< srcHeight
; row
++) {
1488 for (col
= 0; col
< srcWidth
; col
++) {
1489 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1490 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1491 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1494 dstRow
+= dstRowStride
;
1496 dstImage
+= dstImageStride
;
1498 _mesa_free((void *) tempImage
);
1505 _mesa_texstore_argb4444(STORE_PARAMS
)
1507 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1508 dstFormat
== &_mesa_texformat_argb4444_rev
);
1509 ASSERT(dstFormat
->TexelBytes
== 2);
1511 if (!ctx
->_ImageTransferState
&&
1512 !srcPacking
->SwapBytes
&&
1513 dstFormat
== &_mesa_texformat_argb4444
&&
1514 baseInternalFormat
== GL_RGBA
&&
1515 srcFormat
== GL_BGRA
&&
1516 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1517 /* simple memcpy path */
1518 memcpy_texture(dims
,
1519 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1520 dstRowStride
, dstImageStride
,
1521 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1522 srcAddr
, srcPacking
);
1526 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1528 dstFormat
->BaseFormat
,
1529 srcWidth
, srcHeight
, srcDepth
,
1530 srcFormat
, srcType
, srcAddr
,
1532 const GLchan
*src
= tempImage
;
1533 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1534 + dstZoffset
* dstImageStride
1535 + dstYoffset
* dstRowStride
1536 + dstXoffset
* dstFormat
->TexelBytes
;
1537 GLint img
, row
, col
;
1540 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1541 for (img
= 0; img
< srcDepth
; img
++) {
1542 GLubyte
*dstRow
= dstImage
;
1543 for (row
= 0; row
< srcHeight
; row
++) {
1544 GLushort
*dstUS
= (GLushort
*) dstRow
;
1545 if (dstFormat
== &_mesa_texformat_argb4444
) {
1546 for (col
= 0; col
< srcWidth
; col
++) {
1547 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1548 CHAN_TO_UBYTE(src
[RCOMP
]),
1549 CHAN_TO_UBYTE(src
[GCOMP
]),
1550 CHAN_TO_UBYTE(src
[BCOMP
]) );
1555 for (col
= 0; col
< srcWidth
; col
++) {
1556 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1557 CHAN_TO_UBYTE(src
[RCOMP
]),
1558 CHAN_TO_UBYTE(src
[GCOMP
]),
1559 CHAN_TO_UBYTE(src
[BCOMP
]) );
1563 dstRow
+= dstRowStride
;
1565 dstImage
+= dstImageStride
;
1567 _mesa_free((void *) tempImage
);
1575 _mesa_texstore_argb1555(STORE_PARAMS
)
1577 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1578 dstFormat
== &_mesa_texformat_argb1555_rev
);
1579 ASSERT(dstFormat
->TexelBytes
== 2);
1581 if (!ctx
->_ImageTransferState
&&
1582 !srcPacking
->SwapBytes
&&
1583 dstFormat
== &_mesa_texformat_argb1555
&&
1584 baseInternalFormat
== GL_RGBA
&&
1585 srcFormat
== GL_BGRA
&&
1586 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1587 /* simple memcpy path */
1588 memcpy_texture(dims
,
1589 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1590 dstRowStride
, dstImageStride
,
1591 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1592 srcAddr
, srcPacking
);
1596 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1598 dstFormat
->BaseFormat
,
1599 srcWidth
, srcHeight
, srcDepth
,
1600 srcFormat
, srcType
, srcAddr
,
1602 const GLchan
*src
=tempImage
;
1603 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1604 + dstZoffset
* dstImageStride
1605 + dstYoffset
* dstRowStride
1606 + dstXoffset
* dstFormat
->TexelBytes
;
1607 GLint img
, row
, col
;
1610 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1611 for (img
= 0; img
< srcDepth
; img
++) {
1612 GLubyte
*dstRow
= dstImage
;
1613 for (row
= 0; row
< srcHeight
; row
++) {
1614 GLushort
*dstUS
= (GLushort
*) dstRow
;
1615 if (dstFormat
== &_mesa_texformat_argb1555
) {
1616 for (col
= 0; col
< srcWidth
; col
++) {
1617 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1618 CHAN_TO_UBYTE(src
[RCOMP
]),
1619 CHAN_TO_UBYTE(src
[GCOMP
]),
1620 CHAN_TO_UBYTE(src
[BCOMP
]) );
1625 for (col
= 0; col
< srcWidth
; col
++) {
1626 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1627 CHAN_TO_UBYTE(src
[RCOMP
]),
1628 CHAN_TO_UBYTE(src
[GCOMP
]),
1629 CHAN_TO_UBYTE(src
[BCOMP
]) );
1633 dstRow
+= dstRowStride
;
1635 dstImage
+= dstImageStride
;
1637 _mesa_free((void *) tempImage
);
1644 _mesa_texstore_al88(STORE_PARAMS
)
1646 const GLuint ui
= 1;
1647 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1649 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1650 dstFormat
== &_mesa_texformat_al88_rev
);
1651 ASSERT(dstFormat
->TexelBytes
== 2);
1653 if (!ctx
->_ImageTransferState
&&
1654 !srcPacking
->SwapBytes
&&
1655 dstFormat
== &_mesa_texformat_al88
&&
1656 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1657 srcFormat
== GL_LUMINANCE_ALPHA
&&
1658 srcType
== GL_UNSIGNED_BYTE
&&
1660 /* simple memcpy path */
1661 memcpy_texture(dims
,
1662 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1663 dstRowStride
, dstImageStride
,
1664 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1665 srcAddr
, srcPacking
);
1669 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1671 dstFormat
->BaseFormat
,
1672 srcWidth
, srcHeight
, srcDepth
,
1673 srcFormat
, srcType
, srcAddr
,
1675 const GLchan
*src
= tempImage
;
1676 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1677 + dstZoffset
* dstImageStride
1678 + dstYoffset
* dstRowStride
1679 + dstXoffset
* dstFormat
->TexelBytes
;
1680 GLint img
, row
, col
;
1683 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1684 for (img
= 0; img
< srcDepth
; img
++) {
1685 GLubyte
*dstRow
= dstImage
;
1686 for (row
= 0; row
< srcHeight
; row
++) {
1687 GLushort
*dstUS
= (GLushort
*) dstRow
;
1688 if (dstFormat
== &_mesa_texformat_al88
) {
1689 for (col
= 0; col
< srcWidth
; col
++) {
1690 /* src[0] is luminance, src[1] is alpha */
1691 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1692 CHAN_TO_UBYTE(src
[0]) );
1697 for (col
= 0; col
< srcWidth
; col
++) {
1698 /* src[0] is luminance, src[1] is alpha */
1699 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1700 CHAN_TO_UBYTE(src
[0]) );
1704 dstRow
+= dstRowStride
;
1706 dstImage
+= dstImageStride
;
1708 _mesa_free((void *) tempImage
);
1715 _mesa_texstore_rgb332(STORE_PARAMS
)
1717 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1718 ASSERT(dstFormat
->TexelBytes
== 1);
1720 if (!ctx
->_ImageTransferState
&&
1721 !srcPacking
->SwapBytes
&&
1722 baseInternalFormat
== GL_RGB
&&
1723 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1724 /* simple memcpy path */
1725 memcpy_texture(dims
,
1726 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1727 dstRowStride
, dstImageStride
,
1728 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1729 srcAddr
, srcPacking
);
1733 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1735 dstFormat
->BaseFormat
,
1736 srcWidth
, srcHeight
, srcDepth
,
1737 srcFormat
, srcType
, srcAddr
,
1739 const GLchan
*src
= tempImage
;
1740 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1741 + dstZoffset
* dstImageStride
1742 + dstYoffset
* dstRowStride
1743 + dstXoffset
* dstFormat
->TexelBytes
;
1744 GLint img
, row
, col
;
1747 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1748 for (img
= 0; img
< srcDepth
; img
++) {
1749 GLubyte
*dstRow
= dstImage
;
1750 for (row
= 0; row
< srcHeight
; row
++) {
1751 for (col
= 0; col
< srcWidth
; col
++) {
1752 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1753 CHAN_TO_UBYTE(src
[GCOMP
]),
1754 CHAN_TO_UBYTE(src
[BCOMP
]) );
1757 dstRow
+= dstRowStride
;
1759 dstImage
+= dstImageStride
;
1761 _mesa_free((void *) tempImage
);
1768 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1771 _mesa_texstore_a8(STORE_PARAMS
)
1773 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1774 dstFormat
== &_mesa_texformat_l8
||
1775 dstFormat
== &_mesa_texformat_i8
);
1776 ASSERT(dstFormat
->TexelBytes
== 1);
1778 if (!ctx
->_ImageTransferState
&&
1779 !srcPacking
->SwapBytes
&&
1780 baseInternalFormat
== srcFormat
&&
1781 srcType
== GL_UNSIGNED_BYTE
) {
1782 /* simple memcpy path */
1783 memcpy_texture(dims
,
1784 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1785 dstRowStride
, dstImageStride
,
1786 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1787 srcAddr
, srcPacking
);
1791 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1793 dstFormat
->BaseFormat
,
1794 srcWidth
, srcHeight
, srcDepth
,
1795 srcFormat
, srcType
, srcAddr
,
1797 const GLchan
*src
= tempImage
;
1798 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1799 + dstZoffset
* dstImageStride
1800 + dstYoffset
* dstRowStride
1801 + dstXoffset
* dstFormat
->TexelBytes
;
1802 GLint img
, row
, col
;
1805 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1806 for (img
= 0; img
< srcDepth
; img
++) {
1807 GLubyte
*dstRow
= dstImage
;
1808 for (row
= 0; row
< srcHeight
; row
++) {
1809 for (col
= 0; col
< srcWidth
; col
++) {
1810 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1812 dstRow
+= dstRowStride
;
1815 dstImage
+= dstImageStride
;
1817 _mesa_free((void *) tempImage
);
1825 _mesa_texstore_ci8(STORE_PARAMS
)
1827 (void) dims
; (void) baseInternalFormat
;
1828 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1829 ASSERT(dstFormat
->TexelBytes
== 1);
1830 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1832 if (!ctx
->_ImageTransferState
&&
1833 !srcPacking
->SwapBytes
&&
1834 srcFormat
== GL_COLOR_INDEX
&&
1835 srcType
== GL_UNSIGNED_BYTE
) {
1836 /* simple memcpy path */
1837 memcpy_texture(dims
,
1838 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1839 dstRowStride
, dstImageStride
,
1840 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1841 srcAddr
, srcPacking
);
1845 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1846 + dstZoffset
* dstImageStride
1847 + dstYoffset
* dstRowStride
1848 + dstXoffset
* dstFormat
->TexelBytes
;
1850 for (img
= 0; img
< srcDepth
; img
++) {
1851 GLubyte
*dstRow
= dstImage
;
1852 for (row
= 0; row
< srcHeight
; row
++) {
1853 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1854 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1855 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1856 srcType
, src
, srcPacking
,
1857 ctx
->_ImageTransferState
);
1858 dstRow
+= dstRowStride
;
1860 dstImage
+= dstImageStride
;
1868 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1871 _mesa_texstore_ycbcr(STORE_PARAMS
)
1873 const GLuint ui
= 1;
1874 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1875 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
1877 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1878 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1879 ASSERT(dstFormat
->TexelBytes
== 2);
1880 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1881 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1882 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1883 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1884 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1886 /* always just memcpy since no pixel transfer ops apply */
1887 memcpy_texture(dims
,
1888 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1889 dstRowStride
, dstImageStride
,
1890 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1891 srcAddr
, srcPacking
);
1893 /* Check if we need byte swapping */
1894 /* XXX the logic here _might_ be wrong */
1895 if (srcPacking
->SwapBytes
^
1896 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1897 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1899 GLushort
*pImage
= (GLushort
*) ((GLubyte
*) dstAddr
1900 + dstZoffset
* dstImageStride
1901 + dstYoffset
* dstRowStride
1902 + dstXoffset
* dstFormat
->TexelBytes
);
1904 for (img
= 0; img
< srcDepth
; img
++) {
1905 GLushort
*pRow
= pImage
;
1906 for (row
= 0; row
< srcHeight
; row
++) {
1907 _mesa_swap2(pRow
, srcWidth
);
1908 pRow
+= dstRowStride
;
1910 pImage
+= dstImageStride
;
1920 * Store an image in any of the formats:
1921 * _mesa_texformat_rgba_float32
1922 * _mesa_texformat_rgb_float32
1923 * _mesa_texformat_alpha_float32
1924 * _mesa_texformat_luminance_float32
1925 * _mesa_texformat_luminance_alpha_float32
1926 * _mesa_texformat_intensity_float32
1929 _mesa_texstore_rgba_float32(STORE_PARAMS
)
1931 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1933 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
1934 dstFormat
== &_mesa_texformat_rgb_float32
||
1935 dstFormat
== &_mesa_texformat_alpha_float32
||
1936 dstFormat
== &_mesa_texformat_luminance_float32
||
1937 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
1938 dstFormat
== &_mesa_texformat_intensity_float32
);
1939 ASSERT(baseInternalFormat
== GL_RGBA
||
1940 baseInternalFormat
== GL_RGB
||
1941 baseInternalFormat
== GL_ALPHA
||
1942 baseInternalFormat
== GL_LUMINANCE
||
1943 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1944 baseInternalFormat
== GL_INTENSITY
);
1945 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
1947 if (!ctx
->_ImageTransferState
&&
1948 !srcPacking
->SwapBytes
&&
1949 baseInternalFormat
== srcFormat
&&
1950 srcType
== GL_FLOAT
) {
1951 /* simple memcpy path */
1952 memcpy_texture(dims
,
1953 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1954 dstRowStride
, dstImageStride
,
1955 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1956 srcAddr
, srcPacking
);
1960 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1962 dstFormat
->BaseFormat
,
1963 srcWidth
, srcHeight
, srcDepth
,
1964 srcFormat
, srcType
, srcAddr
,
1966 const GLfloat
*src
= tempImage
;
1968 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1969 + dstZoffset
* dstImageStride
1970 + dstYoffset
* dstRowStride
1971 + dstXoffset
* dstFormat
->TexelBytes
;
1975 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1976 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
1977 for (img
= 0; img
< srcDepth
; img
++) {
1978 GLubyte
*dst
= dstImage
;
1979 for (row
= 0; row
< srcHeight
; row
++) {
1980 _mesa_memcpy(dst
, src
, bytesPerRow
);
1981 dst
+= dstRowStride
;
1982 src
+= srcWidth
* components
;
1984 dstImage
+= dstImageStride
;
1987 _mesa_free((void *) tempImage
);
1994 * As above, but store 16-bit floats.
1997 _mesa_texstore_rgba_float16(STORE_PARAMS
)
1999 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
2001 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2002 dstFormat
== &_mesa_texformat_rgb_float16
||
2003 dstFormat
== &_mesa_texformat_alpha_float16
||
2004 dstFormat
== &_mesa_texformat_luminance_float16
||
2005 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2006 dstFormat
== &_mesa_texformat_intensity_float16
);
2007 ASSERT(baseInternalFormat
== GL_RGBA
||
2008 baseInternalFormat
== GL_RGB
||
2009 baseInternalFormat
== GL_ALPHA
||
2010 baseInternalFormat
== GL_LUMINANCE
||
2011 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2012 baseInternalFormat
== GL_INTENSITY
);
2013 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2015 if (!ctx
->_ImageTransferState
&&
2016 !srcPacking
->SwapBytes
&&
2017 baseInternalFormat
== srcFormat
&&
2018 srcType
== GL_HALF_FLOAT_ARB
) {
2019 /* simple memcpy path */
2020 memcpy_texture(dims
,
2021 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2022 dstRowStride
, dstImageStride
,
2023 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2024 srcAddr
, srcPacking
);
2028 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2030 dstFormat
->BaseFormat
,
2031 srcWidth
, srcHeight
, srcDepth
,
2032 srcFormat
, srcType
, srcAddr
,
2034 const GLfloat
*src
= tempImage
;
2035 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2036 + dstZoffset
* dstImageStride
2037 + dstYoffset
* dstRowStride
2038 + dstXoffset
* dstFormat
->TexelBytes
;
2042 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2043 for (img
= 0; img
< srcDepth
; img
++) {
2044 GLubyte
*dstRow
= dstImage
;
2045 for (row
= 0; row
< srcHeight
; row
++) {
2046 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2048 for (i
= 0; i
< srcWidth
* components
; i
++) {
2049 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2051 dstRow
+= dstRowStride
;
2052 src
+= srcWidth
* components
;
2054 dstImage
+= dstImageStride
;
2057 _mesa_free((void *) tempImage
);
2065 * Check if an unpack PBO is active prior to fetching a texture image.
2066 * If so, do bounds checking and map the buffer into main memory.
2067 * Any errors detected will be recorded.
2068 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2071 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2072 GLsizei width
, GLsizei height
, GLsizei depth
,
2073 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2074 const struct gl_pixelstore_attrib
*unpack
,
2075 const char *funcName
)
2079 if (unpack
->BufferObj
->Name
== 0) {
2083 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2084 format
, type
, pixels
)) {
2085 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2089 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2090 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2092 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2096 return ADD_POINTERS(buf
, pixels
);
2101 * Check if an unpack PBO is active prior to fetching a compressed texture
2103 * If so, do bounds checking and map the buffer into main memory.
2104 * Any errors detected will be recorded.
2105 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2108 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2109 GLsizei imageSize
, const GLvoid
*pixels
,
2110 const struct gl_pixelstore_attrib
*packing
,
2111 const char *funcName
)
2115 if (packing
->BufferObj
->Name
== 0) {
2116 /* not using a PBO - return pointer unchanged */
2119 if ((const GLubyte
*) pixels
+ imageSize
>
2120 (const GLubyte
*) packing
->BufferObj
->Size
) {
2121 /* out of bounds read! */
2122 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2126 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2127 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2129 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2133 return ADD_POINTERS(buf
, pixels
);
2138 * This function must be called after either of the validate_pbo_*_teximage()
2139 * functions. It unmaps the PBO buffer if it was mapped earlier.
2142 _mesa_unmap_teximage_pbo(GLcontext
*ctx
, const struct gl_pixelstore_attrib
*unpack
)
2144 if (unpack
->BufferObj
->Name
) {
2145 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2152 * This is the software fallback for Driver.TexImage1D()
2153 * and Driver.CopyTexImage1D().
2154 * \sa _mesa_store_teximage2d()
2157 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2158 GLint internalFormat
,
2159 GLint width
, GLint border
,
2160 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2161 const struct gl_pixelstore_attrib
*packing
,
2162 struct gl_texture_object
*texObj
,
2163 struct gl_texture_image
*texImage
)
2165 GLint postConvWidth
= width
;
2169 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2170 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2173 /* choose the texture format */
2174 assert(ctx
->Driver
.ChooseTextureFormat
);
2175 texImage
->TexFormat
= ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
,
2177 assert(texImage
->TexFormat
);
2178 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2179 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2181 /* allocate memory */
2182 if (texImage
->IsCompressed
)
2183 sizeInBytes
= texImage
->CompressedSize
;
2185 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2186 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2187 if (!texImage
->Data
) {
2188 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2192 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
, pixels
,
2193 packing
, "glTexImage1D");
2195 /* Note: we check for a NULL image pointer here, _after_ we allocated
2196 * memory for the texture. That's what the GL spec calls for.
2201 const GLint dstRowStride
= 0, dstImageStride
= 0;
2203 ASSERT(texImage
->TexFormat
->StoreImage
);
2204 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2205 texImage
->TexFormat
,
2207 0, 0, 0, /* dstX/Y/Zoffset */
2208 dstRowStride
, dstImageStride
,
2210 format
, type
, pixels
, packing
);
2212 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2216 /* GL_SGIS_generate_mipmap */
2217 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2218 _mesa_generate_mipmap(ctx
, target
,
2219 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2223 _mesa_unmap_teximage_pbo(ctx
, packing
);
2228 * This is the software fallback for Driver.TexImage2D()
2229 * and Driver.CopyTexImage2D().
2230 * We store the image in heap memory. We know nothing about on-board
2231 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2232 * textures in main memory, this routine will typically be used by
2233 * hardware drivers too.
2235 * Reasons why a driver might override this function:
2236 * - Special memory allocation needs (VRAM, AGP, etc)
2237 * - Unusual row/image strides or padding
2238 * - Special housekeeping
2239 * - Using VRAM-based Pixel Buffer Objects
2242 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2243 GLint internalFormat
,
2244 GLint width
, GLint height
, GLint border
,
2245 GLenum format
, GLenum type
, const void *pixels
,
2246 const struct gl_pixelstore_attrib
*packing
,
2247 struct gl_texture_object
*texObj
,
2248 struct gl_texture_image
*texImage
)
2250 GLint postConvWidth
= width
, postConvHeight
= height
;
2251 GLint texelBytes
, sizeInBytes
;
2254 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2255 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2259 /* choose the texture format */
2260 assert(ctx
->Driver
.ChooseTextureFormat
);
2261 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2262 internalFormat
, format
, type
);
2263 assert(texImage
->TexFormat
);
2264 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2265 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2267 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2269 /* allocate memory */
2270 if (texImage
->IsCompressed
)
2271 sizeInBytes
= texImage
->CompressedSize
;
2273 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2274 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2275 if (!texImage
->Data
) {
2276 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2280 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2281 pixels
, packing
, "glTexImage2D");
2283 /* Note: we check for a NULL image pointer here, _after_ we allocated
2284 * memory for the texture. That's what the GL spec calls for.
2289 GLint dstRowStride
, dstImageStride
= 0;
2291 if (texImage
->IsCompressed
) {
2292 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2295 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2297 ASSERT(texImage
->TexFormat
->StoreImage
);
2298 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2299 texImage
->TexFormat
,
2301 0, 0, 0, /* dstX/Y/Zoffset */
2302 dstRowStride
, dstImageStride
,
2304 format
, type
, pixels
, packing
);
2306 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2310 /* GL_SGIS_generate_mipmap */
2311 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2312 _mesa_generate_mipmap(ctx
, target
,
2313 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2317 _mesa_unmap_teximage_pbo(ctx
, packing
);
2323 * This is the software fallback for Driver.TexImage3D()
2324 * and Driver.CopyTexImage3D().
2325 * \sa _mesa_store_teximage2d()
2328 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2329 GLint internalFormat
,
2330 GLint width
, GLint height
, GLint depth
, GLint border
,
2331 GLenum format
, GLenum type
, const void *pixels
,
2332 const struct gl_pixelstore_attrib
*packing
,
2333 struct gl_texture_object
*texObj
,
2334 struct gl_texture_image
*texImage
)
2336 GLint texelBytes
, sizeInBytes
;
2339 /* choose the texture format */
2340 assert(ctx
->Driver
.ChooseTextureFormat
);
2341 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2342 internalFormat
, format
, type
);
2343 assert(texImage
->TexFormat
);
2344 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2345 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2347 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2349 /* allocate memory */
2350 if (texImage
->IsCompressed
)
2351 sizeInBytes
= texImage
->CompressedSize
;
2353 sizeInBytes
= width
* height
* depth
* texelBytes
;
2354 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2355 if (!texImage
->Data
) {
2356 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2360 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
, type
,
2361 pixels
, packing
, "glTexImage3D");
2363 /* Note: we check for a NULL image pointer here, _after_ we allocated
2364 * memory for the texture. That's what the GL spec calls for.
2369 GLint dstRowStride
, dstImageStride
;
2371 if (texImage
->IsCompressed
) {
2372 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2376 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2377 dstImageStride
= dstRowStride
* height
;
2379 ASSERT(texImage
->TexFormat
->StoreImage
);
2380 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2381 texImage
->TexFormat
,
2383 0, 0, 0, /* dstX/Y/Zoffset */
2384 dstRowStride
, dstImageStride
,
2385 width
, height
, depth
,
2386 format
, type
, pixels
, packing
);
2388 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2392 /* GL_SGIS_generate_mipmap */
2393 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2394 _mesa_generate_mipmap(ctx
, target
,
2395 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2399 _mesa_unmap_teximage_pbo(ctx
, packing
);
2406 * This is the software fallback for Driver.TexSubImage1D()
2407 * and Driver.CopyTexSubImage1D().
2410 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2411 GLint xoffset
, GLint width
,
2412 GLenum format
, GLenum type
, const void *pixels
,
2413 const struct gl_pixelstore_attrib
*packing
,
2414 struct gl_texture_object
*texObj
,
2415 struct gl_texture_image
*texImage
)
2417 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
, pixels
,
2418 packing
, "glTexSubImage1D");
2423 const GLint dstRowStride
= 0, dstImageStride
= 0;
2425 ASSERT(texImage
->TexFormat
->StoreImage
);
2426 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2427 texImage
->TexFormat
,
2429 xoffset
, 0, 0, /* offsets */
2430 dstRowStride
, dstImageStride
,
2432 format
, type
, pixels
, packing
);
2434 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2438 /* GL_SGIS_generate_mipmap */
2439 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2440 _mesa_generate_mipmap(ctx
, target
,
2441 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2445 _mesa_unmap_teximage_pbo(ctx
, packing
);
2451 * This is the software fallback for Driver.TexSubImage2D()
2452 * and Driver.CopyTexSubImage2D().
2455 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2456 GLint xoffset
, GLint yoffset
,
2457 GLint width
, GLint height
,
2458 GLenum format
, GLenum type
, const void *pixels
,
2459 const struct gl_pixelstore_attrib
*packing
,
2460 struct gl_texture_object
*texObj
,
2461 struct gl_texture_image
*texImage
)
2463 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2464 pixels
, packing
, "glTexSubImage2D");
2469 GLint dstRowStride
= 0, dstImageStride
= 0;
2471 if (texImage
->IsCompressed
) {
2472 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2476 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2478 ASSERT(texImage
->TexFormat
->StoreImage
);
2479 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2480 texImage
->TexFormat
,
2482 xoffset
, yoffset
, 0,
2483 dstRowStride
, dstImageStride
,
2485 format
, type
, pixels
, packing
);
2487 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2491 /* GL_SGIS_generate_mipmap */
2492 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2493 _mesa_generate_mipmap(ctx
, target
,
2494 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2498 _mesa_unmap_teximage_pbo(ctx
, packing
);
2503 * This is the software fallback for Driver.TexSubImage3D().
2504 * and Driver.CopyTexSubImage3D().
2507 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2508 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2509 GLint width
, GLint height
, GLint depth
,
2510 GLenum format
, GLenum type
, const void *pixels
,
2511 const struct gl_pixelstore_attrib
*packing
,
2512 struct gl_texture_object
*texObj
,
2513 struct gl_texture_image
*texImage
)
2515 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
, type
,
2516 pixels
, packing
, "glTexSubImage3D");
2521 GLint dstRowStride
, dstImageStride
;
2523 if (texImage
->IsCompressed
) {
2524 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2526 dstImageStride
= 0; /* XXX fix */
2529 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2530 dstImageStride
= dstRowStride
* texImage
->Height
;
2532 ASSERT(texImage
->TexFormat
->StoreImage
);
2533 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2534 texImage
->TexFormat
,
2536 xoffset
, yoffset
, zoffset
,
2537 dstRowStride
, dstImageStride
,
2538 width
, height
, depth
,
2539 format
, type
, pixels
, packing
);
2541 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2545 /* GL_SGIS_generate_mipmap */
2546 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2547 _mesa_generate_mipmap(ctx
, target
,
2548 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2552 _mesa_unmap_teximage_pbo(ctx
, packing
);
2557 * Fallback for Driver.CompressedTexImage1D()
2560 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2561 GLint internalFormat
,
2562 GLint width
, GLint border
,
2563 GLsizei imageSize
, const GLvoid
*data
,
2564 struct gl_texture_object
*texObj
,
2565 struct gl_texture_image
*texImage
)
2567 /* this space intentionally left blank */
2569 (void) target
; (void) level
;
2570 (void) internalFormat
;
2571 (void) width
; (void) border
;
2572 (void) imageSize
; (void) data
;
2580 * Fallback for Driver.CompressedTexImage2D()
2583 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2584 GLint internalFormat
,
2585 GLint width
, GLint height
, GLint border
,
2586 GLsizei imageSize
, const GLvoid
*data
,
2587 struct gl_texture_object
*texObj
,
2588 struct gl_texture_image
*texImage
)
2590 (void) width
; (void) height
; (void) border
;
2592 /* This is pretty simple, basically just do a memcpy without worrying
2593 * about the usual image unpacking or image transfer operations.
2597 ASSERT(texImage
->Width
> 0);
2598 ASSERT(texImage
->Height
> 0);
2599 ASSERT(texImage
->Depth
== 1);
2600 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2602 /* choose the texture format */
2603 assert(ctx
->Driver
.ChooseTextureFormat
);
2604 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2605 internalFormat
, 0, 0);
2606 assert(texImage
->TexFormat
);
2607 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2608 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2610 /* allocate storage */
2611 texImage
->Data
= MESA_PBUFFER_ALLOC(imageSize
);
2612 if (!texImage
->Data
) {
2613 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2617 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
, &ctx
->Unpack
,
2618 "glCompressedTexImage2D");
2623 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2624 MEMCPY(texImage
->Data
, data
, imageSize
);
2626 /* GL_SGIS_generate_mipmap */
2627 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2628 _mesa_generate_mipmap(ctx
, target
,
2629 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2633 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2639 * Fallback for Driver.CompressedTexImage3D()
2642 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2643 GLint internalFormat
,
2644 GLint width
, GLint height
, GLint depth
,
2646 GLsizei imageSize
, const GLvoid
*data
,
2647 struct gl_texture_object
*texObj
,
2648 struct gl_texture_image
*texImage
)
2650 /* this space intentionally left blank */
2652 (void) target
; (void) level
;
2653 (void) internalFormat
;
2654 (void) width
; (void) height
; (void) depth
;
2656 (void) imageSize
; (void) data
;
2664 * Fallback for Driver.CompressedTexSubImage1D()
2667 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2669 GLint xoffset
, GLsizei width
,
2671 GLsizei imageSize
, const GLvoid
*data
,
2672 struct gl_texture_object
*texObj
,
2673 struct gl_texture_image
*texImage
)
2675 /* this space intentionally left blank */
2677 (void) target
; (void) level
;
2678 (void) xoffset
; (void) width
;
2680 (void) imageSize
; (void) data
;
2687 * Fallback for Driver.CompressedTexSubImage2D()
2690 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2692 GLint xoffset
, GLint yoffset
,
2693 GLsizei width
, GLsizei height
,
2695 GLsizei imageSize
, const GLvoid
*data
,
2696 struct gl_texture_object
*texObj
,
2697 struct gl_texture_image
*texImage
)
2699 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2705 /* these should have been caught sooner */
2706 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2707 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2708 ASSERT((xoffset
& 3) == 0);
2709 ASSERT((yoffset
& 3) == 0);
2711 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
, &ctx
->Unpack
,
2712 "glCompressedTexSubImage2D");
2716 srcRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
, width
);
2717 src
= (const GLubyte
*) data
;
2719 destRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2721 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2722 texImage
->IntFormat
,
2724 (GLubyte
*) texImage
->Data
);
2726 bytesPerRow
= srcRowStride
;
2729 for (i
= 0; i
< rows
; i
++) {
2730 MEMCPY(dest
, src
, bytesPerRow
);
2731 dest
+= destRowStride
;
2732 src
+= srcRowStride
;
2735 /* GL_SGIS_generate_mipmap */
2736 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2737 _mesa_generate_mipmap(ctx
, target
,
2738 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2742 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2747 * Fallback for Driver.CompressedTexSubImage3D()
2750 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2752 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2753 GLsizei width
, GLsizei height
, GLsizei depth
,
2755 GLsizei imageSize
, const GLvoid
*data
,
2756 struct gl_texture_object
*texObj
,
2757 struct gl_texture_image
*texImage
)
2759 /* this space intentionally left blank */
2761 (void) target
; (void) level
;
2762 (void) xoffset
; (void) yoffset
; (void) zoffset
;
2763 (void) width
; (void) height
; (void) depth
;
2765 (void) imageSize
; (void) data
;
2772 * Average together two rows of a source image to produce a single new
2773 * row in the dest image. It's legal for the two source rows to point
2774 * to the same data. The source width must be equal to either the
2775 * dest width or two times the dest width.
2778 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
2779 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
2780 GLint dstWidth
, GLvoid
*dstRow
)
2782 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
2783 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
2785 /* This assertion is no longer valid with non-power-of-2 textures
2786 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2789 switch (format
->MesaFormat
) {
2790 case MESA_FORMAT_RGBA
:
2793 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
2794 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
2795 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
2796 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2797 i
++, j
+= colStride
, k
+= colStride
) {
2798 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2799 rowB
[j
][0] + rowB
[k
][0]) / 4;
2800 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2801 rowB
[j
][1] + rowB
[k
][1]) / 4;
2802 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2803 rowB
[j
][2] + rowB
[k
][2]) / 4;
2804 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2805 rowB
[j
][3] + rowB
[k
][3]) / 4;
2809 case MESA_FORMAT_RGB
:
2812 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
2813 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
2814 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
2815 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2816 i
++, j
+= colStride
, k
+= colStride
) {
2817 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2818 rowB
[j
][0] + rowB
[k
][0]) / 4;
2819 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2820 rowB
[j
][1] + rowB
[k
][1]) / 4;
2821 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2822 rowB
[j
][2] + rowB
[k
][2]) / 4;
2826 case MESA_FORMAT_ALPHA
:
2827 case MESA_FORMAT_LUMINANCE
:
2828 case MESA_FORMAT_INTENSITY
:
2831 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
2832 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
2833 GLchan
*dst
= (GLchan
*) dstRow
;
2834 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2835 i
++, j
+= colStride
, k
+= colStride
) {
2836 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2840 case MESA_FORMAT_LUMINANCE_ALPHA
:
2843 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
2844 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
2845 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
2846 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2847 i
++, j
+= colStride
, k
+= colStride
) {
2848 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2849 rowB
[j
][0] + rowB
[k
][0]) / 4;
2850 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2851 rowB
[j
][1] + rowB
[k
][1]) / 4;
2855 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32
:
2858 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2859 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2860 GLfloat
*dst
= (GLfloat
*) 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
]) * 0.25F
;
2867 case MESA_FORMAT_DEPTH_COMPONENT16
:
2870 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2871 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2872 GLushort
*dst
= (GLushort
*) dstRow
;
2873 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2874 i
++, j
+= colStride
, k
+= colStride
) {
2875 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2879 /* Begin hardware formats */
2880 case MESA_FORMAT_RGBA8888
:
2881 case MESA_FORMAT_RGBA8888_REV
:
2882 case MESA_FORMAT_ARGB8888
:
2883 case MESA_FORMAT_ARGB8888_REV
:
2886 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
2887 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
2888 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
2889 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2890 i
++, j
+= colStride
, k
+= colStride
) {
2891 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2892 rowB
[j
][0] + rowB
[k
][0]) / 4;
2893 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2894 rowB
[j
][1] + rowB
[k
][1]) / 4;
2895 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2896 rowB
[j
][2] + rowB
[k
][2]) / 4;
2897 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2898 rowB
[j
][3] + rowB
[k
][3]) / 4;
2902 case MESA_FORMAT_RGB888
:
2903 case MESA_FORMAT_BGR888
:
2906 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
2907 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
2908 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
2909 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2910 i
++, j
+= colStride
, k
+= colStride
) {
2911 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2912 rowB
[j
][0] + rowB
[k
][0]) / 4;
2913 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2914 rowB
[j
][1] + rowB
[k
][1]) / 4;
2915 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2916 rowB
[j
][2] + rowB
[k
][2]) / 4;
2920 case MESA_FORMAT_RGB565
:
2921 case MESA_FORMAT_RGB565_REV
:
2924 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2925 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2926 GLushort
*dst
= (GLushort
*) dstRow
;
2927 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2928 i
++, j
+= colStride
, k
+= colStride
) {
2929 const GLint rowAr0
= rowA
[j
] & 0x1f;
2930 const GLint rowAr1
= rowA
[k
] & 0x1f;
2931 const GLint rowBr0
= rowB
[j
] & 0x1f;
2932 const GLint rowBr1
= rowB
[k
] & 0x1f;
2933 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
2934 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
2935 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
2936 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
2937 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
2938 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
2939 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
2940 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
2941 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2942 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2943 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2944 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
2948 case MESA_FORMAT_ARGB4444
:
2949 case MESA_FORMAT_ARGB4444_REV
:
2952 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2953 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2954 GLushort
*dst
= (GLushort
*) dstRow
;
2955 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2956 i
++, j
+= colStride
, k
+= colStride
) {
2957 const GLint rowAr0
= rowA
[j
] & 0xf;
2958 const GLint rowAr1
= rowA
[k
] & 0xf;
2959 const GLint rowBr0
= rowB
[j
] & 0xf;
2960 const GLint rowBr1
= rowB
[k
] & 0xf;
2961 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
2962 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
2963 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
2964 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
2965 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
2966 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
2967 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
2968 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
2969 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
2970 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
2971 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
2972 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
2973 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2974 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2975 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2976 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2977 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
2981 case MESA_FORMAT_ARGB1555
:
2982 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
2985 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2986 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2987 GLushort
*dst
= (GLushort
*) dstRow
;
2988 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2989 i
++, j
+= colStride
, k
+= colStride
) {
2990 const GLint rowAr0
= rowA
[j
] & 0x1f;
2991 const GLint rowAr1
= rowA
[k
] & 0x1f;
2992 const GLint rowBr0
= rowB
[j
] & 0x1f;
2993 const GLint rowBr1
= rowB
[k
] & 0xf;
2994 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
2995 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
2996 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
2997 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
2998 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
2999 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3000 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3001 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3002 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3003 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3004 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3005 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3006 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3007 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3008 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3009 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3010 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3014 case MESA_FORMAT_AL88
:
3015 case MESA_FORMAT_AL88_REV
:
3018 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3019 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3020 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3021 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3022 i
++, j
+= colStride
, k
+= colStride
) {
3023 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3024 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3025 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3026 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3030 case MESA_FORMAT_RGB332
:
3033 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3034 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3035 GLubyte
*dst
= (GLubyte
*) dstRow
;
3036 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3037 i
++, j
+= colStride
, k
+= colStride
) {
3038 const GLint rowAr0
= rowA
[j
] & 0x3;
3039 const GLint rowAr1
= rowA
[k
] & 0x3;
3040 const GLint rowBr0
= rowB
[j
] & 0x3;
3041 const GLint rowBr1
= rowB
[k
] & 0x3;
3042 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3043 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3044 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3045 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3046 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3047 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3048 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3049 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3050 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3051 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3052 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3053 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3057 case MESA_FORMAT_A8
:
3058 case MESA_FORMAT_L8
:
3059 case MESA_FORMAT_I8
:
3060 case MESA_FORMAT_CI8
:
3063 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3064 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3065 GLubyte
*dst
= (GLubyte
*) dstRow
;
3066 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3067 i
++, j
+= colStride
, k
+= colStride
) {
3068 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
3072 case MESA_FORMAT_RGBA_FLOAT32
:
3075 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3076 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3077 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
3078 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3079 i
++, j
+= colStride
, k
+= colStride
) {
3080 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3081 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3082 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3083 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3084 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3085 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3086 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3087 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3091 case MESA_FORMAT_RGBA_FLOAT16
:
3093 GLuint i
, j
, k
, comp
;
3094 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3095 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3096 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3097 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3098 i
++, j
+= colStride
, k
+= colStride
) {
3099 for (comp
= 0; comp
< 4; comp
++) {
3100 GLfloat aj
, ak
, bj
, bk
;
3101 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3102 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3103 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3104 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3105 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3110 case MESA_FORMAT_RGB_FLOAT32
:
3113 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3114 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3115 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3116 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3117 i
++, j
+= colStride
, k
+= colStride
) {
3118 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3119 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3120 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3121 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3122 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3123 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3127 case MESA_FORMAT_RGB_FLOAT16
:
3129 GLuint i
, j
, k
, comp
;
3130 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3131 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3132 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3133 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3134 i
++, j
+= colStride
, k
+= colStride
) {
3135 for (comp
= 0; comp
< 3; comp
++) {
3136 GLfloat aj
, ak
, bj
, bk
;
3137 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3138 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3139 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3140 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3141 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3146 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3149 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3150 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3151 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3152 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3153 i
++, j
+= colStride
, k
+= colStride
) {
3154 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3155 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3156 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3157 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3161 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3163 GLuint i
, j
, k
, comp
;
3164 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3165 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3166 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3167 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3168 i
++, j
+= colStride
, k
+= colStride
) {
3169 for (comp
= 0; comp
< 2; comp
++) {
3170 GLfloat aj
, ak
, bj
, bk
;
3171 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3172 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3173 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3174 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3175 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3180 case MESA_FORMAT_ALPHA_FLOAT32
:
3181 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3182 case MESA_FORMAT_INTENSITY_FLOAT32
:
3185 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3186 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3187 GLfloat
*dst
= (GLfloat
*) dstRow
;
3188 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3189 i
++, j
+= colStride
, k
+= colStride
) {
3190 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3194 case MESA_FORMAT_ALPHA_FLOAT16
:
3195 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3196 case MESA_FORMAT_INTENSITY_FLOAT16
:
3199 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3200 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3201 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3202 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3203 i
++, j
+= colStride
, k
+= colStride
) {
3204 GLfloat aj
, ak
, bj
, bk
;
3205 aj
= _mesa_half_to_float(rowA
[j
]);
3206 ak
= _mesa_half_to_float(rowA
[k
]);
3207 bj
= _mesa_half_to_float(rowB
[j
]);
3208 bk
= _mesa_half_to_float(rowB
[k
]);
3209 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3215 _mesa_problem(NULL
, "bad format in do_row()");
3221 * These functions generate a 1/2-size mipmap image from a source image.
3222 * Texture borders are handled by copying or averaging the source image's
3223 * border texels, depending on the scale-down factor.
3227 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3228 GLint srcWidth
, const GLubyte
*srcPtr
,
3229 GLint dstWidth
, GLubyte
*dstPtr
)
3231 const GLint bpt
= format
->TexelBytes
;
3235 /* skip the border pixel, if any */
3236 src
= srcPtr
+ border
* bpt
;
3237 dst
= dstPtr
+ border
* bpt
;
3239 /* we just duplicate the input row, kind of hack, saves code */
3240 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3241 dstWidth
- 2 * border
, dst
);
3244 /* copy left-most pixel from source */
3245 MEMCPY(dstPtr
, srcPtr
, bpt
);
3246 /* copy right-most pixel from source */
3247 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3248 srcPtr
+ (srcWidth
- 1) * bpt
,
3255 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3256 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3257 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3259 const GLint bpt
= format
->TexelBytes
;
3260 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3261 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3262 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3263 const GLint srcRowStride
= bpt
* srcWidth
;
3264 const GLint dstRowStride
= bpt
* dstWidth
;
3265 const GLubyte
*srcA
, *srcB
;
3269 /* Compute src and dst pointers, skipping any border */
3270 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3272 srcB
= srcA
+ srcRowStride
;
3275 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3277 for (row
= 0; row
< dstHeightNB
; row
++) {
3278 do_row(format
, srcWidthNB
, srcA
, srcB
,
3280 srcA
+= 2 * srcRowStride
;
3281 srcB
+= 2 * srcRowStride
;
3282 dst
+= dstRowStride
;
3285 /* This is ugly but probably won't be used much */
3287 /* fill in dest border */
3288 /* lower-left border pixel */
3289 MEMCPY(dstPtr
, srcPtr
, bpt
);
3290 /* lower-right border pixel */
3291 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3292 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3293 /* upper-left border pixel */
3294 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3295 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3296 /* upper-right border pixel */
3297 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3298 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3300 do_row(format
, srcWidthNB
,
3303 dstWidthNB
, dstPtr
+ bpt
);
3305 do_row(format
, srcWidthNB
,
3306 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3307 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3309 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3310 /* left and right borders */
3311 if (srcHeight
== dstHeight
) {
3312 /* copy border pixel from src to dst */
3313 for (row
= 1; row
< srcHeight
; row
++) {
3314 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3315 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3316 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3317 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3321 /* average two src pixels each dest pixel */
3322 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3324 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3325 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3326 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3328 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3329 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3330 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3338 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3339 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3340 const GLubyte
*srcPtr
,
3341 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3344 const GLint bpt
= format
->TexelBytes
;
3345 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3346 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3347 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3348 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3349 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3350 GLvoid
*tmpRowA
, *tmpRowB
;
3352 GLint bytesPerSrcImage
, bytesPerDstImage
;
3353 GLint bytesPerSrcRow
, bytesPerDstRow
;
3354 GLint srcImageOffset
, srcRowOffset
;
3356 (void) srcDepthNB
; /* silence warnings */
3358 /* Need two temporary row buffers */
3359 tmpRowA
= MALLOC(srcWidth
* bpt
);
3362 tmpRowB
= MALLOC(srcWidth
* bpt
);
3368 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3369 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3371 bytesPerSrcRow
= srcWidth
* bpt
;
3372 bytesPerDstRow
= dstWidth
* bpt
;
3374 /* Offset between adjacent src images to be averaged together */
3375 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3377 /* Offset between adjacent src rows to be averaged together */
3378 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3381 * Need to average together up to 8 src pixels for each dest pixel.
3382 * Break that down into 3 operations:
3383 * 1. take two rows from source image and average them together.
3384 * 2. take two rows from next source image and average them together.
3385 * 3. take the two averaged rows and average them for the final dst row.
3389 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3390 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3393 for (img
= 0; img
< dstDepthNB
; img
++) {
3394 /* first source image pointer, skipping border */
3395 const GLubyte
*imgSrcA
= srcPtr
3396 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3397 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3398 /* second source image pointer, skipping border */
3399 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3400 /* address of the dest image, skipping border */
3401 GLubyte
*imgDst
= dstPtr
3402 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3403 + img
* bytesPerDstImage
;
3405 /* setup the four source row pointers and the dest row pointer */
3406 const GLubyte
*srcImgARowA
= imgSrcA
;
3407 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3408 const GLubyte
*srcImgBRowA
= imgSrcB
;
3409 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3410 GLubyte
*dstImgRow
= imgDst
;
3412 for (row
= 0; row
< dstHeightNB
; row
++) {
3413 /* Average together two rows from first src image */
3414 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3415 srcWidthNB
, tmpRowA
);
3416 /* Average together two rows from second src image */
3417 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3418 srcWidthNB
, tmpRowB
);
3419 /* Average together the temp rows to make the final row */
3420 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3421 dstWidthNB
, dstImgRow
);
3422 /* advance to next rows */
3423 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3424 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3425 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3426 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3427 dstImgRow
+= bytesPerDstRow
;
3434 /* Luckily we can leverage the make_2d_mipmap() function here! */
3436 /* do front border image */
3437 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3438 dstWidth
, dstHeight
, dstPtr
);
3439 /* do back border image */
3440 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3441 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3442 dstWidth
, dstHeight
,
3443 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3444 /* do four remaining border edges that span the image slices */
3445 if (srcDepth
== dstDepth
) {
3446 /* just copy border pixels from src to dst */
3447 for (img
= 0; img
< dstDepthNB
; img
++) {
3451 /* do border along [img][row=0][col=0] */
3452 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3453 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3454 MEMCPY(dst
, src
, bpt
);
3456 /* do border along [img][row=dstHeight-1][col=0] */
3457 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3458 + (srcHeight
- 1) * bytesPerSrcRow
;
3459 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3460 + (dstHeight
- 1) * bytesPerDstRow
;
3461 MEMCPY(dst
, src
, bpt
);
3463 /* do border along [img][row=0][col=dstWidth-1] */
3464 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3465 + (srcWidth
- 1) * bpt
;
3466 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3467 + (dstWidth
- 1) * bpt
;
3468 MEMCPY(dst
, src
, bpt
);
3470 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3471 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3472 + (bytesPerSrcImage
- bpt
);
3473 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3474 + (bytesPerDstImage
- bpt
);
3475 MEMCPY(dst
, src
, bpt
);
3479 /* average border pixels from adjacent src image pairs */
3480 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3481 for (img
= 0; img
< dstDepthNB
; img
++) {
3485 /* do border along [img][row=0][col=0] */
3486 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3487 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3488 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3490 /* do border along [img][row=dstHeight-1][col=0] */
3491 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3492 + (srcHeight
- 1) * bytesPerSrcRow
;
3493 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3494 + (dstHeight
- 1) * bytesPerDstRow
;
3495 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3497 /* do border along [img][row=0][col=dstWidth-1] */
3498 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3499 + (srcWidth
- 1) * bpt
;
3500 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3501 + (dstWidth
- 1) * bpt
;
3502 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3504 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3505 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3506 + (bytesPerSrcImage
- bpt
);
3507 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3508 + (bytesPerDstImage
- bpt
);
3509 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3517 * For GL_SGIX_generate_mipmap:
3518 * Generate a complete set of mipmaps from texObj's base-level image.
3519 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3522 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3523 const struct gl_texture_unit
*texUnit
,
3524 struct gl_texture_object
*texObj
)
3526 const struct gl_texture_image
*srcImage
;
3527 const struct gl_texture_format
*convertFormat
;
3528 const GLubyte
*srcData
= NULL
;
3529 GLubyte
*dstData
= NULL
;
3530 GLint level
, maxLevels
;
3533 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3536 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3537 ASSERT(maxLevels
> 0); /* bad target */
3539 /* Find convertFormat - the format that do_row() will process */
3540 if (srcImage
->IsCompressed
) {
3541 /* setup for compressed textures */
3543 GLint components
, size
;
3546 assert(texObj
->Target
== GL_TEXTURE_2D
);
3548 if (srcImage
->Format
== GL_RGB
) {
3549 convertFormat
= &_mesa_texformat_rgb
;
3552 else if (srcImage
->Format
== GL_RGBA
) {
3553 convertFormat
= &_mesa_texformat_rgba
;
3557 _mesa_problem(ctx
, "bad srcImage->Format in _mesa_generate_mipmaps");
3561 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3562 size
= _mesa_bytes_per_pixel(srcImage
->Format
, CHAN_TYPE
)
3563 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3564 /* 20 extra bytes, just be safe when calling last FetchTexel */
3565 srcData
= (GLubyte
*) MALLOC(size
);
3567 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3570 dstData
= (GLubyte
*) MALLOC(size
/ 2); /* 1/4 would probably be OK */
3572 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3573 FREE((void *) srcData
);
3577 /* decompress base image here */
3578 dst
= (GLchan
*) srcData
;
3579 for (row
= 0; row
< srcImage
->Height
; row
++) {
3581 for (col
= 0; col
< srcImage
->Width
; col
++) {
3582 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3589 convertFormat
= srcImage
->TexFormat
;
3592 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3593 && level
< maxLevels
- 1; level
++) {
3594 /* generate image[level+1] from image[level] */
3595 const struct gl_texture_image
*srcImage
;
3596 struct gl_texture_image
*dstImage
;
3597 GLint srcWidth
, srcHeight
, srcDepth
;
3598 GLint dstWidth
, dstHeight
, dstDepth
;
3599 GLint border
, bytesPerTexel
;
3601 /* get src image parameters */
3602 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3604 srcWidth
= srcImage
->Width
;
3605 srcHeight
= srcImage
->Height
;
3606 srcDepth
= srcImage
->Depth
;
3607 border
= srcImage
->Border
;
3609 /* compute next (level+1) image size */
3610 if (srcWidth
- 2 * border
> 1) {
3611 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3614 dstWidth
= srcWidth
; /* can't go smaller */
3616 if (srcHeight
- 2 * border
> 1) {
3617 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3620 dstHeight
= srcHeight
; /* can't go smaller */
3622 if (srcDepth
- 2 * border
> 1) {
3623 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3626 dstDepth
= srcDepth
; /* can't go smaller */
3629 if (dstWidth
== srcWidth
&&
3630 dstHeight
== srcHeight
&&
3631 dstDepth
== srcDepth
) {
3633 if (srcImage
->IsCompressed
) {
3634 FREE((void *) srcData
);
3640 /* get dest gl_texture_image */
3641 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3643 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3647 /* Free old image data */
3649 MESA_PBUFFER_FREE(dstImage
->Data
);
3651 /* initialize new image */
3652 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3653 dstDepth
, border
, srcImage
->IntFormat
);
3654 dstImage
->DriverData
= NULL
;
3655 dstImage
->TexFormat
= srcImage
->TexFormat
;
3656 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3657 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3658 ASSERT(dstImage
->TexFormat
);
3659 ASSERT(dstImage
->FetchTexelc
);
3660 ASSERT(dstImage
->FetchTexelf
);
3662 /* Alloc new teximage data buffer.
3663 * Setup src and dest data pointers.
3665 if (dstImage
->IsCompressed
) {
3666 ASSERT(dstImage
->CompressedSize
> 0); /* set by init_teximage_fields*/
3667 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstImage
->CompressedSize
);
3668 if (!dstImage
->Data
) {
3669 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3672 /* srcData and dstData are already set */
3677 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
3678 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3679 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstWidth
* dstHeight
* dstDepth
3681 if (!dstImage
->Data
) {
3682 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3685 srcData
= (const GLubyte
*) srcImage
->Data
;
3686 dstData
= (GLubyte
*) dstImage
->Data
;
3690 * We use simple 2x2 averaging to compute the next mipmap level.
3694 make_1d_mipmap(convertFormat
, border
,
3699 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3700 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3701 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3702 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3703 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3704 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3705 make_2d_mipmap(convertFormat
, border
,
3706 srcWidth
, srcHeight
, srcData
,
3707 dstWidth
, dstHeight
, dstData
);
3710 make_3d_mipmap(convertFormat
, border
,
3711 srcWidth
, srcHeight
, srcDepth
, srcData
,
3712 dstWidth
, dstHeight
, dstDepth
, dstData
);
3714 case GL_TEXTURE_RECTANGLE_NV
:
3715 /* no mipmaps, do nothing */
3718 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3722 if (dstImage
->IsCompressed
) {
3724 /* compress image from dstData into dstImage->Data */
3725 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3726 GLint dstRowStride
= _mesa_compressed_row_stride(srcImage
->IntFormat
,
3728 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3729 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->Format
,
3730 dstImage
->TexFormat
,
3732 0, 0, 0, /* dstX/Y/Zoffset */
3733 dstRowStride
, 0, /* strides */
3734 dstWidth
, dstHeight
, 1, /* size */
3735 srcFormat
, CHAN_TYPE
,
3736 dstData
, /* src data, actually */
3737 &ctx
->DefaultPacking
);
3738 /* swap src and dest pointers */
3739 temp
= (GLubyte
*) srcData
;
3744 } /* loop over mipmap levels */
3749 * Helper function for drivers which need to rescale texture images to
3750 * certain aspect ratios.
3751 * Nearest filtering only (for broken hardware that can't support
3752 * all aspect ratios). This can be made a lot faster, but I don't
3753 * really care enough...
3756 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
3757 GLuint srcStrideInPixels
,
3758 GLuint dstRowStride
,
3759 GLint srcWidth
, GLint srcHeight
,
3760 GLint dstWidth
, GLint dstHeight
,
3761 const GLvoid
*srcImage
, GLvoid
*dstImage
)
3765 #define INNER_LOOP( TYPE, HOP, WOP ) \
3766 for ( row = 0 ; row < dstHeight ; row++ ) { \
3767 GLint srcRow = row HOP hScale; \
3768 for ( col = 0 ; col < dstWidth ; col++ ) { \
3769 GLint srcCol = col WOP wScale; \
3770 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3772 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3775 #define RESCALE_IMAGE( TYPE ) \
3777 const TYPE *src = (const TYPE *)srcImage; \
3778 TYPE *dst = (TYPE *)dstImage; \
3780 if ( srcHeight < dstHeight ) { \
3781 const GLint hScale = dstHeight / srcHeight; \
3782 if ( srcWidth < dstWidth ) { \
3783 const GLint wScale = dstWidth / srcWidth; \
3784 INNER_LOOP( TYPE, /, / ); \
3787 const GLint wScale = srcWidth / dstWidth; \
3788 INNER_LOOP( TYPE, /, * ); \
3792 const GLint hScale = srcHeight / dstHeight; \
3793 if ( srcWidth < dstWidth ) { \
3794 const GLint wScale = dstWidth / srcWidth; \
3795 INNER_LOOP( TYPE, *, / ); \
3798 const GLint wScale = srcWidth / dstWidth; \
3799 INNER_LOOP( TYPE, *, * ); \
3804 switch ( bytesPerPixel
) {
3806 RESCALE_IMAGE( GLuint
);
3810 RESCALE_IMAGE( GLushort
);
3814 RESCALE_IMAGE( GLubyte
);
3817 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3823 * Upscale an image by replication, not (typical) stretching.
3824 * We use this when the image width or height is less than a
3825 * certain size (4, 8) and we need to upscale an image.
3828 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
3829 GLsizei outWidth
, GLsizei outHeight
,
3830 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
3835 ASSERT(outWidth
>= inWidth
);
3836 ASSERT(outHeight
>= inHeight
);
3838 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
3839 ASSERT((outWidth
& 3) == 0);
3840 ASSERT((outHeight
& 3) == 0);
3843 for (i
= 0; i
< outHeight
; i
++) {
3844 const GLint ii
= i
% inHeight
;
3845 for (j
= 0; j
< outWidth
; j
++) {
3846 const GLint jj
= j
% inWidth
;
3847 for (k
= 0; k
< comps
; k
++) {
3848 dest
[(i
* outWidth
+ j
) * comps
+ k
]
3849 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
3858 * This is the software fallback for Driver.GetTexImage().
3859 * All error checking will have been done before this routine is called.
3862 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3863 GLenum format
, GLenum type
, GLvoid
*pixels
,
3864 const struct gl_texture_object
*texObj
,
3865 const struct gl_texture_image
*texImage
)
3867 GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
3869 if (ctx
->Pack
.BufferObj
->Name
) {
3870 /* pack texture image into a PBO */
3872 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
3873 texImage
->Height
, texImage
->Depth
,
3874 format
, type
, pixels
)) {
3875 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3876 "glGetTexImage(invalid PBO access)");
3879 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3881 ctx
->Pack
.BufferObj
);
3883 /* buffer is already mapped - that's an error */
3884 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
3887 pixels
= ADD_POINTERS(buf
, pixels
);
3895 const GLint width
= texImage
->Width
;
3896 const GLint height
= texImage
->Height
;
3897 const GLint depth
= texImage
->Depth
;
3899 for (img
= 0; img
< depth
; img
++) {
3900 for (row
= 0; row
< height
; row
++) {
3901 /* compute destination address in client memory */
3902 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
3903 width
, height
, format
, type
,
3907 if (format
== GL_COLOR_INDEX
) {
3908 GLuint indexRow
[MAX_WIDTH
];
3910 /* Can't use FetchTexel here because that returns RGBA */
3911 if (texImage
->TexFormat
->IndexBits
== 8) {
3912 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
3913 for (col
= 0; col
< width
; col
++) {
3914 indexRow
[col
] = src
[texImage
->Width
*
3915 (img
* texImage
->Height
+ row
) + col
];
3918 else if (texImage
->TexFormat
->IndexBits
== 16) {
3919 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
3920 for (col
= 0; col
< width
; col
++) {
3921 indexRow
[col
] = src
[texImage
->Width
*
3922 (img
* texImage
->Height
+ row
) + col
];
3927 "Color index problem in _mesa_GetTexImage");
3929 _mesa_pack_index_span(ctx
, width
, type
, dest
,
3930 indexRow
, &ctx
->Pack
,
3931 0 /* no image transfer */);
3933 else if (format
== GL_DEPTH_COMPONENT
) {
3934 GLfloat depthRow
[MAX_WIDTH
];
3936 for (col
= 0; col
< width
; col
++) {
3937 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
3940 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
3941 depthRow
, &ctx
->Pack
);
3943 else if (format
== GL_YCBCR_MESA
) {
3944 /* No pixel transfer */
3945 const GLint rowstride
= texImage
->RowStride
;
3947 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
3948 width
* sizeof(GLushort
));
3949 /* check for byte swapping */
3950 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
3951 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
3952 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
3953 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
3954 if (!ctx
->Pack
.SwapBytes
)
3955 _mesa_swap2((GLushort
*) dest
, width
);
3957 else if (ctx
->Pack
.SwapBytes
) {
3958 _mesa_swap2((GLushort
*) dest
, width
);
3962 /* general case: convert row to RGBA format */
3963 GLfloat rgba
[MAX_WIDTH
][4];
3965 for (col
= 0; col
< width
; col
++) {
3966 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
3968 _mesa_pack_rgba_span_float(ctx
, width
,
3969 (const GLfloat (*)[4]) rgba
,
3970 format
, type
, dest
, &ctx
->Pack
,
3971 0 /* no image transfer */);
3977 if (ctx
->Pack
.BufferObj
->Name
) {
3978 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
3979 ctx
->Pack
.BufferObj
);
3986 * This is the software fallback for Driver.GetCompressedTexImage().
3987 * All error checking will have been done before this routine is called.
3990 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
3992 const struct gl_texture_object
*texObj
,
3993 const struct gl_texture_image
*texImage
)
3995 if (ctx
->Pack
.BufferObj
->Name
) {
3996 /* pack texture image into a PBO */
3998 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
3999 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4000 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4001 "glGetCompressedTexImage(invalid PBO access)");
4004 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4006 ctx
->Pack
.BufferObj
);
4008 /* buffer is already mapped - that's an error */
4009 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4010 "glGetCompressedTexImage(PBO is mapped)");
4013 img
= ADD_POINTERS(buf
, img
);
4020 /* just memcpy, no pixelstore or pixel transfer */
4021 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);
4023 if (ctx
->Pack
.BufferObj
->Name
) {
4024 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4025 ctx
->Pack
.BufferObj
);