1 /* $Id: texstore.c,v 1.21 2001/03/28 20:40:51 gareth 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.
34 * The functions in this file are mostly related to software texture fallbacks.
35 * This includes texture image transfer/packing and texel fetching.
36 * Hardware drivers will likely override most of this.
47 #include "texformat.h"
53 * Given an internal texture format enum or 1, 2, 3, 4 return the
54 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
55 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
56 * number of components for the format. Return -1 if invalid enum.
58 * GH: Do we really need this? We have the number of bytes per texel
59 * in the texture format structures, so why don't we just use that?
62 components_in_intformat( GLint format
)
79 case GL_LUMINANCE_ALPHA
:
80 case GL_LUMINANCE4_ALPHA4
:
81 case GL_LUMINANCE6_ALPHA2
:
82 case GL_LUMINANCE8_ALPHA8
:
83 case GL_LUMINANCE12_ALPHA4
:
84 case GL_LUMINANCE12_ALPHA12
:
85 case GL_LUMINANCE16_ALPHA16
:
114 case GL_COLOR_INDEX1_EXT
:
115 case GL_COLOR_INDEX2_EXT
:
116 case GL_COLOR_INDEX4_EXT
:
117 case GL_COLOR_INDEX8_EXT
:
118 case GL_COLOR_INDEX12_EXT
:
119 case GL_COLOR_INDEX16_EXT
:
121 case GL_DEPTH_COMPONENT
:
122 case GL_DEPTH_COMPONENT16_SGIX
:
123 case GL_DEPTH_COMPONENT24_SGIX
:
124 case GL_DEPTH_COMPONENT32_SGIX
:
127 return -1; /* error */
133 * This function is used to transfer the user's image data into a texture
134 * image buffer. We handle both full texture images and subtexture images.
135 * We also take care of all image transfer operations here, including
136 * convolution, scale/bias, colortables, etc.
138 * The destination texel channel type is always GLchan.
140 * A hardware driver may use this as a helper routine to unpack and
141 * apply pixel transfer ops into a temporary image buffer. Then,
142 * convert the temporary image into the special hardware format.
145 * dimensions - 1, 2, or 3
146 * texFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
148 * texDestAddr - destination image address
149 * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
150 * dstXoffset, dstYoffset, dstZoffset - position to store the image within
151 * the destination 3D texture
152 * dstRowStride, dstImageStride - dest image strides in bytes
153 * srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
154 * srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
155 * srcPacking - describes packing of incoming image.
158 _mesa_transfer_teximage(GLcontext
*ctx
, GLuint dimensions
,
159 GLenum texDestFormat
, GLvoid
*texDestAddr
,
160 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
161 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
162 GLint dstRowStride
, GLint dstImageStride
,
163 GLenum srcFormat
, GLenum srcType
,
164 const GLvoid
*srcAddr
,
165 const struct gl_pixelstore_attrib
*srcPacking
)
170 ASSERT(dimensions
>= 1 && dimensions
<= 3);
172 ASSERT(srcWidth
>= 1);
173 ASSERT(srcHeight
>= 1);
174 ASSERT(srcDepth
>= 1);
175 ASSERT(dstXoffset
>= 0);
176 ASSERT(dstYoffset
>= 0);
177 ASSERT(dstZoffset
>= 0);
178 ASSERT(dstRowStride
>= 0);
179 ASSERT(dstImageStride
>= 0);
183 texComponents
= components_in_intformat(texDestFormat
);
185 /* try common 2D texture cases first */
186 if (!ctx
->_ImageTransferState
&& dimensions
== 2 && srcType
== CHAN_TYPE
) {
188 if (srcFormat
== texDestFormat
) {
189 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
190 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
192 const GLchan
*src
= (const GLchan
*) _mesa_image_address(
193 srcPacking
, srcAddr
, srcWidth
, srcHeight
,
194 srcFormat
, srcType
, 0, 0, 0);
195 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
196 srcWidth
, srcFormat
, srcType
);
197 const GLint widthInBytes
= srcWidth
* texComponents
* sizeof(GLchan
);
198 GLchan
*dst
= (GLchan
*) texDestAddr
+ dstYoffset
* dstRowStride
199 + dstXoffset
* texComponents
;
200 if (srcRowStride
== widthInBytes
&& dstRowStride
== widthInBytes
) {
201 MEMCPY(dst
, src
, srcHeight
* widthInBytes
);
205 for (i
= 0; i
< srcHeight
; i
++) {
206 MEMCPY(dst
, src
, widthInBytes
);
211 return; /* all done */
213 else if (srcFormat
== GL_RGBA
&& texDestFormat
== GL_RGB
) {
214 /* commonly used by Quake */
215 const GLchan
*src
= (const GLchan
*) _mesa_image_address(
216 srcPacking
, srcAddr
, srcWidth
, srcHeight
,
217 srcFormat
, srcType
, 0, 0, 0);
218 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
219 srcWidth
, srcFormat
, srcType
);
220 GLchan
*dst
= (GLchan
*) texDestAddr
+ dstYoffset
* dstRowStride
221 + dstXoffset
* texComponents
;
223 for (i
= 0; i
< srcHeight
; i
++) {
224 const GLchan
*s
= src
;
226 for (j
= 0; j
< srcWidth
; j
++) {
228 *d
++ = *s
++; /*green*/
229 *d
++ = *s
++; /*blue*/
235 return; /* all done */
240 * General case solutions
242 if (texDestFormat
== GL_COLOR_INDEX
) {
243 /* color index texture */
244 const GLenum texType
= CHAN_TYPE
;
246 GLchan
*dest
= (GLchan
*) texDestAddr
+ dstZoffset
* dstImageStride
247 + dstYoffset
* dstRowStride
248 + dstXoffset
* texComponents
;
249 for (img
= 0; img
< srcDepth
; img
++) {
250 GLchan
*destRow
= dest
;
251 for (row
= 0; row
< srcHeight
; row
++) {
252 const GLvoid
*src
= _mesa_image_address(srcPacking
,
253 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
254 _mesa_unpack_index_span(ctx
, srcWidth
, texType
, destRow
,
255 srcType
, src
, srcPacking
,
256 ctx
->_ImageTransferState
);
257 destRow
+= dstRowStride
;
259 dest
+= dstImageStride
;
262 else if (texDestFormat
== GL_DEPTH_COMPONENT
) {
263 /* Depth texture (shadow maps) */
265 GLubyte
*dest
= (GLubyte
*) texDestAddr
266 + dstZoffset
* dstImageStride
267 + dstYoffset
* dstRowStride
268 + dstXoffset
* texComponents
;
269 for (img
= 0; img
< srcDepth
; img
++) {
270 GLubyte
*destRow
= dest
;
271 for (row
= 0; row
< srcHeight
; row
++) {
272 const GLvoid
*src
= _mesa_image_address(srcPacking
,
273 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
274 _mesa_unpack_depth_span(ctx
, srcWidth
, (GLfloat
*) destRow
,
275 srcType
, src
, srcPacking
);
276 destRow
+= dstRowStride
;
278 dest
+= dstImageStride
;
282 /* regular, color texture */
283 if ((dimensions
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
284 (dimensions
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
285 (dimensions
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
287 * Fill texture image with convolution
290 GLint convWidth
= srcWidth
, convHeight
= srcHeight
;
291 GLfloat
*tmpImage
, *convImage
;
292 tmpImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
294 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
297 convImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
299 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
304 for (img
= 0; img
< srcDepth
; img
++) {
306 GLfloat
*dstf
= tmpImage
;
309 /* unpack and do transfer ops up to convolution */
310 for (row
= 0; row
< srcHeight
; row
++) {
311 const GLvoid
*src
= _mesa_image_address(srcPacking
,
312 srcAddr
, srcWidth
, srcHeight
,
313 srcFormat
, srcType
, img
, row
, 0);
314 _mesa_unpack_float_color_span(ctx
, srcWidth
, GL_RGBA
, dstf
,
315 srcFormat
, srcType
, src
, srcPacking
,
316 ctx
->_ImageTransferState
& IMAGE_PRE_CONVOLUTION_BITS
,
318 dstf
+= srcWidth
* 4;
322 if (dimensions
== 1) {
323 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
324 _mesa_convolve_1d_image(ctx
, &convWidth
, tmpImage
, convImage
);
327 if (ctx
->Pixel
.Convolution2DEnabled
) {
328 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
329 tmpImage
, convImage
);
332 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
333 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
334 tmpImage
, convImage
);
338 /* packing and transfer ops after convolution */
340 dest
= (GLchan
*) texDestAddr
+ (dstZoffset
+ img
) * dstImageStride
341 + dstYoffset
* dstRowStride
;
342 for (row
= 0; row
< convHeight
; row
++) {
343 _mesa_pack_float_rgba_span(ctx
, convWidth
,
344 (const GLfloat (*)[4]) srcf
,
345 texDestFormat
, CHAN_TYPE
,
346 dest
, &_mesa_native_packing
,
347 ctx
->_ImageTransferState
348 & IMAGE_POST_CONVOLUTION_BITS
);
349 srcf
+= convWidth
* 4;
350 dest
+= dstRowStride
;
362 GLchan
*dest
= (GLchan
*) texDestAddr
+ dstZoffset
* dstImageStride
363 + dstYoffset
* dstRowStride
364 + dstXoffset
* texComponents
;
365 for (img
= 0; img
< srcDepth
; img
++) {
366 GLchan
*destRow
= dest
;
367 for (row
= 0; row
< srcHeight
; row
++) {
368 const GLvoid
*srcRow
= _mesa_image_address(srcPacking
,
369 srcAddr
, srcWidth
, srcHeight
,
370 srcFormat
, srcType
, img
, row
, 0);
371 _mesa_unpack_chan_color_span(ctx
, srcWidth
, texDestFormat
,
372 destRow
, srcFormat
, srcType
, srcRow
,
373 srcPacking
, ctx
->_ImageTransferState
);
374 destRow
+= dstRowStride
;
376 dest
+= dstImageStride
;
385 * This is the software fallback for Driver.TexImage1D().
386 * The texture image type will be GLchan.
387 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
388 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
392 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
393 GLint internalFormat
,
394 GLint width
, GLint border
,
395 GLenum format
, GLenum type
, const GLvoid
*pixels
,
396 const struct gl_pixelstore_attrib
*packing
,
397 struct gl_texture_object
*texObj
,
398 struct gl_texture_image
*texImage
)
400 GLint postConvWidth
= width
;
403 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
404 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
407 /* setup the teximage struct's fields */
408 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);
410 texelBytes
= texImage
->TexFormat
->TexelBytes
;
412 /* allocate memory */
413 texImage
->Data
= (GLchan
*) MALLOC(postConvWidth
* texelBytes
);
415 return; /* out of memory */
417 /* unpack image, apply transfer ops and store in texImage->Data */
418 _mesa_transfer_teximage(ctx
, 1, texImage
->Format
, texImage
->Data
,
419 width
, 1, 1, 0, 0, 0,
420 0, /* dstRowStride */
421 0, /* dstImageStride */
422 format
, type
, pixels
, packing
);
427 * This is the software fallback for Driver.TexImage2D().
428 * The texture image type will be GLchan.
429 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
430 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
434 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
435 GLint internalFormat
,
436 GLint width
, GLint height
, GLint border
,
437 GLenum format
, GLenum type
, const void *pixels
,
438 const struct gl_pixelstore_attrib
*packing
,
439 struct gl_texture_object
*texObj
,
440 struct gl_texture_image
*texImage
)
442 GLint postConvWidth
= width
, postConvHeight
= height
;
445 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
446 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
450 /* setup the teximage struct's fields */
451 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);
453 texelBytes
= texImage
->TexFormat
->TexelBytes
;
455 /* allocate memory */
456 texImage
->Data
= (GLchan
*) MALLOC(postConvWidth
* postConvHeight
*
459 return; /* out of memory */
461 /* unpack image, apply transfer ops and store in texImage->Data */
462 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, texImage
->Data
,
463 width
, height
, 1, 0, 0, 0,
464 texImage
->Width
* texelBytes
,
465 0, /* dstImageStride */
466 format
, type
, pixels
, packing
);
472 * This is the software fallback for Driver.TexImage3D().
473 * The texture image type will be GLchan.
474 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
475 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
479 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
480 GLint internalFormat
,
481 GLint width
, GLint height
, GLint depth
, GLint border
,
482 GLenum format
, GLenum type
, const void *pixels
,
483 const struct gl_pixelstore_attrib
*packing
,
484 struct gl_texture_object
*texObj
,
485 struct gl_texture_image
*texImage
)
489 /* setup the teximage struct's fields */
490 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);
492 texelBytes
= texImage
->TexFormat
->TexelBytes
;
494 /* allocate memory */
495 texImage
->Data
= (GLchan
*) MALLOC(width
* height
* depth
* texelBytes
);
497 return; /* out of memory */
499 /* unpack image, apply transfer ops and store in texImage->Data */
500 _mesa_transfer_teximage(ctx
, 3, texImage
->Format
, texImage
->Data
,
501 width
, height
, depth
, 0, 0, 0,
502 texImage
->Width
* texelBytes
,
503 texImage
->Width
* texImage
->Height
* texelBytes
,
504 format
, type
, pixels
, packing
);
511 * This is the software fallback for Driver.TexSubImage1D().
514 _mesa_store_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
515 GLint xoffset
, GLint width
,
516 GLenum format
, GLenum type
, const void *pixels
,
517 const struct gl_pixelstore_attrib
*packing
,
518 struct gl_texture_object
*texObj
,
519 struct gl_texture_image
*texImage
)
521 _mesa_transfer_teximage(ctx
, 1, texImage
->Format
, texImage
->Data
,
522 width
, 1, 1, /* src size */
523 xoffset
, 0, 0, /* dest offsets */
524 0, /* dstRowStride */
525 0, /* dstImageStride */
526 format
, type
, pixels
, packing
);
531 * This is the software fallback for Driver.TexSubImage2D().
534 _mesa_store_texsubimage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
535 GLint xoffset
, GLint yoffset
,
536 GLint width
, GLint height
,
537 GLenum format
, GLenum type
, const void *pixels
,
538 const struct gl_pixelstore_attrib
*packing
,
539 struct gl_texture_object
*texObj
,
540 struct gl_texture_image
*texImage
)
542 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, texImage
->Data
,
543 width
, height
, 1, /* src size */
544 xoffset
, yoffset
, 0, /* dest offsets */
545 texImage
->Width
* texImage
->TexFormat
->TexelBytes
,
546 0, /* dstImageStride */
547 format
, type
, pixels
, packing
);
552 * This is the software fallback for Driver.TexSubImage3D().
555 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
556 GLint xoffset
, GLint yoffset
, GLint zoffset
,
557 GLint width
, GLint height
, GLint depth
,
558 GLenum format
, GLenum type
, const void *pixels
,
559 const struct gl_pixelstore_attrib
*packing
,
560 struct gl_texture_object
*texObj
,
561 struct gl_texture_image
*texImage
)
563 const GLint texelBytes
= texImage
->TexFormat
->TexelBytes
;
564 _mesa_transfer_teximage(ctx
, 3, texImage
->Format
, texImage
->Data
,
565 width
, height
, depth
, /* src size */
566 xoffset
, yoffset
, xoffset
, /* dest offsets */
567 texImage
->Width
* texelBytes
,
568 texImage
->Width
* texImage
->Height
* texelBytes
,
569 format
, type
, pixels
, packing
);
576 * Fallback for Driver.CompressedTexImage1D()
579 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
580 GLint internalFormat
,
581 GLint width
, GLint border
,
582 GLsizei imageSize
, const GLvoid
*data
,
583 struct gl_texture_object
*texObj
,
584 struct gl_texture_image
*texImage
)
587 * The device driver has to do it all.
594 * Fallback for Driver.CompressedTexImage2D()
597 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
598 GLint internalFormat
,
599 GLint width
, GLint height
, GLint border
,
600 GLsizei imageSize
, const GLvoid
*data
,
601 struct gl_texture_object
*texObj
,
602 struct gl_texture_image
*texImage
)
605 * The device driver has to do it all.
612 * Fallback for Driver.CompressedTexImage3D()
615 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
616 GLint internalFormat
,
617 GLint width
, GLint height
, GLint depth
,
619 GLsizei imageSize
, const GLvoid
*data
,
620 struct gl_texture_object
*texObj
,
621 struct gl_texture_image
*texImage
)
624 * The device driver has to do it all.
634 * This is the fallback for Driver.TestProxyTexImage().
637 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
638 GLint internalFormat
, GLenum format
, GLenum type
,
639 GLint width
, GLint height
, GLint depth
, GLint border
)
641 struct gl_texture_unit
*texUnit
;
642 struct gl_texture_object
*texObj
;
643 struct gl_texture_image
*texImage
;
648 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
649 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
650 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
653 * The core Mesa code will have already tested the image size, etc.
654 * Drivers may have more stringent texture limits to enforce and will
655 * have to override this function.
657 /* setup the teximage struct's fields */
658 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);