Remove #endif.
[mesa.git] / src / mesa / main / texstore.c
1 /* $Id: texstore.c,v 1.14 2001/03/18 14:05:32 gareth 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 "teximage.h"
48 #include "texstore.h"
49 #include "swrast/s_depth.h" /* XXX this is kind of a cheat */
50 #include "swrast/s_span.h"
51
52
53 /*
54 * Given an internal texture format enum or 1, 2, 3, 4 return the
55 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
56 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
57 * number of components for the format. Return -1 if invalid enum.
58 *
59 * GH: Do we really need this? We have the number of bytes per texel
60 * in the texture format structures, so why don't we just use that?
61 */
62 static GLint
63 components_in_intformat( GLint format )
64 {
65 switch (format) {
66 case GL_ALPHA:
67 case GL_ALPHA4:
68 case GL_ALPHA8:
69 case GL_ALPHA12:
70 case GL_ALPHA16:
71 return 1;
72 case 1:
73 case GL_LUMINANCE:
74 case GL_LUMINANCE4:
75 case GL_LUMINANCE8:
76 case GL_LUMINANCE12:
77 case GL_LUMINANCE16:
78 return 1;
79 case 2:
80 case GL_LUMINANCE_ALPHA:
81 case GL_LUMINANCE4_ALPHA4:
82 case GL_LUMINANCE6_ALPHA2:
83 case GL_LUMINANCE8_ALPHA8:
84 case GL_LUMINANCE12_ALPHA4:
85 case GL_LUMINANCE12_ALPHA12:
86 case GL_LUMINANCE16_ALPHA16:
87 return 2;
88 case GL_INTENSITY:
89 case GL_INTENSITY4:
90 case GL_INTENSITY8:
91 case GL_INTENSITY12:
92 case GL_INTENSITY16:
93 return 1;
94 case 3:
95 case GL_RGB:
96 case GL_R3_G3_B2:
97 case GL_RGB4:
98 case GL_RGB5:
99 case GL_RGB8:
100 case GL_RGB10:
101 case GL_RGB12:
102 case GL_RGB16:
103 return 3;
104 case 4:
105 case GL_RGBA:
106 case GL_RGBA2:
107 case GL_RGBA4:
108 case GL_RGB5_A1:
109 case GL_RGBA8:
110 case GL_RGB10_A2:
111 case GL_RGBA12:
112 case GL_RGBA16:
113 return 4;
114 case GL_COLOR_INDEX:
115 case GL_COLOR_INDEX1_EXT:
116 case GL_COLOR_INDEX2_EXT:
117 case GL_COLOR_INDEX4_EXT:
118 case GL_COLOR_INDEX8_EXT:
119 case GL_COLOR_INDEX12_EXT:
120 case GL_COLOR_INDEX16_EXT:
121 return 1;
122 case GL_DEPTH_COMPONENT:
123 case GL_DEPTH_COMPONENT16_SGIX:
124 case GL_DEPTH_COMPONENT24_SGIX:
125 case GL_DEPTH_COMPONENT32_SGIX:
126 return 1;
127 default:
128 return -1; /* error */
129 }
130 }
131
132
133 /*
134 * This function is used to transfer the user's image data into a texture
135 * image buffer. We handle both full texture images and subtexture images.
136 * We also take care of all image transfer operations here, including
137 * convolution, scale/bias, colortables, etc.
138 *
139 * The destination texel channel type is always GLchan.
140 *
141 * A hardware driver may use this as a helper routine to unpack and
142 * apply pixel transfer ops into a temporary image buffer. Then,
143 * convert the temporary image into the special hardware format.
144 *
145 * Input:
146 * dimensions - 1, 2, or 3
147 * texFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
148 * GL_RGB or GL_RGBA
149 * texAddr - destination image address
150 * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
151 * dstXoffset, dstYoffset, dstZoffset - position to store the image within
152 * the destination 3D texture
153 * dstRowStride, dstImageStride - dest image strides in GLchan's
154 * srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
155 * srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
156 * srcPacking - describes packing of incoming image.
157 */
158 void
159 _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
160 GLenum texFormat, GLchan *texAddr,
161 GLint srcWidth, GLint srcHeight, GLint srcDepth,
162 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
163 GLint dstRowStride, GLint dstImageStride,
164 GLenum srcFormat, GLenum srcType,
165 const GLvoid *srcAddr,
166 const struct gl_pixelstore_attrib *srcPacking)
167 {
168 GLint texComponents;
169
170 ASSERT(ctx);
171 ASSERT(dimensions >= 1 && dimensions <= 3);
172 ASSERT(texAddr);
173 ASSERT(srcWidth >= 1);
174 ASSERT(srcHeight >= 1);
175 ASSERT(srcDepth >= 1);
176 ASSERT(dstXoffset >= 0);
177 ASSERT(dstYoffset >= 0);
178 ASSERT(dstZoffset >= 0);
179 ASSERT(dstRowStride >= 0);
180 ASSERT(dstImageStride >= 0);
181 ASSERT(srcAddr);
182 ASSERT(srcPacking);
183
184 texComponents = components_in_intformat(texFormat);
185
186 /* try common 2D texture cases first */
187 if (!ctx->_ImageTransferState && dimensions == 2 && srcType == CHAN_TYPE) {
188
189 if (srcFormat == texFormat) {
190 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
191 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
192 */
193 const GLchan *src = (const GLchan *) _mesa_image_address(
194 srcPacking, srcAddr, srcWidth, srcHeight,
195 srcFormat, srcType, 0, 0, 0);
196 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
197 srcWidth, srcFormat, srcType);
198 const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
199 GLchan *dst = texAddr + dstYoffset * dstRowStride
200 + dstXoffset * texComponents;
201 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
202 MEMCPY(dst, src, srcHeight * widthInBytes);
203 }
204 else {
205 GLint i;
206 for (i = 0; i < srcHeight; i++) {
207 MEMCPY(dst, src, widthInBytes);
208 src += srcRowStride;
209 dst += dstRowStride;
210 }
211 }
212 return; /* all done */
213 }
214 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
215 /* commonly used by Quake */
216 const GLchan *src = (const GLchan *) _mesa_image_address(
217 srcPacking, srcAddr, srcWidth, srcHeight,
218 srcFormat, srcType, 0, 0, 0);
219 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
220 srcWidth, srcFormat, srcType);
221 GLchan *dst = texAddr + dstYoffset * dstRowStride
222 + dstXoffset * texComponents;
223 GLint i, j;
224 for (i = 0; i < srcHeight; i++) {
225 const GLchan *s = src;
226 GLchan *d = dst;
227 for (j = 0; j < srcWidth; j++) {
228 *d++ = *s++; /*red*/
229 *d++ = *s++; /*green*/
230 *d++ = *s++; /*blue*/
231 s++; /*alpha*/
232 }
233 src += srcRowStride;
234 dst += dstRowStride;
235 }
236 return; /* all done */
237 }
238 }
239
240 /*
241 * General case solutions
242 */
243 if (texFormat == GL_COLOR_INDEX) {
244 /* color index texture */
245 const GLenum texType = CHAN_TYPE;
246 GLint img, row;
247 GLchan *dest = texAddr + dstZoffset * dstImageStride
248 + dstYoffset * dstRowStride
249 + dstXoffset * texComponents;
250 for (img = 0; img < srcDepth; img++) {
251 GLchan *destRow = dest;
252 for (row = 0; row < srcHeight; row++) {
253 const GLvoid *src = _mesa_image_address(srcPacking,
254 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
255 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
256 srcType, src, srcPacking,
257 ctx->_ImageTransferState);
258 destRow += dstRowStride;
259 }
260 dest += dstImageStride;
261 }
262 }
263 else if (texFormat == GL_DEPTH_COMPONENT) {
264 /* Depth texture (shadow maps) */
265 GLint img, row;
266 GLfloat *dest = (GLfloat *) texAddr + dstZoffset * dstImageStride
267 + dstYoffset * dstRowStride
268 + dstXoffset * texComponents;
269 for (img = 0; img < srcDepth; img++) {
270 GLfloat *destRow = dest;
271 for (row = 0; row < srcHeight; row++) {
272 const GLvoid *src = _mesa_image_address(srcPacking,
273 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
274 _mesa_unpack_depth_span(ctx, srcWidth, destRow,
275 srcType, src, srcPacking);
276 destRow += dstRowStride;
277 }
278 dest += dstImageStride;
279 }
280 }
281 else {
282 /* regular, color texture */
283 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
284 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
285 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
286 /*
287 * Fill texture image with convolution
288 */
289 GLint img, row;
290 GLint convWidth = srcWidth, convHeight = srcHeight;
291 GLfloat *tmpImage, *convImage;
292 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
293 if (!tmpImage) {
294 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
295 return;
296 }
297 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
298 if (!convImage) {
299 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
300 FREE(tmpImage);
301 return;
302 }
303
304 for (img = 0; img < srcDepth; img++) {
305 const GLfloat *srcf;
306 GLfloat *dstf = tmpImage;
307 GLchan *dest;
308
309 /* unpack and do transfer ops up to convolution */
310 for (row = 0; row < srcHeight; row++) {
311 const GLvoid *src = _mesa_image_address(srcPacking,
312 srcAddr, srcWidth, srcHeight,
313 srcFormat, srcType, img, row, 0);
314 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
315 srcFormat, srcType, src, srcPacking,
316 ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
317 GL_TRUE);
318 dstf += srcWidth * 4;
319 }
320
321 /* convolve */
322 if (dimensions == 1) {
323 ASSERT(ctx->Pixel.Convolution1DEnabled);
324 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
325 }
326 else {
327 if (ctx->Pixel.Convolution2DEnabled) {
328 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
329 tmpImage, convImage);
330 }
331 else {
332 ASSERT(ctx->Pixel.Separable2DEnabled);
333 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
334 tmpImage, convImage);
335 }
336 }
337
338 /* packing and transfer ops after convolution */
339 srcf = convImage;
340 dest = texAddr + (dstZoffset + img) * dstImageStride
341 + dstYoffset * dstRowStride;
342 for (row = 0; row < convHeight; row++) {
343 _mesa_pack_float_rgba_span(ctx, convWidth,
344 (const GLfloat (*)[4]) srcf,
345 texFormat, CHAN_TYPE,
346 dest, &_mesa_native_packing,
347 ctx->_ImageTransferState
348 & IMAGE_POST_CONVOLUTION_BITS);
349 srcf += convWidth * 4;
350 dest += dstRowStride;
351 }
352 }
353
354 FREE(convImage);
355 FREE(tmpImage);
356 }
357 else {
358 /*
359 * no convolution
360 */
361 GLint img, row;
362 GLchan *dest = texAddr + dstZoffset * dstImageStride
363 + dstYoffset * dstRowStride
364 + dstXoffset * texComponents;
365 for (img = 0; img < srcDepth; img++) {
366 GLchan *destRow = dest;
367 for (row = 0; row < srcHeight; row++) {
368 const GLvoid *srcRow = _mesa_image_address(srcPacking,
369 srcAddr, srcWidth, srcHeight,
370 srcFormat, srcType, img, row, 0);
371 _mesa_unpack_chan_color_span(ctx, srcWidth, texFormat, destRow,
372 srcFormat, srcType, srcRow, srcPacking,
373 ctx->_ImageTransferState);
374 destRow += dstRowStride;
375 }
376 dest += dstImageStride;
377 }
378 }
379 }
380 }
381
382
383
384 /*
385 * This is the software fallback for Driver.TexImage1D().
386 * The texture image type will be GLchan.
387 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
388 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
389 *
390 */
391 void
392 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
393 GLint internalFormat,
394 GLint width, GLint border,
395 GLenum format, GLenum type, const GLvoid *pixels,
396 const struct gl_pixelstore_attrib *packing,
397 struct gl_texture_object *texObj,
398 struct gl_texture_image *texImage)
399 {
400 GLint postConvWidth = width;
401
402 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
403 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
404 }
405
406 /* setup the teximage struct's fields */
407 _mesa_init_tex_format( ctx, internalFormat, texImage );
408 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
409
410 /* allocate memory */
411 texImage->Data = (GLchan *) MALLOC(postConvWidth *
412 texImage->TexFormat->TexelBytes);
413 if (!texImage->Data)
414 return; /* out of memory */
415
416 /* unpack image, apply transfer ops and store in texImage->Data */
417 _mesa_transfer_teximage(ctx, 1, texImage->Format, (GLchan *) texImage->Data,
418 width, 1, 1, 0, 0, 0,
419 0, /* dstRowStride */
420 0, /* dstImageStride */
421 format, type, pixels, packing);
422 }
423
424
425 /*
426 * This is the software fallback for Driver.TexImage2D().
427 * The texture image type will be GLchan.
428 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
429 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
430 *
431 */
432 void
433 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
434 GLint internalFormat,
435 GLint width, GLint height, GLint border,
436 GLenum format, GLenum type, const void *pixels,
437 const struct gl_pixelstore_attrib *packing,
438 struct gl_texture_object *texObj,
439 struct gl_texture_image *texImage)
440 {
441 GLint postConvWidth = width, postConvHeight = height;
442 GLint texelBytes;
443
444 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
445 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
446 &postConvHeight);
447 }
448
449 /* setup the teximage struct's fields */
450 _mesa_init_tex_format( ctx, internalFormat, texImage );
451 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
452
453 texelBytes = texImage->TexFormat->TexelBytes;
454
455 /* allocate memory */
456 texImage->Data = (GLchan *) MALLOC(postConvWidth * postConvHeight *
457 texelBytes);
458 if (!texImage->Data)
459 return; /* out of memory */
460
461 /* unpack image, apply transfer ops and store in texImage->Data */
462 _mesa_transfer_teximage(ctx, 2, texImage->Format, (GLchan *) texImage->Data,
463 width, height, 1, 0, 0, 0,
464 texImage->Width * texelBytes,
465 0, /* dstImageStride */
466 format, type, pixels, packing);
467 }
468
469
470
471 /*
472 * This is the software fallback for Driver.TexImage3D().
473 * The texture image type will be GLchan.
474 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
475 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
476 *
477 */
478 void
479 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
480 GLint internalFormat,
481 GLint width, GLint height, GLint depth, GLint border,
482 GLenum format, GLenum type, const void *pixels,
483 const struct gl_pixelstore_attrib *packing,
484 struct gl_texture_object *texObj,
485 struct gl_texture_image *texImage)
486 {
487 GLint texelBytes;
488
489 /* setup the teximage struct's fields */
490 _mesa_init_tex_format( ctx, internalFormat, texImage );
491 texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
492
493 texelBytes = texImage->TexFormat->TexelBytes;
494
495 /* allocate memory */
496 texImage->Data = (GLchan *) MALLOC(width * height * depth * texelBytes);
497 if (!texImage->Data)
498 return; /* out of memory */
499
500 /* unpack image, apply transfer ops and store in texImage->Data */
501 _mesa_transfer_teximage(ctx, 3, texImage->Format, (GLchan *) texImage->Data,
502 width, height, depth, 0, 0, 0,
503 texImage->Width * texelBytes,
504 texImage->Width * texImage->Height * texelBytes,
505 format, type, pixels, packing);
506 }
507
508
509
510
511 /*
512 * This is the software fallback for Driver.TexSubImage1D().
513 */
514 void
515 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
516 GLint xoffset, GLint width,
517 GLenum format, GLenum type, const void *pixels,
518 const struct gl_pixelstore_attrib *packing,
519 struct gl_texture_object *texObj,
520 struct gl_texture_image *texImage)
521 {
522 _mesa_transfer_teximage(ctx, 1, texImage->Format, (GLchan *) texImage->Data,
523 width, 1, 1, /* src size */
524 xoffset, 0, 0, /* dest offsets */
525 0, /* dstRowStride */
526 0, /* dstImageStride */
527 format, type, pixels, packing);
528 }
529
530
531 /*
532 * This is the software fallback for Driver.TexSubImage2D().
533 */
534 void
535 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
536 GLint xoffset, GLint yoffset,
537 GLint width, GLint height,
538 GLenum format, GLenum type, const void *pixels,
539 const struct gl_pixelstore_attrib *packing,
540 struct gl_texture_object *texObj,
541 struct gl_texture_image *texImage)
542 {
543 const GLint components = components_in_intformat(texImage->IntFormat);
544 const GLint compSize = _mesa_sizeof_type(texImage->Type);
545 _mesa_transfer_teximage(ctx, 2, texImage->Format, (GLchan *) texImage->Data,
546 width, height, 1, /* src size */
547 xoffset, yoffset, 0, /* dest offsets */
548 texImage->Width * components * compSize,
549 0, /* dstImageStride */
550 format, type, pixels, packing);
551 }
552
553
554 /*
555 * This is the software fallback for Driver.TexSubImage3D().
556 */
557 void
558 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
559 GLint xoffset, GLint yoffset, GLint zoffset,
560 GLint width, GLint height, GLint depth,
561 GLenum format, GLenum type, const void *pixels,
562 const struct gl_pixelstore_attrib *packing,
563 struct gl_texture_object *texObj,
564 struct gl_texture_image *texImage)
565 {
566 const GLint components = components_in_intformat(texImage->IntFormat);
567 const GLint compSize = _mesa_sizeof_type(texImage->Type);
568 _mesa_transfer_teximage(ctx, 3, texImage->Format, (GLchan *) texImage->Data,
569 width, height, depth, /* src size */
570 xoffset, yoffset, xoffset, /* dest offsets */
571 texImage->Width * components * compSize,
572 texImage->Width * texImage->Height * components
573 * compSize,
574 format, type, pixels, packing);
575 }
576
577
578
579
580 /*
581 * Read an RGBA image from the frame buffer.
582 * This is used by glCopyTex[Sub]Image[12]D().
583 * Input: ctx - the context
584 * x, y - lower left corner
585 * width, height - size of region to read
586 * Return: pointer to block of GL_RGBA, GLchan data.
587 */
588 static GLchan *
589 read_color_image( GLcontext *ctx, GLint x, GLint y,
590 GLsizei width, GLsizei height )
591 {
592 GLint stride, i;
593 GLchan *image, *dst;
594
595 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
596 if (!image)
597 return NULL;
598
599 /* Select buffer to read from */
600 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
601 ctx->Pixel.DriverReadBuffer );
602
603 RENDER_START(ctx);
604
605 dst = image;
606 stride = width * 4;
607 for (i = 0; i < height; i++) {
608 _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
609 (GLchan (*)[4]) dst );
610 dst += stride;
611 }
612
613 RENDER_FINISH(ctx);
614
615 /* Read from draw buffer (the default) */
616 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
617 ctx->Color.DriverDrawBuffer );
618
619 return image;
620 }
621
622
623 /*
624 * As above, but read data from depth buffer.
625 */
626 static GLfloat *
627 read_depth_image( GLcontext *ctx, GLint x, GLint y,
628 GLsizei width, GLsizei height )
629 {
630 GLint i;
631 GLfloat *image, *dst;
632
633 image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
634 if (!image)
635 return NULL;
636
637 RENDER_START(ctx);
638
639 dst = image;
640 for (i = 0; i < height; i++) {
641 _mesa_read_depth_span_float(ctx, width, x, y + i, dst);
642 dst += width;
643 }
644
645 RENDER_FINISH(ctx);
646
647 return image;
648 }
649
650
651
652 static GLboolean
653 is_depth_format(GLenum format)
654 {
655 switch (format) {
656 case GL_DEPTH_COMPONENT:
657 case GL_DEPTH_COMPONENT16_SGIX:
658 case GL_DEPTH_COMPONENT24_SGIX:
659 case GL_DEPTH_COMPONENT32_SGIX:
660 return GL_TRUE;
661 default:
662 return GL_FALSE;
663 }
664 }
665
666
667 /*
668 * Fallback for Driver.CopyTexImage1D().
669 */
670 void
671 _mesa_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
672 GLenum internalFormat,
673 GLint x, GLint y, GLsizei width, GLint border )
674 {
675 struct gl_texture_unit *texUnit;
676 struct gl_texture_object *texObj;
677 struct gl_texture_image *texImage;
678
679 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
680 texObj = _mesa_select_tex_object(ctx, texUnit, target);
681 ASSERT(texObj);
682 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
683 ASSERT(texImage);
684
685 ASSERT(ctx->Driver.TexImage1D);
686
687 if (is_depth_format(internalFormat)) {
688 /* read depth image from framebuffer */
689 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
690 if (!image) {
691 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
692 return;
693 }
694
695 /* call glTexImage1D to redefine the texture */
696 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
697 width, border,
698 GL_DEPTH_COMPONENT, GL_FLOAT, image,
699 &_mesa_native_packing, texObj, texImage);
700 FREE(image);
701 }
702 else {
703 /* read RGBA image from framebuffer */
704 GLchan *image = read_color_image(ctx, x, y, width, 1);
705 if (!image) {
706 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
707 return;
708 }
709
710 /* call glTexImage1D to redefine the texture */
711 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
712 width, border,
713 GL_RGBA, CHAN_TYPE, image,
714 &_mesa_native_packing, texObj, texImage);
715 FREE(image);
716 }
717 }
718
719
720 /*
721 * Fallback for Driver.CopyTexImage2D().
722 */
723 void
724 _mesa_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
725 GLenum internalFormat,
726 GLint x, GLint y, GLsizei width, GLsizei height,
727 GLint border )
728 {
729 struct gl_texture_unit *texUnit;
730 struct gl_texture_object *texObj;
731 struct gl_texture_image *texImage;
732
733 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
734 texObj = _mesa_select_tex_object(ctx, texUnit, target);
735 ASSERT(texObj);
736 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
737 ASSERT(texImage);
738
739 ASSERT(ctx->Driver.TexImage2D);
740
741 if (is_depth_format(internalFormat)) {
742 /* read depth image from framebuffer */
743 GLfloat *image = read_depth_image(ctx, x, y, width, height);
744 if (!image) {
745 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
746 return;
747 }
748
749 /* call glTexImage2D to redefine the texture */
750 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
751 width, height, border,
752 GL_DEPTH_COMPONENT, GL_FLOAT, image,
753 &_mesa_native_packing, texObj, texImage);
754 FREE(image);
755 }
756 else {
757 /* read RGBA image from framebuffer */
758 GLchan *image = read_color_image(ctx, x, y, width, height);
759 if (!image) {
760 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
761 return;
762 }
763
764 /* call glTexImage2D to redefine the texture */
765 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
766 width, height, border,
767 GL_RGBA, CHAN_TYPE, image,
768 &_mesa_native_packing, texObj, texImage);
769 FREE(image);
770 }
771 }
772
773
774 /*
775 * Fallback for Driver.CopyTexSubImage1D().
776 */
777 void
778 _mesa_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
779 GLint xoffset, GLint x, GLint y, GLsizei width)
780 {
781 struct gl_texture_unit *texUnit;
782 struct gl_texture_object *texObj;
783 struct gl_texture_image *texImage;
784
785 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
786 texObj = _mesa_select_tex_object(ctx, texUnit, target);
787 ASSERT(texObj);
788 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
789 ASSERT(texImage);
790
791 ASSERT(ctx->Driver.TexImage1D);
792
793 if (is_depth_format(texImage->IntFormat)) {
794 /* read depth image from framebuffer */
795 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
796 if (!image) {
797 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
798 return;
799 }
800
801 /* call glTexImage1D to redefine the texture */
802 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
803 GL_DEPTH_COMPONENT, GL_FLOAT, image,
804 &_mesa_native_packing, texObj, texImage);
805 FREE(image);
806 }
807 else {
808 GLchan *image = read_color_image(ctx, x, y, width, 1);
809 if (!image) {
810 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
811 return;
812 }
813
814 /* now call glTexSubImage1D to do the real work */
815 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
816 GL_RGBA, CHAN_TYPE, image,
817 &_mesa_native_packing, texObj, texImage);
818 FREE(image);
819 }
820 }
821
822
823 /*
824 * Fallback for Driver.CopyTexSubImage2D().
825 */
826 void
827 _mesa_copy_texsubimage2d( GLcontext *ctx,
828 GLenum target, GLint level,
829 GLint xoffset, GLint yoffset,
830 GLint x, GLint y, GLsizei width, GLsizei height )
831 {
832 struct gl_texture_unit *texUnit;
833 struct gl_texture_object *texObj;
834 struct gl_texture_image *texImage;
835
836 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
837 texObj = _mesa_select_tex_object(ctx, texUnit, target);
838 ASSERT(texObj);
839 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
840 ASSERT(texImage);
841
842 ASSERT(ctx->Driver.TexImage2D);
843
844 if (is_depth_format(texImage->IntFormat)) {
845 /* read depth image from framebuffer */
846 GLfloat *image = read_depth_image(ctx, x, y, width, height);
847 if (!image) {
848 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
849 return;
850 }
851
852 /* call glTexImage1D to redefine the texture */
853 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
854 xoffset, yoffset, width, height,
855 GL_DEPTH_COMPONENT, GL_FLOAT, image,
856 &_mesa_native_packing, texObj, texImage);
857 FREE(image);
858 }
859 else {
860 /* read RGBA image from framebuffer */
861 GLchan *image = read_color_image(ctx, x, y, width, height);
862 if (!image) {
863 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
864 return;
865 }
866
867 /* now call glTexSubImage2D to do the real work */
868 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
869 xoffset, yoffset, width, height,
870 GL_RGBA, CHAN_TYPE, image,
871 &_mesa_native_packing, texObj, texImage);
872 FREE(image);
873 }
874 }
875
876
877 /*
878 * Fallback for Driver.CopyTexSubImage3D().
879 */
880 void
881 _mesa_copy_texsubimage3d( GLcontext *ctx,
882 GLenum target, GLint level,
883 GLint xoffset, GLint yoffset, GLint zoffset,
884 GLint x, GLint y, GLsizei width, GLsizei height )
885 {
886 struct gl_texture_unit *texUnit;
887 struct gl_texture_object *texObj;
888 struct gl_texture_image *texImage;
889
890 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
891 texObj = _mesa_select_tex_object(ctx, texUnit, target);
892 ASSERT(texObj);
893 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
894 ASSERT(texImage);
895
896 ASSERT(ctx->Driver.TexImage3D);
897
898 if (is_depth_format(texImage->IntFormat)) {
899 /* read depth image from framebuffer */
900 GLfloat *image = read_depth_image(ctx, x, y, width, height);
901 if (!image) {
902 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
903 return;
904 }
905
906 /* call glTexImage1D to redefine the texture */
907 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
908 xoffset, yoffset, zoffset, width, height, 1,
909 GL_DEPTH_COMPONENT, GL_FLOAT, image,
910 &_mesa_native_packing, texObj, texImage);
911 FREE(image);
912 }
913 else {
914 /* read RGBA image from framebuffer */
915 GLchan *image = read_color_image(ctx, x, y, width, height);
916 if (!image) {
917 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
918 return;
919 }
920
921 /* now call glTexSubImage3D to do the real work */
922 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
923 xoffset, yoffset, zoffset, width, height, 1,
924 GL_RGBA, CHAN_TYPE, image,
925 &_mesa_native_packing, texObj, texImage);
926 FREE(image);
927 }
928 }
929
930
931
932 /*
933 * Fallback for Driver.CompressedTexImage1D()
934 */
935 void
936 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
937 GLint internalFormat,
938 GLint width, GLint border,
939 GLsizei imageSize, const GLvoid *data,
940 struct gl_texture_object *texObj,
941 struct gl_texture_image *texImage)
942 {
943 /* Nothing here.
944 * The device driver has to do it all.
945 */
946 }
947
948
949
950 /*
951 * Fallback for Driver.CompressedTexImage2D()
952 */
953 void
954 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
955 GLint internalFormat,
956 GLint width, GLint height, GLint border,
957 GLsizei imageSize, const GLvoid *data,
958 struct gl_texture_object *texObj,
959 struct gl_texture_image *texImage)
960 {
961 /* Nothing here.
962 * The device driver has to do it all.
963 */
964 }
965
966
967
968 /*
969 * Fallback for Driver.CompressedTexImage3D()
970 */
971 void
972 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
973 GLint internalFormat,
974 GLint width, GLint height, GLint depth,
975 GLint border,
976 GLsizei imageSize, const GLvoid *data,
977 struct gl_texture_object *texObj,
978 struct gl_texture_image *texImage)
979 {
980 /* Nothing here.
981 * The device driver has to do it all.
982 */
983 }
984
985
986
987
988
989
990 /*
991 * This is the fallback for Driver.TestProxyTexImage().
992 */
993 GLboolean
994 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
995 GLint internalFormat, GLenum format, GLenum type,
996 GLint width, GLint height, GLint depth, GLint border)
997 {
998 struct gl_texture_unit *texUnit;
999 struct gl_texture_object *texObj;
1000 struct gl_texture_image *texImage;
1001
1002 (void) format;
1003 (void) type;
1004
1005 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1006 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1007 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1008
1009 /* We always pass.
1010 * The core Mesa code will have already tested the image size, etc.
1011 * Drivers may have more stringent texture limits to enforce and will
1012 * have to override this function.
1013 */
1014 /* setup the teximage struct's fields */
1015 _mesa_init_tex_format( ctx, internalFormat, texImage );
1016
1017 return GL_TRUE;
1018 }