added missing \'s
[mesa.git] / src / mesa / swrast / s_texstore.c
1 /* $Id: s_texstore.c,v 1.5 2001/05/21 16:41:04 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27 /*
28 * Authors:
29 * Brian Paul
30 */
31
32
33 /*
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.
37 */
38
39
40
41 #include "colormac.h"
42 #include "context.h"
43 #include "convolve.h"
44 #include "image.h"
45 #include "macros.h"
46 #include "mem.h"
47 #include "texformat.h"
48 #include "teximage.h"
49 #include "texstore.h"
50
51 #include "s_context.h"
52 #include "s_depth.h"
53 #include "s_span.h"
54
55 /*
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.
62 */
63 static GLchan *
64 read_color_image( GLcontext *ctx, GLint x, GLint y,
65 GLsizei width, GLsizei height )
66 {
67 SWcontext *swrast = SWRAST_CONTEXT(ctx);
68 GLint stride, i;
69 GLchan *image, *dst;
70
71 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
72 if (!image)
73 return NULL;
74
75 /* Select buffer to read from */
76 (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
77 ctx->Pixel.DriverReadBuffer );
78
79 RENDER_START(swrast,ctx);
80
81 dst = image;
82 stride = width * 4;
83 for (i = 0; i < height; i++) {
84 _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
85 (GLchan (*)[4]) dst );
86 dst += stride;
87 }
88
89 RENDER_FINISH(swrast,ctx);
90
91 /* Read from draw buffer (the default) */
92 (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
93 ctx->Color.DriverDrawBuffer );
94
95 return image;
96 }
97
98
99 /*
100 * As above, but read data from depth buffer.
101 */
102 static GLfloat *
103 read_depth_image( GLcontext *ctx, GLint x, GLint y,
104 GLsizei width, GLsizei height )
105 {
106 SWcontext *swrast = SWRAST_CONTEXT(ctx);
107 GLfloat *image, *dst;
108 GLint i;
109
110 image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
111 if (!image)
112 return NULL;
113
114 RENDER_START(swrast,ctx);
115
116 dst = image;
117 for (i = 0; i < height; i++) {
118 _mesa_read_depth_span_float(ctx, width, x, y + i, dst);
119 dst += width;
120 }
121
122 RENDER_FINISH(swrast,ctx);
123
124 return image;
125 }
126
127
128
129 static GLboolean
130 is_depth_format(GLenum format)
131 {
132 switch (format) {
133 case GL_DEPTH_COMPONENT:
134 case GL_DEPTH_COMPONENT16_SGIX:
135 case GL_DEPTH_COMPONENT24_SGIX:
136 case GL_DEPTH_COMPONENT32_SGIX:
137 return GL_TRUE;
138 default:
139 return GL_FALSE;
140 }
141 }
142
143
144 /*
145 * Fallback for Driver.CopyTexImage1D().
146 */
147 void
148 _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
149 GLenum internalFormat,
150 GLint x, GLint y, GLsizei width, GLint border )
151 {
152 struct gl_texture_unit *texUnit;
153 struct gl_texture_object *texObj;
154 struct gl_texture_image *texImage;
155
156 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
157 texObj = _mesa_select_tex_object(ctx, texUnit, target);
158 ASSERT(texObj);
159 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
160 ASSERT(texImage);
161
162 ASSERT(ctx->Driver.TexImage1D);
163
164 if (is_depth_format(internalFormat)) {
165 /* read depth image from framebuffer */
166 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
167 if (!image) {
168 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
169 return;
170 }
171
172 /* call glTexImage1D to redefine the texture */
173 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
174 width, border,
175 GL_DEPTH_COMPONENT, GL_FLOAT, image,
176 &_mesa_native_packing, texObj, texImage);
177 FREE(image);
178 }
179 else {
180 /* read RGBA image from framebuffer */
181 GLchan *image = read_color_image(ctx, x, y, width, 1);
182 if (!image) {
183 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
184 return;
185 }
186
187 /* call glTexImage1D to redefine the texture */
188 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
189 width, border,
190 GL_RGBA, CHAN_TYPE, image,
191 &_mesa_native_packing, texObj, texImage);
192 FREE(image);
193 }
194
195 /* GL_SGIS_generate_mipmap */
196 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
197 _mesa_generate_mipmap(ctx, texUnit, texObj);
198 }
199 }
200
201
202 /*
203 * Fallback for Driver.CopyTexImage2D().
204 */
205 void
206 _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
207 GLenum internalFormat,
208 GLint x, GLint y, GLsizei width, GLsizei height,
209 GLint border )
210 {
211 struct gl_texture_unit *texUnit;
212 struct gl_texture_object *texObj;
213 struct gl_texture_image *texImage;
214
215 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
216 texObj = _mesa_select_tex_object(ctx, texUnit, target);
217 ASSERT(texObj);
218 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
219 ASSERT(texImage);
220
221 ASSERT(ctx->Driver.TexImage2D);
222
223 if (is_depth_format(internalFormat)) {
224 /* read depth image from framebuffer */
225 GLfloat *image = read_depth_image(ctx, x, y, width, height);
226 if (!image) {
227 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
228 return;
229 }
230
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);
236 FREE(image);
237 }
238 else {
239 /* read RGBA image from framebuffer */
240 GLchan *image = read_color_image(ctx, x, y, width, height);
241 if (!image) {
242 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
243 return;
244 }
245
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);
251 FREE(image);
252 }
253
254 /* GL_SGIS_generate_mipmap */
255 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
256 _mesa_generate_mipmap(ctx, texUnit, texObj);
257 }
258 }
259
260
261 /*
262 * Fallback for Driver.CopyTexSubImage1D().
263 */
264 void
265 _swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
266 GLint xoffset, GLint x, GLint y, GLsizei width)
267 {
268 struct gl_texture_unit *texUnit;
269 struct gl_texture_object *texObj;
270 struct gl_texture_image *texImage;
271
272 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
273 texObj = _mesa_select_tex_object(ctx, texUnit, target);
274 ASSERT(texObj);
275 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
276 ASSERT(texImage);
277
278 ASSERT(ctx->Driver.TexImage1D);
279
280 if (texImage->Format != GL_DEPTH_COMPONENT) {
281 /* read RGBA image from framebuffer */
282 GLchan *image = read_color_image(ctx, x, y, width, 1);
283 if (!image) {
284 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
285 return;
286 }
287
288 #if 0
289 /*
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.
295 */
296 if (texImage->Format == GL_LUMINANCE ||
297 texImage->Format == GL_RGB) {
298 const GLuint n = width * 4;
299 GLuint i;
300 for (i = 0; i < n; i += 4) {
301 image[i + 3] = CHAN_MAX;
302 }
303 }
304 #endif
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);
309 FREE(image);
310 }
311 else {
312 /* read depth image from framebuffer */
313 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
314 if (!image) {
315 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
316 return;
317 }
318
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);
323 FREE(image);
324 }
325
326 /* GL_SGIS_generate_mipmap */
327 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
328 _mesa_generate_mipmap(ctx, texUnit, texObj);
329 }
330 }
331
332
333 /*
334 * Fallback for Driver.CopyTexSubImage2D().
335 */
336 void
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 )
341 {
342 struct gl_texture_unit *texUnit;
343 struct gl_texture_object *texObj;
344 struct gl_texture_image *texImage;
345
346 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
347 texObj = _mesa_select_tex_object(ctx, texUnit, target);
348 ASSERT(texObj);
349 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
350 ASSERT(texImage);
351
352 ASSERT(ctx->Driver.TexImage2D);
353
354 if (texImage->Format != GL_DEPTH_COMPONENT) {
355 /* read RGBA image from framebuffer */
356 GLchan *image = read_color_image(ctx, x, y, width, height);
357 if (!image) {
358 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
359 return;
360 }
361
362 #if 0
363 /*
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.
369 */
370 if (texImage->Format == GL_LUMINANCE ||
371 texImage->Format == GL_RGB) {
372 const GLuint n = width * height * 4;
373 GLuint i;
374 for (i = 0; i < n; i += 4) {
375 image[i + 3] = CHAN_MAX;
376 }
377 }
378 #endif
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);
384 FREE(image);
385 }
386 else {
387 /* read depth image from framebuffer */
388 GLfloat *image = read_depth_image(ctx, x, y, width, height);
389 if (!image) {
390 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
391 return;
392 }
393
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);
399 FREE(image);
400 }
401
402 /* GL_SGIS_generate_mipmap */
403 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
404 _mesa_generate_mipmap(ctx, texUnit, texObj);
405 }
406 }
407
408
409 /*
410 * Fallback for Driver.CopyTexSubImage3D().
411 */
412 void
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 )
417 {
418 struct gl_texture_unit *texUnit;
419 struct gl_texture_object *texObj;
420 struct gl_texture_image *texImage;
421
422 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
423 texObj = _mesa_select_tex_object(ctx, texUnit, target);
424 ASSERT(texObj);
425 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
426 ASSERT(texImage);
427
428 ASSERT(ctx->Driver.TexImage3D);
429
430 if (texImage->Format != GL_DEPTH_COMPONENT) {
431 /* read RGBA image from framebuffer */
432 GLchan *image = read_color_image(ctx, x, y, width, height);
433 if (!image) {
434 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
435 return;
436 }
437 #if 0
438 /*
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.
444 */
445 if (texImage->Format == GL_LUMINANCE ||
446 texImage->Format == GL_RGB) {
447 const GLuint n = width * height * 4;
448 GLuint i;
449 for (i = 0; i < n; i += 4) {
450 image[i + 3] = CHAN_MAX;
451 }
452 }
453 #endif
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);
459 FREE(image);
460 }
461 else {
462 /* read depth image from framebuffer */
463 GLfloat *image = read_depth_image(ctx, x, y, width, height);
464 if (!image) {
465 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
466 return;
467 }
468
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);
474 FREE(image);
475 }
476
477 /* GL_SGIS_generate_mipmap */
478 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
479 _mesa_generate_mipmap(ctx, texUnit, texObj);
480 }
481 }