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 (logicalBaseFormat
) {
85 map
[0] = map
[1] = map
[2] = 0;
86 if (textureBaseFormat
== GL_RGBA
)
90 ASSERT(textureBaseFormat
== GL_RGBA
);
91 map
[0] = map
[1] = map
[2] = ZERO
;
95 map
[0] = map
[1] = map
[2] = 0;
96 if (textureBaseFormat
== GL_RGBA
)
99 case GL_LUMINANCE_ALPHA
:
100 ASSERT(textureBaseFormat
== GL_RGBA
);
101 map
[0] = map
[1] = map
[2] = 0;
105 ASSERT(textureBaseFormat
== GL_RGBA
);
112 _mesa_problem(NULL
, "Unexpected logicalBaseFormat");
113 map
[0] = map
[1] = map
[2] = map
[3] = 0;
119 * Make a temporary (color) texture image with GLfloat components.
120 * Apply all needed pixel unpacking and pixel transfer operations.
121 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
122 * Suppose the user specifies GL_LUMINANCE as the internal texture format
123 * but the graphics hardware doesn't support luminance textures. So, might
124 * use an RGB hardware format instead.
125 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
127 * \param ctx the rendering context
128 * \param dims image dimensions: 1, 2 or 3
129 * \param logicalBaseFormat basic texture derived from the user's
130 * internal texture format value
131 * \param textureBaseFormat the actual basic format of the texture
132 * \param srcWidth source image width
133 * \param srcHeight source image height
134 * \param srcDepth source image depth
135 * \param srcFormat source image format
136 * \param srcType source image type
137 * \param srcAddr source image address
138 * \param srcPacking source image pixel packing
139 * \return resulting image with format = textureBaseFormat and type = GLfloat.
142 make_temp_float_image(GLcontext
*ctx
, GLuint dims
,
143 GLenum logicalBaseFormat
,
144 GLenum textureBaseFormat
,
145 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
146 GLenum srcFormat
, GLenum srcType
,
147 const GLvoid
*srcAddr
,
148 const struct gl_pixelstore_attrib
*srcPacking
)
150 GLuint transferOps
= ctx
->_ImageTransferState
;
153 ASSERT(dims
>= 1 && dims
<= 3);
155 ASSERT(logicalBaseFormat
== GL_RGBA
||
156 logicalBaseFormat
== GL_RGB
||
157 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
158 logicalBaseFormat
== GL_LUMINANCE
||
159 logicalBaseFormat
== GL_ALPHA
||
160 logicalBaseFormat
== GL_INTENSITY
||
161 logicalBaseFormat
== GL_COLOR_INDEX
||
162 logicalBaseFormat
== GL_DEPTH_COMPONENT
);
164 ASSERT(textureBaseFormat
== GL_RGBA
||
165 textureBaseFormat
== GL_RGB
||
166 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
167 textureBaseFormat
== GL_LUMINANCE
||
168 textureBaseFormat
== GL_ALPHA
||
169 textureBaseFormat
== GL_INTENSITY
||
170 textureBaseFormat
== GL_COLOR_INDEX
||
171 textureBaseFormat
== GL_DEPTH_COMPONENT
);
173 /* conventional color image */
175 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
176 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
177 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
178 /* need image convolution */
179 const GLuint preConvTransferOps
180 = (transferOps
& IMAGE_PRE_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
181 const GLuint postConvTransferOps
182 = (transferOps
& IMAGE_POST_CONVOLUTION_BITS
) | IMAGE_CLAMP_BIT
;
184 GLint convWidth
, convHeight
;
187 /* pre-convolution image buffer (3D) */
188 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
189 * 4 * sizeof(GLfloat
));
193 /* post-convolution image buffer (2D) */
194 convImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
195 * 4 * sizeof(GLfloat
));
197 _mesa_free(tempImage
);
201 /* loop over 3D image slices */
202 for (img
= 0; img
< srcDepth
; img
++) {
203 GLfloat
*dst
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
205 /* unpack and do transfer ops up to convolution */
206 for (row
= 0; row
< srcHeight
; row
++) {
207 const GLvoid
*src
= _mesa_image_address(srcPacking
,
208 srcAddr
, srcWidth
, srcHeight
,
209 srcFormat
, srcType
, img
, row
, 0);
210 _mesa_unpack_color_span_float(ctx
, srcWidth
, GL_RGBA
, dst
,
211 srcFormat
, srcType
, src
,
219 GLfloat
*src
= tempImage
+ img
* (srcWidth
* srcHeight
* 4);
220 convWidth
= srcWidth
;
221 convHeight
= srcHeight
;
223 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
224 _mesa_convolve_1d_image(ctx
, &convWidth
, src
, convImage
);
227 if (ctx
->Pixel
.Convolution2DEnabled
) {
228 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
232 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
233 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
239 /* do post-convolution transfer and pack into tempImage */
241 const GLint logComponents
242 = _mesa_components_in_format(logicalBaseFormat
);
243 const GLfloat
*src
= convImage
;
244 GLfloat
*dst
= tempImage
+ img
* (convWidth
* convHeight
* 4);
245 for (row
= 0; row
< convHeight
; row
++) {
246 _mesa_pack_rgba_span_float(ctx
, convWidth
,
247 (const GLfloat (*)[4]) src
,
248 logicalBaseFormat
, GL_FLOAT
,
249 dst
, &ctx
->DefaultPacking
,
250 postConvTransferOps
);
251 src
+= convWidth
* 4;
252 dst
+= convWidth
* logComponents
;
255 } /* loop over 3D image slices */
257 _mesa_free(convImage
);
259 /* might need these below */
260 srcWidth
= convWidth
;
261 srcHeight
= convHeight
;
265 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
266 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
267 srcWidth
, srcFormat
, srcType
);
271 tempImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
272 * components
* sizeof(GLfloat
));
277 for (img
= 0; img
< srcDepth
; img
++) {
279 = (const GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
283 for (row
= 0; row
< srcHeight
; row
++) {
284 _mesa_unpack_color_span_float(ctx
, srcWidth
, logicalBaseFormat
,
285 dst
, srcFormat
, srcType
, src
,
286 srcPacking
, transferOps
);
287 dst
+= srcWidth
* components
;
293 if (logicalBaseFormat
!= textureBaseFormat
) {
295 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
296 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
301 /* we only promote up to RGB and RGBA formats for now */
302 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
);
304 /* The actual texture format should have at least as many components
305 * as the logical texture format.
307 ASSERT(texComponents
>= logComponents
);
309 newImage
= (GLfloat
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
310 * texComponents
* sizeof(GLfloat
));
312 _mesa_free(tempImage
);
316 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
318 n
= srcWidth
* srcHeight
* srcDepth
;
319 for (i
= 0; i
< n
; i
++) {
321 for (k
= 0; k
< texComponents
; k
++) {
324 newImage
[i
* texComponents
+ k
] = 0.0F
;
326 newImage
[i
* texComponents
+ k
] = 1.0F
;
328 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
332 _mesa_free(tempImage
);
333 tempImage
= newImage
;
341 * Make a temporary (color) texture image with GLchan components.
342 * Apply all needed pixel unpacking and pixel transfer operations.
343 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
344 * Suppose the user specifies GL_LUMINANCE as the internal texture format
345 * but the graphics hardware doesn't support luminance textures. So, might
346 * use an RGB hardware format instead.
347 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
349 * \param ctx the rendering context
350 * \param dims image dimensions: 1, 2 or 3
351 * \param logicalBaseFormat basic texture derived from the user's
352 * internal texture format value
353 * \param textureBaseFormat the actual basic format of the texture
354 * \param srcWidth source image width
355 * \param srcHeight source image height
356 * \param srcDepth source image depth
357 * \param srcFormat source image format
358 * \param srcType source image type
359 * \param srcAddr source image address
360 * \param srcPacking source image pixel packing
361 * \return resulting image with format = textureBaseFormat and type = GLchan.
364 _mesa_make_temp_chan_image(GLcontext
*ctx
, GLuint dims
,
365 GLenum logicalBaseFormat
,
366 GLenum textureBaseFormat
,
367 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
368 GLenum srcFormat
, GLenum srcType
,
369 const GLvoid
*srcAddr
,
370 const struct gl_pixelstore_attrib
*srcPacking
)
372 GLuint transferOps
= ctx
->_ImageTransferState
;
373 const GLint components
= _mesa_components_in_format(logicalBaseFormat
);
374 GLboolean freeSrcImage
= GL_FALSE
;
376 GLchan
*tempImage
, *dst
;
378 ASSERT(dims
>= 1 && dims
<= 3);
380 ASSERT(logicalBaseFormat
== GL_RGBA
||
381 logicalBaseFormat
== GL_RGB
||
382 logicalBaseFormat
== GL_LUMINANCE_ALPHA
||
383 logicalBaseFormat
== GL_LUMINANCE
||
384 logicalBaseFormat
== GL_ALPHA
||
385 logicalBaseFormat
== GL_INTENSITY
);
387 ASSERT(textureBaseFormat
== GL_RGBA
||
388 textureBaseFormat
== GL_RGB
||
389 textureBaseFormat
== GL_LUMINANCE_ALPHA
||
390 textureBaseFormat
== GL_LUMINANCE
||
391 textureBaseFormat
== GL_ALPHA
||
392 textureBaseFormat
== GL_INTENSITY
);
394 if ((dims
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
395 (dims
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
396 (dims
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
397 /* get convolved image */
398 GLfloat
*convImage
= make_temp_float_image(ctx
, dims
,
401 srcWidth
, srcHeight
, srcDepth
,
403 srcAddr
, srcPacking
);
406 /* the convolved image is our new source image */
408 srcFormat
= logicalBaseFormat
;
410 srcPacking
= &ctx
->DefaultPacking
;
411 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
413 freeSrcImage
= GL_TRUE
;
416 /* unpack and transfer the source image */
417 tempImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
418 * components
* sizeof(GLchan
));
423 for (img
= 0; img
< srcDepth
; img
++) {
424 const GLint srcStride
= _mesa_image_row_stride(srcPacking
,
428 = (const GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
432 for (row
= 0; row
< srcHeight
; row
++) {
433 _mesa_unpack_color_span_chan(ctx
, srcWidth
, logicalBaseFormat
, dst
,
434 srcFormat
, srcType
, src
, srcPacking
,
436 dst
+= srcWidth
* components
;
441 /* If we made a temporary image for convolution, free it here */
443 _mesa_free((void *) srcAddr
);
446 if (logicalBaseFormat
!= textureBaseFormat
) {
447 /* one more conversion step */
448 GLint texComponents
= _mesa_components_in_format(textureBaseFormat
);
449 GLint logComponents
= _mesa_components_in_format(logicalBaseFormat
);
454 /* we only promote up to RGB and RGBA formats for now */
455 ASSERT(textureBaseFormat
== GL_RGB
|| textureBaseFormat
== GL_RGBA
);
457 /* The actual texture format should have at least as many components
458 * as the logical texture format.
460 ASSERT(texComponents
>= logComponents
);
462 newImage
= (GLchan
*) _mesa_malloc(srcWidth
* srcHeight
* srcDepth
463 * texComponents
* sizeof(GLchan
));
465 _mesa_free(tempImage
);
469 compute_component_mapping(logicalBaseFormat
, textureBaseFormat
, map
);
471 n
= srcWidth
* srcHeight
* srcDepth
;
472 for (i
= 0; i
< n
; i
++) {
474 for (k
= 0; k
< texComponents
; k
++) {
477 newImage
[i
* texComponents
+ k
] = 0;
479 newImage
[i
* texComponents
+ k
] = CHAN_MAX
;
481 newImage
[i
* texComponents
+ k
] = tempImage
[i
* logComponents
+ j
];
485 _mesa_free(tempImage
);
486 tempImage
= newImage
;
495 * Teximage storage routine for when a simple memcpy will do.
496 * No pixel transfer operations or special texel encodings allowed.
497 * 1D, 2D and 3D images supported.
500 memcpy_texture(const struct gl_texture_format
*dstFormat
,
502 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
503 GLint dstRowStride
, GLint dstImageStride
,
504 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
505 GLenum srcFormat
, GLenum srcType
,
506 const GLvoid
*srcAddr
,
507 const struct gl_pixelstore_attrib
*srcPacking
)
509 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
511 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
512 srcWidth
, srcHeight
, srcFormat
, srcType
);
513 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(srcPacking
,
514 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
515 const GLint bytesPerRow
= srcWidth
* dstFormat
->TexelBytes
;
516 const GLint bytesPerImage
= srcHeight
* bytesPerRow
;
517 const GLint bytesPerTexture
= srcDepth
* bytesPerImage
;
518 GLubyte
*dstImage
= (GLubyte
*) dstAddr
519 + dstZoffset
* dstImageStride
520 + dstYoffset
* dstRowStride
521 + dstXoffset
* dstFormat
->TexelBytes
;
523 if (dstRowStride
== srcRowStride
&&
524 dstRowStride
== bytesPerRow
&&
525 ((dstImageStride
== srcImageStride
&&
526 dstImageStride
== bytesPerImage
) ||
529 _mesa_memcpy(dstImage
, srcImage
, bytesPerTexture
);
533 for (img
= 0; img
< srcDepth
; img
++) {
534 const GLubyte
*srcRow
= srcImage
;
535 GLubyte
*dstRow
= dstImage
;
536 for (row
= 0; row
< srcHeight
; row
++) {
537 _mesa_memcpy(dstRow
, srcRow
, bytesPerRow
);
538 dstRow
+= dstRowStride
;
539 srcRow
+= srcRowStride
;
541 srcImage
+= srcImageStride
;
542 dstImage
+= dstImageStride
;
550 * Store an image in any of the formats:
551 * _mesa_texformat_rgba
552 * _mesa_texformat_rgb
553 * _mesa_texformat_alpha
554 * _mesa_texformat_luminance
555 * _mesa_texformat_luminance_alpha
556 * _mesa_texformat_intensity
558 * \param dims either 1 or 2 or 3
559 * \param baseInternalFormat user-specified base internal format
560 * \param dstFormat destination Mesa texture format
561 * \param dstAddr destination image address
562 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
563 * \param dstRowStride destination image row stride, in bytes
564 * \param dstImageStride destination image layer stride, in bytes
565 * \param srcWidth/Height/Depth source image size, in pixels
566 * \param srcFormat incoming image format
567 * \param srcType incoming image data type
568 * \param srcAddr source image address
569 * \param srcPacking source image packing parameters
572 _mesa_texstore_rgba(GLcontext
*ctx
, GLuint dims
,
573 GLenum baseInternalFormat
,
574 const struct gl_texture_format
*dstFormat
,
576 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
577 GLint dstRowStride
, GLint dstImageStride
,
578 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
579 GLenum srcFormat
, GLenum srcType
,
580 const GLvoid
*srcAddr
,
581 const struct gl_pixelstore_attrib
*srcPacking
)
583 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
585 ASSERT(dstFormat
== &_mesa_texformat_rgba
||
586 dstFormat
== &_mesa_texformat_rgb
||
587 dstFormat
== &_mesa_texformat_alpha
||
588 dstFormat
== &_mesa_texformat_luminance
||
589 dstFormat
== &_mesa_texformat_luminance_alpha
||
590 dstFormat
== &_mesa_texformat_intensity
);
591 ASSERT(baseInternalFormat
== GL_RGBA
||
592 baseInternalFormat
== GL_RGB
||
593 baseInternalFormat
== GL_ALPHA
||
594 baseInternalFormat
== GL_LUMINANCE
||
595 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
596 baseInternalFormat
== GL_INTENSITY
);
597 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLchan
));
599 if (!ctx
->_ImageTransferState
&&
600 !srcPacking
->SwapBytes
&&
601 baseInternalFormat
== srcFormat
&&
602 srcType
== CHAN_TYPE
) {
603 /* simple memcpy path */
604 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
605 dstRowStride
, dstImageStride
,
606 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
607 srcAddr
, srcPacking
);
609 else if (!ctx
->_ImageTransferState
&&
610 !srcPacking
->SwapBytes
&&
611 dstFormat
== &_mesa_texformat_rgb
&&
612 srcFormat
== GL_RGBA
&&
613 srcType
== CHAN_TYPE
) {
614 /* extract RGB from RGBA */
616 GLchan
*dstImage
= (GLchan
*) (GLubyte
*) dstAddr
617 + dstZoffset
* dstImageStride
618 + dstYoffset
* dstRowStride
619 + dstXoffset
* dstFormat
->TexelBytes
;
620 for (img
= 0; img
< srcDepth
; img
++) {
621 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
622 srcWidth
, srcFormat
, srcType
);
623 GLchan
*srcRow
= (GLchan
*) _mesa_image_address(srcPacking
, srcAddr
,
624 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
625 GLchan
*dstRow
= dstImage
;
626 for (row
= 0; row
< srcHeight
; row
++) {
627 for (col
= 0; col
< srcWidth
; col
++) {
628 dstRow
[col
* 3 + RCOMP
] = srcRow
[col
* 4 + RCOMP
];
629 dstRow
[col
* 3 + GCOMP
] = srcRow
[col
* 4 + GCOMP
];
630 dstRow
[col
* 3 + BCOMP
] = srcRow
[col
* 4 + BCOMP
];
632 dstRow
+= dstRowStride
;
633 srcRow
= (GLchan
*) ((GLubyte
*) srcRow
+ srcRowStride
);
635 dstImage
+= dstImageStride
;
640 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
642 dstFormat
->BaseFormat
,
643 srcWidth
, srcHeight
, srcDepth
,
644 srcFormat
, srcType
, srcAddr
,
646 const GLchan
*src
= tempImage
;
648 GLubyte
*dstImage
= (GLubyte
*) dstAddr
649 + dstZoffset
* dstImageStride
650 + dstYoffset
* dstRowStride
651 + dstXoffset
* dstFormat
->TexelBytes
;
655 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
656 bytesPerRow
= srcWidth
* components
* sizeof(GLchan
);
657 for (img
= 0; img
< srcDepth
; img
++) {
658 GLubyte
*dstRow
= dstImage
;
659 for (row
= 0; row
< srcHeight
; row
++) {
660 _mesa_memcpy(dstRow
, src
, bytesPerRow
);
661 dstRow
+= dstRowStride
;
662 src
+= srcWidth
* components
;
664 dstImage
+= dstImageStride
;
667 _mesa_free((void *) tempImage
);
674 * Store a floating point depth component texture image.
677 _mesa_texstore_depth_component_float32(STORE_PARAMS
)
679 ASSERT(dstFormat
== &_mesa_texformat_depth_component_float32
);
680 ASSERT(dstFormat
->TexelBytes
== sizeof(GLfloat
));
682 if (!ctx
->_ImageTransferState
&&
683 !srcPacking
->SwapBytes
&&
684 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
685 srcFormat
== GL_DEPTH_COMPONENT
&&
686 srcType
== GL_FLOAT
) {
687 /* simple memcpy path */
688 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
689 dstRowStride
, dstImageStride
,
690 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
691 srcAddr
, srcPacking
);
695 GLubyte
*dstImage
= (GLubyte
*) dstAddr
696 + dstZoffset
* dstImageStride
697 + dstYoffset
* dstRowStride
698 + dstXoffset
* dstFormat
->TexelBytes
;
700 for (img
= 0; img
< srcDepth
; img
++) {
701 GLubyte
*dstRow
= dstImage
;
702 for (row
= 0; row
< srcHeight
; row
++) {
703 const GLvoid
*src
= _mesa_image_address(srcPacking
,
704 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
705 _mesa_unpack_depth_span(ctx
, srcWidth
, (GLfloat
*) dstRow
,
706 srcType
, src
, srcPacking
);
707 dstRow
+= dstRowStride
;
709 dstImage
+= dstImageStride
;
717 * Store a 16-bit integer depth component texture image.
720 _mesa_texstore_depth_component16(STORE_PARAMS
)
722 ASSERT(dstFormat
== &_mesa_texformat_depth_component16
);
723 ASSERT(dstFormat
->TexelBytes
== sizeof(GLushort
));
725 if (!ctx
->_ImageTransferState
&&
726 !srcPacking
->SwapBytes
&&
727 baseInternalFormat
== GL_DEPTH_COMPONENT
&&
728 srcFormat
== GL_DEPTH_COMPONENT
&&
729 srcType
== GL_UNSIGNED_SHORT
) {
730 /* simple memcpy path */
731 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
732 dstRowStride
, dstImageStride
,
733 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
734 srcAddr
, srcPacking
);
738 GLubyte
*dstImage
= (GLubyte
*) dstAddr
739 + dstZoffset
* dstImageStride
740 + dstYoffset
* dstRowStride
741 + dstXoffset
* dstFormat
->TexelBytes
;
743 for (img
= 0; img
< srcDepth
; img
++) {
744 GLubyte
*dstRow
= dstImage
;
745 for (row
= 0; row
< srcHeight
; row
++) {
746 GLfloat depthTemp
[MAX_WIDTH
];
747 const GLvoid
*src
= _mesa_image_address(srcPacking
,
748 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
749 GLushort
*dst16
= (GLushort
*) dstRow
;
750 _mesa_unpack_depth_span(ctx
, srcWidth
, depthTemp
,
751 srcType
, src
, srcPacking
);
752 for (col
= 0; col
< srcWidth
; col
++) {
753 dst16
[col
] = (GLushort
) (depthTemp
[col
] * 65535.0F
);
755 dstRow
+= dstRowStride
;
757 dstImage
+= dstImageStride
;
765 * Store an rgb565 texture image.
768 _mesa_texstore_rgb565(STORE_PARAMS
)
770 ASSERT(dstFormat
== &_mesa_texformat_rgb565
);
771 ASSERT(dstFormat
->TexelBytes
== 2);
773 if (!ctx
->_ImageTransferState
&&
774 !srcPacking
->SwapBytes
&&
775 baseInternalFormat
== GL_RGB
&&
776 srcFormat
== GL_RGB
&&
777 srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
778 /* simple memcpy path */
779 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
780 dstRowStride
, dstImageStride
,
781 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
782 srcAddr
, srcPacking
);
784 else if (!ctx
->_ImageTransferState
&&
785 !srcPacking
->SwapBytes
&&
786 baseInternalFormat
== GL_RGB
&&
787 srcFormat
== GL_RGB
&&
788 srcType
== GL_UNSIGNED_BYTE
&&
790 /* do optimized tex store */
791 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
793 const GLubyte
*src
= (const GLubyte
*)
794 _mesa_image_address(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
795 srcFormat
, srcType
, 0, 0, 0);
796 GLubyte
*dst
= (GLubyte
*) dstAddr
797 + dstZoffset
* dstImageStride
798 + dstYoffset
* dstRowStride
799 + dstXoffset
* dstFormat
->TexelBytes
;
801 for (row
= 0; row
< srcHeight
; row
++) {
802 const GLubyte
*srcUB
= (const GLubyte
*) src
;
803 GLushort
*dstUS
= (GLushort
*) dst
;
804 for (col
= 0; col
< srcWidth
; col
++) {
805 dstUS
[col
] = PACK_COLOR_565( srcUB
[0], srcUB
[1], srcUB
[2] );
814 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
816 dstFormat
->BaseFormat
,
817 srcWidth
, srcHeight
, srcDepth
,
818 srcFormat
, srcType
, srcAddr
,
820 const GLchan
*src
= tempImage
;
821 GLubyte
*dstImage
= (GLubyte
*) dstAddr
822 + dstZoffset
* dstImageStride
823 + dstYoffset
* dstRowStride
824 + dstXoffset
* dstFormat
->TexelBytes
;
828 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
829 for (img
= 0; img
< srcDepth
; img
++) {
830 GLubyte
*dstRow
= dstImage
;
831 for (row
= 0; row
< srcHeight
; row
++) {
832 GLushort
*dstUS
= (GLushort
*) dstRow
;
833 for (col
= 0; col
< srcWidth
; col
++) {
834 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[RCOMP
]),
835 CHAN_TO_UBYTE(src
[GCOMP
]),
836 CHAN_TO_UBYTE(src
[BCOMP
]) );
839 dstRow
+= dstRowStride
;
841 dstImage
+= dstImageStride
;
843 _mesa_free((void *) tempImage
);
850 * Store an bgr565 texture image.
853 _mesa_texstore_bgr565(STORE_PARAMS
)
855 ASSERT(dstFormat
== &_mesa_texformat_bgr565
);
856 ASSERT(dstFormat
->TexelBytes
== 2);
858 if (!ctx
->_ImageTransferState
&&
859 !srcPacking
->SwapBytes
&&
860 baseInternalFormat
== GL_RGB
&&
861 srcFormat
== GL_RGB
&&
862 srcType
== GL_UNSIGNED_SHORT_5_6_5_REV
) {
863 /* simple memcpy path */
864 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
865 dstRowStride
, dstImageStride
,
866 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
867 srcAddr
, srcPacking
);
869 else if (!ctx
->_ImageTransferState
&&
870 !srcPacking
->SwapBytes
&&
871 baseInternalFormat
== GL_RGB
&&
872 srcFormat
== GL_BGR
&&
873 srcType
== GL_UNSIGNED_BYTE
&&
875 /* do optimized tex store */
876 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
878 const GLubyte
*src
= (const GLubyte
*)
879 _mesa_image_address(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
880 srcFormat
, srcType
, 0, 0, 0);
881 GLubyte
*dst
= (GLubyte
*) dstAddr
882 + dstZoffset
* dstImageStride
883 + dstYoffset
* dstRowStride
884 + dstXoffset
* dstFormat
->TexelBytes
;
886 for (row
= 0; row
< srcHeight
; row
++) {
887 const GLubyte
*srcUB
= (const GLubyte
*) src
;
888 GLushort
*dstUS
= (GLushort
*) dst
;
889 for (col
= 0; col
< srcWidth
; col
++) {
890 dstUS
[col
] = PACK_COLOR_565( srcUB
[2], srcUB
[1], srcUB
[0] );
899 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
901 dstFormat
->BaseFormat
,
902 srcWidth
, srcHeight
, srcDepth
,
903 srcFormat
, srcType
, srcAddr
,
905 const GLchan
*src
= tempImage
;
906 GLubyte
*dstImage
= (GLubyte
*) dstAddr
907 + dstZoffset
* dstImageStride
908 + dstYoffset
* dstRowStride
909 + dstXoffset
* dstFormat
->TexelBytes
;
913 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
914 for (img
= 0; img
< srcDepth
; img
++) {
915 GLubyte
*dstRow
= dstImage
;
916 for (row
= 0; row
< srcHeight
; row
++) {
917 GLushort
*dstUS
= (GLushort
*) dstRow
;
918 for (col
= 0; col
< srcWidth
; col
++) {
919 dstUS
[col
] = PACK_COLOR_565( CHAN_TO_UBYTE(src
[BCOMP
]),
920 CHAN_TO_UBYTE(src
[GCOMP
]),
921 CHAN_TO_UBYTE(src
[RCOMP
]) );
924 dstRow
+= dstRowStride
;
926 dstImage
+= dstImageStride
;
928 _mesa_free((void *) tempImage
);
935 _mesa_texstore_rgba8888(STORE_PARAMS
)
938 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
940 ASSERT(dstFormat
== &_mesa_texformat_rgba8888
);
941 ASSERT(dstFormat
->TexelBytes
== 4);
943 if (!ctx
->_ImageTransferState
&&
944 !srcPacking
->SwapBytes
&&
945 baseInternalFormat
== GL_RGBA
&&
946 srcFormat
== GL_RGBA
&&
947 ((srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
&& littleEndian
) ||
948 (srcType
== GL_UNSIGNED_INT_8_8_8_8
&& !littleEndian
))) {
949 /* simple memcpy path */
950 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
951 dstRowStride
, dstImageStride
,
952 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
953 srcAddr
, srcPacking
);
957 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
959 dstFormat
->BaseFormat
,
960 srcWidth
, srcHeight
, srcDepth
,
961 srcFormat
, srcType
, srcAddr
,
963 const GLchan
*src
= tempImage
;
964 GLubyte
*dstImage
= (GLubyte
*) dstAddr
965 + dstZoffset
* dstImageStride
966 + dstYoffset
* dstRowStride
967 + dstXoffset
* dstFormat
->TexelBytes
;
971 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
972 for (img
= 0; img
< srcDepth
; img
++) {
973 GLubyte
*dstRow
= dstImage
;
974 for (row
= 0; row
< srcHeight
; row
++) {
975 GLuint
*dstUI
= (GLuint
*) dstRow
;
976 for (col
= 0; col
< srcWidth
; col
++) {
977 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[RCOMP
]),
978 CHAN_TO_UBYTE(src
[GCOMP
]),
979 CHAN_TO_UBYTE(src
[BCOMP
]),
980 CHAN_TO_UBYTE(src
[ACOMP
]) );
983 dstRow
+= dstRowStride
;
985 dstImage
+= dstImageStride
;
987 _mesa_free((void *) tempImage
);
994 _mesa_texstore_abgr8888(STORE_PARAMS
)
997 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
999 ASSERT(dstFormat
== &_mesa_texformat_abgr8888
);
1000 ASSERT(dstFormat
->TexelBytes
== 4);
1002 if (!ctx
->_ImageTransferState
&&
1003 !srcPacking
->SwapBytes
&&
1004 baseInternalFormat
== GL_RGBA
&&
1005 srcFormat
== GL_ABGR_EXT
&&
1006 ((srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
&& littleEndian
) ||
1007 (srcType
== GL_UNSIGNED_INT_8_8_8_8
&& !littleEndian
))) {
1008 /* simple memcpy path */
1009 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1010 dstRowStride
, dstImageStride
,
1011 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1012 srcAddr
, srcPacking
);
1016 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1018 dstFormat
->BaseFormat
,
1019 srcWidth
, srcHeight
, srcDepth
,
1020 srcFormat
, srcType
, srcAddr
,
1022 const GLchan
*src
= tempImage
;
1023 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1024 + dstZoffset
* dstImageStride
1025 + dstYoffset
* dstRowStride
1026 + dstXoffset
* dstFormat
->TexelBytes
;
1027 GLint img
, row
, col
;
1030 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1031 for (img
= 0; img
< srcDepth
; img
++) {
1032 GLubyte
*dstRow
= dstImage
;
1033 for (row
= 0; row
< srcHeight
; row
++) {
1034 GLuint
*dstUI
= (GLuint
*) dstRow
;
1035 for (col
= 0; col
< srcWidth
; col
++) {
1036 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1037 CHAN_TO_UBYTE(src
[BCOMP
]),
1038 CHAN_TO_UBYTE(src
[GCOMP
]),
1039 CHAN_TO_UBYTE(src
[RCOMP
]) );
1042 dstRow
+= dstRowStride
;
1044 dstImage
+= dstImageStride
;
1046 _mesa_free((void *) tempImage
);
1053 _mesa_texstore_argb8888(STORE_PARAMS
)
1055 const GLuint ui
= 1;
1056 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1058 ASSERT(dstFormat
== &_mesa_texformat_argb8888
);
1059 ASSERT(dstFormat
->TexelBytes
== 4);
1061 if (!ctx
->_ImageTransferState
&&
1062 !srcPacking
->SwapBytes
&&
1063 baseInternalFormat
== GL_RGBA
&&
1064 srcFormat
== GL_BGRA
&&
1065 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
1066 (srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
&& littleEndian
) ||
1067 (srcType
== GL_UNSIGNED_INT_8_8_8_8
&& !littleEndian
))) {
1068 /* simple memcpy path */
1069 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1070 dstRowStride
, dstImageStride
,
1071 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1072 srcAddr
, srcPacking
);
1076 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1078 dstFormat
->BaseFormat
,
1079 srcWidth
, srcHeight
, srcDepth
,
1080 srcFormat
, srcType
, srcAddr
,
1082 const GLchan
*src
= tempImage
;
1083 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1084 + dstZoffset
* dstImageStride
1085 + dstYoffset
* dstRowStride
1086 + dstXoffset
* dstFormat
->TexelBytes
;
1087 GLint img
, row
, col
;
1090 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1091 for (img
= 0; img
< srcDepth
; img
++) {
1092 GLubyte
*dstRow
= dstImage
;
1093 for (row
= 0; row
< srcHeight
; row
++) {
1094 GLuint
*dstUI
= (GLuint
*) dstRow
;
1095 for (col
= 0; col
< srcWidth
; col
++) {
1096 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[ACOMP
]),
1097 CHAN_TO_UBYTE(src
[RCOMP
]),
1098 CHAN_TO_UBYTE(src
[GCOMP
]),
1099 CHAN_TO_UBYTE(src
[BCOMP
]) );
1102 dstRow
+= dstRowStride
;
1104 dstImage
+= dstImageStride
;
1106 _mesa_free((void *) tempImage
);
1113 _mesa_texstore_bgra8888(STORE_PARAMS
)
1115 const GLuint ui
= 1;
1116 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1118 ASSERT(dstFormat
== &_mesa_texformat_bgra8888
);
1119 ASSERT(dstFormat
->TexelBytes
== 4);
1121 if (!ctx
->_ImageTransferState
&&
1122 !srcPacking
->SwapBytes
&&
1123 baseInternalFormat
== GL_RGBA
&&
1124 srcFormat
== GL_BGRA
&&
1125 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
1126 (srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
&& !littleEndian
) ||
1127 (srcType
== GL_UNSIGNED_INT_8_8_8_8
&& littleEndian
))) {
1128 /* simple memcpy path */
1129 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1130 dstRowStride
, dstImageStride
,
1131 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1132 srcAddr
, srcPacking
);
1136 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1138 dstFormat
->BaseFormat
,
1139 srcWidth
, srcHeight
, srcDepth
,
1140 srcFormat
, srcType
, srcAddr
,
1142 const GLchan
*src
= tempImage
;
1143 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1144 + dstZoffset
* dstImageStride
1145 + dstYoffset
* dstRowStride
1146 + dstXoffset
* dstFormat
->TexelBytes
;
1147 GLint img
, row
, col
;
1150 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1151 for (img
= 0; img
< srcDepth
; img
++) {
1152 GLubyte
*dstRow
= dstImage
;
1153 for (row
= 0; row
< srcHeight
; row
++) {
1154 GLuint
*dstUI
= (GLuint
*) dstRow
;
1155 for (col
= 0; col
< srcWidth
; col
++) {
1156 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[BCOMP
]),
1157 CHAN_TO_UBYTE(src
[GCOMP
]),
1158 CHAN_TO_UBYTE(src
[RCOMP
]),
1159 CHAN_TO_UBYTE(src
[ACOMP
]) );
1162 dstRow
+= dstRowStride
;
1164 dstImage
+= dstImageStride
;
1166 _mesa_free((void *) tempImage
);
1173 _mesa_texstore_rgb888(STORE_PARAMS
)
1175 const GLuint ui
= 1;
1176 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1178 ASSERT(dstFormat
== &_mesa_texformat_rgb888
);
1179 ASSERT(dstFormat
->TexelBytes
== 3);
1181 if (!ctx
->_ImageTransferState
&&
1182 !srcPacking
->SwapBytes
&&
1183 baseInternalFormat
== GL_RGB
&&
1184 srcFormat
== GL_BGR
&&
1185 srcType
== GL_UNSIGNED_BYTE
&&
1187 /* simple memcpy path */
1188 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1189 dstRowStride
, dstImageStride
,
1190 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1191 srcAddr
, srcPacking
);
1193 else if (!ctx
->_ImageTransferState
&&
1194 !srcPacking
->SwapBytes
&&
1195 srcFormat
== GL_RGBA
&&
1196 srcType
== GL_UNSIGNED_BYTE
) {
1197 /* extract RGB from RGBA */
1199 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1200 + dstZoffset
* dstImageStride
1201 + dstYoffset
* dstRowStride
1202 + dstXoffset
* dstFormat
->TexelBytes
;
1203 for (img
= 0; img
< srcDepth
; img
++) {
1204 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1205 srcWidth
, srcFormat
, srcType
);
1206 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
1207 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1208 GLubyte
*dstRow
= dstImage
;
1209 for (row
= 0; row
< srcHeight
; row
++) {
1210 for (col
= 0; col
< srcWidth
; col
++) {
1211 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + BCOMP
];
1212 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1213 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + RCOMP
];
1215 dstRow
+= dstRowStride
;
1216 srcRow
+= srcRowStride
;
1218 dstImage
+= dstImageStride
;
1223 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1225 dstFormat
->BaseFormat
,
1226 srcWidth
, srcHeight
, srcDepth
,
1227 srcFormat
, srcType
, srcAddr
,
1229 const GLchan
*src
= (const GLubyte
*) tempImage
;
1230 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1231 + dstZoffset
* dstImageStride
1232 + dstYoffset
* dstRowStride
1233 + dstXoffset
* dstFormat
->TexelBytes
;
1234 GLint img
, row
, col
;
1237 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1238 for (img
= 0; img
< srcDepth
; img
++) {
1239 GLubyte
*dstRow
= dstImage
;
1240 for (row
= 0; row
< srcHeight
; row
++) {
1243 for (col
= 0; col
< srcWidth
; col
++) {
1244 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1245 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1246 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1251 for (col
= 0; col
< srcWidth
; col
++) {
1252 dstRow
[col
* 3 + 0] = srcUB
[BCOMP
];
1253 dstRow
[col
* 3 + 1] = srcUB
[GCOMP
];
1254 dstRow
[col
* 3 + 2] = srcUB
[RCOMP
];
1259 for (col
= 0; col
< srcWidth
; col
++) {
1260 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[BCOMP
]);
1261 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1262 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[RCOMP
]);
1266 dstRow
+= dstRowStride
;
1268 dstImage
+= dstImageStride
;
1270 _mesa_free((void *) tempImage
);
1277 _mesa_texstore_bgr888(STORE_PARAMS
)
1279 const GLuint ui
= 1;
1280 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1282 ASSERT(dstFormat
== &_mesa_texformat_bgr888
);
1283 ASSERT(dstFormat
->TexelBytes
== 3);
1285 if (!ctx
->_ImageTransferState
&&
1286 !srcPacking
->SwapBytes
&&
1287 baseInternalFormat
== GL_RGB
&&
1288 srcFormat
== GL_RGB
&&
1289 srcType
== GL_UNSIGNED_BYTE
&&
1291 /* simple memcpy path */
1292 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1293 dstRowStride
, dstImageStride
,
1294 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1295 srcAddr
, srcPacking
);
1297 else if (!ctx
->_ImageTransferState
&&
1298 !srcPacking
->SwapBytes
&&
1299 srcFormat
== GL_RGBA
&&
1300 srcType
== GL_UNSIGNED_BYTE
) {
1301 /* extract BGR from RGBA */
1303 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1304 + dstZoffset
* dstImageStride
1305 + dstYoffset
* dstRowStride
1306 + dstXoffset
* dstFormat
->TexelBytes
;
1307 for (img
= 0; img
< srcDepth
; img
++) {
1308 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
1309 srcWidth
, srcFormat
, srcType
);
1310 GLubyte
*srcRow
= (GLubyte
*) _mesa_image_address(srcPacking
, srcAddr
,
1311 srcWidth
, srcHeight
, srcFormat
, srcType
, img
, 0, 0);
1312 GLubyte
*dstRow
= dstImage
;
1313 for (row
= 0; row
< srcHeight
; row
++) {
1314 for (col
= 0; col
< srcWidth
; col
++) {
1315 dstRow
[col
* 3 + 0] = srcRow
[col
* 4 + RCOMP
];
1316 dstRow
[col
* 3 + 1] = srcRow
[col
* 4 + GCOMP
];
1317 dstRow
[col
* 3 + 2] = srcRow
[col
* 4 + BCOMP
];
1319 dstRow
+= dstRowStride
;
1320 srcRow
+= srcRowStride
;
1322 dstImage
+= dstImageStride
;
1327 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1329 dstFormat
->BaseFormat
,
1330 srcWidth
, srcHeight
, srcDepth
,
1331 srcFormat
, srcType
, srcAddr
,
1333 const GLchan
*src
= (const GLubyte
*) tempImage
;
1334 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1335 + dstZoffset
* dstImageStride
1336 + dstYoffset
* dstRowStride
1337 + dstXoffset
* dstFormat
->TexelBytes
;
1338 GLint img
, row
, col
;
1341 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1342 for (img
= 0; img
< srcDepth
; img
++) {
1343 GLubyte
*dstRow
= dstImage
;
1344 for (row
= 0; row
< srcHeight
; row
++) {
1345 for (col
= 0; col
< srcWidth
; col
++) {
1346 dstRow
[col
* 3 + 0] = CHAN_TO_UBYTE(src
[RCOMP
]);
1347 dstRow
[col
* 3 + 1] = CHAN_TO_UBYTE(src
[GCOMP
]);
1348 dstRow
[col
* 3 + 2] = CHAN_TO_UBYTE(src
[BCOMP
]);
1351 dstRow
+= dstRowStride
;
1353 dstImage
+= dstImageStride
;
1355 _mesa_free((void *) tempImage
);
1362 _mesa_texstore_argb4444(STORE_PARAMS
)
1364 const GLuint ui
= 1;
1365 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1367 ASSERT(dstFormat
== &_mesa_texformat_argb4444
);
1368 ASSERT(dstFormat
->TexelBytes
== 2);
1370 if (!ctx
->_ImageTransferState
&&
1371 !srcPacking
->SwapBytes
&&
1372 baseInternalFormat
== GL_RGBA
&&
1373 srcFormat
== GL_BGRA
&&
1374 ((srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
&& littleEndian
) ||
1375 (srcType
== GL_UNSIGNED_SHORT_4_4_4_4
&& !littleEndian
))) {
1376 /* simple memcpy path */
1377 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1378 dstRowStride
, dstImageStride
,
1379 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1380 srcAddr
, srcPacking
);
1384 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1386 dstFormat
->BaseFormat
,
1387 srcWidth
, srcHeight
, srcDepth
,
1388 srcFormat
, srcType
, srcAddr
,
1390 const GLchan
*src
= tempImage
;
1391 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1392 + dstZoffset
* dstImageStride
1393 + dstYoffset
* dstRowStride
1394 + dstXoffset
* dstFormat
->TexelBytes
;
1395 GLint img
, row
, col
;
1398 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1399 for (img
= 0; img
< srcDepth
; img
++) {
1400 GLubyte
*dstRow
= dstImage
;
1401 for (row
= 0; row
< srcHeight
; row
++) {
1402 GLushort
*dstUS
= (GLushort
*) dstRow
;
1403 for (col
= 0; col
< srcWidth
; col
++) {
1404 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[ACOMP
]),
1405 CHAN_TO_UBYTE(src
[RCOMP
]),
1406 CHAN_TO_UBYTE(src
[GCOMP
]),
1407 CHAN_TO_UBYTE(src
[BCOMP
]) );
1410 dstRow
+= dstRowStride
;
1412 dstImage
+= dstImageStride
;
1414 _mesa_free((void *) tempImage
);
1421 _mesa_texstore_bgra4444(STORE_PARAMS
)
1423 const GLuint ui
= 1;
1424 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1426 ASSERT(dstFormat
== &_mesa_texformat_bgra4444
);
1427 ASSERT(dstFormat
->TexelBytes
== 2);
1429 if (!ctx
->_ImageTransferState
&&
1430 !srcPacking
->SwapBytes
&&
1431 baseInternalFormat
== GL_RGBA
&&
1432 srcFormat
== GL_BGRA
&&
1433 ((srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
&& !littleEndian
) ||
1434 (srcType
== GL_UNSIGNED_SHORT_4_4_4_4
&& littleEndian
))) {
1435 /* simple memcpy path */
1436 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1437 dstRowStride
, dstImageStride
,
1438 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1439 srcAddr
, srcPacking
);
1443 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1445 dstFormat
->BaseFormat
,
1446 srcWidth
, srcHeight
, srcDepth
,
1447 srcFormat
, srcType
, srcAddr
,
1449 const GLchan
*src
= tempImage
;
1450 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1451 + dstZoffset
* dstImageStride
1452 + dstYoffset
* dstRowStride
1453 + dstXoffset
* dstFormat
->TexelBytes
;
1454 GLint img
, row
, col
;
1457 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1458 for (img
= 0; img
< srcDepth
; img
++) {
1459 GLubyte
*dstRow
= dstImage
;
1460 for (row
= 0; row
< srcHeight
; row
++) {
1461 GLushort
*dstUS
= (GLushort
*) dstRow
;
1462 for (col
= 0; col
< srcWidth
; col
++) {
1463 dstUS
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[BCOMP
]),
1464 CHAN_TO_UBYTE(src
[GCOMP
]),
1465 CHAN_TO_UBYTE(src
[RCOMP
]),
1466 CHAN_TO_UBYTE(src
[ACOMP
]) );
1469 dstRow
+= dstRowStride
;
1471 dstImage
+= dstImageStride
;
1473 _mesa_free((void *) tempImage
);
1480 _mesa_texstore_argb1555(STORE_PARAMS
)
1482 const GLuint ui
= 1;
1483 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1485 ASSERT(dstFormat
== &_mesa_texformat_argb1555
);
1486 ASSERT(dstFormat
->TexelBytes
== 2);
1488 if (!ctx
->_ImageTransferState
&&
1489 !srcPacking
->SwapBytes
&&
1490 baseInternalFormat
== GL_RGBA
&&
1491 srcFormat
== GL_BGRA
&&
1492 ((srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
&& littleEndian
) ||
1493 (srcType
== GL_UNSIGNED_SHORT_5_5_5_1
&& !littleEndian
))) {
1494 /* simple memcpy path */
1495 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1496 dstRowStride
, dstImageStride
,
1497 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1498 srcAddr
, srcPacking
);
1502 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1504 dstFormat
->BaseFormat
,
1505 srcWidth
, srcHeight
, srcDepth
,
1506 srcFormat
, srcType
, srcAddr
,
1508 const GLchan
*src
=tempImage
;
1509 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1510 + dstZoffset
* dstImageStride
1511 + dstYoffset
* dstRowStride
1512 + dstXoffset
* dstFormat
->TexelBytes
;
1513 GLint img
, row
, col
;
1516 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1517 for (img
= 0; img
< srcDepth
; img
++) {
1518 GLubyte
*dstRow
= dstImage
;
1519 for (row
= 0; row
< srcHeight
; row
++) {
1520 GLushort
*dstUS
= (GLushort
*) dstRow
;
1521 for (col
= 0; col
< srcWidth
; col
++) {
1522 dstUS
[col
] = PACK_COLOR_1555( CHAN_TO_UBYTE(src
[ACOMP
]),
1523 CHAN_TO_UBYTE(src
[RCOMP
]),
1524 CHAN_TO_UBYTE(src
[GCOMP
]),
1525 CHAN_TO_UBYTE(src
[BCOMP
]) );
1528 dstRow
+= dstRowStride
;
1530 dstImage
+= dstImageStride
;
1532 _mesa_free((void *) tempImage
);
1538 _mesa_texstore_bgra5551(STORE_PARAMS
)
1540 const GLuint ui
= 1;
1541 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1543 ASSERT(dstFormat
== &_mesa_texformat_bgra5551
);
1544 ASSERT(dstFormat
->TexelBytes
== 2);
1546 if (!ctx
->_ImageTransferState
&&
1547 !srcPacking
->SwapBytes
&&
1548 baseInternalFormat
== GL_RGBA
&&
1549 srcFormat
== GL_BGRA
&&
1550 ((srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
&& !littleEndian
) ||
1551 (srcType
== GL_UNSIGNED_SHORT_5_5_5_1
&& littleEndian
))) {
1552 /* simple memcpy path */
1553 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1554 dstRowStride
, dstImageStride
,
1555 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1556 srcAddr
, srcPacking
);
1560 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1562 dstFormat
->BaseFormat
,
1563 srcWidth
, srcHeight
, srcDepth
,
1564 srcFormat
, srcType
, srcAddr
,
1566 const GLchan
*src
=tempImage
;
1567 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1568 + dstZoffset
* dstImageStride
1569 + dstYoffset
* dstRowStride
1570 + dstXoffset
* dstFormat
->TexelBytes
;
1571 GLint img
, row
, col
;
1574 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1575 for (img
= 0; img
< srcDepth
; img
++) {
1576 GLubyte
*dstRow
= dstImage
;
1577 for (row
= 0; row
< srcHeight
; row
++) {
1578 GLushort
*dstUS
= (GLushort
*) dstRow
;
1579 for (col
= 0; col
< srcWidth
; col
++) {
1580 dstUS
[col
] = PACK_COLOR_5551( CHAN_TO_UBYTE(src
[RCOMP
]),
1581 CHAN_TO_UBYTE(src
[GCOMP
]),
1582 CHAN_TO_UBYTE(src
[BCOMP
]),
1583 CHAN_TO_UBYTE(src
[ACOMP
]) );
1586 dstRow
+= dstRowStride
;
1588 dstImage
+= dstImageStride
;
1590 _mesa_free((void *) tempImage
);
1597 _mesa_texstore_al88(STORE_PARAMS
)
1599 const GLuint ui
= 1;
1600 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1602 ASSERT(dstFormat
== &_mesa_texformat_al88
);
1603 ASSERT(dstFormat
->TexelBytes
== 2);
1605 if (!ctx
->_ImageTransferState
&&
1606 !srcPacking
->SwapBytes
&&
1607 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1608 srcFormat
== GL_LUMINANCE_ALPHA
&&
1609 srcType
== GL_UNSIGNED_BYTE
&&
1611 /* simple memcpy path */
1612 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1613 dstRowStride
, dstImageStride
,
1614 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1615 srcAddr
, srcPacking
);
1619 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1621 dstFormat
->BaseFormat
,
1622 srcWidth
, srcHeight
, srcDepth
,
1623 srcFormat
, srcType
, srcAddr
,
1625 const GLchan
*src
= tempImage
;
1626 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1627 + dstZoffset
* dstImageStride
1628 + dstYoffset
* dstRowStride
1629 + dstXoffset
* dstFormat
->TexelBytes
;
1630 GLint img
, row
, col
;
1633 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1634 for (img
= 0; img
< srcDepth
; img
++) {
1635 GLubyte
*dstRow
= dstImage
;
1636 for (row
= 0; row
< srcHeight
; row
++) {
1637 GLushort
*dstUS
= (GLushort
*) dstRow
;
1638 for (col
= 0; col
< srcWidth
; col
++) {
1639 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[ACOMP
]),
1640 CHAN_TO_UBYTE(src
[RCOMP
]) );
1643 dstRow
+= dstRowStride
;
1645 dstImage
+= dstImageStride
;
1647 _mesa_free((void *) tempImage
);
1654 _mesa_texstore_la88(STORE_PARAMS
)
1656 const GLuint ui
= 1;
1657 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1659 ASSERT(dstFormat
== &_mesa_texformat_la88
);
1660 ASSERT(dstFormat
->TexelBytes
== 2);
1662 if (!ctx
->_ImageTransferState
&&
1663 !srcPacking
->SwapBytes
&&
1664 baseInternalFormat
== GL_LUMINANCE_ALPHA
&&
1665 srcFormat
== GL_LUMINANCE_ALPHA
&&
1666 srcType
== GL_UNSIGNED_BYTE
&&
1668 /* simple memcpy path */
1669 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1670 dstRowStride
, dstImageStride
,
1671 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1672 srcAddr
, srcPacking
);
1676 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1678 dstFormat
->BaseFormat
,
1679 srcWidth
, srcHeight
, srcDepth
,
1680 srcFormat
, srcType
, srcAddr
,
1682 const GLchan
*src
= tempImage
;
1683 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1684 + dstZoffset
* dstImageStride
1685 + dstYoffset
* dstRowStride
1686 + dstXoffset
* dstFormat
->TexelBytes
;
1687 GLint img
, row
, col
;
1690 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1691 for (img
= 0; img
< srcDepth
; img
++) {
1692 GLubyte
*dstRow
= dstImage
;
1693 for (row
= 0; row
< srcHeight
; row
++) {
1694 GLushort
*dstUS
= (GLushort
*) dstRow
;
1695 for (col
= 0; col
< srcWidth
; col
++) {
1696 dstUS
[col
] = PACK_COLOR_88( CHAN_TO_UBYTE(src
[RCOMP
]),
1697 CHAN_TO_UBYTE(src
[ACOMP
]) );
1700 dstRow
+= dstRowStride
;
1702 dstImage
+= dstImageStride
;
1704 _mesa_free((void *) tempImage
);
1711 _mesa_texstore_rgb332(STORE_PARAMS
)
1713 ASSERT(dstFormat
== &_mesa_texformat_rgb332
);
1714 ASSERT(dstFormat
->TexelBytes
== 1);
1716 if (!ctx
->_ImageTransferState
&&
1717 !srcPacking
->SwapBytes
&&
1718 baseInternalFormat
== GL_RGB
&&
1719 srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE_3_3_2
) {
1720 /* simple memcpy path */
1721 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1722 dstRowStride
, dstImageStride
,
1723 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1724 srcAddr
, srcPacking
);
1728 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1730 dstFormat
->BaseFormat
,
1731 srcWidth
, srcHeight
, srcDepth
,
1732 srcFormat
, srcType
, srcAddr
,
1734 const GLchan
*src
= tempImage
;
1735 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1736 + dstZoffset
* dstImageStride
1737 + dstYoffset
* dstRowStride
1738 + dstXoffset
* dstFormat
->TexelBytes
;
1739 GLint img
, row
, col
;
1742 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1743 for (img
= 0; img
< srcDepth
; img
++) {
1744 GLubyte
*dstRow
= dstImage
;
1745 for (row
= 0; row
< srcHeight
; row
++) {
1746 for (col
= 0; col
< srcWidth
; col
++) {
1747 dstRow
[col
] = PACK_COLOR_332( CHAN_TO_UBYTE(src
[RCOMP
]),
1748 CHAN_TO_UBYTE(src
[GCOMP
]),
1749 CHAN_TO_UBYTE(src
[BCOMP
]) );
1752 dstRow
+= dstRowStride
;
1754 dstImage
+= dstImageStride
;
1756 _mesa_free((void *) tempImage
);
1763 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1766 _mesa_texstore_a8(STORE_PARAMS
)
1768 ASSERT(dstFormat
== &_mesa_texformat_a8
||
1769 dstFormat
== &_mesa_texformat_l8
||
1770 dstFormat
== &_mesa_texformat_i8
);
1771 ASSERT(dstFormat
->TexelBytes
== 1);
1773 if (!ctx
->_ImageTransferState
&&
1774 !srcPacking
->SwapBytes
&&
1775 baseInternalFormat
== srcFormat
&&
1776 srcType
== GL_UNSIGNED_BYTE
) {
1777 /* simple memcpy path */
1778 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1779 dstRowStride
, dstImageStride
,
1780 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1781 srcAddr
, srcPacking
);
1785 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
1787 dstFormat
->BaseFormat
,
1788 srcWidth
, srcHeight
, srcDepth
,
1789 srcFormat
, srcType
, srcAddr
,
1791 const GLchan
*src
= tempImage
;
1792 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1793 + dstZoffset
* dstImageStride
1794 + dstYoffset
* dstRowStride
1795 + dstXoffset
* dstFormat
->TexelBytes
;
1796 GLint img
, row
, col
;
1799 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1800 for (img
= 0; img
< srcDepth
; img
++) {
1801 GLubyte
*dstRow
= dstImage
;
1802 for (row
= 0; row
< srcHeight
; row
++) {
1803 for (col
= 0; col
< srcWidth
; col
++) {
1804 dstRow
[col
] = CHAN_TO_UBYTE(src
[col
]);
1806 dstRow
+= dstRowStride
;
1809 dstImage
+= dstImageStride
;
1811 _mesa_free((void *) tempImage
);
1819 _mesa_texstore_ci8(STORE_PARAMS
)
1821 ASSERT(dstFormat
== &_mesa_texformat_ci8
);
1822 ASSERT(dstFormat
->TexelBytes
== 1);
1823 ASSERT(baseInternalFormat
== GL_COLOR_INDEX
);
1825 if (!ctx
->_ImageTransferState
&&
1826 !srcPacking
->SwapBytes
&&
1827 srcFormat
== GL_COLOR_INDEX
&&
1828 srcType
== GL_UNSIGNED_BYTE
) {
1829 /* simple memcpy path */
1830 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1831 dstRowStride
, dstImageStride
,
1832 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1833 srcAddr
, srcPacking
);
1837 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1838 + dstZoffset
* dstImageStride
1839 + dstYoffset
* dstRowStride
1840 + dstXoffset
* dstFormat
->TexelBytes
;
1842 for (img
= 0; img
< srcDepth
; img
++) {
1843 GLubyte
*dstRow
= dstImage
;
1844 for (row
= 0; row
< srcHeight
; row
++) {
1845 const GLvoid
*src
= _mesa_image_address(srcPacking
,
1846 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
1847 _mesa_unpack_index_span(ctx
, srcWidth
, GL_UNSIGNED_BYTE
, dstRow
,
1848 srcType
, src
, srcPacking
,
1849 ctx
->_ImageTransferState
);
1850 dstRow
+= dstRowStride
;
1852 dstImage
+= dstImageStride
;
1860 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1863 _mesa_texstore_ycbcr(STORE_PARAMS
)
1865 const GLuint ui
= 1;
1866 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
1868 ASSERT((dstFormat
== &_mesa_texformat_ycbcr
) ||
1869 (dstFormat
== &_mesa_texformat_ycbcr_rev
));
1870 ASSERT(dstFormat
->TexelBytes
== 2);
1871 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1872 ASSERT(srcFormat
== GL_YCBCR_MESA
);
1873 ASSERT((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
1874 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
1875 ASSERT(baseInternalFormat
== GL_YCBCR_MESA
);
1877 /* always just memcpy since no pixel transfer ops apply */
1878 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1879 dstRowStride
, dstImageStride
,
1880 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1881 srcAddr
, srcPacking
);
1883 /* Check if we need byte swapping */
1884 /* XXX the logic here _might_ be wrong */
1885 if (srcPacking
->SwapBytes
^
1886 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
1887 (dstFormat
== &_mesa_texformat_ycbcr_rev
) ^
1889 GLushort
*pImage
= (GLushort
*) ((GLubyte
*) dstAddr
1890 + dstZoffset
* dstImageStride
1891 + dstYoffset
* dstRowStride
1892 + dstXoffset
* dstFormat
->TexelBytes
);
1894 for (img
= 0; img
< srcDepth
; img
++) {
1895 GLushort
*pRow
= pImage
;
1896 for (row
= 0; row
< srcHeight
; row
++) {
1897 _mesa_swap2(pRow
, srcWidth
);
1898 pRow
+= dstRowStride
;
1900 pImage
+= dstImageStride
;
1910 * Store an image in any of the formats:
1911 * _mesa_texformat_rgba_float32
1912 * _mesa_texformat_rgb_float32
1913 * _mesa_texformat_alpha_float32
1914 * _mesa_texformat_luminance_float32
1915 * _mesa_texformat_luminance_alpha_float32
1916 * _mesa_texformat_intensity_float32
1919 _mesa_texstore_rgba_float32(STORE_PARAMS
)
1921 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1923 ASSERT(dstFormat
== &_mesa_texformat_rgba_float32
||
1924 dstFormat
== &_mesa_texformat_rgb_float32
||
1925 dstFormat
== &_mesa_texformat_alpha_float32
||
1926 dstFormat
== &_mesa_texformat_luminance_float32
||
1927 dstFormat
== &_mesa_texformat_luminance_alpha_float32
||
1928 dstFormat
== &_mesa_texformat_intensity_float32
);
1929 ASSERT(baseInternalFormat
== GL_RGBA
||
1930 baseInternalFormat
== GL_RGB
||
1931 baseInternalFormat
== GL_ALPHA
||
1932 baseInternalFormat
== GL_LUMINANCE
||
1933 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
1934 baseInternalFormat
== GL_INTENSITY
);
1935 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLfloat
));
1937 if (!ctx
->_ImageTransferState
&&
1938 !srcPacking
->SwapBytes
&&
1939 baseInternalFormat
== srcFormat
&&
1940 srcType
== GL_FLOAT
) {
1941 /* simple memcpy path */
1942 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
1943 dstRowStride
, dstImageStride
,
1944 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
1945 srcAddr
, srcPacking
);
1949 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
1951 dstFormat
->BaseFormat
,
1952 srcWidth
, srcHeight
, srcDepth
,
1953 srcFormat
, srcType
, srcAddr
,
1955 const GLfloat
*src
= tempImage
;
1957 GLubyte
*dstImage
= (GLubyte
*) dstAddr
1958 + dstZoffset
* dstImageStride
1959 + dstYoffset
* dstRowStride
1960 + dstXoffset
* dstFormat
->TexelBytes
;
1964 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
1965 bytesPerRow
= srcWidth
* components
* sizeof(GLfloat
);
1966 for (img
= 0; img
< srcDepth
; img
++) {
1967 GLubyte
*dst
= dstImage
;
1968 for (row
= 0; row
< srcHeight
; row
++) {
1969 _mesa_memcpy(dst
, src
, bytesPerRow
);
1970 dst
+= dstRowStride
;
1971 src
+= srcWidth
* components
;
1973 dstImage
+= dstImageStride
;
1976 _mesa_free((void *) tempImage
);
1983 * As above, but store 16-bit floats.
1986 _mesa_texstore_rgba_float16(STORE_PARAMS
)
1988 const GLint components
= _mesa_components_in_format(baseInternalFormat
);
1990 ASSERT(dstFormat
== &_mesa_texformat_rgba_float16
||
1991 dstFormat
== &_mesa_texformat_rgb_float16
||
1992 dstFormat
== &_mesa_texformat_alpha_float16
||
1993 dstFormat
== &_mesa_texformat_luminance_float16
||
1994 dstFormat
== &_mesa_texformat_luminance_alpha_float16
||
1995 dstFormat
== &_mesa_texformat_intensity_float16
);
1996 ASSERT(baseInternalFormat
== GL_RGBA
||
1997 baseInternalFormat
== GL_RGB
||
1998 baseInternalFormat
== GL_ALPHA
||
1999 baseInternalFormat
== GL_LUMINANCE
||
2000 baseInternalFormat
== GL_LUMINANCE_ALPHA
||
2001 baseInternalFormat
== GL_INTENSITY
);
2002 ASSERT(dstFormat
->TexelBytes
== components
* sizeof(GLhalfARB
));
2004 if (!ctx
->_ImageTransferState
&&
2005 !srcPacking
->SwapBytes
&&
2006 baseInternalFormat
== srcFormat
&&
2007 srcType
== GL_HALF_FLOAT_ARB
) {
2008 /* simple memcpy path */
2009 memcpy_texture(dstFormat
, dstAddr
, dstXoffset
, dstYoffset
, dstZoffset
,
2010 dstRowStride
, dstImageStride
,
2011 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
2012 srcAddr
, srcPacking
);
2016 const GLfloat
*tempImage
= make_temp_float_image(ctx
, dims
,
2018 dstFormat
->BaseFormat
,
2019 srcWidth
, srcHeight
, srcDepth
,
2020 srcFormat
, srcType
, srcAddr
,
2022 const GLfloat
*src
= tempImage
;
2023 GLubyte
*dstImage
= (GLubyte
*) dstAddr
2024 + dstZoffset
* dstImageStride
2025 + dstYoffset
* dstRowStride
2026 + dstXoffset
* dstFormat
->TexelBytes
;
2030 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
2031 for (img
= 0; img
< srcDepth
; img
++) {
2032 GLubyte
*dstRow
= dstImage
;
2033 for (row
= 0; row
< srcHeight
; row
++) {
2034 GLhalfARB
*dstTexel
= (GLhalfARB
*) dstRow
;
2036 for (i
= 0; i
< srcWidth
* components
; i
++) {
2037 dstTexel
[i
] = _mesa_float_to_half(src
[i
]);
2039 dstRow
+= dstRowStride
;
2040 src
+= srcWidth
* components
;
2042 dstImage
+= dstImageStride
;
2045 _mesa_free((void *) tempImage
);
2053 * Validate acces to a PBO for texture data.
2055 * \todo If the PBO is really resident in VRAM, this won't work; the
2056 * device driver should check for that and do the right thing.
2058 static const GLvoid
*
2059 validate_pbo_teximage( GLsizei width
, GLsizei height
, GLsizei depth
,
2060 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2061 const struct gl_pixelstore_attrib
*unpack
)
2063 if (unpack
->BufferObj
->Name
== 0) {
2067 else if (_mesa_validate_pbo_access(unpack
, width
, height
, depth
, format
,
2069 return ADD_POINTERS(unpack
->BufferObj
->Data
, pixels
);
2077 * Validate that unpacking compressed texture image data from a PBO
2078 * won't go out of bounds.
2080 * \todo If the PBO is really resident in VRAM, this won't work; the
2081 * device driver should check for that and do the right thing.
2083 static const GLvoid
*
2084 validate_pbo_compressed_teximage(GLsizei imageSize
, const GLvoid
*pixels
,
2085 const struct gl_pixelstore_attrib
*packing
)
2087 if (packing
->BufferObj
->Name
== 0) {
2088 /* not using a PBO - return pointer unchanged */
2093 if ((const GLubyte
*) pixels
+ imageSize
>
2094 (const GLubyte
*) packing
->BufferObj
->Size
) {
2095 /* out of bounds read! */
2099 return ADD_POINTERS(packing
->BufferObj
->Data
, pixels
);
2106 * This is the software fallback for Driver.TexImage1D()
2107 * and Driver.CopyTexImage1D().
2110 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2111 GLint internalFormat
,
2112 GLint width
, GLint border
,
2113 GLenum format
, GLenum type
, const GLvoid
*pixels
,
2114 const struct gl_pixelstore_attrib
*packing
,
2115 struct gl_texture_object
*texObj
,
2116 struct gl_texture_image
*texImage
)
2118 GLint postConvWidth
= width
;
2121 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2122 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2125 /* choose the texture format */
2126 assert(ctx
->Driver
.ChooseTextureFormat
);
2127 texImage
->TexFormat
= ctx
->Driver
.ChooseTextureFormat(ctx
, internalFormat
,
2129 assert(texImage
->TexFormat
);
2130 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2131 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2133 /* allocate memory */
2134 if (texImage
->IsCompressed
)
2135 sizeInBytes
= texImage
->CompressedSize
;
2137 sizeInBytes
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2138 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2139 if (!texImage
->Data
) {
2140 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2144 pixels
= validate_pbo_teximage(width
, 1, 1, format
, type
, pixels
, packing
);
2149 const GLint dstRowStride
= 0, dstImageStride
= 0;
2151 ASSERT(texImage
->TexFormat
->StoreImage
);
2152 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2153 texImage
->TexFormat
,
2155 0, 0, 0, /* dstX/Y/Zoffset */
2156 dstRowStride
, dstImageStride
,
2158 format
, type
, pixels
, packing
);
2160 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2165 /* GL_SGIS_generate_mipmap */
2166 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2167 _mesa_generate_mipmap(ctx
, target
,
2168 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2175 * This is the software fallback for Driver.TexImage2D()
2176 * and Driver.CopyTexImage2D().
2177 * Reasons why a driver might override this function:
2178 * - Special memory allocation needs
2179 * - Unusual row/image strides
2180 * - Special housekeeping
2183 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2184 GLint internalFormat
,
2185 GLint width
, GLint height
, GLint border
,
2186 GLenum format
, GLenum type
, const void *pixels
,
2187 const struct gl_pixelstore_attrib
*packing
,
2188 struct gl_texture_object
*texObj
,
2189 struct gl_texture_image
*texImage
)
2191 GLint postConvWidth
= width
, postConvHeight
= height
;
2192 GLint texelBytes
, sizeInBytes
;
2194 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2195 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2199 /* choose the texture format */
2200 assert(ctx
->Driver
.ChooseTextureFormat
);
2201 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2202 internalFormat
, format
, type
);
2203 assert(texImage
->TexFormat
);
2204 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2205 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2207 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2209 /* allocate memory */
2210 if (texImage
->IsCompressed
)
2211 sizeInBytes
= texImage
->CompressedSize
;
2213 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
2214 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2215 if (!texImage
->Data
) {
2216 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2220 pixels
= validate_pbo_teximage(width
, height
, 1,
2221 format
, type
, pixels
, packing
);
2226 GLint dstRowStride
, dstImageStride
= 0;
2228 if (texImage
->IsCompressed
) {
2229 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2232 dstRowStride
= postConvWidth
* texImage
->TexFormat
->TexelBytes
;
2234 ASSERT(texImage
->TexFormat
->StoreImage
);
2235 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2236 texImage
->TexFormat
,
2238 0, 0, 0, /* dstX/Y/Zoffset */
2239 dstRowStride
, dstImageStride
,
2241 format
, type
, pixels
, packing
);
2243 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2248 /* GL_SGIS_generate_mipmap */
2249 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2250 _mesa_generate_mipmap(ctx
, target
,
2251 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2259 * This is the software fallback for Driver.TexImage3D()
2260 * and Driver.CopyTexImage3D().
2263 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2264 GLint internalFormat
,
2265 GLint width
, GLint height
, GLint depth
, GLint border
,
2266 GLenum format
, GLenum type
, const void *pixels
,
2267 const struct gl_pixelstore_attrib
*packing
,
2268 struct gl_texture_object
*texObj
,
2269 struct gl_texture_image
*texImage
)
2271 GLint texelBytes
, sizeInBytes
;
2273 /* choose the texture format */
2274 assert(ctx
->Driver
.ChooseTextureFormat
);
2275 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2276 internalFormat
, format
, type
);
2277 assert(texImage
->TexFormat
);
2278 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2279 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2281 texelBytes
= texImage
->TexFormat
->TexelBytes
;
2283 /* allocate memory */
2284 if (texImage
->IsCompressed
)
2285 sizeInBytes
= texImage
->CompressedSize
;
2287 sizeInBytes
= width
* height
* depth
* texelBytes
;
2288 texImage
->Data
= MESA_PBUFFER_ALLOC(sizeInBytes
);
2289 if (!texImage
->Data
) {
2290 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2294 pixels
= validate_pbo_teximage(width
, height
, depth
,
2295 format
, type
, pixels
, packing
);
2299 /* unpack image, apply transfer ops and store in texImage->Data */
2301 GLint dstRowStride
, dstImageStride
;
2303 if (texImage
->IsCompressed
) {
2304 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,width
);
2308 dstRowStride
= width
* texImage
->TexFormat
->TexelBytes
;
2309 dstImageStride
= dstRowStride
* height
;
2311 ASSERT(texImage
->TexFormat
->StoreImage
);
2312 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2313 texImage
->TexFormat
,
2315 0, 0, 0, /* dstX/Y/Zoffset */
2316 dstRowStride
, dstImageStride
,
2317 width
, height
, depth
,
2318 format
, type
, pixels
, packing
);
2320 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2325 /* GL_SGIS_generate_mipmap */
2326 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2327 _mesa_generate_mipmap(ctx
, target
,
2328 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2337 * This is the software fallback for Driver.TexSubImage1D()
2338 * and Driver.CopyTexSubImage1D().
2341 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2342 GLint xoffset
, GLint width
,
2343 GLenum format
, GLenum type
, const void *pixels
,
2344 const struct gl_pixelstore_attrib
*packing
,
2345 struct gl_texture_object
*texObj
,
2346 struct gl_texture_image
*texImage
)
2348 pixels
= validate_pbo_teximage(width
, 1, 1,
2349 format
, type
, pixels
, packing
);
2354 const GLint dstRowStride
= 0, dstImageStride
= 0;
2356 ASSERT(texImage
->TexFormat
->StoreImage
);
2357 success
= texImage
->TexFormat
->StoreImage(ctx
, 1, texImage
->Format
,
2358 texImage
->TexFormat
,
2360 xoffset
, 0, 0, /* offsets */
2361 dstRowStride
, dstImageStride
,
2363 format
, type
, pixels
, packing
);
2365 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
2370 /* GL_SGIS_generate_mipmap */
2371 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2372 _mesa_generate_mipmap(ctx
, target
,
2373 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2381 * This is the software fallback for Driver.TexSubImage2D()
2382 * and Driver.CopyTexSubImage2D().
2385 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2386 GLint xoffset
, GLint yoffset
,
2387 GLint width
, GLint height
,
2388 GLenum format
, GLenum type
, const void *pixels
,
2389 const struct gl_pixelstore_attrib
*packing
,
2390 struct gl_texture_object
*texObj
,
2391 struct gl_texture_image
*texImage
)
2393 pixels
= validate_pbo_teximage(width
, height
, 1,
2394 format
, type
, pixels
, packing
);
2399 GLint dstRowStride
= 0, dstImageStride
= 0;
2401 if (texImage
->IsCompressed
) {
2402 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2406 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2408 ASSERT(texImage
->TexFormat
->StoreImage
);
2409 success
= texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
2410 texImage
->TexFormat
,
2412 xoffset
, yoffset
, 0,
2413 dstRowStride
, dstImageStride
,
2415 format
, type
, pixels
, packing
);
2417 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2422 /* GL_SGIS_generate_mipmap */
2423 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2424 _mesa_generate_mipmap(ctx
, target
,
2425 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2432 * This is the software fallback for Driver.TexSubImage3D().
2433 * and Driver.CopyTexSubImage3D().
2436 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2437 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2438 GLint width
, GLint height
, GLint depth
,
2439 GLenum format
, GLenum type
, const void *pixels
,
2440 const struct gl_pixelstore_attrib
*packing
,
2441 struct gl_texture_object
*texObj
,
2442 struct gl_texture_image
*texImage
)
2444 pixels
= validate_pbo_teximage(width
, height
, depth
,
2445 format
, type
, pixels
, packing
);
2450 GLint dstRowStride
, dstImageStride
;
2452 if (texImage
->IsCompressed
) {
2453 dstRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2455 dstImageStride
= 0; /* XXX fix */
2458 dstRowStride
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
2459 dstImageStride
= dstRowStride
* texImage
->Height
;
2461 ASSERT(texImage
->TexFormat
->StoreImage
);
2462 success
= texImage
->TexFormat
->StoreImage(ctx
, 3, texImage
->Format
,
2463 texImage
->TexFormat
,
2465 xoffset
, yoffset
, zoffset
,
2466 dstRowStride
, dstImageStride
,
2467 width
, height
, depth
,
2468 format
, type
, pixels
, packing
);
2470 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
2475 /* GL_SGIS_generate_mipmap */
2476 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2477 _mesa_generate_mipmap(ctx
, target
,
2478 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2485 * Fallback for Driver.CompressedTexImage1D()
2488 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
2489 GLint internalFormat
,
2490 GLint width
, GLint border
,
2491 GLsizei imageSize
, const GLvoid
*data
,
2492 struct gl_texture_object
*texObj
,
2493 struct gl_texture_image
*texImage
)
2495 /* this space intentionally left blank */
2501 * Fallback for Driver.CompressedTexImage2D()
2504 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
2505 GLint internalFormat
,
2506 GLint width
, GLint height
, GLint border
,
2507 GLsizei imageSize
, const GLvoid
*data
,
2508 struct gl_texture_object
*texObj
,
2509 struct gl_texture_image
*texImage
)
2511 /* This is pretty simple, basically just do a memcpy without worrying
2512 * about the usual image unpacking or image transfer operations.
2516 ASSERT(texImage
->Width
> 0);
2517 ASSERT(texImage
->Height
> 0);
2518 ASSERT(texImage
->Depth
== 1);
2519 ASSERT(texImage
->Data
== NULL
); /* was freed in glCompressedTexImage2DARB */
2521 /* choose the texture format */
2522 assert(ctx
->Driver
.ChooseTextureFormat
);
2523 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2524 internalFormat
, 0, 0);
2525 assert(texImage
->TexFormat
);
2526 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2527 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2529 /* allocate storage */
2530 texImage
->Data
= MESA_PBUFFER_ALLOC(imageSize
);
2531 if (!texImage
->Data
) {
2532 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
2536 data
= validate_pbo_compressed_teximage(imageSize
, data
, &ctx
->Unpack
);
2541 ASSERT(texImage
->CompressedSize
== (GLuint
) imageSize
);
2542 MEMCPY(texImage
->Data
, data
, imageSize
);
2544 /* GL_SGIS_generate_mipmap */
2545 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2546 _mesa_generate_mipmap(ctx
, target
,
2547 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2555 * Fallback for Driver.CompressedTexImage3D()
2558 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
2559 GLint internalFormat
,
2560 GLint width
, GLint height
, GLint depth
,
2562 GLsizei imageSize
, const GLvoid
*data
,
2563 struct gl_texture_object
*texObj
,
2564 struct gl_texture_image
*texImage
)
2566 /* this space intentionally left blank */
2572 * Fallback for Driver.CompressedTexSubImage1D()
2575 _mesa_store_compressed_texsubimage1d(GLcontext
*ctx
, GLenum target
,
2577 GLint xoffset
, GLsizei width
,
2579 GLsizei imageSize
, const GLvoid
*data
,
2580 struct gl_texture_object
*texObj
,
2581 struct gl_texture_image
*texImage
)
2583 /* this space intentionally left blank */
2588 * Fallback for Driver.CompressedTexSubImage2D()
2591 _mesa_store_compressed_texsubimage2d(GLcontext
*ctx
, GLenum target
,
2593 GLint xoffset
, GLint yoffset
,
2594 GLsizei width
, GLsizei height
,
2596 GLsizei imageSize
, const GLvoid
*data
,
2597 struct gl_texture_object
*texObj
,
2598 struct gl_texture_image
*texImage
)
2600 GLint bytesPerRow
, destRowStride
, srcRowStride
;
2605 /* these should have been caught sooner */
2606 ASSERT((width
& 3) == 0 || width
== 2 || width
== 1);
2607 ASSERT((height
& 3) == 0 || height
== 2 || height
== 1);
2608 ASSERT((xoffset
& 3) == 0);
2609 ASSERT((yoffset
& 3) == 0);
2611 data
= validate_pbo_compressed_teximage(imageSize
, data
, &ctx
->Unpack
);
2615 srcRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
, width
);
2616 src
= (const GLubyte
*) data
;
2618 destRowStride
= _mesa_compressed_row_stride(texImage
->IntFormat
,
2620 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
2621 texImage
->IntFormat
,
2623 (GLubyte
*) texImage
->Data
);
2625 bytesPerRow
= srcRowStride
;
2628 for (i
= 0; i
< rows
; i
++) {
2629 MEMCPY(dest
, src
, bytesPerRow
);
2630 dest
+= destRowStride
;
2631 src
+= srcRowStride
;
2634 /* GL_SGIS_generate_mipmap */
2635 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
2636 _mesa_generate_mipmap(ctx
, target
,
2637 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
2644 * Fallback for Driver.CompressedTexSubImage3D()
2647 _mesa_store_compressed_texsubimage3d(GLcontext
*ctx
, GLenum target
,
2649 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2650 GLsizei width
, GLsizei height
, GLsizei depth
,
2652 GLsizei imageSize
, const GLvoid
*data
,
2653 struct gl_texture_object
*texObj
,
2654 struct gl_texture_image
*texImage
)
2656 /* this space intentionally left blank */
2661 * Average together two rows of a source image to produce a single new
2662 * row in the dest image. It's legal for the two source rows to point
2663 * to the same data. The source width must be equal to either the
2664 * dest width or two times the dest width.
2667 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
2668 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
2669 GLint dstWidth
, GLvoid
*dstRow
)
2671 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
2672 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
2674 /* This assertion is no longer valid with non-power-of-2 textures
2675 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2678 switch (format
->MesaFormat
) {
2679 case MESA_FORMAT_RGBA
:
2682 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
2683 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
2684 GLchan (*dst
)[4] = (GLchan (*)[4]) 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]) / 4;
2689 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2690 rowB
[j
][1] + rowB
[k
][1]) / 4;
2691 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2692 rowB
[j
][2] + rowB
[k
][2]) / 4;
2693 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2694 rowB
[j
][3] + rowB
[k
][3]) / 4;
2698 case MESA_FORMAT_RGB
:
2701 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
2702 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
2703 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
2704 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2705 i
++, j
+= colStride
, k
+= colStride
) {
2706 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2707 rowB
[j
][0] + rowB
[k
][0]) / 4;
2708 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2709 rowB
[j
][1] + rowB
[k
][1]) / 4;
2710 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2711 rowB
[j
][2] + rowB
[k
][2]) / 4;
2715 case MESA_FORMAT_ALPHA
:
2716 case MESA_FORMAT_LUMINANCE
:
2717 case MESA_FORMAT_INTENSITY
:
2720 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
2721 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
2722 GLchan
*dst
= (GLchan
*) dstRow
;
2723 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2724 i
++, j
+= colStride
, k
+= colStride
) {
2725 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2729 case MESA_FORMAT_LUMINANCE_ALPHA
:
2732 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
2733 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
2734 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
2735 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2736 i
++, j
+= colStride
, k
+= colStride
) {
2737 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2738 rowB
[j
][0] + rowB
[k
][0]) / 4;
2739 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2740 rowB
[j
][1] + rowB
[k
][1]) / 4;
2744 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32
:
2747 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
2748 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
2749 GLfloat
*dst
= (GLfloat
*) dstRow
;
2750 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2751 i
++, j
+= colStride
, k
+= colStride
) {
2752 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
2756 case MESA_FORMAT_DEPTH_COMPONENT16
:
2759 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2760 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2761 GLushort
*dst
= (GLushort
*) dstRow
;
2762 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2763 i
++, j
+= colStride
, k
+= colStride
) {
2764 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
2768 /* Begin hardware formats */
2769 case MESA_FORMAT_RGBA8888
:
2770 case MESA_FORMAT_ABGR8888
:
2771 case MESA_FORMAT_ARGB8888
:
2772 case MESA_FORMAT_BGRA8888
:
2775 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
2776 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
2777 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
2778 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2779 i
++, j
+= colStride
, k
+= colStride
) {
2780 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2781 rowB
[j
][0] + rowB
[k
][0]) / 4;
2782 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2783 rowB
[j
][1] + rowB
[k
][1]) / 4;
2784 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2785 rowB
[j
][2] + rowB
[k
][2]) / 4;
2786 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2787 rowB
[j
][3] + rowB
[k
][3]) / 4;
2791 case MESA_FORMAT_RGB888
:
2792 case MESA_FORMAT_BGR888
:
2795 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
2796 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
2797 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
2798 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2799 i
++, j
+= colStride
, k
+= colStride
) {
2800 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2801 rowB
[j
][0] + rowB
[k
][0]) / 4;
2802 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2803 rowB
[j
][1] + rowB
[k
][1]) / 4;
2804 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2805 rowB
[j
][2] + rowB
[k
][2]) / 4;
2809 case MESA_FORMAT_RGB565
:
2810 case MESA_FORMAT_BGR565
:
2813 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2814 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2815 GLushort
*dst
= (GLushort
*) dstRow
;
2816 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2817 i
++, j
+= colStride
, k
+= colStride
) {
2818 const GLint rowAr0
= rowA
[j
] & 0x1f;
2819 const GLint rowAr1
= rowA
[k
] & 0x1f;
2820 const GLint rowBr0
= rowB
[j
] & 0x1f;
2821 const GLint rowBr1
= rowB
[k
] & 0x1f;
2822 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
2823 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
2824 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
2825 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
2826 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
2827 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
2828 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
2829 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
2830 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2831 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2832 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2833 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
2837 case MESA_FORMAT_ARGB4444
:
2838 case MESA_FORMAT_BGRA4444
:
2841 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2842 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2843 GLushort
*dst
= (GLushort
*) dstRow
;
2844 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2845 i
++, j
+= colStride
, k
+= colStride
) {
2846 const GLint rowAr0
= rowA
[j
] & 0xf;
2847 const GLint rowAr1
= rowA
[k
] & 0xf;
2848 const GLint rowBr0
= rowB
[j
] & 0xf;
2849 const GLint rowBr1
= rowB
[k
] & 0xf;
2850 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
2851 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
2852 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
2853 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
2854 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
2855 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
2856 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
2857 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
2858 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
2859 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
2860 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
2861 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
2862 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2863 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2864 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2865 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2866 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
2870 case MESA_FORMAT_ARGB1555
:
2873 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
2874 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
2875 GLushort
*dst
= (GLushort
*) dstRow
;
2876 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2877 i
++, j
+= colStride
, k
+= colStride
) {
2878 const GLint rowAr0
= rowA
[j
] & 0x1f;
2879 const GLint rowAr1
= rowA
[k
] & 0x1f;
2880 const GLint rowBr0
= rowB
[j
] & 0x1f;
2881 const GLint rowBr1
= rowB
[k
] & 0xf;
2882 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
2883 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
2884 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
2885 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
2886 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
2887 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
2888 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
2889 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
2890 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
2891 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
2892 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
2893 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
2894 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2895 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2896 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2897 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
2898 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
2902 case MESA_FORMAT_AL88
:
2905 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
2906 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
2907 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
2908 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2909 i
++, j
+= colStride
, k
+= colStride
) {
2910 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2911 rowB
[j
][0] + rowB
[k
][0]) >> 2;
2912 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2913 rowB
[j
][1] + rowB
[k
][1]) >> 2;
2917 case MESA_FORMAT_RGB332
:
2920 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
2921 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
2922 GLubyte
*dst
= (GLubyte
*) dstRow
;
2923 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2924 i
++, j
+= colStride
, k
+= colStride
) {
2925 const GLint rowAr0
= rowA
[j
] & 0x3;
2926 const GLint rowAr1
= rowA
[k
] & 0x3;
2927 const GLint rowBr0
= rowB
[j
] & 0x3;
2928 const GLint rowBr1
= rowB
[k
] & 0x3;
2929 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
2930 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
2931 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
2932 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
2933 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
2934 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
2935 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
2936 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
2937 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
2938 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
2939 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
2940 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
2944 case MESA_FORMAT_A8
:
2945 case MESA_FORMAT_L8
:
2946 case MESA_FORMAT_I8
:
2947 case MESA_FORMAT_CI8
:
2950 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
2951 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
2952 GLubyte
*dst
= (GLubyte
*) dstRow
;
2953 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2954 i
++, j
+= colStride
, k
+= colStride
) {
2955 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
2959 case MESA_FORMAT_RGBA_FLOAT32
:
2962 const GLfloat (*rowA
)[4] = (const GLfloat (*)[4]) srcRowA
;
2963 const GLfloat (*rowB
)[4] = (const GLfloat (*)[4]) srcRowB
;
2964 GLfloat (*dst
)[4] = (GLfloat (*)[4]) dstRow
;
2965 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2966 i
++, j
+= colStride
, k
+= colStride
) {
2967 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
2968 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
2969 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
2970 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
2971 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
2972 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
2973 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
2974 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
2978 case MESA_FORMAT_RGBA_FLOAT16
:
2980 GLuint i
, j
, k
, comp
;
2981 const GLhalfARB (*rowA
)[4] = (const GLhalfARB (*)[4]) srcRowA
;
2982 const GLhalfARB (*rowB
)[4] = (const GLhalfARB (*)[4]) srcRowB
;
2983 GLhalfARB (*dst
)[4] = (GLhalfARB (*)[4]) dstRow
;
2984 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
2985 i
++, j
+= colStride
, k
+= colStride
) {
2986 for (comp
= 0; comp
< 4; comp
++) {
2987 GLfloat aj
, ak
, bj
, bk
;
2988 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
2989 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
2990 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
2991 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
2992 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
2997 case MESA_FORMAT_RGB_FLOAT32
:
3000 const GLfloat (*rowA
)[3] = (const GLfloat (*)[3]) srcRowA
;
3001 const GLfloat (*rowB
)[3] = (const GLfloat (*)[3]) srcRowB
;
3002 GLfloat (*dst
)[3] = (GLfloat (*)[3]) dstRow
;
3003 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3004 i
++, j
+= colStride
, k
+= colStride
) {
3005 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3006 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3007 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3008 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3009 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
3010 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
3014 case MESA_FORMAT_RGB_FLOAT16
:
3016 GLuint i
, j
, k
, comp
;
3017 const GLhalfARB (*rowA
)[3] = (const GLhalfARB (*)[3]) srcRowA
;
3018 const GLhalfARB (*rowB
)[3] = (const GLhalfARB (*)[3]) srcRowB
;
3019 GLhalfARB (*dst
)[3] = (GLhalfARB (*)[3]) dstRow
;
3020 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3021 i
++, j
+= colStride
, k
+= colStride
) {
3022 for (comp
= 0; comp
< 3; comp
++) {
3023 GLfloat aj
, ak
, bj
, bk
;
3024 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3025 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3026 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3027 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3028 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3033 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32
:
3036 const GLfloat (*rowA
)[2] = (const GLfloat (*)[2]) srcRowA
;
3037 const GLfloat (*rowB
)[2] = (const GLfloat (*)[2]) srcRowB
;
3038 GLfloat (*dst
)[2] = (GLfloat (*)[2]) dstRow
;
3039 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3040 i
++, j
+= colStride
, k
+= colStride
) {
3041 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
3042 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
3043 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
3044 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
3048 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16
:
3050 GLuint i
, j
, k
, comp
;
3051 const GLhalfARB (*rowA
)[2] = (const GLhalfARB (*)[2]) srcRowA
;
3052 const GLhalfARB (*rowB
)[2] = (const GLhalfARB (*)[2]) srcRowB
;
3053 GLhalfARB (*dst
)[2] = (GLhalfARB (*)[2]) dstRow
;
3054 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3055 i
++, j
+= colStride
, k
+= colStride
) {
3056 for (comp
= 0; comp
< 2; comp
++) {
3057 GLfloat aj
, ak
, bj
, bk
;
3058 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
3059 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
3060 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
3061 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
3062 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3067 case MESA_FORMAT_ALPHA_FLOAT32
:
3068 case MESA_FORMAT_LUMINANCE_FLOAT32
:
3069 case MESA_FORMAT_INTENSITY_FLOAT32
:
3072 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
3073 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
3074 GLfloat
*dst
= (GLfloat
*) dstRow
;
3075 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3076 i
++, j
+= colStride
, k
+= colStride
) {
3077 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
3081 case MESA_FORMAT_ALPHA_FLOAT16
:
3082 case MESA_FORMAT_LUMINANCE_FLOAT16
:
3083 case MESA_FORMAT_INTENSITY_FLOAT16
:
3086 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
3087 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
3088 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
3089 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
3090 i
++, j
+= colStride
, k
+= colStride
) {
3091 GLfloat aj
, ak
, bj
, bk
;
3092 aj
= _mesa_half_to_float(rowA
[j
]);
3093 ak
= _mesa_half_to_float(rowA
[k
]);
3094 bj
= _mesa_half_to_float(rowB
[j
]);
3095 bk
= _mesa_half_to_float(rowB
[k
]);
3096 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
3102 _mesa_problem(NULL
, "bad format in do_row()");
3108 * These functions generate a 1/2-size mipmap image from a source image.
3109 * Texture borders are handled by copying or averaging the source image's
3110 * border texels, depending on the scale-down factor.
3114 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3115 GLint srcWidth
, const GLubyte
*srcPtr
,
3116 GLint dstWidth
, GLubyte
*dstPtr
)
3118 const GLint bpt
= format
->TexelBytes
;
3122 /* skip the border pixel, if any */
3123 src
= srcPtr
+ border
* bpt
;
3124 dst
= dstPtr
+ border
* bpt
;
3126 /* we just duplicate the input row, kind of hack, saves code */
3127 do_row(format
, srcWidth
- 2 * border
, src
, src
,
3128 dstWidth
- 2 * border
, dst
);
3131 /* copy left-most pixel from source */
3132 MEMCPY(dstPtr
, srcPtr
, bpt
);
3133 /* copy right-most pixel from source */
3134 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3135 srcPtr
+ (srcWidth
- 1) * bpt
,
3142 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3143 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
3144 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
3146 const GLint bpt
= format
->TexelBytes
;
3147 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3148 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3149 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3150 const GLint srcRowStride
= bpt
* srcWidth
;
3151 const GLint dstRowStride
= bpt
* dstWidth
;
3152 const GLubyte
*srcA
, *srcB
;
3156 /* Compute src and dst pointers, skipping any border */
3157 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
3159 srcB
= srcA
+ srcRowStride
;
3162 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
3164 for (row
= 0; row
< dstHeightNB
; row
++) {
3165 do_row(format
, srcWidthNB
, srcA
, srcB
,
3167 srcA
+= 2 * srcRowStride
;
3168 srcB
+= 2 * srcRowStride
;
3169 dst
+= dstRowStride
;
3172 /* This is ugly but probably won't be used much */
3174 /* fill in dest border */
3175 /* lower-left border pixel */
3176 MEMCPY(dstPtr
, srcPtr
, bpt
);
3177 /* lower-right border pixel */
3178 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
3179 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
3180 /* upper-left border pixel */
3181 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
3182 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
3183 /* upper-right border pixel */
3184 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
3185 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
3187 do_row(format
, srcWidthNB
,
3190 dstWidthNB
, dstPtr
+ bpt
);
3192 do_row(format
, srcWidthNB
,
3193 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3194 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
3196 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
3197 /* left and right borders */
3198 if (srcHeight
== dstHeight
) {
3199 /* copy border pixel from src to dst */
3200 for (row
= 1; row
< srcHeight
; row
++) {
3201 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
3202 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
3203 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
3204 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
3208 /* average two src pixels each dest pixel */
3209 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
3211 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
3212 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
3213 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
3215 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
3216 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
3217 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
3225 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
3226 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
3227 const GLubyte
*srcPtr
,
3228 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
3231 const GLint bpt
= format
->TexelBytes
;
3232 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
3233 const GLint srcDepthNB
= srcDepth
- 2 * border
;
3234 const GLint dstWidthNB
= dstWidth
- 2 * border
;
3235 const GLint dstHeightNB
= dstHeight
- 2 * border
;
3236 const GLint dstDepthNB
= dstDepth
- 2 * border
;
3237 GLvoid
*tmpRowA
, *tmpRowB
;
3239 GLint bytesPerSrcImage
, bytesPerDstImage
;
3240 GLint bytesPerSrcRow
, bytesPerDstRow
;
3241 GLint srcImageOffset
, srcRowOffset
;
3243 (void) srcDepthNB
; /* silence warnings */
3245 /* Need two temporary row buffers */
3246 tmpRowA
= MALLOC(srcWidth
* bpt
);
3249 tmpRowB
= MALLOC(srcWidth
* bpt
);
3255 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
3256 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
3258 bytesPerSrcRow
= srcWidth
* bpt
;
3259 bytesPerDstRow
= dstWidth
* bpt
;
3261 /* Offset between adjacent src images to be averaged together */
3262 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
3264 /* Offset between adjacent src rows to be averaged together */
3265 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
3268 * Need to average together up to 8 src pixels for each dest pixel.
3269 * Break that down into 3 operations:
3270 * 1. take two rows from source image and average them together.
3271 * 2. take two rows from next source image and average them together.
3272 * 3. take the two averaged rows and average them for the final dst row.
3276 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3277 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3280 for (img
= 0; img
< dstDepthNB
; img
++) {
3281 /* first source image pointer, skipping border */
3282 const GLubyte
*imgSrcA
= srcPtr
3283 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
3284 + img
* (bytesPerSrcImage
+ srcImageOffset
);
3285 /* second source image pointer, skipping border */
3286 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
3287 /* address of the dest image, skipping border */
3288 GLubyte
*imgDst
= dstPtr
3289 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
3290 + img
* bytesPerDstImage
;
3292 /* setup the four source row pointers and the dest row pointer */
3293 const GLubyte
*srcImgARowA
= imgSrcA
;
3294 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
3295 const GLubyte
*srcImgBRowA
= imgSrcB
;
3296 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
3297 GLubyte
*dstImgRow
= imgDst
;
3299 for (row
= 0; row
< dstHeightNB
; row
++) {
3300 /* Average together two rows from first src image */
3301 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
3302 srcWidthNB
, tmpRowA
);
3303 /* Average together two rows from second src image */
3304 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
3305 srcWidthNB
, tmpRowB
);
3306 /* Average together the temp rows to make the final row */
3307 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
3308 dstWidthNB
, dstImgRow
);
3309 /* advance to next rows */
3310 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
3311 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
3312 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
3313 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
3314 dstImgRow
+= bytesPerDstRow
;
3321 /* Luckily we can leverage the make_2d_mipmap() function here! */
3323 /* do front border image */
3324 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
3325 dstWidth
, dstHeight
, dstPtr
);
3326 /* do back border image */
3327 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
3328 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
3329 dstWidth
, dstHeight
,
3330 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
3331 /* do four remaining border edges that span the image slices */
3332 if (srcDepth
== dstDepth
) {
3333 /* just copy border pixels from src to dst */
3334 for (img
= 0; img
< dstDepthNB
; img
++) {
3338 /* do border along [img][row=0][col=0] */
3339 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
3340 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3341 MEMCPY(dst
, src
, bpt
);
3343 /* do border along [img][row=dstHeight-1][col=0] */
3344 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3345 + (srcHeight
- 1) * bytesPerSrcRow
;
3346 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3347 + (dstHeight
- 1) * bytesPerDstRow
;
3348 MEMCPY(dst
, src
, bpt
);
3350 /* do border along [img][row=0][col=dstWidth-1] */
3351 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3352 + (srcWidth
- 1) * bpt
;
3353 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3354 + (dstWidth
- 1) * bpt
;
3355 MEMCPY(dst
, src
, bpt
);
3357 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3358 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3359 + (bytesPerSrcImage
- bpt
);
3360 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3361 + (bytesPerDstImage
- bpt
);
3362 MEMCPY(dst
, src
, bpt
);
3366 /* average border pixels from adjacent src image pairs */
3367 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
3368 for (img
= 0; img
< dstDepthNB
; img
++) {
3372 /* do border along [img][row=0][col=0] */
3373 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
3374 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
3375 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3377 /* do border along [img][row=dstHeight-1][col=0] */
3378 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3379 + (srcHeight
- 1) * bytesPerSrcRow
;
3380 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3381 + (dstHeight
- 1) * bytesPerDstRow
;
3382 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3384 /* do border along [img][row=0][col=dstWidth-1] */
3385 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3386 + (srcWidth
- 1) * bpt
;
3387 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3388 + (dstWidth
- 1) * bpt
;
3389 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3391 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3392 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
3393 + (bytesPerSrcImage
- bpt
);
3394 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
3395 + (bytesPerDstImage
- bpt
);
3396 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
3404 * For GL_SGIX_generate_mipmap:
3405 * Generate a complete set of mipmaps from texObj's base-level image.
3406 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3409 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
3410 const struct gl_texture_unit
*texUnit
,
3411 struct gl_texture_object
*texObj
)
3413 const struct gl_texture_image
*srcImage
;
3414 const struct gl_texture_format
*convertFormat
;
3415 const GLubyte
*srcData
= NULL
;
3416 GLubyte
*dstData
= NULL
;
3417 GLint level
, maxLevels
;
3420 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
3423 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
3424 ASSERT(maxLevels
> 0); /* bad target */
3426 /* Find convertFormat - the format that do_row() will process */
3427 if (srcImage
->IsCompressed
) {
3428 /* setup for compressed textures */
3430 GLint components
, size
;
3433 assert(texObj
->Target
== GL_TEXTURE_2D
);
3435 if (srcImage
->Format
== GL_RGB
) {
3436 convertFormat
= &_mesa_texformat_rgb
;
3439 else if (srcImage
->Format
== GL_RGBA
) {
3440 convertFormat
= &_mesa_texformat_rgba
;
3444 _mesa_problem(ctx
, "bad srcImage->Format in _mesa_generate_mipmaps");
3448 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3449 size
= _mesa_bytes_per_pixel(srcImage
->Format
, CHAN_TYPE
)
3450 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
3451 /* 20 extra bytes, just be safe when calling last FetchTexel */
3452 srcData
= (GLubyte
*) MALLOC(size
);
3454 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3457 dstData
= (GLubyte
*) MALLOC(size
/ 2); /* 1/4 would probably be OK */
3459 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
3460 FREE((void *) srcData
);
3464 /* decompress base image here */
3465 dst
= (GLchan
*) srcData
;
3466 for (row
= 0; row
< srcImage
->Height
; row
++) {
3468 for (col
= 0; col
< srcImage
->Width
; col
++) {
3469 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
3476 convertFormat
= srcImage
->TexFormat
;
3479 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
3480 && level
< maxLevels
- 1; level
++) {
3481 /* generate image[level+1] from image[level] */
3482 const struct gl_texture_image
*srcImage
;
3483 struct gl_texture_image
*dstImage
;
3484 GLint srcWidth
, srcHeight
, srcDepth
;
3485 GLint dstWidth
, dstHeight
, dstDepth
;
3486 GLint border
, bytesPerTexel
;
3488 /* get src image parameters */
3489 srcImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3491 srcWidth
= srcImage
->Width
;
3492 srcHeight
= srcImage
->Height
;
3493 srcDepth
= srcImage
->Depth
;
3494 border
= srcImage
->Border
;
3496 /* compute next (level+1) image size */
3497 if (srcWidth
- 2 * border
> 1) {
3498 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
3501 dstWidth
= srcWidth
; /* can't go smaller */
3503 if (srcHeight
- 2 * border
> 1) {
3504 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
3507 dstHeight
= srcHeight
; /* can't go smaller */
3509 if (srcDepth
- 2 * border
> 1) {
3510 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
3513 dstDepth
= srcDepth
; /* can't go smaller */
3516 if (dstWidth
== srcWidth
&&
3517 dstHeight
== srcHeight
&&
3518 dstDepth
== srcDepth
) {
3520 if (srcImage
->IsCompressed
) {
3521 FREE((void *) srcData
);
3527 /* get dest gl_texture_image */
3528 dstImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
+ 1);
3530 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3534 /* Free old image data */
3536 MESA_PBUFFER_FREE(dstImage
->Data
);
3538 /* initialize new image */
3539 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
3540 dstDepth
, border
, srcImage
->IntFormat
);
3541 dstImage
->DriverData
= NULL
;
3542 dstImage
->TexFormat
= srcImage
->TexFormat
;
3543 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
3544 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
3545 ASSERT(dstImage
->TexFormat
);
3546 ASSERT(dstImage
->FetchTexelc
);
3547 ASSERT(dstImage
->FetchTexelf
);
3549 /* Alloc new teximage data buffer.
3550 * Setup src and dest data pointers.
3552 if (dstImage
->IsCompressed
) {
3553 ASSERT(dstImage
->CompressedSize
> 0); /* set by init_teximage_fields*/
3554 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstImage
->CompressedSize
);
3555 if (!dstImage
->Data
) {
3556 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3559 /* srcData and dstData are already set */
3564 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
3565 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
3566 dstImage
->Data
= MESA_PBUFFER_ALLOC(dstWidth
* dstHeight
* dstDepth
3568 if (!dstImage
->Data
) {
3569 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
3572 srcData
= (const GLubyte
*) srcImage
->Data
;
3573 dstData
= (GLubyte
*) dstImage
->Data
;
3577 * We use simple 2x2 averaging to compute the next mipmap level.
3581 make_1d_mipmap(convertFormat
, border
,
3586 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3587 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3588 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3589 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3590 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3591 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3592 make_2d_mipmap(convertFormat
, border
,
3593 srcWidth
, srcHeight
, srcData
,
3594 dstWidth
, dstHeight
, dstData
);
3597 make_3d_mipmap(convertFormat
, border
,
3598 srcWidth
, srcHeight
, srcDepth
, srcData
,
3599 dstWidth
, dstHeight
, dstDepth
, dstData
);
3601 case GL_TEXTURE_RECTANGLE_NV
:
3602 /* no mipmaps, do nothing */
3605 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
3609 if (dstImage
->IsCompressed
) {
3611 /* compress image from dstData into dstImage->Data */
3612 const GLenum srcFormat
= convertFormat
->BaseFormat
;
3613 GLint dstRowStride
= _mesa_compressed_row_stride(srcImage
->IntFormat
,
3615 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
3616 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->Format
,
3617 dstImage
->TexFormat
,
3619 0, 0, 0, /* dstX/Y/Zoffset */
3620 dstRowStride
, 0, /* strides */
3621 dstWidth
, dstHeight
, 1, /* size */
3622 srcFormat
, CHAN_TYPE
,
3623 dstData
, /* src data, actually */
3624 &ctx
->DefaultPacking
);
3625 /* swap src and dest pointers */
3626 temp
= (GLubyte
*) srcData
;
3631 } /* loop over mipmap levels */
3636 * Helper function for drivers which need to rescale texture images to
3637 * certain aspect ratios.
3638 * Nearest filtering only (for broken hardware that can't support
3639 * all aspect ratios). This can be made a lot faster, but I don't
3640 * really care enough...
3642 void _mesa_rescale_teximage2d( GLuint bytesPerPixel
, GLuint dstRowStride
,
3643 GLint srcWidth
, GLint srcHeight
,
3644 GLint dstWidth
, GLint dstHeight
,
3645 const GLvoid
*srcImage
, GLvoid
*dstImage
)
3649 #define INNER_LOOP( TYPE, HOP, WOP ) \
3650 for ( row = 0 ; row < dstHeight ; row++ ) { \
3651 GLint srcRow = row HOP hScale; \
3652 for ( col = 0 ; col < dstWidth ; col++ ) { \
3653 GLint srcCol = col WOP wScale; \
3654 dst[col] = src[srcRow * srcWidth + srcCol]; \
3656 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3659 #define RESCALE_IMAGE( TYPE ) \
3661 const TYPE *src = (const TYPE *)srcImage; \
3662 TYPE *dst = (TYPE *)dstImage; \
3664 if ( srcHeight <= dstHeight ) { \
3665 const GLint hScale = dstHeight / srcHeight; \
3666 if ( srcWidth <= dstWidth ) { \
3667 const GLint wScale = dstWidth / srcWidth; \
3668 INNER_LOOP( TYPE, /, / ); \
3671 const GLint wScale = srcWidth / dstWidth; \
3672 INNER_LOOP( TYPE, /, * ); \
3676 const GLint hScale = srcHeight / dstHeight; \
3677 if ( srcWidth <= dstWidth ) { \
3678 const GLint wScale = dstWidth / srcWidth; \
3679 INNER_LOOP( TYPE, *, / ); \
3682 const GLint wScale = srcWidth / dstWidth; \
3683 INNER_LOOP( TYPE, *, * ); \
3688 switch ( bytesPerPixel
) {
3690 RESCALE_IMAGE( GLuint
);
3694 RESCALE_IMAGE( GLushort
);
3698 RESCALE_IMAGE( GLubyte
);
3701 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3707 * Upscale an image by replication, not (typical) stretching.
3708 * We use this when the image width or height is less than a
3709 * certain size (4, 8) and we need to upscale an image.
3712 _mesa_upscale_teximage2d (GLsizei inWidth
, GLsizei inHeight
,
3713 GLsizei outWidth
, GLsizei outHeight
,
3714 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
3719 ASSERT(outWidth
>= inWidth
);
3720 ASSERT(outHeight
>= inHeight
);
3721 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
3723 ASSERT((outWidth
& 3) == 0);
3724 ASSERT((outHeight
& 3) == 0);
3727 for (i
= 0; i
< outHeight
; i
++) {
3728 const GLint ii
= i
% inHeight
;
3729 for (j
= 0; j
< outWidth
; j
++) {
3730 const GLint jj
= j
% inWidth
;
3731 for (k
= 0; k
< comps
; k
++) {
3732 dest
[(i
* outWidth
+ j
) * comps
+ k
]
3733 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];