1 /* $Id: s_texstore.c,v 1.8 2002/09/27 02:45:39 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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_use_read_buffer(ctx
);
78 RENDER_START(swrast
,ctx
);
82 for (i
= 0; i
< height
; i
++) {
83 _mesa_read_rgba_span( ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
84 (GLchan (*)[4]) dst
);
88 RENDER_FINISH(swrast
,ctx
);
90 /* Read from draw buffer (the default) */
91 _swrast_use_draw_buffer(ctx
);
98 * As above, but read data from depth buffer.
101 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
102 GLsizei width
, GLsizei height
)
104 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
105 GLfloat
*image
, *dst
;
108 image
= (GLfloat
*) MALLOC(width
* height
* sizeof(GLfloat
));
112 RENDER_START(swrast
,ctx
);
115 for (i
= 0; i
< height
; i
++) {
116 _mesa_read_depth_span_float(ctx
, width
, x
, y
+ i
, dst
);
120 RENDER_FINISH(swrast
,ctx
);
128 is_depth_format(GLenum format
)
131 case GL_DEPTH_COMPONENT
:
132 case GL_DEPTH_COMPONENT16_SGIX
:
133 case GL_DEPTH_COMPONENT24_SGIX
:
134 case GL_DEPTH_COMPONENT32_SGIX
:
143 * Fallback for Driver.CopyTexImage1D().
146 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
147 GLenum internalFormat
,
148 GLint x
, GLint y
, GLsizei width
, GLint border
)
150 struct gl_texture_unit
*texUnit
;
151 struct gl_texture_object
*texObj
;
152 struct gl_texture_image
*texImage
;
154 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
155 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
157 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
160 ASSERT(ctx
->Driver
.TexImage1D
);
162 if (is_depth_format(internalFormat
)) {
163 /* read depth image from framebuffer */
164 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
166 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
170 /* call glTexImage1D to redefine the texture */
171 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
173 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
174 &_mesa_native_packing
, texObj
, texImage
);
178 /* read RGBA image from framebuffer */
179 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
181 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
185 /* call glTexImage1D to redefine the texture */
186 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
188 GL_RGBA
, CHAN_TYPE
, image
,
189 &_mesa_native_packing
, texObj
, texImage
);
193 /* GL_SGIS_generate_mipmap */
194 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
195 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
201 * Fallback for Driver.CopyTexImage2D().
204 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
205 GLenum internalFormat
,
206 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
209 struct gl_texture_unit
*texUnit
;
210 struct gl_texture_object
*texObj
;
211 struct gl_texture_image
*texImage
;
213 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
214 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
216 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
219 ASSERT(ctx
->Driver
.TexImage2D
);
221 if (is_depth_format(internalFormat
)) {
222 /* read depth image from framebuffer */
223 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
225 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
229 /* call glTexImage2D to redefine the texture */
230 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
231 width
, height
, border
,
232 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
233 &_mesa_native_packing
, texObj
, texImage
);
237 /* read RGBA image from framebuffer */
238 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
240 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
244 /* call glTexImage2D to redefine the texture */
245 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
246 width
, height
, border
,
247 GL_RGBA
, CHAN_TYPE
, image
,
248 &_mesa_native_packing
, texObj
, texImage
);
252 /* GL_SGIS_generate_mipmap */
253 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
254 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
260 * Fallback for Driver.CopyTexSubImage1D().
263 _swrast_copy_texsubimage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
264 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
266 struct gl_texture_unit
*texUnit
;
267 struct gl_texture_object
*texObj
;
268 struct gl_texture_image
*texImage
;
270 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
271 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
273 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
276 ASSERT(ctx
->Driver
.TexImage1D
);
278 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
279 /* read depth image from framebuffer */
280 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
282 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
286 /* call glTexSubImage1D to redefine the texture */
287 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
288 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
289 &_mesa_native_packing
, texObj
, texImage
);
293 /* read RGBA image from framebuffer */
294 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
296 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
300 /* now call glTexSubImage1D to do the real work */
301 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
302 GL_RGBA
, CHAN_TYPE
, image
,
303 &_mesa_native_packing
, texObj
, texImage
);
307 /* GL_SGIS_generate_mipmap */
308 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
309 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
315 * Fallback for Driver.CopyTexSubImage2D().
318 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
319 GLenum target
, GLint level
,
320 GLint xoffset
, GLint yoffset
,
321 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
323 struct gl_texture_unit
*texUnit
;
324 struct gl_texture_object
*texObj
;
325 struct gl_texture_image
*texImage
;
327 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
328 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
330 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
333 ASSERT(ctx
->Driver
.TexImage2D
);
335 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
336 /* read depth image from framebuffer */
337 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
339 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
343 /* call glTexImage1D to redefine the texture */
344 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
,
345 xoffset
, yoffset
, width
, height
,
346 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
347 &_mesa_native_packing
, texObj
, texImage
);
351 /* read RGBA image from framebuffer */
352 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
354 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
358 /* now call glTexSubImage2D to do the real work */
359 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
,
360 xoffset
, yoffset
, width
, height
,
361 GL_RGBA
, CHAN_TYPE
, image
,
362 &_mesa_native_packing
, texObj
, texImage
);
366 /* GL_SGIS_generate_mipmap */
367 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
368 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
374 * Fallback for Driver.CopyTexSubImage3D().
377 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
378 GLenum target
, GLint level
,
379 GLint xoffset
, GLint yoffset
, GLint zoffset
,
380 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
382 struct gl_texture_unit
*texUnit
;
383 struct gl_texture_object
*texObj
;
384 struct gl_texture_image
*texImage
;
386 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
387 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
389 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
392 ASSERT(ctx
->Driver
.TexImage3D
);
394 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
395 /* read depth image from framebuffer */
396 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
398 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
402 /* call glTexImage1D to redefine the texture */
403 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
404 xoffset
, yoffset
, zoffset
, width
, height
, 1,
405 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
406 &_mesa_native_packing
, texObj
, texImage
);
410 /* read RGBA image from framebuffer */
411 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
413 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
417 /* now call glTexSubImage3D to do the real work */
418 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
419 xoffset
, yoffset
, zoffset
, width
, height
, 1,
420 GL_RGBA
, CHAN_TYPE
, image
,
421 &_mesa_native_packing
, texObj
, texImage
);
425 /* GL_SGIS_generate_mipmap */
426 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
427 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);