1 /* $Id: texstore.c,v 1.30 2001/07/13 16:38:44 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #include "texformat.h"
45 * Given an internal texture format enum or 1, 2, 3, 4 return the
46 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
47 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
48 * number of components for the format. Return -1 if invalid enum.
50 * GH: Do we really need this? We have the number of bytes per texel
51 * in the texture format structures, so why don't we just use that?
54 components_in_intformat( GLint format
)
71 case GL_LUMINANCE_ALPHA
:
72 case GL_LUMINANCE4_ALPHA4
:
73 case GL_LUMINANCE6_ALPHA2
:
74 case GL_LUMINANCE8_ALPHA8
:
75 case GL_LUMINANCE12_ALPHA4
:
76 case GL_LUMINANCE12_ALPHA12
:
77 case GL_LUMINANCE16_ALPHA16
:
106 case GL_COLOR_INDEX1_EXT
:
107 case GL_COLOR_INDEX2_EXT
:
108 case GL_COLOR_INDEX4_EXT
:
109 case GL_COLOR_INDEX8_EXT
:
110 case GL_COLOR_INDEX12_EXT
:
111 case GL_COLOR_INDEX16_EXT
:
113 case GL_DEPTH_COMPONENT
:
114 case GL_DEPTH_COMPONENT16_SGIX
:
115 case GL_DEPTH_COMPONENT24_SGIX
:
116 case GL_DEPTH_COMPONENT32_SGIX
:
119 return -1; /* error */
125 * This function is used to transfer the user's image data into a texture
126 * image buffer. We handle both full texture images and subtexture images.
127 * We also take care of all image transfer operations here, including
128 * convolution, scale/bias, colortables, etc.
130 * The destination texel channel type is always GLchan.
132 * A hardware driver may use this as a helper routine to unpack and
133 * apply pixel transfer ops into a temporary image buffer. Then,
134 * convert the temporary image into the special hardware format.
137 * dimensions - 1, 2, or 3
138 * texFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
140 * texDestAddr - destination image address
141 * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
142 * dstXoffset, dstYoffset, dstZoffset - position to store the image within
143 * the destination 3D texture
144 * dstRowStride, dstImageStride - dest image strides in bytes
145 * srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
146 * srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
147 * srcPacking - describes packing of incoming image.
148 * transferOps - mask of pixel transfer operations
151 transfer_teximage(GLcontext
*ctx
, GLuint dimensions
,
152 GLenum texDestFormat
, GLvoid
*texDestAddr
,
153 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
154 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
155 GLint dstRowStride
, GLint dstImageStride
,
156 GLenum srcFormat
, GLenum srcType
,
157 const GLvoid
*srcAddr
,
158 const struct gl_pixelstore_attrib
*srcPacking
,
164 ASSERT(dimensions
>= 1 && dimensions
<= 3);
166 ASSERT(srcWidth
>= 1);
167 ASSERT(srcHeight
>= 1);
168 ASSERT(srcDepth
>= 1);
169 ASSERT(dstXoffset
>= 0);
170 ASSERT(dstYoffset
>= 0);
171 ASSERT(dstZoffset
>= 0);
172 ASSERT(dstRowStride
>= 0);
173 ASSERT(dstImageStride
>= 0);
177 texComponents
= components_in_intformat(texDestFormat
);
179 /* try common 2D texture cases first */
180 if (!transferOps
&& dimensions
== 2 && srcType
== CHAN_TYPE
) {
182 if (srcFormat
== texDestFormat
) {
183 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
184 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
186 const GLchan
*src
= (const GLchan
*) _mesa_image_address(
187 srcPacking
, srcAddr
, srcWidth
, srcHeight
,
188 srcFormat
, srcType
, 0, 0, 0);
189 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
190 srcWidth
, srcFormat
, srcType
);
191 const GLint widthInBytes
= srcWidth
* texComponents
* sizeof(GLchan
);
192 GLchan
*dst
= (GLchan
*) texDestAddr
+ dstYoffset
* dstRowStride
193 + dstXoffset
* texComponents
;
194 if (srcRowStride
== widthInBytes
&& dstRowStride
== widthInBytes
) {
195 MEMCPY(dst
, src
, srcHeight
* widthInBytes
);
199 for (i
= 0; i
< srcHeight
; i
++) {
200 MEMCPY(dst
, src
, widthInBytes
);
205 return; /* all done */
207 else if (srcFormat
== GL_RGBA
&& texDestFormat
== GL_RGB
) {
208 /* commonly used by Quake */
209 const GLchan
*src
= (const GLchan
*) _mesa_image_address(
210 srcPacking
, srcAddr
, srcWidth
, srcHeight
,
211 srcFormat
, srcType
, 0, 0, 0);
212 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
213 srcWidth
, srcFormat
, srcType
);
214 GLchan
*dst
= (GLchan
*) texDestAddr
+ dstYoffset
* dstRowStride
215 + dstXoffset
* texComponents
;
217 for (i
= 0; i
< srcHeight
; i
++) {
218 const GLchan
*s
= src
;
220 for (j
= 0; j
< srcWidth
; j
++) {
222 *d
++ = *s
++; /*green*/
223 *d
++ = *s
++; /*blue*/
229 return; /* all done */
234 * General case solutions
236 if (texDestFormat
== GL_COLOR_INDEX
) {
237 /* color index texture */
238 const GLenum texType
= CHAN_TYPE
;
240 GLchan
*dest
= (GLchan
*) texDestAddr
+ dstZoffset
* dstImageStride
241 + dstYoffset
* dstRowStride
242 + dstXoffset
* texComponents
;
243 for (img
= 0; img
< srcDepth
; img
++) {
244 GLchan
*destRow
= dest
;
245 for (row
= 0; row
< srcHeight
; row
++) {
246 const GLvoid
*src
= _mesa_image_address(srcPacking
,
247 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
248 _mesa_unpack_index_span(ctx
, srcWidth
, texType
, destRow
,
249 srcType
, src
, srcPacking
, transferOps
);
250 destRow
+= dstRowStride
;
252 dest
+= dstImageStride
;
255 else if (texDestFormat
== GL_DEPTH_COMPONENT
) {
256 /* Depth texture (shadow maps) */
258 GLubyte
*dest
= (GLubyte
*) texDestAddr
259 + dstZoffset
* dstImageStride
260 + dstYoffset
* dstRowStride
261 + dstXoffset
* texComponents
;
262 for (img
= 0; img
< srcDepth
; img
++) {
263 GLubyte
*destRow
= dest
;
264 for (row
= 0; row
< srcHeight
; row
++) {
265 const GLvoid
*src
= _mesa_image_address(srcPacking
,
266 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
267 _mesa_unpack_depth_span(ctx
, srcWidth
, (GLfloat
*) destRow
,
268 srcType
, src
, srcPacking
);
269 destRow
+= dstRowStride
;
271 dest
+= dstImageStride
;
275 /* regular, color texture */
276 if ((dimensions
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
277 (dimensions
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
278 (dimensions
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
280 * Fill texture image with convolution
283 GLint convWidth
= srcWidth
, convHeight
= srcHeight
;
284 GLfloat
*tmpImage
, *convImage
;
285 tmpImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
287 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
290 convImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
292 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
297 for (img
= 0; img
< srcDepth
; img
++) {
299 GLfloat
*dstf
= tmpImage
;
302 /* unpack and do transfer ops up to convolution */
303 for (row
= 0; row
< srcHeight
; row
++) {
304 const GLvoid
*src
= _mesa_image_address(srcPacking
,
305 srcAddr
, srcWidth
, srcHeight
,
306 srcFormat
, srcType
, img
, row
, 0);
307 _mesa_unpack_float_color_span(ctx
, srcWidth
, GL_RGBA
, dstf
,
308 srcFormat
, srcType
, src
, srcPacking
,
309 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
311 dstf
+= srcWidth
* 4;
315 if (dimensions
== 1) {
316 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
317 _mesa_convolve_1d_image(ctx
, &convWidth
, tmpImage
, convImage
);
320 if (ctx
->Pixel
.Convolution2DEnabled
) {
321 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
322 tmpImage
, convImage
);
325 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
326 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
327 tmpImage
, convImage
);
331 /* packing and transfer ops after convolution */
333 dest
= (GLchan
*) texDestAddr
+ (dstZoffset
+ img
) * dstImageStride
334 + dstYoffset
* dstRowStride
;
335 for (row
= 0; row
< convHeight
; row
++) {
336 _mesa_pack_float_rgba_span(ctx
, convWidth
,
337 (const GLfloat (*)[4]) srcf
,
338 texDestFormat
, CHAN_TYPE
,
339 dest
, &_mesa_native_packing
,
341 & IMAGE_POST_CONVOLUTION_BITS
);
342 srcf
+= convWidth
* 4;
343 dest
+= dstRowStride
;
355 GLchan
*dest
= (GLchan
*) texDestAddr
+ dstZoffset
* dstImageStride
356 + dstYoffset
* dstRowStride
357 + dstXoffset
* texComponents
;
358 for (img
= 0; img
< srcDepth
; img
++) {
359 GLchan
*destRow
= dest
;
360 for (row
= 0; row
< srcHeight
; row
++) {
361 const GLvoid
*srcRow
= _mesa_image_address(srcPacking
,
362 srcAddr
, srcWidth
, srcHeight
,
363 srcFormat
, srcType
, img
, row
, 0);
364 _mesa_unpack_chan_color_span(ctx
, srcWidth
, texDestFormat
,
365 destRow
, srcFormat
, srcType
, srcRow
,
366 srcPacking
, transferOps
);
367 destRow
+= dstRowStride
;
369 dest
+= dstImageStride
;
378 * Transfer a texture image from user space to <destAddr> applying all
379 * needed image transfer operations and storing the result in the format
380 * specified by <dstFormat>. <dstFormat> may be any format from texformat.h.
382 * dimensions - 1, 2 or 3
383 * baseInternalFormat - base format of the internal texture format
384 * specified by the user. This is very important, see below.
385 * dstFormat - destination image format
386 * dstAddr - destination address
387 * srcWidth, srcHeight, srcDepth - size of source iamge
388 * dstX/Y/Zoffset - as specified by glTexSubImage
389 * dstRowStride - stride between dest rows in bytes
390 * dstImagetride - stride between dest images in bytes
391 * srcFormat, srcType - incoming image format and datatype
392 * srcAddr - source image address
393 * srcPacking - packing params of source image
395 * XXX this function is a bit more complicated than it should be. If
396 * _mesa_convert_texsubimage[123]d could handle any dest/source formats
397 * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
398 * could simplify things here.
401 _mesa_transfer_teximage(GLcontext
*ctx
, GLuint dimensions
,
402 GLenum baseInternalFormat
,
403 const struct gl_texture_format
*dstFormat
,
405 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
406 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
407 GLint dstRowStride
, GLint dstImageStride
,
408 GLenum srcFormat
, GLenum srcType
,
409 const GLvoid
*srcAddr
,
410 const struct gl_pixelstore_attrib
*srcPacking
)
412 const GLint dstRowStridePixels
= dstRowStride
/ dstFormat
->TexelBytes
;
413 const GLint dstImageStridePixels
= dstImageStride
/ dstFormat
->TexelBytes
;
415 GLuint transferOps
= ctx
->_ImageTransferState
;
416 GLboolean freeSourceData
= GL_FALSE
;
417 GLint postConvWidth
= srcWidth
, postConvHeight
= srcHeight
;
419 assert(baseInternalFormat
> 0);
421 if (transferOps
& IMAGE_CONVOLUTION_BIT
) {
422 _mesa_adjust_image_for_convolution(ctx
, dimensions
, &postConvWidth
,
427 * Consider this scenario: The user's source image is GL_RGB and the
428 * requested internal format is GL_LUMINANCE. Now suppose the device
429 * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
430 * texture format. In that case we still need to do an intermediate
431 * conversion to luminance format so that the incoming red channel gets
432 * replicated into the dest red, green and blue channels. The following
433 * code takes care of that.
435 if (dstFormat
->BaseFormat
!= baseInternalFormat
) {
436 /* Allocate storage for temporary image in the baseInternalFormat */
437 const GLint texelSize
= _mesa_components_in_format(baseInternalFormat
)
439 const GLint bytes
= texelSize
* postConvWidth
* postConvHeight
*srcDepth
;
440 const GLint tmpRowStride
= texelSize
* postConvWidth
;
441 const GLint tmpImgStride
= texelSize
* postConvWidth
* postConvHeight
;
442 GLvoid
*tmpImage
= MALLOC(bytes
);
445 transfer_teximage(ctx
, dimensions
, baseInternalFormat
, tmpImage
,
446 srcWidth
, srcHeight
, srcDepth
,
447 0, 0, 0, /* x/y/zoffset */
448 tmpRowStride
, tmpImgStride
,
449 srcFormat
, srcType
, srcAddr
, srcPacking
, transferOps
);
451 /* this is our new source image */
452 srcWidth
= postConvWidth
;
453 srcHeight
= postConvHeight
;
454 srcFormat
= baseInternalFormat
;
457 srcPacking
= &_mesa_native_packing
;
458 freeSourceData
= GL_TRUE
;
459 transferOps
= 0; /* image transfer ops were completed */
462 /* Let the optimized tex conversion functions take a crack at the
463 * image conversion if the dest format is a h/w format.
465 if (_mesa_is_hardware_tex_format(dstFormat
)) {
470 if (dimensions
== 1) {
471 makeTemp
= !_mesa_convert_texsubimage1d(dstFormat
->MesaFormat
,
478 else if (dimensions
== 2) {
479 makeTemp
= !_mesa_convert_texsubimage2d(dstFormat
->MesaFormat
,
480 dstXoffset
, dstYoffset
,
488 assert(dimensions
== 3);
489 makeTemp
= !_mesa_convert_texsubimage3d(dstFormat
->MesaFormat
,
490 dstXoffset
, dstYoffset
, dstZoffset
,
491 srcWidth
, srcHeight
, srcDepth
,
492 dstRowStridePixels
, dstImageStridePixels
,
494 srcPacking
, srcAddr
, dstAddr
);
499 FREE((void *) srcAddr
);
505 /* software texture format */
510 GLint postConvWidth
= srcWidth
, postConvHeight
= srcHeight
;
512 GLuint tmpComps
, tmpTexelSize
;
513 GLint tmpRowStride
, tmpImageStride
;
516 if (transferOps
& IMAGE_CONVOLUTION_BIT
) {
517 _mesa_adjust_image_for_convolution(ctx
, dimensions
, &postConvWidth
,
521 tmpFormat
= dstFormat
->BaseFormat
;
522 tmpComps
= _mesa_components_in_format(tmpFormat
);
523 tmpTexelSize
= tmpComps
* sizeof(GLchan
);
524 tmpRowStride
= postConvWidth
* tmpTexelSize
;
525 tmpImageStride
= postConvWidth
* postConvHeight
* tmpTexelSize
;
526 tmpImage
= (GLubyte
*) MALLOC(postConvWidth
* postConvHeight
*
527 srcDepth
* tmpTexelSize
);
530 FREE((void *) srcAddr
);
534 transfer_teximage(ctx
, dimensions
, tmpFormat
, tmpImage
,
535 srcWidth
, srcHeight
, srcDepth
,
536 0, 0, 0, /* x/y/zoffset */
537 tmpRowStride
, tmpImageStride
,
538 srcFormat
, srcType
, srcAddr
, srcPacking
, transferOps
);
541 FREE((void *) srcAddr
);
543 /* the temp image is our new source image */
544 srcWidth
= postConvWidth
;
545 srcHeight
= postConvHeight
;
546 srcFormat
= tmpFormat
;
549 srcPacking
= &_mesa_native_packing
;
550 freeSourceData
= GL_TRUE
;
553 if (_mesa_is_hardware_tex_format(dstFormat
)) {
555 if (dimensions
== 1) {
557 b
= _mesa_convert_texsubimage1d(dstFormat
->MesaFormat
,
565 else if (dimensions
== 2) {
567 b
= _mesa_convert_texsubimage2d(dstFormat
->MesaFormat
,
568 dstXoffset
, dstYoffset
,
578 b
= _mesa_convert_texsubimage3d(dstFormat
->MesaFormat
,
579 dstXoffset
, dstYoffset
, dstZoffset
,
580 srcWidth
, srcHeight
, srcDepth
,
581 dstRowStridePixels
, dstImageStridePixels
,
583 srcPacking
, srcAddr
, dstAddr
);
588 /* software format */
590 transfer_teximage(ctx
, dimensions
, dstFormat
->BaseFormat
, dstAddr
,
591 srcWidth
, srcHeight
, srcDepth
,
592 dstXoffset
, dstYoffset
, dstZoffset
,
593 dstRowStride
, dstImageStride
,
594 srcFormat
, srcType
, srcAddr
, srcPacking
, transferOps
);
598 FREE((void *) srcAddr
); /* the temp image */
603 * This is the software fallback for Driver.TexImage1D().
604 * The texture image type will be GLchan.
605 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
606 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
610 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
611 GLint internalFormat
,
612 GLint width
, GLint border
,
613 GLenum format
, GLenum type
, const GLvoid
*pixels
,
614 const struct gl_pixelstore_attrib
*packing
,
615 struct gl_texture_object
*texObj
,
616 struct gl_texture_image
*texImage
)
618 GLint postConvWidth
= width
;
619 GLint texelBytes
, sizeInBytes
;
621 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
622 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
625 /* choose the texture format */
626 assert(ctx
->Driver
.ChooseTextureFormat
);
627 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
628 internalFormat
, format
, type
);
629 assert(texImage
->TexFormat
);
630 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel1D
;
632 texelBytes
= texImage
->TexFormat
->TexelBytes
;
634 /* Compute image size, in bytes */
635 if (texImage
->IsCompressed
) {
636 assert(ctx
->Driver
.CompressedTextureSize
);
637 sizeInBytes
= ctx
->Driver
.CompressedTextureSize(ctx
, texImage
);
638 assert(sizeInBytes
> 0);
639 texImage
->CompressedSize
= sizeInBytes
;
642 sizeInBytes
= postConvWidth
* texelBytes
;
645 /* allocate memory */
646 texImage
->Data
= MALLOC(sizeInBytes
);
647 if (!texImage
->Data
) {
648 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
652 /* unpack image, apply transfer ops and store in texImage->Data */
653 _mesa_transfer_teximage(ctx
, 1, _mesa_base_tex_format(ctx
, internalFormat
),
654 texImage
->TexFormat
, texImage
->Data
,
655 width
, 1, 1, 0, 0, 0,
656 0, /* dstRowStride */
657 0, /* dstImageStride */
658 format
, type
, pixels
, packing
);
660 /* GL_SGIS_generate_mipmap */
661 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
662 _mesa_generate_mipmap(ctx
, &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
669 * This is the software fallback for Driver.TexImage2D().
670 * The texture image type will be GLchan.
671 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
672 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
674 * NOTE: if real texture compression is supported, this whole function
675 * will need to be overridden.
678 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
679 GLint internalFormat
,
680 GLint width
, GLint height
, GLint border
,
681 GLenum format
, GLenum type
, const void *pixels
,
682 const struct gl_pixelstore_attrib
*packing
,
683 struct gl_texture_object
*texObj
,
684 struct gl_texture_image
*texImage
)
686 GLint postConvWidth
= width
, postConvHeight
= height
;
687 GLint texelBytes
, sizeInBytes
;
689 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
690 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
694 /* choose the texture format */
695 assert(ctx
->Driver
.ChooseTextureFormat
);
696 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
697 internalFormat
, format
, type
);
698 assert(texImage
->TexFormat
);
699 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel2D
;
701 texelBytes
= texImage
->TexFormat
->TexelBytes
;
703 /* Compute image size, in bytes */
704 if (texImage
->IsCompressed
) {
705 assert(ctx
->Driver
.CompressedTextureSize
);
706 sizeInBytes
= ctx
->Driver
.CompressedTextureSize(ctx
, texImage
);
707 assert(sizeInBytes
> 0);
708 texImage
->CompressedSize
= sizeInBytes
;
711 sizeInBytes
= postConvWidth
* postConvHeight
* texelBytes
;
714 /* allocate memory */
715 texImage
->Data
= MALLOC(sizeInBytes
);
716 if (!texImage
->Data
) {
717 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
721 /* unpack image, apply transfer ops and store in texImage->Data */
722 _mesa_transfer_teximage(ctx
, 2, _mesa_base_tex_format(ctx
, internalFormat
),
723 texImage
->TexFormat
, texImage
->Data
,
724 width
, height
, 1, 0, 0, 0,
725 texImage
->Width
* texelBytes
,
726 0, /* dstImageStride */
727 format
, type
, pixels
, packing
);
729 /* GL_SGIS_generate_mipmap */
730 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
731 _mesa_generate_mipmap(ctx
, &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
739 * This is the software fallback for Driver.TexImage3D().
740 * The texture image type will be GLchan.
741 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
742 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
746 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
747 GLint internalFormat
,
748 GLint width
, GLint height
, GLint depth
, GLint border
,
749 GLenum format
, GLenum type
, const void *pixels
,
750 const struct gl_pixelstore_attrib
*packing
,
751 struct gl_texture_object
*texObj
,
752 struct gl_texture_image
*texImage
)
754 GLint texelBytes
, sizeInBytes
;
756 /* choose the texture format */
757 assert(ctx
->Driver
.ChooseTextureFormat
);
758 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
759 internalFormat
, format
, type
);
760 assert(texImage
->TexFormat
);
761 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel3D
;
763 texelBytes
= texImage
->TexFormat
->TexelBytes
;
765 /* Compute image size, in bytes */
766 if (texImage
->IsCompressed
) {
767 assert(ctx
->Driver
.CompressedTextureSize
);
768 sizeInBytes
= ctx
->Driver
.CompressedTextureSize(ctx
, texImage
);
769 assert(sizeInBytes
> 0);
770 texImage
->CompressedSize
= sizeInBytes
;
773 sizeInBytes
= width
* height
* depth
* texelBytes
;
776 /* allocate memory */
777 texImage
->Data
= MALLOC(sizeInBytes
);
778 if (!texImage
->Data
) {
779 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
783 /* unpack image, apply transfer ops and store in texImage->Data */
784 _mesa_transfer_teximage(ctx
, 3, _mesa_base_tex_format(ctx
, internalFormat
),
785 texImage
->TexFormat
, texImage
->Data
,
786 width
, height
, depth
, 0, 0, 0,
787 texImage
->Width
* texelBytes
,
788 texImage
->Width
* texImage
->Height
* texelBytes
,
789 format
, type
, pixels
, packing
);
791 /* GL_SGIS_generate_mipmap */
792 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
793 _mesa_generate_mipmap(ctx
, &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
802 * This is the software fallback for Driver.TexSubImage1D().
805 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
806 GLint xoffset
, GLint width
,
807 GLenum format
, GLenum type
, const void *pixels
,
808 const struct gl_pixelstore_attrib
*packing
,
809 struct gl_texture_object
*texObj
,
810 struct gl_texture_image
*texImage
)
812 _mesa_transfer_teximage(ctx
, 1,
813 _mesa_base_tex_format(ctx
, texImage
->IntFormat
),
814 texImage
->TexFormat
, texImage
->Data
,
815 width
, 1, 1, /* src size */
816 xoffset
, 0, 0, /* dest offsets */
817 0, /* dstRowStride */
818 0, /* dstImageStride */
819 format
, type
, pixels
, packing
);
821 /* GL_SGIS_generate_mipmap */
822 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
823 _mesa_generate_mipmap(ctx
, &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
830 * This is the software fallback for Driver.TexSubImage2D().
833 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
834 GLint xoffset
, GLint yoffset
,
835 GLint width
, GLint height
,
836 GLenum format
, GLenum type
, const void *pixels
,
837 const struct gl_pixelstore_attrib
*packing
,
838 struct gl_texture_object
*texObj
,
839 struct gl_texture_image
*texImage
)
841 _mesa_transfer_teximage(ctx
, 2,
842 _mesa_base_tex_format(ctx
, texImage
->IntFormat
),
843 texImage
->TexFormat
, texImage
->Data
,
844 width
, height
, 1, /* src size */
845 xoffset
, yoffset
, 0, /* dest offsets */
846 texImage
->Width
* texImage
->TexFormat
->TexelBytes
,
847 0, /* dstImageStride */
848 format
, type
, pixels
, packing
);
850 /* GL_SGIS_generate_mipmap */
851 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
852 _mesa_generate_mipmap(ctx
, &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
859 * This is the software fallback for Driver.TexSubImage3D().
862 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
863 GLint xoffset
, GLint yoffset
, GLint zoffset
,
864 GLint width
, GLint height
, GLint depth
,
865 GLenum format
, GLenum type
, const void *pixels
,
866 const struct gl_pixelstore_attrib
*packing
,
867 struct gl_texture_object
*texObj
,
868 struct gl_texture_image
*texImage
)
870 const GLint texelBytes
= texImage
->TexFormat
->TexelBytes
;
871 _mesa_transfer_teximage(ctx
, 3,
872 _mesa_base_tex_format(ctx
, texImage
->IntFormat
),
873 texImage
->TexFormat
, texImage
->Data
,
874 width
, height
, depth
, /* src size */
875 xoffset
, yoffset
, xoffset
, /* dest offsets */
876 texImage
->Width
* texelBytes
,
877 texImage
->Width
* texImage
->Height
* texelBytes
,
878 format
, type
, pixels
, packing
);
879 /* GL_SGIS_generate_mipmap */
880 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
881 _mesa_generate_mipmap(ctx
, &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
],
890 * Fallback for Driver.CompressedTexImage1D()
893 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
894 GLint internalFormat
,
895 GLint width
, GLint border
,
896 GLsizei imageSize
, const GLvoid
*data
,
897 struct gl_texture_object
*texObj
,
898 struct gl_texture_image
*texImage
)
901 * The device driver has to do it all.
908 * Fallback for Driver.CompressedTexImage2D()
911 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
912 GLint internalFormat
,
913 GLint width
, GLint height
, GLint border
,
914 GLsizei imageSize
, const GLvoid
*data
,
915 struct gl_texture_object
*texObj
,
916 struct gl_texture_image
*texImage
)
919 * The device driver has to do it all.
926 * Fallback for Driver.CompressedTexImage3D()
929 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
930 GLint internalFormat
,
931 GLint width
, GLint height
, GLint depth
,
933 GLsizei imageSize
, const GLvoid
*data
,
934 struct gl_texture_object
*texObj
,
935 struct gl_texture_image
*texImage
)
938 * The device driver has to do it all.
945 * Fallback for Driver.GetCompressedTexImage3D()
946 * This will probably work find for hardware drivers. That is, hardware
947 * drivers won't have to override this function, unless the compressed
948 * texture must first be fetched from the TRAM.
951 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
,
952 GLint level
, void *image
,
953 const struct gl_texture_object
*texObj
,
954 struct gl_texture_image
*texImage
)
956 assert(texImage
->IsCompressed
);
957 assert(texImage
->CompressedSize
> 0);
958 MEMCPY(image
, texImage
->Data
, texImage
->CompressedSize
);
964 * This is the fallback for Driver.TestProxyTexImage().
967 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
968 GLint internalFormat
, GLenum format
, GLenum type
,
969 GLint width
, GLint height
, GLint depth
, GLint border
)
971 struct gl_texture_unit
*texUnit
;
972 struct gl_texture_object
*texObj
;
973 struct gl_texture_image
*texImage
;
978 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
979 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
980 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
983 * The core Mesa code will have already tested the image size, etc.
984 * If a driver has more stringent texture limits to enforce it will
985 * have to override this function.
987 /* choose the texture format */
988 assert(ctx
->Driver
.ChooseTextureFormat
);
989 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
990 internalFormat
, format
, type
);
991 assert(texImage
->TexFormat
);
999 * Average together two rows of a source image to produce a single new
1000 * row in the dest image. It's legal for the two source rows to point
1001 * to the same data. The source width must be equal to either the
1002 * dest width or two times the dest width.
1005 do_row(const struct gl_texture_format
*format
, GLint srcWidth
,
1006 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
1007 GLint dstWidth
, GLvoid
*dstRow
)
1009 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
1010 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
1012 assert(srcWidth
== dstWidth
|| srcWidth
== 2 * dstWidth
);
1014 switch (format
->MesaFormat
) {
1015 case MESA_FORMAT_RGBA
:
1018 const GLchan (*rowA
)[4] = (const GLchan (*)[4]) srcRowA
;
1019 const GLchan (*rowB
)[4] = (const GLchan (*)[4]) srcRowB
;
1020 GLchan (*dst
)[4] = (GLchan (*)[4]) dstRow
;
1021 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1022 i
++, j
+= colStride
, k
+= colStride
) {
1023 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
1024 rowB
[j
][0] + rowB
[k
][0]) >> 2;
1025 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
1026 rowB
[j
][1] + rowB
[k
][1]) >> 2;
1027 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
1028 rowB
[j
][2] + rowB
[k
][2]) >> 2;
1029 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
1030 rowB
[j
][3] + rowB
[k
][3]) >> 2;
1034 case MESA_FORMAT_RGB
:
1037 const GLchan (*rowA
)[3] = (const GLchan (*)[3]) srcRowA
;
1038 const GLchan (*rowB
)[3] = (const GLchan (*)[3]) srcRowB
;
1039 GLchan (*dst
)[3] = (GLchan (*)[3]) dstRow
;
1040 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1041 i
++, j
+= colStride
, k
+= colStride
) {
1042 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
1043 rowB
[j
][0] + rowB
[k
][0]) >> 2;
1044 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
1045 rowB
[j
][1] + rowB
[k
][1]) >> 2;
1046 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
1047 rowB
[j
][2] + rowB
[k
][2]) >> 2;
1051 case MESA_FORMAT_ALPHA
:
1052 case MESA_FORMAT_LUMINANCE
:
1053 case MESA_FORMAT_INTENSITY
:
1054 case MESA_FORMAT_COLOR_INDEX
:
1057 const GLchan
*rowA
= (const GLchan
*) srcRowA
;
1058 const GLchan
*rowB
= (const GLchan
*) srcRowB
;
1059 GLchan
*dst
= (GLchan
*) dstRow
;
1060 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1061 i
++, j
+= colStride
, k
+= colStride
) {
1062 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
1066 case MESA_FORMAT_LUMINANCE_ALPHA
:
1069 const GLchan (*rowA
)[2] = (const GLchan (*)[2]) srcRowA
;
1070 const GLchan (*rowB
)[2] = (const GLchan (*)[2]) srcRowB
;
1071 GLchan (*dst
)[2] = (GLchan (*)[2]) dstRow
;
1072 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1073 i
++, j
+= colStride
, k
+= colStride
) {
1074 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
1075 rowB
[j
][0] + rowB
[k
][0]) >> 2;
1076 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
1077 rowB
[j
][1] + rowB
[k
][1]) >> 2;
1081 case MESA_FORMAT_DEPTH_COMPONENT
:
1084 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
1085 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
1086 GLfloat
*dst
= (GLfloat
*) dstRow
;
1087 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1088 i
++, j
+= colStride
, k
+= colStride
) {
1089 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
1093 /* Begin hardware formats */
1094 case MESA_FORMAT_RGBA8888
:
1095 case MESA_FORMAT_ARGB8888
:
1098 const GLubyte (*rowA
)[4] = (const GLubyte (*)[4]) srcRowA
;
1099 const GLubyte (*rowB
)[4] = (const GLubyte (*)[4]) srcRowB
;
1100 GLubyte (*dst
)[4] = (GLubyte (*)[4]) dstRow
;
1101 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1102 i
++, j
+= colStride
, k
+= colStride
) {
1103 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
1104 rowB
[j
][0] + rowB
[k
][0]) >> 2;
1105 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
1106 rowB
[j
][1] + rowB
[k
][1]) >> 2;
1107 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
1108 rowB
[j
][2] + rowB
[k
][2]) >> 2;
1109 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
1110 rowB
[j
][3] + rowB
[k
][3]) >> 2;
1114 case MESA_FORMAT_RGB888
:
1117 const GLubyte (*rowA
)[3] = (const GLubyte (*)[3]) srcRowA
;
1118 const GLubyte (*rowB
)[3] = (const GLubyte (*)[3]) srcRowB
;
1119 GLubyte (*dst
)[3] = (GLubyte (*)[3]) dstRow
;
1120 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1121 i
++, j
+= colStride
, k
+= colStride
) {
1122 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
1123 rowB
[j
][0] + rowB
[k
][0]) >> 2;
1124 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
1125 rowB
[j
][1] + rowB
[k
][1]) >> 2;
1126 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
1127 rowB
[j
][2] + rowB
[k
][2]) >> 2;
1131 case MESA_FORMAT_RGB565
:
1134 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
1135 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
1136 GLushort
*dst
= (GLushort
*) dstRow
;
1137 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1138 i
++, j
+= colStride
, k
+= colStride
) {
1139 const GLint rowAr0
= rowA
[j
] & 0x1f;
1140 const GLint rowAr1
= rowA
[k
] & 0x1f;
1141 const GLint rowBr0
= rowB
[j
] & 0x1f;
1142 const GLint rowBr1
= rowB
[k
] & 0x1f;
1143 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
1144 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
1145 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
1146 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
1147 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
1148 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
1149 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
1150 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
1151 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 4;
1152 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 4;
1153 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 4;
1154 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
1158 case MESA_FORMAT_ARGB4444
:
1161 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
1162 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
1163 GLushort
*dst
= (GLushort
*) dstRow
;
1164 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1165 i
++, j
+= colStride
, k
+= colStride
) {
1166 const GLint rowAr0
= rowA
[j
] & 0xf;
1167 const GLint rowAr1
= rowA
[k
] & 0xf;
1168 const GLint rowBr0
= rowB
[j
] & 0xf;
1169 const GLint rowBr1
= rowB
[k
] & 0xf;
1170 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
1171 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
1172 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
1173 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
1174 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
1175 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
1176 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
1177 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
1178 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
1179 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
1180 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
1181 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
1182 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 4;
1183 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 4;
1184 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 4;
1185 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 4;
1186 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
1190 case MESA_FORMAT_ARGB1555
:
1193 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
1194 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
1195 GLushort
*dst
= (GLushort
*) dstRow
;
1196 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1197 i
++, j
+= colStride
, k
+= colStride
) {
1198 const GLint rowAr0
= rowA
[j
] & 0x1f;
1199 const GLint rowAr1
= rowA
[k
] & 0x1f;
1200 const GLint rowBr0
= rowB
[j
] & 0x1f;
1201 const GLint rowBr1
= rowB
[k
] & 0xf;
1202 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
1203 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
1204 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
1205 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
1206 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
1207 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
1208 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
1209 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
1210 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
1211 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
1212 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
1213 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
1214 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 4;
1215 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 4;
1216 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 4;
1217 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 4;
1218 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
1222 case MESA_FORMAT_AL88
:
1225 const GLubyte (*rowA
)[2] = (const GLubyte (*)[2]) srcRowA
;
1226 const GLubyte (*rowB
)[2] = (const GLubyte (*)[2]) srcRowB
;
1227 GLubyte (*dst
)[2] = (GLubyte (*)[2]) dstRow
;
1228 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1229 i
++, j
+= colStride
, k
+= colStride
) {
1230 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
1231 rowB
[j
][0] + rowB
[k
][0]) >> 2;
1232 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
1233 rowB
[j
][1] + rowB
[k
][1]) >> 2;
1237 case MESA_FORMAT_RGB332
:
1240 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
1241 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
1242 GLubyte
*dst
= (GLubyte
*) dstRow
;
1243 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1244 i
++, j
+= colStride
, k
+= colStride
) {
1245 const GLint rowAr0
= rowA
[j
] & 0x3;
1246 const GLint rowAr1
= rowA
[k
] & 0x3;
1247 const GLint rowBr0
= rowB
[j
] & 0x3;
1248 const GLint rowBr1
= rowB
[k
] & 0x3;
1249 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
1250 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
1251 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
1252 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
1253 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
1254 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
1255 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
1256 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
1257 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 4;
1258 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 4;
1259 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 4;
1260 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
1264 case MESA_FORMAT_A8
:
1265 case MESA_FORMAT_L8
:
1266 case MESA_FORMAT_I8
:
1267 case MESA_FORMAT_CI8
:
1270 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
1271 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
1272 GLubyte
*dst
= (GLubyte
*) dstRow
;
1273 for (i
= j
= 0, k
= k0
; i
< dstWidth
;
1274 i
++, j
+= colStride
, k
+= colStride
) {
1275 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
1280 _mesa_problem(NULL
, "bad format in do_row()");
1286 * These functions generate a 1/2-size mipmap image from a source image.
1287 * Texture borders are handled by copying or averaging the source image's
1288 * border texels, depending on the scale-down factor.
1292 make_1d_mipmap(const struct gl_texture_format
*format
, GLint border
,
1293 GLint srcWidth
, const GLubyte
*srcPtr
,
1294 GLint dstWidth
, GLubyte
*dstPtr
)
1296 const GLint bpt
= format
->TexelBytes
;
1300 /* skip the border pixel, if any */
1301 src
= srcPtr
+ border
* bpt
;
1302 dst
= dstPtr
+ border
* bpt
;
1304 /* we just duplicate the input row, kind of hack, saves code */
1305 do_row(format
, srcWidth
- 2 * border
, src
, src
,
1306 dstWidth
- 2 * border
, dst
);
1309 /* copy left-most pixel from source */
1310 MEMCPY(dstPtr
, srcPtr
, bpt
);
1311 /* copy right-most pixel from source */
1312 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
1313 srcPtr
+ (srcWidth
- 1) * bpt
,
1320 make_2d_mipmap(const struct gl_texture_format
*format
, GLint border
,
1321 GLint srcWidth
, GLint srcHeight
, const GLubyte
*srcPtr
,
1322 GLint dstWidth
, GLint dstHeight
, GLubyte
*dstPtr
)
1324 const GLint bpt
= format
->TexelBytes
;
1325 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1326 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1327 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1328 const GLint srcRowStride
= bpt
* srcWidth
;
1329 const GLint dstRowStride
= bpt
* dstWidth
;
1330 const GLubyte
*srcA
, *srcB
;
1332 GLint row
, colStride
;
1334 colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
1336 /* Compute src and dst pointers, skipping any border */
1337 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1339 srcB
= srcA
+ srcRowStride
;
1342 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1344 for (row
= 0; row
< dstHeightNB
; row
++) {
1345 do_row(format
, srcWidthNB
, srcA
, srcB
,
1347 srcA
+= 2 * srcRowStride
;
1348 srcB
+= 2 * srcRowStride
;
1349 dst
+= dstRowStride
;
1352 /* This is ugly but probably won't be used much */
1354 /* fill in dest border */
1355 /* lower-left border pixel */
1356 MEMCPY(dstPtr
, srcPtr
, bpt
);
1357 /* lower-right border pixel */
1358 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
1359 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
1360 /* upper-left border pixel */
1361 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
1362 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
1363 /* upper-right border pixel */
1364 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
1365 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
1367 do_row(format
, srcWidthNB
,
1370 dstWidthNB
, dstPtr
+ bpt
);
1372 do_row(format
, srcWidthNB
,
1373 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1374 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1376 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
1377 /* left and right borders */
1378 if (srcHeight
== dstHeight
) {
1379 /* copy border pixel from src to dst */
1380 for (row
= 1; row
< srcHeight
; row
++) {
1381 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
1382 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
1383 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
1384 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
1388 /* average two src pixels each dest pixel */
1389 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
1391 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
1392 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
1393 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
1395 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
1396 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
1397 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
1405 make_3d_mipmap(const struct gl_texture_format
*format
, GLint border
,
1406 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1407 const GLubyte
*srcPtr
,
1408 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1411 const GLint bpt
= format
->TexelBytes
;
1412 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1413 const GLint srcDepthNB
= srcDepth
- 2 * border
;
1414 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1415 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1416 const GLint dstDepthNB
= dstDepth
- 2 * border
;
1417 GLvoid
*tmpRowA
, *tmpRowB
;
1419 GLint bytesPerSrcImage
, bytesPerDstImage
;
1420 GLint bytesPerSrcRow
, bytesPerDstRow
;
1421 GLint srcImageOffset
, srcRowOffset
;
1423 (void) srcDepthNB
; /* silence warnings */
1425 /* Need two temporary row buffers */
1426 tmpRowA
= MALLOC(srcWidth
* bpt
);
1429 tmpRowB
= MALLOC(srcWidth
* bpt
);
1435 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
1436 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
1438 bytesPerSrcRow
= srcWidth
* bpt
;
1439 bytesPerDstRow
= dstWidth
* bpt
;
1441 /* Offset between adjacent src images to be averaged together */
1442 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
1444 /* Offset between adjacent src rows to be averaged together */
1445 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
1448 * Need to average together up to 8 src pixels for each dest pixel.
1449 * Break that down into 3 operations:
1450 * 1. take two rows from source image and average them together.
1451 * 2. take two rows from next source image and average them together.
1452 * 3. take the two averaged rows and average them for the final dst row.
1456 printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1457 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1460 for (img
= 0; img
< dstDepthNB
; img
++) {
1461 /* first source image pointer, skipping border */
1462 const GLubyte
*imgSrcA
= srcPtr
1463 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
1464 + img
* (bytesPerSrcImage
+ srcImageOffset
);
1465 /* second source image pointer, skipping border */
1466 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
1467 /* address of the dest image, skipping border */
1468 GLubyte
*imgDst
= dstPtr
1469 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
1470 + img
* bytesPerDstImage
;
1472 /* setup the four source row pointers and the dest row pointer */
1473 const GLubyte
*srcImgARowA
= imgSrcA
;
1474 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
1475 const GLubyte
*srcImgBRowA
= imgSrcB
;
1476 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
1477 GLubyte
*dstImgRow
= imgDst
;
1479 for (row
= 0; row
< dstHeightNB
; row
++) {
1480 /* Average together two rows from first src image */
1481 do_row(format
, srcWidthNB
, srcImgARowA
, srcImgARowB
,
1482 srcWidthNB
, tmpRowA
);
1483 /* Average together two rows from second src image */
1484 do_row(format
, srcWidthNB
, srcImgBRowA
, srcImgBRowB
,
1485 srcWidthNB
, tmpRowB
);
1486 /* Average together the temp rows to make the final row */
1487 do_row(format
, srcWidthNB
, tmpRowA
, tmpRowB
,
1488 dstWidthNB
, dstImgRow
);
1489 /* advance to next rows */
1490 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
1491 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
1492 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
1493 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
1494 dstImgRow
+= bytesPerDstRow
;
1501 /* Luckily we can leverage the make_2d_mipmap() function here! */
1503 /* do front border image */
1504 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
, srcPtr
,
1505 dstWidth
, dstHeight
, dstPtr
);
1506 /* do back border image */
1507 make_2d_mipmap(format
, 1, srcWidth
, srcHeight
,
1508 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1),
1509 dstWidth
, dstHeight
,
1510 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1));
1511 /* do four remaining border edges that span the image slices */
1512 if (srcDepth
== dstDepth
) {
1513 /* just copy border pixels from src to dst */
1514 for (img
= 0; img
< dstDepthNB
; img
++) {
1518 /* do border along [img][row=0][col=0] */
1519 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
1520 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
1521 MEMCPY(dst
, src
, bpt
);
1523 /* do border along [img][row=dstHeight-1][col=0] */
1524 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1525 + (srcHeight
- 1) * bytesPerSrcRow
;
1526 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1527 + (dstHeight
- 1) * bytesPerDstRow
;
1528 MEMCPY(dst
, src
, bpt
);
1530 /* do border along [img][row=0][col=dstWidth-1] */
1531 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1532 + (srcWidth
- 1) * bpt
;
1533 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1534 + (dstWidth
- 1) * bpt
;
1535 MEMCPY(dst
, src
, bpt
);
1537 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1538 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1539 + (bytesPerSrcImage
- bpt
);
1540 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1541 + (bytesPerDstImage
- bpt
);
1542 MEMCPY(dst
, src
, bpt
);
1546 /* average border pixels from adjacent src image pairs */
1547 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
1548 for (img
= 0; img
< dstDepthNB
; img
++) {
1552 /* do border along [img][row=0][col=0] */
1553 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
1554 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
1555 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1557 /* do border along [img][row=dstHeight-1][col=0] */
1558 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1559 + (srcHeight
- 1) * bytesPerSrcRow
;
1560 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1561 + (dstHeight
- 1) * bytesPerDstRow
;
1562 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1564 /* do border along [img][row=0][col=dstWidth-1] */
1565 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1566 + (srcWidth
- 1) * bpt
;
1567 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1568 + (dstWidth
- 1) * bpt
;
1569 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1571 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1572 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1573 + (bytesPerSrcImage
- bpt
);
1574 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1575 + (bytesPerDstImage
- bpt
);
1576 do_row(format
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1584 * For GL_SGIX_generate_mipmap:
1585 * Generate a complete set of mipmaps from texObj's base-level image.
1586 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
1589 _mesa_generate_mipmap(GLcontext
*ctx
,
1590 const struct gl_texture_unit
*texUnit
,
1591 struct gl_texture_object
*texObj
)
1593 const GLenum targets1D
[] = { GL_TEXTURE_1D
, 0 };
1594 const GLenum targets2D
[] = { GL_TEXTURE_2D
, 0 };
1595 const GLenum targets3D
[] = { GL_TEXTURE_3D
, 0 };
1596 const GLenum targetsCube
[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
,
1597 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
,
1598 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
,
1599 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
,
1600 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
,
1601 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
,
1603 const GLenum
*targets
;
1605 GLint maxLevels
= 0;
1608 ASSERT(texObj
->Image
[texObj
->BaseLevel
]);
1610 switch (texObj
->Dimensions
) {
1612 targets
= targets1D
;
1613 maxLevels
= ctx
->Const
.MaxTextureLevels
;
1616 targets
= targets2D
;
1617 maxLevels
= ctx
->Const
.MaxTextureLevels
;
1620 targets
= targets3D
;
1621 maxLevels
= ctx
->Const
.Max3DTextureLevels
;
1624 targets
= targetsCube
;
1625 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
1629 "Bad texture object dimension in _mesa_generate_mipmaps");
1633 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
1634 && level
< maxLevels
- 1; level
++) {
1635 /* generate image[level+1] from image[level] */
1636 const struct gl_texture_image
*srcImage
;
1637 struct gl_texture_image
*dstImage
;
1638 GLint srcWidth
, srcHeight
, srcDepth
;
1639 GLint dstWidth
, dstHeight
, dstDepth
;
1640 GLint border
, bytesPerTexel
;
1643 srcImage
= texObj
->Image
[level
];
1645 srcWidth
= srcImage
->Width
;
1646 srcHeight
= srcImage
->Height
;
1647 srcDepth
= srcImage
->Depth
;
1648 border
= srcImage
->Border
;
1649 bytesPerTexel
= srcImage
->TexFormat
->TexelBytes
;
1651 /* compute next (level+1) image size */
1652 if (srcWidth
- 2 * border
> 1) {
1653 dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
1656 dstWidth
= srcWidth
; /* can't go smaller */
1658 if (srcHeight
- 2 * border
> 1) {
1659 dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
1662 dstHeight
= srcHeight
; /* can't go smaller */
1664 if (srcDepth
- 2 * border
> 1) {
1665 dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
1668 dstDepth
= srcDepth
; /* can't go smaller */
1671 if (dstWidth
== srcWidth
&&
1672 dstHeight
== srcHeight
&&
1673 dstDepth
== srcDepth
) {
1678 /* Need this loop just because of cubemaps */
1679 for (t
= 0; targets
[t
]; t
++) {
1682 dstImage
= _mesa_select_tex_image(ctx
, texUnit
, targets
[t
], level
+1);
1684 dstImage
= _mesa_alloc_texture_image();
1686 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1689 _mesa_set_tex_image(texObj
, targets
[t
], level
+ 1, dstImage
);
1692 /* Free old image data */
1694 FREE(dstImage
->Data
);
1696 /* initialize new image */
1697 _mesa_init_teximage_fields(ctx
, dstImage
, dstWidth
, dstHeight
,
1698 dstDepth
, border
, srcImage
->Format
);
1699 dstImage
->DriverData
= NULL
;
1700 dstImage
->TexFormat
= srcImage
->TexFormat
;
1701 dstImage
->FetchTexel
= srcImage
->FetchTexel
;
1702 ASSERT(dstImage
->TexFormat
);
1703 ASSERT(dstImage
->FetchTexel
);
1705 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
1707 /* alloc new image buffer */
1708 dstImage
->Data
= MALLOC(dstWidth
* dstHeight
* dstDepth
1710 if (!dstImage
->Data
) {
1711 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1716 * We use simple 2x2 averaging to compute the next mipmap level.
1718 switch (texObj
->Dimensions
) {
1720 make_1d_mipmap(srcImage
->TexFormat
, border
,
1721 srcWidth
, (const GLubyte
*) srcImage
->Data
,
1722 dstWidth
, (GLubyte
*) dstImage
->Data
);
1726 make_2d_mipmap(srcImage
->TexFormat
, border
,
1727 srcWidth
, srcHeight
, (const GLubyte
*) srcImage
->Data
,
1728 dstWidth
, dstHeight
, (GLubyte
*) dstImage
->Data
);
1731 make_3d_mipmap(srcImage
->TexFormat
, border
,
1732 srcWidth
, srcHeight
, srcDepth
, (const GLubyte
*) srcImage
->Data
,
1733 dstWidth
, dstHeight
, dstDepth
, (GLubyte
*) dstImage
->Data
);
1736 _mesa_problem(ctx
, "bad dimensions in _mesa_generate_mipmaps");
1739 } /* loop over tex image targets */
1740 } /* loop over tex levels */