2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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.
32 * The functions in this file are mostly related to software texture fallbacks.
33 * This includes texture image transfer/packing and texel fetching.
34 * Hardware drivers will likely override most of this.
46 #include "texformat.h"
50 #include "s_context.h"
55 * Read an RGBA image from the frame buffer.
56 * This is used by glCopyTex[Sub]Image[12]D().
57 * Input: ctx - the context
58 * x, y - lower left corner
59 * width, height - size of region to read
60 * Return: pointer to block of GL_RGBA, GLchan data.
63 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
,
64 GLsizei width
, GLsizei height
)
66 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
67 const GLint stride
= 4 * width
;
71 image
= (GLchan
*) _mesa_malloc(width
* height
* 4 * sizeof(GLchan
));
75 RENDER_START(swrast
, ctx
);
78 for (i
= 0; i
< height
; i
++) {
79 _swrast_read_rgba_span(ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
80 width
, x
, y
+ i
, (GLchan (*)[4]) dst
);
84 RENDER_FINISH(swrast
, ctx
);
91 * As above, but read data from depth buffer.
94 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
95 GLsizei width
, GLsizei height
)
97 struct gl_renderbuffer
*rb
98 = ctx
->ReadBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
99 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
100 GLfloat
*image
, *dst
;
103 image
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
107 RENDER_START(swrast
, ctx
);
110 for (i
= 0; i
< height
; i
++) {
111 _swrast_read_depth_span_float(ctx
, rb
, width
, x
, y
+ i
, dst
);
115 RENDER_FINISH(swrast
, ctx
);
122 * As above, but read data from depth+stencil buffers.
125 read_depth_stencil_image(GLcontext
*ctx
, GLint x
, GLint y
,
126 GLsizei width
, GLsizei height
)
128 struct gl_renderbuffer
*depthRb
129 = ctx
->ReadBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
130 struct gl_renderbuffer
*stencilRb
131 = ctx
->ReadBuffer
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
132 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
139 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
143 RENDER_START(swrast
, ctx
);
145 /* read from depth buffer */
147 if (depthRb
->DataType
== GL_UNSIGNED_INT
) {
148 for (i
= 0; i
< height
; i
++) {
149 _swrast_get_row(ctx
, depthRb
, width
, x
, y
+ i
, dst
, sizeof(GLuint
));
154 GLuint z16
[MAX_WIDTH
];
155 ASSERT(depthRb
->DataType
== GL_UNSIGNED_SHORT
);
156 for (i
= 0; i
< height
; i
++) {
158 _swrast_get_row(ctx
, depthRb
, width
, x
, y
+ i
, z16
, sizeof(GLushort
));
159 for (j
= 0; j
< width
; j
++) {
166 /* put depth values into bits 0xffffff00 */
167 if (depthRb
->DepthBits
== 24) {
169 for (j
= 0; j
< width
* height
; j
++) {
173 else if (depthRb
->DepthBits
== 16) {
175 for (j
= 0; j
< width
* height
; j
++) {
176 image
[j
] = (image
[j
] << 16) | (image
[j
] & 0xff00);
180 /* this handles arbitrary depthBits >= 12 */
181 GLint lShift
= 32 - depthRb
->DepthBits
;
182 GLint rShift
= depthRb
->DepthBits
;
184 for (j
= 0; j
< width
* height
; j
++) {
185 GLuint z
= (image
[j
] << lShift
);
186 image
[j
] = z
| (z
>> rShift
);
190 /* read stencil values and interleave into image array */
192 for (i
= 0; i
< height
; i
++) {
193 GLstencil stencil
[MAX_WIDTH
];
195 ASSERT(sizeof(GLstencil
) == stencilRb
->StencilBits
);
196 _swrast_get_row(ctx
, stencilRb
, width
, x
, y
+ i
,
197 stencil
, sizeof(GLstencil
));
198 for (j
= 0; j
< width
; j
++) {
199 dst
[j
] = (dst
[j
] & 0xffffff00) | (stencil
[j
] & 0xff);
204 RENDER_FINISH(swrast
, ctx
);
211 is_depth_format(GLenum format
)
214 case GL_DEPTH_COMPONENT
:
215 case GL_DEPTH_COMPONENT16_SGIX
:
216 case GL_DEPTH_COMPONENT24_SGIX
:
217 case GL_DEPTH_COMPONENT32_SGIX
:
226 is_depth_stencil_format(GLenum format
)
229 case GL_DEPTH_STENCIL_EXT
:
230 case GL_DEPTH24_STENCIL8_EXT
:
239 * Fallback for Driver.CopyTexImage1D().
242 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
243 GLenum internalFormat
,
244 GLint x
, GLint y
, GLsizei width
, GLint border
)
246 struct gl_texture_unit
*texUnit
;
247 struct gl_texture_object
*texObj
;
248 struct gl_texture_image
*texImage
;
250 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
251 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
253 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
256 ASSERT(ctx
->Driver
.TexImage1D
);
258 if (is_depth_format(internalFormat
)) {
259 /* read depth image from framebuffer */
260 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
262 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
265 /* call glTexImage1D to redefine the texture */
266 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
268 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
269 &ctx
->DefaultPacking
, texObj
, texImage
);
272 else if (is_depth_stencil_format(internalFormat
)) {
273 /* read depth/stencil image from framebuffer */
274 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
276 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
279 /* call glTexImage1D to redefine the texture */
280 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
282 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
283 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
287 /* read RGBA image from framebuffer */
288 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
290 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
293 /* call glTexImage1D to redefine the texture */
294 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
296 GL_RGBA
, CHAN_TYPE
, image
,
297 &ctx
->DefaultPacking
, texObj
, texImage
);
301 /* GL_SGIS_generate_mipmap */
302 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
303 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
309 * Fallback for Driver.CopyTexImage2D().
312 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
313 GLenum internalFormat
,
314 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
317 struct gl_texture_unit
*texUnit
;
318 struct gl_texture_object
*texObj
;
319 struct gl_texture_image
*texImage
;
321 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
322 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
324 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
327 ASSERT(ctx
->Driver
.TexImage2D
);
329 if (is_depth_format(internalFormat
)) {
330 /* read depth image from framebuffer */
331 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
333 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
336 /* call glTexImage2D to redefine the texture */
337 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
338 width
, height
, border
,
339 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
340 &ctx
->DefaultPacking
, texObj
, texImage
);
343 else if (is_depth_stencil_format(internalFormat
)) {
344 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
346 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
349 /* call glTexImage2D to redefine the texture */
350 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
351 width
, height
, border
,
352 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
353 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
357 /* read RGBA image from framebuffer */
358 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
360 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
363 /* call glTexImage2D to redefine the texture */
364 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
365 width
, height
, border
,
366 GL_RGBA
, CHAN_TYPE
, image
,
367 &ctx
->DefaultPacking
, texObj
, texImage
);
371 /* GL_SGIS_generate_mipmap */
372 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
373 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
379 * Fallback for Driver.CopyTexSubImage1D().
382 _swrast_copy_texsubimage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
383 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
385 struct gl_texture_unit
*texUnit
;
386 struct gl_texture_object
*texObj
;
387 struct gl_texture_image
*texImage
;
389 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
390 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
392 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
395 ASSERT(ctx
->Driver
.TexImage1D
);
397 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
398 /* read depth image from framebuffer */
399 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
401 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
405 /* call glTexSubImage1D to redefine the texture */
406 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
407 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
408 &ctx
->DefaultPacking
, texObj
, texImage
);
411 else if (texImage
->Format
== GL_DEPTH_STENCIL_EXT
) {
412 /* read depth/stencil image from framebuffer */
413 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
415 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
418 /* call glTexImage1D to redefine the texture */
419 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
420 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
421 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
425 /* read RGBA image from framebuffer */
426 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
428 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
431 /* now call glTexSubImage1D to do the real work */
432 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
433 GL_RGBA
, CHAN_TYPE
, image
,
434 &ctx
->DefaultPacking
, texObj
, texImage
);
438 /* GL_SGIS_generate_mipmap */
439 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
440 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
446 * Fallback for Driver.CopyTexSubImage2D().
449 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
450 GLenum target
, GLint level
,
451 GLint xoffset
, GLint yoffset
,
452 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
454 struct gl_texture_unit
*texUnit
;
455 struct gl_texture_object
*texObj
;
456 struct gl_texture_image
*texImage
;
458 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
459 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
461 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
464 ASSERT(ctx
->Driver
.TexImage2D
);
466 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
467 /* read depth image from framebuffer */
468 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
470 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
473 /* call glTexImage2D to redefine the texture */
474 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
475 xoffset
, yoffset
, width
, height
,
476 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
477 &ctx
->DefaultPacking
, texObj
, texImage
);
480 else if (texImage
->Format
== GL_DEPTH_STENCIL_EXT
) {
481 /* read depth/stencil image from framebuffer */
482 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
484 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
487 /* call glTexImage2D to redefine the texture */
488 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
489 xoffset
, yoffset
, width
, height
,
490 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
491 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
495 /* read RGBA image from framebuffer */
496 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
498 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
501 /* now call glTexSubImage2D to do the real work */
502 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
503 xoffset
, yoffset
, width
, height
,
504 GL_RGBA
, CHAN_TYPE
, image
,
505 &ctx
->DefaultPacking
, texObj
, texImage
);
509 /* GL_SGIS_generate_mipmap */
510 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
511 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
517 * Fallback for Driver.CopyTexSubImage3D().
520 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
521 GLenum target
, GLint level
,
522 GLint xoffset
, GLint yoffset
, GLint zoffset
,
523 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
525 struct gl_texture_unit
*texUnit
;
526 struct gl_texture_object
*texObj
;
527 struct gl_texture_image
*texImage
;
529 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
530 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
532 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
535 ASSERT(ctx
->Driver
.TexImage3D
);
537 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
538 /* read depth image from framebuffer */
539 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
541 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
544 /* call glTexImage3D to redefine the texture */
545 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
546 xoffset
, yoffset
, zoffset
, width
, height
, 1,
547 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
548 &ctx
->DefaultPacking
, texObj
, texImage
);
551 else if (texImage
->Format
== GL_DEPTH_STENCIL_EXT
) {
552 /* read depth/stencil image from framebuffer */
553 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
555 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
558 /* call glTexImage3D to redefine the texture */
559 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
560 xoffset
, yoffset
, zoffset
, width
, height
, 1,
561 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
562 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
566 /* read RGBA image from framebuffer */
567 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
569 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
572 /* now call glTexSubImage3D to do the real work */
573 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
574 xoffset
, yoffset
, zoffset
, width
, height
, 1,
575 GL_RGBA
, CHAN_TYPE
, image
,
576 &ctx
->DefaultPacking
, texObj
, texImage
);
580 /* GL_SGIS_generate_mipmap */
581 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
582 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);