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 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
71 const GLint pixelSize
= _mesa_bytes_per_pixel(GL_RGBA
, type
);
72 const GLint stride
= width
* pixelSize
;
76 image
= (GLubyte
*) _mesa_malloc(width
* height
* pixelSize
);
80 swrast_render_start(ctx
);
83 for (row
= 0; row
< height
; row
++) {
84 _swrast_read_rgba_span(ctx
, rb
, width
, x
, y
+ row
, type
, dst
);
88 swrast_render_finish(ctx
);
95 * As above, but read data from depth buffer. Returned as GLuints.
96 * \sa read_color_image
99 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
100 GLsizei width
, GLsizei height
)
102 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_DepthBuffer
;
106 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
110 swrast_render_start(ctx
);
113 for (i
= 0; i
< height
; i
++) {
114 _swrast_read_depth_span_uint(ctx
, rb
, width
, x
, y
+ i
, dst
);
118 swrast_render_finish(ctx
);
125 * As above, but read data from depth+stencil buffers.
128 read_depth_stencil_image(GLcontext
*ctx
, GLint x
, GLint y
,
129 GLsizei width
, GLsizei height
)
131 struct gl_renderbuffer
*depthRb
= ctx
->ReadBuffer
->_DepthBuffer
;
132 struct gl_renderbuffer
*stencilRb
= ctx
->ReadBuffer
->_StencilBuffer
;
139 image
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
143 swrast_render_start(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 GLushort 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 /* convert GLushorts to GLuints */
160 for (j
= 0; j
< width
; j
++) {
167 /* put depth values into bits 0xffffff00 */
168 if (ctx
->ReadBuffer
->Visual
.depthBits
== 24) {
170 for (j
= 0; j
< width
* height
; j
++) {
174 else if (ctx
->ReadBuffer
->Visual
.depthBits
== 16) {
176 for (j
= 0; j
< width
* height
; j
++) {
177 image
[j
] = (image
[j
] << 16) | (image
[j
] & 0xff00);
181 /* this handles arbitrary depthBits >= 12 */
182 const GLint rShift
= ctx
->ReadBuffer
->Visual
.depthBits
;
183 const GLint lShift
= 32 - rShift
;
185 for (j
= 0; j
< width
* height
; j
++) {
186 GLuint z
= (image
[j
] << lShift
);
187 image
[j
] = z
| (z
>> rShift
);
191 /* read stencil values and interleave into image array */
193 for (i
= 0; i
< height
; i
++) {
194 GLstencil stencil
[MAX_WIDTH
];
196 ASSERT(8 * sizeof(GLstencil
) == stencilRb
->StencilBits
);
197 _swrast_get_row(ctx
, stencilRb
, width
, x
, y
+ i
,
198 stencil
, sizeof(GLstencil
));
199 for (j
= 0; j
< width
; j
++) {
200 dst
[j
] = (dst
[j
] & 0xffffff00) | (stencil
[j
] & 0xff);
205 swrast_render_finish(ctx
);
212 is_depth_format(GLenum format
)
215 case GL_DEPTH_COMPONENT
:
216 case GL_DEPTH_COMPONENT16
:
217 case GL_DEPTH_COMPONENT24
:
218 case GL_DEPTH_COMPONENT32
:
227 is_depth_stencil_format(GLenum format
)
230 case GL_DEPTH_STENCIL_EXT
:
231 case GL_DEPTH24_STENCIL8_EXT
:
240 * Fallback for Driver.CopyTexImage1D().
243 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
244 GLenum internalFormat
,
245 GLint x
, GLint y
, GLsizei width
, GLint border
)
247 struct gl_texture_unit
*texUnit
;
248 struct gl_texture_object
*texObj
;
249 struct gl_texture_image
*texImage
;
251 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
252 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
254 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
257 ASSERT(ctx
->Driver
.TexImage1D
);
259 if (is_depth_format(internalFormat
)) {
260 /* read depth image from framebuffer */
261 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
263 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
266 /* call glTexImage1D to redefine the texture */
267 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
269 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
270 &ctx
->DefaultPacking
, texObj
, texImage
);
273 else if (is_depth_stencil_format(internalFormat
)) {
274 /* read depth/stencil image from framebuffer */
275 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
277 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
280 /* call glTexImage1D to redefine the texture */
281 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
283 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
284 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
288 /* read RGBA image from framebuffer */
289 const GLenum format
= GL_RGBA
;
290 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
291 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, 1);
293 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
296 /* call glTexImage1D to redefine the texture */
297 ctx
->Driver
.TexImage1D(ctx
, target
, level
, internalFormat
,
298 width
, border
, format
, type
, image
,
299 &ctx
->DefaultPacking
, texObj
, texImage
);
303 /* GL_SGIS_generate_mipmap */
304 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
305 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
311 * Fallback for Driver.CopyTexImage2D().
313 * We implement CopyTexImage by reading the image from the framebuffer
314 * then passing it to the ctx->Driver.TexImage2D() function.
316 * Device drivers should try to implement direct framebuffer->texture copies.
319 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
320 GLenum internalFormat
,
321 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
324 struct gl_texture_unit
*texUnit
;
325 struct gl_texture_object
*texObj
;
326 struct gl_texture_image
*texImage
;
328 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
329 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
331 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
334 ASSERT(ctx
->Driver
.TexImage2D
);
336 if (is_depth_format(internalFormat
)) {
337 /* read depth image from framebuffer */
338 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
340 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
343 /* call glTexImage2D to redefine the texture */
344 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
345 width
, height
, border
,
346 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
347 &ctx
->DefaultPacking
, texObj
, texImage
);
350 else if (is_depth_stencil_format(internalFormat
)) {
351 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
353 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
356 /* call glTexImage2D to redefine the texture */
357 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
358 width
, height
, border
,
359 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
360 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
364 /* read RGBA image from framebuffer */
365 const GLenum format
= GL_RGBA
;
366 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
367 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, height
);
369 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
372 /* call glTexImage2D to redefine the texture */
373 ctx
->Driver
.TexImage2D(ctx
, target
, level
, internalFormat
,
374 width
, height
, border
, format
, type
, image
,
375 &ctx
->DefaultPacking
, texObj
, texImage
);
379 /* GL_SGIS_generate_mipmap */
380 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
381 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
387 * Fallback for Driver.CopyTexSubImage1D().
390 _swrast_copy_texsubimage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
391 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
393 struct gl_texture_unit
*texUnit
;
394 struct gl_texture_object
*texObj
;
395 struct gl_texture_image
*texImage
;
397 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
398 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
400 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
403 ASSERT(ctx
->Driver
.TexImage1D
);
405 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
406 /* read depth image from framebuffer */
407 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
409 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
413 /* call glTexSubImage1D to redefine the texture */
414 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
415 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
416 &ctx
->DefaultPacking
, texObj
, texImage
);
419 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
420 /* read depth/stencil image from framebuffer */
421 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, 1);
423 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
426 /* call glTexImage1D to redefine the texture */
427 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
428 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
429 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
433 /* read RGBA image from framebuffer */
434 const GLenum format
= GL_RGBA
;
435 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
436 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, 1);
438 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
441 /* now call glTexSubImage1D to do the real work */
442 ctx
->Driver
.TexSubImage1D(ctx
, target
, level
, xoffset
, width
,
444 &ctx
->DefaultPacking
, texObj
, texImage
);
448 /* GL_SGIS_generate_mipmap */
449 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
450 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
456 * Fallback for Driver.CopyTexSubImage2D().
458 * Read the image from the framebuffer then hand it
459 * off to ctx->Driver.TexSubImage2D().
462 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
463 GLenum target
, GLint level
,
464 GLint xoffset
, GLint yoffset
,
465 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
467 struct gl_texture_unit
*texUnit
;
468 struct gl_texture_object
*texObj
;
469 struct gl_texture_image
*texImage
;
471 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
472 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
474 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
477 ASSERT(ctx
->Driver
.TexImage2D
);
479 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
480 /* read depth image from framebuffer */
481 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
483 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
486 /* call glTexImage2D to redefine the texture */
487 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
488 xoffset
, yoffset
, width
, height
,
489 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
490 &ctx
->DefaultPacking
, texObj
, texImage
);
493 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
494 /* read depth/stencil image from framebuffer */
495 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
497 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
500 /* call glTexImage2D to redefine the texture */
501 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
502 xoffset
, yoffset
, width
, height
,
503 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
504 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
508 /* read RGBA image from framebuffer */
509 const GLenum format
= GL_RGBA
;
510 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
511 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, height
);
513 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
516 /* now call glTexSubImage2D to do the real work */
517 ctx
->Driver
.TexSubImage2D(ctx
, target
, level
,
518 xoffset
, yoffset
, width
, height
,
520 &ctx
->DefaultPacking
, texObj
, texImage
);
524 /* GL_SGIS_generate_mipmap */
525 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
526 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);
532 * Fallback for Driver.CopyTexSubImage3D().
535 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
536 GLenum target
, GLint level
,
537 GLint xoffset
, GLint yoffset
, GLint zoffset
,
538 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
540 struct gl_texture_unit
*texUnit
;
541 struct gl_texture_object
*texObj
;
542 struct gl_texture_image
*texImage
;
544 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
545 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
547 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
550 ASSERT(ctx
->Driver
.TexImage3D
);
552 if (texImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
553 /* read depth image from framebuffer */
554 GLuint
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
556 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
559 /* call glTexImage3D to redefine the texture */
560 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
561 xoffset
, yoffset
, zoffset
, width
, height
, 1,
562 GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, image
,
563 &ctx
->DefaultPacking
, texObj
, texImage
);
566 else if (texImage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
567 /* read depth/stencil image from framebuffer */
568 GLuint
*image
= read_depth_stencil_image(ctx
, x
, y
, width
, height
);
570 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
573 /* call glTexImage3D to redefine the texture */
574 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
575 xoffset
, yoffset
, zoffset
, width
, height
, 1,
576 GL_DEPTH_STENCIL_EXT
, GL_UNSIGNED_INT_24_8_EXT
,
577 image
, &ctx
->DefaultPacking
, texObj
, texImage
);
581 /* read RGBA image from framebuffer */
582 const GLenum format
= GL_RGBA
;
583 const GLenum type
= ctx
->ReadBuffer
->_ColorReadBuffer
->DataType
;
584 GLvoid
*image
= read_color_image(ctx
, x
, y
, type
, width
, height
);
586 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
589 /* now call glTexSubImage3D to do the real work */
590 ctx
->Driver
.TexSubImage3D(ctx
, target
, level
,
591 xoffset
, yoffset
, zoffset
, width
, height
, 1,
593 &ctx
->DefaultPacking
, texObj
, texImage
);
597 /* GL_SGIS_generate_mipmap */
598 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
599 ctx
->Driver
.GenerateMipmap(ctx
, target
, texObj
);