1 /* $Id: texstore.c,v 1.16 2001/03/19 02:25:35 keithw 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 * texAddr - 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 GLchan's
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 texFormat
, GLchan
*texAddr
,
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(texFormat
);
185 /* try common 2D texture cases first */
186 if (!ctx
->_ImageTransferState
&& dimensions
== 2 && srcType
== CHAN_TYPE
) {
188 if (srcFormat
== texFormat
) {
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
= texAddr
+ 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
&& texFormat
== 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
= texAddr
+ 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 (texFormat
== GL_COLOR_INDEX
) {
243 /* color index texture */
244 const GLenum texType
= CHAN_TYPE
;
246 GLchan
*dest
= texAddr
+ 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 (texFormat
== GL_DEPTH_COMPONENT
) {
263 /* Depth texture (shadow maps) */
265 GLfloat
*dest
= (GLfloat
*) texAddr
+ dstZoffset
* dstImageStride
266 + dstYoffset
* dstRowStride
267 + dstXoffset
* texComponents
;
268 for (img
= 0; img
< srcDepth
; img
++) {
269 GLfloat
*destRow
= dest
;
270 for (row
= 0; row
< srcHeight
; row
++) {
271 const GLvoid
*src
= _mesa_image_address(srcPacking
,
272 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
273 _mesa_unpack_depth_span(ctx
, srcWidth
, destRow
,
274 srcType
, src
, srcPacking
);
275 destRow
+= dstRowStride
;
277 dest
+= dstImageStride
;
281 /* regular, color texture */
282 if ((dimensions
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
283 (dimensions
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
284 (dimensions
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
286 * Fill texture image with convolution
289 GLint convWidth
= srcWidth
, convHeight
= srcHeight
;
290 GLfloat
*tmpImage
, *convImage
;
291 tmpImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
293 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
296 convImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
298 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
303 for (img
= 0; img
< srcDepth
; img
++) {
305 GLfloat
*dstf
= tmpImage
;
308 /* unpack and do transfer ops up to convolution */
309 for (row
= 0; row
< srcHeight
; row
++) {
310 const GLvoid
*src
= _mesa_image_address(srcPacking
,
311 srcAddr
, srcWidth
, srcHeight
,
312 srcFormat
, srcType
, img
, row
, 0);
313 _mesa_unpack_float_color_span(ctx
, srcWidth
, GL_RGBA
, dstf
,
314 srcFormat
, srcType
, src
, srcPacking
,
315 ctx
->_ImageTransferState
& IMAGE_PRE_CONVOLUTION_BITS
,
317 dstf
+= srcWidth
* 4;
321 if (dimensions
== 1) {
322 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
323 _mesa_convolve_1d_image(ctx
, &convWidth
, tmpImage
, convImage
);
326 if (ctx
->Pixel
.Convolution2DEnabled
) {
327 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
328 tmpImage
, convImage
);
331 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
332 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
333 tmpImage
, convImage
);
337 /* packing and transfer ops after convolution */
339 dest
= texAddr
+ (dstZoffset
+ img
) * dstImageStride
340 + dstYoffset
* dstRowStride
;
341 for (row
= 0; row
< convHeight
; row
++) {
342 _mesa_pack_float_rgba_span(ctx
, convWidth
,
343 (const GLfloat (*)[4]) srcf
,
344 texFormat
, CHAN_TYPE
,
345 dest
, &_mesa_native_packing
,
346 ctx
->_ImageTransferState
347 & IMAGE_POST_CONVOLUTION_BITS
);
348 srcf
+= convWidth
* 4;
349 dest
+= dstRowStride
;
361 GLchan
*dest
= texAddr
+ dstZoffset
* dstImageStride
362 + dstYoffset
* dstRowStride
363 + dstXoffset
* texComponents
;
364 for (img
= 0; img
< srcDepth
; img
++) {
365 GLchan
*destRow
= dest
;
366 for (row
= 0; row
< srcHeight
; row
++) {
367 const GLvoid
*srcRow
= _mesa_image_address(srcPacking
,
368 srcAddr
, srcWidth
, srcHeight
,
369 srcFormat
, srcType
, img
, row
, 0);
370 _mesa_unpack_chan_color_span(ctx
, srcWidth
, texFormat
, destRow
,
371 srcFormat
, srcType
, srcRow
, srcPacking
,
372 ctx
->_ImageTransferState
);
373 destRow
+= dstRowStride
;
375 dest
+= dstImageStride
;
384 * This is the software fallback for Driver.TexImage1D().
385 * The texture image type will be GLchan.
386 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
387 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
391 _mesa_store_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
392 GLint internalFormat
,
393 GLint width
, GLint border
,
394 GLenum format
, GLenum type
, const GLvoid
*pixels
,
395 const struct gl_pixelstore_attrib
*packing
,
396 struct gl_texture_object
*texObj
,
397 struct gl_texture_image
*texImage
)
399 GLint postConvWidth
= width
;
401 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
402 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
405 /* setup the teximage struct's fields */
406 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);
407 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel1D
;
409 /* allocate memory */
410 texImage
->Data
= (GLchan
*) MALLOC(postConvWidth
*
411 texImage
->TexFormat
->TexelBytes
);
413 return; /* out of memory */
415 /* unpack image, apply transfer ops and store in texImage->Data */
416 _mesa_transfer_teximage(ctx
, 1, texImage
->Format
, (GLchan
*) texImage
->Data
,
417 width
, 1, 1, 0, 0, 0,
418 0, /* dstRowStride */
419 0, /* dstImageStride */
420 format
, type
, pixels
, packing
);
425 * This is the software fallback for Driver.TexImage2D().
426 * The texture image type will be GLchan.
427 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
428 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
432 _mesa_store_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
433 GLint internalFormat
,
434 GLint width
, GLint height
, GLint border
,
435 GLenum format
, GLenum type
, const void *pixels
,
436 const struct gl_pixelstore_attrib
*packing
,
437 struct gl_texture_object
*texObj
,
438 struct gl_texture_image
*texImage
)
440 GLint postConvWidth
= width
, postConvHeight
= height
;
443 if (ctx
->_ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
444 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
448 /* setup the teximage struct's fields */
449 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);
450 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel2D
;
452 texelBytes
= texImage
->TexFormat
->TexelBytes
;
454 /* allocate memory */
455 texImage
->Data
= (GLchan
*) MALLOC(postConvWidth
* postConvHeight
*
458 return; /* out of memory */
460 /* unpack image, apply transfer ops and store in texImage->Data */
461 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, (GLchan
*) texImage
->Data
,
462 width
, height
, 1, 0, 0, 0,
463 texImage
->Width
* texelBytes
,
464 0, /* dstImageStride */
465 format
, type
, pixels
, packing
);
471 * This is the software fallback for Driver.TexImage3D().
472 * The texture image type will be GLchan.
473 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
474 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
478 _mesa_store_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
479 GLint internalFormat
,
480 GLint width
, GLint height
, GLint depth
, GLint border
,
481 GLenum format
, GLenum type
, const void *pixels
,
482 const struct gl_pixelstore_attrib
*packing
,
483 struct gl_texture_object
*texObj
,
484 struct gl_texture_image
*texImage
)
488 /* setup the teximage struct's fields */
489 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);
490 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel3D
;
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
, (GLchan
*) 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
, (GLchan
*) 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 const GLint components
= components_in_intformat(texImage
->IntFormat
);
543 const GLint compSize
= _mesa_sizeof_type(texImage
->Type
);
544 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, (GLchan
*) texImage
->Data
,
545 width
, height
, 1, /* src size */
546 xoffset
, yoffset
, 0, /* dest offsets */
547 texImage
->Width
* components
* compSize
,
548 0, /* dstImageStride */
549 format
, type
, pixels
, packing
);
554 * This is the software fallback for Driver.TexSubImage3D().
557 _mesa_store_texsubimage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
558 GLint xoffset
, GLint yoffset
, GLint zoffset
,
559 GLint width
, GLint height
, GLint depth
,
560 GLenum format
, GLenum type
, const void *pixels
,
561 const struct gl_pixelstore_attrib
*packing
,
562 struct gl_texture_object
*texObj
,
563 struct gl_texture_image
*texImage
)
565 const GLint components
= components_in_intformat(texImage
->IntFormat
);
566 const GLint compSize
= _mesa_sizeof_type(texImage
->Type
);
567 _mesa_transfer_teximage(ctx
, 3, texImage
->Format
, (GLchan
*) texImage
->Data
,
568 width
, height
, depth
, /* src size */
569 xoffset
, yoffset
, xoffset
, /* dest offsets */
570 texImage
->Width
* components
* compSize
,
571 texImage
->Width
* texImage
->Height
* components
573 format
, type
, pixels
, packing
);
580 * Fallback for Driver.CompressedTexImage1D()
583 _mesa_store_compressed_teximage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
584 GLint internalFormat
,
585 GLint width
, GLint border
,
586 GLsizei imageSize
, const GLvoid
*data
,
587 struct gl_texture_object
*texObj
,
588 struct gl_texture_image
*texImage
)
591 * The device driver has to do it all.
598 * Fallback for Driver.CompressedTexImage2D()
601 _mesa_store_compressed_teximage2d(GLcontext
*ctx
, GLenum target
, GLint level
,
602 GLint internalFormat
,
603 GLint width
, GLint height
, GLint border
,
604 GLsizei imageSize
, const GLvoid
*data
,
605 struct gl_texture_object
*texObj
,
606 struct gl_texture_image
*texImage
)
609 * The device driver has to do it all.
616 * Fallback for Driver.CompressedTexImage3D()
619 _mesa_store_compressed_teximage3d(GLcontext
*ctx
, GLenum target
, GLint level
,
620 GLint internalFormat
,
621 GLint width
, GLint height
, GLint depth
,
623 GLsizei imageSize
, const GLvoid
*data
,
624 struct gl_texture_object
*texObj
,
625 struct gl_texture_image
*texImage
)
628 * The device driver has to do it all.
638 * This is the fallback for Driver.TestProxyTexImage().
641 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
642 GLint internalFormat
, GLenum format
, GLenum type
,
643 GLint width
, GLint height
, GLint depth
, GLint border
)
645 struct gl_texture_unit
*texUnit
;
646 struct gl_texture_object
*texObj
;
647 struct gl_texture_image
*texImage
;
652 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
653 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
654 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
657 * The core Mesa code will have already tested the image size, etc.
658 * Drivers may have more stringent texture limits to enforce and will
659 * have to override this function.
661 /* setup the teximage struct's fields */
662 _mesa_init_tex_format( ctx
, internalFormat
, texImage
);