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