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.
39 #include "main/glheader.h"
40 #include "main/imports.h"
41 #include "main/colormac.h"
42 #include "main/context.h"
43 #include "main/convolve.h"
44 #include "main/image.h"
45 #include "main/macros.h"
46 #include "main/mipmap.h"
47 #include "main/texformat.h"
48 #include "main/teximage.h"
49 #include "main/texstore.h"
51 #include "s_context.h"
57 * Read an RGBA image from the frame buffer.
58 * This is used by glCopyTex[Sub]Image[12]D().
59 * \param x window source x
60 * \param y window source y
61 * \param width image width
62 * \param height image height
63 * \param type datatype for returned GL_RGBA image
64 * \return pointer to image
67 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
, GLenum type
,
68 GLsizei width
, GLsizei height
)
70 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
71 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
72 const GLint pixelSize
= _mesa_bytes_per_pixel(GL_RGBA
, type
);
73 const GLint stride
= width
* pixelSize
;
77 image
= (GLubyte
*) _mesa_malloc(width
* height
* pixelSize
);
81 RENDER_START(swrast
, ctx
);
84 for (row
= 0; row
< height
; row
++) {
85 _swrast_read_rgba_span(ctx
, rb
, width
, x
, y
+ row
, type
, dst
);
89 RENDER_FINISH(swrast
, ctx
);
96 * As above, but read data from depth buffer. Returned as GLuints.
97 * \sa read_color_image
100 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
101 GLsizei width
, GLsizei height
)
103 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_DepthBuffer
;
104 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
108 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
112 RENDER_START(swrast
, ctx
);
115 for (i
= 0; i
< height
; i
++) {
116 _swrast_read_depth_span_uint(ctx
, rb
, width
, x
, y
+ i
, dst
);
120 RENDER_FINISH(swrast
, ctx
);
127 * As above, but read data from depth+stencil buffers.
130 read_depth_stencil_image(GLcontext
*ctx
, GLint x
, GLint y
,
131 GLsizei width
, GLsizei height
)
133 struct gl_renderbuffer
*depthRb
= ctx
->ReadBuffer
->_DepthBuffer
;
134 struct gl_renderbuffer
*stencilRb
= ctx
->ReadBuffer
->_StencilBuffer
;
135 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
142 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
146 RENDER_START(swrast
, ctx
);
148 /* read from depth buffer */
150 if (depthRb
->DataType
== GL_UNSIGNED_INT
) {
151 for (i
= 0; i
< height
; i
++) {
152 _swrast_get_row(ctx
, depthRb
, width
, x
, y
+ i
, dst
, sizeof(GLuint
));
157 GLushort z16
[MAX_WIDTH
];
158 ASSERT(depthRb
->DataType
== GL_UNSIGNED_SHORT
);
159 for (i
= 0; i
< height
; i
++) {
161 _swrast_get_row(ctx
, depthRb
, width
, x
, y
+ i
, z16
, sizeof(GLushort
));
162 /* convert GLushorts to GLuints */
163 for (j
= 0; j
< width
; j
++) {
170 /* put depth values into bits 0xffffff00 */
171 if (ctx
->ReadBuffer
->Visual
.depthBits
== 24) {
173 for (j
= 0; j
< width
* height
; j
++) {
177 else if (ctx
->ReadBuffer
->Visual
.depthBits
== 16) {
179 for (j
= 0; j
< width
* height
; j
++) {
180 image
[j
] = (image
[j
] << 16) | (image
[j
] & 0xff00);
184 /* this handles arbitrary depthBits >= 12 */
185 const GLint rShift
= ctx
->ReadBuffer
->Visual
.depthBits
;
186 const GLint lShift
= 32 - rShift
;
188 for (j
= 0; j
< width
* height
; j
++) {
189 GLuint z
= (image
[j
] << lShift
);
190 image
[j
] = z
| (z
>> rShift
);
194 /* read stencil values and interleave into image array */
196 for (i
= 0; i
< height
; i
++) {
197 GLstencil stencil
[MAX_WIDTH
];
199 ASSERT(8 * sizeof(GLstencil
) == stencilRb
->StencilBits
);
200 _swrast_get_row(ctx
, stencilRb
, width
, x
, y
+ i
,
201 stencil
, sizeof(GLstencil
));
202 for (j
= 0; j
< width
; j
++) {
203 dst
[j
] = (dst
[j
] & 0xffffff00) | (stencil
[j
] & 0xff);
208 RENDER_FINISH(swrast
, ctx
);
215 is_depth_format(GLenum format
)
218 case GL_DEPTH_COMPONENT
:
219 case GL_DEPTH_COMPONENT16
:
220 case GL_DEPTH_COMPONENT24
:
221 case GL_DEPTH_COMPONENT32
:
230 is_depth_stencil_format(GLenum format
)
233 case GL_DEPTH_STENCIL_EXT
:
234 case GL_DEPTH24_STENCIL8_EXT
:
243 * Fallback for Driver.CopyTexImage1D().
246 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
247 GLenum internalFormat
,
248 GLint x
, GLint y
, GLsizei width
, GLint border
)
250 struct gl_texture_unit
*texUnit
;
251 struct gl_texture_object
*texObj
;
252 struct gl_texture_image
*texImage
;
254 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
255 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
257 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
260 ASSERT(ctx
->Driver
.TexImage1D
);
262 if (is_depth_format(internalFormat
)) {
263 /* read depth image from framebuffer */
264 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
266 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
269 /* call glTexImage1D to redefine the texture */
270 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
272 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
273 &ctx
->DefaultPacking
, texObj
, texImage
);
276 else if (is_depth_stencil_format(internalFormat
)) {
277 /* read depth/stencil image from framebuffer */
278 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
280 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
283 /* call glTexImage1D to redefine the texture */
284 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
286 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
287 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
291 /* read RGBA image from framebuffer */
292 const GLenum format
= GL_RGBA
;
293 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
294 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, 1);
296 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
299 /* call glTexImage1D to redefine the texture */
300 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
301 width
, border
, format
, type
, image
,
302 &ctx
->DefaultPacking
, texObj
, texImage
);
306 /* GL_SGIS_generate_mipmap */
307 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
308 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
314 * Fallback for Driver.CopyTexImage2D().
316 * We implement CopyTexImage by reading the image from the framebuffer
317 * then passing it to the ctx->Driver.TexImage2D() function.
319 * Device drivers should try to implement direct framebuffer->texture copies.
322 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
323 GLenum internalFormat
,
324 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
327 struct gl_texture_unit
*texUnit
;
328 struct gl_texture_object
*texObj
;
329 struct gl_texture_image
*texImage
;
331 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
332 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
334 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
337 ASSERT(ctx
->Driver
.TexImage2D
);
339 if (is_depth_format(internalFormat
)) {
340 /* read depth image from framebuffer */
341 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
343 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
346 /* call glTexImage2D to redefine the texture */
347 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
348 width
, height
, border
,
349 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
350 &ctx
->DefaultPacking
, texObj
, texImage
);
353 else if (is_depth_stencil_format(internalFormat
)) {
354 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
356 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
359 /* call glTexImage2D to redefine the texture */
360 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
361 width
, height
, border
,
362 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
363 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
367 /* read RGBA image from framebuffer */
368 const GLenum format
= GL_RGBA
;
369 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
370 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, height
);
372 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
375 /* call glTexImage2D to redefine the texture */
376 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
377 width
, height
, border
, format
, type
, image
,
378 &ctx
->DefaultPacking
, texObj
, texImage
);
382 /* GL_SGIS_generate_mipmap */
383 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
384 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
390 * Fallback for Driver.CopyTexSubImage1D().
393 _swrast_copy_texsubimage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
394 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
396 struct gl_texture_unit
*texUnit
;
397 struct gl_texture_object
*texObj
;
398 struct gl_texture_image
*texImage
;
400 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
401 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
403 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
406 ASSERT(ctx
->Driver
.TexImage1D
);
408 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
409 /* read depth image from framebuffer */
410 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
412 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
416 /* call glTexSubImage1D to redefine the texture */
417 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
418 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
419 &ctx
->DefaultPacking
, texObj
, texImage
);
422 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
423 /* read depth/stencil image from framebuffer */
424 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
426 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
429 /* call glTexImage1D to redefine the texture */
430 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
431 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
432 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
436 /* read RGBA image from framebuffer */
437 const GLenum format
= GL_RGBA
;
438 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
439 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, 1);
441 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
444 /* now call glTexSubImage1D to do the real work */
445 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
447 &ctx
->DefaultPacking
, texObj
, texImage
);
451 /* GL_SGIS_generate_mipmap */
452 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
453 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
459 * Fallback for Driver.CopyTexSubImage2D().
461 * Read the image from the framebuffer then hand it
462 * off to ctx->Driver.TexSubImage2D().
465 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
466 GLenum target
, GLint level
,
467 GLint xoffset
, GLint yoffset
,
468 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
470 struct gl_texture_unit
*texUnit
;
471 struct gl_texture_object
*texObj
;
472 struct gl_texture_image
*texImage
;
474 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
475 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
477 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
480 ASSERT(ctx
->Driver
.TexImage2D
);
482 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
483 /* read depth image from framebuffer */
484 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
486 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
489 /* call glTexImage2D to redefine the texture */
490 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
491 xoffset
, yoffset
, width
, height
,
492 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
493 &ctx
->DefaultPacking
, texObj
, texImage
);
496 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
497 /* read depth/stencil image from framebuffer */
498 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
500 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
503 /* call glTexImage2D to redefine the texture */
504 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
505 xoffset
, yoffset
, width
, height
,
506 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
507 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
511 /* read RGBA image from framebuffer */
512 const GLenum format
= GL_RGBA
;
513 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
514 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, height
);
516 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
519 /* now call glTexSubImage2D to do the real work */
520 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
521 xoffset
, yoffset
, width
, height
,
523 &ctx
->DefaultPacking
, texObj
, texImage
);
527 /* GL_SGIS_generate_mipmap */
528 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
529 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
535 * Fallback for Driver.CopyTexSubImage3D().
538 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
539 GLenum target
, GLint level
,
540 GLint xoffset
, GLint yoffset
, GLint zoffset
,
541 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
543 struct gl_texture_unit
*texUnit
;
544 struct gl_texture_object
*texObj
;
545 struct gl_texture_image
*texImage
;
547 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
548 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
550 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
553 ASSERT(ctx
->Driver
.TexImage3D
);
555 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
556 /* read depth image from framebuffer */
557 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
559 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
562 /* call glTexImage3D to redefine the texture */
563 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
564 xoffset
, yoffset
, zoffset
, width
, height
, 1,
565 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
566 &ctx
->DefaultPacking
, texObj
, texImage
);
569 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
570 /* read depth/stencil image from framebuffer */
571 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
573 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
576 /* call glTexImage3D to redefine the texture */
577 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
578 xoffset
, yoffset
, zoffset
, width
, height
, 1,
579 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
580 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
584 /* read RGBA image from framebuffer */
585 const GLenum format
= GL_RGBA
;
586 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
587 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, height
);
589 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
592 /* now call glTexSubImage3D to do the real work */
593 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
594 xoffset
, yoffset
, zoffset
, width
, height
, 1,
596 &ctx
->DefaultPacking
, texObj
, texImage
);
600 /* GL_SGIS_generate_mipmap */
601 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
602 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);