remove unused413 stuff, glDrawBuffersARB uses that slot now
[mesa.git] / src / mesa / swrast / s_texstore.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
23 */
24
25 /*
26 * Authors:
27 * Brian Paul
28 */
29
30
31 /*
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.
35 */
36
37
38
39 #include "glheader.h"
40 #include "imports.h"
41 #include "colormac.h"
42 #include "context.h"
43 #include "convolve.h"
44 #include "image.h"
45 #include "macros.h"
46 #include "texformat.h"
47 #include "teximage.h"
48 #include "texstore.h"
49
50 #include "s_context.h"
51 #include "s_depth.h"
52 #include "s_span.h"
53
54 /*
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.
61 */
62 static GLchan *
63 read_color_image( GLcontext *ctx, GLint x, GLint y,
64 GLsizei width, GLsizei height )
65 {
66 SWcontext *swrast = SWRAST_CONTEXT(ctx);
67 GLint stride, i;
68 GLchan *image, *dst;
69
70 image = (GLchan *) _mesa_malloc(width * height * 4 * sizeof(GLchan));
71 if (!image)
72 return NULL;
73
74 /* Select buffer to read from */
75 _swrast_use_read_buffer(ctx);
76
77 RENDER_START(swrast,ctx);
78
79 dst = image;
80 stride = width * 4;
81 for (i = 0; i < height; i++) {
82 _swrast_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
83 (GLchan (*)[4]) dst );
84 dst += stride;
85 }
86
87 RENDER_FINISH(swrast,ctx);
88
89 /* Read from draw buffer (the default) */
90 _swrast_use_draw_buffer(ctx);
91
92 return image;
93 }
94
95
96 /*
97 * As above, but read data from depth buffer.
98 */
99 static GLfloat *
100 read_depth_image( GLcontext *ctx, GLint x, GLint y,
101 GLsizei width, GLsizei height )
102 {
103 SWcontext *swrast = SWRAST_CONTEXT(ctx);
104 GLfloat *image, *dst;
105 GLint i;
106
107 image = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
108 if (!image)
109 return NULL;
110
111 RENDER_START(swrast,ctx);
112
113 dst = image;
114 for (i = 0; i < height; i++) {
115 _swrast_read_depth_span_float(ctx, width, x, y + i, dst);
116 dst += width;
117 }
118
119 RENDER_FINISH(swrast,ctx);
120
121 return image;
122 }
123
124
125
126 static GLboolean
127 is_depth_format(GLenum format)
128 {
129 switch (format) {
130 case GL_DEPTH_COMPONENT:
131 case GL_DEPTH_COMPONENT16_SGIX:
132 case GL_DEPTH_COMPONENT24_SGIX:
133 case GL_DEPTH_COMPONENT32_SGIX:
134 return GL_TRUE;
135 default:
136 return GL_FALSE;
137 }
138 }
139
140
141 /*
142 * Fallback for Driver.CopyTexImage1D().
143 */
144 void
145 _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
146 GLenum internalFormat,
147 GLint x, GLint y, GLsizei width, GLint border )
148 {
149 struct gl_texture_unit *texUnit;
150 struct gl_texture_object *texObj;
151 struct gl_texture_image *texImage;
152
153 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
154 texObj = _mesa_select_tex_object(ctx, texUnit, target);
155 ASSERT(texObj);
156 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
157 ASSERT(texImage);
158
159 ASSERT(ctx->Driver.TexImage1D);
160
161 if (is_depth_format(internalFormat)) {
162 /* read depth image from framebuffer */
163 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
164 if (!image) {
165 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
166 return;
167 }
168
169 /* call glTexImage1D to redefine the texture */
170 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
171 width, border,
172 GL_DEPTH_COMPONENT, GL_FLOAT, image,
173 &ctx->DefaultPacking, texObj, texImage);
174 _mesa_free(image);
175 }
176 else {
177 /* read RGBA image from framebuffer */
178 GLchan *image = read_color_image(ctx, x, y, width, 1);
179 if (!image) {
180 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
181 return;
182 }
183
184 /* call glTexImage1D to redefine the texture */
185 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
186 width, border,
187 GL_RGBA, CHAN_TYPE, image,
188 &ctx->DefaultPacking, texObj, texImage);
189 _mesa_free(image);
190 }
191
192 /* GL_SGIS_generate_mipmap */
193 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
194 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
195 }
196 }
197
198
199 /*
200 * Fallback for Driver.CopyTexImage2D().
201 */
202 void
203 _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
204 GLenum internalFormat,
205 GLint x, GLint y, GLsizei width, GLsizei height,
206 GLint border )
207 {
208 struct gl_texture_unit *texUnit;
209 struct gl_texture_object *texObj;
210 struct gl_texture_image *texImage;
211
212 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
213 texObj = _mesa_select_tex_object(ctx, texUnit, target);
214 ASSERT(texObj);
215 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
216 ASSERT(texImage);
217
218 ASSERT(ctx->Driver.TexImage2D);
219
220 if (is_depth_format(internalFormat)) {
221 /* read depth image from framebuffer */
222 GLfloat *image = read_depth_image(ctx, x, y, width, height);
223 if (!image) {
224 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
225 return;
226 }
227
228 /* call glTexImage2D to redefine the texture */
229 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
230 width, height, border,
231 GL_DEPTH_COMPONENT, GL_FLOAT, image,
232 &ctx->DefaultPacking, texObj, texImage);
233 _mesa_free(image);
234 }
235 else {
236 /* read RGBA image from framebuffer */
237 GLchan *image = read_color_image(ctx, x, y, width, height);
238 if (!image) {
239 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
240 return;
241 }
242
243 /* call glTexImage2D to redefine the texture */
244 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
245 width, height, border,
246 GL_RGBA, CHAN_TYPE, image,
247 &ctx->DefaultPacking, texObj, texImage);
248 _mesa_free(image);
249 }
250
251 /* GL_SGIS_generate_mipmap */
252 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
253 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
254 }
255 }
256
257
258 /*
259 * Fallback for Driver.CopyTexSubImage1D().
260 */
261 void
262 _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
263 GLint xoffset, GLint x, GLint y, GLsizei width )
264 {
265 struct gl_texture_unit *texUnit;
266 struct gl_texture_object *texObj;
267 struct gl_texture_image *texImage;
268
269 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
270 texObj = _mesa_select_tex_object(ctx, texUnit, target);
271 ASSERT(texObj);
272 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
273 ASSERT(texImage);
274
275 ASSERT(ctx->Driver.TexImage1D);
276
277 if (texImage->Format == GL_DEPTH_COMPONENT) {
278 /* read depth image from framebuffer */
279 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
280 if (!image) {
281 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
282 return;
283 }
284
285 /* call glTexSubImage1D to redefine the texture */
286 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
287 GL_DEPTH_COMPONENT, GL_FLOAT, image,
288 &ctx->DefaultPacking, texObj, texImage);
289 _mesa_free(image);
290 }
291 else {
292 /* read RGBA image from framebuffer */
293 GLchan *image = read_color_image(ctx, x, y, width, 1);
294 if (!image) {
295 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
296 return;
297 }
298
299 /* now call glTexSubImage1D to do the real work */
300 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
301 GL_RGBA, CHAN_TYPE, image,
302 &ctx->DefaultPacking, texObj, texImage);
303 _mesa_free(image);
304 }
305
306 /* GL_SGIS_generate_mipmap */
307 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
308 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
309 }
310 }
311
312
313 /*
314 * Fallback for Driver.CopyTexSubImage2D().
315 */
316 void
317 _swrast_copy_texsubimage2d( GLcontext *ctx,
318 GLenum target, GLint level,
319 GLint xoffset, GLint yoffset,
320 GLint x, GLint y, GLsizei width, GLsizei height )
321 {
322 struct gl_texture_unit *texUnit;
323 struct gl_texture_object *texObj;
324 struct gl_texture_image *texImage;
325
326 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
327 texObj = _mesa_select_tex_object(ctx, texUnit, target);
328 ASSERT(texObj);
329 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
330 ASSERT(texImage);
331
332 ASSERT(ctx->Driver.TexImage2D);
333
334 if (texImage->Format == GL_DEPTH_COMPONENT) {
335 /* read depth image from framebuffer */
336 GLfloat *image = read_depth_image(ctx, x, y, width, height);
337 if (!image) {
338 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
339 return;
340 }
341
342 /* call glTexImage1D to redefine the texture */
343 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
344 xoffset, yoffset, width, height,
345 GL_DEPTH_COMPONENT, GL_FLOAT, image,
346 &ctx->DefaultPacking, texObj, texImage);
347 _mesa_free(image);
348 }
349 else {
350 /* read RGBA image from framebuffer */
351 GLchan *image = read_color_image(ctx, x, y, width, height);
352 if (!image) {
353 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
354 return;
355 }
356
357 /* now call glTexSubImage2D to do the real work */
358 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
359 xoffset, yoffset, width, height,
360 GL_RGBA, CHAN_TYPE, image,
361 &ctx->DefaultPacking, texObj, texImage);
362 _mesa_free(image);
363 }
364
365 /* GL_SGIS_generate_mipmap */
366 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
367 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
368 }
369 }
370
371
372 /*
373 * Fallback for Driver.CopyTexSubImage3D().
374 */
375 void
376 _swrast_copy_texsubimage3d( GLcontext *ctx,
377 GLenum target, GLint level,
378 GLint xoffset, GLint yoffset, GLint zoffset,
379 GLint x, GLint y, GLsizei width, GLsizei height )
380 {
381 struct gl_texture_unit *texUnit;
382 struct gl_texture_object *texObj;
383 struct gl_texture_image *texImage;
384
385 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
386 texObj = _mesa_select_tex_object(ctx, texUnit, target);
387 ASSERT(texObj);
388 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
389 ASSERT(texImage);
390
391 ASSERT(ctx->Driver.TexImage3D);
392
393 if (texImage->Format == GL_DEPTH_COMPONENT) {
394 /* read depth image from framebuffer */
395 GLfloat *image = read_depth_image(ctx, x, y, width, height);
396 if (!image) {
397 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
398 return;
399 }
400
401 /* call glTexImage1D to redefine the texture */
402 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
403 xoffset, yoffset, zoffset, width, height, 1,
404 GL_DEPTH_COMPONENT, GL_FLOAT, image,
405 &ctx->DefaultPacking, texObj, texImage);
406 _mesa_free(image);
407 }
408 else {
409 /* read RGBA image from framebuffer */
410 GLchan *image = read_color_image(ctx, x, y, width, height);
411 if (!image) {
412 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
413 return;
414 }
415
416 /* now call glTexSubImage3D to do the real work */
417 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
418 xoffset, yoffset, zoffset, width, height, 1,
419 GL_RGBA, CHAN_TYPE, image,
420 &ctx->DefaultPacking, texObj, texImage);
421 _mesa_free(image);
422 }
423
424 /* GL_SGIS_generate_mipmap */
425 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
426 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
427 }
428 }