2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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
);
70 image
= (GLchan
*) _mesa_malloc(width
* height
* 4 * sizeof(GLchan
));
74 /* Select buffer to read from */
75 _swrast_use_read_buffer(ctx
);
77 RENDER_START(swrast
,ctx
);
81 for (i
= 0; i
< height
; i
++) {
82 _swrast_read_rgba_span(ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
83 width
, x
, y
+ i
, (GLchan (*)[4]) dst
);
87 RENDER_FINISH(swrast
,ctx
);
89 /* Read from draw buffer (the default) */
90 _swrast_use_draw_buffer(ctx
);
97 * As above, but read data from depth buffer.
100 read_depth_image( GLcontext
*ctx
, GLint x
, GLint y
,
101 GLsizei width
, GLsizei height
)
103 struct gl_renderbuffer
*rb
104 = ctx
->ReadBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
105 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
106 GLfloat
*image
, *dst
;
109 image
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
113 RENDER_START(swrast
,ctx
);
116 for (i
= 0; i
< height
; i
++) {
117 _swrast_read_depth_span_float(ctx
, rb
, width
, x
, y
+ i
, dst
);
121 RENDER_FINISH(swrast
,ctx
);
129 is_depth_format(GLenum format
)
132 case GL_DEPTH_COMPONENT
:
133 case GL_DEPTH_COMPONENT16_SGIX
:
134 case GL_DEPTH_COMPONENT24_SGIX
:
135 case GL_DEPTH_COMPONENT32_SGIX
:
144 * Fallback for Driver.CopyTexImage1D().
147 _swrast_copy_teximage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
148 GLenum internalFormat
,
149 GLint x
, GLint y
, GLsizei width
, GLint border
)
151 struct gl_texture_unit
*texUnit
;
152 struct gl_texture_object
*texObj
;
153 struct gl_texture_image
*texImage
;
155 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
156 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
158 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
161 ASSERT(ctx
->Driver
.TexImage1D
);
163 if (is_depth_format(internalFormat
)) {
164 /* read depth image from framebuffer */
165 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
167 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
171 /* call glTexImage1D to redefine the texture */
172 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
174 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
175 &ctx
->DefaultPacking
, texObj
, texImage
);
179 /* read RGBA image from framebuffer */
180 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
182 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
186 /* call glTexImage1D to redefine the texture */
187 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
189 GL_RGBA
, CHAN_TYPE
, image
,
190 &ctx
->DefaultPacking
, texObj
, texImage
);
194 /* GL_SGIS_generate_mipmap */
195 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
196 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
202 * Fallback for Driver.CopyTexImage2D().
205 _swrast_copy_teximage2d( GLcontext
*ctx
, GLenum target
, GLint level
,
206 GLenum internalFormat
,
207 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
210 struct gl_texture_unit
*texUnit
;
211 struct gl_texture_object
*texObj
;
212 struct gl_texture_image
*texImage
;
214 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
215 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
217 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
220 ASSERT(ctx
->Driver
.TexImage2D
);
222 if (is_depth_format(internalFormat
)) {
223 /* read depth image from framebuffer */
224 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
226 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
230 /* call glTexImage2D to redefine the texture */
231 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
232 width
, height
, border
,
233 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
234 &ctx
->DefaultPacking
, texObj
, texImage
);
238 /* read RGBA image from framebuffer */
239 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
241 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
245 /* call glTexImage2D to redefine the texture */
246 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
247 width
, height
, border
,
248 GL_RGBA
, CHAN_TYPE
, image
,
249 &ctx
->DefaultPacking
, texObj
, texImage
);
253 /* GL_SGIS_generate_mipmap */
254 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
255 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
261 * Fallback for Driver.CopyTexSubImage1D().
264 _swrast_copy_texsubimage1d( GLcontext
*ctx
, GLenum target
, GLint level
,
265 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
267 struct gl_texture_unit
*texUnit
;
268 struct gl_texture_object
*texObj
;
269 struct gl_texture_image
*texImage
;
271 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
272 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
274 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
277 ASSERT(ctx
->Driver
.TexImage1D
);
279 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
280 /* read depth image from framebuffer */
281 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, 1);
283 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D");
287 /* call glTexSubImage1D to redefine the texture */
288 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
289 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
290 &ctx
->DefaultPacking
, texObj
, texImage
);
294 /* read RGBA image from framebuffer */
295 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, 1);
297 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage1D" );
301 /* now call glTexSubImage1D to do the real work */
302 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
303 GL_RGBA
, CHAN_TYPE
, image
,
304 &ctx
->DefaultPacking
, texObj
, texImage
);
308 /* GL_SGIS_generate_mipmap */
309 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
310 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
316 * Fallback for Driver.CopyTexSubImage2D().
319 _swrast_copy_texsubimage2d( GLcontext
*ctx
,
320 GLenum target
, GLint level
,
321 GLint xoffset
, GLint yoffset
,
322 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
, texUnit
, target
, level
);
334 ASSERT(ctx
->Driver
.TexImage2D
);
336 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
337 /* read depth image from framebuffer */
338 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
340 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D");
344 /* call glTexImage1D to redefine the texture */
345 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
,
346 xoffset
, yoffset
, width
, height
,
347 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
348 &ctx
->DefaultPacking
, texObj
, texImage
);
352 /* read RGBA image from framebuffer */
353 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
355 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
359 /* now call glTexSubImage2D to do the real work */
360 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
,
361 xoffset
, yoffset
, width
, height
,
362 GL_RGBA
, CHAN_TYPE
, image
,
363 &ctx
->DefaultPacking
, texObj
, texImage
);
367 /* GL_SGIS_generate_mipmap */
368 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
369 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);
375 * Fallback for Driver.CopyTexSubImage3D().
378 _swrast_copy_texsubimage3d( GLcontext
*ctx
,
379 GLenum target
, GLint level
,
380 GLint xoffset
, GLint yoffset
, GLint zoffset
,
381 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
383 struct gl_texture_unit
*texUnit
;
384 struct gl_texture_object
*texObj
;
385 struct gl_texture_image
*texImage
;
387 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
388 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
390 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
393 ASSERT(ctx
->Driver
.TexImage3D
);
395 if (texImage
->Format
== GL_DEPTH_COMPONENT
) {
396 /* read depth image from framebuffer */
397 GLfloat
*image
= read_depth_image(ctx
, x
, y
, width
, height
);
399 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D");
403 /* call glTexImage1D to redefine the texture */
404 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
405 xoffset
, yoffset
, zoffset
, width
, height
, 1,
406 GL_DEPTH_COMPONENT
, GL_FLOAT
, image
,
407 &ctx
->DefaultPacking
, texObj
, texImage
);
411 /* read RGBA image from framebuffer */
412 GLchan
*image
= read_color_image(ctx
, x
, y
, width
, height
);
414 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage3D" );
418 /* now call glTexSubImage3D to do the real work */
419 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
420 xoffset
, yoffset
, zoffset
, width
, height
, 1,
421 GL_RGBA
, CHAN_TYPE
, image
,
422 &ctx
->DefaultPacking
, texObj
, texImage
);
426 /* GL_SGIS_generate_mipmap */
427 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
428 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);