2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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. Returned as GLuints.
92 * \sa read_color_image
95 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
96 GLsizei width
, GLsizei height
)
98 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_DepthBuffer
;
99 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
103 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
107 RENDER_START(swrast
, ctx
);
110 for (i
= 0; i
< height
; i
++) {
111 _swrast_read_depth_span_uint(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
= ctx
->ReadBuffer
->_DepthBuffer
;
129 struct gl_renderbuffer
*stencilRb
= ctx
->ReadBuffer
->_StencilBuffer
;
130 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
137 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
141 RENDER_START(swrast
, ctx
);
143 /* read from depth buffer */
145 if (depthRb
->DataType
== GL_UNSIGNED_INT
) {
146 for (i
= 0; i
< height
; i
++) {
147 _swrast_get_row(ctx
, depthRb
, width
, x
, y
+ i
, dst
, sizeof(GLuint
));
152 GLushort z16
[MAX_WIDTH
];
153 ASSERT(depthRb
->DataType
== GL_UNSIGNED_SHORT
);
154 for (i
= 0; i
< height
; i
++) {
156 _swrast_get_row(ctx
, depthRb
, width
, x
, y
+ i
, z16
, sizeof(GLushort
));
157 /* convert GLushorts to GLuints */
158 for (j
= 0; j
< width
; j
++) {
165 /* put depth values into bits 0xffffff00 */
166 if (ctx
->ReadBuffer
->Visual
.depthBits
== 24) {
168 for (j
= 0; j
< width
* height
; j
++) {
172 else if (ctx
->ReadBuffer
->Visual
.depthBits
== 16) {
174 for (j
= 0; j
< width
* height
; j
++) {
175 image
[j
] = (image
[j
] << 16) | (image
[j
] & 0xff00);
179 /* this handles arbitrary depthBits >= 12 */
180 const GLint rShift
= ctx
->ReadBuffer
->Visual
.depthBits
;
181 const GLint lShift
= 32 - rShift
;
183 for (j
= 0; j
< width
* height
; j
++) {
184 GLuint z
= (image
[j
] << lShift
);
185 image
[j
] = z
| (z
>> rShift
);
189 /* read stencil values and interleave into image array */
191 for (i
= 0; i
< height
; i
++) {
192 GLstencil stencil
[MAX_WIDTH
];
194 ASSERT(8 * sizeof(GLstencil
) == stencilRb
->StencilBits
);
195 _swrast_get_row(ctx
, stencilRb
, width
, x
, y
+ i
,
196 stencil
, sizeof(GLstencil
));
197 for (j
= 0; j
< width
; j
++) {
198 dst
[j
] = (dst
[j
] & 0xffffff00) | (stencil
[j
] & 0xff);
203 RENDER_FINISH(swrast
, ctx
);
210 is_depth_format(GLenum format
)
213 case GL_DEPTH_COMPONENT
:
214 case GL_DEPTH_COMPONENT16_SGIX
:
215 case GL_DEPTH_COMPONENT24_SGIX
:
216 case GL_DEPTH_COMPONENT32_SGIX
:
225 is_depth_stencil_format(GLenum format
)
228 case GL_DEPTH_STENCIL_EXT
:
229 case GL_DEPTH24_STENCIL8_EXT
:
238 * Fallback for Driver.CopyTexImage1D().
241 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
242 GLenum internalFormat
,
243 GLint x
, GLint y
, GLsizei width
, GLint border
)
245 struct gl_texture_unit
*texUnit
;
246 struct gl_texture_object
*texObj
;
247 struct gl_texture_image
*texImage
;
249 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
250 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
252 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
255 ASSERT(ctx
->Driver
.TexImage1D
);
257 if (is_depth_format(internalFormat
)) {
258 /* read depth image from framebuffer */
259 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
261 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
264 /* call glTexImage1D to redefine the texture */
265 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
267 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
268 &ctx
->DefaultPacking
, texObj
, texImage
);
271 else if (is_depth_stencil_format(internalFormat
)) {
272 /* read depth/stencil image from framebuffer */
273 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
275 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
278 /* call glTexImage1D to redefine the texture */
279 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
281 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
282 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
286 /* read RGBA image from framebuffer */
287 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
289 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
292 /* call glTexImage1D to redefine the texture */
293 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
295 GL_RGBA
, CHAN_TYPE
, image
,
296 &ctx
->DefaultPacking
, texObj
, texImage
);
300 /* GL_SGIS_generate_mipmap */
301 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
302 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
308 * Fallback for Driver.CopyTexImage2D().
310 * We implement CopyTexImage by reading the image from the framebuffer
311 * then passing it to the ctx->Driver.TexImage2D() function.
313 * Device drivers should try to implement direct framebuffer->texture copies.
316 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
317 GLenum internalFormat
,
318 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
321 struct gl_texture_unit
*texUnit
;
322 struct gl_texture_object
*texObj
;
323 struct gl_texture_image
*texImage
;
325 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
326 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
328 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
331 ASSERT(ctx
->Driver
.TexImage2D
);
333 if (is_depth_format(internalFormat
)) {
334 /* read depth image from framebuffer */
335 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
337 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
340 /* call glTexImage2D to redefine the texture */
341 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
342 width
, height
, border
,
343 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
344 &ctx
->DefaultPacking
, texObj
, texImage
);
347 else if (is_depth_stencil_format(internalFormat
)) {
348 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
350 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
353 /* call glTexImage2D to redefine the texture */
354 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
355 width
, height
, border
,
356 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
357 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
361 /* read RGBA image from framebuffer */
362 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
364 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
367 /* call glTexImage2D to redefine the texture */
368 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
369 width
, height
, border
,
370 GL_RGBA
, CHAN_TYPE
, image
,
371 &ctx
->DefaultPacking
, texObj
, texImage
);
375 /* GL_SGIS_generate_mipmap */
376 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
377 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
383 * Fallback for Driver.CopyTexSubImage1D().
386 _swrast_copy_texsubimage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
387 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
389 struct gl_texture_unit
*texUnit
;
390 struct gl_texture_object
*texObj
;
391 struct gl_texture_image
*texImage
;
393 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
394 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
396 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
399 ASSERT(ctx
->Driver
.TexImage1D
);
401 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
402 /* read depth image from framebuffer */
403 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
405 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
409 /* call glTexSubImage1D to redefine the texture */
410 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
411 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
412 &ctx
->DefaultPacking
, texObj
, texImage
);
415 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
416 /* read depth/stencil image from framebuffer */
417 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
419 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
422 /* call glTexImage1D to redefine the texture */
423 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
424 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
425 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
429 /* read RGBA image from framebuffer */
430 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
432 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
435 /* now call glTexSubImage1D to do the real work */
436 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
437 GL_RGBA
, CHAN_TYPE
, image
,
438 &ctx
->DefaultPacking
, texObj
, texImage
);
442 /* GL_SGIS_generate_mipmap */
443 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
444 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
450 * Fallback for Driver.CopyTexSubImage2D().
452 * Read the image from the framebuffer then hand it
453 * off to ctx->Driver.TexSubImage2D().
456 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
457 GLenum target
, GLint level
,
458 GLint xoffset
, GLint yoffset
,
459 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
461 struct gl_texture_unit
*texUnit
;
462 struct gl_texture_object
*texObj
;
463 struct gl_texture_image
*texImage
;
465 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
466 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
468 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
471 ASSERT(ctx
->Driver
.TexImage2D
);
473 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
474 /* read depth image from framebuffer */
475 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
477 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
480 /* call glTexImage2D to redefine the texture */
481 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
482 xoffset
, yoffset
, width
, height
,
483 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
484 &ctx
->DefaultPacking
, texObj
, texImage
);
487 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
488 /* read depth/stencil image from framebuffer */
489 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
491 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
494 /* call glTexImage2D to redefine the texture */
495 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
496 xoffset
, yoffset
, width
, height
,
497 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
498 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
502 /* read RGBA image from framebuffer */
503 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
505 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
508 /* now call glTexSubImage2D to do the real work */
509 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
510 xoffset
, yoffset
, width
, height
,
511 GL_RGBA
, CHAN_TYPE
, image
,
512 &ctx
->DefaultPacking
, texObj
, texImage
);
516 /* GL_SGIS_generate_mipmap */
517 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
518 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
524 * Fallback for Driver.CopyTexSubImage3D().
527 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
528 GLenum target
, GLint level
,
529 GLint xoffset
, GLint yoffset
, GLint zoffset
,
530 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
532 struct gl_texture_unit
*texUnit
;
533 struct gl_texture_object
*texObj
;
534 struct gl_texture_image
*texImage
;
536 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
537 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
539 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
542 ASSERT(ctx
->Driver
.TexImage3D
);
544 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
545 /* read depth image from framebuffer */
546 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
548 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
551 /* call glTexImage3D to redefine the texture */
552 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
553 xoffset
, yoffset
, zoffset
, width
, height
, 1,
554 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
555 &ctx
->DefaultPacking
, texObj
, texImage
);
558 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
559 /* read depth/stencil image from framebuffer */
560 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
562 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
565 /* call glTexImage3D to redefine the texture */
566 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
567 xoffset
, yoffset
, zoffset
, width
, height
, 1,
568 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
569 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
573 /* read RGBA image from framebuffer */
574 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
576 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
579 /* now call glTexSubImage3D to do the real work */
580 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
581 xoffset
, yoffset
, zoffset
, width
, height
, 1,
582 GL_RGBA
, CHAN_TYPE
, image
,
583 &ctx
->DefaultPacking
, texObj
, texImage
);
587 /* GL_SGIS_generate_mipmap */
588 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
589 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);