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
)
705 ASSERT(dstFormat
== &_mesa_texformat_depth_component_float32
);
706 ASSERT(dstFormat
->TexelBytes
== sizeof(GLfloat
));
708 if (!ctx
->_ImageTransferState
&&
709 !srcPacking
->SwapBytes
&&
710 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
711 srcFormat
== GL_DEPTH_COMPONENT
&&
712 srcType
== GL_FLOAT
) {
713 /* simple memcpy path */
714 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
715 dstRowStride
, dstImageStride
,
716 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
717 srcAddr
, srcPacking
);
721 GLubyte
*dstImage
= (GLubyte
*) dstAddr
722 + dstZoffset
* dstImageStride
723 + dstYoffset
* dstRowStride
724 + dstXoffset
* dstFormat
->TexelBytes
;
726 for (img
= 0; img
< srcDepth
; img
++) {
727 GLubyte
*dstRow
= dstImage
;
728 for (row
= 0; row
< srcHeight
; row
++) {
729 const GLvoid
*src
= _mesa_image_address(srcPacking
,
730 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
731 _mesa_unpack_depth_span(ctx
, srcWidth
, (GLfloat
*) dstRow
,
732 srcType
, src
, srcPacking
);
733 dstRow
+= dstRowStride
;
735 dstImage
+= dstImageStride
;
743 * Store a 16-bit integer depth component texture image.
746 _mesa_texstore_depth_component16(STORE_PARAMS
)
749 ASSERT(dstFormat
== &_mesa_texformat_depth_component16
);
750 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
752 if (!ctx
->_ImageTransferState
&&
753 !srcPacking
->SwapBytes
&&
754 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
755 srcFormat
== GL_DEPTH_COMPONENT
&&
756 srcType
== GL_UNSIGNED_SHORT
) {
757 /* simple memcpy path */
758 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
759 dstRowStride
, dstImageStride
,
760 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
761 srcAddr
, srcPacking
);
765 GLubyte
*dstImage
= (GLubyte
*) dstAddr
766 + dstZoffset
* dstImageStride
767 + dstYoffset
* dstRowStride
768 + dstXoffset
* dstFormat
->TexelBytes
;
770 for (img
= 0; img
< srcDepth
; img
++) {
771 GLubyte
*dstRow
= dstImage
;
772 for (row
= 0; row
< srcHeight
; row
++) {
773 GLfloat depthTemp
[MAX_WIDTH
];
774 const GLvoid
*src
= _mesa_image_address(srcPacking
,
775 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
776 GLushort
*dst16
= (GLushort
*) dstRow
;
777 _mesa_unpack_depth_span(ctx
, srcWidth
, depthTemp
,
778 srcType
, src
, srcPacking
);
779 for (col
= 0; col
< srcWidth
; col
++) {
780 dst16
[col
] = (GLushort
) (depthTemp
[col
] * 65535.0F
);
782 dstRow
+= dstRowStride
;
784 dstImage
+= dstImageStride
;
792 * Store an rgb565 or rgb565_rev texture image.
795 _mesa_texstore_rgb565(STORE_PARAMS
)
797 ASSERT(dstFormat
== &_mesa_texformat_rgb565
||
798 dstFormat
== &_mesa_texformat_rgb565_rev
);
799 ASSERT(dstFormat
->TexelBytes
== 2);
801 if (!ctx
->_ImageTransferState
&&
802 !srcPacking
->SwapBytes
&&
803 dstFormat
== &_mesa_texformat_rgb565
&&
804 baseInternalFormat
== GL_RGB
&&
805 srcFormat
== GL_RGB
&&
806 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
807 /* simple memcpy path */
808 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
809 dstRowStride
, dstImageStride
,
810 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
811 srcAddr
, srcPacking
);
813 else if (!ctx
->_ImageTransferState
&&
814 !srcPacking
->SwapBytes
&&
815 baseInternalFormat
== GL_RGB
&&
816 srcFormat
== GL_RGB
&&
817 srcType
== GL_UNSIGNED_BYTE
&&
819 /* do optimized tex store */
820 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
822 const GLubyte
*src
= (const GLubyte
*)
823 _mesa_image_address(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
824 srcFormat
, srcType
, 0, 0, 0);
825 GLubyte
*dst
= (GLubyte
*) dstAddr
826 + dstZoffset
* dstImageStride
827 + dstYoffset
* dstRowStride
828 + dstXoffset
* dstFormat
->TexelBytes
;
830 for (row
= 0; row
< srcHeight
; row
++) {
831 const GLubyte
*srcUB
= (const GLubyte
*) src
;
832 GLushort
*dstUS
= (GLushort
*) dst
;
833 /* check for byteswapped format */
834 if (dstFormat
== &_mesa_texformat_rgb565
) {
835 for (col
= 0; col
< srcWidth
; col
++) {
836 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
841 for (col
= 0; col
< srcWidth
; col
++) {
842 dstUS
[col
] = PACK_COLOR_565_REV( srcUB
[0], srcUB
[1], srcUB
[2] );
852 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
854 dstFormat
->BaseFormat
,
855 srcWidth
, srcHeight
, srcDepth
,
856 srcFormat
, srcType
, srcAddr
,
858 const GLchan
*src
= tempImage
;
859 GLubyte
*dstImage
= (GLubyte
*) dstAddr
860 + dstZoffset
* dstImageStride
861 + dstYoffset
* dstRowStride
862 + dstXoffset
* dstFormat
->TexelBytes
;
866 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
867 for (img
= 0; img
< srcDepth
; img
++) {
868 GLubyte
*dstRow
= dstImage
;
869 for (row
= 0; row
< srcHeight
; row
++) {
870 GLushort
*dstUS
= (GLushort
*) dstRow
;
871 /* check for byteswapped format */
872 if (dstFormat
== &_mesa_texformat_rgb565
) {
873 for (col
= 0; col
< srcWidth
; col
++) {
874 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
875 CHAN_TO_UBYTE(src
[GCOMP
]),
876 CHAN_TO_UBYTE(src
[BCOMP
]) );
881 for (col
= 0; col
< srcWidth
; col
++) {
882 dstUS
[col
] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
883 CHAN_TO_UBYTE(src
[GCOMP
]),
884 CHAN_TO_UBYTE(src
[BCOMP
]) );
888 dstRow
+= dstRowStride
;
890 dstImage
+= dstImageStride
;
892 _mesa_free((void *) tempImage
);
899 _mesa_texstore_rgba8888(STORE_PARAMS
)
901 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
||
902 dstFormat
== &_mesa_texformat_rgba8888_rev
);
903 ASSERT(dstFormat
->TexelBytes
== 4);
905 if (!ctx
->_ImageTransferState
&&
906 !srcPacking
->SwapBytes
&&
907 dstFormat
== &_mesa_texformat_rgba8888
&&
908 baseInternalFormat
== GL_RGBA
&&
909 ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
910 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
))) {
911 /* simple memcpy path */
912 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
913 dstRowStride
, dstImageStride
,
914 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
915 srcAddr
, srcPacking
);
919 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
921 dstFormat
->BaseFormat
,
922 srcWidth
, srcHeight
, srcDepth
,
923 srcFormat
, srcType
, srcAddr
,
925 const GLchan
*src
= tempImage
;
926 GLubyte
*dstImage
= (GLubyte
*) dstAddr
927 + dstZoffset
* dstImageStride
928 + dstYoffset
* dstRowStride
929 + dstXoffset
* dstFormat
->TexelBytes
;
933 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
934 for (img
= 0; img
< srcDepth
; img
++) {
935 GLubyte
*dstRow
= dstImage
;
936 for (row
= 0; row
< srcHeight
; row
++) {
937 GLuint
*dstUI
= (GLuint
*) dstRow
;
938 if (dstFormat
== &_mesa_texformat_rgba8888
) {
939 for (col
= 0; col
< srcWidth
; col
++) {
940 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
941 CHAN_TO_UBYTE(src
[GCOMP
]),
942 CHAN_TO_UBYTE(src
[BCOMP
]),
943 CHAN_TO_UBYTE(src
[ACOMP
]) );
948 for (col
= 0; col
< srcWidth
; col
++) {
949 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[RCOMP
]),
950 CHAN_TO_UBYTE(src
[GCOMP
]),
951 CHAN_TO_UBYTE(src
[BCOMP
]),
952 CHAN_TO_UBYTE(src
[ACOMP
]) );
956 dstRow
+= dstRowStride
;
958 dstImage
+= dstImageStride
;
960 _mesa_free((void *) tempImage
);
967 _mesa_texstore_argb8888(STORE_PARAMS
)
970 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
972 ASSERT(dstFormat
== &_mesa_texformat_argb8888
||
973 dstFormat
== &_mesa_texformat_argb8888_rev
);
974 ASSERT(dstFormat
->TexelBytes
== 4);
976 if (!ctx
->_ImageTransferState
&&
977 !srcPacking
->SwapBytes
&&
978 dstFormat
== &_mesa_texformat_argb8888
&&
979 baseInternalFormat
== GL_RGBA
&&
980 srcFormat
== GL_BGRA
&&
981 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
982 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
983 /* simple memcpy path (little endian) */
984 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
985 dstRowStride
, dstImageStride
,
986 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
987 srcAddr
, srcPacking
);
989 else if (!ctx
->_ImageTransferState
&&
990 !srcPacking
->SwapBytes
&&
991 dstFormat
== &_mesa_texformat_argb8888_rev
&&
992 baseInternalFormat
== GL_RGBA
&&
993 srcFormat
== GL_BGRA
&&
994 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
995 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
996 /* simple memcpy path (big endian) */
997 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
998 dstRowStride
, dstImageStride
,
999 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1000 srcAddr
, srcPacking
);
1004 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1006 dstFormat
->BaseFormat
,
1007 srcWidth
, srcHeight
, srcDepth
,
1008 srcFormat
, srcType
, srcAddr
,
1010 const GLchan
*src
= tempImage
;
1011 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1012 + dstZoffset
* dstImageStride
1013 + dstYoffset
* dstRowStride
1014 + dstXoffset
* dstFormat
->TexelBytes
;
1015 GLint img
, row
, col
;
1018 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1019 for (img
= 0; img
< srcDepth
; img
++) {
1020 GLubyte
*dstRow
= dstImage
;
1021 for (row
= 0; row
< srcHeight
; row
++) {
1022 GLuint
*dstUI
= (GLuint
*) dstRow
;
1023 if (dstFormat
== &_mesa_texformat_argb8888
) {
1024 for (col
= 0; col
< srcWidth
; col
++) {
1025 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1026 CHAN_TO_UBYTE(src
[RCOMP
]),
1027 CHAN_TO_UBYTE(src
[GCOMP
]),
1028 CHAN_TO_UBYTE(src
[BCOMP
]) );
1033 for (col
= 0; col
< srcWidth
; col
++) {
1034 dstUI
[col
] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1035 CHAN_TO_UBYTE(src
[RCOMP
]),
1036 CHAN_TO_UBYTE(src
[GCOMP
]),
1037 CHAN_TO_UBYTE(src
[BCOMP
]) );
1041 dstRow
+= dstRowStride
;
1043 dstImage
+= dstImageStride
;
1045 _mesa_free((void *) tempImage
);
1052 _mesa_texstore_rgb888(STORE_PARAMS
)
1054 const GLuint ui
= 1;
1055 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1057 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1058 ASSERT(dstFormat
->TexelBytes
== 3);
1060 if (!ctx
->_ImageTransferState
&&
1061 !srcPacking
->SwapBytes
&&
1062 baseInternalFormat
== GL_RGB
&&
1063 srcFormat
== GL_BGR
&&
1064 srcType
== GL_UNSIGNED_BYTE
&&
1066 /* simple memcpy path */
1067 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1068 dstRowStride
, dstImageStride
,
1069 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1070 srcAddr
, srcPacking
);
1072 else if (!ctx
->_ImageTransferState
&&
1073 !srcPacking
->SwapBytes
&&
1074 srcFormat
== GL_RGBA
&&
1075 srcType
== GL_UNSIGNED_BYTE
) {
1076 /* extract RGB from RGBA */
1078 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1079 + dstZoffset
* dstImageStride
1080 + dstYoffset
* dstRowStride
1081 + dstXoffset
* dstFormat
->TexelBytes
;
1082 for (img
= 0; img
< srcDepth
; img
++) {
1083 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1084 srcWidth
, srcFormat
, srcType
);
1085 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
1086 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1087 GLubyte
*dstRow
= dstImage
;
1088 for (row
= 0; row
< srcHeight
; row
++) {
1089 for (col
= 0; col
< srcWidth
; col
++) {
1090 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1091 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1092 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1094 dstRow
+= dstRowStride
;
1095 srcRow
+= srcRowStride
;
1097 dstImage
+= dstImageStride
;
1102 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1104 dstFormat
->BaseFormat
,
1105 srcWidth
, srcHeight
, srcDepth
,
1106 srcFormat
, srcType
, srcAddr
,
1108 const GLchan
*src
= (const GLchan
*) tempImage
;
1109 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1110 + dstZoffset
* dstImageStride
1111 + dstYoffset
* dstRowStride
1112 + dstXoffset
* dstFormat
->TexelBytes
;
1113 GLint img
, row
, col
;
1116 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1117 for (img
= 0; img
< srcDepth
; img
++) {
1118 GLubyte
*dstRow
= dstImage
;
1119 for (row
= 0; row
< srcHeight
; row
++) {
1122 for (col
= 0; col
< srcWidth
; col
++) {
1123 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1124 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1125 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1130 for (col
= 0; col
< srcWidth
; col
++) {
1131 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1132 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1133 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1138 for (col
= 0; col
< srcWidth
; col
++) {
1139 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1140 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1141 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1145 dstRow
+= dstRowStride
;
1147 dstImage
+= dstImageStride
;
1149 _mesa_free((void *) tempImage
);
1156 _mesa_texstore_bgr888(STORE_PARAMS
)
1158 const GLuint ui
= 1;
1159 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1161 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1162 ASSERT(dstFormat
->TexelBytes
== 3);
1164 if (!ctx
->_ImageTransferState
&&
1165 !srcPacking
->SwapBytes
&&
1166 baseInternalFormat
== GL_RGB
&&
1167 srcFormat
== GL_RGB
&&
1168 srcType
== GL_UNSIGNED_BYTE
&&
1170 /* simple memcpy path */
1171 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1172 dstRowStride
, dstImageStride
,
1173 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1174 srcAddr
, srcPacking
);
1176 else if (!ctx
->_ImageTransferState
&&
1177 !srcPacking
->SwapBytes
&&
1178 srcFormat
== GL_RGBA
&&
1179 srcType
== GL_UNSIGNED_BYTE
) {
1180 /* extract BGR from RGBA */
1182 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1183 + dstZoffset
* dstImageStride
1184 + dstYoffset
* dstRowStride
1185 + dstXoffset
* dstFormat
->TexelBytes
;
1186 for (img
= 0; img
< srcDepth
; img
++) {
1187 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1188 srcWidth
, srcFormat
, srcType
);
1189 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
1190 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1191 GLubyte
*dstRow
= dstImage
;
1192 for (row
= 0; row
< srcHeight
; row
++) {
1193 for (col
= 0; col
< srcWidth
; col
++) {
1194 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1195 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1196 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1198 dstRow
+= dstRowStride
;
1199 srcRow
+= srcRowStride
;
1201 dstImage
+= dstImageStride
;
1206 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1208 dstFormat
->BaseFormat
,
1209 srcWidth
, srcHeight
, srcDepth
,
1210 srcFormat
, srcType
, srcAddr
,
1212 const GLchan
*src
= (const GLchan
*) tempImage
;
1213 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1214 + dstZoffset
* dstImageStride
1215 + dstYoffset
* dstRowStride
1216 + dstXoffset
* dstFormat
->TexelBytes
;
1217 GLint img
, row
, col
;
1220 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1221 for (img
= 0; img
< srcDepth
; img
++) {
1222 GLubyte
*dstRow
= dstImage
;
1223 for (row
= 0; row
< srcHeight
; row
++) {
1224 for (col
= 0; col
< srcWidth
; col
++) {
1225 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1226 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1227 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1230 dstRow
+= dstRowStride
;
1232 dstImage
+= dstImageStride
;
1234 _mesa_free((void *) tempImage
);
1241 _mesa_texstore_argb4444(STORE_PARAMS
)
1243 ASSERT(dstFormat
== &_mesa_texformat_argb4444
||
1244 dstFormat
== &_mesa_texformat_argb4444_rev
);
1245 ASSERT(dstFormat
->TexelBytes
== 2);
1247 if (!ctx
->_ImageTransferState
&&
1248 !srcPacking
->SwapBytes
&&
1249 dstFormat
== &_mesa_texformat_argb4444
&&
1250 baseInternalFormat
== GL_RGBA
&&
1251 srcFormat
== GL_BGRA
&&
1252 srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
1253 /* simple memcpy path */
1254 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1255 dstRowStride
, dstImageStride
,
1256 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1257 srcAddr
, srcPacking
);
1261 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1263 dstFormat
->BaseFormat
,
1264 srcWidth
, srcHeight
, srcDepth
,
1265 srcFormat
, srcType
, srcAddr
,
1267 const GLchan
*src
= tempImage
;
1268 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1269 + dstZoffset
* dstImageStride
1270 + dstYoffset
* dstRowStride
1271 + dstXoffset
* dstFormat
->TexelBytes
;
1272 GLint img
, row
, col
;
1275 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1276 for (img
= 0; img
< srcDepth
; img
++) {
1277 GLubyte
*dstRow
= dstImage
;
1278 for (row
= 0; row
< srcHeight
; row
++) {
1279 GLushort
*dstUS
= (GLushort
*) dstRow
;
1280 if (dstFormat
== &_mesa_texformat_argb4444
) {
1281 for (col
= 0; col
< srcWidth
; col
++) {
1282 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1283 CHAN_TO_UBYTE(src
[RCOMP
]),
1284 CHAN_TO_UBYTE(src
[GCOMP
]),
1285 CHAN_TO_UBYTE(src
[BCOMP
]) );
1290 for (col
= 0; col
< srcWidth
; col
++) {
1291 dstUS
[col
] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1292 CHAN_TO_UBYTE(src
[RCOMP
]),
1293 CHAN_TO_UBYTE(src
[GCOMP
]),
1294 CHAN_TO_UBYTE(src
[BCOMP
]) );
1298 dstRow
+= dstRowStride
;
1300 dstImage
+= dstImageStride
;
1302 _mesa_free((void *) tempImage
);
1310 _mesa_texstore_argb1555(STORE_PARAMS
)
1312 ASSERT(dstFormat
== &_mesa_texformat_argb1555
||
1313 dstFormat
== &_mesa_texformat_argb1555_rev
);
1314 ASSERT(dstFormat
->TexelBytes
== 2);
1316 if (!ctx
->_ImageTransferState
&&
1317 !srcPacking
->SwapBytes
&&
1318 dstFormat
== &_mesa_texformat_argb1555
&&
1319 baseInternalFormat
== GL_RGBA
&&
1320 srcFormat
== GL_BGRA
&&
1321 srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
1322 /* simple memcpy path */
1323 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1324 dstRowStride
, dstImageStride
,
1325 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1326 srcAddr
, srcPacking
);
1330 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1332 dstFormat
->BaseFormat
,
1333 srcWidth
, srcHeight
, srcDepth
,
1334 srcFormat
, srcType
, srcAddr
,
1336 const GLchan
*src
=tempImage
;
1337 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1338 + dstZoffset
* dstImageStride
1339 + dstYoffset
* dstRowStride
1340 + dstXoffset
* dstFormat
->TexelBytes
;
1341 GLint img
, row
, col
;
1344 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1345 for (img
= 0; img
< srcDepth
; img
++) {
1346 GLubyte
*dstRow
= dstImage
;
1347 for (row
= 0; row
< srcHeight
; row
++) {
1348 GLushort
*dstUS
= (GLushort
*) dstRow
;
1349 if (dstFormat
== &_mesa_texformat_argb1555
) {
1350 for (col
= 0; col
< srcWidth
; col
++) {
1351 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1352 CHAN_TO_UBYTE(src
[RCOMP
]),
1353 CHAN_TO_UBYTE(src
[GCOMP
]),
1354 CHAN_TO_UBYTE(src
[BCOMP
]) );
1359 for (col
= 0; col
< srcWidth
; col
++) {
1360 dstUS
[col
] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src
[ACOMP
]),
1361 CHAN_TO_UBYTE(src
[RCOMP
]),
1362 CHAN_TO_UBYTE(src
[GCOMP
]),
1363 CHAN_TO_UBYTE(src
[BCOMP
]) );
1367 dstRow
+= dstRowStride
;
1369 dstImage
+= dstImageStride
;
1371 _mesa_free((void *) tempImage
);
1378 _mesa_texstore_al88(STORE_PARAMS
)
1380 const GLuint ui
= 1;
1381 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1383 ASSERT(dstFormat
== &_mesa_texformat_al88
||
1384 dstFormat
== &_mesa_texformat_al88_rev
);
1385 ASSERT(dstFormat
->TexelBytes
== 2);
1387 if (!ctx
->_ImageTransferState
&&
1388 !srcPacking
->SwapBytes
&&
1389 dstFormat
== &_mesa_texformat_al88
&&
1390 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1391 srcFormat
== GL_LUMINANCE_ALPHA
&&
1392 srcType
== GL_UNSIGNED_BYTE
&&
1394 /* simple memcpy path */
1395 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1396 dstRowStride
, dstImageStride
,
1397 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1398 srcAddr
, srcPacking
);
1402 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1404 dstFormat
->BaseFormat
,
1405 srcWidth
, srcHeight
, srcDepth
,
1406 srcFormat
, srcType
, srcAddr
,
1408 const GLchan
*src
= tempImage
;
1409 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1410 + dstZoffset
* dstImageStride
1411 + dstYoffset
* dstRowStride
1412 + dstXoffset
* dstFormat
->TexelBytes
;
1413 GLint img
, row
, col
;
1416 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1417 for (img
= 0; img
< srcDepth
; img
++) {
1418 GLubyte
*dstRow
= dstImage
;
1419 for (row
= 0; row
< srcHeight
; row
++) {
1420 GLushort
*dstUS
= (GLushort
*) dstRow
;
1421 if (dstFormat
== &_mesa_texformat_al88
) {
1422 for (col
= 0; col
< srcWidth
; col
++) {
1423 /* src[0] is luminance, src[1] is alpha */
1424 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[1]),
1425 CHAN_TO_UBYTE(src
[0]) );
1430 for (col
= 0; col
< srcWidth
; col
++) {
1431 /* src[0] is luminance, src[1] is alpha */
1432 dstUS
[col
] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src
[1]),
1433 CHAN_TO_UBYTE(src
[0]) );
1437 dstRow
+= dstRowStride
;
1439 dstImage
+= dstImageStride
;
1441 _mesa_free((void *) tempImage
);
1448 _mesa_texstore_rgb332(STORE_PARAMS
)
1450 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1451 ASSERT(dstFormat
->TexelBytes
== 1);
1453 if (!ctx
->_ImageTransferState
&&
1454 !srcPacking
->SwapBytes
&&
1455 baseInternalFormat
== GL_RGB
&&
1456 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1457 /* simple memcpy path */
1458 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1459 dstRowStride
, dstImageStride
,
1460 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1461 srcAddr
, srcPacking
);
1465 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1467 dstFormat
->BaseFormat
,
1468 srcWidth
, srcHeight
, srcDepth
,
1469 srcFormat
, srcType
, srcAddr
,
1471 const GLchan
*src
= tempImage
;
1472 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1473 + dstZoffset
* dstImageStride
1474 + dstYoffset
* dstRowStride
1475 + dstXoffset
* dstFormat
->TexelBytes
;
1476 GLint img
, row
, col
;
1479 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1480 for (img
= 0; img
< srcDepth
; img
++) {
1481 GLubyte
*dstRow
= dstImage
;
1482 for (row
= 0; row
< srcHeight
; row
++) {
1483 for (col
= 0; col
< srcWidth
; col
++) {
1484 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1485 CHAN_TO_UBYTE(src
[GCOMP
]),
1486 CHAN_TO_UBYTE(src
[BCOMP
]) );
1489 dstRow
+= dstRowStride
;
1491 dstImage
+= dstImageStride
;
1493 _mesa_free((void *) tempImage
);
1500 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1503 _mesa_texstore_a8(STORE_PARAMS
)
1505 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1506 dstFormat
== &_mesa_texformat_l8
||
1507 dstFormat
== &_mesa_texformat_i8
);
1508 ASSERT(dstFormat
->TexelBytes
== 1);
1510 if (!ctx
->_ImageTransferState
&&
1511 !srcPacking
->SwapBytes
&&
1512 baseInternalFormat
== srcFormat
&&
1513 srcType
== GL_UNSIGNED_BYTE
) {
1514 /* simple memcpy path */
1515 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1516 dstRowStride
, dstImageStride
,
1517 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1518 srcAddr
, srcPacking
);
1522 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1524 dstFormat
->BaseFormat
,
1525 srcWidth
, srcHeight
, srcDepth
,
1526 srcFormat
, srcType
, srcAddr
,
1528 const GLchan
*src
= tempImage
;
1529 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1530 + dstZoffset
* dstImageStride
1531 + dstYoffset
* dstRowStride
1532 + dstXoffset
* dstFormat
->TexelBytes
;
1533 GLint img
, row
, col
;
1536 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1537 for (img
= 0; img
< srcDepth
; img
++) {
1538 GLubyte
*dstRow
= dstImage
;
1539 for (row
= 0; row
< srcHeight
; row
++) {
1540 for (col
= 0; col
< srcWidth
; col
++) {
1541 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1543 dstRow
+= dstRowStride
;
1546 dstImage
+= dstImageStride
;
1548 _mesa_free((void *) tempImage
);
1556 _mesa_texstore_ci8(STORE_PARAMS
)
1558 (void) dims
; (void) baseInternalFormat
;
1559 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1560 ASSERT(dstFormat
->TexelBytes
== 1);
1561 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1563 if (!ctx
->_ImageTransferState
&&
1564 !srcPacking
->SwapBytes
&&
1565 srcFormat
== GL_COLOR_INDEX
&&
1566 srcType
== GL_UNSIGNED_BYTE
) {
1567 /* simple memcpy path */
1568 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1569 dstRowStride
, dstImageStride
,
1570 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1571 srcAddr
, srcPacking
);
1575 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1576 + dstZoffset
* dstImageStride
1577 + dstYoffset
* dstRowStride
1578 + dstXoffset
* dstFormat
->TexelBytes
;
1580 for (img
= 0; img
< srcDepth
; img
++) {
1581 GLubyte
*dstRow
= dstImage
;
1582 for (row
= 0; row
< srcHeight
; row
++) {
1583 const GLvoid
*src
= _mesa_image_address(srcPacking
,
1584 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1585 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1586 srcType
, src
, srcPacking
,
1587 ctx
->_ImageTransferState
);
1588 dstRow
+= dstRowStride
;
1590 dstImage
+= dstImageStride
;
1598 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1601 _mesa_texstore_ycbcr(STORE_PARAMS
)
1603 const GLuint ui
= 1;
1604 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1605 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
1607 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1608 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1609 ASSERT(dstFormat
->TexelBytes
== 2);
1610 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1611 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1612 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1613 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1614 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1616 /* always just memcpy since no pixel transfer ops apply */
1617 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1618 dstRowStride
, dstImageStride
,
1619 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1620 srcAddr
, srcPacking
);
1622 /* Check if we need byte swapping */
1623 /* XXX the logic here _might_ be wrong */
1624 if (srcPacking
->SwapBytes
^
1625 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1626 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1628 GLushort
*pImage
= (GLushort
*) ((GLubyte
*) dstAddr
1629 + dstZoffset
* dstImageStride
1630 + dstYoffset
* dstRowStride
1631 + dstXoffset
* dstFormat
->TexelBytes
);
1633 for (img
= 0; img
< srcDepth
; img
++) {
1634 GLushort
*pRow
= pImage
;
1635 for (row
= 0; row
< srcHeight
; row
++) {
1636 _mesa_swap2(pRow
, srcWidth
);
1637 pRow
+= dstRowStride
;
1639 pImage
+= dstImageStride
;
1649 * Store an image in any of the formats:
1650 * _mesa_texformat_rgba_float32
1651 * _mesa_texformat_rgb_float32
1652 * _mesa_texformat_alpha_float32
1653 * _mesa_texformat_luminance_float32
1654 * _mesa_texformat_luminance_alpha_float32
1655 * _mesa_texformat_intensity_float32
1658 _mesa_texstore_rgba_float32(STORE_PARAMS
)
1660 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1662 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
1663 dstFormat
== &_mesa_texformat_rgb_float32
||
1664 dstFormat
== &_mesa_texformat_alpha_float32
||
1665 dstFormat
== &_mesa_texformat_luminance_float32
||
1666 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
1667 dstFormat
== &_mesa_texformat_intensity_float32
);
1668 ASSERT(baseInternalFormat
== GL_RGBA
||
1669 baseInternalFormat
== GL_RGB
||
1670 baseInternalFormat
== GL_ALPHA
||
1671 baseInternalFormat
== GL_LUMINANCE
||
1672 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1673 baseInternalFormat
== GL_INTENSITY
);
1674 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
1676 if (!ctx
->_ImageTransferState
&&
1677 !srcPacking
->SwapBytes
&&
1678 baseInternalFormat
== srcFormat
&&
1679 srcType
== GL_FLOAT
) {
1680 /* simple memcpy path */
1681 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1682 dstRowStride
, dstImageStride
,
1683 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1684 srcAddr
, srcPacking
);
1688 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1690 dstFormat
->BaseFormat
,
1691 srcWidth
, srcHeight
, srcDepth
,
1692 srcFormat
, srcType
, srcAddr
,
1694 const GLfloat
*src
= tempImage
;
1696 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1697 + dstZoffset
* dstImageStride
1698 + dstYoffset
* dstRowStride
1699 + dstXoffset
* dstFormat
->TexelBytes
;
1703 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1704 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
1705 for (img
= 0; img
< srcDepth
; img
++) {
1706 GLubyte
*dst
= dstImage
;
1707 for (row
= 0; row
< srcHeight
; row
++) {
1708 _mesa_memcpy(dst
, src
, bytesPerRow
);
1709 dst
+= dstRowStride
;
1710 src
+= srcWidth
* components
;
1712 dstImage
+= dstImageStride
;
1715 _mesa_free((void *) tempImage
);
1722 * As above, but store 16-bit floats.
1725 _mesa_texstore_rgba_float16(STORE_PARAMS
)
1727 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1729 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
1730 dstFormat
== &_mesa_texformat_rgb_float16
||
1731 dstFormat
== &_mesa_texformat_alpha_float16
||
1732 dstFormat
== &_mesa_texformat_luminance_float16
||
1733 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
1734 dstFormat
== &_mesa_texformat_intensity_float16
);
1735 ASSERT(baseInternalFormat
== GL_RGBA
||
1736 baseInternalFormat
== GL_RGB
||
1737 baseInternalFormat
== GL_ALPHA
||
1738 baseInternalFormat
== GL_LUMINANCE
||
1739 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1740 baseInternalFormat
== GL_INTENSITY
);
1741 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
1743 if (!ctx
->_ImageTransferState
&&
1744 !srcPacking
->SwapBytes
&&
1745 baseInternalFormat
== srcFormat
&&
1746 srcType
== GL_HALF_FLOAT_ARB
) {
1747 /* simple memcpy path */
1748 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1749 dstRowStride
, dstImageStride
,
1750 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1751 srcAddr
, srcPacking
);
1755 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1757 dstFormat
->BaseFormat
,
1758 srcWidth
, srcHeight
, srcDepth
,
1759 srcFormat
, srcType
, srcAddr
,
1761 const GLfloat
*src
= tempImage
;
1762 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1763 + dstZoffset
* dstImageStride
1764 + dstYoffset
* dstRowStride
1765 + dstXoffset
* dstFormat
->TexelBytes
;
1769 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1770 for (img
= 0; img
< srcDepth
; img
++) {
1771 GLubyte
*dstRow
= dstImage
;
1772 for (row
= 0; row
< srcHeight
; row
++) {
1773 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
1775 for (i
= 0; i
< srcWidth
* components
; i
++) {
1776 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
1778 dstRow
+= dstRowStride
;
1779 src
+= srcWidth
* components
;
1781 dstImage
+= dstImageStride
;
1784 _mesa_free((void *) tempImage
);
1792 * Validate acces to a PBO for texture data.
1794 * \todo If the PBO is really resident in VRAM, this won't work; the
1795 * device driver should check for that and do the right thing.
1797 static const GLvoid
*
1798 validate_pbo_teximage( GLsizei width
, GLsizei height
, GLsizei depth
,
1799 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1800 const struct gl_pixelstore_attrib
*unpack
)
1802 if (unpack
->BufferObj
->Name
== 0) {
1806 else if (_mesa_validate_pbo_access(unpack
, width
, height
, depth
, format
,
1808 return ADD_POINTERS(unpack
->BufferObj
->Data
, pixels
);
1816 * Validate that unpacking compressed texture image data from a PBO
1817 * won't go out of bounds.
1819 * \todo If the PBO is really resident in VRAM, this won't work; the
1820 * device driver should check for that and do the right thing.
1822 static const GLvoid
*
1823 validate_pbo_compressed_teximage(GLsizei imageSize
, const GLvoid
*pixels
,
1824 const struct gl_pixelstore_attrib
*packing
)
1826 if (packing
->BufferObj
->Name
== 0) {
1827 /* not using a PBO - return pointer unchanged */
1832 if ((const GLubyte
*) pixels
+ imageSize
>
1833 (const GLubyte
*) packing
->BufferObj
->Size
) {
1834 /* out of bounds read! */
1838 return ADD_POINTERS(packing
->BufferObj
->Data
, pixels
);
1845 * This is the software fallback for Driver.TexImage1D()
1846 * and Driver.CopyTexImage1D().
1849 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
1850 GLint internalFormat
,
1851 GLint width
, GLint border
,
1852 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1853 const struct gl_pixelstore_attrib
*packing
,
1854 struct gl_texture_object
*texObj
,
1855 struct gl_texture_image
*texImage
)
1857 GLint postConvWidth
= width
;
1861 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
1862 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1865 /* choose the texture format */
1866 assert(ctx
->Driver
.ChooseTextureFormat
);
1867 texImage
->TexFormat
= ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
,
1869 assert(texImage
->TexFormat
);
1870 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
1871 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
1873 /* allocate memory */
1874 if (texImage
->IsCompressed
)
1875 sizeInBytes
= texImage
->CompressedSize
;
1877 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
1878 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
1879 if (!texImage
->Data
) {
1880 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1884 pixels
= validate_pbo_teximage(width
, 1, 1, format
, type
, pixels
, packing
);
1889 const GLint dstRowStride
= 0, dstImageStride
= 0;
1891 ASSERT(texImage
->TexFormat
->StoreImage
);
1892 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
1893 texImage
->TexFormat
,
1895 0, 0, 0, /* dstX/Y/Zoffset */
1896 dstRowStride
, dstImageStride
,
1898 format
, type
, pixels
, packing
);
1900 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1905 /* GL_SGIS_generate_mipmap */
1906 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1907 _mesa_generate_mipmap(ctx
, target
,
1908 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
1915 * This is the software fallback for Driver.TexImage2D()
1916 * and Driver.CopyTexImage2D().
1917 * Reasons why a driver might override this function:
1918 * - Special memory allocation needs
1919 * - Unusual row/image strides
1920 * - Special housekeeping
1923 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
1924 GLint internalFormat
,
1925 GLint width
, GLint height
, GLint border
,
1926 GLenum format
, GLenum type
, const void *pixels
,
1927 const struct gl_pixelstore_attrib
*packing
,
1928 struct gl_texture_object
*texObj
,
1929 struct gl_texture_image
*texImage
)
1931 GLint postConvWidth
= width
, postConvHeight
= height
;
1932 GLint texelBytes
, sizeInBytes
;
1935 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
1936 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
1940 /* choose the texture format */
1941 assert(ctx
->Driver
.ChooseTextureFormat
);
1942 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
1943 internalFormat
, format
, type
);
1944 assert(texImage
->TexFormat
);
1945 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
1946 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
1948 texelBytes
= texImage
->TexFormat
->TexelBytes
;
1950 /* allocate memory */
1951 if (texImage
->IsCompressed
)
1952 sizeInBytes
= texImage
->CompressedSize
;
1954 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
1955 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
1956 if (!texImage
->Data
) {
1957 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1961 pixels
= validate_pbo_teximage(width
, height
, 1,
1962 format
, type
, pixels
, packing
);
1967 GLint dstRowStride
, dstImageStride
= 0;
1969 if (texImage
->IsCompressed
) {
1970 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
1973 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
1975 ASSERT(texImage
->TexFormat
->StoreImage
);
1976 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1977 texImage
->TexFormat
,
1979 0, 0, 0, /* dstX/Y/Zoffset */
1980 dstRowStride
, dstImageStride
,
1982 format
, type
, pixels
, packing
);
1984 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1989 /* GL_SGIS_generate_mipmap */
1990 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1991 _mesa_generate_mipmap(ctx
, target
,
1992 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2000 * This is the software fallback for Driver.TexImage3D()
2001 * and Driver.CopyTexImage3D().
2004 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2005 GLint internalFormat
,
2006 GLint width
, GLint height
, GLint depth
, GLint border
,
2007 GLenum format
, GLenum type
, const void *pixels
,
2008 const struct gl_pixelstore_attrib
*packing
,
2009 struct gl_texture_object
*texObj
,
2010 struct gl_texture_image
*texImage
)
2012 GLint texelBytes
, sizeInBytes
;
2015 /* choose the texture format */
2016 assert(ctx
->Driver
.ChooseTextureFormat
);
2017 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2018 internalFormat
, format
, type
);
2019 assert(texImage
->TexFormat
);
2020 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2021 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2023 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2025 /* allocate memory */
2026 if (texImage
->IsCompressed
)
2027 sizeInBytes
= texImage
->CompressedSize
;
2029 sizeInBytes
= width
* height
* depth
* texelBytes
;
2030 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2031 if (!texImage
->Data
) {
2032 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2036 pixels
= validate_pbo_teximage(width
, height
, depth
,
2037 format
, type
, pixels
, packing
);
2041 /* unpack image, apply transfer ops and store in texImage->Data */
2043 GLint dstRowStride
, dstImageStride
;
2045 if (texImage
->IsCompressed
) {
2046 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2050 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2051 dstImageStride
= dstRowStride
* height
;
2053 ASSERT(texImage
->TexFormat
->StoreImage
);
2054 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2055 texImage
->TexFormat
,
2057 0, 0, 0, /* dstX/Y/Zoffset */
2058 dstRowStride
, dstImageStride
,
2059 width
, height
, depth
,
2060 format
, type
, pixels
, packing
);
2062 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2067 /* GL_SGIS_generate_mipmap */
2068 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2069 _mesa_generate_mipmap(ctx
, target
,
2070 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2079 * This is the software fallback for Driver.TexSubImage1D()
2080 * and Driver.CopyTexSubImage1D().
2083 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2084 GLint xoffset
, GLint width
,
2085 GLenum format
, GLenum type
, const void *pixels
,
2086 const struct gl_pixelstore_attrib
*packing
,
2087 struct gl_texture_object
*texObj
,
2088 struct gl_texture_image
*texImage
)
2090 pixels
= validate_pbo_teximage(width
, 1, 1,
2091 format
, type
, pixels
, packing
);
2096 const GLint dstRowStride
= 0, dstImageStride
= 0;
2098 ASSERT(texImage
->TexFormat
->StoreImage
);
2099 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2100 texImage
->TexFormat
,
2102 xoffset
, 0, 0, /* offsets */
2103 dstRowStride
, dstImageStride
,
2105 format
, type
, pixels
, packing
);
2107 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2112 /* GL_SGIS_generate_mipmap */
2113 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2114 _mesa_generate_mipmap(ctx
, target
,
2115 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2123 * This is the software fallback for Driver.TexSubImage2D()
2124 * and Driver.CopyTexSubImage2D().
2127 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2128 GLint xoffset
, GLint yoffset
,
2129 GLint width
, GLint height
,
2130 GLenum format
, GLenum type
, const void *pixels
,
2131 const struct gl_pixelstore_attrib
*packing
,
2132 struct gl_texture_object
*texObj
,
2133 struct gl_texture_image
*texImage
)
2135 pixels
= validate_pbo_teximage(width
, height
, 1,
2136 format
, type
, pixels
, packing
);
2141 GLint dstRowStride
= 0, dstImageStride
= 0;
2143 if (texImage
->IsCompressed
) {
2144 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2148 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2150 ASSERT(texImage
->TexFormat
->StoreImage
);
2151 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2152 texImage
->TexFormat
,
2154 xoffset
, yoffset
, 0,
2155 dstRowStride
, dstImageStride
,
2157 format
, type
, pixels
, packing
);
2159 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2164 /* GL_SGIS_generate_mipmap */
2165 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2166 _mesa_generate_mipmap(ctx
, target
,
2167 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2174 * This is the software fallback for Driver.TexSubImage3D().
2175 * and Driver.CopyTexSubImage3D().
2178 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2179 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2180 GLint width
, GLint height
, GLint depth
,
2181 GLenum format
, GLenum type
, const void *pixels
,
2182 const struct gl_pixelstore_attrib
*packing
,
2183 struct gl_texture_object
*texObj
,
2184 struct gl_texture_image
*texImage
)
2186 pixels
= validate_pbo_teximage(width
, height
, depth
,
2187 format
, type
, pixels
, packing
);
2192 GLint dstRowStride
, dstImageStride
;
2194 if (texImage
->IsCompressed
) {
2195 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2197 dstImageStride
= 0; /* XXX fix */
2200 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2201 dstImageStride
= dstRowStride
* texImage
->Height
;
2203 ASSERT(texImage
->TexFormat
->StoreImage
);
2204 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2205 texImage
->TexFormat
,
2207 xoffset
, yoffset
, zoffset
,
2208 dstRowStride
, dstImageStride
,
2209 width
, height
, depth
,
2210 format
, type
, pixels
, packing
);
2212 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2217 /* GL_SGIS_generate_mipmap */
2218 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2219 _mesa_generate_mipmap(ctx
, target
,
2220 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2227 * Fallback for Driver.CompressedTexImage1D()
2230 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2231 GLint internalFormat
,
2232 GLint width
, GLint border
,
2233 GLsizei imageSize
, const GLvoid
*data
,
2234 struct gl_texture_object
*texObj
,
2235 struct gl_texture_image
*texImage
)
2237 /* this space intentionally left blank */
2239 (void) target
; (void) level
;
2240 (void) internalFormat
;
2241 (void) width
; (void) border
;
2242 (void) imageSize
; (void) data
;
2250 * Fallback for Driver.CompressedTexImage2D()
2253 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2254 GLint internalFormat
,
2255 GLint width
, GLint height
, GLint border
,
2256 GLsizei imageSize
, const GLvoid
*data
,
2257 struct gl_texture_object
*texObj
,
2258 struct gl_texture_image
*texImage
)
2260 (void) width
; (void) height
; (void) border
;
2262 /* This is pretty simple, basically just do a memcpy without worrying
2263 * about the usual image unpacking or image transfer operations.
2267 ASSERT(texImage
->Width
> 0);
2268 ASSERT(texImage
->Height
> 0);
2269 ASSERT(texImage
->Depth
== 1);
2270 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2272 /* choose the texture format */
2273 assert(ctx
->Driver
.ChooseTextureFormat
);
2274 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2275 internalFormat
, 0, 0);
2276 assert(texImage
->TexFormat
);
2277 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2278 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2280 /* allocate storage */
2281 texImage
->Data
= MESA_PBUFFER_ALLOC(imageSize
);
2282 if (!texImage
->Data
) {
2283 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2287 data
= validate_pbo_compressed_teximage(imageSize
, data
, &ctx
->Unpack
);
2292 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2293 MEMCPY(texImage
->Data
, data
, imageSize
);
2295 /* GL_SGIS_generate_mipmap */
2296 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2297 _mesa_generate_mipmap(ctx
, target
,
2298 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2306 * Fallback for Driver.CompressedTexImage3D()
2309 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2310 GLint internalFormat
,
2311 GLint width
, GLint height
, GLint depth
,
2313 GLsizei imageSize
, const GLvoid
*data
,
2314 struct gl_texture_object
*texObj
,
2315 struct gl_texture_image
*texImage
)
2317 /* this space intentionally left blank */
2319 (void) target
; (void) level
;
2320 (void) internalFormat
;
2321 (void) width
; (void) height
; (void) depth
;
2323 (void) imageSize
; (void) data
;
2331 * Fallback for Driver.CompressedTexSubImage1D()
2334 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2336 GLint xoffset
, GLsizei width
,
2338 GLsizei imageSize
, const GLvoid
*data
,
2339 struct gl_texture_object
*texObj
,
2340 struct gl_texture_image
*texImage
)
2342 /* this space intentionally left blank */
2344 (void) target
; (void) level
;
2345 (void) xoffset
; (void) width
;
2347 (void) imageSize
; (void) data
;
2354 * Fallback for Driver.CompressedTexSubImage2D()
2357 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2359 GLint xoffset
, GLint yoffset
,
2360 GLsizei width
, GLsizei height
,
2362 GLsizei imageSize
, const GLvoid
*data
,
2363 struct gl_texture_object
*texObj
,
2364 struct gl_texture_image
*texImage
)
2366 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2372 /* these should have been caught sooner */
2373 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2374 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2375 ASSERT((xoffset
& 3) == 0);
2376 ASSERT((yoffset
& 3) == 0);
2378 data
= validate_pbo_compressed_teximage(imageSize
, data
, &ctx
->Unpack
);
2382 srcRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
, width
);
2383 src
= (const GLubyte
*) data
;
2385 destRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2387 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2388 texImage
->IntFormat
,
2390 (GLubyte
*) texImage
->Data
);
2392 bytesPerRow
= srcRowStride
;
2395 for (i
= 0; i
< rows
; i
++) {
2396 MEMCPY(dest
, src
, bytesPerRow
);
2397 dest
+= destRowStride
;
2398 src
+= srcRowStride
;
2401 /* GL_SGIS_generate_mipmap */
2402 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2403 _mesa_generate_mipmap(ctx
, target
,
2404 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2411 * Fallback for Driver.CompressedTexSubImage3D()
2414 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2416 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2417 GLsizei width
, GLsizei height
, GLsizei depth
,
2419 GLsizei imageSize
, const GLvoid
*data
,
2420 struct gl_texture_object
*texObj
,
2421 struct gl_texture_image
*texImage
)
2423 /* this space intentionally left blank */
2425 (void) target
; (void) level
;
2426 (void) xoffset
; (void) yoffset
; (void) zoffset
;
2427 (void) width
; (void) height
; (void) depth
;
2429 (void) imageSize
; (void) data
;
2436 * Average together two rows of a source image to produce a single new
2437 * row in the dest image. It's legal for the two source rows to point
2438 * to the same data. The source width must be equal to either the
2439 * dest width or two times the dest width.
2442 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
2443 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
2444 GLint dstWidth
, GLvoid
*dstRow
)
2446 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
2447 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
2449 /* This assertion is no longer valid with non-power-of-2 textures
2450 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2453 switch (format
->MesaFormat
) {
2454 case MESA_FORMAT_RGBA
:
2457 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
2458 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
2459 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
2460 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2461 i
++, j
+= colStride
, k
+= colStride
) {
2462 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2463 rowB
[j
][0] + rowB
[k
][0]) / 4;
2464 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2465 rowB
[j
][1] + rowB
[k
][1]) / 4;
2466 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2467 rowB
[j
][2] + rowB
[k
][2]) / 4;
2468 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2469 rowB
[j
][3] + rowB
[k
][3]) / 4;
2473 case MESA_FORMAT_RGB
:
2476 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
2477 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
2478 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
2479 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2480 i
++, j
+= colStride
, k
+= colStride
) {
2481 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2482 rowB
[j
][0] + rowB
[k
][0]) / 4;
2483 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2484 rowB
[j
][1] + rowB
[k
][1]) / 4;
2485 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2486 rowB
[j
][2] + rowB
[k
][2]) / 4;
2490 case MESA_FORMAT_ALPHA
:
2491 case MESA_FORMAT_LUMINANCE
:
2492 case MESA_FORMAT_INTENSITY
:
2495 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
2496 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
2497 GLchan
*dst
= (GLchan
*) dstRow
;
2498 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2499 i
++, j
+= colStride
, k
+= colStride
) {
2500 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2504 case MESA_FORMAT_LUMINANCE_ALPHA
:
2507 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
2508 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
2509 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
2510 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2511 i
++, j
+= colStride
, k
+= colStride
) {
2512 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2513 rowB
[j
][0] + rowB
[k
][0]) / 4;
2514 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2515 rowB
[j
][1] + rowB
[k
][1]) / 4;
2519 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32
:
2522 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2523 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2524 GLfloat
*dst
= (GLfloat
*) dstRow
;
2525 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2526 i
++, j
+= colStride
, k
+= colStride
) {
2527 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
2531 case MESA_FORMAT_DEPTH_COMPONENT16
:
2534 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2535 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2536 GLushort
*dst
= (GLushort
*) dstRow
;
2537 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2538 i
++, j
+= colStride
, k
+= colStride
) {
2539 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2543 /* Begin hardware formats */
2544 case MESA_FORMAT_RGBA8888
:
2545 case MESA_FORMAT_RGBA8888_REV
:
2546 case MESA_FORMAT_ARGB8888
:
2547 case MESA_FORMAT_ARGB8888_REV
:
2550 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
2551 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
2552 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
2553 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2554 i
++, j
+= colStride
, k
+= colStride
) {
2555 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2556 rowB
[j
][0] + rowB
[k
][0]) / 4;
2557 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2558 rowB
[j
][1] + rowB
[k
][1]) / 4;
2559 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2560 rowB
[j
][2] + rowB
[k
][2]) / 4;
2561 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2562 rowB
[j
][3] + rowB
[k
][3]) / 4;
2566 case MESA_FORMAT_RGB888
:
2567 case MESA_FORMAT_BGR888
:
2570 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
2571 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
2572 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
2573 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2574 i
++, j
+= colStride
, k
+= colStride
) {
2575 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2576 rowB
[j
][0] + rowB
[k
][0]) / 4;
2577 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2578 rowB
[j
][1] + rowB
[k
][1]) / 4;
2579 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2580 rowB
[j
][2] + rowB
[k
][2]) / 4;
2584 case MESA_FORMAT_RGB565
:
2585 case MESA_FORMAT_RGB565_REV
:
2588 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2589 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2590 GLushort
*dst
= (GLushort
*) dstRow
;
2591 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2592 i
++, j
+= colStride
, k
+= colStride
) {
2593 const GLint rowAr0
= rowA
[j
] & 0x1f;
2594 const GLint rowAr1
= rowA
[k
] & 0x1f;
2595 const GLint rowBr0
= rowB
[j
] & 0x1f;
2596 const GLint rowBr1
= rowB
[k
] & 0x1f;
2597 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
2598 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
2599 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
2600 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
2601 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
2602 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
2603 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
2604 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
2605 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2606 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2607 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2608 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
2612 case MESA_FORMAT_ARGB4444
:
2613 case MESA_FORMAT_ARGB4444_REV
:
2616 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2617 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2618 GLushort
*dst
= (GLushort
*) dstRow
;
2619 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2620 i
++, j
+= colStride
, k
+= colStride
) {
2621 const GLint rowAr0
= rowA
[j
] & 0xf;
2622 const GLint rowAr1
= rowA
[k
] & 0xf;
2623 const GLint rowBr0
= rowB
[j
] & 0xf;
2624 const GLint rowBr1
= rowB
[k
] & 0xf;
2625 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
2626 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
2627 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
2628 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
2629 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
2630 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
2631 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
2632 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
2633 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
2634 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
2635 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
2636 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
2637 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2638 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2639 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2640 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2641 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
2645 case MESA_FORMAT_ARGB1555
:
2646 case MESA_FORMAT_ARGB1555_REV
: /* XXX broken? */
2649 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2650 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2651 GLushort
*dst
= (GLushort
*) dstRow
;
2652 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2653 i
++, j
+= colStride
, k
+= colStride
) {
2654 const GLint rowAr0
= rowA
[j
] & 0x1f;
2655 const GLint rowAr1
= rowA
[k
] & 0x1f;
2656 const GLint rowBr0
= rowB
[j
] & 0x1f;
2657 const GLint rowBr1
= rowB
[k
] & 0xf;
2658 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
2659 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
2660 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
2661 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
2662 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
2663 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
2664 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
2665 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
2666 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
2667 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
2668 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
2669 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
2670 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2671 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2672 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2673 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2674 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
2678 case MESA_FORMAT_AL88
:
2679 case MESA_FORMAT_AL88_REV
:
2682 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
2683 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
2684 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
2685 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2686 i
++, j
+= colStride
, k
+= colStride
) {
2687 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2688 rowB
[j
][0] + rowB
[k
][0]) >> 2;
2689 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2690 rowB
[j
][1] + rowB
[k
][1]) >> 2;
2694 case MESA_FORMAT_RGB332
:
2697 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
2698 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
2699 GLubyte
*dst
= (GLubyte
*) dstRow
;
2700 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2701 i
++, j
+= colStride
, k
+= colStride
) {
2702 const GLint rowAr0
= rowA
[j
] & 0x3;
2703 const GLint rowAr1
= rowA
[k
] & 0x3;
2704 const GLint rowBr0
= rowB
[j
] & 0x3;
2705 const GLint rowBr1
= rowB
[k
] & 0x3;
2706 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
2707 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
2708 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
2709 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
2710 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
2711 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
2712 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
2713 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
2714 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2715 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2716 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2717 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
2721 case MESA_FORMAT_A8
:
2722 case MESA_FORMAT_L8
:
2723 case MESA_FORMAT_I8
:
2724 case MESA_FORMAT_CI8
:
2727 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
2728 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
2729 GLubyte
*dst
= (GLubyte
*) dstRow
;
2730 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2731 i
++, j
+= colStride
, k
+= colStride
) {
2732 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
2736 case MESA_FORMAT_RGBA_FLOAT32
:
2739 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
2740 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
2741 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
2742 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2743 i
++, j
+= colStride
, k
+= colStride
) {
2744 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2745 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2746 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2747 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2748 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2749 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
2750 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2751 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
2755 case MESA_FORMAT_RGBA_FLOAT16
:
2757 GLuint i
, j
, k
, comp
;
2758 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
2759 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
2760 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
2761 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2762 i
++, j
+= colStride
, k
+= colStride
) {
2763 for (comp
= 0; comp
< 4; comp
++) {
2764 GLfloat aj
, ak
, bj
, bk
;
2765 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2766 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2767 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2768 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2769 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2774 case MESA_FORMAT_RGB_FLOAT32
:
2777 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
2778 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
2779 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
2780 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2781 i
++, j
+= colStride
, k
+= colStride
) {
2782 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2783 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2784 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2785 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2786 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2787 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
2791 case MESA_FORMAT_RGB_FLOAT16
:
2793 GLuint i
, j
, k
, comp
;
2794 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
2795 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
2796 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
2797 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2798 i
++, j
+= colStride
, k
+= colStride
) {
2799 for (comp
= 0; comp
< 3; comp
++) {
2800 GLfloat aj
, ak
, bj
, bk
;
2801 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2802 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2803 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2804 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2805 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2810 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
2813 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
2814 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
2815 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
2816 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2817 i
++, j
+= colStride
, k
+= colStride
) {
2818 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2819 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2820 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2821 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2825 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
2827 GLuint i
, j
, k
, comp
;
2828 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
2829 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
2830 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
2831 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2832 i
++, j
+= colStride
, k
+= colStride
) {
2833 for (comp
= 0; comp
< 2; comp
++) {
2834 GLfloat aj
, ak
, bj
, bk
;
2835 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2836 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2837 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2838 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2839 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2844 case MESA_FORMAT_ALPHA_FLOAT32
:
2845 case MESA_FORMAT_LUMINANCE_FLOAT32
:
2846 case MESA_FORMAT_INTENSITY_FLOAT32
:
2849 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2850 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2851 GLfloat
*dst
= (GLfloat
*) dstRow
;
2852 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2853 i
++, j
+= colStride
, k
+= colStride
) {
2854 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
2858 case MESA_FORMAT_ALPHA_FLOAT16
:
2859 case MESA_FORMAT_LUMINANCE_FLOAT16
:
2860 case MESA_FORMAT_INTENSITY_FLOAT16
:
2863 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
2864 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
2865 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
2866 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2867 i
++, j
+= colStride
, k
+= colStride
) {
2868 GLfloat aj
, ak
, bj
, bk
;
2869 aj
= _mesa_half_to_float(rowA
[j
]);
2870 ak
= _mesa_half_to_float(rowA
[k
]);
2871 bj
= _mesa_half_to_float(rowB
[j
]);
2872 bk
= _mesa_half_to_float(rowB
[k
]);
2873 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2879 _mesa_problem(NULL
, "bad format in do_row()");
2885 * These functions generate a 1/2-size mipmap image from a source image.
2886 * Texture borders are handled by copying or averaging the source image's
2887 * border texels, depending on the scale-down factor.
2891 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
2892 GLint srcWidth
, const GLubyte
*srcPtr
,
2893 GLint dstWidth
, GLubyte
*dstPtr
)
2895 const GLint bpt
= format
->TexelBytes
;
2899 /* skip the border pixel, if any */
2900 src
= srcPtr
+ border
* bpt
;
2901 dst
= dstPtr
+ border
* bpt
;
2903 /* we just duplicate the input row, kind of hack, saves code */
2904 do_row(format
, srcWidth
- 2 * border
, src
, src
,
2905 dstWidth
- 2 * border
, dst
);
2908 /* copy left-most pixel from source */
2909 MEMCPY(dstPtr
, srcPtr
, bpt
);
2910 /* copy right-most pixel from source */
2911 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
2912 srcPtr
+ (srcWidth
- 1) * bpt
,
2919 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
2920 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
2921 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
2923 const GLint bpt
= format
->TexelBytes
;
2924 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
2925 const GLint dstWidthNB
= dstWidth
- 2 * border
;
2926 const GLint dstHeightNB
= dstHeight
- 2 * border
;
2927 const GLint srcRowStride
= bpt
* srcWidth
;
2928 const GLint dstRowStride
= bpt
* dstWidth
;
2929 const GLubyte
*srcA
, *srcB
;
2933 /* Compute src and dst pointers, skipping any border */
2934 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
2936 srcB
= srcA
+ srcRowStride
;
2939 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
2941 for (row
= 0; row
< dstHeightNB
; row
++) {
2942 do_row(format
, srcWidthNB
, srcA
, srcB
,
2944 srcA
+= 2 * srcRowStride
;
2945 srcB
+= 2 * srcRowStride
;
2946 dst
+= dstRowStride
;
2949 /* This is ugly but probably won't be used much */
2951 /* fill in dest border */
2952 /* lower-left border pixel */
2953 MEMCPY(dstPtr
, srcPtr
, bpt
);
2954 /* lower-right border pixel */
2955 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
2956 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
2957 /* upper-left border pixel */
2958 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
2959 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
2960 /* upper-right border pixel */
2961 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
2962 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
2964 do_row(format
, srcWidthNB
,
2967 dstWidthNB
, dstPtr
+ bpt
);
2969 do_row(format
, srcWidthNB
,
2970 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
2971 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
2973 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
2974 /* left and right borders */
2975 if (srcHeight
== dstHeight
) {
2976 /* copy border pixel from src to dst */
2977 for (row
= 1; row
< srcHeight
; row
++) {
2978 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
2979 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
2980 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
2981 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
2985 /* average two src pixels each dest pixel */
2986 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
2988 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
2989 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
2990 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
2992 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
2993 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
2994 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3002 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3003 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3004 const GLubyte
*srcPtr
,
3005 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3008 const GLint bpt
= format
->TexelBytes
;
3009 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3010 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3011 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3012 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3013 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3014 GLvoid
*tmpRowA
, *tmpRowB
;
3016 GLint bytesPerSrcImage
, bytesPerDstImage
;
3017 GLint bytesPerSrcRow
, bytesPerDstRow
;
3018 GLint srcImageOffset
, srcRowOffset
;
3020 (void) srcDepthNB
; /* silence warnings */
3022 /* Need two temporary row buffers */
3023 tmpRowA
= MALLOC(srcWidth
* bpt
);
3026 tmpRowB
= MALLOC(srcWidth
* bpt
);
3032 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3033 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3035 bytesPerSrcRow
= srcWidth
* bpt
;
3036 bytesPerDstRow
= dstWidth
* bpt
;
3038 /* Offset between adjacent src images to be averaged together */
3039 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3041 /* Offset between adjacent src rows to be averaged together */
3042 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3045 * Need to average together up to 8 src pixels for each dest pixel.
3046 * Break that down into 3 operations:
3047 * 1. take two rows from source image and average them together.
3048 * 2. take two rows from next source image and average them together.
3049 * 3. take the two averaged rows and average them for the final dst row.
3053 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3054 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3057 for (img
= 0; img
< dstDepthNB
; img
++) {
3058 /* first source image pointer, skipping border */
3059 const GLubyte
*imgSrcA
= srcPtr
3060 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3061 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3062 /* second source image pointer, skipping border */
3063 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3064 /* address of the dest image, skipping border */
3065 GLubyte
*imgDst
= dstPtr
3066 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3067 + img
* bytesPerDstImage
;
3069 /* setup the four source row pointers and the dest row pointer */
3070 const GLubyte
*srcImgARowA
= imgSrcA
;
3071 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3072 const GLubyte
*srcImgBRowA
= imgSrcB
;
3073 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3074 GLubyte
*dstImgRow
= imgDst
;
3076 for (row
= 0; row
< dstHeightNB
; row
++) {
3077 /* Average together two rows from first src image */
3078 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3079 srcWidthNB
, tmpRowA
);
3080 /* Average together two rows from second src image */
3081 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3082 srcWidthNB
, tmpRowB
);
3083 /* Average together the temp rows to make the final row */
3084 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3085 dstWidthNB
, dstImgRow
);
3086 /* advance to next rows */
3087 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3088 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3089 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3090 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3091 dstImgRow
+= bytesPerDstRow
;
3098 /* Luckily we can leverage the make_2d_mipmap() function here! */
3100 /* do front border image */
3101 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3102 dstWidth
, dstHeight
, dstPtr
);
3103 /* do back border image */
3104 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3105 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3106 dstWidth
, dstHeight
,
3107 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3108 /* do four remaining border edges that span the image slices */
3109 if (srcDepth
== dstDepth
) {
3110 /* just copy border pixels from src to dst */
3111 for (img
= 0; img
< dstDepthNB
; img
++) {
3115 /* do border along [img][row=0][col=0] */
3116 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3117 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3118 MEMCPY(dst
, src
, bpt
);
3120 /* do border along [img][row=dstHeight-1][col=0] */
3121 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3122 + (srcHeight
- 1) * bytesPerSrcRow
;
3123 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3124 + (dstHeight
- 1) * bytesPerDstRow
;
3125 MEMCPY(dst
, src
, bpt
);
3127 /* do border along [img][row=0][col=dstWidth-1] */
3128 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3129 + (srcWidth
- 1) * bpt
;
3130 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3131 + (dstWidth
- 1) * bpt
;
3132 MEMCPY(dst
, src
, bpt
);
3134 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3135 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3136 + (bytesPerSrcImage
- bpt
);
3137 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3138 + (bytesPerDstImage
- bpt
);
3139 MEMCPY(dst
, src
, bpt
);
3143 /* average border pixels from adjacent src image pairs */
3144 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3145 for (img
= 0; img
< dstDepthNB
; img
++) {
3149 /* do border along [img][row=0][col=0] */
3150 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3151 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3152 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3154 /* do border along [img][row=dstHeight-1][col=0] */
3155 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3156 + (srcHeight
- 1) * bytesPerSrcRow
;
3157 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3158 + (dstHeight
- 1) * bytesPerDstRow
;
3159 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3161 /* do border along [img][row=0][col=dstWidth-1] */
3162 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3163 + (srcWidth
- 1) * bpt
;
3164 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3165 + (dstWidth
- 1) * bpt
;
3166 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3168 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3169 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3170 + (bytesPerSrcImage
- bpt
);
3171 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3172 + (bytesPerDstImage
- bpt
);
3173 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3181 * For GL_SGIX_generate_mipmap:
3182 * Generate a complete set of mipmaps from texObj's base-level image.
3183 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3186 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3187 const struct gl_texture_unit
*texUnit
,
3188 struct gl_texture_object
*texObj
)
3190 const struct gl_texture_image
*srcImage
;
3191 const struct gl_texture_format
*convertFormat
;
3192 const GLubyte
*srcData
= NULL
;
3193 GLubyte
*dstData
= NULL
;
3194 GLint level
, maxLevels
;
3197 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3200 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3201 ASSERT(maxLevels
> 0); /* bad target */
3203 /* Find convertFormat - the format that do_row() will process */
3204 if (srcImage
->IsCompressed
) {
3205 /* setup for compressed textures */
3207 GLint components
, size
;
3210 assert(texObj
->Target
== GL_TEXTURE_2D
);
3212 if (srcImage
->Format
== GL_RGB
) {
3213 convertFormat
= &_mesa_texformat_rgb
;
3216 else if (srcImage
->Format
== GL_RGBA
) {
3217 convertFormat
= &_mesa_texformat_rgba
;
3221 _mesa_problem(ctx
, "bad srcImage->Format in _mesa_generate_mipmaps");
3225 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3226 size
= _mesa_bytes_per_pixel(srcImage
->Format
, CHAN_TYPE
)
3227 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3228 /* 20 extra bytes, just be safe when calling last FetchTexel */
3229 srcData
= (GLubyte
*) MALLOC(size
);
3231 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3234 dstData
= (GLubyte
*) MALLOC(size
/ 2); /* 1/4 would probably be OK */
3236 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3237 FREE((void *) srcData
);
3241 /* decompress base image here */
3242 dst
= (GLchan
*) srcData
;
3243 for (row
= 0; row
< srcImage
->Height
; row
++) {
3245 for (col
= 0; col
< srcImage
->Width
; col
++) {
3246 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3253 convertFormat
= srcImage
->TexFormat
;
3256 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3257 && level
< maxLevels
- 1; level
++) {
3258 /* generate image[level+1] from image[level] */
3259 const struct gl_texture_image
*srcImage
;
3260 struct gl_texture_image
*dstImage
;
3261 GLint srcWidth
, srcHeight
, srcDepth
;
3262 GLint dstWidth
, dstHeight
, dstDepth
;
3263 GLint border
, bytesPerTexel
;
3265 /* get src image parameters */
3266 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3268 srcWidth
= srcImage
->Width
;
3269 srcHeight
= srcImage
->Height
;
3270 srcDepth
= srcImage
->Depth
;
3271 border
= srcImage
->Border
;
3273 /* compute next (level+1) image size */
3274 if (srcWidth
- 2 * border
> 1) {
3275 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3278 dstWidth
= srcWidth
; /* can't go smaller */
3280 if (srcHeight
- 2 * border
> 1) {
3281 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3284 dstHeight
= srcHeight
; /* can't go smaller */
3286 if (srcDepth
- 2 * border
> 1) {
3287 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3290 dstDepth
= srcDepth
; /* can't go smaller */
3293 if (dstWidth
== srcWidth
&&
3294 dstHeight
== srcHeight
&&
3295 dstDepth
== srcDepth
) {
3297 if (srcImage
->IsCompressed
) {
3298 FREE((void *) srcData
);
3304 /* get dest gl_texture_image */
3305 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3307 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3311 /* Free old image data */
3313 MESA_PBUFFER_FREE(dstImage
->Data
);
3315 /* initialize new image */
3316 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3317 dstDepth
, border
, srcImage
->IntFormat
);
3318 dstImage
->DriverData
= NULL
;
3319 dstImage
->TexFormat
= srcImage
->TexFormat
;
3320 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3321 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3322 ASSERT(dstImage
->TexFormat
);
3323 ASSERT(dstImage
->FetchTexelc
);
3324 ASSERT(dstImage
->FetchTexelf
);
3326 /* Alloc new teximage data buffer.
3327 * Setup src and dest data pointers.
3329 if (dstImage
->IsCompressed
) {
3330 ASSERT(dstImage
->CompressedSize
> 0); /* set by init_teximage_fields*/
3331 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstImage
->CompressedSize
);
3332 if (!dstImage
->Data
) {
3333 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3336 /* srcData and dstData are already set */
3341 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
3342 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3343 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstWidth
* dstHeight
* dstDepth
3345 if (!dstImage
->Data
) {
3346 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3349 srcData
= (const GLubyte
*) srcImage
->Data
;
3350 dstData
= (GLubyte
*) dstImage
->Data
;
3354 * We use simple 2x2 averaging to compute the next mipmap level.
3358 make_1d_mipmap(convertFormat
, border
,
3363 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3364 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3365 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3366 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3367 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3368 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3369 make_2d_mipmap(convertFormat
, border
,
3370 srcWidth
, srcHeight
, srcData
,
3371 dstWidth
, dstHeight
, dstData
);
3374 make_3d_mipmap(convertFormat
, border
,
3375 srcWidth
, srcHeight
, srcDepth
, srcData
,
3376 dstWidth
, dstHeight
, dstDepth
, dstData
);
3378 case GL_TEXTURE_RECTANGLE_NV
:
3379 /* no mipmaps, do nothing */
3382 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3386 if (dstImage
->IsCompressed
) {
3388 /* compress image from dstData into dstImage->Data */
3389 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3390 GLint dstRowStride
= _mesa_compressed_row_stride(srcImage
->IntFormat
,
3392 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3393 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->Format
,
3394 dstImage
->TexFormat
,
3396 0, 0, 0, /* dstX/Y/Zoffset */
3397 dstRowStride
, 0, /* strides */
3398 dstWidth
, dstHeight
, 1, /* size */
3399 srcFormat
, CHAN_TYPE
,
3400 dstData
, /* src data, actually */
3401 &ctx
->DefaultPacking
);
3402 /* swap src and dest pointers */
3403 temp
= (GLubyte
*) srcData
;
3408 } /* loop over mipmap levels */
3413 * Helper function for drivers which need to rescale texture images to
3414 * certain aspect ratios.
3415 * Nearest filtering only (for broken hardware that can't support
3416 * all aspect ratios). This can be made a lot faster, but I don't
3417 * really care enough...
3420 _mesa_rescale_teximage2d (GLuint bytesPerPixel
,
3421 GLuint srcStrideInPixels
,
3422 GLuint dstRowStride
,
3423 GLint srcWidth
, GLint srcHeight
,
3424 GLint dstWidth
, GLint dstHeight
,
3425 const GLvoid
*srcImage
, GLvoid
*dstImage
)
3429 #define INNER_LOOP( TYPE, HOP, WOP ) \
3430 for ( row = 0 ; row < dstHeight ; row++ ) { \
3431 GLint srcRow = row HOP hScale; \
3432 for ( col = 0 ; col < dstWidth ; col++ ) { \
3433 GLint srcCol = col WOP wScale; \
3434 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3436 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3439 #define RESCALE_IMAGE( TYPE ) \
3441 const TYPE *src = (const TYPE *)srcImage; \
3442 TYPE *dst = (TYPE *)dstImage; \
3444 if ( srcHeight < dstHeight ) { \
3445 const GLint hScale = dstHeight / srcHeight; \
3446 if ( srcWidth < dstWidth ) { \
3447 const GLint wScale = dstWidth / srcWidth; \
3448 INNER_LOOP( TYPE, /, / ); \
3451 const GLint wScale = srcWidth / dstWidth; \
3452 INNER_LOOP( TYPE, /, * ); \
3456 const GLint hScale = srcHeight / dstHeight; \
3457 if ( srcWidth < dstWidth ) { \
3458 const GLint wScale = dstWidth / srcWidth; \
3459 INNER_LOOP( TYPE, *, / ); \
3462 const GLint wScale = srcWidth / dstWidth; \
3463 INNER_LOOP( TYPE, *, * ); \
3468 switch ( bytesPerPixel
) {
3470 RESCALE_IMAGE( GLuint
);
3474 RESCALE_IMAGE( GLushort
);
3478 RESCALE_IMAGE( GLubyte
);
3481 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3487 * Upscale an image by replication, not (typical) stretching.
3488 * We use this when the image width or height is less than a
3489 * certain size (4, 8) and we need to upscale an image.
3492 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
3493 GLsizei outWidth
, GLsizei outHeight
,
3494 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
3499 ASSERT(outWidth
>= inWidth
);
3500 ASSERT(outHeight
>= inHeight
);
3502 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
3503 ASSERT((outWidth
& 3) == 0);
3504 ASSERT((outHeight
& 3) == 0);
3507 for (i
= 0; i
< outHeight
; i
++) {
3508 const GLint ii
= i
% inHeight
;
3509 for (j
= 0; j
< outWidth
; j
++) {
3510 const GLint jj
= j
% inWidth
;
3511 for (k
= 0; k
< comps
; k
++) {
3512 dest
[(i
* outWidth
+ j
) * comps
+ k
]
3513 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];