2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
62 #include "texcompress.h"
63 #include "texformat.h"
68 static const GLint ZERO
= 4, ONE
= 5;
70 static GLboolean
can_swizzle(GLenum logicalBaseFormat
)
72 switch (logicalBaseFormat
) {
75 case GL_LUMINANCE_ALPHA
:
87 * When promoting texture formats (see below) we need to compute the
88 * mapping of dest components back to source components.
89 * This function does that.
90 * \param logicalBaseFormat the logical format of the texture
91 * \param textureBaseFormat the final texture format
92 * \return map[4] the four mapping values
95 compute_component_mapping(GLenum logicalBaseFormat
, GLenum textureBaseFormat
,
101 /* compute mapping from dest components back to src components */
102 switch (textureBaseFormat
) {
105 switch (logicalBaseFormat
) {
107 map
[0] = map
[1] = map
[2] = 0;
108 if (textureBaseFormat
== GL_RGBA
)
112 ASSERT(textureBaseFormat
== GL_RGBA
);
113 map
[0] = map
[1] = map
[2] = ZERO
;
117 map
[0] = map
[1] = map
[2] = 0;
118 if (textureBaseFormat
== GL_RGBA
)
121 case GL_LUMINANCE_ALPHA
:
122 ASSERT(textureBaseFormat
== GL_RGBA
);
123 map
[0] = map
[1] = map
[2] = 0;
127 ASSERT(textureBaseFormat
== GL_RGBA
);
134 ASSERT(textureBaseFormat
== GL_RGBA
);
141 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
142 map
[0] = map
[1] = map
[2] = map
[3] = 0;
145 case GL_LUMINANCE_ALPHA
:
146 switch (logicalBaseFormat
) {
160 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
165 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
173 * Make a temporary (color) texture image with GLfloat components.
174 * Apply all needed pixel unpacking and pixel transfer operations.
175 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
176 * Suppose the user specifies GL_LUMINANCE as the internal texture format
177 * but the graphics hardware doesn't support luminance textures. So, might
178 * use an RGB hardware format instead.
179 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
181 * \param ctx the rendering context
182 * \param dims image dimensions: 1, 2 or 3
183 * \param logicalBaseFormat basic texture derived from the user's
184 * internal texture format value
185 * \param textureBaseFormat the actual basic format of the texture
186 * \param srcWidth source image width
187 * \param srcHeight source image height
188 * \param srcDepth source image depth
189 * \param srcFormat source image format
190 * \param srcType source image type
191 * \param srcAddr source image address
192 * \param srcPacking source image pixel packing
193 * \return resulting image with format = textureBaseFormat and type = GLfloat.
196 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
197 GLenum logicalBaseFormat
,
198 GLenum textureBaseFormat
,
199 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
200 GLenum srcFormat
, GLenum srcType
,
201 const GLvoid
*srcAddr
,
202 const struct gl_pixelstore_attrib
*srcPacking
)
204 GLuint transferOps
= ctx
->_ImageTransferState
;
207 ASSERT(dims
>= 1 && dims
<= 3);
209 ASSERT(logicalBaseFormat
== GL_RGBA
||
210 logicalBaseFormat
== GL_RGB
||
211 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
212 logicalBaseFormat
== GL_LUMINANCE
||
213 logicalBaseFormat
== GL_ALPHA
||
214 logicalBaseFormat
== GL_INTENSITY
||
215 logicalBaseFormat
== GL_COLOR_INDEX
||
216 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
218 ASSERT(textureBaseFormat
== GL_RGBA
||
219 textureBaseFormat
== GL_RGB
||
220 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
221 textureBaseFormat
== GL_LUMINANCE
||
222 textureBaseFormat
== GL_ALPHA
||
223 textureBaseFormat
== GL_INTENSITY
||
224 textureBaseFormat
== GL_COLOR_INDEX
||
225 textureBaseFormat
== GL_DEPTH_COMPONENT
);
227 /* conventional color image */
229 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
230 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
231 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
232 /* need image convolution */
233 const GLuint preConvTransferOps
234 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
235 const GLuint postConvTransferOps
236 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
238 GLint convWidth
, convHeight
;
241 /* pre-convolution image buffer (3D) */
242 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
243 * 4 * sizeof(GLfloat
));
247 /* post-convolution image buffer (2D) */
248 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
249 * 4 * sizeof(GLfloat
));
251 _mesa_free(tempImage
);
255 /* loop over 3D image slices */
256 for (img
= 0; img
< srcDepth
; img
++) {
257 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
259 /* unpack and do transfer ops up to convolution */
260 for (row
= 0; row
< srcHeight
; row
++) {
261 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
262 srcAddr
, srcWidth
, srcHeight
,
263 srcFormat
, srcType
, img
, row
, 0);
264 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
265 srcFormat
, srcType
, src
,
273 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
274 convWidth
= srcWidth
;
275 convHeight
= srcHeight
;
277 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
278 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
281 if (ctx
->Pixel
.Convolution2DEnabled
) {
282 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
286 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
287 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
293 /* do post-convolution transfer and pack into tempImage */
295 const GLint logComponents
296 = _mesa_components_in_format(logicalBaseFormat
);
297 const GLfloat
*src
= convImage
;
298 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
299 for (row
= 0; row
< convHeight
; row
++) {
300 _mesa_pack_rgba_span_float(ctx
, convWidth
,
301 (const GLfloat (*)[4]) src
,
302 logicalBaseFormat
, GL_FLOAT
,
303 dst
, &ctx
->DefaultPacking
,
304 postConvTransferOps
);
305 src
+= convWidth
* 4;
306 dst
+= convWidth
* logComponents
;
309 } /* loop over 3D image slices */
311 _mesa_free(convImage
);
313 /* might need these below */
314 srcWidth
= convWidth
;
315 srcHeight
= convHeight
;
319 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
320 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
321 srcWidth
, srcFormat
, srcType
);
325 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
326 * components
* sizeof(GLfloat
));
331 for (img
= 0; img
< srcDepth
; img
++) {
333 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
337 for (row
= 0; row
< srcHeight
; row
++) {
338 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
339 dst
, srcFormat
, srcType
, src
,
340 srcPacking
, transferOps
);
341 dst
+= srcWidth
* components
;
347 if (logicalBaseFormat
!= textureBaseFormat
) {
349 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
350 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
355 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
356 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
357 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
359 /* The actual texture format should have at least as many components
360 * as the logical texture format.
362 ASSERT(texComponents
>= logComponents
);
364 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
365 * texComponents
* sizeof(GLfloat
));
367 _mesa_free(tempImage
);
371 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
373 n
= srcWidth
* srcHeight
* srcDepth
;
374 for (i
= 0; i
< n
; i
++) {
376 for (k
= 0; k
< texComponents
; k
++) {
379 newImage
[i
* texComponents
+ k
] = 0.0F
;
381 newImage
[i
* texComponents
+ k
] = 1.0F
;
383 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
387 _mesa_free(tempImage
);
388 tempImage
= newImage
;
396 * Make a temporary (color) texture image with GLchan components.
397 * Apply all needed pixel unpacking and pixel transfer operations.
398 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
399 * Suppose the user specifies GL_LUMINANCE as the internal texture format
400 * but the graphics hardware doesn't support luminance textures. So, might
401 * use an RGB hardware format instead.
402 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
404 * \param ctx the rendering context
405 * \param dims image dimensions: 1, 2 or 3
406 * \param logicalBaseFormat basic texture derived from the user's
407 * internal texture format value
408 * \param textureBaseFormat the actual basic format of the texture
409 * \param srcWidth source image width
410 * \param srcHeight source image height
411 * \param srcDepth source image depth
412 * \param srcFormat source image format
413 * \param srcType source image type
414 * \param srcAddr source image address
415 * \param srcPacking source image pixel packing
416 * \return resulting image with format = textureBaseFormat and type = GLchan.
419 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
420 GLenum logicalBaseFormat
,
421 GLenum textureBaseFormat
,
422 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
423 GLenum srcFormat
, GLenum srcType
,
424 const GLvoid
*srcAddr
,
425 const struct gl_pixelstore_attrib
*srcPacking
)
427 GLuint transferOps
= ctx
->_ImageTransferState
;
428 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
429 GLboolean freeSrcImage
= GL_FALSE
;
431 GLchan
*tempImage
, *dst
;
433 ASSERT(dims
>= 1 && dims
<= 3);
435 ASSERT(logicalBaseFormat
== GL_RGBA
||
436 logicalBaseFormat
== GL_RGB
||
437 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
438 logicalBaseFormat
== GL_LUMINANCE
||
439 logicalBaseFormat
== GL_ALPHA
||
440 logicalBaseFormat
== GL_INTENSITY
);
442 ASSERT(textureBaseFormat
== GL_RGBA
||
443 textureBaseFormat
== GL_RGB
||
444 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
445 textureBaseFormat
== GL_LUMINANCE
||
446 textureBaseFormat
== GL_ALPHA
||
447 textureBaseFormat
== GL_INTENSITY
);
449 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
450 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
451 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
452 /* get convolved image */
453 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
456 srcWidth
, srcHeight
, srcDepth
,
458 srcAddr
, srcPacking
);
461 /* the convolved image is our new source image */
463 srcFormat
= logicalBaseFormat
;
465 srcPacking
= &ctx
->DefaultPacking
;
466 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
468 freeSrcImage
= GL_TRUE
;
471 /* unpack and transfer the source image */
472 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
473 * components
* sizeof(GLchan
));
478 for (img
= 0; img
< srcDepth
; img
++) {
479 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
483 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
487 for (row
= 0; row
< srcHeight
; row
++) {
488 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
489 srcFormat
, srcType
, src
, srcPacking
,
491 dst
+= srcWidth
* components
;
496 /* If we made a temporary image for convolution, free it here */
498 _mesa_free((void *) srcAddr
);
501 if (logicalBaseFormat
!= textureBaseFormat
) {
502 /* one more conversion step */
503 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
504 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
509 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
510 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
511 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
513 /* The actual texture format should have at least as many components
514 * as the logical texture format.
516 ASSERT(texComponents
>= logComponents
);
518 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
519 * texComponents
* sizeof(GLchan
));
521 _mesa_free(tempImage
);
525 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
527 n
= srcWidth
* srcHeight
* srcDepth
;
528 for (i
= 0; i
< n
; i
++) {
530 for (k
= 0; k
< texComponents
; k
++) {
533 newImage
[i
* texComponents
+ k
] = 0;
535 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
537 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
541 _mesa_free(tempImage
);
542 tempImage
= newImage
;
550 * Copy GLubyte pixels from <src> to <dst> with swizzling.
551 * \param dst destination pixels
552 * \param dstComponents number of color components in destination pixels
553 * \param src source pixels
554 * \param srcComponents number of color components in source pixels
555 * \param map the swizzle mapping
556 * \param count number of pixels to copy/swizzle.
559 swizzle_copy(GLubyte
*dst
, GLuint dstComponents
, const GLubyte
*src
,
560 GLuint srcComponents
, const GLubyte
*map
, GLuint count
)
568 switch (dstComponents
) {
570 for (i
= 0; i
< count
; i
++) {
572 src
+= srcComponents
;
573 dst
[0] = tmp
[map
[0]];
574 dst
[1] = tmp
[map
[1]];
575 dst
[2] = tmp
[map
[2]];
576 dst
[3] = tmp
[map
[3]];
581 for (i
= 0; i
< count
; i
++) {
583 src
+= srcComponents
;
584 dst
[0] = tmp
[map
[0]];
585 dst
[1] = tmp
[map
[1]];
586 dst
[2] = tmp
[map
[2]];
591 for (i
= 0; i
< count
; i
++) {
593 src
+= srcComponents
;
594 dst
[0] = tmp
[map
[0]];
595 dst
[1] = tmp
[map
[1]];
604 * Transfer a GLubyte texture image with component swizzling.
607 _mesa_swizzle_ubyte_image(GLcontext
*ctx
,
610 const GLubyte
*dstmap
, GLint dstComponents
,
613 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
615 const GLuint
*dstImageOffsets
,
617 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
618 const GLvoid
*srcAddr
,
619 const struct gl_pixelstore_attrib
*srcPacking
)
621 GLint srcComponents
= _mesa_components_in_format(srcFormat
);
622 GLubyte srcmap
[6], map
[4];
625 const GLint srcRowStride
=
626 _mesa_image_row_stride(srcPacking
, srcWidth
,
627 srcFormat
, GL_UNSIGNED_BYTE
);
628 const GLint srcImageStride
629 = _mesa_image_image_stride(srcPacking
, srcWidth
, srcHeight
, srcFormat
,
631 const GLubyte
*srcImage
632 = (const GLubyte
*) _mesa_image_address(dimensions
, srcPacking
, srcAddr
,
633 srcWidth
, srcHeight
, srcFormat
,
634 GL_UNSIGNED_BYTE
, 0, 0, 0);
638 compute_component_mapping(srcFormat
, GL_RGBA
, srcmap
);
640 for (i
= 0; i
< 4; i
++)
641 map
[i
] = srcmap
[dstmap
[i
]];
643 if (srcRowStride
== srcWidth
* srcComponents
&&
645 /* 1 and 2D images only */
646 GLubyte
*dstImage
= (GLubyte
*) dstAddr
647 + dstYoffset
* dstRowStride
648 + dstXoffset
* dstComponents
;
649 swizzle_copy(dstImage
, dstComponents
, srcImage
, srcComponents
, map
,
650 srcWidth
* srcHeight
);
654 for (img
= 0; img
< srcDepth
; img
++) {
655 const GLubyte
*srcRow
= srcImage
;
656 GLubyte
*dstRow
= (GLubyte
*) dstAddr
657 + dstImageOffsets
[dstZoffset
+ img
] * dstComponents
658 + dstYoffset
* dstRowStride
659 + dstXoffset
* dstComponents
;
660 for (row
= 0; row
< srcHeight
; row
++) {
661 swizzle_copy(dstRow
, dstComponents
, srcRow
, srcComponents
, map
, srcWidth
);
662 dstRow
+= dstRowStride
;
663 srcRow
+= srcRowStride
;
665 srcImage
+= srcImageStride
;
672 * Teximage storage routine for when a simple memcpy will do.
673 * No pixel transfer operations or special texel encodings allowed.
674 * 1D, 2D and 3D images supported.
677 memcpy_texture(GLcontext
*ctx
,
679 const struct gl_texture_format
*dstFormat
,
681 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
683 const GLuint
*dstImageOffsets
,
684 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
685 GLenum srcFormat
, GLenum srcType
,
686 const GLvoid
*srcAddr
,
687 const struct gl_pixelstore_attrib
*srcPacking
)
689 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
691 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
692 srcWidth
, srcHeight
, srcFormat
, srcType
);
693 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
694 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
695 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
698 /* XXX update/re-enable for dstImageOffsets array */
699 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
700 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
701 GLubyte
*dstImage
= (GLubyte
*) dstAddr
702 + dstZoffset
* dstImageStride
703 + dstYoffset
* dstRowStride
704 + dstXoffset
* dstFormat
->TexelBytes
;
706 if (dstRowStride
== srcRowStride
&&
707 dstRowStride
== bytesPerRow
&&
708 ((dstImageStride
== srcImageStride
&&
709 dstImageStride
== bytesPerImage
) ||
712 ctx
->Driver
.TextureMemCpy(dstImage
, srcImage
, bytesPerTexture
);
717 for (img
= 0; img
< srcDepth
; img
++) {
718 const GLubyte
*srcRow
= srcImage
;
719 GLubyte
*dstRow
= dstImage
;
720 for (row
= 0; row
< srcHeight
; row
++) {
721 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
722 dstRow
+= dstRowStride
;
723 srcRow
+= srcRowStride
;
725 srcImage
+= srcImageStride
;
726 dstImage
+= dstImageStride
;
732 for (img
= 0; img
< srcDepth
; img
++) {
733 const GLubyte
*srcRow
= srcImage
;
734 GLubyte
*dstRow
= (GLubyte
*) dstAddr
735 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
736 + dstYoffset
* dstRowStride
737 + dstXoffset
* dstFormat
->TexelBytes
;
738 for (row
= 0; row
< srcHeight
; row
++) {
739 ctx
->Driver
.TextureMemCpy(dstRow
, srcRow
, bytesPerRow
);
740 dstRow
+= dstRowStride
;
741 srcRow
+= srcRowStride
;
743 srcImage
+= srcImageStride
;
750 * Store an image in any of the formats:
751 * _mesa_texformat_rgba
752 * _mesa_texformat_rgb
753 * _mesa_texformat_alpha
754 * _mesa_texformat_luminance
755 * _mesa_texformat_luminance_alpha
756 * _mesa_texformat_intensity
760 _mesa_texstore_rgba(TEXSTORE_PARAMS
)
762 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
764 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
765 dstFormat
== &_mesa_texformat_rgb
||
766 dstFormat
== &_mesa_texformat_alpha
||
767 dstFormat
== &_mesa_texformat_luminance
||
768 dstFormat
== &_mesa_texformat_luminance_alpha
||
769 dstFormat
== &_mesa_texformat_intensity
);
770 ASSERT(baseInternalFormat
== GL_RGBA
||
771 baseInternalFormat
== GL_RGB
||
772 baseInternalFormat
== GL_ALPHA
||
773 baseInternalFormat
== GL_LUMINANCE
||
774 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
775 baseInternalFormat
== GL_INTENSITY
);
776 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
778 if (!ctx
->_ImageTransferState
&&
779 !srcPacking
->SwapBytes
&&
780 baseInternalFormat
== srcFormat
&&
781 srcType
== CHAN_TYPE
) {
782 /* simple memcpy path */
783 memcpy_texture(ctx
, dims
,
784 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
787 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
788 srcAddr
, srcPacking
);
790 else if (!ctx
->_ImageTransferState
&&
791 !srcPacking
->SwapBytes
&&
792 dstFormat
== &_mesa_texformat_rgb
&&
793 srcFormat
== GL_RGBA
&&
794 srcType
== CHAN_TYPE
) {
795 /* extract RGB from RGBA */
797 for (img
= 0; img
< srcDepth
; img
++) {
798 GLchan
*dstImage
= (GLchan
*)
800 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
801 + dstYoffset
* dstRowStride
802 + dstXoffset
* dstFormat
->TexelBytes
);
804 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
805 srcWidth
, srcFormat
, srcType
);
806 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(dims
, srcPacking
,
807 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
808 GLchan
*dstRow
= dstImage
;
809 for (row
= 0; row
< srcHeight
; row
++) {
810 for (col
= 0; col
< srcWidth
; col
++) {
811 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
812 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
813 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
815 dstRow
+= dstRowStride
/ sizeof(GLchan
);
816 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
822 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
824 dstFormat
->BaseFormat
,
825 srcWidth
, srcHeight
, srcDepth
,
826 srcFormat
, srcType
, srcAddr
,
828 const GLchan
*src
= tempImage
;
833 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
834 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
835 for (img
= 0; img
< srcDepth
; img
++) {
836 GLubyte
*dstRow
= (GLubyte
*) dstAddr
837 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
838 + dstYoffset
* dstRowStride
839 + dstXoffset
* dstFormat
->TexelBytes
;
840 for (row
= 0; row
< srcHeight
; row
++) {
841 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
842 dstRow
+= dstRowStride
;
843 src
+= srcWidth
* components
;
847 _mesa_free((void *) tempImage
);
854 * Store a 32-bit integer depth component texture image.
857 _mesa_texstore_z32(TEXSTORE_PARAMS
)
859 const GLfloat depthScale
= (GLfloat
) 0xffffffff;
861 ASSERT(dstFormat
== &_mesa_texformat_z32
);
862 ASSERT(dstFormat
->TexelBytes
== sizeof(GLuint
));
864 if (!ctx
->_ImageTransferState
&&
865 !srcPacking
->SwapBytes
&&
866 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
867 srcFormat
== GL_DEPTH_COMPONENT
&&
868 srcType
== GL_UNSIGNED_INT
) {
869 /* simple memcpy path */
870 memcpy_texture(ctx
, dims
,
871 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
874 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
875 srcAddr
, srcPacking
);
880 for (img
= 0; img
< srcDepth
; img
++) {
881 GLubyte
*dstRow
= (GLubyte
*) dstAddr
882 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
883 + dstYoffset
* dstRowStride
884 + dstXoffset
* dstFormat
->TexelBytes
;
885 for (row
= 0; row
< srcHeight
; row
++) {
886 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
887 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
888 _mesa_unpack_depth_span(ctx
, srcWidth
,
889 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
890 depthScale
, srcType
, src
, srcPacking
);
891 dstRow
+= dstRowStride
;
901 * Store a 16-bit integer depth component texture image.
904 _mesa_texstore_z16(TEXSTORE_PARAMS
)
906 const GLfloat depthScale
= 65535.0f
;
908 ASSERT(dstFormat
== &_mesa_texformat_z16
);
909 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
911 if (!ctx
->_ImageTransferState
&&
912 !srcPacking
->SwapBytes
&&
913 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
914 srcFormat
== GL_DEPTH_COMPONENT
&&
915 srcType
== GL_UNSIGNED_SHORT
) {
916 /* simple memcpy path */
917 memcpy_texture(ctx
, dims
,
918 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
921 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
922 srcAddr
, srcPacking
);
927 for (img
= 0; img
< srcDepth
; img
++) {
928 GLubyte
*dstRow
= (GLubyte
*) dstAddr
929 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
930 + dstYoffset
* dstRowStride
931 + dstXoffset
* dstFormat
->TexelBytes
;
932 for (row
= 0; row
< srcHeight
; row
++) {
933 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
934 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
935 GLushort
*dst16
= (GLushort
*) dstRow
;
936 _mesa_unpack_depth_span(ctx
, srcWidth
,
937 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
938 srcType
, src
, srcPacking
);
939 dstRow
+= dstRowStride
;
948 * Store an rgb565 or rgb565_rev texture image.
951 _mesa_texstore_rgb565(TEXSTORE_PARAMS
)
953 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
954 dstFormat
== &_mesa_texformat_rgb565_rev
);
955 ASSERT(dstFormat
->TexelBytes
== 2);
957 if (!ctx
->_ImageTransferState
&&
958 !srcPacking
->SwapBytes
&&
959 dstFormat
== &_mesa_texformat_rgb565
&&
960 baseInternalFormat
== GL_RGB
&&
961 srcFormat
== GL_RGB
&&
962 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
963 /* simple memcpy path */
964 memcpy_texture(ctx
, dims
,
965 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
968 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
969 srcAddr
, srcPacking
);
971 else if (!ctx
->_ImageTransferState
&&
972 !srcPacking
->SwapBytes
&&
973 baseInternalFormat
== GL_RGB
&&
974 srcFormat
== GL_RGB
&&
975 srcType
== GL_UNSIGNED_BYTE
&&
977 /* do optimized tex store */
978 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
980 const GLubyte
*src
= (const GLubyte
*)
981 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
982 srcFormat
, srcType
, 0, 0, 0);
983 GLubyte
*dst
= (GLubyte
*) dstAddr
984 + dstYoffset
* dstRowStride
985 + dstXoffset
* dstFormat
->TexelBytes
;
987 for (row
= 0; row
< srcHeight
; row
++) {
988 const GLubyte
*srcUB
= (const GLubyte
*) src
;
989 GLushort
*dstUS
= (GLushort
*) dst
;
990 /* check for byteswapped format */
991 if (dstFormat
== &_mesa_texformat_rgb565
) {
992 for (col
= 0; col
< srcWidth
; col
++) {
993 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
998 for (col
= 0; col
< srcWidth
; col
++) {
999 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
1003 dst
+= dstRowStride
;
1004 src
+= srcRowStride
;
1009 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1011 dstFormat
->BaseFormat
,
1012 srcWidth
, srcHeight
, srcDepth
,
1013 srcFormat
, srcType
, srcAddr
,
1015 const GLchan
*src
= tempImage
;
1016 GLint img
, row
, col
;
1019 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1020 for (img
= 0; img
< srcDepth
; img
++) {
1021 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1022 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1023 + dstYoffset
* dstRowStride
1024 + dstXoffset
* dstFormat
->TexelBytes
;
1025 for (row
= 0; row
< srcHeight
; row
++) {
1026 GLushort
*dstUS
= (GLushort
*) dstRow
;
1027 /* check for byteswapped format */
1028 if (dstFormat
== &_mesa_texformat_rgb565
) {
1029 for (col
= 0; col
< srcWidth
; col
++) {
1030 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
1031 CHAN_TO_UBYTE(src
[GCOMP
]),
1032 CHAN_TO_UBYTE(src
[BCOMP
]) );
1037 for (col
= 0; col
< srcWidth
; col
++) {
1038 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1039 CHAN_TO_UBYTE(src
[GCOMP
]),
1040 CHAN_TO_UBYTE(src
[BCOMP
]) );
1044 dstRow
+= dstRowStride
;
1047 _mesa_free((void *) tempImage
);
1054 _mesa_texstore_rgba8888(TEXSTORE_PARAMS
)
1056 const GLuint ui
= 1;
1057 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1060 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
1061 dstFormat
== &_mesa_texformat_rgba8888_rev
);
1062 ASSERT(dstFormat
->TexelBytes
== 4);
1064 if (!ctx
->_ImageTransferState
&&
1065 !srcPacking
->SwapBytes
&&
1066 dstFormat
== &_mesa_texformat_rgba8888
&&
1067 baseInternalFormat
== GL_RGBA
&&
1068 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
1069 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
1070 /* simple memcpy path */
1071 memcpy_texture(ctx
, dims
,
1072 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1075 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1076 srcAddr
, srcPacking
);
1080 else if (!ctx
->_ImageTransferState
&&
1081 !srcPacking
->SwapBytes
&&
1082 srcType
== GL_UNSIGNED_BYTE
&&
1083 dstFormat
== &_mesa_texformat_rgba8888
&&
1085 /* Three texture formats involved: srcFormat,
1086 * baseInternalFormat and destFormat (GL_RGBA). Only two
1087 * may differ. _mesa_swizzle_ubyte_image can't handle two
1088 * propagations at once correctly. */
1089 (srcFormat
== baseInternalFormat
||
1090 baseInternalFormat
== GL_RGBA
) &&
1091 can_swizzle(srcFormat
)) {
1094 /* dstmap - how to swizzle from GL_RGBA to dst format:
1096 * FIXME - add !litteEndian and _rev varients:
1103 _mesa_swizzle_ubyte_image(ctx
, dims
,
1106 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1107 dstRowStride
, dstImageStride
,
1108 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1114 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1116 dstFormat
->BaseFormat
,
1117 srcWidth
, srcHeight
, srcDepth
,
1118 srcFormat
, srcType
, srcAddr
,
1120 const GLchan
*src
= tempImage
;
1121 GLint img
, row
, col
;
1124 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1125 for (img
= 0; img
< srcDepth
; img
++) {
1126 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1127 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1128 + dstYoffset
* dstRowStride
1129 + dstXoffset
* dstFormat
->TexelBytes
;
1130 for (row
= 0; row
< srcHeight
; row
++) {
1131 GLuint
*dstUI
= (GLuint
*) dstRow
;
1132 if (dstFormat
== &_mesa_texformat_rgba8888
) {
1133 for (col
= 0; col
< srcWidth
; col
++) {
1134 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
1135 CHAN_TO_UBYTE(src
[GCOMP
]),
1136 CHAN_TO_UBYTE(src
[BCOMP
]),
1137 CHAN_TO_UBYTE(src
[ACOMP
]) );
1142 for (col
= 0; col
< srcWidth
; col
++) {
1143 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
1144 CHAN_TO_UBYTE(src
[GCOMP
]),
1145 CHAN_TO_UBYTE(src
[BCOMP
]),
1146 CHAN_TO_UBYTE(src
[ACOMP
]) );
1150 dstRow
+= dstRowStride
;
1153 _mesa_free((void *) tempImage
);
1160 _mesa_texstore_argb8888(TEXSTORE_PARAMS
)
1162 const GLuint ui
= 1;
1163 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1165 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
1166 dstFormat
== &_mesa_texformat_argb8888_rev
);
1167 ASSERT(dstFormat
->TexelBytes
== 4);
1169 if (!ctx
->_ImageTransferState
&&
1170 !srcPacking
->SwapBytes
&&
1171 dstFormat
== &_mesa_texformat_argb8888
&&
1172 baseInternalFormat
== GL_RGBA
&&
1173 srcFormat
== GL_BGRA
&&
1174 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1175 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
1176 /* simple memcpy path (little endian) */
1177 memcpy_texture(ctx
, dims
,
1178 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1181 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1182 srcAddr
, srcPacking
);
1184 else if (!ctx
->_ImageTransferState
&&
1185 !srcPacking
->SwapBytes
&&
1186 dstFormat
== &_mesa_texformat_argb8888_rev
&&
1187 baseInternalFormat
== GL_RGBA
&&
1188 srcFormat
== GL_BGRA
&&
1189 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1190 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
1191 /* simple memcpy path (big endian) */
1192 memcpy_texture(ctx
, dims
,
1193 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1196 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1197 srcAddr
, srcPacking
);
1199 else if (!ctx
->_ImageTransferState
&&
1200 !srcPacking
->SwapBytes
&&
1201 dstFormat
== &_mesa_texformat_argb8888
&&
1202 srcFormat
== GL_RGB
&&
1203 srcType
== GL_UNSIGNED_BYTE
) {
1206 for (img
= 0; img
< srcDepth
; img
++) {
1207 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1208 srcWidth
, srcFormat
, srcType
);
1209 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1210 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1211 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1212 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1213 + dstYoffset
* dstRowStride
1214 + dstXoffset
* dstFormat
->TexelBytes
;
1215 for (row
= 0; row
< srcHeight
; row
++) {
1216 for (col
= 0; col
< srcWidth
; col
++) {
1217 dstRow
[col
* 4 + 0] = srcRow
[col
* 3 + BCOMP
];
1218 dstRow
[col
* 4 + 1] = srcRow
[col
* 3 + GCOMP
];
1219 dstRow
[col
* 4 + 2] = srcRow
[col
* 3 + RCOMP
];
1220 dstRow
[col
* 4 + 3] = 0xff;
1222 dstRow
+= dstRowStride
;
1223 srcRow
+= srcRowStride
;
1227 else if (!ctx
->_ImageTransferState
&&
1228 !srcPacking
->SwapBytes
&&
1229 dstFormat
== &_mesa_texformat_argb8888
&&
1230 srcFormat
== GL_RGBA
&&
1231 (srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
1232 GLint img
, row
, col
;
1233 /* For some reason, streaming copies to write-combined regions
1234 * are extremely sensitive to the characteristics of how the
1235 * source data is retrieved. By reordering the source reads to
1236 * be in-order, the speed of this operation increases by half.
1237 * Strangely the same isn't required for the RGB path, above.
1239 for (img
= 0; img
< srcDepth
; img
++) {
1240 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1241 srcWidth
, srcFormat
, srcType
);
1242 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1243 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1244 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1245 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1246 + dstYoffset
* dstRowStride
1247 + dstXoffset
* dstFormat
->TexelBytes
;
1249 for (row
= 0; row
< srcHeight
; row
++) {
1250 for (col
= 0; col
< srcWidth
; col
++) {
1251 *(GLuint
*)(dstRow
+ col
* 4) = (srcRow
[col
* 4 + RCOMP
] << 16 |
1252 srcRow
[col
* 4 + GCOMP
] << 8 |
1253 srcRow
[col
* 4 + BCOMP
] << 0 |
1254 srcRow
[col
* 4 + ACOMP
] << 24);
1256 dstRow
+= dstRowStride
;
1257 srcRow
+= srcRowStride
;
1261 else if (!ctx
->_ImageTransferState
&&
1262 !srcPacking
->SwapBytes
&&
1263 dstFormat
== &_mesa_texformat_argb8888
&&
1264 srcFormat
== GL_RGBA
&&
1265 srcType
== GL_UNSIGNED_BYTE
) {
1267 GLint img
, row
, col
;
1268 for (img
= 0; img
< srcDepth
; img
++) {
1269 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1270 srcWidth
, srcFormat
, srcType
);
1271 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1272 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1273 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1274 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1275 + dstYoffset
* dstRowStride
1276 + dstXoffset
* dstFormat
->TexelBytes
;
1277 for (row
= 0; row
< srcHeight
; row
++) {
1278 for (col
= 0; col
< srcWidth
; col
++) {
1279 dstRow
[col
* 4 + 0] = srcRow
[col
* 4 + BCOMP
];
1280 dstRow
[col
* 4 + 1] = srcRow
[col
* 4 + GCOMP
];
1281 dstRow
[col
* 4 + 2] = srcRow
[col
* 4 + RCOMP
];
1282 dstRow
[col
* 4 + 3] = srcRow
[col
* 4 + ACOMP
];
1284 dstRow
+= dstRowStride
;
1285 srcRow
+= srcRowStride
;
1289 else if (!ctx
->_ImageTransferState
&&
1290 !srcPacking
->SwapBytes
&&
1291 dstFormat
== &_mesa_texformat_argb8888
&&
1292 srcType
== GL_UNSIGNED_BYTE
&&
1294 /* Three texture formats involved: srcFormat,
1295 * baseInternalFormat and destFormat (GL_RGBA). Only two
1296 * may differ. _mesa_swizzle_ubyte_image can't handle two
1297 * propagations at once correctly. */
1298 (srcFormat
== baseInternalFormat
||
1299 baseInternalFormat
== GL_RGBA
) &&
1300 can_swizzle(srcFormat
)) {
1304 /* dstmap - how to swizzle from GL_RGBA to dst format:
1306 dstmap
[3] = 3; /* alpha */
1307 dstmap
[2] = 0; /* red */
1308 dstmap
[1] = 1; /* green */
1309 dstmap
[0] = 2; /* blue */
1311 _mesa_swizzle_ubyte_image(ctx
, dims
,
1314 dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1317 srcWidth
, srcHeight
, srcDepth
, srcAddr
,
1322 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1324 dstFormat
->BaseFormat
,
1325 srcWidth
, srcHeight
, srcDepth
,
1326 srcFormat
, srcType
, srcAddr
,
1328 const GLchan
*src
= tempImage
;
1329 GLint img
, row
, col
;
1332 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1333 for (img
= 0; img
< srcDepth
; img
++) {
1334 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1335 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1336 + dstYoffset
* dstRowStride
1337 + dstXoffset
* dstFormat
->TexelBytes
;
1338 for (row
= 0; row
< srcHeight
; row
++) {
1339 GLuint
*dstUI
= (GLuint
*) dstRow
;
1340 if (dstFormat
== &_mesa_texformat_argb8888
) {
1341 for (col
= 0; col
< srcWidth
; col
++) {
1342 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1343 CHAN_TO_UBYTE(src
[RCOMP
]),
1344 CHAN_TO_UBYTE(src
[GCOMP
]),
1345 CHAN_TO_UBYTE(src
[BCOMP
]) );
1350 for (col
= 0; col
< srcWidth
; col
++) {
1351 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1352 CHAN_TO_UBYTE(src
[RCOMP
]),
1353 CHAN_TO_UBYTE(src
[GCOMP
]),
1354 CHAN_TO_UBYTE(src
[BCOMP
]) );
1358 dstRow
+= dstRowStride
;
1361 _mesa_free((void *) tempImage
);
1368 _mesa_texstore_rgb888(TEXSTORE_PARAMS
)
1370 const GLuint ui
= 1;
1371 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1373 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1374 ASSERT(dstFormat
->TexelBytes
== 3);
1376 if (!ctx
->_ImageTransferState
&&
1377 !srcPacking
->SwapBytes
&&
1378 baseInternalFormat
== GL_RGB
&&
1379 srcFormat
== GL_BGR
&&
1380 srcType
== GL_UNSIGNED_BYTE
&&
1382 /* simple memcpy path */
1383 memcpy_texture(ctx
, dims
,
1384 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1387 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1388 srcAddr
, srcPacking
);
1390 else if (!ctx
->_ImageTransferState
&&
1391 !srcPacking
->SwapBytes
&&
1392 srcFormat
== GL_RGBA
&&
1393 srcType
== GL_UNSIGNED_BYTE
) {
1394 /* extract RGB from RGBA */
1395 GLint img
, row
, col
;
1396 for (img
= 0; img
< srcDepth
; img
++) {
1397 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1398 srcWidth
, srcFormat
, srcType
);
1399 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1400 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1401 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1402 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1403 + dstYoffset
* dstRowStride
1404 + dstXoffset
* dstFormat
->TexelBytes
;
1405 for (row
= 0; row
< srcHeight
; row
++) {
1406 for (col
= 0; col
< srcWidth
; col
++) {
1407 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1408 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1409 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1411 dstRow
+= dstRowStride
;
1412 srcRow
+= srcRowStride
;
1418 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1420 dstFormat
->BaseFormat
,
1421 srcWidth
, srcHeight
, srcDepth
,
1422 srcFormat
, srcType
, srcAddr
,
1424 const GLchan
*src
= (const GLchan
*) tempImage
;
1425 GLint img
, row
, col
;
1428 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1429 for (img
= 0; img
< srcDepth
; img
++) {
1430 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1431 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1432 + dstYoffset
* dstRowStride
1433 + dstXoffset
* dstFormat
->TexelBytes
;
1434 for (row
= 0; row
< srcHeight
; row
++) {
1437 for (col
= 0; col
< srcWidth
; col
++) {
1438 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1439 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1440 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1445 for (col
= 0; col
< srcWidth
; col
++) {
1446 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1447 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1448 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1453 for (col
= 0; col
< srcWidth
; col
++) {
1454 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1455 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1456 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1460 dstRow
+= dstRowStride
;
1463 _mesa_free((void *) tempImage
);
1470 _mesa_texstore_bgr888(TEXSTORE_PARAMS
)
1472 const GLuint ui
= 1;
1473 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1475 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1476 ASSERT(dstFormat
->TexelBytes
== 3);
1478 if (!ctx
->_ImageTransferState
&&
1479 !srcPacking
->SwapBytes
&&
1480 baseInternalFormat
== GL_RGB
&&
1481 srcFormat
== GL_RGB
&&
1482 srcType
== GL_UNSIGNED_BYTE
&&
1484 /* simple memcpy path */
1485 memcpy_texture(ctx
, dims
,
1486 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1489 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1490 srcAddr
, srcPacking
);
1492 else if (!ctx
->_ImageTransferState
&&
1493 !srcPacking
->SwapBytes
&&
1494 srcFormat
== GL_RGBA
&&
1495 srcType
== GL_UNSIGNED_BYTE
) {
1496 /* extract BGR from RGBA */
1498 for (img
= 0; img
< srcDepth
; img
++) {
1499 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1500 srcWidth
, srcFormat
, srcType
);
1501 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(dims
, srcPacking
,
1502 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1503 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1504 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1505 + dstYoffset
* dstRowStride
1506 + dstXoffset
* dstFormat
->TexelBytes
;
1507 for (row
= 0; row
< srcHeight
; row
++) {
1508 for (col
= 0; col
< srcWidth
; col
++) {
1509 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1510 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1511 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1513 dstRow
+= dstRowStride
;
1514 srcRow
+= srcRowStride
;
1520 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1522 dstFormat
->BaseFormat
,
1523 srcWidth
, srcHeight
, srcDepth
,
1524 srcFormat
, srcType
, srcAddr
,
1526 const GLchan
*src
= (const GLchan
*) tempImage
;
1527 GLint img
, row
, col
;
1530 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1531 for (img
= 0; img
< srcDepth
; img
++) {
1532 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1533 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1534 + dstYoffset
* dstRowStride
1535 + dstXoffset
* dstFormat
->TexelBytes
;
1536 for (row
= 0; row
< srcHeight
; row
++) {
1537 for (col
= 0; col
< srcWidth
; col
++) {
1538 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1539 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1540 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1543 dstRow
+= dstRowStride
;
1546 _mesa_free((void *) tempImage
);
1553 _mesa_texstore_argb4444(TEXSTORE_PARAMS
)
1555 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1556 dstFormat
== &_mesa_texformat_argb4444_rev
);
1557 ASSERT(dstFormat
->TexelBytes
== 2);
1559 if (!ctx
->_ImageTransferState
&&
1560 !srcPacking
->SwapBytes
&&
1561 dstFormat
== &_mesa_texformat_argb4444
&&
1562 baseInternalFormat
== GL_RGBA
&&
1563 srcFormat
== GL_BGRA
&&
1564 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1565 /* simple memcpy path */
1566 memcpy_texture(ctx
, dims
,
1567 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1570 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1571 srcAddr
, srcPacking
);
1575 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1577 dstFormat
->BaseFormat
,
1578 srcWidth
, srcHeight
, srcDepth
,
1579 srcFormat
, srcType
, srcAddr
,
1581 const GLchan
*src
= tempImage
;
1582 GLint img
, row
, col
;
1585 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1586 for (img
= 0; img
< srcDepth
; img
++) {
1587 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1588 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1589 + dstYoffset
* dstRowStride
1590 + dstXoffset
* dstFormat
->TexelBytes
;
1591 for (row
= 0; row
< srcHeight
; row
++) {
1592 GLushort
*dstUS
= (GLushort
*) dstRow
;
1593 if (dstFormat
== &_mesa_texformat_argb4444
) {
1594 for (col
= 0; col
< srcWidth
; col
++) {
1595 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1596 CHAN_TO_UBYTE(src
[RCOMP
]),
1597 CHAN_TO_UBYTE(src
[GCOMP
]),
1598 CHAN_TO_UBYTE(src
[BCOMP
]) );
1603 for (col
= 0; col
< srcWidth
; col
++) {
1604 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1605 CHAN_TO_UBYTE(src
[RCOMP
]),
1606 CHAN_TO_UBYTE(src
[GCOMP
]),
1607 CHAN_TO_UBYTE(src
[BCOMP
]) );
1611 dstRow
+= dstRowStride
;
1614 _mesa_free((void *) tempImage
);
1622 _mesa_texstore_argb1555(TEXSTORE_PARAMS
)
1624 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1625 dstFormat
== &_mesa_texformat_argb1555_rev
);
1626 ASSERT(dstFormat
->TexelBytes
== 2);
1628 if (!ctx
->_ImageTransferState
&&
1629 !srcPacking
->SwapBytes
&&
1630 dstFormat
== &_mesa_texformat_argb1555
&&
1631 baseInternalFormat
== GL_RGBA
&&
1632 srcFormat
== GL_BGRA
&&
1633 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1634 /* simple memcpy path */
1635 memcpy_texture(ctx
, dims
,
1636 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1639 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1640 srcAddr
, srcPacking
);
1644 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1646 dstFormat
->BaseFormat
,
1647 srcWidth
, srcHeight
, srcDepth
,
1648 srcFormat
, srcType
, srcAddr
,
1650 const GLchan
*src
=tempImage
;
1651 GLint img
, row
, col
;
1654 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1655 for (img
= 0; img
< srcDepth
; img
++) {
1656 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1657 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1658 + dstYoffset
* dstRowStride
1659 + dstXoffset
* dstFormat
->TexelBytes
;
1660 for (row
= 0; row
< srcHeight
; row
++) {
1661 GLushort
*dstUS
= (GLushort
*) dstRow
;
1662 if (dstFormat
== &_mesa_texformat_argb1555
) {
1663 for (col
= 0; col
< srcWidth
; col
++) {
1664 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1665 CHAN_TO_UBYTE(src
[RCOMP
]),
1666 CHAN_TO_UBYTE(src
[GCOMP
]),
1667 CHAN_TO_UBYTE(src
[BCOMP
]) );
1672 for (col
= 0; col
< srcWidth
; col
++) {
1673 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1674 CHAN_TO_UBYTE(src
[RCOMP
]),
1675 CHAN_TO_UBYTE(src
[GCOMP
]),
1676 CHAN_TO_UBYTE(src
[BCOMP
]) );
1680 dstRow
+= dstRowStride
;
1683 _mesa_free((void *) tempImage
);
1690 _mesa_texstore_al88(TEXSTORE_PARAMS
)
1692 const GLuint ui
= 1;
1693 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1695 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1696 dstFormat
== &_mesa_texformat_al88_rev
);
1697 ASSERT(dstFormat
->TexelBytes
== 2);
1699 if (!ctx
->_ImageTransferState
&&
1700 !srcPacking
->SwapBytes
&&
1701 dstFormat
== &_mesa_texformat_al88
&&
1702 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1703 srcFormat
== GL_LUMINANCE_ALPHA
&&
1704 srcType
== GL_UNSIGNED_BYTE
&&
1706 /* simple memcpy path */
1707 memcpy_texture(ctx
, dims
,
1708 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1711 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1712 srcAddr
, srcPacking
);
1716 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1718 dstFormat
->BaseFormat
,
1719 srcWidth
, srcHeight
, srcDepth
,
1720 srcFormat
, srcType
, srcAddr
,
1722 const GLchan
*src
= tempImage
;
1723 GLint img
, row
, col
;
1726 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1727 for (img
= 0; img
< srcDepth
; img
++) {
1728 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1729 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1730 + dstYoffset
* dstRowStride
1731 + dstXoffset
* dstFormat
->TexelBytes
;
1732 for (row
= 0; row
< srcHeight
; row
++) {
1733 GLushort
*dstUS
= (GLushort
*) dstRow
;
1734 if (dstFormat
== &_mesa_texformat_al88
) {
1735 for (col
= 0; col
< srcWidth
; col
++) {
1736 /* src[0] is luminance, src[1] is alpha */
1737 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1738 CHAN_TO_UBYTE(src
[0]) );
1743 for (col
= 0; col
< srcWidth
; col
++) {
1744 /* src[0] is luminance, src[1] is alpha */
1745 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1746 CHAN_TO_UBYTE(src
[0]) );
1750 dstRow
+= dstRowStride
;
1753 _mesa_free((void *) tempImage
);
1760 _mesa_texstore_rgb332(TEXSTORE_PARAMS
)
1762 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1763 ASSERT(dstFormat
->TexelBytes
== 1);
1765 if (!ctx
->_ImageTransferState
&&
1766 !srcPacking
->SwapBytes
&&
1767 baseInternalFormat
== GL_RGB
&&
1768 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1769 /* simple memcpy path */
1770 memcpy_texture(ctx
, dims
,
1771 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1774 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1775 srcAddr
, srcPacking
);
1779 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1781 dstFormat
->BaseFormat
,
1782 srcWidth
, srcHeight
, srcDepth
,
1783 srcFormat
, srcType
, srcAddr
,
1785 const GLchan
*src
= tempImage
;
1786 GLint img
, row
, col
;
1789 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1790 for (img
= 0; img
< srcDepth
; img
++) {
1791 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1792 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1793 + dstYoffset
* dstRowStride
1794 + dstXoffset
* dstFormat
->TexelBytes
;
1795 for (row
= 0; row
< srcHeight
; row
++) {
1796 for (col
= 0; col
< srcWidth
; col
++) {
1797 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1798 CHAN_TO_UBYTE(src
[GCOMP
]),
1799 CHAN_TO_UBYTE(src
[BCOMP
]) );
1802 dstRow
+= dstRowStride
;
1805 _mesa_free((void *) tempImage
);
1812 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1815 _mesa_texstore_a8(TEXSTORE_PARAMS
)
1817 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1818 dstFormat
== &_mesa_texformat_l8
||
1819 dstFormat
== &_mesa_texformat_i8
);
1820 ASSERT(dstFormat
->TexelBytes
== 1);
1822 if (!ctx
->_ImageTransferState
&&
1823 !srcPacking
->SwapBytes
&&
1824 baseInternalFormat
== srcFormat
&&
1825 srcType
== GL_UNSIGNED_BYTE
) {
1826 /* simple memcpy path */
1827 memcpy_texture(ctx
, dims
,
1828 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1831 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1832 srcAddr
, srcPacking
);
1836 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1838 dstFormat
->BaseFormat
,
1839 srcWidth
, srcHeight
, srcDepth
,
1840 srcFormat
, srcType
, srcAddr
,
1842 const GLchan
*src
= tempImage
;
1843 GLint img
, row
, col
;
1846 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1847 for (img
= 0; img
< srcDepth
; img
++) {
1848 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1849 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1850 + dstYoffset
* dstRowStride
1851 + dstXoffset
* dstFormat
->TexelBytes
;
1852 for (row
= 0; row
< srcHeight
; row
++) {
1853 for (col
= 0; col
< srcWidth
; col
++) {
1854 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1856 dstRow
+= dstRowStride
;
1860 _mesa_free((void *) tempImage
);
1868 _mesa_texstore_ci8(TEXSTORE_PARAMS
)
1870 (void) dims
; (void) baseInternalFormat
;
1871 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1872 ASSERT(dstFormat
->TexelBytes
== 1);
1873 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1875 if (!ctx
->_ImageTransferState
&&
1876 !srcPacking
->SwapBytes
&&
1877 srcFormat
== GL_COLOR_INDEX
&&
1878 srcType
== GL_UNSIGNED_BYTE
) {
1879 /* simple memcpy path */
1880 memcpy_texture(ctx
, dims
,
1881 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1884 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1885 srcAddr
, srcPacking
);
1890 for (img
= 0; img
< srcDepth
; img
++) {
1891 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1892 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1893 + dstYoffset
* dstRowStride
1894 + dstXoffset
* dstFormat
->TexelBytes
;
1895 for (row
= 0; row
< srcHeight
; row
++) {
1896 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
1897 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1898 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1899 srcType
, src
, srcPacking
,
1900 ctx
->_ImageTransferState
);
1901 dstRow
+= dstRowStride
;
1910 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1913 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
1915 const GLuint ui
= 1;
1916 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1917 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
1919 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1920 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1921 ASSERT(dstFormat
->TexelBytes
== 2);
1922 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1923 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1924 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1925 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1926 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1928 /* always just memcpy since no pixel transfer ops apply */
1929 memcpy_texture(ctx
, dims
,
1930 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1933 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1934 srcAddr
, srcPacking
);
1936 /* Check if we need byte swapping */
1937 /* XXX the logic here _might_ be wrong */
1938 if (srcPacking
->SwapBytes
^
1939 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1940 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1943 for (img
= 0; img
< srcDepth
; img
++) {
1944 GLubyte
*dstRow
= (GLubyte
*) dstAddr
1945 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
1946 + dstYoffset
* dstRowStride
1947 + dstXoffset
* dstFormat
->TexelBytes
;
1948 for (row
= 0; row
< srcHeight
; row
++) {
1949 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
1950 dstRow
+= dstRowStride
;
1960 * Store a combined depth/stencil texture image.
1963 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
1965 ASSERT(dstFormat
== &_mesa_texformat_z24_s8
);
1966 ASSERT(srcFormat
== GL_DEPTH_STENCIL_EXT
);
1967 ASSERT(srcType
== GL_UNSIGNED_INT_24_8_EXT
);
1969 if (!ctx
->_ImageTransferState
&&
1970 !srcPacking
->SwapBytes
) {
1972 memcpy_texture(ctx
, dims
,
1973 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1976 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1977 srcAddr
, srcPacking
);
1981 const GLint srcRowStride
1982 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
1986 for (img
= 0; img
< srcDepth
; img
++) {
1987 GLuint
*dstRow
= (GLuint
*) dstAddr
1988 + dstImageOffsets
[dstZoffset
+ img
]
1989 + dstYoffset
* dstRowStride
/ sizeof(GLuint
)
1992 = (const GLuint
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
1993 srcWidth
, srcHeight
,
1996 for (row
= 0; row
< srcHeight
; row
++) {
1997 GLubyte stencil
[MAX_WIDTH
];
1999 /* the 24 depth bits will be in the high position: */
2000 _mesa_unpack_depth_span(ctx
, srcWidth
,
2001 GL_UNSIGNED_INT
, /* dst type */
2002 dstRow
, /* dst addr */
2003 (GLfloat
) 0xffffff, /* depthScale */
2004 srcType
, src
, srcPacking
);
2005 /* get the 8-bit stencil values */
2006 _mesa_unpack_stencil_span(ctx
, srcWidth
,
2007 GL_UNSIGNED_BYTE
, /* dst type */
2008 stencil
, /* dst addr */
2009 srcType
, src
, srcPacking
,
2010 ctx
->_ImageTransferState
);
2011 /* merge stencil values into depth values */
2012 for (i
= 0; i
< srcWidth
; i
++)
2013 dstRow
[i
] |= stencil
[i
];
2015 src
+= srcRowStride
;
2016 dstRow
+= dstRowStride
/ sizeof(GLuint
);
2026 * Store an image in any of the formats:
2027 * _mesa_texformat_rgba_float32
2028 * _mesa_texformat_rgb_float32
2029 * _mesa_texformat_alpha_float32
2030 * _mesa_texformat_luminance_float32
2031 * _mesa_texformat_luminance_alpha_float32
2032 * _mesa_texformat_intensity_float32
2035 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS
)
2037 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2039 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
2040 dstFormat
== &_mesa_texformat_rgb_float32
||
2041 dstFormat
== &_mesa_texformat_alpha_float32
||
2042 dstFormat
== &_mesa_texformat_luminance_float32
||
2043 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
2044 dstFormat
== &_mesa_texformat_intensity_float32
);
2045 ASSERT(baseInternalFormat
== GL_RGBA
||
2046 baseInternalFormat
== GL_RGB
||
2047 baseInternalFormat
== GL_ALPHA
||
2048 baseInternalFormat
== GL_LUMINANCE
||
2049 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2050 baseInternalFormat
== GL_INTENSITY
);
2051 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
2053 if (!ctx
->_ImageTransferState
&&
2054 !srcPacking
->SwapBytes
&&
2055 baseInternalFormat
== srcFormat
&&
2056 srcType
== GL_FLOAT
) {
2057 /* simple memcpy path */
2058 memcpy_texture(ctx
, dims
,
2059 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2062 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2063 srcAddr
, srcPacking
);
2067 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2069 dstFormat
->BaseFormat
,
2070 srcWidth
, srcHeight
, srcDepth
,
2071 srcFormat
, srcType
, srcAddr
,
2073 const GLfloat
*srcRow
= tempImage
;
2078 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2079 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
2080 for (img
= 0; img
< srcDepth
; img
++) {
2081 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2082 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2083 + dstYoffset
* dstRowStride
2084 + dstXoffset
* dstFormat
->TexelBytes
;
2085 for (row
= 0; row
< srcHeight
; row
++) {
2086 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
2087 dstRow
+= dstRowStride
;
2088 srcRow
+= srcWidth
* components
;
2092 _mesa_free((void *) tempImage
);
2099 * As above, but store 16-bit floats.
2102 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS
)
2104 const GLint components
= _mesa_components_in_format(dstFormat
->BaseFormat
);
2106 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
2107 dstFormat
== &_mesa_texformat_rgb_float16
||
2108 dstFormat
== &_mesa_texformat_alpha_float16
||
2109 dstFormat
== &_mesa_texformat_luminance_float16
||
2110 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
2111 dstFormat
== &_mesa_texformat_intensity_float16
);
2112 ASSERT(baseInternalFormat
== GL_RGBA
||
2113 baseInternalFormat
== GL_RGB
||
2114 baseInternalFormat
== GL_ALPHA
||
2115 baseInternalFormat
== GL_LUMINANCE
||
2116 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2117 baseInternalFormat
== GL_INTENSITY
);
2118 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2120 if (!ctx
->_ImageTransferState
&&
2121 !srcPacking
->SwapBytes
&&
2122 baseInternalFormat
== srcFormat
&&
2123 srcType
== GL_HALF_FLOAT_ARB
) {
2124 /* simple memcpy path */
2125 memcpy_texture(ctx
, dims
,
2126 dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2129 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2130 srcAddr
, srcPacking
);
2134 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2136 dstFormat
->BaseFormat
,
2137 srcWidth
, srcHeight
, srcDepth
,
2138 srcFormat
, srcType
, srcAddr
,
2140 const GLfloat
*src
= tempImage
;
2144 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2145 for (img
= 0; img
< srcDepth
; img
++) {
2146 GLubyte
*dstRow
= (GLubyte
*) dstAddr
2147 + dstImageOffsets
[dstZoffset
+ img
] * dstFormat
->TexelBytes
2148 + dstYoffset
* dstRowStride
2149 + dstXoffset
* dstFormat
->TexelBytes
;
2150 for (row
= 0; row
< srcHeight
; row
++) {
2151 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2153 for (i
= 0; i
< srcWidth
* components
; i
++) {
2154 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2156 dstRow
+= dstRowStride
;
2157 src
+= srcWidth
* components
;
2161 _mesa_free((void *) tempImage
);
2169 * Check if an unpack PBO is active prior to fetching a texture image.
2170 * If so, do bounds checking and map the buffer into main memory.
2171 * Any errors detected will be recorded.
2172 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2175 _mesa_validate_pbo_teximage(GLcontext
*ctx
, GLuint dimensions
,
2176 GLsizei width
, GLsizei height
, GLsizei depth
,
2177 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2178 const struct gl_pixelstore_attrib
*unpack
,
2179 const char *funcName
)
2183 if (unpack
->BufferObj
->Name
== 0) {
2187 if (!_mesa_validate_pbo_access(dimensions
, unpack
, width
, height
, depth
,
2188 format
, type
, pixels
)) {
2189 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2193 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2194 GL_READ_ONLY_ARB
, unpack
->BufferObj
);
2196 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2200 return ADD_POINTERS(buf
, pixels
);
2205 * Check if an unpack PBO is active prior to fetching a compressed texture
2207 * If so, do bounds checking and map the buffer into main memory.
2208 * Any errors detected will be recorded.
2209 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2212 _mesa_validate_pbo_compressed_teximage(GLcontext
*ctx
,
2213 GLsizei imageSize
, const GLvoid
*pixels
,
2214 const struct gl_pixelstore_attrib
*packing
,
2215 const char *funcName
)
2219 if (packing
->BufferObj
->Name
== 0) {
2220 /* not using a PBO - return pointer unchanged */
2223 if ((const GLubyte
*) pixels
+ imageSize
>
2224 ((const GLubyte
*) 0) + packing
->BufferObj
->Size
) {
2225 /* out of bounds read! */
2226 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(invalid PBO access");
2230 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2231 GL_READ_ONLY_ARB
, packing
->BufferObj
);
2233 _mesa_error(ctx
, GL_INVALID_OPERATION
, funcName
, "(PBO is mapped");
2237 return ADD_POINTERS(buf
, pixels
);
2242 * This function must be called after either of the validate_pbo_*_teximage()
2243 * functions. It unmaps the PBO buffer if it was mapped earlier.
2246 _mesa_unmap_teximage_pbo(GLcontext
*ctx
,
2247 const struct gl_pixelstore_attrib
*unpack
)
2249 if (unpack
->BufferObj
->Name
) {
2250 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
2258 * Adaptor for fetching a GLchan texel from a float-valued texture.
2261 FetchTexelFloatToChan( const struct gl_texture_image
*texImage
,
2262 GLint i
, GLint j
, GLint k
, GLchan
*texelOut
)
2265 ASSERT(texImage
->FetchTexelf
);
2266 texImage
->FetchTexelf(texImage
, i
, j
, k
, temp
);
2267 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2268 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2269 /* just one channel */
2270 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2274 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[0], temp
[0]);
2275 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[1], temp
[1]);
2276 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[2], temp
[2]);
2277 UNCLAMPED_FLOAT_TO_CHAN(texelOut
[3], temp
[3]);
2283 * Adaptor for fetching a float texel from a GLchan-valued texture.
2286 FetchTexelChanToFloat( const struct gl_texture_image
*texImage
,
2287 GLint i
, GLint j
, GLint k
, GLfloat
*texelOut
)
2290 ASSERT(texImage
->FetchTexelc
);
2291 texImage
->FetchTexelc(texImage
, i
, j
, k
, temp
);
2292 if (texImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2293 texImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2294 /* just one channel */
2295 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2299 texelOut
[0] = CHAN_TO_FLOAT(temp
[0]);
2300 texelOut
[1] = CHAN_TO_FLOAT(temp
[1]);
2301 texelOut
[2] = CHAN_TO_FLOAT(temp
[2]);
2302 texelOut
[3] = CHAN_TO_FLOAT(temp
[3]);
2308 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2311 set_fetch_functions(struct gl_texture_image
*texImage
, GLuint dims
)
2313 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2314 ASSERT(texImage
->TexFormat
);
2318 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2319 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2322 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2323 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2326 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2327 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2333 /* now check if we need to use a float/chan adaptor */
2334 if (!texImage
->FetchTexelc
) {
2335 texImage
->FetchTexelc
= FetchTexelFloatToChan
;
2337 else if (!texImage
->FetchTexelf
) {
2338 texImage
->FetchTexelf
= FetchTexelChanToFloat
;
2342 ASSERT(texImage
->FetchTexelc
);
2343 ASSERT(texImage
->FetchTexelf
);
2348 * Choose the actual storage format for a new texture image.
2349 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2350 * Also set some other texImage fields related to texture compression, etc.
2351 * \param ctx rendering context
2352 * \param texImage the gl_texture_image
2353 * \param dims texture dimensions (1, 2 or 3)
2354 * \param format the user-specified format parameter
2355 * \param type the user-specified type parameter
2356 * \param internalFormat the user-specified internal format hint
2359 choose_texture_format(GLcontext
*ctx
, struct gl_texture_image
*texImage
,
2361 GLenum format
, GLenum type
, GLint internalFormat
)
2363 ASSERT(dims
== 1 || dims
== 2 || dims
== 3);
2364 ASSERT(ctx
->Driver
.ChooseTextureFormat
);
2367 = ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
, format
, type
);
2369 ASSERT(texImage
->TexFormat
);
2371 set_fetch_functions(texImage
, dims
);
2373 if (texImage
->TexFormat
->TexelBytes
== 0) {
2374 /* must be a compressed format */
2375 texImage
->IsCompressed
= GL_TRUE
;
2376 texImage
->CompressedSize
=
2377 ctx
->Driver
.CompressedTextureSize(ctx
, texImage
->Width
,
2378 texImage
->Height
, texImage
->Depth
,
2379 texImage
->TexFormat
->MesaFormat
);
2382 /* non-compressed format */
2383 texImage
->IsCompressed
= GL_FALSE
;
2384 texImage
->CompressedSize
= 0;
2391 * This is the software fallback for Driver.TexImage1D()
2392 * and Driver.CopyTexImage1D().
2393 * \sa _mesa_store_teximage2d()
2396 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2397 GLint internalFormat
,
2398 GLint width
, GLint border
,
2399 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2400 const struct gl_pixelstore_attrib
*packing
,
2401 struct gl_texture_object
*texObj
,
2402 struct gl_texture_image
*texImage
)
2404 GLint postConvWidth
= width
;
2408 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2409 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2412 choose_texture_format(ctx
, texImage
, 1, format
, type
, internalFormat
);
2414 /* allocate memory */
2415 if (texImage
->IsCompressed
)
2416 sizeInBytes
= texImage
->CompressedSize
;
2418 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2419 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2420 if (!texImage
->Data
) {
2421 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2425 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2426 pixels
, packing
, "glTexImage1D");
2428 /* Note: we check for a NULL image pointer here, _after_ we allocated
2429 * memory for the texture. That's what the GL spec calls for.
2434 const GLint dstRowStride
= 0;
2436 ASSERT(texImage
->TexFormat
->StoreImage
);
2437 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2438 texImage
->TexFormat
,
2440 0, 0, 0, /* dstX/Y/Zoffset */
2442 texImage
->ImageOffsets
,
2444 format
, type
, pixels
, packing
);
2446 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2450 /* GL_SGIS_generate_mipmap */
2451 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2452 _mesa_generate_mipmap(ctx
, target
,
2453 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2457 _mesa_unmap_teximage_pbo(ctx
, packing
);
2462 * This is the software fallback for Driver.TexImage2D()
2463 * and Driver.CopyTexImage2D().
2465 * This function is oriented toward storing images in main memory, rather
2466 * than VRAM. Device driver's can easily plug in their own replacement.
2468 * Note: width and height may be pre-convolved dimensions, but
2469 * texImage->Width and texImage->Height will be post-convolved dimensions.
2472 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2473 GLint internalFormat
,
2474 GLint width
, GLint height
, GLint border
,
2475 GLenum format
, GLenum type
, const void *pixels
,
2476 const struct gl_pixelstore_attrib
*packing
,
2477 struct gl_texture_object
*texObj
,
2478 struct gl_texture_image
*texImage
)
2480 GLint postConvWidth
= width
, postConvHeight
= height
;
2481 GLint texelBytes
, sizeInBytes
;
2484 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2485 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2489 choose_texture_format(ctx
, texImage
, 2, format
, type
, internalFormat
);
2491 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2493 /* allocate memory */
2494 if (texImage
->IsCompressed
)
2495 sizeInBytes
= texImage
->CompressedSize
;
2497 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2498 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2499 if (!texImage
->Data
) {
2500 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2504 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2505 pixels
, packing
, "glTexImage2D");
2507 /* Note: we check for a NULL image pointer here, _after_ we allocated
2508 * memory for the texture. That's what the GL spec calls for.
2515 if (texImage
->IsCompressed
) {
2517 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2520 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2522 ASSERT(texImage
->TexFormat
->StoreImage
);
2523 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2524 texImage
->TexFormat
,
2526 0, 0, 0, /* dstX/Y/Zoffset */
2528 texImage
->ImageOffsets
,
2530 format
, type
, pixels
, packing
);
2532 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2536 /* GL_SGIS_generate_mipmap */
2537 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2538 _mesa_generate_mipmap(ctx
, target
,
2539 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2543 _mesa_unmap_teximage_pbo(ctx
, packing
);
2549 * This is the software fallback for Driver.TexImage3D()
2550 * and Driver.CopyTexImage3D().
2551 * \sa _mesa_store_teximage2d()
2554 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2555 GLint internalFormat
,
2556 GLint width
, GLint height
, GLint depth
, GLint border
,
2557 GLenum format
, GLenum type
, const void *pixels
,
2558 const struct gl_pixelstore_attrib
*packing
,
2559 struct gl_texture_object
*texObj
,
2560 struct gl_texture_image
*texImage
)
2562 GLint texelBytes
, sizeInBytes
;
2565 choose_texture_format(ctx
, texImage
, 3, format
, type
, internalFormat
);
2567 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2569 /* allocate memory */
2570 if (texImage
->IsCompressed
)
2571 sizeInBytes
= texImage
->CompressedSize
;
2573 sizeInBytes
= width
* height
* depth
* texelBytes
;
2574 texImage
->Data
= _mesa_alloc_texmemory(sizeInBytes
);
2575 if (!texImage
->Data
) {
2576 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2580 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2581 type
, pixels
, packing
, "glTexImage3D");
2583 /* Note: we check for a NULL image pointer here, _after_ we allocated
2584 * memory for the texture. That's what the GL spec calls for.
2591 if (texImage
->IsCompressed
) {
2593 = _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, width
);
2596 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2598 ASSERT(texImage
->TexFormat
->StoreImage
);
2599 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2600 texImage
->TexFormat
,
2602 0, 0, 0, /* dstX/Y/Zoffset */
2604 texImage
->ImageOffsets
,
2605 width
, height
, depth
,
2606 format
, type
, pixels
, packing
);
2608 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2612 /* GL_SGIS_generate_mipmap */
2613 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2614 _mesa_generate_mipmap(ctx
, target
,
2615 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2619 _mesa_unmap_teximage_pbo(ctx
, packing
);
2626 * This is the software fallback for Driver.TexSubImage1D()
2627 * and Driver.CopyTexSubImage1D().
2630 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2631 GLint xoffset
, GLint width
,
2632 GLenum format
, GLenum type
, const void *pixels
,
2633 const struct gl_pixelstore_attrib
*packing
,
2634 struct gl_texture_object
*texObj
,
2635 struct gl_texture_image
*texImage
)
2637 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2638 pixels
= _mesa_validate_pbo_teximage(ctx
, 1, width
, 1, 1, format
, type
,
2639 pixels
, packing
, "glTexSubImage1D");
2644 const GLint dstRowStride
= 0;
2646 ASSERT(texImage
->TexFormat
->StoreImage
);
2647 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->_BaseFormat
,
2648 texImage
->TexFormat
,
2650 xoffset
, 0, 0, /* offsets */
2652 texImage
->ImageOffsets
,
2654 format
, type
, pixels
, packing
);
2656 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2660 /* GL_SGIS_generate_mipmap */
2661 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2662 _mesa_generate_mipmap(ctx
, target
,
2663 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2667 _mesa_unmap_teximage_pbo(ctx
, packing
);
2673 * This is the software fallback for Driver.TexSubImage2D()
2674 * and Driver.CopyTexSubImage2D().
2677 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2678 GLint xoffset
, GLint yoffset
,
2679 GLint width
, GLint height
,
2680 GLenum format
, GLenum type
, const void *pixels
,
2681 const struct gl_pixelstore_attrib
*packing
,
2682 struct gl_texture_object
*texObj
,
2683 struct gl_texture_image
*texImage
)
2685 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2686 pixels
= _mesa_validate_pbo_teximage(ctx
, 2, width
, height
, 1, format
, type
,
2687 pixels
, packing
, "glTexSubImage2D");
2692 GLint dstRowStride
= 0;
2694 if (texImage
->IsCompressed
) {
2695 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
2699 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2701 ASSERT(texImage
->TexFormat
->StoreImage
);
2702 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
2703 texImage
->TexFormat
,
2705 xoffset
, yoffset
, 0,
2707 texImage
->ImageOffsets
,
2709 format
, type
, pixels
, packing
);
2711 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2715 /* GL_SGIS_generate_mipmap */
2716 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2717 _mesa_generate_mipmap(ctx
, target
,
2718 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2722 _mesa_unmap_teximage_pbo(ctx
, packing
);
2727 * This is the software fallback for Driver.TexSubImage3D().
2728 * and Driver.CopyTexSubImage3D().
2731 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2732 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2733 GLint width
, GLint height
, GLint depth
,
2734 GLenum format
, GLenum type
, const void *pixels
,
2735 const struct gl_pixelstore_attrib
*packing
,
2736 struct gl_texture_object
*texObj
,
2737 struct gl_texture_image
*texImage
)
2739 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2740 pixels
= _mesa_validate_pbo_teximage(ctx
, 3, width
, height
, depth
, format
,
2741 type
, pixels
, packing
,
2749 if (texImage
->IsCompressed
) {
2750 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
,
2754 dstRowStride
= texImage
->RowStride
* texImage
->TexFormat
->TexelBytes
;
2756 ASSERT(texImage
->TexFormat
->StoreImage
);
2757 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->_BaseFormat
,
2758 texImage
->TexFormat
,
2760 xoffset
, yoffset
, zoffset
,
2762 texImage
->ImageOffsets
,
2763 width
, height
, depth
,
2764 format
, type
, pixels
, packing
);
2766 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2770 /* GL_SGIS_generate_mipmap */
2771 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2772 _mesa_generate_mipmap(ctx
, target
,
2773 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2777 _mesa_unmap_teximage_pbo(ctx
, packing
);
2782 * Fallback for Driver.CompressedTexImage1D()
2785 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2786 GLint internalFormat
,
2787 GLint width
, GLint border
,
2788 GLsizei imageSize
, const GLvoid
*data
,
2789 struct gl_texture_object
*texObj
,
2790 struct gl_texture_image
*texImage
)
2792 /* this space intentionally left blank */
2794 (void) target
; (void) level
;
2795 (void) internalFormat
;
2796 (void) width
; (void) border
;
2797 (void) imageSize
; (void) data
;
2805 * Fallback for Driver.CompressedTexImage2D()
2808 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2809 GLint internalFormat
,
2810 GLint width
, GLint height
, GLint border
,
2811 GLsizei imageSize
, const GLvoid
*data
,
2812 struct gl_texture_object
*texObj
,
2813 struct gl_texture_image
*texImage
)
2815 (void) width
; (void) height
; (void) border
;
2817 /* This is pretty simple, basically just do a memcpy without worrying
2818 * about the usual image unpacking or image transfer operations.
2822 ASSERT(texImage
->Width
> 0);
2823 ASSERT(texImage
->Height
> 0);
2824 ASSERT(texImage
->Depth
== 1);
2825 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2827 choose_texture_format(ctx
, texImage
, 2, 0, 0, internalFormat
);
2829 /* allocate storage */
2830 texImage
->Data
= _mesa_alloc_texmemory(imageSize
);
2831 if (!texImage
->Data
) {
2832 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2836 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2838 "glCompressedTexImage2D");
2843 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2844 MEMCPY(texImage
->Data
, data
, imageSize
);
2846 /* GL_SGIS_generate_mipmap */
2847 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2848 _mesa_generate_mipmap(ctx
, target
,
2849 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2853 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2859 * Fallback for Driver.CompressedTexImage3D()
2862 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2863 GLint internalFormat
,
2864 GLint width
, GLint height
, GLint depth
,
2866 GLsizei imageSize
, const GLvoid
*data
,
2867 struct gl_texture_object
*texObj
,
2868 struct gl_texture_image
*texImage
)
2870 /* this space intentionally left blank */
2872 (void) target
; (void) level
;
2873 (void) internalFormat
;
2874 (void) width
; (void) height
; (void) depth
;
2876 (void) imageSize
; (void) data
;
2884 * Fallback for Driver.CompressedTexSubImage1D()
2887 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2889 GLint xoffset
, GLsizei width
,
2891 GLsizei imageSize
, const GLvoid
*data
,
2892 struct gl_texture_object
*texObj
,
2893 struct gl_texture_image
*texImage
)
2895 /* there are no compressed 1D texture formats yet */
2897 (void) target
; (void) level
;
2898 (void) xoffset
; (void) width
;
2900 (void) imageSize
; (void) data
;
2907 * Fallback for Driver.CompressedTexSubImage2D()
2910 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2912 GLint xoffset
, GLint yoffset
,
2913 GLsizei width
, GLsizei height
,
2915 GLsizei imageSize
, const GLvoid
*data
,
2916 struct gl_texture_object
*texObj
,
2917 struct gl_texture_image
*texImage
)
2919 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2923 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
2927 /* these should have been caught sooner */
2928 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2929 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2930 ASSERT((xoffset
& 3) == 0);
2931 ASSERT((yoffset
& 3) == 0);
2933 /* get pointer to src pixels (may be in a pbo which we'll map here) */
2934 data
= _mesa_validate_pbo_compressed_teximage(ctx
, imageSize
, data
,
2936 "glCompressedTexSubImage2D");
2940 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
2941 src
= (const GLubyte
*) data
;
2943 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
2944 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2945 texImage
->TexFormat
->MesaFormat
,
2947 (GLubyte
*) texImage
->Data
);
2949 bytesPerRow
= srcRowStride
;
2952 for (i
= 0; i
< rows
; i
++) {
2953 MEMCPY(dest
, src
, bytesPerRow
);
2954 dest
+= destRowStride
;
2955 src
+= srcRowStride
;
2958 /* GL_SGIS_generate_mipmap */
2959 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2960 _mesa_generate_mipmap(ctx
, target
,
2961 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2965 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);
2970 * Fallback for Driver.CompressedTexSubImage3D()
2973 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2975 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2976 GLsizei width
, GLsizei height
, GLsizei depth
,
2978 GLsizei imageSize
, const GLvoid
*data
,
2979 struct gl_texture_object
*texObj
,
2980 struct gl_texture_image
*texImage
)
2982 /* there are no compressed 3D texture formats yet */
2984 (void) target
; (void) level
;
2985 (void) xoffset
; (void) yoffset
; (void) zoffset
;
2986 (void) width
; (void) height
; (void) depth
;
2988 (void) imageSize
; (void) data
;
2995 * Average together two rows of a source image to produce a single new
2996 * row in the dest image. It's legal for the two source rows to point
2997 * to the same data. The source width must be equal to either the
2998 * dest width or two times the dest width.
3001 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
3002 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
3003 GLint dstWidth
, GLvoid
*dstRow
)
3005 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
3006 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
3008 /* This assertion is no longer valid with non-power-of-2 textures
3009 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
3012 switch (format
->MesaFormat
) {
3013 case MESA_FORMAT_RGBA
:
3016 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
3017 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
3018 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
3019 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3020 i
++, j
+= colStride
, k
+= colStride
) {
3021 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3022 rowB
[j
][0] + rowB
[k
][0]) / 4;
3023 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3024 rowB
[j
][1] + rowB
[k
][1]) / 4;
3025 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3026 rowB
[j
][2] + rowB
[k
][2]) / 4;
3027 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3028 rowB
[j
][3] + rowB
[k
][3]) / 4;
3032 case MESA_FORMAT_RGB
:
3035 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
3036 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
3037 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
3038 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3039 i
++, j
+= colStride
, k
+= colStride
) {
3040 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3041 rowB
[j
][0] + rowB
[k
][0]) / 4;
3042 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3043 rowB
[j
][1] + rowB
[k
][1]) / 4;
3044 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3045 rowB
[j
][2] + rowB
[k
][2]) / 4;
3049 case MESA_FORMAT_ALPHA
:
3050 case MESA_FORMAT_LUMINANCE
:
3051 case MESA_FORMAT_INTENSITY
:
3054 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
3055 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
3056 GLchan
*dst
= (GLchan
*) dstRow
;
3057 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3058 i
++, j
+= colStride
, k
+= colStride
) {
3059 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3063 case MESA_FORMAT_LUMINANCE_ALPHA
:
3066 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
3067 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
3068 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
3069 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3070 i
++, j
+= colStride
, k
+= colStride
) {
3071 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3072 rowB
[j
][0] + rowB
[k
][0]) / 4;
3073 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3074 rowB
[j
][1] + rowB
[k
][1]) / 4;
3078 case MESA_FORMAT_Z32
:
3081 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
3082 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
3083 GLfloat
*dst
= (GLfloat
*) dstRow
;
3084 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3085 i
++, j
+= colStride
, k
+= colStride
) {
3086 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
3090 case MESA_FORMAT_Z16
:
3093 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3094 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3095 GLushort
*dst
= (GLushort
*) dstRow
;
3096 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3097 i
++, j
+= colStride
, k
+= colStride
) {
3098 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
3102 /* Begin hardware formats */
3103 case MESA_FORMAT_RGBA8888
:
3104 case MESA_FORMAT_RGBA8888_REV
:
3105 case MESA_FORMAT_ARGB8888
:
3106 case MESA_FORMAT_ARGB8888_REV
:
3109 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
3110 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
3111 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
3112 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3113 i
++, j
+= colStride
, k
+= colStride
) {
3114 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3115 rowB
[j
][0] + rowB
[k
][0]) / 4;
3116 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3117 rowB
[j
][1] + rowB
[k
][1]) / 4;
3118 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3119 rowB
[j
][2] + rowB
[k
][2]) / 4;
3120 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3121 rowB
[j
][3] + rowB
[k
][3]) / 4;
3125 case MESA_FORMAT_RGB888
:
3126 case MESA_FORMAT_BGR888
:
3129 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
3130 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
3131 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
3132 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3133 i
++, j
+= colStride
, k
+= colStride
) {
3134 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3135 rowB
[j
][0] + rowB
[k
][0]) / 4;
3136 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3137 rowB
[j
][1] + rowB
[k
][1]) / 4;
3138 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3139 rowB
[j
][2] + rowB
[k
][2]) / 4;
3143 case MESA_FORMAT_RGB565
:
3144 case MESA_FORMAT_RGB565_REV
:
3147 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3148 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3149 GLushort
*dst
= (GLushort
*) dstRow
;
3150 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3151 i
++, j
+= colStride
, k
+= colStride
) {
3152 const GLint rowAr0
= rowA
[j
] & 0x1f;
3153 const GLint rowAr1
= rowA
[k
] & 0x1f;
3154 const GLint rowBr0
= rowB
[j
] & 0x1f;
3155 const GLint rowBr1
= rowB
[k
] & 0x1f;
3156 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
3157 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
3158 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
3159 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
3160 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
3161 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
3162 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
3163 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
3164 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3165 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3166 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3167 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
3171 case MESA_FORMAT_ARGB4444
:
3172 case MESA_FORMAT_ARGB4444_REV
:
3175 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3176 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3177 GLushort
*dst
= (GLushort
*) dstRow
;
3178 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3179 i
++, j
+= colStride
, k
+= colStride
) {
3180 const GLint rowAr0
= rowA
[j
] & 0xf;
3181 const GLint rowAr1
= rowA
[k
] & 0xf;
3182 const GLint rowBr0
= rowB
[j
] & 0xf;
3183 const GLint rowBr1
= rowB
[k
] & 0xf;
3184 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
3185 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
3186 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
3187 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
3188 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
3189 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
3190 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
3191 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
3192 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
3193 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
3194 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
3195 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
3196 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3197 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3198 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3199 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3200 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
3204 case MESA_FORMAT_ARGB1555
:
3205 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
3208 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
3209 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
3210 GLushort
*dst
= (GLushort
*) dstRow
;
3211 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3212 i
++, j
+= colStride
, k
+= colStride
) {
3213 const GLint rowAr0
= rowA
[j
] & 0x1f;
3214 const GLint rowAr1
= rowA
[k
] & 0x1f;
3215 const GLint rowBr0
= rowB
[j
] & 0x1f;
3216 const GLint rowBr1
= rowB
[k
] & 0xf;
3217 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
3218 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
3219 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
3220 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
3221 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
3222 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
3223 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
3224 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
3225 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
3226 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
3227 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
3228 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
3229 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3230 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3231 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3232 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
3233 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
3237 case MESA_FORMAT_AL88
:
3238 case MESA_FORMAT_AL88_REV
:
3241 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
3242 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
3243 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
3244 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3245 i
++, j
+= colStride
, k
+= colStride
) {
3246 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3247 rowB
[j
][0] + rowB
[k
][0]) >> 2;
3248 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3249 rowB
[j
][1] + rowB
[k
][1]) >> 2;
3253 case MESA_FORMAT_RGB332
:
3256 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3257 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3258 GLubyte
*dst
= (GLubyte
*) dstRow
;
3259 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3260 i
++, j
+= colStride
, k
+= colStride
) {
3261 const GLint rowAr0
= rowA
[j
] & 0x3;
3262 const GLint rowAr1
= rowA
[k
] & 0x3;
3263 const GLint rowBr0
= rowB
[j
] & 0x3;
3264 const GLint rowBr1
= rowB
[k
] & 0x3;
3265 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
3266 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
3267 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
3268 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
3269 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
3270 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
3271 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
3272 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
3273 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
3274 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
3275 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
3276 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
3280 case MESA_FORMAT_A8
:
3281 case MESA_FORMAT_L8
:
3282 case MESA_FORMAT_I8
:
3283 case MESA_FORMAT_CI8
:
3286 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
3287 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
3288 GLubyte
*dst
= (GLubyte
*) dstRow
;
3289 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3290 i
++, j
+= colStride
, k
+= colStride
) {
3291 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
3295 case MESA_FORMAT_RGBA_FLOAT32
:
3298 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
3299 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
3300 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
3301 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3302 i
++, j
+= colStride
, k
+= colStride
) {
3303 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3304 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3305 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3306 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3307 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3308 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3309 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
3310 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
3314 case MESA_FORMAT_RGBA_FLOAT16
:
3316 GLuint i
, j
, k
, comp
;
3317 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
3318 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
3319 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
3320 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3321 i
++, j
+= colStride
, k
+= colStride
) {
3322 for (comp
= 0; comp
< 4; comp
++) {
3323 GLfloat aj
, ak
, bj
, bk
;
3324 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3325 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3326 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3327 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3328 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3333 case MESA_FORMAT_RGB_FLOAT32
:
3336 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3337 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3338 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3339 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3340 i
++, j
+= colStride
, k
+= colStride
) {
3341 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3342 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3343 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3344 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3345 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3346 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3350 case MESA_FORMAT_RGB_FLOAT16
:
3352 GLuint i
, j
, k
, comp
;
3353 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3354 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3355 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3356 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3357 i
++, j
+= colStride
, k
+= colStride
) {
3358 for (comp
= 0; comp
< 3; comp
++) {
3359 GLfloat aj
, ak
, bj
, bk
;
3360 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3361 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3362 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3363 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3364 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3369 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3372 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3373 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3374 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3375 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3376 i
++, j
+= colStride
, k
+= colStride
) {
3377 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3378 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3379 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3380 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3384 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3386 GLuint i
, j
, k
, comp
;
3387 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3388 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3389 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3390 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3391 i
++, j
+= colStride
, k
+= colStride
) {
3392 for (comp
= 0; comp
< 2; comp
++) {
3393 GLfloat aj
, ak
, bj
, bk
;
3394 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3395 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3396 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3397 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3398 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3403 case MESA_FORMAT_ALPHA_FLOAT32
:
3404 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3405 case MESA_FORMAT_INTENSITY_FLOAT32
:
3408 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3409 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3410 GLfloat
*dst
= (GLfloat
*) dstRow
;
3411 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3412 i
++, j
+= colStride
, k
+= colStride
) {
3413 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3417 case MESA_FORMAT_ALPHA_FLOAT16
:
3418 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3419 case MESA_FORMAT_INTENSITY_FLOAT16
:
3422 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3423 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3424 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3425 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3426 i
++, j
+= colStride
, k
+= colStride
) {
3427 GLfloat aj
, ak
, bj
, bk
;
3428 aj
= _mesa_half_to_float(rowA
[j
]);
3429 ak
= _mesa_half_to_float(rowA
[k
]);
3430 bj
= _mesa_half_to_float(rowB
[j
]);
3431 bk
= _mesa_half_to_float(rowB
[k
]);
3432 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3438 _mesa_problem(NULL
, "bad format in do_row()");
3444 * These functions generate a 1/2-size mipmap image from a source image.
3445 * Texture borders are handled by copying or averaging the source image's
3446 * border texels, depending on the scale-down factor.
3450 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3451 GLint srcWidth
, const GLubyte
*srcPtr
,
3452 GLint dstWidth
, GLubyte
*dstPtr
)
3454 const GLint bpt
= format
->TexelBytes
;
3458 /* skip the border pixel, if any */
3459 src
= srcPtr
+ border
* bpt
;
3460 dst
= dstPtr
+ border
* bpt
;
3462 /* we just duplicate the input row, kind of hack, saves code */
3463 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3464 dstWidth
- 2 * border
, dst
);
3467 /* copy left-most pixel from source */
3468 MEMCPY(dstPtr
, srcPtr
, bpt
);
3469 /* copy right-most pixel from source */
3470 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3471 srcPtr
+ (srcWidth
- 1) * bpt
,
3478 * XXX need to use the tex image's row stride!
3481 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3482 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3483 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3485 const GLint bpt
= format
->TexelBytes
;
3486 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3487 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3488 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3489 const GLint srcRowStride
= bpt
* srcWidth
;
3490 const GLint dstRowStride
= bpt
* dstWidth
;
3491 const GLubyte
*srcA
, *srcB
;
3495 /* Compute src and dst pointers, skipping any border */
3496 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3498 srcB
= srcA
+ srcRowStride
;
3501 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3503 for (row
= 0; row
< dstHeightNB
; row
++) {
3504 do_row(format
, srcWidthNB
, srcA
, srcB
,
3506 srcA
+= 2 * srcRowStride
;
3507 srcB
+= 2 * srcRowStride
;
3508 dst
+= dstRowStride
;
3511 /* This is ugly but probably won't be used much */
3513 /* fill in dest border */
3514 /* lower-left border pixel */
3515 MEMCPY(dstPtr
, srcPtr
, bpt
);
3516 /* lower-right border pixel */
3517 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3518 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3519 /* upper-left border pixel */
3520 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3521 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3522 /* upper-right border pixel */
3523 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3524 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3526 do_row(format
, srcWidthNB
,
3529 dstWidthNB
, dstPtr
+ bpt
);
3531 do_row(format
, srcWidthNB
,
3532 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3533 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3535 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3536 /* left and right borders */
3537 if (srcHeight
== dstHeight
) {
3538 /* copy border pixel from src to dst */
3539 for (row
= 1; row
< srcHeight
; row
++) {
3540 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3541 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3542 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3543 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3547 /* average two src pixels each dest pixel */
3548 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3550 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3551 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3552 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3554 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3555 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3556 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3564 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3565 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3566 const GLubyte
*srcPtr
,
3567 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3570 const GLint bpt
= format
->TexelBytes
;
3571 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3572 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3573 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3574 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3575 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3576 GLvoid
*tmpRowA
, *tmpRowB
;
3578 GLint bytesPerSrcImage
, bytesPerDstImage
;
3579 GLint bytesPerSrcRow
, bytesPerDstRow
;
3580 GLint srcImageOffset
, srcRowOffset
;
3582 (void) srcDepthNB
; /* silence warnings */
3584 /* Need two temporary row buffers */
3585 tmpRowA
= _mesa_malloc(srcWidth
* bpt
);
3588 tmpRowB
= _mesa_malloc(srcWidth
* bpt
);
3590 _mesa_free(tmpRowA
);
3594 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3595 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3597 bytesPerSrcRow
= srcWidth
* bpt
;
3598 bytesPerDstRow
= dstWidth
* bpt
;
3600 /* Offset between adjacent src images to be averaged together */
3601 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3603 /* Offset between adjacent src rows to be averaged together */
3604 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3607 * Need to average together up to 8 src pixels for each dest pixel.
3608 * Break that down into 3 operations:
3609 * 1. take two rows from source image and average them together.
3610 * 2. take two rows from next source image and average them together.
3611 * 3. take the two averaged rows and average them for the final dst row.
3615 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3616 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3619 for (img
= 0; img
< dstDepthNB
; img
++) {
3620 /* first source image pointer, skipping border */
3621 const GLubyte
*imgSrcA
= srcPtr
3622 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3623 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3624 /* second source image pointer, skipping border */
3625 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3626 /* address of the dest image, skipping border */
3627 GLubyte
*imgDst
= dstPtr
3628 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3629 + img
* bytesPerDstImage
;
3631 /* setup the four source row pointers and the dest row pointer */
3632 const GLubyte
*srcImgARowA
= imgSrcA
;
3633 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3634 const GLubyte
*srcImgBRowA
= imgSrcB
;
3635 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3636 GLubyte
*dstImgRow
= imgDst
;
3638 for (row
= 0; row
< dstHeightNB
; row
++) {
3639 /* Average together two rows from first src image */
3640 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3641 srcWidthNB
, tmpRowA
);
3642 /* Average together two rows from second src image */
3643 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3644 srcWidthNB
, tmpRowB
);
3645 /* Average together the temp rows to make the final row */
3646 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3647 dstWidthNB
, dstImgRow
);
3648 /* advance to next rows */
3649 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3650 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3651 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3652 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3653 dstImgRow
+= bytesPerDstRow
;
3657 _mesa_free(tmpRowA
);
3658 _mesa_free(tmpRowB
);
3660 /* Luckily we can leverage the make_2d_mipmap() function here! */
3662 /* do front border image */
3663 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3664 dstWidth
, dstHeight
, dstPtr
);
3665 /* do back border image */
3666 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3667 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3668 dstWidth
, dstHeight
,
3669 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3670 /* do four remaining border edges that span the image slices */
3671 if (srcDepth
== dstDepth
) {
3672 /* just copy border pixels from src to dst */
3673 for (img
= 0; img
< dstDepthNB
; img
++) {
3677 /* do border along [img][row=0][col=0] */
3678 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3679 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3680 MEMCPY(dst
, src
, bpt
);
3682 /* do border along [img][row=dstHeight-1][col=0] */
3683 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3684 + (srcHeight
- 1) * bytesPerSrcRow
;
3685 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3686 + (dstHeight
- 1) * bytesPerDstRow
;
3687 MEMCPY(dst
, src
, bpt
);
3689 /* do border along [img][row=0][col=dstWidth-1] */
3690 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3691 + (srcWidth
- 1) * bpt
;
3692 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3693 + (dstWidth
- 1) * bpt
;
3694 MEMCPY(dst
, src
, bpt
);
3696 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3697 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3698 + (bytesPerSrcImage
- bpt
);
3699 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3700 + (bytesPerDstImage
- bpt
);
3701 MEMCPY(dst
, src
, bpt
);
3705 /* average border pixels from adjacent src image pairs */
3706 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3707 for (img
= 0; img
< dstDepthNB
; img
++) {
3711 /* do border along [img][row=0][col=0] */
3712 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3713 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3714 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3716 /* do border along [img][row=dstHeight-1][col=0] */
3717 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3718 + (srcHeight
- 1) * bytesPerSrcRow
;
3719 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3720 + (dstHeight
- 1) * bytesPerDstRow
;
3721 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3723 /* do border along [img][row=0][col=dstWidth-1] */
3724 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3725 + (srcWidth
- 1) * bpt
;
3726 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3727 + (dstWidth
- 1) * bpt
;
3728 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3730 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3731 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3732 + (bytesPerSrcImage
- bpt
);
3733 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3734 + (bytesPerDstImage
- bpt
);
3735 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3743 * For GL_SGIX_generate_mipmap:
3744 * Generate a complete set of mipmaps from texObj's base-level image.
3745 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3748 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3749 const struct gl_texture_unit
*texUnit
,
3750 struct gl_texture_object
*texObj
)
3752 const struct gl_texture_image
*srcImage
;
3753 const struct gl_texture_format
*convertFormat
;
3754 const GLubyte
*srcData
= NULL
;
3755 GLubyte
*dstData
= NULL
;
3756 GLint level
, maxLevels
;
3759 /* XXX choose cube map face here??? */
3760 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3763 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3764 ASSERT(maxLevels
> 0); /* bad target */
3766 /* Find convertFormat - the format that do_row() will process */
3767 if (srcImage
->IsCompressed
) {
3768 /* setup for compressed textures */
3770 GLint components
, size
;
3773 assert(texObj
->Target
== GL_TEXTURE_2D
);
3775 if (srcImage
->_BaseFormat
== GL_RGB
) {
3776 convertFormat
= &_mesa_texformat_rgb
;
3779 else if (srcImage
->_BaseFormat
== GL_RGBA
) {
3780 convertFormat
= &_mesa_texformat_rgba
;
3784 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
3788 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3789 size
= _mesa_bytes_per_pixel(srcImage
->_BaseFormat
, CHAN_TYPE
)
3790 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3791 /* 20 extra bytes, just be safe when calling last FetchTexel */
3792 srcData
= (GLubyte
*) _mesa_malloc(size
);
3794 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3797 dstData
= (GLubyte
*) _mesa_malloc(size
/ 2); /* 1/4 would probably be OK */
3799 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3800 _mesa_free((void *) srcData
);
3804 /* decompress base image here */
3805 dst
= (GLchan
*) srcData
;
3806 for (row
= 0; row
< srcImage
->Height
; row
++) {
3808 for (col
= 0; col
< srcImage
->Width
; col
++) {
3809 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3816 convertFormat
= srcImage
->TexFormat
;
3819 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3820 && level
< maxLevels
- 1; level
++) {
3821 /* generate image[level+1] from image[level] */
3822 const struct gl_texture_image
*srcImage
;
3823 struct gl_texture_image
*dstImage
;
3824 GLint srcWidth
, srcHeight
, srcDepth
;
3825 GLint dstWidth
, dstHeight
, dstDepth
;
3826 GLint border
, bytesPerTexel
;
3828 /* get src image parameters */
3829 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3831 srcWidth
= srcImage
->Width
;
3832 srcHeight
= srcImage
->Height
;
3833 srcDepth
= srcImage
->Depth
;
3834 border
= srcImage
->Border
;
3836 /* compute next (level+1) image size */
3837 if (srcWidth
- 2 * border
> 1) {
3838 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3841 dstWidth
= srcWidth
; /* can't go smaller */
3843 if (srcHeight
- 2 * border
> 1) {
3844 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3847 dstHeight
= srcHeight
; /* can't go smaller */
3849 if (srcDepth
- 2 * border
> 1) {
3850 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3853 dstDepth
= srcDepth
; /* can't go smaller */
3856 if (dstWidth
== srcWidth
&&
3857 dstHeight
== srcHeight
&&
3858 dstDepth
== srcDepth
) {
3860 if (srcImage
->IsCompressed
) {
3861 _mesa_free((void *) srcData
);
3862 _mesa_free(dstData
);
3867 /* get dest gl_texture_image */
3868 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3870 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3874 /* Free old image data */
3876 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
3878 /* initialize new image */
3879 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3880 dstDepth
, border
, srcImage
->InternalFormat
);
3881 dstImage
->DriverData
= NULL
;
3882 dstImage
->TexFormat
= srcImage
->TexFormat
;
3883 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3884 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3885 dstImage
->IsCompressed
= srcImage
->IsCompressed
;
3886 if (dstImage
->IsCompressed
) {
3887 dstImage
->CompressedSize
3888 = ctx
->Driver
.CompressedTextureSize(ctx
, dstImage
->Width
,
3891 dstImage
->TexFormat
->MesaFormat
);
3892 ASSERT(dstImage
->CompressedSize
> 0);
3895 ASSERT(dstImage
->TexFormat
);
3896 ASSERT(dstImage
->FetchTexelc
);
3897 ASSERT(dstImage
->FetchTexelf
);
3899 /* Alloc new teximage data buffer.
3900 * Setup src and dest data pointers.
3902 if (dstImage
->IsCompressed
) {
3903 dstImage
->Data
= _mesa_alloc_texmemory(dstImage
->CompressedSize
);
3904 if (!dstImage
->Data
) {
3905 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3908 /* srcData and dstData are already set */
3913 bytesPerTexel
= dstImage
->TexFormat
->TexelBytes
;
3914 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3915 dstImage
->Data
= _mesa_alloc_texmemory(dstWidth
* dstHeight
3916 * dstDepth
* bytesPerTexel
);
3917 if (!dstImage
->Data
) {
3918 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3921 srcData
= (const GLubyte
*) srcImage
->Data
;
3922 dstData
= (GLubyte
*) dstImage
->Data
;
3926 * We use simple 2x2 averaging to compute the next mipmap level.
3930 make_1d_mipmap(convertFormat
, border
,
3935 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3936 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3937 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3938 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3939 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3940 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3941 make_2d_mipmap(convertFormat
, border
,
3942 srcWidth
, srcHeight
, srcData
,
3943 dstWidth
, dstHeight
, dstData
);
3946 make_3d_mipmap(convertFormat
, border
,
3947 srcWidth
, srcHeight
, srcDepth
, srcData
,
3948 dstWidth
, dstHeight
, dstDepth
, dstData
);
3950 case GL_TEXTURE_RECTANGLE_NV
:
3951 /* no mipmaps, do nothing */
3954 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3958 if (dstImage
->IsCompressed
) {
3960 /* compress image from dstData into dstImage->Data */
3961 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3963 = _mesa_compressed_row_stride(dstImage
->TexFormat
->MesaFormat
, dstWidth
);
3964 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3965 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->_BaseFormat
,
3966 dstImage
->TexFormat
,
3968 0, 0, 0, /* dstX/Y/Zoffset */
3969 dstRowStride
, 0, /* strides */
3970 dstWidth
, dstHeight
, 1, /* size */
3971 srcFormat
, CHAN_TYPE
,
3972 dstData
, /* src data, actually */
3973 &ctx
->DefaultPacking
);
3974 /* swap src and dest pointers */
3975 temp
= (GLubyte
*) srcData
;
3980 } /* loop over mipmap levels */
3985 * Helper function for drivers which need to rescale texture images to
3986 * certain aspect ratios.
3987 * Nearest filtering only (for broken hardware that can't support
3988 * all aspect ratios). This can be made a lot faster, but I don't
3989 * really care enough...
3992 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
3993 GLuint srcStrideInPixels
,
3994 GLuint dstRowStride
,
3995 GLint srcWidth
, GLint srcHeight
,
3996 GLint dstWidth
, GLint dstHeight
,
3997 const GLvoid
*srcImage
, GLvoid
*dstImage
)
4001 #define INNER_LOOP( TYPE, HOP, WOP ) \
4002 for ( row = 0 ; row < dstHeight ; row++ ) { \
4003 GLint srcRow = row HOP hScale; \
4004 for ( col = 0 ; col < dstWidth ; col++ ) { \
4005 GLint srcCol = col WOP wScale; \
4006 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
4008 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
4011 #define RESCALE_IMAGE( TYPE ) \
4013 const TYPE *src = (const TYPE *)srcImage; \
4014 TYPE *dst = (TYPE *)dstImage; \
4016 if ( srcHeight < dstHeight ) { \
4017 const GLint hScale = dstHeight / srcHeight; \
4018 if ( srcWidth < dstWidth ) { \
4019 const GLint wScale = dstWidth / srcWidth; \
4020 INNER_LOOP( TYPE, /, / ); \
4023 const GLint wScale = srcWidth / dstWidth; \
4024 INNER_LOOP( TYPE, /, * ); \
4028 const GLint hScale = srcHeight / dstHeight; \
4029 if ( srcWidth < dstWidth ) { \
4030 const GLint wScale = dstWidth / srcWidth; \
4031 INNER_LOOP( TYPE, *, / ); \
4034 const GLint wScale = srcWidth / dstWidth; \
4035 INNER_LOOP( TYPE, *, * ); \
4040 switch ( bytesPerPixel
) {
4042 RESCALE_IMAGE( GLuint
);
4046 RESCALE_IMAGE( GLushort
);
4050 RESCALE_IMAGE( GLubyte
);
4053 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
4059 * Upscale an image by replication, not (typical) stretching.
4060 * We use this when the image width or height is less than a
4061 * certain size (4, 8) and we need to upscale an image.
4064 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
4065 GLsizei outWidth
, GLsizei outHeight
,
4066 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
4071 ASSERT(outWidth
>= inWidth
);
4072 ASSERT(outHeight
>= inHeight
);
4074 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
4075 ASSERT((outWidth
& 3) == 0);
4076 ASSERT((outHeight
& 3) == 0);
4079 for (i
= 0; i
< outHeight
; i
++) {
4080 const GLint ii
= i
% inHeight
;
4081 for (j
= 0; j
< outWidth
; j
++) {
4082 const GLint jj
= j
% inWidth
;
4083 for (k
= 0; k
< comps
; k
++) {
4084 dest
[(i
* outWidth
+ j
) * comps
+ k
]
4085 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];
4094 * This is the software fallback for Driver.GetTexImage().
4095 * All error checking will have been done before this routine is called.
4098 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4099 GLenum format
, GLenum type
, GLvoid
*pixels
,
4100 struct gl_texture_object
*texObj
,
4101 struct gl_texture_image
*texImage
)
4103 GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
4105 if (ctx
->Pack
.BufferObj
->Name
) {
4106 /* pack texture image into a PBO */
4108 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
4109 texImage
->Height
, texImage
->Depth
,
4110 format
, type
, pixels
)) {
4111 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4112 "glGetTexImage(invalid PBO access)");
4115 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4117 ctx
->Pack
.BufferObj
);
4119 /* buffer is already mapped - that's an error */
4120 _mesa_error(ctx
, GL_INVALID_OPERATION
,"glGetTexImage(PBO is mapped)");
4123 pixels
= ADD_POINTERS(buf
, pixels
);
4131 const GLint width
= texImage
->Width
;
4132 const GLint height
= texImage
->Height
;
4133 const GLint depth
= texImage
->Depth
;
4135 for (img
= 0; img
< depth
; img
++) {
4136 for (row
= 0; row
< height
; row
++) {
4137 /* compute destination address in client memory */
4138 GLvoid
*dest
= _mesa_image_address( dimensions
, &ctx
->Pack
, pixels
,
4139 width
, height
, format
, type
,
4143 if (format
== GL_COLOR_INDEX
) {
4144 GLuint indexRow
[MAX_WIDTH
];
4146 /* Can't use FetchTexel here because that returns RGBA */
4147 if (texImage
->TexFormat
->IndexBits
== 8) {
4148 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
4149 src
+= width
* (img
* texImage
->Height
+ row
);
4150 for (col
= 0; col
< width
; col
++) {
4151 indexRow
[col
] = src
[col
];
4154 else if (texImage
->TexFormat
->IndexBits
== 16) {
4155 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
4156 src
+= width
* (img
* texImage
->Height
+ row
);
4157 for (col
= 0; col
< width
; col
++) {
4158 indexRow
[col
] = src
[col
];
4163 "Color index problem in _mesa_GetTexImage");
4165 _mesa_pack_index_span(ctx
, width
, type
, dest
,
4166 indexRow
, &ctx
->Pack
,
4167 0 /* no image transfer */);
4169 else if (format
== GL_DEPTH_COMPONENT
) {
4170 GLfloat depthRow
[MAX_WIDTH
];
4172 for (col
= 0; col
< width
; col
++) {
4173 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
4176 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
4177 depthRow
, &ctx
->Pack
);
4179 else if (format
== GL_DEPTH_STENCIL_EXT
) {
4180 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4181 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
4182 src
+= width
* row
+ width
* height
* img
;
4183 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
4184 if (ctx
->Pack
.SwapBytes
) {
4185 _mesa_swap4((GLuint
*) dest
, width
);
4188 else if (format
== GL_YCBCR_MESA
) {
4189 /* No pixel transfer */
4190 const GLint rowstride
= texImage
->RowStride
;
4192 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
4193 width
* sizeof(GLushort
));
4194 /* check for byte swapping */
4195 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
4196 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
4197 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
4198 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
4199 if (!ctx
->Pack
.SwapBytes
)
4200 _mesa_swap2((GLushort
*) dest
, width
);
4202 else if (ctx
->Pack
.SwapBytes
) {
4203 _mesa_swap2((GLushort
*) dest
, width
);
4207 /* general case: convert row to RGBA format */
4208 GLfloat rgba
[MAX_WIDTH
][4];
4210 for (col
= 0; col
< width
; col
++) {
4211 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
4213 _mesa_pack_rgba_span_float(ctx
, width
,
4214 (const GLfloat (*)[4]) rgba
,
4215 format
, type
, dest
, &ctx
->Pack
,
4216 0 /* no image transfer */);
4222 if (ctx
->Pack
.BufferObj
->Name
) {
4223 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4224 ctx
->Pack
.BufferObj
);
4231 * This is the software fallback for Driver.GetCompressedTexImage().
4232 * All error checking will have been done before this routine is called.
4235 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
4237 const struct gl_texture_object
*texObj
,
4238 const struct gl_texture_image
*texImage
)
4242 if (ctx
->Pack
.BufferObj
->Name
) {
4243 /* pack texture image into a PBO */
4245 if ((const GLubyte
*) img
+ texImage
->CompressedSize
>
4246 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
4247 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4248 "glGetCompressedTexImage(invalid PBO access)");
4251 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4253 ctx
->Pack
.BufferObj
);
4255 /* buffer is already mapped - that's an error */
4256 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4257 "glGetCompressedTexImage(PBO is mapped)");
4260 img
= ADD_POINTERS(buf
, img
);
4267 /* don't use texImage->CompressedSize since that may be padded out */
4268 size
= _mesa_compressed_texture_size(ctx
, texImage
->Width
, texImage
->Height
,
4270 texImage
->TexFormat
->MesaFormat
);
4272 /* just memcpy, no pixelstore or pixel transfer */
4273 _mesa_memcpy(img
, texImage
->Data
, size
);
4275 if (ctx
->Pack
.BufferObj
->Name
) {
4276 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
4277 ctx
->Pack
.BufferObj
);