1 /* $Id: s_texstore.c,v 1.5 2001/05/21 16:41:04 brianp 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"
51 #include "s_context.h"
56 * Read an RGBA image from the frame buffer.
57 * This is used by glCopyTex[Sub]Image[12]D().
58 * Input: ctx - the context
59 * x, y - lower left corner
60 * width, height - size of region to read
61 * Return: pointer to block of GL_RGBA, GLchan data.
64 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
,
65 GLsizei width
, GLsizei height
)
67 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
71 image
= (GLchan
*) MALLOC(width
* height
* 4 * sizeof(GLchan
));
75 /* Select buffer to read from */
76 (*swrast
->Driver
.SetReadBuffer
)( ctx
, ctx
->ReadBuffer
,
77 ctx
->Pixel
.DriverReadBuffer
);
79 RENDER_START(swrast
,ctx
);
83 for (i
= 0; i
< height
; i
++) {
84 _mesa_read_rgba_span( ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
85 (GLchan (*)[4]) dst
);
89 RENDER_FINISH(swrast
,ctx
);
91 /* Read from draw buffer (the default) */
92 (*swrast
->Driver
.SetReadBuffer
)( ctx
, ctx
->DrawBuffer
,
93 ctx
->Color
.DriverDrawBuffer
);
100 * As above, but read data from depth buffer.
103 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
104 GLsizei width
, GLsizei height
)
106 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
107 GLfloat
*image
, *dst
;
110 image
= (GLfloat
*) MALLOC(width
* height
* sizeof(GLfloat
));
114 RENDER_START(swrast
,ctx
);
117 for (i
= 0; i
< height
; i
++) {
118 _mesa_read_depth_span_float(ctx
, width
, x
, y
+ i
, dst
);
122 RENDER_FINISH(swrast
,ctx
);
130 is_depth_format(GLenum format
)
133 case GL_DEPTH_COMPONENT
:
134 case GL_DEPTH_COMPONENT16_SGIX
:
135 case GL_DEPTH_COMPONENT24_SGIX
:
136 case GL_DEPTH_COMPONENT32_SGIX
:
145 * Fallback for Driver.CopyTexImage1D().
148 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
149 GLenum internalFormat
,
150 GLint x
, GLint y
, GLsizei width
, GLint border
)
152 struct gl_texture_unit
*texUnit
;
153 struct gl_texture_object
*texObj
;
154 struct gl_texture_image
*texImage
;
156 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
157 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
159 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
162 ASSERT(ctx
->Driver
.TexImage1D
);
164 if (is_depth_format(internalFormat
)) {
165 /* read depth image from framebuffer */
166 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
168 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
172 /* call glTexImage1D to redefine the texture */
173 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
175 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
176 &_mesa_native_packing
, texObj
, texImage
);
180 /* read RGBA image from framebuffer */
181 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
183 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
187 /* call glTexImage1D to redefine the texture */
188 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
190 GL_RGBA
, CHAN_TYPE
, image
,
191 &_mesa_native_packing
, texObj
, texImage
);
195 /* GL_SGIS_generate_mipmap */
196 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
197 _mesa_generate_mipmap(ctx
, texUnit
, texObj
);
203 * Fallback for Driver.CopyTexImage2D().
206 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
207 GLenum internalFormat
,
208 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
211 struct gl_texture_unit
*texUnit
;
212 struct gl_texture_object
*texObj
;
213 struct gl_texture_image
*texImage
;
215 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
216 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
218 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
221 ASSERT(ctx
->Driver
.TexImage2D
);
223 if (is_depth_format(internalFormat
)) {
224 /* read depth image from framebuffer */
225 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
227 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
231 /* call glTexImage2D to redefine the texture */
232 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
233 width
, height
, border
,
234 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
235 &_mesa_native_packing
, texObj
, texImage
);
239 /* read RGBA image from framebuffer */
240 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
242 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
246 /* call glTexImage2D to redefine the texture */
247 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
248 width
, height
, border
,
249 GL_RGBA
, CHAN_TYPE
, image
,
250 &_mesa_native_packing
, texObj
, texImage
);
254 /* GL_SGIS_generate_mipmap */
255 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
256 _mesa_generate_mipmap(ctx
, texUnit
, texObj
);
262 * Fallback for Driver.CopyTexSubImage1D().
265 _swrast_copy_texsubimage1d(GLcontext
*ctx
, GLenum target
, GLint level
,
266 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
268 struct gl_texture_unit
*texUnit
;
269 struct gl_texture_object
*texObj
;
270 struct gl_texture_image
*texImage
;
272 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
273 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
275 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
278 ASSERT(ctx
->Driver
.TexImage1D
);
280 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
281 /* read RGBA image from framebuffer */
282 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
284 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
290 * XXX this is a bit of a hack. We need to be sure that the alpha
291 * channel is 1.0 if the internal texture format is not supposed to
292 * have an alpha channel. This is because some drivers may store
293 * RGB textures as RGBA and the texutil.c code isn't smart enough
294 * to set the alpha channel to 1.0 in this situation.
296 if (texImage
->Format
== GL_LUMINANCE
||
297 texImage
->Format
== GL_RGB
) {
298 const GLuint n
= width
* 4;
300 for (i
= 0; i
< n
; i
+= 4) {
301 image
[i
+ 3] = CHAN_MAX
;
305 /* now call glTexSubImage1D to do the real work */
306 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
307 GL_RGBA
, CHAN_TYPE
, image
,
308 &_mesa_native_packing
, texObj
, texImage
);
312 /* read depth image from framebuffer */
313 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
315 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
319 /* call glTexSubImage1D to redefine the texture */
320 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
321 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
322 &_mesa_native_packing
, texObj
, texImage
);
326 /* GL_SGIS_generate_mipmap */
327 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
328 _mesa_generate_mipmap(ctx
, texUnit
, texObj
);
334 * Fallback for Driver.CopyTexSubImage2D().
337 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
338 GLenum target
, GLint level
,
339 GLint xoffset
, GLint yoffset
,
340 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
342 struct gl_texture_unit
*texUnit
;
343 struct gl_texture_object
*texObj
;
344 struct gl_texture_image
*texImage
;
346 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
347 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
349 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
352 ASSERT(ctx
->Driver
.TexImage2D
);
354 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
355 /* read RGBA image from framebuffer */
356 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
358 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
364 * XXX this is a bit of a hack. We need to be sure that the alpha
365 * channel is 1.0 if the internal texture format is not supposed to
366 * have an alpha channel. This is because some drivers may store
367 * RGB textures as RGBA and the texutil.c code isn't smart enough
368 * to set the alpha channel to 1.0 in this situation.
370 if (texImage
->Format
== GL_LUMINANCE
||
371 texImage
->Format
== GL_RGB
) {
372 const GLuint n
= width
* height
* 4;
374 for (i
= 0; i
< n
; i
+= 4) {
375 image
[i
+ 3] = CHAN_MAX
;
379 /* now call glTexSubImage2D to do the real work */
380 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
,
381 xoffset
, yoffset
, width
, height
,
382 GL_RGBA
, CHAN_TYPE
, image
,
383 &_mesa_native_packing
, texObj
, texImage
);
387 /* read depth image from framebuffer */
388 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
390 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
394 /* call glTexImage1D to redefine the texture */
395 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
,
396 xoffset
, yoffset
, width
, height
,
397 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
398 &_mesa_native_packing
, texObj
, texImage
);
402 /* GL_SGIS_generate_mipmap */
403 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
404 _mesa_generate_mipmap(ctx
, texUnit
, texObj
);
410 * Fallback for Driver.CopyTexSubImage3D().
413 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
414 GLenum target
, GLint level
,
415 GLint xoffset
, GLint yoffset
, GLint zoffset
,
416 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
418 struct gl_texture_unit
*texUnit
;
419 struct gl_texture_object
*texObj
;
420 struct gl_texture_image
*texImage
;
422 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
423 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
425 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
428 ASSERT(ctx
->Driver
.TexImage3D
);
430 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
431 /* read RGBA image from framebuffer */
432 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
434 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
439 * XXX this is a bit of a hack. We need to be sure that the alpha
440 * channel is 1.0 if the internal texture format is not supposed to
441 * have an alpha channel. This is because some drivers may store
442 * RGB textures as RGBA and the texutil.c code isn't smart enough
443 * to set the alpha channel to 1.0 in this situation.
445 if (texImage
->Format
== GL_LUMINANCE
||
446 texImage
->Format
== GL_RGB
) {
447 const GLuint n
= width
* height
* 4;
449 for (i
= 0; i
< n
; i
+= 4) {
450 image
[i
+ 3] = CHAN_MAX
;
454 /* now call glTexSubImage3D to do the real work */
455 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
456 xoffset
, yoffset
, zoffset
, width
, height
, 1,
457 GL_RGBA
, CHAN_TYPE
, image
,
458 &_mesa_native_packing
, texObj
, texImage
);
462 /* read depth image from framebuffer */
463 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
465 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
469 /* call glTexImage1D to redefine the texture */
470 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
471 xoffset
, yoffset
, zoffset
, width
, height
, 1,
472 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
473 &_mesa_native_packing
, texObj
, texImage
);
477 /* GL_SGIS_generate_mipmap */
478 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
479 _mesa_generate_mipmap(ctx
, texUnit
, texObj
);