2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
62 #include "texcompress.h"
63 #include "texformat.h"
68 static const GLint ZERO
= 1000, ONE
= 1001;
71 * When promoting texture formats (see below) we need to compute the
72 * mapping of dest components back to source components.
73 * This function does that.
74 * \param logicalBaseFormat the logical format of the texture
75 * \param textureBaseFormat the final texture format
76 * \return map[4] the four mapping values
79 compute_component_mapping(GLenum logicalBaseFormat
, GLenum textureBaseFormat
,
82 /* compute mapping from dest components back to src components */
83 switch (textureBaseFormat
) {
86 switch (logicalBaseFormat
) {
88 map
[0] = map
[1] = map
[2] = 0;
89 if (textureBaseFormat
== GL_RGBA
)
93 ASSERT(textureBaseFormat
== GL_RGBA
);
94 map
[0] = map
[1] = map
[2] = ZERO
;
98 map
[0] = map
[1] = map
[2] = 0;
99 if (textureBaseFormat
== GL_RGBA
)
102 case GL_LUMINANCE_ALPHA
:
103 ASSERT(textureBaseFormat
== GL_RGBA
);
104 map
[0] = map
[1] = map
[2] = 0;
108 ASSERT(textureBaseFormat
== GL_RGBA
);
115 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
116 map
[0] = map
[1] = map
[2] = map
[3] = 0;
119 case GL_LUMINANCE_ALPHA
:
120 switch (logicalBaseFormat
) {
134 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
142 * Make a temporary (color) texture image with GLfloat components.
143 * Apply all needed pixel unpacking and pixel transfer operations.
144 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
145 * Suppose the user specifies GL_LUMINANCE as the internal texture format
146 * but the graphics hardware doesn't support luminance textures. So, might
147 * use an RGB hardware format instead.
148 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
150 * \param ctx the rendering context
151 * \param dims image dimensions: 1, 2 or 3
152 * \param logicalBaseFormat basic texture derived from the user's
153 * internal texture format value
154 * \param textureBaseFormat the actual basic format of the texture
155 * \param srcWidth source image width
156 * \param srcHeight source image height
157 * \param srcDepth source image depth
158 * \param srcFormat source image format
159 * \param srcType source image type
160 * \param srcAddr source image address
161 * \param srcPacking source image pixel packing
162 * \return resulting image with format = textureBaseFormat and type = GLfloat.
165 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
166 GLenum logicalBaseFormat
,
167 GLenum textureBaseFormat
,
168 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
169 GLenum srcFormat
, GLenum srcType
,
170 const GLvoid
*srcAddr
,
171 const struct gl_pixelstore_attrib
*srcPacking
)
173 GLuint transferOps
= ctx
->_ImageTransferState
;
176 ASSERT(dims
>= 1 && dims
<= 3);
178 ASSERT(logicalBaseFormat
== GL_RGBA
||
179 logicalBaseFormat
== GL_RGB
||
180 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
181 logicalBaseFormat
== GL_LUMINANCE
||
182 logicalBaseFormat
== GL_ALPHA
||
183 logicalBaseFormat
== GL_INTENSITY
||
184 logicalBaseFormat
== GL_COLOR_INDEX
||
185 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
187 ASSERT(textureBaseFormat
== GL_RGBA
||
188 textureBaseFormat
== GL_RGB
||
189 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
190 textureBaseFormat
== GL_LUMINANCE
||
191 textureBaseFormat
== GL_ALPHA
||
192 textureBaseFormat
== GL_INTENSITY
||
193 textureBaseFormat
== GL_COLOR_INDEX
||
194 textureBaseFormat
== GL_DEPTH_COMPONENT
);
196 /* conventional color image */
198 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
199 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
200 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
201 /* need image convolution */
202 const GLuint preConvTransferOps
203 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
204 const GLuint postConvTransferOps
205 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
207 GLint convWidth
, convHeight
;
210 /* pre-convolution image buffer (3D) */
211 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
212 * 4 * sizeof(GLfloat
));
216 /* post-convolution image buffer (2D) */
217 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
218 * 4 * sizeof(GLfloat
));
220 _mesa_free(tempImage
);
224 /* loop over 3D image slices */
225 for (img
= 0; img
< srcDepth
; img
++) {
226 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
228 /* unpack and do transfer ops up to convolution */
229 for (row
= 0; row
< srcHeight
; row
++) {
230 const GLvoid
*src
= _mesa_image_address(srcPacking
,
231 srcAddr
, srcWidth
, srcHeight
,
232 srcFormat
, srcType
, img
, row
, 0);
233 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
234 srcFormat
, srcType
, src
,
242 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
243 convWidth
= srcWidth
;
244 convHeight
= srcHeight
;
246 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
247 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
250 if (ctx
->Pixel
.Convolution2DEnabled
) {
251 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
255 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
256 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
262 /* do post-convolution transfer and pack into tempImage */
264 const GLint logComponents
265 = _mesa_components_in_format(logicalBaseFormat
);
266 const GLfloat
*src
= convImage
;
267 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
268 for (row
= 0; row
< convHeight
; row
++) {
269 _mesa_pack_rgba_span_float(ctx
, convWidth
,
270 (const GLfloat (*)[4]) src
,
271 logicalBaseFormat
, GL_FLOAT
,
272 dst
, &ctx
->DefaultPacking
,
273 postConvTransferOps
);
274 src
+= convWidth
* 4;
275 dst
+= convWidth
* logComponents
;
278 } /* loop over 3D image slices */
280 _mesa_free(convImage
);
282 /* might need these below */
283 srcWidth
= convWidth
;
284 srcHeight
= convHeight
;
288 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
289 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
290 srcWidth
, srcFormat
, srcType
);
294 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
295 * components
* sizeof(GLfloat
));
300 for (img
= 0; img
< srcDepth
; img
++) {
302 = (const GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
306 for (row
= 0; row
< srcHeight
; row
++) {
307 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
308 dst
, srcFormat
, srcType
, src
,
309 srcPacking
, transferOps
);
310 dst
+= srcWidth
* components
;
316 if (logicalBaseFormat
!= textureBaseFormat
) {
318 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
319 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
324 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
325 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
326 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
328 /* The actual texture format should have at least as many components
329 * as the logical texture format.
331 ASSERT(texComponents
>= logComponents
);
333 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
334 * texComponents
* sizeof(GLfloat
));
336 _mesa_free(tempImage
);
340 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
342 n
= srcWidth
* srcHeight
* srcDepth
;
343 for (i
= 0; i
< n
; i
++) {
345 for (k
= 0; k
< texComponents
; k
++) {
348 newImage
[i
* texComponents
+ k
] = 0.0F
;
350 newImage
[i
* texComponents
+ k
] = 1.0F
;
352 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
356 _mesa_free(tempImage
);
357 tempImage
= newImage
;
365 * Make a temporary (color) texture image with GLchan components.
366 * Apply all needed pixel unpacking and pixel transfer operations.
367 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
368 * Suppose the user specifies GL_LUMINANCE as the internal texture format
369 * but the graphics hardware doesn't support luminance textures. So, might
370 * use an RGB hardware format instead.
371 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
373 * \param ctx the rendering context
374 * \param dims image dimensions: 1, 2 or 3
375 * \param logicalBaseFormat basic texture derived from the user's
376 * internal texture format value
377 * \param textureBaseFormat the actual basic format of the texture
378 * \param srcWidth source image width
379 * \param srcHeight source image height
380 * \param srcDepth source image depth
381 * \param srcFormat source image format
382 * \param srcType source image type
383 * \param srcAddr source image address
384 * \param srcPacking source image pixel packing
385 * \return resulting image with format = textureBaseFormat and type = GLchan.
388 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
389 GLenum logicalBaseFormat
,
390 GLenum textureBaseFormat
,
391 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
392 GLenum srcFormat
, GLenum srcType
,
393 const GLvoid
*srcAddr
,
394 const struct gl_pixelstore_attrib
*srcPacking
)
396 GLuint transferOps
= ctx
->_ImageTransferState
;
397 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
398 GLboolean freeSrcImage
= GL_FALSE
;
400 GLchan
*tempImage
, *dst
;
402 ASSERT(dims
>= 1 && dims
<= 3);
404 ASSERT(logicalBaseFormat
== GL_RGBA
||
405 logicalBaseFormat
== GL_RGB
||
406 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
407 logicalBaseFormat
== GL_LUMINANCE
||
408 logicalBaseFormat
== GL_ALPHA
||
409 logicalBaseFormat
== GL_INTENSITY
);
411 ASSERT(textureBaseFormat
== GL_RGBA
||
412 textureBaseFormat
== GL_RGB
||
413 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
414 textureBaseFormat
== GL_LUMINANCE
||
415 textureBaseFormat
== GL_ALPHA
||
416 textureBaseFormat
== GL_INTENSITY
);
418 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
419 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
420 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
421 /* get convolved image */
422 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
425 srcWidth
, srcHeight
, srcDepth
,
427 srcAddr
, srcPacking
);
430 /* the convolved image is our new source image */
432 srcFormat
= logicalBaseFormat
;
434 srcPacking
= &ctx
->DefaultPacking
;
435 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
437 freeSrcImage
= GL_TRUE
;
440 /* unpack and transfer the source image */
441 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
442 * components
* sizeof(GLchan
));
447 for (img
= 0; img
< srcDepth
; img
++) {
448 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
452 = (const GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
456 for (row
= 0; row
< srcHeight
; row
++) {
457 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
458 srcFormat
, srcType
, src
, srcPacking
,
460 dst
+= srcWidth
* components
;
465 /* If we made a temporary image for convolution, free it here */
467 _mesa_free((void *) srcAddr
);
470 if (logicalBaseFormat
!= textureBaseFormat
) {
471 /* one more conversion step */
472 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
473 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
478 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
479 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
||
480 textureBaseFormat
== GL_LUMINANCE_ALPHA
);
482 /* The actual texture format should have at least as many components
483 * as the logical texture format.
485 ASSERT(texComponents
>= logComponents
);
487 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
488 * texComponents
* sizeof(GLchan
));
490 _mesa_free(tempImage
);
494 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
496 n
= srcWidth
* srcHeight
* srcDepth
;
497 for (i
= 0; i
< n
; i
++) {
499 for (k
= 0; k
< texComponents
; k
++) {
502 newImage
[i
* texComponents
+ k
] = 0;
504 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
506 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
510 _mesa_free(tempImage
);
511 tempImage
= newImage
;
520 * Teximage storage routine for when a simple memcpy will do.
521 * No pixel transfer operations or special texel encodings allowed.
522 * 1D, 2D and 3D images supported.
525 memcpy_texture(const struct gl_texture_format
*dstFormat
,
527 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
528 GLint dstRowStride
, GLint dstImageStride
,
529 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
530 GLenum srcFormat
, GLenum srcType
,
531 const GLvoid
*srcAddr
,
532 const struct gl_pixelstore_attrib
*srcPacking
)
534 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
536 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
537 srcWidth
, srcHeight
, srcFormat
, srcType
);
538 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(srcPacking
,
539 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
540 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
541 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
542 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
543 GLubyte
*dstImage
= (GLubyte
*) dstAddr
544 + dstZoffset
* dstImageStride
545 + dstYoffset
* dstRowStride
546 + dstXoffset
* dstFormat
->TexelBytes
;
548 if (dstRowStride
== srcRowStride
&&
549 dstRowStride
== bytesPerRow
&&
550 ((dstImageStride
== srcImageStride
&&
551 dstImageStride
== bytesPerImage
) ||
554 _mesa_memcpy(dstImage
, srcImage
, bytesPerTexture
);
558 for (img
= 0; img
< srcDepth
; img
++) {
559 const GLubyte
*srcRow
= srcImage
;
560 GLubyte
*dstRow
= dstImage
;
561 for (row
= 0; row
< srcHeight
; row
++) {
562 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
563 dstRow
+= dstRowStride
;
564 srcRow
+= srcRowStride
;
566 srcImage
+= srcImageStride
;
567 dstImage
+= dstImageStride
;
575 * Store an image in any of the formats:
576 * _mesa_texformat_rgba
577 * _mesa_texformat_rgb
578 * _mesa_texformat_alpha
579 * _mesa_texformat_luminance
580 * _mesa_texformat_luminance_alpha
581 * _mesa_texformat_intensity
583 * \param dims either 1 or 2 or 3
584 * \param baseInternalFormat user-specified base internal format
585 * \param dstFormat destination Mesa texture format
586 * \param dstAddr destination image address
587 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
588 * \param dstRowStride destination image row stride, in bytes
589 * \param dstImageStride destination image layer stride, in bytes
590 * \param srcWidth/Height/Depth source image size, in pixels
591 * \param srcFormat incoming image format
592 * \param srcType incoming image data type
593 * \param srcAddr source image address
594 * \param srcPacking source image packing parameters
597 _mesa_texstore_rgba(GLcontext
*ctx
, GLuint dims
,
598 GLenum baseInternalFormat
,
599 const struct gl_texture_format
*dstFormat
,
601 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
602 GLint dstRowStride
, GLint dstImageStride
,
603 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
604 GLenum srcFormat
, GLenum srcType
,
605 const GLvoid
*srcAddr
,
606 const struct gl_pixelstore_attrib
*srcPacking
)
608 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
610 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
611 dstFormat
== &_mesa_texformat_rgb
||
612 dstFormat
== &_mesa_texformat_alpha
||
613 dstFormat
== &_mesa_texformat_luminance
||
614 dstFormat
== &_mesa_texformat_luminance_alpha
||
615 dstFormat
== &_mesa_texformat_intensity
);
616 ASSERT(baseInternalFormat
== GL_RGBA
||
617 baseInternalFormat
== GL_RGB
||
618 baseInternalFormat
== GL_ALPHA
||
619 baseInternalFormat
== GL_LUMINANCE
||
620 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
621 baseInternalFormat
== GL_INTENSITY
);
622 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
624 if (!ctx
->_ImageTransferState
&&
625 !srcPacking
->SwapBytes
&&
626 baseInternalFormat
== srcFormat
&&
627 srcType
== CHAN_TYPE
) {
628 /* simple memcpy path */
629 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
630 dstRowStride
, dstImageStride
,
631 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
632 srcAddr
, srcPacking
);
634 else if (!ctx
->_ImageTransferState
&&
635 !srcPacking
->SwapBytes
&&
636 dstFormat
== &_mesa_texformat_rgb
&&
637 srcFormat
== GL_RGBA
&&
638 srcType
== CHAN_TYPE
) {
639 /* extract RGB from RGBA */
641 GLchan
*dstImage
= (GLchan
*) (GLubyte
*) dstAddr
642 + dstZoffset
* dstImageStride
643 + dstYoffset
* dstRowStride
644 + dstXoffset
* dstFormat
->TexelBytes
;
645 for (img
= 0; img
< srcDepth
; img
++) {
646 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
647 srcWidth
, srcFormat
, srcType
);
648 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(srcPacking
, srcAddr
,
649 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
650 GLchan
*dstRow
= dstImage
;
651 for (row
= 0; row
< srcHeight
; row
++) {
652 for (col
= 0; col
< srcWidth
; col
++) {
653 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
654 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
655 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
657 dstRow
+= dstRowStride
;
658 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
660 dstImage
+= dstImageStride
;
665 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
667 dstFormat
->BaseFormat
,
668 srcWidth
, srcHeight
, srcDepth
,
669 srcFormat
, srcType
, srcAddr
,
671 const GLchan
*src
= tempImage
;
673 GLubyte
*dstImage
= (GLubyte
*) dstAddr
674 + dstZoffset
* dstImageStride
675 + dstYoffset
* dstRowStride
676 + dstXoffset
* dstFormat
->TexelBytes
;
680 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
681 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
682 for (img
= 0; img
< srcDepth
; img
++) {
683 GLubyte
*dstRow
= dstImage
;
684 for (row
= 0; row
< srcHeight
; row
++) {
685 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
686 dstRow
+= dstRowStride
;
687 src
+= srcWidth
* components
;
689 dstImage
+= dstImageStride
;
692 _mesa_free((void *) tempImage
);
699 * Store a floating point depth component texture image.
702 _mesa_texstore_depth_component_float32(STORE_PARAMS
)
704 ASSERT(dstFormat
== &_mesa_texformat_depth_component_float32
);
705 ASSERT(dstFormat
->TexelBytes
== sizeof(GLfloat
));
707 if (!ctx
->_ImageTransferState
&&
708 !srcPacking
->SwapBytes
&&
709 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
710 srcFormat
== GL_DEPTH_COMPONENT
&&
711 srcType
== GL_FLOAT
) {
712 /* simple memcpy path */
713 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
714 dstRowStride
, dstImageStride
,
715 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
716 srcAddr
, srcPacking
);
720 GLubyte
*dstImage
= (GLubyte
*) dstAddr
721 + dstZoffset
* dstImageStride
722 + dstYoffset
* dstRowStride
723 + dstXoffset
* dstFormat
->TexelBytes
;
725 for (img
= 0; img
< srcDepth
; img
++) {
726 GLubyte
*dstRow
= dstImage
;
727 for (row
= 0; row
< srcHeight
; row
++) {
728 const GLvoid
*src
= _mesa_image_address(srcPacking
,
729 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
730 _mesa_unpack_depth_span(ctx
, srcWidth
, (GLfloat
*) dstRow
,
731 srcType
, src
, srcPacking
);
732 dstRow
+= dstRowStride
;
734 dstImage
+= dstImageStride
;
742 * Store a 16-bit integer depth component texture image.
745 _mesa_texstore_depth_component16(STORE_PARAMS
)
747 ASSERT(dstFormat
== &_mesa_texformat_depth_component16
);
748 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
750 if (!ctx
->_ImageTransferState
&&
751 !srcPacking
->SwapBytes
&&
752 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
753 srcFormat
== GL_DEPTH_COMPONENT
&&
754 srcType
== GL_UNSIGNED_SHORT
) {
755 /* simple memcpy path */
756 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
757 dstRowStride
, dstImageStride
,
758 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
759 srcAddr
, srcPacking
);
763 GLubyte
*dstImage
= (GLubyte
*) dstAddr
764 + dstZoffset
* dstImageStride
765 + dstYoffset
* dstRowStride
766 + dstXoffset
* dstFormat
->TexelBytes
;
768 for (img
= 0; img
< srcDepth
; img
++) {
769 GLubyte
*dstRow
= dstImage
;
770 for (row
= 0; row
< srcHeight
; row
++) {
771 GLfloat depthTemp
[MAX_WIDTH
];
772 const GLvoid
*src
= _mesa_image_address(srcPacking
,
773 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
774 GLushort
*dst16
= (GLushort
*) dstRow
;
775 _mesa_unpack_depth_span(ctx
, srcWidth
, depthTemp
,
776 srcType
, src
, srcPacking
);
777 for (col
= 0; col
< srcWidth
; col
++) {
778 dst16
[col
] = (GLushort
) (depthTemp
[col
] * 65535.0F
);
780 dstRow
+= dstRowStride
;
782 dstImage
+= dstImageStride
;
790 * Store an rgb565 or rgb565_rev texture image.
793 _mesa_texstore_rgb565(STORE_PARAMS
)
795 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
796 dstFormat
== &_mesa_texformat_rgb565_rev
);
797 ASSERT(dstFormat
->TexelBytes
== 2);
799 if (!ctx
->_ImageTransferState
&&
800 !srcPacking
->SwapBytes
&&
801 dstFormat
== &_mesa_texformat_rgb565
&&
802 baseInternalFormat
== GL_RGB
&&
803 srcFormat
== GL_RGB
&&
804 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
805 /* simple memcpy path */
806 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
807 dstRowStride
, dstImageStride
,
808 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
809 srcAddr
, srcPacking
);
811 else if (!ctx
->_ImageTransferState
&&
812 !srcPacking
->SwapBytes
&&
813 baseInternalFormat
== GL_RGB
&&
814 srcFormat
== GL_RGB
&&
815 srcType
== GL_UNSIGNED_BYTE
&&
817 /* do optimized tex store */
818 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
820 const GLubyte
*src
= (const GLubyte
*)
821 _mesa_image_address(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
822 srcFormat
, srcType
, 0, 0, 0);
823 GLubyte
*dst
= (GLubyte
*) dstAddr
824 + dstZoffset
* dstImageStride
825 + dstYoffset
* dstRowStride
826 + dstXoffset
* dstFormat
->TexelBytes
;
828 for (row
= 0; row
< srcHeight
; row
++) {
829 const GLubyte
*srcUB
= (const GLubyte
*) src
;
830 GLushort
*dstUS
= (GLushort
*) dst
;
831 /* check for byteswapped format */
832 if (dstFormat
== &_mesa_texformat_rgb565
) {
833 for (col
= 0; col
< srcWidth
; col
++) {
834 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
839 for (col
= 0; col
< srcWidth
; col
++) {
840 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
850 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
852 dstFormat
->BaseFormat
,
853 srcWidth
, srcHeight
, srcDepth
,
854 srcFormat
, srcType
, srcAddr
,
856 const GLchan
*src
= tempImage
;
857 GLubyte
*dstImage
= (GLubyte
*) dstAddr
858 + dstZoffset
* dstImageStride
859 + dstYoffset
* dstRowStride
860 + dstXoffset
* dstFormat
->TexelBytes
;
864 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
865 for (img
= 0; img
< srcDepth
; img
++) {
866 GLubyte
*dstRow
= dstImage
;
867 for (row
= 0; row
< srcHeight
; row
++) {
868 GLushort
*dstUS
= (GLushort
*) dstRow
;
869 /* check for byteswapped format */
870 if (dstFormat
== &_mesa_texformat_rgb565
) {
871 for (col
= 0; col
< srcWidth
; col
++) {
872 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
873 CHAN_TO_UBYTE(src
[GCOMP
]),
874 CHAN_TO_UBYTE(src
[BCOMP
]) );
879 for (col
= 0; col
< srcWidth
; col
++) {
880 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
881 CHAN_TO_UBYTE(src
[GCOMP
]),
882 CHAN_TO_UBYTE(src
[BCOMP
]) );
886 dstRow
+= dstRowStride
;
888 dstImage
+= dstImageStride
;
890 _mesa_free((void *) tempImage
);
897 _mesa_texstore_rgba8888(STORE_PARAMS
)
899 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
900 dstFormat
== &_mesa_texformat_rgba8888_rev
);
901 ASSERT(dstFormat
->TexelBytes
== 4);
903 if (!ctx
->_ImageTransferState
&&
904 !srcPacking
->SwapBytes
&&
905 dstFormat
== &_mesa_texformat_rgba8888
&&
906 baseInternalFormat
== GL_RGBA
&&
907 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
908 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
909 /* simple memcpy path */
910 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
911 dstRowStride
, dstImageStride
,
912 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
913 srcAddr
, srcPacking
);
917 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
919 dstFormat
->BaseFormat
,
920 srcWidth
, srcHeight
, srcDepth
,
921 srcFormat
, srcType
, srcAddr
,
923 const GLchan
*src
= tempImage
;
924 GLubyte
*dstImage
= (GLubyte
*) dstAddr
925 + dstZoffset
* dstImageStride
926 + dstYoffset
* dstRowStride
927 + dstXoffset
* dstFormat
->TexelBytes
;
931 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
932 for (img
= 0; img
< srcDepth
; img
++) {
933 GLubyte
*dstRow
= dstImage
;
934 for (row
= 0; row
< srcHeight
; row
++) {
935 GLuint
*dstUI
= (GLuint
*) dstRow
;
936 if (dstFormat
== &_mesa_texformat_rgba8888
) {
937 for (col
= 0; col
< srcWidth
; col
++) {
938 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
939 CHAN_TO_UBYTE(src
[GCOMP
]),
940 CHAN_TO_UBYTE(src
[BCOMP
]),
941 CHAN_TO_UBYTE(src
[ACOMP
]) );
946 for (col
= 0; col
< srcWidth
; col
++) {
947 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
948 CHAN_TO_UBYTE(src
[GCOMP
]),
949 CHAN_TO_UBYTE(src
[BCOMP
]),
950 CHAN_TO_UBYTE(src
[ACOMP
]) );
954 dstRow
+= dstRowStride
;
956 dstImage
+= dstImageStride
;
958 _mesa_free((void *) tempImage
);
965 _mesa_texstore_argb8888(STORE_PARAMS
)
968 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
970 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
971 dstFormat
== &_mesa_texformat_argb8888_rev
);
972 ASSERT(dstFormat
->TexelBytes
== 4);
974 if (!ctx
->_ImageTransferState
&&
975 !srcPacking
->SwapBytes
&&
976 dstFormat
== &_mesa_texformat_argb8888
&&
977 baseInternalFormat
== GL_RGBA
&&
978 srcFormat
== GL_BGRA
&&
979 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
980 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
981 /* simple memcpy path (little endian) */
982 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
983 dstRowStride
, dstImageStride
,
984 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
985 srcAddr
, srcPacking
);
987 else if (!ctx
->_ImageTransferState
&&
988 !srcPacking
->SwapBytes
&&
989 dstFormat
== &_mesa_texformat_argb8888_rev
&&
990 baseInternalFormat
== GL_RGBA
&&
991 srcFormat
== GL_BGRA
&&
992 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
993 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
994 /* simple memcpy path (big endian) */
995 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
996 dstRowStride
, dstImageStride
,
997 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
998 srcAddr
, srcPacking
);
1002 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1004 dstFormat
->BaseFormat
,
1005 srcWidth
, srcHeight
, srcDepth
,
1006 srcFormat
, srcType
, srcAddr
,
1008 const GLchan
*src
= tempImage
;
1009 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1010 + dstZoffset
* dstImageStride
1011 + dstYoffset
* dstRowStride
1012 + dstXoffset
* dstFormat
->TexelBytes
;
1013 GLint img
, row
, col
;
1016 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1017 for (img
= 0; img
< srcDepth
; img
++) {
1018 GLubyte
*dstRow
= dstImage
;
1019 for (row
= 0; row
< srcHeight
; row
++) {
1020 GLuint
*dstUI
= (GLuint
*) dstRow
;
1021 if (dstFormat
== &_mesa_texformat_argb8888
) {
1022 for (col
= 0; col
< srcWidth
; col
++) {
1023 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1024 CHAN_TO_UBYTE(src
[RCOMP
]),
1025 CHAN_TO_UBYTE(src
[GCOMP
]),
1026 CHAN_TO_UBYTE(src
[BCOMP
]) );
1031 for (col
= 0; col
< srcWidth
; col
++) {
1032 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1033 CHAN_TO_UBYTE(src
[RCOMP
]),
1034 CHAN_TO_UBYTE(src
[GCOMP
]),
1035 CHAN_TO_UBYTE(src
[BCOMP
]) );
1039 dstRow
+= dstRowStride
;
1041 dstImage
+= dstImageStride
;
1043 _mesa_free((void *) tempImage
);
1050 _mesa_texstore_rgb888(STORE_PARAMS
)
1052 const GLuint ui
= 1;
1053 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1055 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1056 ASSERT(dstFormat
->TexelBytes
== 3);
1058 if (!ctx
->_ImageTransferState
&&
1059 !srcPacking
->SwapBytes
&&
1060 baseInternalFormat
== GL_RGB
&&
1061 srcFormat
== GL_BGR
&&
1062 srcType
== GL_UNSIGNED_BYTE
&&
1064 /* simple memcpy path */
1065 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1066 dstRowStride
, dstImageStride
,
1067 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1068 srcAddr
, srcPacking
);
1070 else if (!ctx
->_ImageTransferState
&&
1071 !srcPacking
->SwapBytes
&&
1072 srcFormat
== GL_RGBA
&&
1073 srcType
== GL_UNSIGNED_BYTE
) {
1074 /* extract RGB from RGBA */
1076 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1077 + dstZoffset
* dstImageStride
1078 + dstYoffset
* dstRowStride
1079 + dstXoffset
* dstFormat
->TexelBytes
;
1080 for (img
= 0; img
< srcDepth
; img
++) {
1081 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1082 srcWidth
, srcFormat
, srcType
);
1083 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
1084 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1085 GLubyte
*dstRow
= dstImage
;
1086 for (row
= 0; row
< srcHeight
; row
++) {
1087 for (col
= 0; col
< srcWidth
; col
++) {
1088 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1089 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1090 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1092 dstRow
+= dstRowStride
;
1093 srcRow
+= srcRowStride
;
1095 dstImage
+= dstImageStride
;
1100 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1102 dstFormat
->BaseFormat
,
1103 srcWidth
, srcHeight
, srcDepth
,
1104 srcFormat
, srcType
, srcAddr
,
1106 const GLchan
*src
= (const GLubyte
*) tempImage
;
1107 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1108 + dstZoffset
* dstImageStride
1109 + dstYoffset
* dstRowStride
1110 + dstXoffset
* dstFormat
->TexelBytes
;
1111 GLint img
, row
, col
;
1114 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1115 for (img
= 0; img
< srcDepth
; img
++) {
1116 GLubyte
*dstRow
= dstImage
;
1117 for (row
= 0; row
< srcHeight
; row
++) {
1120 for (col
= 0; col
< srcWidth
; col
++) {
1121 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1122 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1123 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1128 for (col
= 0; col
< srcWidth
; col
++) {
1129 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1130 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1131 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1136 for (col
= 0; col
< srcWidth
; col
++) {
1137 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1138 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1139 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1143 dstRow
+= dstRowStride
;
1145 dstImage
+= dstImageStride
;
1147 _mesa_free((void *) tempImage
);
1154 _mesa_texstore_bgr888(STORE_PARAMS
)
1156 const GLuint ui
= 1;
1157 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1159 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1160 ASSERT(dstFormat
->TexelBytes
== 3);
1162 if (!ctx
->_ImageTransferState
&&
1163 !srcPacking
->SwapBytes
&&
1164 baseInternalFormat
== GL_RGB
&&
1165 srcFormat
== GL_RGB
&&
1166 srcType
== GL_UNSIGNED_BYTE
&&
1168 /* simple memcpy path */
1169 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1170 dstRowStride
, dstImageStride
,
1171 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1172 srcAddr
, srcPacking
);
1174 else if (!ctx
->_ImageTransferState
&&
1175 !srcPacking
->SwapBytes
&&
1176 srcFormat
== GL_RGBA
&&
1177 srcType
== GL_UNSIGNED_BYTE
) {
1178 /* extract BGR from RGBA */
1180 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1181 + dstZoffset
* dstImageStride
1182 + dstYoffset
* dstRowStride
1183 + dstXoffset
* dstFormat
->TexelBytes
;
1184 for (img
= 0; img
< srcDepth
; img
++) {
1185 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1186 srcWidth
, srcFormat
, srcType
);
1187 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
1188 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1189 GLubyte
*dstRow
= dstImage
;
1190 for (row
= 0; row
< srcHeight
; row
++) {
1191 for (col
= 0; col
< srcWidth
; col
++) {
1192 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1193 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1194 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1196 dstRow
+= dstRowStride
;
1197 srcRow
+= srcRowStride
;
1199 dstImage
+= dstImageStride
;
1204 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1206 dstFormat
->BaseFormat
,
1207 srcWidth
, srcHeight
, srcDepth
,
1208 srcFormat
, srcType
, srcAddr
,
1210 const GLchan
*src
= (const GLubyte
*) tempImage
;
1211 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1212 + dstZoffset
* dstImageStride
1213 + dstYoffset
* dstRowStride
1214 + dstXoffset
* dstFormat
->TexelBytes
;
1215 GLint img
, row
, col
;
1218 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1219 for (img
= 0; img
< srcDepth
; img
++) {
1220 GLubyte
*dstRow
= dstImage
;
1221 for (row
= 0; row
< srcHeight
; row
++) {
1222 for (col
= 0; col
< srcWidth
; col
++) {
1223 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1224 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1225 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1228 dstRow
+= dstRowStride
;
1230 dstImage
+= dstImageStride
;
1232 _mesa_free((void *) tempImage
);
1239 _mesa_texstore_argb4444(STORE_PARAMS
)
1241 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1242 dstFormat
== &_mesa_texformat_argb4444_rev
);
1243 ASSERT(dstFormat
->TexelBytes
== 2);
1245 if (!ctx
->_ImageTransferState
&&
1246 !srcPacking
->SwapBytes
&&
1247 dstFormat
== &_mesa_texformat_argb4444
&&
1248 baseInternalFormat
== GL_RGBA
&&
1249 srcFormat
== GL_BGRA
&&
1250 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1251 /* simple memcpy path */
1252 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1253 dstRowStride
, dstImageStride
,
1254 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1255 srcAddr
, srcPacking
);
1259 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1261 dstFormat
->BaseFormat
,
1262 srcWidth
, srcHeight
, srcDepth
,
1263 srcFormat
, srcType
, srcAddr
,
1265 const GLchan
*src
= tempImage
;
1266 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1267 + dstZoffset
* dstImageStride
1268 + dstYoffset
* dstRowStride
1269 + dstXoffset
* dstFormat
->TexelBytes
;
1270 GLint img
, row
, col
;
1273 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1274 for (img
= 0; img
< srcDepth
; img
++) {
1275 GLubyte
*dstRow
= dstImage
;
1276 for (row
= 0; row
< srcHeight
; row
++) {
1277 GLushort
*dstUS
= (GLushort
*) dstRow
;
1278 if (dstFormat
== &_mesa_texformat_argb4444
) {
1279 for (col
= 0; col
< srcWidth
; col
++) {
1280 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1281 CHAN_TO_UBYTE(src
[RCOMP
]),
1282 CHAN_TO_UBYTE(src
[GCOMP
]),
1283 CHAN_TO_UBYTE(src
[BCOMP
]) );
1288 for (col
= 0; col
< srcWidth
; col
++) {
1289 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1290 CHAN_TO_UBYTE(src
[RCOMP
]),
1291 CHAN_TO_UBYTE(src
[GCOMP
]),
1292 CHAN_TO_UBYTE(src
[BCOMP
]) );
1296 dstRow
+= dstRowStride
;
1298 dstImage
+= dstImageStride
;
1300 _mesa_free((void *) tempImage
);
1308 _mesa_texstore_argb1555(STORE_PARAMS
)
1310 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1311 dstFormat
== &_mesa_texformat_argb1555_rev
);
1312 ASSERT(dstFormat
->TexelBytes
== 2);
1314 if (!ctx
->_ImageTransferState
&&
1315 !srcPacking
->SwapBytes
&&
1316 dstFormat
== &_mesa_texformat_argb1555
&&
1317 baseInternalFormat
== GL_RGBA
&&
1318 srcFormat
== GL_BGRA
&&
1319 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1320 /* simple memcpy path */
1321 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1322 dstRowStride
, dstImageStride
,
1323 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1324 srcAddr
, srcPacking
);
1328 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1330 dstFormat
->BaseFormat
,
1331 srcWidth
, srcHeight
, srcDepth
,
1332 srcFormat
, srcType
, srcAddr
,
1334 const GLchan
*src
=tempImage
;
1335 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1336 + dstZoffset
* dstImageStride
1337 + dstYoffset
* dstRowStride
1338 + dstXoffset
* dstFormat
->TexelBytes
;
1339 GLint img
, row
, col
;
1342 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1343 for (img
= 0; img
< srcDepth
; img
++) {
1344 GLubyte
*dstRow
= dstImage
;
1345 for (row
= 0; row
< srcHeight
; row
++) {
1346 GLushort
*dstUS
= (GLushort
*) dstRow
;
1347 if (dstFormat
== &_mesa_texformat_argb1555
) {
1348 for (col
= 0; col
< srcWidth
; col
++) {
1349 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1350 CHAN_TO_UBYTE(src
[RCOMP
]),
1351 CHAN_TO_UBYTE(src
[GCOMP
]),
1352 CHAN_TO_UBYTE(src
[BCOMP
]) );
1357 for (col
= 0; col
< srcWidth
; col
++) {
1358 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1359 CHAN_TO_UBYTE(src
[RCOMP
]),
1360 CHAN_TO_UBYTE(src
[GCOMP
]),
1361 CHAN_TO_UBYTE(src
[BCOMP
]) );
1365 dstRow
+= dstRowStride
;
1367 dstImage
+= dstImageStride
;
1369 _mesa_free((void *) tempImage
);
1376 _mesa_texstore_al88(STORE_PARAMS
)
1378 const GLuint ui
= 1;
1379 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1381 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1382 dstFormat
== &_mesa_texformat_al88_rev
);
1383 ASSERT(dstFormat
->TexelBytes
== 2);
1385 if (!ctx
->_ImageTransferState
&&
1386 !srcPacking
->SwapBytes
&&
1387 dstFormat
== &_mesa_texformat_al88
&&
1388 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1389 srcFormat
== GL_LUMINANCE_ALPHA
&&
1390 srcType
== GL_UNSIGNED_BYTE
&&
1392 /* simple memcpy path */
1393 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1394 dstRowStride
, dstImageStride
,
1395 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1396 srcAddr
, srcPacking
);
1400 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1402 dstFormat
->BaseFormat
,
1403 srcWidth
, srcHeight
, srcDepth
,
1404 srcFormat
, srcType
, srcAddr
,
1406 const GLchan
*src
= tempImage
;
1407 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1408 + dstZoffset
* dstImageStride
1409 + dstYoffset
* dstRowStride
1410 + dstXoffset
* dstFormat
->TexelBytes
;
1411 GLint img
, row
, col
;
1414 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1415 for (img
= 0; img
< srcDepth
; img
++) {
1416 GLubyte
*dstRow
= dstImage
;
1417 for (row
= 0; row
< srcHeight
; row
++) {
1418 GLushort
*dstUS
= (GLushort
*) dstRow
;
1419 if (dstFormat
== &_mesa_texformat_al88
) {
1420 for (col
= 0; col
< srcWidth
; col
++) {
1421 /* src[0] is luminance, src[1] is alpha */
1422 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1423 CHAN_TO_UBYTE(src
[0]) );
1428 for (col
= 0; col
< srcWidth
; col
++) {
1429 /* src[0] is luminance, src[1] is alpha */
1430 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1431 CHAN_TO_UBYTE(src
[0]) );
1435 dstRow
+= dstRowStride
;
1437 dstImage
+= dstImageStride
;
1439 _mesa_free((void *) tempImage
);
1446 _mesa_texstore_rgb332(STORE_PARAMS
)
1448 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1449 ASSERT(dstFormat
->TexelBytes
== 1);
1451 if (!ctx
->_ImageTransferState
&&
1452 !srcPacking
->SwapBytes
&&
1453 baseInternalFormat
== GL_RGB
&&
1454 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1455 /* simple memcpy path */
1456 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1457 dstRowStride
, dstImageStride
,
1458 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1459 srcAddr
, srcPacking
);
1463 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1465 dstFormat
->BaseFormat
,
1466 srcWidth
, srcHeight
, srcDepth
,
1467 srcFormat
, srcType
, srcAddr
,
1469 const GLchan
*src
= tempImage
;
1470 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1471 + dstZoffset
* dstImageStride
1472 + dstYoffset
* dstRowStride
1473 + dstXoffset
* dstFormat
->TexelBytes
;
1474 GLint img
, row
, col
;
1477 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1478 for (img
= 0; img
< srcDepth
; img
++) {
1479 GLubyte
*dstRow
= dstImage
;
1480 for (row
= 0; row
< srcHeight
; row
++) {
1481 for (col
= 0; col
< srcWidth
; col
++) {
1482 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1483 CHAN_TO_UBYTE(src
[GCOMP
]),
1484 CHAN_TO_UBYTE(src
[BCOMP
]) );
1487 dstRow
+= dstRowStride
;
1489 dstImage
+= dstImageStride
;
1491 _mesa_free((void *) tempImage
);
1498 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1501 _mesa_texstore_a8(STORE_PARAMS
)
1503 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1504 dstFormat
== &_mesa_texformat_l8
||
1505 dstFormat
== &_mesa_texformat_i8
);
1506 ASSERT(dstFormat
->TexelBytes
== 1);
1508 if (!ctx
->_ImageTransferState
&&
1509 !srcPacking
->SwapBytes
&&
1510 baseInternalFormat
== srcFormat
&&
1511 srcType
== GL_UNSIGNED_BYTE
) {
1512 /* simple memcpy path */
1513 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1514 dstRowStride
, dstImageStride
,
1515 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1516 srcAddr
, srcPacking
);
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
= tempImage
;
1527 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1528 + dstZoffset
* dstImageStride
1529 + dstYoffset
* dstRowStride
1530 + dstXoffset
* dstFormat
->TexelBytes
;
1531 GLint img
, row
, col
;
1534 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1535 for (img
= 0; img
< srcDepth
; img
++) {
1536 GLubyte
*dstRow
= dstImage
;
1537 for (row
= 0; row
< srcHeight
; row
++) {
1538 for (col
= 0; col
< srcWidth
; col
++) {
1539 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1541 dstRow
+= dstRowStride
;
1544 dstImage
+= dstImageStride
;
1546 _mesa_free((void *) tempImage
);
1554 _mesa_texstore_ci8(STORE_PARAMS
)
1556 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1557 ASSERT(dstFormat
->TexelBytes
== 1);
1558 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1560 if (!ctx
->_ImageTransferState
&&
1561 !srcPacking
->SwapBytes
&&
1562 srcFormat
== GL_COLOR_INDEX
&&
1563 srcType
== GL_UNSIGNED_BYTE
) {
1564 /* simple memcpy path */
1565 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1566 dstRowStride
, dstImageStride
,
1567 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1568 srcAddr
, srcPacking
);
1572 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1573 + dstZoffset
* dstImageStride
1574 + dstYoffset
* dstRowStride
1575 + dstXoffset
* dstFormat
->TexelBytes
;
1577 for (img
= 0; img
< srcDepth
; img
++) {
1578 GLubyte
*dstRow
= dstImage
;
1579 for (row
= 0; row
< srcHeight
; row
++) {
1580 const GLvoid
*src
= _mesa_image_address(srcPacking
,
1581 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1582 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1583 srcType
, src
, srcPacking
,
1584 ctx
->_ImageTransferState
);
1585 dstRow
+= dstRowStride
;
1587 dstImage
+= dstImageStride
;
1595 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1598 _mesa_texstore_ycbcr(STORE_PARAMS
)
1600 const GLuint ui
= 1;
1601 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1603 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1604 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1605 ASSERT(dstFormat
->TexelBytes
== 2);
1606 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1607 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1608 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1609 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1610 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1612 /* always just memcpy since no pixel transfer ops apply */
1613 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1614 dstRowStride
, dstImageStride
,
1615 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1616 srcAddr
, srcPacking
);
1618 /* Check if we need byte swapping */
1619 /* XXX the logic here _might_ be wrong */
1620 if (srcPacking
->SwapBytes
^
1621 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1622 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1624 GLushort
*pImage
= (GLushort
*) ((GLubyte
*) dstAddr
1625 + dstZoffset
* dstImageStride
1626 + dstYoffset
* dstRowStride
1627 + dstXoffset
* dstFormat
->TexelBytes
);
1629 for (img
= 0; img
< srcDepth
; img
++) {
1630 GLushort
*pRow
= pImage
;
1631 for (row
= 0; row
< srcHeight
; row
++) {
1632 _mesa_swap2(pRow
, srcWidth
);
1633 pRow
+= dstRowStride
;
1635 pImage
+= dstImageStride
;
1645 * Store an image in any of the formats:
1646 * _mesa_texformat_rgba_float32
1647 * _mesa_texformat_rgb_float32
1648 * _mesa_texformat_alpha_float32
1649 * _mesa_texformat_luminance_float32
1650 * _mesa_texformat_luminance_alpha_float32
1651 * _mesa_texformat_intensity_float32
1654 _mesa_texstore_rgba_float32(STORE_PARAMS
)
1656 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1658 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
1659 dstFormat
== &_mesa_texformat_rgb_float32
||
1660 dstFormat
== &_mesa_texformat_alpha_float32
||
1661 dstFormat
== &_mesa_texformat_luminance_float32
||
1662 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
1663 dstFormat
== &_mesa_texformat_intensity_float32
);
1664 ASSERT(baseInternalFormat
== GL_RGBA
||
1665 baseInternalFormat
== GL_RGB
||
1666 baseInternalFormat
== GL_ALPHA
||
1667 baseInternalFormat
== GL_LUMINANCE
||
1668 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1669 baseInternalFormat
== GL_INTENSITY
);
1670 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
1672 if (!ctx
->_ImageTransferState
&&
1673 !srcPacking
->SwapBytes
&&
1674 baseInternalFormat
== srcFormat
&&
1675 srcType
== GL_FLOAT
) {
1676 /* simple memcpy path */
1677 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1678 dstRowStride
, dstImageStride
,
1679 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1680 srcAddr
, srcPacking
);
1684 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1686 dstFormat
->BaseFormat
,
1687 srcWidth
, srcHeight
, srcDepth
,
1688 srcFormat
, srcType
, srcAddr
,
1690 const GLfloat
*src
= tempImage
;
1692 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1693 + dstZoffset
* dstImageStride
1694 + dstYoffset
* dstRowStride
1695 + dstXoffset
* dstFormat
->TexelBytes
;
1699 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1700 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
1701 for (img
= 0; img
< srcDepth
; img
++) {
1702 GLubyte
*dst
= dstImage
;
1703 for (row
= 0; row
< srcHeight
; row
++) {
1704 _mesa_memcpy(dst
, src
, bytesPerRow
);
1705 dst
+= dstRowStride
;
1706 src
+= srcWidth
* components
;
1708 dstImage
+= dstImageStride
;
1711 _mesa_free((void *) tempImage
);
1718 * As above, but store 16-bit floats.
1721 _mesa_texstore_rgba_float16(STORE_PARAMS
)
1723 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1725 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
1726 dstFormat
== &_mesa_texformat_rgb_float16
||
1727 dstFormat
== &_mesa_texformat_alpha_float16
||
1728 dstFormat
== &_mesa_texformat_luminance_float16
||
1729 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
1730 dstFormat
== &_mesa_texformat_intensity_float16
);
1731 ASSERT(baseInternalFormat
== GL_RGBA
||
1732 baseInternalFormat
== GL_RGB
||
1733 baseInternalFormat
== GL_ALPHA
||
1734 baseInternalFormat
== GL_LUMINANCE
||
1735 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1736 baseInternalFormat
== GL_INTENSITY
);
1737 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
1739 if (!ctx
->_ImageTransferState
&&
1740 !srcPacking
->SwapBytes
&&
1741 baseInternalFormat
== srcFormat
&&
1742 srcType
== GL_HALF_FLOAT_ARB
) {
1743 /* simple memcpy path */
1744 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1745 dstRowStride
, dstImageStride
,
1746 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1747 srcAddr
, srcPacking
);
1751 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1753 dstFormat
->BaseFormat
,
1754 srcWidth
, srcHeight
, srcDepth
,
1755 srcFormat
, srcType
, srcAddr
,
1757 const GLfloat
*src
= tempImage
;
1758 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1759 + dstZoffset
* dstImageStride
1760 + dstYoffset
* dstRowStride
1761 + dstXoffset
* dstFormat
->TexelBytes
;
1765 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1766 for (img
= 0; img
< srcDepth
; img
++) {
1767 GLubyte
*dstRow
= dstImage
;
1768 for (row
= 0; row
< srcHeight
; row
++) {
1769 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
1771 for (i
= 0; i
< srcWidth
* components
; i
++) {
1772 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
1774 dstRow
+= dstRowStride
;
1775 src
+= srcWidth
* components
;
1777 dstImage
+= dstImageStride
;
1780 _mesa_free((void *) tempImage
);
1788 * Validate acces to a PBO for texture data.
1790 * \todo If the PBO is really resident in VRAM, this won't work; the
1791 * device driver should check for that and do the right thing.
1793 static const GLvoid
*
1794 validate_pbo_teximage( GLsizei width
, GLsizei height
, GLsizei depth
,
1795 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1796 const struct gl_pixelstore_attrib
*unpack
)
1798 if (unpack
->BufferObj
->Name
== 0) {
1802 else if (_mesa_validate_pbo_access(unpack
, width
, height
, depth
, format
,
1804 return ADD_POINTERS(unpack
->BufferObj
->Data
, pixels
);
1812 * Validate that unpacking compressed texture image data from a PBO
1813 * won't go out of bounds.
1815 * \todo If the PBO is really resident in VRAM, this won't work; the
1816 * device driver should check for that and do the right thing.
1818 static const GLvoid
*
1819 validate_pbo_compressed_teximage(GLsizei imageSize
, const GLvoid
*pixels
,
1820 const struct gl_pixelstore_attrib
*packing
)
1822 if (packing
->BufferObj
->Name
== 0) {
1823 /* not using a PBO - return pointer unchanged */
1828 if ((const GLubyte
*) pixels
+ imageSize
>
1829 (const GLubyte
*) packing
->BufferObj
->Size
) {
1830 /* out of bounds read! */
1834 return ADD_POINTERS(packing
->BufferObj
->Data
, pixels
);
1841 * This is the software fallback for Driver.TexImage1D()
1842 * and Driver.CopyTexImage1D().
1845 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
1846 GLint internalFormat
,
1847 GLint width
, GLint border
,
1848 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1849 const struct gl_pixelstore_attrib
*packing
,
1850 struct gl_texture_object
*texObj
,
1851 struct gl_texture_image
*texImage
)
1853 GLint postConvWidth
= width
;
1856 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
1857 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1860 /* choose the texture format */
1861 assert(ctx
->Driver
.ChooseTextureFormat
);
1862 texImage
->TexFormat
= ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
,
1864 assert(texImage
->TexFormat
);
1865 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
1866 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
1868 /* allocate memory */
1869 if (texImage
->IsCompressed
)
1870 sizeInBytes
= texImage
->CompressedSize
;
1872 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
1873 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
1874 if (!texImage
->Data
) {
1875 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1879 pixels
= validate_pbo_teximage(width
, 1, 1, format
, type
, pixels
, packing
);
1884 const GLint dstRowStride
= 0, dstImageStride
= 0;
1886 ASSERT(texImage
->TexFormat
->StoreImage
);
1887 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
1888 texImage
->TexFormat
,
1890 0, 0, 0, /* dstX/Y/Zoffset */
1891 dstRowStride
, dstImageStride
,
1893 format
, type
, pixels
, packing
);
1895 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1900 /* GL_SGIS_generate_mipmap */
1901 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1902 _mesa_generate_mipmap(ctx
, target
,
1903 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
1910 * This is the software fallback for Driver.TexImage2D()
1911 * and Driver.CopyTexImage2D().
1912 * Reasons why a driver might override this function:
1913 * - Special memory allocation needs
1914 * - Unusual row/image strides
1915 * - Special housekeeping
1918 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
1919 GLint internalFormat
,
1920 GLint width
, GLint height
, GLint border
,
1921 GLenum format
, GLenum type
, const void *pixels
,
1922 const struct gl_pixelstore_attrib
*packing
,
1923 struct gl_texture_object
*texObj
,
1924 struct gl_texture_image
*texImage
)
1926 GLint postConvWidth
= width
, postConvHeight
= height
;
1927 GLint texelBytes
, sizeInBytes
;
1929 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
1930 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
1934 /* choose the texture format */
1935 assert(ctx
->Driver
.ChooseTextureFormat
);
1936 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
1937 internalFormat
, format
, type
);
1938 assert(texImage
->TexFormat
);
1939 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
1940 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
1942 texelBytes
= texImage
->TexFormat
->TexelBytes
;
1944 /* allocate memory */
1945 if (texImage
->IsCompressed
)
1946 sizeInBytes
= texImage
->CompressedSize
;
1948 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
1949 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
1950 if (!texImage
->Data
) {
1951 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1955 pixels
= validate_pbo_teximage(width
, height
, 1,
1956 format
, type
, pixels
, packing
);
1961 GLint dstRowStride
, dstImageStride
= 0;
1963 if (texImage
->IsCompressed
) {
1964 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
1967 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
1969 ASSERT(texImage
->TexFormat
->StoreImage
);
1970 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1971 texImage
->TexFormat
,
1973 0, 0, 0, /* dstX/Y/Zoffset */
1974 dstRowStride
, dstImageStride
,
1976 format
, type
, pixels
, packing
);
1978 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1983 /* GL_SGIS_generate_mipmap */
1984 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1985 _mesa_generate_mipmap(ctx
, target
,
1986 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
1994 * This is the software fallback for Driver.TexImage3D()
1995 * and Driver.CopyTexImage3D().
1998 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
1999 GLint internalFormat
,
2000 GLint width
, GLint height
, GLint depth
, GLint border
,
2001 GLenum format
, GLenum type
, const void *pixels
,
2002 const struct gl_pixelstore_attrib
*packing
,
2003 struct gl_texture_object
*texObj
,
2004 struct gl_texture_image
*texImage
)
2006 GLint texelBytes
, sizeInBytes
;
2008 /* choose the texture format */
2009 assert(ctx
->Driver
.ChooseTextureFormat
);
2010 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2011 internalFormat
, format
, type
);
2012 assert(texImage
->TexFormat
);
2013 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2014 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2016 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2018 /* allocate memory */
2019 if (texImage
->IsCompressed
)
2020 sizeInBytes
= texImage
->CompressedSize
;
2022 sizeInBytes
= width
* height
* depth
* texelBytes
;
2023 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2024 if (!texImage
->Data
) {
2025 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2029 pixels
= validate_pbo_teximage(width
, height
, depth
,
2030 format
, type
, pixels
, packing
);
2034 /* unpack image, apply transfer ops and store in texImage->Data */
2036 GLint dstRowStride
, dstImageStride
;
2038 if (texImage
->IsCompressed
) {
2039 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2043 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2044 dstImageStride
= dstRowStride
* height
;
2046 ASSERT(texImage
->TexFormat
->StoreImage
);
2047 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2048 texImage
->TexFormat
,
2050 0, 0, 0, /* dstX/Y/Zoffset */
2051 dstRowStride
, dstImageStride
,
2052 width
, height
, depth
,
2053 format
, type
, pixels
, packing
);
2055 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2060 /* GL_SGIS_generate_mipmap */
2061 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2062 _mesa_generate_mipmap(ctx
, target
,
2063 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2072 * This is the software fallback for Driver.TexSubImage1D()
2073 * and Driver.CopyTexSubImage1D().
2076 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2077 GLint xoffset
, GLint width
,
2078 GLenum format
, GLenum type
, const void *pixels
,
2079 const struct gl_pixelstore_attrib
*packing
,
2080 struct gl_texture_object
*texObj
,
2081 struct gl_texture_image
*texImage
)
2083 pixels
= validate_pbo_teximage(width
, 1, 1,
2084 format
, type
, pixels
, packing
);
2089 const GLint dstRowStride
= 0, dstImageStride
= 0;
2091 ASSERT(texImage
->TexFormat
->StoreImage
);
2092 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2093 texImage
->TexFormat
,
2095 xoffset
, 0, 0, /* offsets */
2096 dstRowStride
, dstImageStride
,
2098 format
, type
, pixels
, packing
);
2100 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2105 /* GL_SGIS_generate_mipmap */
2106 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2107 _mesa_generate_mipmap(ctx
, target
,
2108 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2116 * This is the software fallback for Driver.TexSubImage2D()
2117 * and Driver.CopyTexSubImage2D().
2120 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2121 GLint xoffset
, GLint yoffset
,
2122 GLint width
, GLint height
,
2123 GLenum format
, GLenum type
, const void *pixels
,
2124 const struct gl_pixelstore_attrib
*packing
,
2125 struct gl_texture_object
*texObj
,
2126 struct gl_texture_image
*texImage
)
2128 pixels
= validate_pbo_teximage(width
, height
, 1,
2129 format
, type
, pixels
, packing
);
2134 GLint dstRowStride
= 0, dstImageStride
= 0;
2136 if (texImage
->IsCompressed
) {
2137 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2141 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2143 ASSERT(texImage
->TexFormat
->StoreImage
);
2144 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2145 texImage
->TexFormat
,
2147 xoffset
, yoffset
, 0,
2148 dstRowStride
, dstImageStride
,
2150 format
, type
, pixels
, packing
);
2152 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2157 /* GL_SGIS_generate_mipmap */
2158 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2159 _mesa_generate_mipmap(ctx
, target
,
2160 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2167 * This is the software fallback for Driver.TexSubImage3D().
2168 * and Driver.CopyTexSubImage3D().
2171 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2172 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2173 GLint width
, GLint height
, GLint depth
,
2174 GLenum format
, GLenum type
, const void *pixels
,
2175 const struct gl_pixelstore_attrib
*packing
,
2176 struct gl_texture_object
*texObj
,
2177 struct gl_texture_image
*texImage
)
2179 pixels
= validate_pbo_teximage(width
, height
, depth
,
2180 format
, type
, pixels
, packing
);
2185 GLint dstRowStride
, dstImageStride
;
2187 if (texImage
->IsCompressed
) {
2188 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2190 dstImageStride
= 0; /* XXX fix */
2193 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2194 dstImageStride
= dstRowStride
* texImage
->Height
;
2196 ASSERT(texImage
->TexFormat
->StoreImage
);
2197 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2198 texImage
->TexFormat
,
2200 xoffset
, yoffset
, zoffset
,
2201 dstRowStride
, dstImageStride
,
2202 width
, height
, depth
,
2203 format
, type
, pixels
, packing
);
2205 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2210 /* GL_SGIS_generate_mipmap */
2211 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2212 _mesa_generate_mipmap(ctx
, target
,
2213 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2220 * Fallback for Driver.CompressedTexImage1D()
2223 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2224 GLint internalFormat
,
2225 GLint width
, GLint border
,
2226 GLsizei imageSize
, const GLvoid
*data
,
2227 struct gl_texture_object
*texObj
,
2228 struct gl_texture_image
*texImage
)
2230 /* this space intentionally left blank */
2236 * Fallback for Driver.CompressedTexImage2D()
2239 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2240 GLint internalFormat
,
2241 GLint width
, GLint height
, GLint border
,
2242 GLsizei imageSize
, const GLvoid
*data
,
2243 struct gl_texture_object
*texObj
,
2244 struct gl_texture_image
*texImage
)
2246 /* This is pretty simple, basically just do a memcpy without worrying
2247 * about the usual image unpacking or image transfer operations.
2251 ASSERT(texImage
->Width
> 0);
2252 ASSERT(texImage
->Height
> 0);
2253 ASSERT(texImage
->Depth
== 1);
2254 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2256 /* choose the texture format */
2257 assert(ctx
->Driver
.ChooseTextureFormat
);
2258 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2259 internalFormat
, 0, 0);
2260 assert(texImage
->TexFormat
);
2261 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2262 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2264 /* allocate storage */
2265 texImage
->Data
= MESA_PBUFFER_ALLOC(imageSize
);
2266 if (!texImage
->Data
) {
2267 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2271 data
= validate_pbo_compressed_teximage(imageSize
, data
, &ctx
->Unpack
);
2276 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2277 MEMCPY(texImage
->Data
, data
, imageSize
);
2279 /* GL_SGIS_generate_mipmap */
2280 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2281 _mesa_generate_mipmap(ctx
, target
,
2282 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2290 * Fallback for Driver.CompressedTexImage3D()
2293 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2294 GLint internalFormat
,
2295 GLint width
, GLint height
, GLint depth
,
2297 GLsizei imageSize
, const GLvoid
*data
,
2298 struct gl_texture_object
*texObj
,
2299 struct gl_texture_image
*texImage
)
2301 /* this space intentionally left blank */
2307 * Fallback for Driver.CompressedTexSubImage1D()
2310 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2312 GLint xoffset
, GLsizei width
,
2314 GLsizei imageSize
, const GLvoid
*data
,
2315 struct gl_texture_object
*texObj
,
2316 struct gl_texture_image
*texImage
)
2318 /* this space intentionally left blank */
2323 * Fallback for Driver.CompressedTexSubImage2D()
2326 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2328 GLint xoffset
, GLint yoffset
,
2329 GLsizei width
, GLsizei height
,
2331 GLsizei imageSize
, const GLvoid
*data
,
2332 struct gl_texture_object
*texObj
,
2333 struct gl_texture_image
*texImage
)
2335 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2340 /* these should have been caught sooner */
2341 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2342 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2343 ASSERT((xoffset
& 3) == 0);
2344 ASSERT((yoffset
& 3) == 0);
2346 data
= validate_pbo_compressed_teximage(imageSize
, data
, &ctx
->Unpack
);
2350 srcRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
, width
);
2351 src
= (const GLubyte
*) data
;
2353 destRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2355 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2356 texImage
->IntFormat
,
2358 (GLubyte
*) texImage
->Data
);
2360 bytesPerRow
= srcRowStride
;
2363 for (i
= 0; i
< rows
; i
++) {
2364 MEMCPY(dest
, src
, bytesPerRow
);
2365 dest
+= destRowStride
;
2366 src
+= srcRowStride
;
2369 /* GL_SGIS_generate_mipmap */
2370 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2371 _mesa_generate_mipmap(ctx
, target
,
2372 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2379 * Fallback for Driver.CompressedTexSubImage3D()
2382 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2384 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2385 GLsizei width
, GLsizei height
, GLsizei depth
,
2387 GLsizei imageSize
, const GLvoid
*data
,
2388 struct gl_texture_object
*texObj
,
2389 struct gl_texture_image
*texImage
)
2391 /* this space intentionally left blank */
2396 * Average together two rows of a source image to produce a single new
2397 * row in the dest image. It's legal for the two source rows to point
2398 * to the same data. The source width must be equal to either the
2399 * dest width or two times the dest width.
2402 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
2403 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
2404 GLint dstWidth
, GLvoid
*dstRow
)
2406 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
2407 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
2409 /* This assertion is no longer valid with non-power-of-2 textures
2410 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2413 switch (format
->MesaFormat
) {
2414 case MESA_FORMAT_RGBA
:
2417 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
2418 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
2419 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
2420 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2421 i
++, j
+= colStride
, k
+= colStride
) {
2422 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2423 rowB
[j
][0] + rowB
[k
][0]) / 4;
2424 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2425 rowB
[j
][1] + rowB
[k
][1]) / 4;
2426 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2427 rowB
[j
][2] + rowB
[k
][2]) / 4;
2428 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2429 rowB
[j
][3] + rowB
[k
][3]) / 4;
2433 case MESA_FORMAT_RGB
:
2436 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
2437 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
2438 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
2439 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2440 i
++, j
+= colStride
, k
+= colStride
) {
2441 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2442 rowB
[j
][0] + rowB
[k
][0]) / 4;
2443 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2444 rowB
[j
][1] + rowB
[k
][1]) / 4;
2445 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2446 rowB
[j
][2] + rowB
[k
][2]) / 4;
2450 case MESA_FORMAT_ALPHA
:
2451 case MESA_FORMAT_LUMINANCE
:
2452 case MESA_FORMAT_INTENSITY
:
2455 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
2456 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
2457 GLchan
*dst
= (GLchan
*) dstRow
;
2458 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2459 i
++, j
+= colStride
, k
+= colStride
) {
2460 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2464 case MESA_FORMAT_LUMINANCE_ALPHA
:
2467 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
2468 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
2469 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
2470 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2471 i
++, j
+= colStride
, k
+= colStride
) {
2472 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2473 rowB
[j
][0] + rowB
[k
][0]) / 4;
2474 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2475 rowB
[j
][1] + rowB
[k
][1]) / 4;
2479 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32
:
2482 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2483 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2484 GLfloat
*dst
= (GLfloat
*) dstRow
;
2485 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2486 i
++, j
+= colStride
, k
+= colStride
) {
2487 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
2491 case MESA_FORMAT_DEPTH_COMPONENT16
:
2494 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2495 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2496 GLushort
*dst
= (GLushort
*) dstRow
;
2497 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2498 i
++, j
+= colStride
, k
+= colStride
) {
2499 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2503 /* Begin hardware formats */
2504 case MESA_FORMAT_RGBA8888
:
2505 case MESA_FORMAT_RGBA8888_REV
:
2506 case MESA_FORMAT_ARGB8888
:
2507 case MESA_FORMAT_ARGB8888_REV
:
2510 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
2511 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
2512 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
2513 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2514 i
++, j
+= colStride
, k
+= colStride
) {
2515 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2516 rowB
[j
][0] + rowB
[k
][0]) / 4;
2517 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2518 rowB
[j
][1] + rowB
[k
][1]) / 4;
2519 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2520 rowB
[j
][2] + rowB
[k
][2]) / 4;
2521 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2522 rowB
[j
][3] + rowB
[k
][3]) / 4;
2526 case MESA_FORMAT_RGB888
:
2527 case MESA_FORMAT_BGR888
:
2530 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
2531 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
2532 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
2533 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2534 i
++, j
+= colStride
, k
+= colStride
) {
2535 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2536 rowB
[j
][0] + rowB
[k
][0]) / 4;
2537 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2538 rowB
[j
][1] + rowB
[k
][1]) / 4;
2539 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2540 rowB
[j
][2] + rowB
[k
][2]) / 4;
2544 case MESA_FORMAT_RGB565
:
2545 case MESA_FORMAT_RGB565_REV
:
2548 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2549 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2550 GLushort
*dst
= (GLushort
*) dstRow
;
2551 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2552 i
++, j
+= colStride
, k
+= colStride
) {
2553 const GLint rowAr0
= rowA
[j
] & 0x1f;
2554 const GLint rowAr1
= rowA
[k
] & 0x1f;
2555 const GLint rowBr0
= rowB
[j
] & 0x1f;
2556 const GLint rowBr1
= rowB
[k
] & 0x1f;
2557 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
2558 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
2559 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
2560 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
2561 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
2562 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
2563 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
2564 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
2565 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2566 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2567 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2568 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
2572 case MESA_FORMAT_ARGB4444
:
2573 case MESA_FORMAT_ARGB4444_REV
:
2576 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2577 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2578 GLushort
*dst
= (GLushort
*) dstRow
;
2579 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2580 i
++, j
+= colStride
, k
+= colStride
) {
2581 const GLint rowAr0
= rowA
[j
] & 0xf;
2582 const GLint rowAr1
= rowA
[k
] & 0xf;
2583 const GLint rowBr0
= rowB
[j
] & 0xf;
2584 const GLint rowBr1
= rowB
[k
] & 0xf;
2585 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
2586 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
2587 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
2588 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
2589 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
2590 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
2591 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
2592 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
2593 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
2594 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
2595 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
2596 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
2597 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2598 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2599 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2600 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2601 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
2605 case MESA_FORMAT_ARGB1555
:
2606 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
2609 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2610 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2611 GLushort
*dst
= (GLushort
*) dstRow
;
2612 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2613 i
++, j
+= colStride
, k
+= colStride
) {
2614 const GLint rowAr0
= rowA
[j
] & 0x1f;
2615 const GLint rowAr1
= rowA
[k
] & 0x1f;
2616 const GLint rowBr0
= rowB
[j
] & 0x1f;
2617 const GLint rowBr1
= rowB
[k
] & 0xf;
2618 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
2619 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
2620 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
2621 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
2622 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
2623 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
2624 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
2625 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
2626 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
2627 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
2628 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
2629 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
2630 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2631 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2632 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2633 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2634 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
2638 case MESA_FORMAT_AL88
:
2639 case MESA_FORMAT_AL88_REV
:
2642 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
2643 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
2644 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
2645 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2646 i
++, j
+= colStride
, k
+= colStride
) {
2647 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2648 rowB
[j
][0] + rowB
[k
][0]) >> 2;
2649 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2650 rowB
[j
][1] + rowB
[k
][1]) >> 2;
2654 case MESA_FORMAT_RGB332
:
2657 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
2658 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
2659 GLubyte
*dst
= (GLubyte
*) dstRow
;
2660 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2661 i
++, j
+= colStride
, k
+= colStride
) {
2662 const GLint rowAr0
= rowA
[j
] & 0x3;
2663 const GLint rowAr1
= rowA
[k
] & 0x3;
2664 const GLint rowBr0
= rowB
[j
] & 0x3;
2665 const GLint rowBr1
= rowB
[k
] & 0x3;
2666 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
2667 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
2668 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
2669 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
2670 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
2671 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
2672 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
2673 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
2674 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2675 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2676 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2677 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
2681 case MESA_FORMAT_A8
:
2682 case MESA_FORMAT_L8
:
2683 case MESA_FORMAT_I8
:
2684 case MESA_FORMAT_CI8
:
2687 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
2688 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
2689 GLubyte
*dst
= (GLubyte
*) dstRow
;
2690 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2691 i
++, j
+= colStride
, k
+= colStride
) {
2692 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
2696 case MESA_FORMAT_RGBA_FLOAT32
:
2699 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
2700 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
2701 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
2702 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2703 i
++, j
+= colStride
, k
+= colStride
) {
2704 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2705 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2706 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2707 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2708 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2709 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
2710 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2711 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
2715 case MESA_FORMAT_RGBA_FLOAT16
:
2717 GLuint i
, j
, k
, comp
;
2718 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
2719 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
2720 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
2721 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2722 i
++, j
+= colStride
, k
+= colStride
) {
2723 for (comp
= 0; comp
< 4; comp
++) {
2724 GLfloat aj
, ak
, bj
, bk
;
2725 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2726 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2727 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2728 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2729 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2734 case MESA_FORMAT_RGB_FLOAT32
:
2737 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
2738 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
2739 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
2740 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2741 i
++, j
+= colStride
, k
+= colStride
) {
2742 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2743 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2744 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2745 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2746 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2747 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
2751 case MESA_FORMAT_RGB_FLOAT16
:
2753 GLuint i
, j
, k
, comp
;
2754 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
2755 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
2756 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
2757 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2758 i
++, j
+= colStride
, k
+= colStride
) {
2759 for (comp
= 0; comp
< 3; comp
++) {
2760 GLfloat aj
, ak
, bj
, bk
;
2761 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2762 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2763 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2764 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2765 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2770 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
2773 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
2774 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
2775 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
2776 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2777 i
++, j
+= colStride
, k
+= colStride
) {
2778 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2779 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2780 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2781 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2785 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
2787 GLuint i
, j
, k
, comp
;
2788 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
2789 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
2790 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
2791 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2792 i
++, j
+= colStride
, k
+= colStride
) {
2793 for (comp
= 0; comp
< 2; comp
++) {
2794 GLfloat aj
, ak
, bj
, bk
;
2795 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2796 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2797 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2798 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2799 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2804 case MESA_FORMAT_ALPHA_FLOAT32
:
2805 case MESA_FORMAT_LUMINANCE_FLOAT32
:
2806 case MESA_FORMAT_INTENSITY_FLOAT32
:
2809 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2810 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2811 GLfloat
*dst
= (GLfloat
*) dstRow
;
2812 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2813 i
++, j
+= colStride
, k
+= colStride
) {
2814 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
2818 case MESA_FORMAT_ALPHA_FLOAT16
:
2819 case MESA_FORMAT_LUMINANCE_FLOAT16
:
2820 case MESA_FORMAT_INTENSITY_FLOAT16
:
2823 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
2824 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
2825 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
2826 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2827 i
++, j
+= colStride
, k
+= colStride
) {
2828 GLfloat aj
, ak
, bj
, bk
;
2829 aj
= _mesa_half_to_float(rowA
[j
]);
2830 ak
= _mesa_half_to_float(rowA
[k
]);
2831 bj
= _mesa_half_to_float(rowB
[j
]);
2832 bk
= _mesa_half_to_float(rowB
[k
]);
2833 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2839 _mesa_problem(NULL
, "bad format in do_row()");
2845 * These functions generate a 1/2-size mipmap image from a source image.
2846 * Texture borders are handled by copying or averaging the source image's
2847 * border texels, depending on the scale-down factor.
2851 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
2852 GLint srcWidth
, const GLubyte
*srcPtr
,
2853 GLint dstWidth
, GLubyte
*dstPtr
)
2855 const GLint bpt
= format
->TexelBytes
;
2859 /* skip the border pixel, if any */
2860 src
= srcPtr
+ border
* bpt
;
2861 dst
= dstPtr
+ border
* bpt
;
2863 /* we just duplicate the input row, kind of hack, saves code */
2864 do_row(format
, srcWidth
- 2 * border
, src
, src
,
2865 dstWidth
- 2 * border
, dst
);
2868 /* copy left-most pixel from source */
2869 MEMCPY(dstPtr
, srcPtr
, bpt
);
2870 /* copy right-most pixel from source */
2871 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
2872 srcPtr
+ (srcWidth
- 1) * bpt
,
2879 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
2880 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
2881 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
2883 const GLint bpt
= format
->TexelBytes
;
2884 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
2885 const GLint dstWidthNB
= dstWidth
- 2 * border
;
2886 const GLint dstHeightNB
= dstHeight
- 2 * border
;
2887 const GLint srcRowStride
= bpt
* srcWidth
;
2888 const GLint dstRowStride
= bpt
* dstWidth
;
2889 const GLubyte
*srcA
, *srcB
;
2893 /* Compute src and dst pointers, skipping any border */
2894 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
2896 srcB
= srcA
+ srcRowStride
;
2899 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
2901 for (row
= 0; row
< dstHeightNB
; row
++) {
2902 do_row(format
, srcWidthNB
, srcA
, srcB
,
2904 srcA
+= 2 * srcRowStride
;
2905 srcB
+= 2 * srcRowStride
;
2906 dst
+= dstRowStride
;
2909 /* This is ugly but probably won't be used much */
2911 /* fill in dest border */
2912 /* lower-left border pixel */
2913 MEMCPY(dstPtr
, srcPtr
, bpt
);
2914 /* lower-right border pixel */
2915 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
2916 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
2917 /* upper-left border pixel */
2918 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
2919 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
2920 /* upper-right border pixel */
2921 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
2922 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
2924 do_row(format
, srcWidthNB
,
2927 dstWidthNB
, dstPtr
+ bpt
);
2929 do_row(format
, srcWidthNB
,
2930 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
2931 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
2933 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
2934 /* left and right borders */
2935 if (srcHeight
== dstHeight
) {
2936 /* copy border pixel from src to dst */
2937 for (row
= 1; row
< srcHeight
; row
++) {
2938 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
2939 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
2940 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
2941 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
2945 /* average two src pixels each dest pixel */
2946 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
2948 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
2949 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
2950 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
2952 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
2953 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
2954 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
2962 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
2963 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
2964 const GLubyte
*srcPtr
,
2965 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
2968 const GLint bpt
= format
->TexelBytes
;
2969 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
2970 const GLint srcDepthNB
= srcDepth
- 2 * border
;
2971 const GLint dstWidthNB
= dstWidth
- 2 * border
;
2972 const GLint dstHeightNB
= dstHeight
- 2 * border
;
2973 const GLint dstDepthNB
= dstDepth
- 2 * border
;
2974 GLvoid
*tmpRowA
, *tmpRowB
;
2976 GLint bytesPerSrcImage
, bytesPerDstImage
;
2977 GLint bytesPerSrcRow
, bytesPerDstRow
;
2978 GLint srcImageOffset
, srcRowOffset
;
2980 (void) srcDepthNB
; /* silence warnings */
2982 /* Need two temporary row buffers */
2983 tmpRowA
= MALLOC(srcWidth
* bpt
);
2986 tmpRowB
= MALLOC(srcWidth
* bpt
);
2992 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
2993 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
2995 bytesPerSrcRow
= srcWidth
* bpt
;
2996 bytesPerDstRow
= dstWidth
* bpt
;
2998 /* Offset between adjacent src images to be averaged together */
2999 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3001 /* Offset between adjacent src rows to be averaged together */
3002 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3005 * Need to average together up to 8 src pixels for each dest pixel.
3006 * Break that down into 3 operations:
3007 * 1. take two rows from source image and average them together.
3008 * 2. take two rows from next source image and average them together.
3009 * 3. take the two averaged rows and average them for the final dst row.
3013 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3014 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3017 for (img
= 0; img
< dstDepthNB
; img
++) {
3018 /* first source image pointer, skipping border */
3019 const GLubyte
*imgSrcA
= srcPtr
3020 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3021 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3022 /* second source image pointer, skipping border */
3023 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3024 /* address of the dest image, skipping border */
3025 GLubyte
*imgDst
= dstPtr
3026 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3027 + img
* bytesPerDstImage
;
3029 /* setup the four source row pointers and the dest row pointer */
3030 const GLubyte
*srcImgARowA
= imgSrcA
;
3031 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3032 const GLubyte
*srcImgBRowA
= imgSrcB
;
3033 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3034 GLubyte
*dstImgRow
= imgDst
;
3036 for (row
= 0; row
< dstHeightNB
; row
++) {
3037 /* Average together two rows from first src image */
3038 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3039 srcWidthNB
, tmpRowA
);
3040 /* Average together two rows from second src image */
3041 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3042 srcWidthNB
, tmpRowB
);
3043 /* Average together the temp rows to make the final row */
3044 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3045 dstWidthNB
, dstImgRow
);
3046 /* advance to next rows */
3047 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3048 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3049 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3050 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3051 dstImgRow
+= bytesPerDstRow
;
3058 /* Luckily we can leverage the make_2d_mipmap() function here! */
3060 /* do front border image */
3061 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3062 dstWidth
, dstHeight
, dstPtr
);
3063 /* do back border image */
3064 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3065 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3066 dstWidth
, dstHeight
,
3067 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3068 /* do four remaining border edges that span the image slices */
3069 if (srcDepth
== dstDepth
) {
3070 /* just copy border pixels from src to dst */
3071 for (img
= 0; img
< dstDepthNB
; img
++) {
3075 /* do border along [img][row=0][col=0] */
3076 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3077 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3078 MEMCPY(dst
, src
, bpt
);
3080 /* do border along [img][row=dstHeight-1][col=0] */
3081 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3082 + (srcHeight
- 1) * bytesPerSrcRow
;
3083 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3084 + (dstHeight
- 1) * bytesPerDstRow
;
3085 MEMCPY(dst
, src
, bpt
);
3087 /* do border along [img][row=0][col=dstWidth-1] */
3088 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3089 + (srcWidth
- 1) * bpt
;
3090 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3091 + (dstWidth
- 1) * bpt
;
3092 MEMCPY(dst
, src
, bpt
);
3094 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3095 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3096 + (bytesPerSrcImage
- bpt
);
3097 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3098 + (bytesPerDstImage
- bpt
);
3099 MEMCPY(dst
, src
, bpt
);
3103 /* average border pixels from adjacent src image pairs */
3104 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3105 for (img
= 0; img
< dstDepthNB
; img
++) {
3109 /* do border along [img][row=0][col=0] */
3110 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3111 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3112 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3114 /* do border along [img][row=dstHeight-1][col=0] */
3115 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3116 + (srcHeight
- 1) * bytesPerSrcRow
;
3117 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3118 + (dstHeight
- 1) * bytesPerDstRow
;
3119 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3121 /* do border along [img][row=0][col=dstWidth-1] */
3122 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3123 + (srcWidth
- 1) * bpt
;
3124 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3125 + (dstWidth
- 1) * bpt
;
3126 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3128 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3129 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3130 + (bytesPerSrcImage
- bpt
);
3131 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3132 + (bytesPerDstImage
- bpt
);
3133 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3141 * For GL_SGIX_generate_mipmap:
3142 * Generate a complete set of mipmaps from texObj's base-level image.
3143 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3146 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3147 const struct gl_texture_unit
*texUnit
,
3148 struct gl_texture_object
*texObj
)
3150 const struct gl_texture_image
*srcImage
;
3151 const struct gl_texture_format
*convertFormat
;
3152 const GLubyte
*srcData
= NULL
;
3153 GLubyte
*dstData
= NULL
;
3154 GLint level
, maxLevels
;
3157 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3160 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3161 ASSERT(maxLevels
> 0); /* bad target */
3163 /* Find convertFormat - the format that do_row() will process */
3164 if (srcImage
->IsCompressed
) {
3165 /* setup for compressed textures */
3167 GLint components
, size
;
3170 assert(texObj
->Target
== GL_TEXTURE_2D
);
3172 if (srcImage
->Format
== GL_RGB
) {
3173 convertFormat
= &_mesa_texformat_rgb
;
3176 else if (srcImage
->Format
== GL_RGBA
) {
3177 convertFormat
= &_mesa_texformat_rgba
;
3181 _mesa_problem(ctx
, "bad srcImage->Format in _mesa_generate_mipmaps");
3185 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3186 size
= _mesa_bytes_per_pixel(srcImage
->Format
, CHAN_TYPE
)
3187 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3188 /* 20 extra bytes, just be safe when calling last FetchTexel */
3189 srcData
= (GLubyte
*) MALLOC(size
);
3191 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3194 dstData
= (GLubyte
*) MALLOC(size
/ 2); /* 1/4 would probably be OK */
3196 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3197 FREE((void *) srcData
);
3201 /* decompress base image here */
3202 dst
= (GLchan
*) srcData
;
3203 for (row
= 0; row
< srcImage
->Height
; row
++) {
3205 for (col
= 0; col
< srcImage
->Width
; col
++) {
3206 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3213 convertFormat
= srcImage
->TexFormat
;
3216 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3217 && level
< maxLevels
- 1; level
++) {
3218 /* generate image[level+1] from image[level] */
3219 const struct gl_texture_image
*srcImage
;
3220 struct gl_texture_image
*dstImage
;
3221 GLint srcWidth
, srcHeight
, srcDepth
;
3222 GLint dstWidth
, dstHeight
, dstDepth
;
3223 GLint border
, bytesPerTexel
;
3225 /* get src image parameters */
3226 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3228 srcWidth
= srcImage
->Width
;
3229 srcHeight
= srcImage
->Height
;
3230 srcDepth
= srcImage
->Depth
;
3231 border
= srcImage
->Border
;
3233 /* compute next (level+1) image size */
3234 if (srcWidth
- 2 * border
> 1) {
3235 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3238 dstWidth
= srcWidth
; /* can't go smaller */
3240 if (srcHeight
- 2 * border
> 1) {
3241 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3244 dstHeight
= srcHeight
; /* can't go smaller */
3246 if (srcDepth
- 2 * border
> 1) {
3247 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3250 dstDepth
= srcDepth
; /* can't go smaller */
3253 if (dstWidth
== srcWidth
&&
3254 dstHeight
== srcHeight
&&
3255 dstDepth
== srcDepth
) {
3257 if (srcImage
->IsCompressed
) {
3258 FREE((void *) srcData
);
3264 /* get dest gl_texture_image */
3265 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3267 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3271 /* Free old image data */
3273 MESA_PBUFFER_FREE(dstImage
->Data
);
3275 /* initialize new image */
3276 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3277 dstDepth
, border
, srcImage
->IntFormat
);
3278 dstImage
->DriverData
= NULL
;
3279 dstImage
->TexFormat
= srcImage
->TexFormat
;
3280 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3281 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3282 ASSERT(dstImage
->TexFormat
);
3283 ASSERT(dstImage
->FetchTexelc
);
3284 ASSERT(dstImage
->FetchTexelf
);
3286 /* Alloc new teximage data buffer.
3287 * Setup src and dest data pointers.
3289 if (dstImage
->IsCompressed
) {
3290 ASSERT(dstImage
->CompressedSize
> 0); /* set by init_teximage_fields*/
3291 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstImage
->CompressedSize
);
3292 if (!dstImage
->Data
) {
3293 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3296 /* srcData and dstData are already set */
3301 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
3302 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3303 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstWidth
* dstHeight
* dstDepth
3305 if (!dstImage
->Data
) {
3306 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3309 srcData
= (const GLubyte
*) srcImage
->Data
;
3310 dstData
= (GLubyte
*) dstImage
->Data
;
3314 * We use simple 2x2 averaging to compute the next mipmap level.
3318 make_1d_mipmap(convertFormat
, border
,
3323 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3324 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3325 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3326 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3327 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3328 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3329 make_2d_mipmap(convertFormat
, border
,
3330 srcWidth
, srcHeight
, srcData
,
3331 dstWidth
, dstHeight
, dstData
);
3334 make_3d_mipmap(convertFormat
, border
,
3335 srcWidth
, srcHeight
, srcDepth
, srcData
,
3336 dstWidth
, dstHeight
, dstDepth
, dstData
);
3338 case GL_TEXTURE_RECTANGLE_NV
:
3339 /* no mipmaps, do nothing */
3342 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3346 if (dstImage
->IsCompressed
) {
3348 /* compress image from dstData into dstImage->Data */
3349 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3350 GLint dstRowStride
= _mesa_compressed_row_stride(srcImage
->IntFormat
,
3352 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3353 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->Format
,
3354 dstImage
->TexFormat
,
3356 0, 0, 0, /* dstX/Y/Zoffset */
3357 dstRowStride
, 0, /* strides */
3358 dstWidth
, dstHeight
, 1, /* size */
3359 srcFormat
, CHAN_TYPE
,
3360 dstData
, /* src data, actually */
3361 &ctx
->DefaultPacking
);
3362 /* swap src and dest pointers */
3363 temp
= (GLubyte
*) srcData
;
3368 } /* loop over mipmap levels */
3373 * Helper function for drivers which need to rescale texture images to
3374 * certain aspect ratios.
3375 * Nearest filtering only (for broken hardware that can't support
3376 * all aspect ratios). This can be made a lot faster, but I don't
3377 * really care enough...
3379 void _mesa_rescale_teximage2d( GLuint bytesPerPixel
, GLuint dstRowStride
,
3380 GLint srcWidth
, GLint srcHeight
,
3381 GLint dstWidth
, GLint dstHeight
,
3382 const GLvoid
*srcImage
, GLvoid
*dstImage
)
3386 #define INNER_LOOP( TYPE, HOP, WOP ) \
3387 for ( row = 0 ; row < dstHeight ; row++ ) { \
3388 GLint srcRow = row HOP hScale; \
3389 for ( col = 0 ; col < dstWidth ; col++ ) { \
3390 GLint srcCol = col WOP wScale; \
3391 dst[col] = src[srcRow * srcWidth + srcCol]; \
3393 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3396 #define RESCALE_IMAGE( TYPE ) \
3398 const TYPE *src = (const TYPE *)srcImage; \
3399 TYPE *dst = (TYPE *)dstImage; \
3401 if ( srcHeight <= dstHeight ) { \
3402 const GLint hScale = dstHeight / srcHeight; \
3403 if ( srcWidth <= dstWidth ) { \
3404 const GLint wScale = dstWidth / srcWidth; \
3405 INNER_LOOP( TYPE, /, / ); \
3408 const GLint wScale = srcWidth / dstWidth; \
3409 INNER_LOOP( TYPE, /, * ); \
3413 const GLint hScale = srcHeight / dstHeight; \
3414 if ( srcWidth <= dstWidth ) { \
3415 const GLint wScale = dstWidth / srcWidth; \
3416 INNER_LOOP( TYPE, *, / ); \
3419 const GLint wScale = srcWidth / dstWidth; \
3420 INNER_LOOP( TYPE, *, * ); \
3425 switch ( bytesPerPixel
) {
3427 RESCALE_IMAGE( GLuint
);
3431 RESCALE_IMAGE( GLushort
);
3435 RESCALE_IMAGE( GLubyte
);
3438 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3444 * Upscale an image by replication, not (typical) stretching.
3445 * We use this when the image width or height is less than a
3446 * certain size (4, 8) and we need to upscale an image.
3449 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
3450 GLsizei outWidth
, GLsizei outHeight
,
3451 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
3456 ASSERT(outWidth
>= inWidth
);
3457 ASSERT(outHeight
>= inHeight
);
3459 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
3460 ASSERT((outWidth
& 3) == 0);
3461 ASSERT((outHeight
& 3) == 0);
3464 for (i
= 0; i
< outHeight
; i
++) {
3465 const GLint ii
= i
% inHeight
;
3466 for (j
= 0; j
< outWidth
; j
++) {
3467 const GLint jj
= j
% inWidth
;
3468 for (k
= 0; k
< comps
; k
++) {
3469 dest
[(i
* outWidth
+ j
) * comps
+ k
]
3470 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];