4f4684ddb5780671a23c2e23a9dcda85b69ef746
[mesa.git] / src / mesa / swrast / s_texstore.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2005 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 const GLint stride = 4 * width;
68 GLint i;
69 GLchan *image, *dst;
70
71 image = (GLchan *) _mesa_malloc(width * height * 4 * sizeof(GLchan));
72 if (!image)
73 return NULL;
74
75 RENDER_START(swrast, ctx);
76
77 dst = image;
78 for (i = 0; i < height; i++) {
79 _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
80 width, x, y + i, (GLchan (*)[4]) dst);
81 dst += stride;
82 }
83
84 RENDER_FINISH(swrast, ctx);
85
86 return image;
87 }
88
89
90 /**
91 * As above, but read data from depth buffer.
92 */
93 static GLfloat *
94 read_depth_image( GLcontext *ctx, GLint x, GLint y,
95 GLsizei width, GLsizei height )
96 {
97 struct gl_renderbuffer *rb
98 = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
99 SWcontext *swrast = SWRAST_CONTEXT(ctx);
100 GLfloat *image, *dst;
101 GLint i;
102
103 image = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
104 if (!image)
105 return NULL;
106
107 RENDER_START(swrast, ctx);
108
109 dst = image;
110 for (i = 0; i < height; i++) {
111 _swrast_read_depth_span_float(ctx, rb, width, x, y + i, dst);
112 dst += width;
113 }
114
115 RENDER_FINISH(swrast, ctx);
116
117 return image;
118 }
119
120
121 /**
122 * As above, but read data from depth+stencil buffers.
123 */
124 static GLuint *
125 read_depth_stencil_image(GLcontext *ctx, GLint x, GLint y,
126 GLsizei width, GLsizei height)
127 {
128 struct gl_renderbuffer *depthRb
129 = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
130 struct gl_renderbuffer *stencilRb
131 = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
132 SWcontext *swrast = SWRAST_CONTEXT(ctx);
133 GLuint *image, *dst;
134 GLint i;
135
136 ASSERT(depthRb);
137 ASSERT(stencilRb);
138
139 image = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
140 if (!image)
141 return NULL;
142
143 RENDER_START(swrast, ctx);
144
145 /* read from depth buffer */
146 dst = image;
147 if (depthRb->DataType == GL_UNSIGNED_INT) {
148 for (i = 0; i < height; i++) {
149 _swrast_get_row(ctx, depthRb, width, x, y + i, dst, sizeof(GLuint));
150 dst += width;
151 }
152 }
153 else {
154 GLuint z16[MAX_WIDTH];
155 ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
156 for (i = 0; i < height; i++) {
157 GLint j;
158 _swrast_get_row(ctx, depthRb, width, x, y + i, z16, sizeof(GLushort));
159 for (j = 0; j < width; j++) {
160 dst[j] = z16[j];
161 }
162 dst += width;
163 }
164 }
165
166 /* put depth values into bits 0xffffff00 */
167 if (depthRb->DepthBits == 24) {
168 GLint j;
169 for (j = 0; j < width * height; j++) {
170 image[j] <<= 8;
171 }
172 }
173 else if (depthRb->DepthBits == 16) {
174 GLint j;
175 for (j = 0; j < width * height; j++) {
176 image[j] = (image[j] << 16) | (image[j] & 0xff00);
177 }
178 }
179 else {
180 /* this handles arbitrary depthBits >= 12 */
181 GLint lShift = 32 - depthRb->DepthBits;
182 GLint rShift = depthRb->DepthBits;
183 GLint j;
184 for (j = 0; j < width * height; j++) {
185 GLuint z = (image[j] << lShift);
186 image[j] = z | (z >> rShift);
187 }
188 }
189
190 /* read stencil values and interleave into image array */
191 dst = image;
192 for (i = 0; i < height; i++) {
193 GLstencil stencil[MAX_WIDTH];
194 GLint j;
195 ASSERT(sizeof(GLstencil) == stencilRb->StencilBits);
196 _swrast_get_row(ctx, stencilRb, width, x, y + i,
197 stencil, sizeof(GLstencil));
198 for (j = 0; j < width; j++) {
199 dst[j] = (dst[j] & 0xffffff00) | (stencil[j] & 0xff);
200 }
201 dst += width;
202 }
203
204 RENDER_FINISH(swrast, ctx);
205
206 return image;
207 }
208
209
210 static GLboolean
211 is_depth_format(GLenum format)
212 {
213 switch (format) {
214 case GL_DEPTH_COMPONENT:
215 case GL_DEPTH_COMPONENT16_SGIX:
216 case GL_DEPTH_COMPONENT24_SGIX:
217 case GL_DEPTH_COMPONENT32_SGIX:
218 return GL_TRUE;
219 default:
220 return GL_FALSE;
221 }
222 }
223
224
225 static GLboolean
226 is_depth_stencil_format(GLenum format)
227 {
228 switch (format) {
229 case GL_DEPTH_STENCIL_EXT:
230 case GL_DEPTH24_STENCIL8_EXT:
231 return GL_TRUE;
232 default:
233 return GL_FALSE;
234 }
235 }
236
237
238 /*
239 * Fallback for Driver.CopyTexImage1D().
240 */
241 void
242 _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
243 GLenum internalFormat,
244 GLint x, GLint y, GLsizei width, GLint border )
245 {
246 struct gl_texture_unit *texUnit;
247 struct gl_texture_object *texObj;
248 struct gl_texture_image *texImage;
249
250 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
251 texObj = _mesa_select_tex_object(ctx, texUnit, target);
252 ASSERT(texObj);
253 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
254 ASSERT(texImage);
255
256 ASSERT(ctx->Driver.TexImage1D);
257
258 if (is_depth_format(internalFormat)) {
259 /* read depth image from framebuffer */
260 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
261 if (!image) {
262 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
263 return;
264 }
265 /* call glTexImage1D to redefine the texture */
266 ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
267 width, border,
268 GL_DEPTH_COMPONENT, GL_FLOAT, image,
269 &ctx->DefaultPacking, texObj, texImage);
270 _mesa_free(image);
271 }
272 else if (is_depth_stencil_format(internalFormat)) {
273 /* read depth/stencil image from framebuffer */
274 GLuint *image = read_depth_stencil_image(ctx, x, y, width, 1);
275 if (!image) {
276 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
277 return;
278 }
279 /* call glTexImage1D to redefine the texture */
280 ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
281 width, border,
282 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
283 image, &ctx->DefaultPacking, texObj, texImage);
284 _mesa_free(image);
285 }
286 else {
287 /* read RGBA image from framebuffer */
288 GLchan *image = read_color_image(ctx, x, y, width, 1);
289 if (!image) {
290 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
291 return;
292 }
293 /* call glTexImage1D to redefine the texture */
294 ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
295 width, border,
296 GL_RGBA, CHAN_TYPE, image,
297 &ctx->DefaultPacking, texObj, texImage);
298 _mesa_free(image);
299 }
300
301 /* GL_SGIS_generate_mipmap */
302 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
303 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
304 }
305 }
306
307
308 /*
309 * Fallback for Driver.CopyTexImage2D().
310 */
311 void
312 _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
313 GLenum internalFormat,
314 GLint x, GLint y, GLsizei width, GLsizei height,
315 GLint border )
316 {
317 struct gl_texture_unit *texUnit;
318 struct gl_texture_object *texObj;
319 struct gl_texture_image *texImage;
320
321 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
322 texObj = _mesa_select_tex_object(ctx, texUnit, target);
323 ASSERT(texObj);
324 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
325 ASSERT(texImage);
326
327 ASSERT(ctx->Driver.TexImage2D);
328
329 if (is_depth_format(internalFormat)) {
330 /* read depth image from framebuffer */
331 GLfloat *image = read_depth_image(ctx, x, y, width, height);
332 if (!image) {
333 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
334 return;
335 }
336 /* call glTexImage2D to redefine the texture */
337 ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
338 width, height, border,
339 GL_DEPTH_COMPONENT, GL_FLOAT, image,
340 &ctx->DefaultPacking, texObj, texImage);
341 _mesa_free(image);
342 }
343 else if (is_depth_stencil_format(internalFormat)) {
344 GLuint *image = read_depth_stencil_image(ctx, x, y, width, height);
345 if (!image) {
346 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
347 return;
348 }
349 /* call glTexImage2D to redefine the texture */
350 ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
351 width, height, border,
352 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
353 image, &ctx->DefaultPacking, texObj, texImage);
354 _mesa_free(image);
355 }
356 else {
357 /* read RGBA image from framebuffer */
358 GLchan *image = read_color_image(ctx, x, y, width, height);
359 if (!image) {
360 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
361 return;
362 }
363 /* call glTexImage2D to redefine the texture */
364 ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
365 width, height, border,
366 GL_RGBA, CHAN_TYPE, image,
367 &ctx->DefaultPacking, texObj, texImage);
368 _mesa_free(image);
369 }
370
371 /* GL_SGIS_generate_mipmap */
372 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
373 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
374 }
375 }
376
377
378 /*
379 * Fallback for Driver.CopyTexSubImage1D().
380 */
381 void
382 _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
383 GLint xoffset, GLint x, GLint y, GLsizei width )
384 {
385 struct gl_texture_unit *texUnit;
386 struct gl_texture_object *texObj;
387 struct gl_texture_image *texImage;
388
389 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
390 texObj = _mesa_select_tex_object(ctx, texUnit, target);
391 ASSERT(texObj);
392 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
393 ASSERT(texImage);
394
395 ASSERT(ctx->Driver.TexImage1D);
396
397 if (texImage->Format == GL_DEPTH_COMPONENT) {
398 /* read depth image from framebuffer */
399 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
400 if (!image) {
401 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
402 return;
403 }
404
405 /* call glTexSubImage1D to redefine the texture */
406 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
407 GL_DEPTH_COMPONENT, GL_FLOAT, image,
408 &ctx->DefaultPacking, texObj, texImage);
409 _mesa_free(image);
410 }
411 else if (texImage->Format == GL_DEPTH_STENCIL_EXT) {
412 /* read depth/stencil image from framebuffer */
413 GLuint *image = read_depth_stencil_image(ctx, x, y, width, 1);
414 if (!image) {
415 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
416 return;
417 }
418 /* call glTexImage1D to redefine the texture */
419 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
420 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
421 image, &ctx->DefaultPacking, texObj, texImage);
422 _mesa_free(image);
423 }
424 else {
425 /* read RGBA image from framebuffer */
426 GLchan *image = read_color_image(ctx, x, y, width, 1);
427 if (!image) {
428 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
429 return;
430 }
431 /* now call glTexSubImage1D to do the real work */
432 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
433 GL_RGBA, CHAN_TYPE, image,
434 &ctx->DefaultPacking, texObj, texImage);
435 _mesa_free(image);
436 }
437
438 /* GL_SGIS_generate_mipmap */
439 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
440 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
441 }
442 }
443
444
445 /*
446 * Fallback for Driver.CopyTexSubImage2D().
447 */
448 void
449 _swrast_copy_texsubimage2d( GLcontext *ctx,
450 GLenum target, GLint level,
451 GLint xoffset, GLint yoffset,
452 GLint x, GLint y, GLsizei width, GLsizei height )
453 {
454 struct gl_texture_unit *texUnit;
455 struct gl_texture_object *texObj;
456 struct gl_texture_image *texImage;
457
458 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
459 texObj = _mesa_select_tex_object(ctx, texUnit, target);
460 ASSERT(texObj);
461 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
462 ASSERT(texImage);
463
464 ASSERT(ctx->Driver.TexImage2D);
465
466 if (texImage->Format == GL_DEPTH_COMPONENT) {
467 /* read depth image from framebuffer */
468 GLfloat *image = read_depth_image(ctx, x, y, width, height);
469 if (!image) {
470 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
471 return;
472 }
473 /* call glTexImage2D to redefine the texture */
474 ctx->Driver.TexSubImage2D(ctx, target, level,
475 xoffset, yoffset, width, height,
476 GL_DEPTH_COMPONENT, GL_FLOAT, image,
477 &ctx->DefaultPacking, texObj, texImage);
478 _mesa_free(image);
479 }
480 else if (texImage->Format == GL_DEPTH_STENCIL_EXT) {
481 /* read depth/stencil image from framebuffer */
482 GLuint *image = read_depth_stencil_image(ctx, x, y, width, height);
483 if (!image) {
484 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
485 return;
486 }
487 /* call glTexImage2D to redefine the texture */
488 ctx->Driver.TexSubImage2D(ctx, target, level,
489 xoffset, yoffset, width, height,
490 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
491 image, &ctx->DefaultPacking, texObj, texImage);
492 _mesa_free(image);
493 }
494 else {
495 /* read RGBA image from framebuffer */
496 GLchan *image = read_color_image(ctx, x, y, width, height);
497 if (!image) {
498 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
499 return;
500 }
501 /* now call glTexSubImage2D to do the real work */
502 ctx->Driver.TexSubImage2D(ctx, target, level,
503 xoffset, yoffset, width, height,
504 GL_RGBA, CHAN_TYPE, image,
505 &ctx->DefaultPacking, texObj, texImage);
506 _mesa_free(image);
507 }
508
509 /* GL_SGIS_generate_mipmap */
510 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
511 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
512 }
513 }
514
515
516 /*
517 * Fallback for Driver.CopyTexSubImage3D().
518 */
519 void
520 _swrast_copy_texsubimage3d( GLcontext *ctx,
521 GLenum target, GLint level,
522 GLint xoffset, GLint yoffset, GLint zoffset,
523 GLint x, GLint y, GLsizei width, GLsizei height )
524 {
525 struct gl_texture_unit *texUnit;
526 struct gl_texture_object *texObj;
527 struct gl_texture_image *texImage;
528
529 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
530 texObj = _mesa_select_tex_object(ctx, texUnit, target);
531 ASSERT(texObj);
532 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
533 ASSERT(texImage);
534
535 ASSERT(ctx->Driver.TexImage3D);
536
537 if (texImage->Format == GL_DEPTH_COMPONENT) {
538 /* read depth image from framebuffer */
539 GLfloat *image = read_depth_image(ctx, x, y, width, height);
540 if (!image) {
541 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
542 return;
543 }
544 /* call glTexImage3D to redefine the texture */
545 ctx->Driver.TexSubImage3D(ctx, target, level,
546 xoffset, yoffset, zoffset, width, height, 1,
547 GL_DEPTH_COMPONENT, GL_FLOAT, image,
548 &ctx->DefaultPacking, texObj, texImage);
549 _mesa_free(image);
550 }
551 else if (texImage->Format == GL_DEPTH_STENCIL_EXT) {
552 /* read depth/stencil image from framebuffer */
553 GLuint *image = read_depth_stencil_image(ctx, x, y, width, height);
554 if (!image) {
555 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
556 return;
557 }
558 /* call glTexImage3D to redefine the texture */
559 ctx->Driver.TexSubImage3D(ctx, target, level,
560 xoffset, yoffset, zoffset, width, height, 1,
561 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
562 image, &ctx->DefaultPacking, texObj, texImage);
563 _mesa_free(image);
564 }
565 else {
566 /* read RGBA image from framebuffer */
567 GLchan *image = read_color_image(ctx, x, y, width, height);
568 if (!image) {
569 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
570 return;
571 }
572 /* now call glTexSubImage3D to do the real work */
573 ctx->Driver.TexSubImage3D(ctx, target, level,
574 xoffset, yoffset, zoffset, width, height, 1,
575 GL_RGBA, CHAN_TYPE, image,
576 &ctx->DefaultPacking, texObj, texImage);
577 _mesa_free(image);
578 }
579
580 /* GL_SGIS_generate_mipmap */
581 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
582 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
583 }
584 }