81453e34f4f642b0afa329b7d4e18b2e036457dd
[mesa.git] / src / mesa / main / texstore.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
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 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
34 * texture image data.
35 *
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
38 * code:
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
42 * etc...
43 *
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
46 * pixel unpacking
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
48 *
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
51 */
52
53
54 #include "glheader.h"
55 #include "bufferobj.h"
56 #include "colormac.h"
57 #include "context.h"
58 #include "convolve.h"
59 #include "image.h"
60 #include "macros.h"
61 #include "imports.h"
62 #include "texcompress.h"
63 #include "texformat.h"
64 #include "teximage.h"
65 #include "texstore.h"
66
67
68 static const GLint ZERO = 4, ONE = 5;
69
70 static GLboolean can_swizzle(GLenum logicalBaseFormat)
71 {
72 switch (logicalBaseFormat) {
73 case GL_RGBA:
74 case GL_RGB:
75 case GL_LUMINANCE_ALPHA:
76 case GL_INTENSITY:
77 case GL_ALPHA:
78 case GL_LUMINANCE:
79 return GL_TRUE;
80 default:
81 return GL_FALSE;
82 }
83 }
84
85
86 /**
87 * When promoting texture formats (see below) we need to compute the
88 * mapping of dest components back to source components.
89 * This function does that.
90 * \param logicalBaseFormat the logical format of the texture
91 * \param textureBaseFormat the final texture format
92 * \return map[4] the four mapping values
93 */
94 static void
95 compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
96 GLubyte map[6])
97 {
98 map[ZERO] = ZERO;
99 map[ONE] = ONE;
100
101 /* compute mapping from dest components back to src components */
102 switch (textureBaseFormat) {
103 case GL_RGB:
104 case GL_RGBA:
105 switch (logicalBaseFormat) {
106 case GL_LUMINANCE:
107 map[0] = map[1] = map[2] = 0;
108 if (textureBaseFormat == GL_RGBA)
109 map[3] = ONE;
110 break;
111 case GL_ALPHA:
112 ASSERT(textureBaseFormat == GL_RGBA);
113 map[0] = map[1] = map[2] = ZERO;
114 map[3] = 0;
115 break;
116 case GL_INTENSITY:
117 map[0] = map[1] = map[2] = 0;
118 if (textureBaseFormat == GL_RGBA)
119 map[3] = 0;
120 break;
121 case GL_LUMINANCE_ALPHA:
122 ASSERT(textureBaseFormat == GL_RGBA);
123 map[0] = map[1] = map[2] = 0;
124 map[3] = 1;
125 break;
126 case GL_RGB:
127 ASSERT(textureBaseFormat == GL_RGBA);
128 map[0] = 0;
129 map[1] = 1;
130 map[2] = 2;
131 map[3] = ONE;
132 break;
133 case GL_RGBA:
134 ASSERT(textureBaseFormat == GL_RGBA);
135 map[0] = 0;
136 map[1] = 1;
137 map[2] = 2;
138 map[3] = 3;
139 break;
140 default:
141 _mesa_problem(NULL, "Unexpected logicalBaseFormat");
142 map[0] = map[1] = map[2] = map[3] = 0;
143 }
144 break;
145 case GL_LUMINANCE_ALPHA:
146 switch (logicalBaseFormat) {
147 case GL_LUMINANCE:
148 map[0] = 0;
149 map[1] = ONE;
150 break;
151 case GL_ALPHA:
152 map[0] = ZERO;
153 map[1] = 0;
154 break;
155 case GL_INTENSITY:
156 map[0] = 0;
157 map[1] = 0;
158 break;
159 default:
160 _mesa_problem(NULL, "Unexpected logicalBaseFormat");
161 map[0] = map[1] = 0;
162 }
163 break;
164 default:
165 _mesa_problem(NULL, "Unexpected logicalBaseFormat");
166 map[0] = map[1] = 0;
167 break;
168 }
169 }
170
171
172 /**
173 * Make a temporary (color) texture image with GLfloat components.
174 * Apply all needed pixel unpacking and pixel transfer operations.
175 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
176 * Suppose the user specifies GL_LUMINANCE as the internal texture format
177 * but the graphics hardware doesn't support luminance textures. So, might
178 * use an RGB hardware format instead.
179 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
180 *
181 * \param ctx the rendering context
182 * \param dims image dimensions: 1, 2 or 3
183 * \param logicalBaseFormat basic texture derived from the user's
184 * internal texture format value
185 * \param textureBaseFormat the actual basic format of the texture
186 * \param srcWidth source image width
187 * \param srcHeight source image height
188 * \param srcDepth source image depth
189 * \param srcFormat source image format
190 * \param srcType source image type
191 * \param srcAddr source image address
192 * \param srcPacking source image pixel packing
193 * \return resulting image with format = textureBaseFormat and type = GLfloat.
194 */
195 static GLfloat *
196 make_temp_float_image(GLcontext *ctx, GLuint dims,
197 GLenum logicalBaseFormat,
198 GLenum textureBaseFormat,
199 GLint srcWidth, GLint srcHeight, GLint srcDepth,
200 GLenum srcFormat, GLenum srcType,
201 const GLvoid *srcAddr,
202 const struct gl_pixelstore_attrib *srcPacking)
203 {
204 GLuint transferOps = ctx->_ImageTransferState;
205 GLfloat *tempImage;
206
207 ASSERT(dims >= 1 && dims <= 3);
208
209 ASSERT(logicalBaseFormat == GL_RGBA ||
210 logicalBaseFormat == GL_RGB ||
211 logicalBaseFormat == GL_LUMINANCE_ALPHA ||
212 logicalBaseFormat == GL_LUMINANCE ||
213 logicalBaseFormat == GL_ALPHA ||
214 logicalBaseFormat == GL_INTENSITY ||
215 logicalBaseFormat == GL_COLOR_INDEX ||
216 logicalBaseFormat == GL_DEPTH_COMPONENT);
217
218 ASSERT(textureBaseFormat == GL_RGBA ||
219 textureBaseFormat == GL_RGB ||
220 textureBaseFormat == GL_LUMINANCE_ALPHA ||
221 textureBaseFormat == GL_LUMINANCE ||
222 textureBaseFormat == GL_ALPHA ||
223 textureBaseFormat == GL_INTENSITY ||
224 textureBaseFormat == GL_COLOR_INDEX ||
225 textureBaseFormat == GL_DEPTH_COMPONENT);
226
227 /* conventional color image */
228
229 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
230 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
231 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
232 /* need image convolution */
233 const GLuint preConvTransferOps
234 = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
235 const GLuint postConvTransferOps
236 = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
237 GLint img, row;
238 GLint convWidth, convHeight;
239 GLfloat *convImage;
240
241 /* pre-convolution image buffer (3D) */
242 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
243 * 4 * sizeof(GLfloat));
244 if (!tempImage)
245 return NULL;
246
247 /* post-convolution image buffer (2D) */
248 convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight
249 * 4 * sizeof(GLfloat));
250 if (!convImage) {
251 _mesa_free(tempImage);
252 return NULL;
253 }
254
255 /* loop over 3D image slices */
256 for (img = 0; img < srcDepth; img++) {
257 GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4);
258
259 /* unpack and do transfer ops up to convolution */
260 for (row = 0; row < srcHeight; row++) {
261 const GLvoid *src = _mesa_image_address(dims, srcPacking,
262 srcAddr, srcWidth, srcHeight,
263 srcFormat, srcType, img, row, 0);
264 _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
265 srcFormat, srcType, src,
266 srcPacking,
267 preConvTransferOps);
268 dst += srcWidth * 4;
269 }
270
271 /* do convolution */
272 {
273 GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
274 convWidth = srcWidth;
275 convHeight = srcHeight;
276 if (dims == 1) {
277 ASSERT(ctx->Pixel.Convolution1DEnabled);
278 _mesa_convolve_1d_image(ctx, &convWidth, src, convImage);
279 }
280 else {
281 if (ctx->Pixel.Convolution2DEnabled) {
282 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
283 src, convImage);
284 }
285 else {
286 ASSERT(ctx->Pixel.Separable2DEnabled);
287 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
288 src, convImage);
289 }
290 }
291 }
292
293 /* do post-convolution transfer and pack into tempImage */
294 {
295 const GLint logComponents
296 = _mesa_components_in_format(logicalBaseFormat);
297 const GLfloat *src = convImage;
298 GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
299 for (row = 0; row < convHeight; row++) {
300 _mesa_pack_rgba_span_float(ctx, convWidth,
301 (const GLfloat (*)[4]) src,
302 logicalBaseFormat, GL_FLOAT,
303 dst, &ctx->DefaultPacking,
304 postConvTransferOps);
305 src += convWidth * 4;
306 dst += convWidth * logComponents;
307 }
308 }
309 } /* loop over 3D image slices */
310
311 _mesa_free(convImage);
312
313 /* might need these below */
314 srcWidth = convWidth;
315 srcHeight = convHeight;
316 }
317 else {
318 /* no convolution */
319 const GLint components = _mesa_components_in_format(logicalBaseFormat);
320 const GLint srcStride = _mesa_image_row_stride(srcPacking,
321 srcWidth, srcFormat, srcType);
322 GLfloat *dst;
323 GLint img, row;
324
325 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
326 * components * sizeof(GLfloat));
327 if (!tempImage)
328 return NULL;
329
330 dst = tempImage;
331 for (img = 0; img < srcDepth; img++) {
332 const GLubyte *src
333 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
334 srcWidth, srcHeight,
335 srcFormat, srcType,
336 img, 0, 0);
337 for (row = 0; row < srcHeight; row++) {
338 _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
339 dst, srcFormat, srcType, src,
340 srcPacking, transferOps);
341 dst += srcWidth * components;
342 src += srcStride;
343 }
344 }
345 }
346
347 if (logicalBaseFormat != textureBaseFormat) {
348 /* more work */
349 GLint texComponents = _mesa_components_in_format(textureBaseFormat);
350 GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
351 GLfloat *newImage;
352 GLint i, n;
353 GLubyte map[6];
354
355 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
356 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
357 textureBaseFormat == GL_LUMINANCE_ALPHA);
358
359 /* The actual texture format should have at least as many components
360 * as the logical texture format.
361 */
362 ASSERT(texComponents >= logComponents);
363
364 newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
365 * texComponents * sizeof(GLfloat));
366 if (!newImage) {
367 _mesa_free(tempImage);
368 return NULL;
369 }
370
371 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
372
373 n = srcWidth * srcHeight * srcDepth;
374 for (i = 0; i < n; i++) {
375 GLint k;
376 for (k = 0; k < texComponents; k++) {
377 GLint j = map[k];
378 if (j == ZERO)
379 newImage[i * texComponents + k] = 0.0F;
380 else if (j == ONE)
381 newImage[i * texComponents + k] = 1.0F;
382 else
383 newImage[i * texComponents + k] = tempImage[i * logComponents + j];
384 }
385 }
386
387 _mesa_free(tempImage);
388 tempImage = newImage;
389 }
390
391 return tempImage;
392 }
393
394
395 /**
396 * Make a temporary (color) texture image with GLchan components.
397 * Apply all needed pixel unpacking and pixel transfer operations.
398 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
399 * Suppose the user specifies GL_LUMINANCE as the internal texture format
400 * but the graphics hardware doesn't support luminance textures. So, might
401 * use an RGB hardware format instead.
402 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
403 *
404 * \param ctx the rendering context
405 * \param dims image dimensions: 1, 2 or 3
406 * \param logicalBaseFormat basic texture derived from the user's
407 * internal texture format value
408 * \param textureBaseFormat the actual basic format of the texture
409 * \param srcWidth source image width
410 * \param srcHeight source image height
411 * \param srcDepth source image depth
412 * \param srcFormat source image format
413 * \param srcType source image type
414 * \param srcAddr source image address
415 * \param srcPacking source image pixel packing
416 * \return resulting image with format = textureBaseFormat and type = GLchan.
417 */
418 GLchan *
419 _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
420 GLenum logicalBaseFormat,
421 GLenum textureBaseFormat,
422 GLint srcWidth, GLint srcHeight, GLint srcDepth,
423 GLenum srcFormat, GLenum srcType,
424 const GLvoid *srcAddr,
425 const struct gl_pixelstore_attrib *srcPacking)
426 {
427 GLuint transferOps = ctx->_ImageTransferState;
428 const GLint components = _mesa_components_in_format(logicalBaseFormat);
429 GLboolean freeSrcImage = GL_FALSE;
430 GLint img, row;
431 GLchan *tempImage, *dst;
432
433 ASSERT(dims >= 1 && dims <= 3);
434
435 ASSERT(logicalBaseFormat == GL_RGBA ||
436 logicalBaseFormat == GL_RGB ||
437 logicalBaseFormat == GL_LUMINANCE_ALPHA ||
438 logicalBaseFormat == GL_LUMINANCE ||
439 logicalBaseFormat == GL_ALPHA ||
440 logicalBaseFormat == GL_INTENSITY);
441
442 ASSERT(textureBaseFormat == GL_RGBA ||
443 textureBaseFormat == GL_RGB ||
444 textureBaseFormat == GL_LUMINANCE_ALPHA ||
445 textureBaseFormat == GL_LUMINANCE ||
446 textureBaseFormat == GL_ALPHA ||
447 textureBaseFormat == GL_INTENSITY);
448
449 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
450 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
451 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
452 /* get convolved image */
453 GLfloat *convImage = make_temp_float_image(ctx, dims,
454 logicalBaseFormat,
455 logicalBaseFormat,
456 srcWidth, srcHeight, srcDepth,
457 srcFormat, srcType,
458 srcAddr, srcPacking);
459 if (!convImage)
460 return NULL;
461 /* the convolved image is our new source image */
462 srcAddr = convImage;
463 srcFormat = logicalBaseFormat;
464 srcType = GL_FLOAT;
465 srcPacking = &ctx->DefaultPacking;
466 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
467 transferOps = 0;
468 freeSrcImage = GL_TRUE;
469 }
470
471 /* unpack and transfer the source image */
472 tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
473 * components * sizeof(GLchan));
474 if (!tempImage)
475 return NULL;
476
477 dst = tempImage;
478 for (img = 0; img < srcDepth; img++) {
479 const GLint srcStride = _mesa_image_row_stride(srcPacking,
480 srcWidth, srcFormat,
481 srcType);
482 const GLubyte *src
483 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
484 srcWidth, srcHeight,
485 srcFormat, srcType,
486 img, 0, 0);
487 for (row = 0; row < srcHeight; row++) {
488 _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
489 srcFormat, srcType, src, srcPacking,
490 transferOps);
491 dst += srcWidth * components;
492 src += srcStride;
493 }
494 }
495
496 /* If we made a temporary image for convolution, free it here */
497 if (freeSrcImage) {
498 _mesa_free((void *) srcAddr);
499 }
500
501 if (logicalBaseFormat != textureBaseFormat) {
502 /* one more conversion step */
503 GLint texComponents = _mesa_components_in_format(textureBaseFormat);
504 GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
505 GLchan *newImage;
506 GLint i, n;
507 GLubyte map[6];
508
509 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
510 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
511 textureBaseFormat == GL_LUMINANCE_ALPHA);
512
513 /* The actual texture format should have at least as many components
514 * as the logical texture format.
515 */
516 ASSERT(texComponents >= logComponents);
517
518 newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
519 * texComponents * sizeof(GLchan));
520 if (!newImage) {
521 _mesa_free(tempImage);
522 return NULL;
523 }
524
525 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
526
527 n = srcWidth * srcHeight * srcDepth;
528 for (i = 0; i < n; i++) {
529 GLint k;
530 for (k = 0; k < texComponents; k++) {
531 GLint j = map[k];
532 if (j == ZERO)
533 newImage[i * texComponents + k] = 0;
534 else if (j == ONE)
535 newImage[i * texComponents + k] = CHAN_MAX;
536 else
537 newImage[i * texComponents + k] = tempImage[i * logComponents + j];
538 }
539 }
540
541 _mesa_free(tempImage);
542 tempImage = newImage;
543 }
544
545 return tempImage;
546 }
547
548
549 /**
550 * Copy GLubyte pixels from <src> to <dst> with swizzling.
551 * \param dst destination pixels
552 * \param dstComponents number of color components in destination pixels
553 * \param src source pixels
554 * \param srcComponents number of color components in source pixels
555 * \param map the swizzle mapping
556 * \param count number of pixels to copy/swizzle.
557 */
558 static void
559 swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
560 GLuint srcComponents, const GLubyte *map, GLuint count)
561 {
562 GLubyte tmp[8];
563 GLint i;
564
565 tmp[ZERO] = 0x0;
566 tmp[ONE] = 0xff;
567
568 switch (dstComponents) {
569 case 4:
570 for (i = 0; i < count; i++) {
571 COPY_4UBV(tmp, src);
572 src += srcComponents;
573 dst[0] = tmp[map[0]];
574 dst[1] = tmp[map[1]];
575 dst[2] = tmp[map[2]];
576 dst[3] = tmp[map[3]];
577 dst += 4;
578 }
579 break;
580 case 3:
581 for (i = 0; i < count; i++) {
582 COPY_4UBV(tmp, src);
583 src += srcComponents;
584 dst[0] = tmp[map[0]];
585 dst[1] = tmp[map[1]];
586 dst[2] = tmp[map[2]];
587 dst += 3;
588 }
589 break;
590 case 2:
591 for (i = 0; i < count; i++) {
592 COPY_4UBV(tmp, src);
593 src += srcComponents;
594 dst[0] = tmp[map[0]];
595 dst[1] = tmp[map[1]];
596 dst += 2;
597 }
598 break;
599 }
600 }
601
602
603 /**
604 * Transfer a GLubyte texture image with component swizzling.
605 */
606 static void
607 _mesa_swizzle_ubyte_image(GLcontext *ctx,
608 GLuint dimensions,
609 GLenum srcFormat,
610 const GLubyte *dstmap, GLint dstComponents,
611
612 GLvoid *dstAddr,
613 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
614 GLint dstRowStride, GLint dstImageStride,
615
616 GLint srcWidth, GLint srcHeight, GLint srcDepth,
617 const GLvoid *srcAddr,
618 const struct gl_pixelstore_attrib *srcPacking )
619 {
620 GLint srcComponents = _mesa_components_in_format(srcFormat);
621 GLubyte srcmap[6], map[4];
622 GLint i;
623
624 const GLint srcRowStride =
625 _mesa_image_row_stride(srcPacking, srcWidth,
626 srcFormat, GL_UNSIGNED_BYTE);
627 const GLint srcImageStride
628 = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat,
629 GL_UNSIGNED_BYTE);
630 const GLubyte *srcImage
631 = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr,
632 srcWidth, srcHeight, srcFormat,
633 GL_UNSIGNED_BYTE, 0, 0, 0);
634
635 GLubyte *dstImage = (GLubyte *) dstAddr
636 + dstZoffset * dstImageStride
637 + dstYoffset * dstRowStride
638 + dstXoffset * dstComponents;
639
640 compute_component_mapping(srcFormat, GL_RGBA, srcmap);
641
642 for (i = 0; i < 4; i++)
643 map[i] = srcmap[dstmap[i]];
644
645 if (srcRowStride == srcWidth * srcComponents &&
646 (srcImageStride == srcWidth * srcHeight * srcComponents ||
647 srcDepth == 1)) {
648 swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
649 srcWidth * srcHeight * srcDepth);
650 }
651 else {
652 GLint img, row;
653 for (img = 0; img < srcDepth; img++) {
654 const GLubyte *srcRow = srcImage;
655 GLubyte *dstRow = dstImage;
656 for (row = 0; row < srcHeight; row++) {
657 swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
658 dstRow += dstRowStride;
659 srcRow += srcRowStride;
660 }
661 srcImage += srcImageStride;
662 dstImage += dstImageStride;
663 }
664 }
665 }
666
667
668 /**
669 * Teximage storage routine for when a simple memcpy will do.
670 * No pixel transfer operations or special texel encodings allowed.
671 * 1D, 2D and 3D images supported.
672 */
673 static void
674 memcpy_texture(GLcontext *ctx,
675 GLuint dimensions,
676 const struct gl_texture_format *dstFormat,
677 GLvoid *dstAddr,
678 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
679 GLint dstRowStride, GLint dstImageStride,
680 GLint srcWidth, GLint srcHeight, GLint srcDepth,
681 GLenum srcFormat, GLenum srcType,
682 const GLvoid *srcAddr,
683 const struct gl_pixelstore_attrib *srcPacking)
684 {
685 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
686 srcFormat, srcType);
687 const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
688 srcWidth, srcHeight, srcFormat, srcType);
689 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
690 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
691 const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
692 const GLint bytesPerImage = srcHeight * bytesPerRow;
693 const GLint bytesPerTexture = srcDepth * bytesPerImage;
694 GLubyte *dstImage = (GLubyte *) dstAddr
695 + dstZoffset * dstImageStride
696 + dstYoffset * dstRowStride
697 + dstXoffset * dstFormat->TexelBytes;
698
699 if (dstRowStride == srcRowStride &&
700 dstRowStride == bytesPerRow &&
701 ((dstImageStride == srcImageStride &&
702 dstImageStride == bytesPerImage) ||
703 (srcDepth == 1))) {
704 /* one big memcpy */
705 ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
706 }
707 else {
708 GLint img, row;
709 for (img = 0; img < srcDepth; img++) {
710 const GLubyte *srcRow = srcImage;
711 GLubyte *dstRow = dstImage;
712 for (row = 0; row < srcHeight; row++) {
713 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
714 dstRow += dstRowStride;
715 srcRow += srcRowStride;
716 }
717 srcImage += srcImageStride;
718 dstImage += dstImageStride;
719 }
720 }
721 }
722
723
724
725 /**
726 * Store an image in any of the formats:
727 * _mesa_texformat_rgba
728 * _mesa_texformat_rgb
729 * _mesa_texformat_alpha
730 * _mesa_texformat_luminance
731 * _mesa_texformat_luminance_alpha
732 * _mesa_texformat_intensity
733 *
734 * \param dims either 1 or 2 or 3
735 * \param baseInternalFormat user-specified base internal format
736 * \param dstFormat destination Mesa texture format
737 * \param dstAddr destination image address
738 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
739 * \param dstRowStride destination image row stride, in bytes
740 * \param dstImageStride destination image layer stride, in bytes
741 * \param srcWidth/Height/Depth source image size, in pixels
742 * \param srcFormat incoming image format
743 * \param srcType incoming image data type
744 * \param srcAddr source image address
745 * \param srcPacking source image packing parameters
746 */
747 GLboolean
748 _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
749 GLenum baseInternalFormat,
750 const struct gl_texture_format *dstFormat,
751 GLvoid *dstAddr,
752 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
753 GLint dstRowStride, GLint dstImageStride,
754 GLint srcWidth, GLint srcHeight, GLint srcDepth,
755 GLenum srcFormat, GLenum srcType,
756 const GLvoid *srcAddr,
757 const struct gl_pixelstore_attrib *srcPacking)
758 {
759 const GLint components = _mesa_components_in_format(baseInternalFormat);
760
761 ASSERT(dstFormat == &_mesa_texformat_rgba ||
762 dstFormat == &_mesa_texformat_rgb ||
763 dstFormat == &_mesa_texformat_alpha ||
764 dstFormat == &_mesa_texformat_luminance ||
765 dstFormat == &_mesa_texformat_luminance_alpha ||
766 dstFormat == &_mesa_texformat_intensity);
767 ASSERT(baseInternalFormat == GL_RGBA ||
768 baseInternalFormat == GL_RGB ||
769 baseInternalFormat == GL_ALPHA ||
770 baseInternalFormat == GL_LUMINANCE ||
771 baseInternalFormat == GL_LUMINANCE_ALPHA ||
772 baseInternalFormat == GL_INTENSITY);
773 ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan));
774
775 if (!ctx->_ImageTransferState &&
776 !srcPacking->SwapBytes &&
777 baseInternalFormat == srcFormat &&
778 srcType == CHAN_TYPE) {
779 /* simple memcpy path */
780 memcpy_texture(ctx, dims,
781 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
782 dstRowStride, dstImageStride,
783 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
784 srcAddr, srcPacking);
785 }
786 else if (!ctx->_ImageTransferState &&
787 !srcPacking->SwapBytes &&
788 dstFormat == &_mesa_texformat_rgb &&
789 srcFormat == GL_RGBA &&
790 srcType == CHAN_TYPE) {
791 /* extract RGB from RGBA */
792 int img, row, col;
793 GLchan *dstImage = (GLchan *) (GLubyte *) dstAddr
794 + dstZoffset * dstImageStride
795 + dstYoffset * dstRowStride
796 + dstXoffset * dstFormat->TexelBytes;
797 for (img = 0; img < srcDepth; img++) {
798 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
799 srcWidth, srcFormat, srcType);
800 GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
801 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
802 GLchan *dstRow = dstImage;
803 for (row = 0; row < srcHeight; row++) {
804 for (col = 0; col < srcWidth; col++) {
805 dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
806 dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
807 dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
808 }
809 dstRow += dstRowStride;
810 srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
811 }
812 dstImage += dstImageStride;
813 }
814 }
815 else {
816 /* general path */
817 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
818 baseInternalFormat,
819 dstFormat->BaseFormat,
820 srcWidth, srcHeight, srcDepth,
821 srcFormat, srcType, srcAddr,
822 srcPacking);
823 const GLchan *src = tempImage;
824 GLint bytesPerRow;
825 GLubyte *dstImage = (GLubyte *) dstAddr
826 + dstZoffset * dstImageStride
827 + dstYoffset * dstRowStride
828 + dstXoffset * dstFormat->TexelBytes;
829 GLint img, row;
830 if (!tempImage)
831 return GL_FALSE;
832 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
833 bytesPerRow = srcWidth * components * sizeof(GLchan);
834 for (img = 0; img < srcDepth; img++) {
835 GLubyte *dstRow = dstImage;
836 for (row = 0; row < srcHeight; row++) {
837 _mesa_memcpy(dstRow, src, bytesPerRow);
838 dstRow += dstRowStride;
839 src += srcWidth * components;
840 }
841 dstImage += dstImageStride;
842 }
843
844 _mesa_free((void *) tempImage);
845 }
846 return GL_TRUE;
847 }
848
849
850 /**
851 * Store a floating point depth component texture image.
852 */
853 GLboolean
854 _mesa_texstore_depth_component_float32(STORE_PARAMS)
855 {
856 (void) dims;
857 ASSERT(dstFormat == &_mesa_texformat_depth_component_float32);
858 ASSERT(dstFormat->TexelBytes == sizeof(GLfloat));
859
860 if (!ctx->_ImageTransferState &&
861 !srcPacking->SwapBytes &&
862 baseInternalFormat == GL_DEPTH_COMPONENT &&
863 srcFormat == GL_DEPTH_COMPONENT &&
864 srcType == GL_FLOAT) {
865 /* simple memcpy path */
866 memcpy_texture(ctx, dims,
867 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
868 dstRowStride, dstImageStride,
869 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
870 srcAddr, srcPacking);
871 }
872 else {
873 /* general path */
874 GLubyte *dstImage = (GLubyte *) dstAddr
875 + dstZoffset * dstImageStride
876 + dstYoffset * dstRowStride
877 + dstXoffset * dstFormat->TexelBytes;
878 GLint img, row;
879 for (img = 0; img < srcDepth; img++) {
880 GLubyte *dstRow = dstImage;
881 for (row = 0; row < srcHeight; row++) {
882 const GLvoid *src = _mesa_image_address(dims, srcPacking,
883 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
884 _mesa_unpack_depth_span(ctx, srcWidth,
885 GL_FLOAT, (GLfloat *) dstRow, 1.0F,
886 srcType, src, srcPacking);
887 dstRow += dstRowStride;
888 }
889 dstImage += dstImageStride;
890 }
891 }
892 return GL_TRUE;
893 }
894
895
896 /**
897 * Store a 16-bit integer depth component texture image.
898 */
899 GLboolean
900 _mesa_texstore_depth_component16(STORE_PARAMS)
901 {
902 (void) dims;
903 ASSERT(dstFormat == &_mesa_texformat_depth_component16);
904 ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
905
906 if (!ctx->_ImageTransferState &&
907 !srcPacking->SwapBytes &&
908 baseInternalFormat == GL_DEPTH_COMPONENT &&
909 srcFormat == GL_DEPTH_COMPONENT &&
910 srcType == GL_UNSIGNED_SHORT) {
911 /* simple memcpy path */
912 memcpy_texture(ctx, dims,
913 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
914 dstRowStride, dstImageStride,
915 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
916 srcAddr, srcPacking);
917 }
918 else {
919 /* general path */
920 GLubyte *dstImage = (GLubyte *) dstAddr
921 + dstZoffset * dstImageStride
922 + dstYoffset * dstRowStride
923 + dstXoffset * dstFormat->TexelBytes;
924 GLint img, row;
925 for (img = 0; img < srcDepth; img++) {
926 GLubyte *dstRow = dstImage;
927 for (row = 0; row < srcHeight; row++) {
928 const GLvoid *src = _mesa_image_address(dims, srcPacking,
929 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
930 GLushort *dst16 = (GLushort *) dstRow;
931 _mesa_unpack_depth_span(ctx, srcWidth,
932 GL_UNSIGNED_SHORT, dst16, 65535.0F,
933 srcType, src, srcPacking);
934 dstRow += dstRowStride;
935 }
936 dstImage += dstImageStride;
937 }
938 }
939 return GL_TRUE;
940 }
941
942
943 /**
944 * Store an rgb565 or rgb565_rev texture image.
945 */
946 GLboolean
947 _mesa_texstore_rgb565(STORE_PARAMS)
948 {
949 ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
950 dstFormat == &_mesa_texformat_rgb565_rev);
951 ASSERT(dstFormat->TexelBytes == 2);
952
953 if (!ctx->_ImageTransferState &&
954 !srcPacking->SwapBytes &&
955 dstFormat == &_mesa_texformat_rgb565 &&
956 baseInternalFormat == GL_RGB &&
957 srcFormat == GL_RGB &&
958 srcType == GL_UNSIGNED_SHORT_5_6_5) {
959 /* simple memcpy path */
960 memcpy_texture(ctx, dims,
961 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
962 dstRowStride, dstImageStride,
963 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
964 srcAddr, srcPacking);
965 }
966 else if (!ctx->_ImageTransferState &&
967 !srcPacking->SwapBytes &&
968 baseInternalFormat == GL_RGB &&
969 srcFormat == GL_RGB &&
970 srcType == GL_UNSIGNED_BYTE &&
971 dims == 2) {
972 /* do optimized tex store */
973 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
974 srcFormat, srcType);
975 const GLubyte *src = (const GLubyte *)
976 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
977 srcFormat, srcType, 0, 0, 0);
978 GLubyte *dst = (GLubyte *) dstAddr
979 + dstZoffset * dstImageStride
980 + dstYoffset * dstRowStride
981 + dstXoffset * dstFormat->TexelBytes;
982 GLint row, col;
983 for (row = 0; row < srcHeight; row++) {
984 const GLubyte *srcUB = (const GLubyte *) src;
985 GLushort *dstUS = (GLushort *) dst;
986 /* check for byteswapped format */
987 if (dstFormat == &_mesa_texformat_rgb565) {
988 for (col = 0; col < srcWidth; col++) {
989 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
990 srcUB += 3;
991 }
992 }
993 else {
994 for (col = 0; col < srcWidth; col++) {
995 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
996 srcUB += 3;
997 }
998 }
999 dst += dstRowStride;
1000 src += srcRowStride;
1001 }
1002 }
1003 else {
1004 /* general path */
1005 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1006 baseInternalFormat,
1007 dstFormat->BaseFormat,
1008 srcWidth, srcHeight, srcDepth,
1009 srcFormat, srcType, srcAddr,
1010 srcPacking);
1011 const GLchan *src = tempImage;
1012 GLubyte *dstImage = (GLubyte *) dstAddr
1013 + dstZoffset * dstImageStride
1014 + dstYoffset * dstRowStride
1015 + dstXoffset * dstFormat->TexelBytes;
1016 GLint img, row, col;
1017 if (!tempImage)
1018 return GL_FALSE;
1019 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1020 for (img = 0; img < srcDepth; img++) {
1021 GLubyte *dstRow = dstImage;
1022 for (row = 0; row < srcHeight; row++) {
1023 GLushort *dstUS = (GLushort *) dstRow;
1024 /* check for byteswapped format */
1025 if (dstFormat == &_mesa_texformat_rgb565) {
1026 for (col = 0; col < srcWidth; col++) {
1027 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
1028 CHAN_TO_UBYTE(src[GCOMP]),
1029 CHAN_TO_UBYTE(src[BCOMP]) );
1030 src += 3;
1031 }
1032 }
1033 else {
1034 for (col = 0; col < srcWidth; col++) {
1035 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
1036 CHAN_TO_UBYTE(src[GCOMP]),
1037 CHAN_TO_UBYTE(src[BCOMP]) );
1038 src += 3;
1039 }
1040 }
1041 dstRow += dstRowStride;
1042 }
1043 dstImage += dstImageStride;
1044 }
1045 _mesa_free((void *) tempImage);
1046 }
1047 return GL_TRUE;
1048 }
1049
1050
1051 GLboolean
1052 _mesa_texstore_rgba8888(STORE_PARAMS)
1053 {
1054 const GLuint ui = 1;
1055 const GLubyte littleEndian = *((const GLubyte *) &ui);
1056
1057 (void)littleEndian;
1058 ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
1059 dstFormat == &_mesa_texformat_rgba8888_rev);
1060 ASSERT(dstFormat->TexelBytes == 4);
1061
1062 if (!ctx->_ImageTransferState &&
1063 !srcPacking->SwapBytes &&
1064 dstFormat == &_mesa_texformat_rgba8888 &&
1065 baseInternalFormat == GL_RGBA &&
1066 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1067 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) {
1068 /* simple memcpy path */
1069 memcpy_texture(ctx, dims,
1070 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1071 dstRowStride, dstImageStride,
1072 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1073 srcAddr, srcPacking);
1074 }
1075 #if 0
1076 else if (!ctx->_ImageTransferState &&
1077 !srcPacking->SwapBytes &&
1078 srcType == GL_UNSIGNED_BYTE &&
1079 dstFormat == &_mesa_texformat_rgba8888 &&
1080 littleEndian &&
1081 /* Three texture formats involved: srcFormat,
1082 * baseInternalFormat and destFormat (GL_RGBA). Only two
1083 * may differ. _mesa_swizzle_ubyte_image can't handle two
1084 * propagations at once correctly. */
1085 (srcFormat == baseInternalFormat ||
1086 baseInternalFormat == GL_RGBA) &&
1087 can_swizzle(srcFormat)) {
1088 GLubyte dstmap[4];
1089
1090 /* dstmap - how to swizzle from GL_RGBA to dst format:
1091 *
1092 * FIXME - add !litteEndian and _rev varients:
1093 */
1094 dstmap[3] = 0;
1095 dstmap[2] = 1;
1096 dstmap[1] = 2;
1097 dstmap[0] = 3;
1098
1099 _mesa_swizzle_ubyte_image(ctx, dims,
1100 srcFormat,
1101 dstmap, 4,
1102 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1103 dstRowStride, dstImageStride,
1104 srcWidth, srcHeight, srcDepth, srcAddr,
1105 srcPacking);
1106 }
1107 #endif
1108 else {
1109 /* general path */
1110 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1111 baseInternalFormat,
1112 dstFormat->BaseFormat,
1113 srcWidth, srcHeight, srcDepth,
1114 srcFormat, srcType, srcAddr,
1115 srcPacking);
1116 const GLchan *src = tempImage;
1117 GLubyte *dstImage = (GLubyte *) dstAddr
1118 + dstZoffset * dstImageStride
1119 + dstYoffset * dstRowStride
1120 + dstXoffset * dstFormat->TexelBytes;
1121 GLint img, row, col;
1122 if (!tempImage)
1123 return GL_FALSE;
1124 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1125 for (img = 0; img < srcDepth; img++) {
1126 GLubyte *dstRow = dstImage;
1127 for (row = 0; row < srcHeight; row++) {
1128 GLuint *dstUI = (GLuint *) dstRow;
1129 if (dstFormat == &_mesa_texformat_rgba8888) {
1130 for (col = 0; col < srcWidth; col++) {
1131 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
1132 CHAN_TO_UBYTE(src[GCOMP]),
1133 CHAN_TO_UBYTE(src[BCOMP]),
1134 CHAN_TO_UBYTE(src[ACOMP]) );
1135 src += 4;
1136 }
1137 }
1138 else {
1139 for (col = 0; col < srcWidth; col++) {
1140 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
1141 CHAN_TO_UBYTE(src[GCOMP]),
1142 CHAN_TO_UBYTE(src[BCOMP]),
1143 CHAN_TO_UBYTE(src[ACOMP]) );
1144 src += 4;
1145 }
1146 }
1147 dstRow += dstRowStride;
1148 }
1149 dstImage += dstImageStride;
1150 }
1151 _mesa_free((void *) tempImage);
1152 }
1153 return GL_TRUE;
1154 }
1155
1156
1157 GLboolean
1158 _mesa_texstore_argb8888(STORE_PARAMS)
1159 {
1160 const GLuint ui = 1;
1161 const GLubyte littleEndian = *((const GLubyte *) &ui);
1162
1163 ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
1164 dstFormat == &_mesa_texformat_argb8888_rev);
1165 ASSERT(dstFormat->TexelBytes == 4);
1166
1167 if (!ctx->_ImageTransferState &&
1168 !srcPacking->SwapBytes &&
1169 dstFormat == &_mesa_texformat_argb8888 &&
1170 baseInternalFormat == GL_RGBA &&
1171 srcFormat == GL_BGRA &&
1172 ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1173 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
1174 /* simple memcpy path (little endian) */
1175 memcpy_texture(ctx, dims,
1176 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1177 dstRowStride, dstImageStride,
1178 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1179 srcAddr, srcPacking);
1180 }
1181 else if (!ctx->_ImageTransferState &&
1182 !srcPacking->SwapBytes &&
1183 dstFormat == &_mesa_texformat_argb8888_rev &&
1184 baseInternalFormat == GL_RGBA &&
1185 srcFormat == GL_BGRA &&
1186 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1187 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
1188 /* simple memcpy path (big endian) */
1189 memcpy_texture(ctx, dims,
1190 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1191 dstRowStride, dstImageStride,
1192 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1193 srcAddr, srcPacking);
1194 }
1195 else if (!ctx->_ImageTransferState &&
1196 !srcPacking->SwapBytes &&
1197 dstFormat == &_mesa_texformat_argb8888 &&
1198 srcFormat == GL_RGB &&
1199 srcType == GL_UNSIGNED_BYTE) {
1200
1201 int img, row, col;
1202 GLubyte *dstImage = (GLubyte *) dstAddr
1203 + dstZoffset * dstImageStride
1204 + dstYoffset * dstRowStride
1205 + dstXoffset * dstFormat->TexelBytes;
1206 for (img = 0; img < srcDepth; img++) {
1207 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1208 srcWidth, srcFormat, srcType);
1209 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1210 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1211 GLubyte *dstRow = dstImage;
1212 for (row = 0; row < srcHeight; row++) {
1213 for (col = 0; col < srcWidth; col++) {
1214 dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP];
1215 dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP];
1216 dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP];
1217 dstRow[col * 4 + 3] = 0xff;
1218 }
1219 dstRow += dstRowStride;
1220 srcRow += srcRowStride;
1221 }
1222 dstImage += dstImageStride;
1223 }
1224 }
1225 else if (!ctx->_ImageTransferState &&
1226 !srcPacking->SwapBytes &&
1227 dstFormat == &_mesa_texformat_argb8888 &&
1228 srcFormat == GL_RGBA &&
1229 srcType == GL_UNSIGNED_BYTE) {
1230
1231 int img, row, col;
1232 GLubyte *dstImage = (GLubyte *) dstAddr
1233 + dstZoffset * dstImageStride
1234 + dstYoffset * dstRowStride
1235 + dstXoffset * dstFormat->TexelBytes;
1236 for (img = 0; img < srcDepth; img++) {
1237 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1238 srcWidth, srcFormat, srcType);
1239 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1240 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1241 GLubyte *dstRow = dstImage;
1242 for (row = 0; row < srcHeight; row++) {
1243 for (col = 0; col < srcWidth; col++) {
1244 dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP];
1245 dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP];
1246 dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP];
1247 dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP];
1248 }
1249 dstRow += dstRowStride;
1250 srcRow += srcRowStride;
1251 }
1252 dstImage += dstImageStride;
1253 }
1254 }
1255 else if (!ctx->_ImageTransferState &&
1256 !srcPacking->SwapBytes &&
1257 dstFormat == &_mesa_texformat_argb8888 &&
1258 srcType == GL_UNSIGNED_BYTE &&
1259 littleEndian &&
1260 /* Three texture formats involved: srcFormat,
1261 * baseInternalFormat and destFormat (GL_RGBA). Only two
1262 * may differ. _mesa_swizzle_ubyte_image can't handle two
1263 * propagations at once correctly. */
1264 (srcFormat == baseInternalFormat ||
1265 baseInternalFormat == GL_RGBA) &&
1266 can_swizzle(srcFormat)) {
1267
1268 GLubyte dstmap[4];
1269
1270 /* dstmap - how to swizzle from GL_RGBA to dst format:
1271 */
1272 dstmap[3] = 3; /* alpha */
1273 dstmap[2] = 0; /* red */
1274 dstmap[1] = 1; /* green */
1275 dstmap[0] = 2; /* blue */
1276
1277 _mesa_swizzle_ubyte_image(ctx, dims,
1278 srcFormat,
1279 dstmap, 4,
1280 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1281 dstRowStride, dstImageStride,
1282 srcWidth, srcHeight, srcDepth, srcAddr,
1283 srcPacking);
1284 }
1285 else {
1286 /* general path */
1287 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1288 baseInternalFormat,
1289 dstFormat->BaseFormat,
1290 srcWidth, srcHeight, srcDepth,
1291 srcFormat, srcType, srcAddr,
1292 srcPacking);
1293 const GLchan *src = tempImage;
1294 GLubyte *dstImage = (GLubyte *) dstAddr
1295 + dstZoffset * dstImageStride
1296 + dstYoffset * dstRowStride
1297 + dstXoffset * dstFormat->TexelBytes;
1298 GLint img, row, col;
1299 if (!tempImage)
1300 return GL_FALSE;
1301 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1302 for (img = 0; img < srcDepth; img++) {
1303 GLubyte *dstRow = dstImage;
1304 for (row = 0; row < srcHeight; row++) {
1305 GLuint *dstUI = (GLuint *) dstRow;
1306 if (dstFormat == &_mesa_texformat_argb8888) {
1307 for (col = 0; col < srcWidth; col++) {
1308 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1309 CHAN_TO_UBYTE(src[RCOMP]),
1310 CHAN_TO_UBYTE(src[GCOMP]),
1311 CHAN_TO_UBYTE(src[BCOMP]) );
1312 src += 4;
1313 }
1314 }
1315 else {
1316 for (col = 0; col < srcWidth; col++) {
1317 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1318 CHAN_TO_UBYTE(src[RCOMP]),
1319 CHAN_TO_UBYTE(src[GCOMP]),
1320 CHAN_TO_UBYTE(src[BCOMP]) );
1321 src += 4;
1322 }
1323 }
1324 dstRow += dstRowStride;
1325 }
1326 dstImage += dstImageStride;
1327 }
1328 _mesa_free((void *) tempImage);
1329 }
1330 return GL_TRUE;
1331 }
1332
1333
1334 GLboolean
1335 _mesa_texstore_rgb888(STORE_PARAMS)
1336 {
1337 const GLuint ui = 1;
1338 const GLubyte littleEndian = *((const GLubyte *) &ui);
1339
1340 ASSERT(dstFormat == &_mesa_texformat_rgb888);
1341 ASSERT(dstFormat->TexelBytes == 3);
1342
1343 if (!ctx->_ImageTransferState &&
1344 !srcPacking->SwapBytes &&
1345 baseInternalFormat == GL_RGB &&
1346 srcFormat == GL_BGR &&
1347 srcType == GL_UNSIGNED_BYTE &&
1348 littleEndian) {
1349 /* simple memcpy path */
1350 memcpy_texture(ctx, dims,
1351 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1352 dstRowStride, dstImageStride,
1353 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1354 srcAddr, srcPacking);
1355 }
1356 else if (!ctx->_ImageTransferState &&
1357 !srcPacking->SwapBytes &&
1358 srcFormat == GL_RGBA &&
1359 srcType == GL_UNSIGNED_BYTE) {
1360 /* extract RGB from RGBA */
1361 int img, row, col;
1362 GLubyte *dstImage = (GLubyte *) dstAddr
1363 + dstZoffset * dstImageStride
1364 + dstYoffset * dstRowStride
1365 + dstXoffset * dstFormat->TexelBytes;
1366 for (img = 0; img < srcDepth; img++) {
1367 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1368 srcWidth, srcFormat, srcType);
1369 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1370 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1371 GLubyte *dstRow = dstImage;
1372 for (row = 0; row < srcHeight; row++) {
1373 for (col = 0; col < srcWidth; col++) {
1374 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1375 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1376 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1377 }
1378 dstRow += dstRowStride;
1379 srcRow += srcRowStride;
1380 }
1381 dstImage += dstImageStride;
1382 }
1383 }
1384 else {
1385 /* general path */
1386 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1387 baseInternalFormat,
1388 dstFormat->BaseFormat,
1389 srcWidth, srcHeight, srcDepth,
1390 srcFormat, srcType, srcAddr,
1391 srcPacking);
1392 const GLchan *src = (const GLchan *) tempImage;
1393 GLubyte *dstImage = (GLubyte *) dstAddr
1394 + dstZoffset * dstImageStride
1395 + dstYoffset * dstRowStride
1396 + dstXoffset * dstFormat->TexelBytes;
1397 GLint img, row, col;
1398 if (!tempImage)
1399 return GL_FALSE;
1400 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1401 for (img = 0; img < srcDepth; img++) {
1402 GLubyte *dstRow = dstImage;
1403 for (row = 0; row < srcHeight; row++) {
1404 #if 0
1405 if (littleEndian) {
1406 for (col = 0; col < srcWidth; col++) {
1407 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1408 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1409 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1410 srcUB += 3;
1411 }
1412 }
1413 else {
1414 for (col = 0; col < srcWidth; col++) {
1415 dstRow[col * 3 + 0] = srcUB[BCOMP];
1416 dstRow[col * 3 + 1] = srcUB[GCOMP];
1417 dstRow[col * 3 + 2] = srcUB[RCOMP];
1418 srcUB += 3;
1419 }
1420 }
1421 #else
1422 for (col = 0; col < srcWidth; col++) {
1423 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1424 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1425 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1426 src += 3;
1427 }
1428 #endif
1429 dstRow += dstRowStride;
1430 }
1431 dstImage += dstImageStride;
1432 }
1433 _mesa_free((void *) tempImage);
1434 }
1435 return GL_TRUE;
1436 }
1437
1438
1439 GLboolean
1440 _mesa_texstore_bgr888(STORE_PARAMS)
1441 {
1442 const GLuint ui = 1;
1443 const GLubyte littleEndian = *((const GLubyte *) &ui);
1444
1445 ASSERT(dstFormat == &_mesa_texformat_bgr888);
1446 ASSERT(dstFormat->TexelBytes == 3);
1447
1448 if (!ctx->_ImageTransferState &&
1449 !srcPacking->SwapBytes &&
1450 baseInternalFormat == GL_RGB &&
1451 srcFormat == GL_RGB &&
1452 srcType == GL_UNSIGNED_BYTE &&
1453 littleEndian) {
1454 /* simple memcpy path */
1455 memcpy_texture(ctx, dims,
1456 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1457 dstRowStride, dstImageStride,
1458 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1459 srcAddr, srcPacking);
1460 }
1461 else if (!ctx->_ImageTransferState &&
1462 !srcPacking->SwapBytes &&
1463 srcFormat == GL_RGBA &&
1464 srcType == GL_UNSIGNED_BYTE) {
1465 /* extract BGR from RGBA */
1466 int img, row, col;
1467 GLubyte *dstImage = (GLubyte *) dstAddr
1468 + dstZoffset * dstImageStride
1469 + dstYoffset * dstRowStride
1470 + dstXoffset * dstFormat->TexelBytes;
1471 for (img = 0; img < srcDepth; img++) {
1472 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1473 srcWidth, srcFormat, srcType);
1474 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1475 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1476 GLubyte *dstRow = dstImage;
1477 for (row = 0; row < srcHeight; row++) {
1478 for (col = 0; col < srcWidth; col++) {
1479 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1480 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1481 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1482 }
1483 dstRow += dstRowStride;
1484 srcRow += srcRowStride;
1485 }
1486 dstImage += dstImageStride;
1487 }
1488 }
1489 else {
1490 /* general path */
1491 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1492 baseInternalFormat,
1493 dstFormat->BaseFormat,
1494 srcWidth, srcHeight, srcDepth,
1495 srcFormat, srcType, srcAddr,
1496 srcPacking);
1497 const GLchan *src = (const GLchan *) tempImage;
1498 GLubyte *dstImage = (GLubyte *) dstAddr
1499 + dstZoffset * dstImageStride
1500 + dstYoffset * dstRowStride
1501 + dstXoffset * dstFormat->TexelBytes;
1502 GLint img, row, col;
1503 if (!tempImage)
1504 return GL_FALSE;
1505 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1506 for (img = 0; img < srcDepth; img++) {
1507 GLubyte *dstRow = dstImage;
1508 for (row = 0; row < srcHeight; row++) {
1509 for (col = 0; col < srcWidth; col++) {
1510 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1511 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1512 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1513 src += 3;
1514 }
1515 dstRow += dstRowStride;
1516 }
1517 dstImage += dstImageStride;
1518 }
1519 _mesa_free((void *) tempImage);
1520 }
1521 return GL_TRUE;
1522 }
1523
1524
1525 GLboolean
1526 _mesa_texstore_argb4444(STORE_PARAMS)
1527 {
1528 ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
1529 dstFormat == &_mesa_texformat_argb4444_rev);
1530 ASSERT(dstFormat->TexelBytes == 2);
1531
1532 if (!ctx->_ImageTransferState &&
1533 !srcPacking->SwapBytes &&
1534 dstFormat == &_mesa_texformat_argb4444 &&
1535 baseInternalFormat == GL_RGBA &&
1536 srcFormat == GL_BGRA &&
1537 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1538 /* simple memcpy path */
1539 memcpy_texture(ctx, dims,
1540 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1541 dstRowStride, dstImageStride,
1542 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1543 srcAddr, srcPacking);
1544 }
1545 else {
1546 /* general path */
1547 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1548 baseInternalFormat,
1549 dstFormat->BaseFormat,
1550 srcWidth, srcHeight, srcDepth,
1551 srcFormat, srcType, srcAddr,
1552 srcPacking);
1553 const GLchan *src = tempImage;
1554 GLubyte *dstImage = (GLubyte *) dstAddr
1555 + dstZoffset * dstImageStride
1556 + dstYoffset * dstRowStride
1557 + dstXoffset * dstFormat->TexelBytes;
1558 GLint img, row, col;
1559 if (!tempImage)
1560 return GL_FALSE;
1561 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1562 for (img = 0; img < srcDepth; img++) {
1563 GLubyte *dstRow = dstImage;
1564 for (row = 0; row < srcHeight; row++) {
1565 GLushort *dstUS = (GLushort *) dstRow;
1566 if (dstFormat == &_mesa_texformat_argb4444) {
1567 for (col = 0; col < srcWidth; col++) {
1568 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1569 CHAN_TO_UBYTE(src[RCOMP]),
1570 CHAN_TO_UBYTE(src[GCOMP]),
1571 CHAN_TO_UBYTE(src[BCOMP]) );
1572 src += 4;
1573 }
1574 }
1575 else {
1576 for (col = 0; col < srcWidth; col++) {
1577 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
1578 CHAN_TO_UBYTE(src[RCOMP]),
1579 CHAN_TO_UBYTE(src[GCOMP]),
1580 CHAN_TO_UBYTE(src[BCOMP]) );
1581 src += 4;
1582 }
1583 }
1584 dstRow += dstRowStride;
1585 }
1586 dstImage += dstImageStride;
1587 }
1588 _mesa_free((void *) tempImage);
1589 }
1590 return GL_TRUE;
1591 }
1592
1593
1594
1595 GLboolean
1596 _mesa_texstore_argb1555(STORE_PARAMS)
1597 {
1598 ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
1599 dstFormat == &_mesa_texformat_argb1555_rev);
1600 ASSERT(dstFormat->TexelBytes == 2);
1601
1602 if (!ctx->_ImageTransferState &&
1603 !srcPacking->SwapBytes &&
1604 dstFormat == &_mesa_texformat_argb1555 &&
1605 baseInternalFormat == GL_RGBA &&
1606 srcFormat == GL_BGRA &&
1607 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
1608 /* simple memcpy path */
1609 memcpy_texture(ctx, dims,
1610 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1611 dstRowStride, dstImageStride,
1612 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1613 srcAddr, srcPacking);
1614 }
1615 else {
1616 /* general path */
1617 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1618 baseInternalFormat,
1619 dstFormat->BaseFormat,
1620 srcWidth, srcHeight, srcDepth,
1621 srcFormat, srcType, srcAddr,
1622 srcPacking);
1623 const GLchan *src =tempImage;
1624 GLubyte *dstImage = (GLubyte *) dstAddr
1625 + dstZoffset * dstImageStride
1626 + dstYoffset * dstRowStride
1627 + dstXoffset * dstFormat->TexelBytes;
1628 GLint img, row, col;
1629 if (!tempImage)
1630 return GL_FALSE;
1631 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1632 for (img = 0; img < srcDepth; img++) {
1633 GLubyte *dstRow = dstImage;
1634 for (row = 0; row < srcHeight; row++) {
1635 GLushort *dstUS = (GLushort *) dstRow;
1636 if (dstFormat == &_mesa_texformat_argb1555) {
1637 for (col = 0; col < srcWidth; col++) {
1638 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
1639 CHAN_TO_UBYTE(src[RCOMP]),
1640 CHAN_TO_UBYTE(src[GCOMP]),
1641 CHAN_TO_UBYTE(src[BCOMP]) );
1642 src += 4;
1643 }
1644 }
1645 else {
1646 for (col = 0; col < srcWidth; col++) {
1647 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
1648 CHAN_TO_UBYTE(src[RCOMP]),
1649 CHAN_TO_UBYTE(src[GCOMP]),
1650 CHAN_TO_UBYTE(src[BCOMP]) );
1651 src += 4;
1652 }
1653 }
1654 dstRow += dstRowStride;
1655 }
1656 dstImage += dstImageStride;
1657 }
1658 _mesa_free((void *) tempImage);
1659 }
1660 return GL_TRUE;
1661 }
1662
1663
1664 GLboolean
1665 _mesa_texstore_al88(STORE_PARAMS)
1666 {
1667 const GLuint ui = 1;
1668 const GLubyte littleEndian = *((const GLubyte *) &ui);
1669
1670 ASSERT(dstFormat == &_mesa_texformat_al88 ||
1671 dstFormat == &_mesa_texformat_al88_rev);
1672 ASSERT(dstFormat->TexelBytes == 2);
1673
1674 if (!ctx->_ImageTransferState &&
1675 !srcPacking->SwapBytes &&
1676 dstFormat == &_mesa_texformat_al88 &&
1677 baseInternalFormat == GL_LUMINANCE_ALPHA &&
1678 srcFormat == GL_LUMINANCE_ALPHA &&
1679 srcType == GL_UNSIGNED_BYTE &&
1680 littleEndian) {
1681 /* simple memcpy path */
1682 memcpy_texture(ctx, dims,
1683 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1684 dstRowStride, dstImageStride,
1685 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1686 srcAddr, srcPacking);
1687 }
1688 else {
1689 /* general path */
1690 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1691 baseInternalFormat,
1692 dstFormat->BaseFormat,
1693 srcWidth, srcHeight, srcDepth,
1694 srcFormat, srcType, srcAddr,
1695 srcPacking);
1696 const GLchan *src = tempImage;
1697 GLubyte *dstImage = (GLubyte *) dstAddr
1698 + dstZoffset * dstImageStride
1699 + dstYoffset * dstRowStride
1700 + dstXoffset * dstFormat->TexelBytes;
1701 GLint img, row, col;
1702 if (!tempImage)
1703 return GL_FALSE;
1704 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1705 for (img = 0; img < srcDepth; img++) {
1706 GLubyte *dstRow = dstImage;
1707 for (row = 0; row < srcHeight; row++) {
1708 GLushort *dstUS = (GLushort *) dstRow;
1709 if (dstFormat == &_mesa_texformat_al88) {
1710 for (col = 0; col < srcWidth; col++) {
1711 /* src[0] is luminance, src[1] is alpha */
1712 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
1713 CHAN_TO_UBYTE(src[0]) );
1714 src += 2;
1715 }
1716 }
1717 else {
1718 for (col = 0; col < srcWidth; col++) {
1719 /* src[0] is luminance, src[1] is alpha */
1720 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
1721 CHAN_TO_UBYTE(src[0]) );
1722 src += 2;
1723 }
1724 }
1725 dstRow += dstRowStride;
1726 }
1727 dstImage += dstImageStride;
1728 }
1729 _mesa_free((void *) tempImage);
1730 }
1731 return GL_TRUE;
1732 }
1733
1734
1735 GLboolean
1736 _mesa_texstore_rgb332(STORE_PARAMS)
1737 {
1738 ASSERT(dstFormat == &_mesa_texformat_rgb332);
1739 ASSERT(dstFormat->TexelBytes == 1);
1740
1741 if (!ctx->_ImageTransferState &&
1742 !srcPacking->SwapBytes &&
1743 baseInternalFormat == GL_RGB &&
1744 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
1745 /* simple memcpy path */
1746 memcpy_texture(ctx, dims,
1747 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1748 dstRowStride, dstImageStride,
1749 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1750 srcAddr, srcPacking);
1751 }
1752 else {
1753 /* general path */
1754 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1755 baseInternalFormat,
1756 dstFormat->BaseFormat,
1757 srcWidth, srcHeight, srcDepth,
1758 srcFormat, srcType, srcAddr,
1759 srcPacking);
1760 const GLchan *src = tempImage;
1761 GLubyte *dstImage = (GLubyte *) dstAddr
1762 + dstZoffset * dstImageStride
1763 + dstYoffset * dstRowStride
1764 + dstXoffset * dstFormat->TexelBytes;
1765 GLint img, row, col;
1766 if (!tempImage)
1767 return GL_FALSE;
1768 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1769 for (img = 0; img < srcDepth; img++) {
1770 GLubyte *dstRow = dstImage;
1771 for (row = 0; row < srcHeight; row++) {
1772 for (col = 0; col < srcWidth; col++) {
1773 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
1774 CHAN_TO_UBYTE(src[GCOMP]),
1775 CHAN_TO_UBYTE(src[BCOMP]) );
1776 src += 3;
1777 }
1778 dstRow += dstRowStride;
1779 }
1780 dstImage += dstImageStride;
1781 }
1782 _mesa_free((void *) tempImage);
1783 }
1784 return GL_TRUE;
1785 }
1786
1787
1788 /**
1789 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1790 */
1791 GLboolean
1792 _mesa_texstore_a8(STORE_PARAMS)
1793 {
1794 ASSERT(dstFormat == &_mesa_texformat_a8 ||
1795 dstFormat == &_mesa_texformat_l8 ||
1796 dstFormat == &_mesa_texformat_i8);
1797 ASSERT(dstFormat->TexelBytes == 1);
1798
1799 if (!ctx->_ImageTransferState &&
1800 !srcPacking->SwapBytes &&
1801 baseInternalFormat == srcFormat &&
1802 srcType == GL_UNSIGNED_BYTE) {
1803 /* simple memcpy path */
1804 memcpy_texture(ctx, dims,
1805 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1806 dstRowStride, dstImageStride,
1807 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1808 srcAddr, srcPacking);
1809 }
1810 else {
1811 /* general path */
1812 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1813 baseInternalFormat,
1814 dstFormat->BaseFormat,
1815 srcWidth, srcHeight, srcDepth,
1816 srcFormat, srcType, srcAddr,
1817 srcPacking);
1818 const GLchan *src = tempImage;
1819 GLubyte *dstImage = (GLubyte *) dstAddr
1820 + dstZoffset * dstImageStride
1821 + dstYoffset * dstRowStride
1822 + dstXoffset * dstFormat->TexelBytes;
1823 GLint img, row, col;
1824 if (!tempImage)
1825 return GL_FALSE;
1826 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1827 for (img = 0; img < srcDepth; img++) {
1828 GLubyte *dstRow = dstImage;
1829 for (row = 0; row < srcHeight; row++) {
1830 for (col = 0; col < srcWidth; col++) {
1831 dstRow[col] = CHAN_TO_UBYTE(src[col]);
1832 }
1833 dstRow += dstRowStride;
1834 src += srcWidth;
1835 }
1836 dstImage += dstImageStride;
1837 }
1838 _mesa_free((void *) tempImage);
1839 }
1840 return GL_TRUE;
1841 }
1842
1843
1844
1845 GLboolean
1846 _mesa_texstore_ci8(STORE_PARAMS)
1847 {
1848 (void) dims; (void) baseInternalFormat;
1849 ASSERT(dstFormat == &_mesa_texformat_ci8);
1850 ASSERT(dstFormat->TexelBytes == 1);
1851 ASSERT(baseInternalFormat == GL_COLOR_INDEX);
1852
1853 if (!ctx->_ImageTransferState &&
1854 !srcPacking->SwapBytes &&
1855 srcFormat == GL_COLOR_INDEX &&
1856 srcType == GL_UNSIGNED_BYTE) {
1857 /* simple memcpy path */
1858 memcpy_texture(ctx, dims,
1859 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1860 dstRowStride, dstImageStride,
1861 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1862 srcAddr, srcPacking);
1863 }
1864 else {
1865 /* general path */
1866 GLubyte *dstImage = (GLubyte *) dstAddr
1867 + dstZoffset * dstImageStride
1868 + dstYoffset * dstRowStride
1869 + dstXoffset * dstFormat->TexelBytes;
1870 GLint img, row;
1871 for (img = 0; img < srcDepth; img++) {
1872 GLubyte *dstRow = dstImage;
1873 for (row = 0; row < srcHeight; row++) {
1874 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1875 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1876 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
1877 srcType, src, srcPacking,
1878 ctx->_ImageTransferState);
1879 dstRow += dstRowStride;
1880 }
1881 dstImage += dstImageStride;
1882 }
1883 }
1884 return GL_TRUE;
1885 }
1886
1887
1888 /**
1889 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1890 */
1891 GLboolean
1892 _mesa_texstore_ycbcr(STORE_PARAMS)
1893 {
1894 const GLuint ui = 1;
1895 const GLubyte littleEndian = *((const GLubyte *) &ui);
1896 (void) ctx; (void) dims; (void) baseInternalFormat;
1897
1898 ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
1899 (dstFormat == &_mesa_texformat_ycbcr_rev));
1900 ASSERT(dstFormat->TexelBytes == 2);
1901 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1902 ASSERT(srcFormat == GL_YCBCR_MESA);
1903 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
1904 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
1905 ASSERT(baseInternalFormat == GL_YCBCR_MESA);
1906
1907 /* always just memcpy since no pixel transfer ops apply */
1908 memcpy_texture(ctx, dims,
1909 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1910 dstRowStride, dstImageStride,
1911 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1912 srcAddr, srcPacking);
1913
1914 /* Check if we need byte swapping */
1915 /* XXX the logic here _might_ be wrong */
1916 if (srcPacking->SwapBytes ^
1917 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
1918 (dstFormat == &_mesa_texformat_ycbcr_rev) ^
1919 !littleEndian) {
1920 GLubyte *pImage = (GLubyte *) dstAddr
1921 + dstZoffset * dstImageStride
1922 + dstYoffset * dstRowStride
1923 + dstXoffset * dstFormat->TexelBytes;
1924 GLint img, row;
1925 for (img = 0; img < srcDepth; img++) {
1926 GLubyte *pRow = pImage;
1927 for (row = 0; row < srcHeight; row++) {
1928 _mesa_swap2((GLushort *) pRow, srcWidth);
1929 pRow += dstRowStride;
1930 }
1931 pImage += dstImageStride;
1932 }
1933 }
1934 return GL_TRUE;
1935 }
1936
1937
1938
1939 /**
1940 * Store a combined depth/stencil texture image.
1941 */
1942 GLboolean
1943 _mesa_texstore_z24_s8(STORE_PARAMS)
1944 {
1945 ASSERT(dstFormat == &_mesa_texformat_z24_s8);
1946 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
1947 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
1948
1949 if (!ctx->_ImageTransferState &&
1950 !srcPacking->SwapBytes) {
1951 /* simple path */
1952 memcpy_texture(ctx, dims,
1953 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1954 dstRowStride, dstImageStride,
1955 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1956 srcAddr, srcPacking);
1957 }
1958 else {
1959 /* general path */
1960 const GLint srcRowStride
1961 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
1962 / sizeof(GLuint);
1963 GLuint *dstImage = (GLuint *) dstAddr;
1964 GLint img, row;
1965
1966 for (img = 0; img < srcDepth; img++) {
1967 GLuint *dst = dstImage;
1968 const GLuint *src
1969 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
1970 srcWidth, srcHeight,
1971 srcFormat, srcType,
1972 img, 0, 0);
1973 for (row = 0; row < srcHeight; row++) {
1974 GLubyte stencil[MAX_WIDTH];
1975 GLint i;
1976 /* the 24 depth bits will be in the high position: */
1977 _mesa_unpack_depth_span(ctx, srcWidth,
1978 GL_UNSIGNED_INT, /* dst type */
1979 dst, /* dst addr */
1980 (GLfloat) 0xffffff, /* depthScale */
1981 srcType, src, srcPacking);
1982 /* get the 8-bit stencil values */
1983 _mesa_unpack_stencil_span(ctx, srcWidth,
1984 GL_UNSIGNED_BYTE, /* dst type */
1985 stencil, /* dst addr */
1986 srcType, src, srcPacking,
1987 ctx->_ImageTransferState);
1988 /* merge stencil values into depth values */
1989 for (i = 0; i < srcWidth; i++)
1990 dst[i] |= stencil[i];
1991
1992 src += srcRowStride;
1993 dst += dstRowStride / sizeof(GLuint);
1994 }
1995 dstImage += dstImageStride / sizeof(GLuint);
1996 }
1997 }
1998
1999
2000 return GL_TRUE;
2001 }
2002
2003
2004
2005 /**
2006 * Store an image in any of the formats:
2007 * _mesa_texformat_rgba_float32
2008 * _mesa_texformat_rgb_float32
2009 * _mesa_texformat_alpha_float32
2010 * _mesa_texformat_luminance_float32
2011 * _mesa_texformat_luminance_alpha_float32
2012 * _mesa_texformat_intensity_float32
2013 */
2014 GLboolean
2015 _mesa_texstore_rgba_float32(STORE_PARAMS)
2016 {
2017 const GLint components = _mesa_components_in_format(baseInternalFormat);
2018
2019 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
2020 dstFormat == &_mesa_texformat_rgb_float32 ||
2021 dstFormat == &_mesa_texformat_alpha_float32 ||
2022 dstFormat == &_mesa_texformat_luminance_float32 ||
2023 dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
2024 dstFormat == &_mesa_texformat_intensity_float32);
2025 ASSERT(baseInternalFormat == GL_RGBA ||
2026 baseInternalFormat == GL_RGB ||
2027 baseInternalFormat == GL_ALPHA ||
2028 baseInternalFormat == GL_LUMINANCE ||
2029 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2030 baseInternalFormat == GL_INTENSITY);
2031 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
2032
2033 if (!ctx->_ImageTransferState &&
2034 !srcPacking->SwapBytes &&
2035 baseInternalFormat == srcFormat &&
2036 srcType == GL_FLOAT) {
2037 /* simple memcpy path */
2038 memcpy_texture(ctx, dims,
2039 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2040 dstRowStride, dstImageStride,
2041 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2042 srcAddr, srcPacking);
2043 }
2044 else {
2045 /* general path */
2046 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2047 baseInternalFormat,
2048 dstFormat->BaseFormat,
2049 srcWidth, srcHeight, srcDepth,
2050 srcFormat, srcType, srcAddr,
2051 srcPacking);
2052 const GLfloat *src = tempImage;
2053 GLint bytesPerRow;
2054 GLubyte *dstImage = (GLubyte *) dstAddr
2055 + dstZoffset * dstImageStride
2056 + dstYoffset * dstRowStride
2057 + dstXoffset * dstFormat->TexelBytes;
2058 GLint img, row;
2059 if (!tempImage)
2060 return GL_FALSE;
2061 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2062 bytesPerRow = srcWidth * components * sizeof(GLfloat);
2063 for (img = 0; img < srcDepth; img++) {
2064 GLubyte *dst = dstImage;
2065 for (row = 0; row < srcHeight; row++) {
2066 _mesa_memcpy(dst, src, bytesPerRow);
2067 dst += dstRowStride;
2068 src += srcWidth * components;
2069 }
2070 dstImage += dstImageStride;
2071 }
2072
2073 _mesa_free((void *) tempImage);
2074 }
2075 return GL_TRUE;
2076 }
2077
2078
2079 /**
2080 * As above, but store 16-bit floats.
2081 */
2082 GLboolean
2083 _mesa_texstore_rgba_float16(STORE_PARAMS)
2084 {
2085 const GLint components = _mesa_components_in_format(baseInternalFormat);
2086
2087 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
2088 dstFormat == &_mesa_texformat_rgb_float16 ||
2089 dstFormat == &_mesa_texformat_alpha_float16 ||
2090 dstFormat == &_mesa_texformat_luminance_float16 ||
2091 dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
2092 dstFormat == &_mesa_texformat_intensity_float16);
2093 ASSERT(baseInternalFormat == GL_RGBA ||
2094 baseInternalFormat == GL_RGB ||
2095 baseInternalFormat == GL_ALPHA ||
2096 baseInternalFormat == GL_LUMINANCE ||
2097 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2098 baseInternalFormat == GL_INTENSITY);
2099 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
2100
2101 if (!ctx->_ImageTransferState &&
2102 !srcPacking->SwapBytes &&
2103 baseInternalFormat == srcFormat &&
2104 srcType == GL_HALF_FLOAT_ARB) {
2105 /* simple memcpy path */
2106 memcpy_texture(ctx, dims,
2107 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2108 dstRowStride, dstImageStride,
2109 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2110 srcAddr, srcPacking);
2111 }
2112 else {
2113 /* general path */
2114 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2115 baseInternalFormat,
2116 dstFormat->BaseFormat,
2117 srcWidth, srcHeight, srcDepth,
2118 srcFormat, srcType, srcAddr,
2119 srcPacking);
2120 const GLfloat *src = tempImage;
2121 GLubyte *dstImage = (GLubyte *) dstAddr
2122 + dstZoffset * dstImageStride
2123 + dstYoffset * dstRowStride
2124 + dstXoffset * dstFormat->TexelBytes;
2125 GLint img, row;
2126 if (!tempImage)
2127 return GL_FALSE;
2128 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2129 for (img = 0; img < srcDepth; img++) {
2130 GLubyte *dstRow = dstImage;
2131 for (row = 0; row < srcHeight; row++) {
2132 GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
2133 GLint i;
2134 for (i = 0; i < srcWidth * components; i++) {
2135 dstTexel[i] = _mesa_float_to_half(src[i]);
2136 }
2137 dstRow += dstRowStride;
2138 src += srcWidth * components;
2139 }
2140 dstImage += dstImageStride;
2141 }
2142
2143 _mesa_free((void *) tempImage);
2144 }
2145 return GL_TRUE;
2146 }
2147
2148
2149
2150 /**
2151 * Check if an unpack PBO is active prior to fetching a texture image.
2152 * If so, do bounds checking and map the buffer into main memory.
2153 * Any errors detected will be recorded.
2154 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2155 */
2156 const GLvoid *
2157 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
2158 GLsizei width, GLsizei height, GLsizei depth,
2159 GLenum format, GLenum type, const GLvoid *pixels,
2160 const struct gl_pixelstore_attrib *unpack,
2161 const char *funcName)
2162 {
2163 GLubyte *buf;
2164
2165 if (unpack->BufferObj->Name == 0) {
2166 /* no PBO */
2167 return pixels;
2168 }
2169 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
2170 format, type, pixels)) {
2171 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2172 return NULL;
2173 }
2174
2175 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2176 GL_READ_ONLY_ARB, unpack->BufferObj);
2177 if (!buf) {
2178 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2179 return NULL;
2180 }
2181
2182 return ADD_POINTERS(buf, pixels);
2183 }
2184
2185
2186 /**
2187 * Check if an unpack PBO is active prior to fetching a compressed texture
2188 * image.
2189 * If so, do bounds checking and map the buffer into main memory.
2190 * Any errors detected will be recorded.
2191 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2192 */
2193 const GLvoid *
2194 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
2195 GLsizei imageSize, const GLvoid *pixels,
2196 const struct gl_pixelstore_attrib *packing,
2197 const char *funcName)
2198 {
2199 GLubyte *buf;
2200
2201 if (packing->BufferObj->Name == 0) {
2202 /* not using a PBO - return pointer unchanged */
2203 return pixels;
2204 }
2205 if ((const GLubyte *) pixels + imageSize >
2206 ((const GLubyte *) 0) + packing->BufferObj->Size) {
2207 /* out of bounds read! */
2208 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2209 return NULL;
2210 }
2211
2212 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2213 GL_READ_ONLY_ARB, packing->BufferObj);
2214 if (!buf) {
2215 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2216 return NULL;
2217 }
2218
2219 return ADD_POINTERS(buf, pixels);
2220 }
2221
2222
2223 /**
2224 * This function must be called after either of the validate_pbo_*_teximage()
2225 * functions. It unmaps the PBO buffer if it was mapped earlier.
2226 */
2227 void
2228 _mesa_unmap_teximage_pbo(GLcontext *ctx,
2229 const struct gl_pixelstore_attrib *unpack)
2230 {
2231 if (unpack->BufferObj->Name) {
2232 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2233 unpack->BufferObj);
2234 }
2235 }
2236
2237
2238
2239 /**
2240 * Adaptor for fetching a GLchan texel from a float-valued texture.
2241 */
2242 static void
2243 FetchTexelFloatToChan( const struct gl_texture_image *texImage,
2244 GLint i, GLint j, GLint k, GLchan *texelOut )
2245 {
2246 GLfloat temp[4];
2247 ASSERT(texImage->FetchTexelf);
2248 texImage->FetchTexelf(texImage, i, j, k, temp);
2249 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
2250 /* just one channel */
2251 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2252 }
2253 else {
2254 /* four channels */
2255 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2256 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
2257 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
2258 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
2259 }
2260 }
2261
2262
2263 /**
2264 * Adaptor for fetching a float texel from a GLchan-valued texture.
2265 */
2266 static void
2267 FetchTexelChanToFloat( const struct gl_texture_image *texImage,
2268 GLint i, GLint j, GLint k, GLfloat *texelOut )
2269 {
2270 GLchan temp[4];
2271 ASSERT(texImage->FetchTexelc);
2272 texImage->FetchTexelc(texImage, i, j, k, temp);
2273 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
2274 /* just one channel */
2275 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2276 }
2277 else {
2278 /* four channels */
2279 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2280 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
2281 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
2282 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
2283 }
2284 }
2285
2286
2287 /**
2288 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2289 */
2290 static void
2291 set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
2292 {
2293 ASSERT(dims == 1 || dims == 2 || dims == 3);
2294 ASSERT(texImage->TexFormat);
2295
2296 switch (dims) {
2297 case 1:
2298 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
2299 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
2300 break;
2301 case 2:
2302 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2303 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2304 break;
2305 case 3:
2306 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
2307 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
2308 break;
2309 default:
2310 ;
2311 }
2312
2313 /* now check if we need to use a float/chan adaptor */
2314 if (!texImage->FetchTexelc) {
2315 texImage->FetchTexelc = FetchTexelFloatToChan;
2316 }
2317 else if (!texImage->FetchTexelf) {
2318 texImage->FetchTexelf = FetchTexelChanToFloat;
2319 }
2320
2321
2322 ASSERT(texImage->FetchTexelc);
2323 ASSERT(texImage->FetchTexelf);
2324 }
2325
2326
2327 /*
2328 * This is the software fallback for Driver.TexImage1D()
2329 * and Driver.CopyTexImage1D().
2330 * \sa _mesa_store_teximage2d()
2331 */
2332 void
2333 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2334 GLint internalFormat,
2335 GLint width, GLint border,
2336 GLenum format, GLenum type, const GLvoid *pixels,
2337 const struct gl_pixelstore_attrib *packing,
2338 struct gl_texture_object *texObj,
2339 struct gl_texture_image *texImage)
2340 {
2341 GLint postConvWidth = width;
2342 GLint sizeInBytes;
2343 (void) border;
2344
2345 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2346 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2347 }
2348
2349 /* choose the texture format */
2350 assert(ctx->Driver.ChooseTextureFormat);
2351 texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2352 format, type);
2353 assert(texImage->TexFormat);
2354 set_fetch_functions(texImage, 1);
2355
2356 /* allocate memory */
2357 if (texImage->IsCompressed)
2358 sizeInBytes = texImage->CompressedSize;
2359 else
2360 sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes;
2361 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2362 if (!texImage->Data) {
2363 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2364 return;
2365 }
2366
2367 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2368 pixels, packing, "glTexImage1D");
2369 if (!pixels) {
2370 /* Note: we check for a NULL image pointer here, _after_ we allocated
2371 * memory for the texture. That's what the GL spec calls for.
2372 */
2373 return;
2374 }
2375 else {
2376 const GLint dstRowStride = 0, dstImageStride = 0;
2377 GLboolean success;
2378 ASSERT(texImage->TexFormat->StoreImage);
2379 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
2380 texImage->TexFormat,
2381 texImage->Data,
2382 0, 0, 0, /* dstX/Y/Zoffset */
2383 dstRowStride, dstImageStride,
2384 width, 1, 1,
2385 format, type, pixels, packing);
2386 if (!success) {
2387 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2388 }
2389 }
2390
2391 /* GL_SGIS_generate_mipmap */
2392 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2393 _mesa_generate_mipmap(ctx, target,
2394 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2395 texObj);
2396 }
2397
2398 _mesa_unmap_teximage_pbo(ctx, packing);
2399 }
2400
2401
2402 /**
2403 * This is the software fallback for Driver.TexImage2D()
2404 * and Driver.CopyTexImage2D().
2405 * We store the image in heap memory. We know nothing about on-board
2406 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2407 * textures in main memory, this routine will typically be used by
2408 * hardware drivers too.
2409 *
2410 * Reasons why a driver might override this function:
2411 * - Special memory allocation needs (VRAM, AGP, etc)
2412 * - Unusual row/image strides or padding
2413 * - Special housekeeping
2414 * - Using VRAM-based Pixel Buffer Objects
2415 */
2416 void
2417 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2418 GLint internalFormat,
2419 GLint width, GLint height, GLint border,
2420 GLenum format, GLenum type, const void *pixels,
2421 const struct gl_pixelstore_attrib *packing,
2422 struct gl_texture_object *texObj,
2423 struct gl_texture_image *texImage)
2424 {
2425 GLint postConvWidth = width, postConvHeight = height;
2426 GLint texelBytes, sizeInBytes;
2427 (void) border;
2428
2429 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2430 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2431 &postConvHeight);
2432 }
2433
2434 /* choose the texture format */
2435 assert(ctx->Driver.ChooseTextureFormat);
2436 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2437 internalFormat, format, type);
2438 assert(texImage->TexFormat);
2439 set_fetch_functions(texImage, 2);
2440
2441 texelBytes = texImage->TexFormat->TexelBytes;
2442
2443 /* allocate memory */
2444 if (texImage->IsCompressed)
2445 sizeInBytes = texImage->CompressedSize;
2446 else
2447 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
2448 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2449 if (!texImage->Data) {
2450 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2451 return;
2452 }
2453
2454 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2455 pixels, packing, "glTexImage2D");
2456 if (!pixels) {
2457 /* Note: we check for a NULL image pointer here, _after_ we allocated
2458 * memory for the texture. That's what the GL spec calls for.
2459 */
2460 return;
2461 }
2462 else {
2463 GLint dstRowStride, dstImageStride = 0;
2464 GLboolean success;
2465 if (texImage->IsCompressed) {
2466 dstRowStride
2467 = _mesa_compressed_row_stride(texImage->InternalFormat,width);
2468 }
2469 else {
2470 dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
2471 }
2472 ASSERT(texImage->TexFormat->StoreImage);
2473 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
2474 texImage->TexFormat,
2475 texImage->Data,
2476 0, 0, 0, /* dstX/Y/Zoffset */
2477 dstRowStride, dstImageStride,
2478 width, height, 1,
2479 format, type, pixels, packing);
2480 if (!success) {
2481 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2482 }
2483 }
2484
2485 /* GL_SGIS_generate_mipmap */
2486 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2487 _mesa_generate_mipmap(ctx, target,
2488 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2489 texObj);
2490 }
2491
2492 _mesa_unmap_teximage_pbo(ctx, packing);
2493 }
2494
2495
2496
2497 /**
2498 * This is the software fallback for Driver.TexImage3D()
2499 * and Driver.CopyTexImage3D().
2500 * \sa _mesa_store_teximage2d()
2501 */
2502 void
2503 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2504 GLint internalFormat,
2505 GLint width, GLint height, GLint depth, GLint border,
2506 GLenum format, GLenum type, const void *pixels,
2507 const struct gl_pixelstore_attrib *packing,
2508 struct gl_texture_object *texObj,
2509 struct gl_texture_image *texImage)
2510 {
2511 GLint texelBytes, sizeInBytes;
2512 (void) border;
2513
2514 /* choose the texture format */
2515 assert(ctx->Driver.ChooseTextureFormat);
2516 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2517 internalFormat, format, type);
2518 assert(texImage->TexFormat);
2519 set_fetch_functions(texImage, 3);
2520
2521 texelBytes = texImage->TexFormat->TexelBytes;
2522
2523 /* allocate memory */
2524 if (texImage->IsCompressed)
2525 sizeInBytes = texImage->CompressedSize;
2526 else
2527 sizeInBytes = width * height * depth * texelBytes;
2528 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2529 if (!texImage->Data) {
2530 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2531 return;
2532 }
2533
2534 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
2535 type, pixels, packing, "glTexImage3D");
2536 if (!pixels) {
2537 /* Note: we check for a NULL image pointer here, _after_ we allocated
2538 * memory for the texture. That's what the GL spec calls for.
2539 */
2540 return;
2541 }
2542 else {
2543 GLint dstRowStride, dstImageStride;
2544 GLboolean success;
2545 if (texImage->IsCompressed) {
2546 dstRowStride
2547 = _mesa_compressed_row_stride(texImage->InternalFormat,width);
2548 dstImageStride = 0;
2549 }
2550 else {
2551 dstRowStride = width * texImage->TexFormat->TexelBytes;
2552 dstImageStride = dstRowStride * height;
2553 }
2554 ASSERT(texImage->TexFormat->StoreImage);
2555 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
2556 texImage->TexFormat,
2557 texImage->Data,
2558 0, 0, 0, /* dstX/Y/Zoffset */
2559 dstRowStride, dstImageStride,
2560 width, height, depth,
2561 format, type, pixels, packing);
2562 if (!success) {
2563 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2564 }
2565 }
2566
2567 /* GL_SGIS_generate_mipmap */
2568 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2569 _mesa_generate_mipmap(ctx, target,
2570 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2571 texObj);
2572 }
2573
2574 _mesa_unmap_teximage_pbo(ctx, packing);
2575 }
2576
2577
2578
2579
2580 /*
2581 * This is the software fallback for Driver.TexSubImage1D()
2582 * and Driver.CopyTexSubImage1D().
2583 */
2584 void
2585 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
2586 GLint xoffset, GLint width,
2587 GLenum format, GLenum type, const void *pixels,
2588 const struct gl_pixelstore_attrib *packing,
2589 struct gl_texture_object *texObj,
2590 struct gl_texture_image *texImage)
2591 {
2592 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2593 pixels, packing, "glTexSubImage1D");
2594 if (!pixels)
2595 return;
2596
2597 {
2598 const GLint dstRowStride = 0, dstImageStride = 0;
2599 GLboolean success;
2600 ASSERT(texImage->TexFormat->StoreImage);
2601 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
2602 texImage->TexFormat,
2603 texImage->Data,
2604 xoffset, 0, 0, /* offsets */
2605 dstRowStride, dstImageStride,
2606 width, 1, 1,
2607 format, type, pixels, packing);
2608 if (!success) {
2609 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
2610 }
2611 }
2612
2613 /* GL_SGIS_generate_mipmap */
2614 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2615 _mesa_generate_mipmap(ctx, target,
2616 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2617 texObj);
2618 }
2619
2620 _mesa_unmap_teximage_pbo(ctx, packing);
2621 }
2622
2623
2624
2625 /**
2626 * This is the software fallback for Driver.TexSubImage2D()
2627 * and Driver.CopyTexSubImage2D().
2628 */
2629 void
2630 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
2631 GLint xoffset, GLint yoffset,
2632 GLint width, GLint height,
2633 GLenum format, GLenum type, const void *pixels,
2634 const struct gl_pixelstore_attrib *packing,
2635 struct gl_texture_object *texObj,
2636 struct gl_texture_image *texImage)
2637 {
2638 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2639 pixels, packing, "glTexSubImage2D");
2640 if (!pixels)
2641 return;
2642
2643 {
2644 GLint dstRowStride = 0, dstImageStride = 0;
2645 GLboolean success;
2646 if (texImage->IsCompressed) {
2647 dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
2648 texImage->Width);
2649 }
2650 else {
2651 dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2652 }
2653 ASSERT(texImage->TexFormat->StoreImage);
2654 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
2655 texImage->TexFormat,
2656 texImage->Data,
2657 xoffset, yoffset, 0,
2658 dstRowStride, dstImageStride,
2659 width, height, 1,
2660 format, type, pixels, packing);
2661 if (!success) {
2662 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2663 }
2664 }
2665
2666 /* GL_SGIS_generate_mipmap */
2667 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2668 _mesa_generate_mipmap(ctx, target,
2669 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2670 texObj);
2671 }
2672
2673 _mesa_unmap_teximage_pbo(ctx, packing);
2674 }
2675
2676
2677 /*
2678 * This is the software fallback for Driver.TexSubImage3D().
2679 * and Driver.CopyTexSubImage3D().
2680 */
2681 void
2682 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
2683 GLint xoffset, GLint yoffset, GLint zoffset,
2684 GLint width, GLint height, GLint depth,
2685 GLenum format, GLenum type, const void *pixels,
2686 const struct gl_pixelstore_attrib *packing,
2687 struct gl_texture_object *texObj,
2688 struct gl_texture_image *texImage)
2689 {
2690 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
2691 type, pixels, packing,
2692 "glTexSubImage3D");
2693 if (!pixels)
2694 return;
2695
2696 {
2697 GLint dstRowStride, dstImageStride;
2698 GLboolean success;
2699 if (texImage->IsCompressed) {
2700 dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
2701 texImage->Width);
2702 dstImageStride = 0; /* XXX fix */
2703 }
2704 else {
2705 dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2706 dstImageStride = dstRowStride * texImage->Height;
2707 }
2708 ASSERT(texImage->TexFormat->StoreImage);
2709 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
2710 texImage->TexFormat,
2711 texImage->Data,
2712 xoffset, yoffset, zoffset,
2713 dstRowStride, dstImageStride,
2714 width, height, depth,
2715 format, type, pixels, packing);
2716 if (!success) {
2717 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
2718 }
2719 }
2720
2721 /* GL_SGIS_generate_mipmap */
2722 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2723 _mesa_generate_mipmap(ctx, target,
2724 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2725 texObj);
2726 }
2727
2728 _mesa_unmap_teximage_pbo(ctx, packing);
2729 }
2730
2731
2732 /*
2733 * Fallback for Driver.CompressedTexImage1D()
2734 */
2735 void
2736 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2737 GLint internalFormat,
2738 GLint width, GLint border,
2739 GLsizei imageSize, const GLvoid *data,
2740 struct gl_texture_object *texObj,
2741 struct gl_texture_image *texImage)
2742 {
2743 /* this space intentionally left blank */
2744 (void) ctx;
2745 (void) target; (void) level;
2746 (void) internalFormat;
2747 (void) width; (void) border;
2748 (void) imageSize; (void) data;
2749 (void) texObj;
2750 (void) texImage;
2751 }
2752
2753
2754
2755 /*
2756 * Fallback for Driver.CompressedTexImage2D()
2757 */
2758 void
2759 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2760 GLint internalFormat,
2761 GLint width, GLint height, GLint border,
2762 GLsizei imageSize, const GLvoid *data,
2763 struct gl_texture_object *texObj,
2764 struct gl_texture_image *texImage)
2765 {
2766 (void) width; (void) height; (void) border;
2767
2768 /* This is pretty simple, basically just do a memcpy without worrying
2769 * about the usual image unpacking or image transfer operations.
2770 */
2771 ASSERT(texObj);
2772 ASSERT(texImage);
2773 ASSERT(texImage->Width > 0);
2774 ASSERT(texImage->Height > 0);
2775 ASSERT(texImage->Depth == 1);
2776 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
2777
2778 /* choose the texture format */
2779 assert(ctx->Driver.ChooseTextureFormat);
2780 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2781 internalFormat, 0, 0);
2782 assert(texImage->TexFormat);
2783 set_fetch_functions(texImage, 2);
2784
2785 /* allocate storage */
2786 texImage->Data = _mesa_alloc_texmemory(imageSize);
2787 if (!texImage->Data) {
2788 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2789 return;
2790 }
2791
2792 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
2793 &ctx->Unpack,
2794 "glCompressedTexImage2D");
2795 if (!data)
2796 return;
2797
2798 /* copy the data */
2799 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
2800 MEMCPY(texImage->Data, data, imageSize);
2801
2802 /* GL_SGIS_generate_mipmap */
2803 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2804 _mesa_generate_mipmap(ctx, target,
2805 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2806 texObj);
2807 }
2808
2809 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
2810 }
2811
2812
2813
2814 /*
2815 * Fallback for Driver.CompressedTexImage3D()
2816 */
2817 void
2818 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2819 GLint internalFormat,
2820 GLint width, GLint height, GLint depth,
2821 GLint border,
2822 GLsizei imageSize, const GLvoid *data,
2823 struct gl_texture_object *texObj,
2824 struct gl_texture_image *texImage)
2825 {
2826 /* this space intentionally left blank */
2827 (void) ctx;
2828 (void) target; (void) level;
2829 (void) internalFormat;
2830 (void) width; (void) height; (void) depth;
2831 (void) border;
2832 (void) imageSize; (void) data;
2833 (void) texObj;
2834 (void) texImage;
2835 }
2836
2837
2838
2839 /**
2840 * Fallback for Driver.CompressedTexSubImage1D()
2841 */
2842 void
2843 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
2844 GLint level,
2845 GLint xoffset, GLsizei width,
2846 GLenum format,
2847 GLsizei imageSize, const GLvoid *data,
2848 struct gl_texture_object *texObj,
2849 struct gl_texture_image *texImage)
2850 {
2851 /* this space intentionally left blank */
2852 (void) ctx;
2853 (void) target; (void) level;
2854 (void) xoffset; (void) width;
2855 (void) format;
2856 (void) imageSize; (void) data;
2857 (void) texObj;
2858 (void) texImage;
2859 }
2860
2861
2862 /**
2863 * Fallback for Driver.CompressedTexSubImage2D()
2864 */
2865 void
2866 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
2867 GLint level,
2868 GLint xoffset, GLint yoffset,
2869 GLsizei width, GLsizei height,
2870 GLenum format,
2871 GLsizei imageSize, const GLvoid *data,
2872 struct gl_texture_object *texObj,
2873 struct gl_texture_image *texImage)
2874 {
2875 GLint bytesPerRow, destRowStride, srcRowStride;
2876 GLint i, rows;
2877 GLubyte *dest;
2878 const GLubyte *src;
2879 (void) format;
2880
2881 /* these should have been caught sooner */
2882 ASSERT((width & 3) == 0 || width == 2 || width == 1);
2883 ASSERT((height & 3) == 0 || height == 2 || height == 1);
2884 ASSERT((xoffset & 3) == 0);
2885 ASSERT((yoffset & 3) == 0);
2886
2887 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
2888 &ctx->Unpack,
2889 "glCompressedTexSubImage2D");
2890 if (!data)
2891 return;
2892
2893 srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, width);
2894 src = (const GLubyte *) data;
2895
2896 destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
2897 texImage->Width);
2898 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
2899 texImage->InternalFormat,
2900 texImage->Width,
2901 (GLubyte*) texImage->Data);
2902
2903 bytesPerRow = srcRowStride;
2904 rows = height / 4;
2905
2906 for (i = 0; i < rows; i++) {
2907 MEMCPY(dest, src, bytesPerRow);
2908 dest += destRowStride;
2909 src += srcRowStride;
2910 }
2911
2912 /* GL_SGIS_generate_mipmap */
2913 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2914 _mesa_generate_mipmap(ctx, target,
2915 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2916 texObj);
2917 }
2918
2919 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
2920 }
2921
2922
2923 /**
2924 * Fallback for Driver.CompressedTexSubImage3D()
2925 */
2926 void
2927 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
2928 GLint level,
2929 GLint xoffset, GLint yoffset, GLint zoffset,
2930 GLsizei width, GLsizei height, GLsizei depth,
2931 GLenum format,
2932 GLsizei imageSize, const GLvoid *data,
2933 struct gl_texture_object *texObj,
2934 struct gl_texture_image *texImage)
2935 {
2936 /* this space intentionally left blank */
2937 (void) ctx;
2938 (void) target; (void) level;
2939 (void) xoffset; (void) yoffset; (void) zoffset;
2940 (void) width; (void) height; (void) depth;
2941 (void) format;
2942 (void) imageSize; (void) data;
2943 (void) texObj;
2944 (void) texImage;
2945 }
2946
2947
2948 /*
2949 * Average together two rows of a source image to produce a single new
2950 * row in the dest image. It's legal for the two source rows to point
2951 * to the same data. The source width must be equal to either the
2952 * dest width or two times the dest width.
2953 */
2954 static void
2955 do_row(const struct gl_texture_format *format, GLint srcWidth,
2956 const GLvoid *srcRowA, const GLvoid *srcRowB,
2957 GLint dstWidth, GLvoid *dstRow)
2958 {
2959 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
2960 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
2961
2962 /* This assertion is no longer valid with non-power-of-2 textures
2963 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2964 */
2965
2966 switch (format->MesaFormat) {
2967 case MESA_FORMAT_RGBA:
2968 {
2969 GLuint i, j, k;
2970 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
2971 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
2972 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
2973 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2974 i++, j += colStride, k += colStride) {
2975 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2976 rowB[j][0] + rowB[k][0]) / 4;
2977 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2978 rowB[j][1] + rowB[k][1]) / 4;
2979 dst[i][2] = (rowA[j][2] + rowA[k][2] +
2980 rowB[j][2] + rowB[k][2]) / 4;
2981 dst[i][3] = (rowA[j][3] + rowA[k][3] +
2982 rowB[j][3] + rowB[k][3]) / 4;
2983 }
2984 }
2985 return;
2986 case MESA_FORMAT_RGB:
2987 {
2988 GLuint i, j, k;
2989 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
2990 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
2991 GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
2992 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2993 i++, j += colStride, k += colStride) {
2994 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2995 rowB[j][0] + rowB[k][0]) / 4;
2996 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2997 rowB[j][1] + rowB[k][1]) / 4;
2998 dst[i][2] = (rowA[j][2] + rowA[k][2] +
2999 rowB[j][2] + rowB[k][2]) / 4;
3000 }
3001 }
3002 return;
3003 case MESA_FORMAT_ALPHA:
3004 case MESA_FORMAT_LUMINANCE:
3005 case MESA_FORMAT_INTENSITY:
3006 {
3007 GLuint i, j, k;
3008 const GLchan *rowA = (const GLchan *) srcRowA;
3009 const GLchan *rowB = (const GLchan *) srcRowB;
3010 GLchan *dst = (GLchan *) dstRow;
3011 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3012 i++, j += colStride, k += colStride) {
3013 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
3014 }
3015 }
3016 return;
3017 case MESA_FORMAT_LUMINANCE_ALPHA:
3018 {
3019 GLuint i, j, k;
3020 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
3021 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
3022 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
3023 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3024 i++, j += colStride, k += colStride) {
3025 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3026 rowB[j][0] + rowB[k][0]) / 4;
3027 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3028 rowB[j][1] + rowB[k][1]) / 4;
3029 }
3030 }
3031 return;
3032 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32:
3033 {
3034 GLuint i, j, k;
3035 const GLfloat *rowA = (const GLfloat *) srcRowA;
3036 const GLfloat *rowB = (const GLfloat *) srcRowB;
3037 GLfloat *dst = (GLfloat *) dstRow;
3038 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3039 i++, j += colStride, k += colStride) {
3040 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
3041 }
3042 }
3043 return;
3044 case MESA_FORMAT_DEPTH_COMPONENT16:
3045 {
3046 GLuint i, j, k;
3047 const GLushort *rowA = (const GLushort *) srcRowA;
3048 const GLushort *rowB = (const GLushort *) srcRowB;
3049 GLushort *dst = (GLushort *) dstRow;
3050 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3051 i++, j += colStride, k += colStride) {
3052 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
3053 }
3054 }
3055 return;
3056 /* Begin hardware formats */
3057 case MESA_FORMAT_RGBA8888:
3058 case MESA_FORMAT_RGBA8888_REV:
3059 case MESA_FORMAT_ARGB8888:
3060 case MESA_FORMAT_ARGB8888_REV:
3061 {
3062 GLuint i, j, k;
3063 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
3064 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
3065 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
3066 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3067 i++, j += colStride, k += colStride) {
3068 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3069 rowB[j][0] + rowB[k][0]) / 4;
3070 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3071 rowB[j][1] + rowB[k][1]) / 4;
3072 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3073 rowB[j][2] + rowB[k][2]) / 4;
3074 dst[i][3] = (rowA[j][3] + rowA[k][3] +
3075 rowB[j][3] + rowB[k][3]) / 4;
3076 }
3077 }
3078 return;
3079 case MESA_FORMAT_RGB888:
3080 case MESA_FORMAT_BGR888:
3081 {
3082 GLuint i, j, k;
3083 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
3084 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
3085 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
3086 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3087 i++, j += colStride, k += colStride) {
3088 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3089 rowB[j][0] + rowB[k][0]) / 4;
3090 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3091 rowB[j][1] + rowB[k][1]) / 4;
3092 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3093 rowB[j][2] + rowB[k][2]) / 4;
3094 }
3095 }
3096 return;
3097 case MESA_FORMAT_RGB565:
3098 case MESA_FORMAT_RGB565_REV:
3099 {
3100 GLuint i, j, k;
3101 const GLushort *rowA = (const GLushort *) srcRowA;
3102 const GLushort *rowB = (const GLushort *) srcRowB;
3103 GLushort *dst = (GLushort *) dstRow;
3104 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3105 i++, j += colStride, k += colStride) {
3106 const GLint rowAr0 = rowA[j] & 0x1f;
3107 const GLint rowAr1 = rowA[k] & 0x1f;
3108 const GLint rowBr0 = rowB[j] & 0x1f;
3109 const GLint rowBr1 = rowB[k] & 0x1f;
3110 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
3111 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
3112 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
3113 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
3114 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
3115 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
3116 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
3117 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
3118 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3119 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3120 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3121 dst[i] = (blue << 11) | (green << 5) | red;
3122 }
3123 }
3124 return;
3125 case MESA_FORMAT_ARGB4444:
3126 case MESA_FORMAT_ARGB4444_REV:
3127 {
3128 GLuint i, j, k;
3129 const GLushort *rowA = (const GLushort *) srcRowA;
3130 const GLushort *rowB = (const GLushort *) srcRowB;
3131 GLushort *dst = (GLushort *) dstRow;
3132 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3133 i++, j += colStride, k += colStride) {
3134 const GLint rowAr0 = rowA[j] & 0xf;
3135 const GLint rowAr1 = rowA[k] & 0xf;
3136 const GLint rowBr0 = rowB[j] & 0xf;
3137 const GLint rowBr1 = rowB[k] & 0xf;
3138 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
3139 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
3140 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
3141 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
3142 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
3143 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
3144 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
3145 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
3146 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
3147 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
3148 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
3149 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
3150 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3151 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3152 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3153 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
3154 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
3155 }
3156 }
3157 return;
3158 case MESA_FORMAT_ARGB1555:
3159 case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */
3160 {
3161 GLuint i, j, k;
3162 const GLushort *rowA = (const GLushort *) srcRowA;
3163 const GLushort *rowB = (const GLushort *) srcRowB;
3164 GLushort *dst = (GLushort *) dstRow;
3165 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3166 i++, j += colStride, k += colStride) {
3167 const GLint rowAr0 = rowA[j] & 0x1f;
3168 const GLint rowAr1 = rowA[k] & 0x1f;
3169 const GLint rowBr0 = rowB[j] & 0x1f;
3170 const GLint rowBr1 = rowB[k] & 0xf;
3171 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
3172 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
3173 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
3174 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
3175 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
3176 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
3177 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
3178 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
3179 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
3180 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
3181 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
3182 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
3183 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3184 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3185 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3186 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
3187 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
3188 }
3189 }
3190 return;
3191 case MESA_FORMAT_AL88:
3192 case MESA_FORMAT_AL88_REV:
3193 {
3194 GLuint i, j, k;
3195 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
3196 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
3197 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
3198 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3199 i++, j += colStride, k += colStride) {
3200 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3201 rowB[j][0] + rowB[k][0]) >> 2;
3202 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3203 rowB[j][1] + rowB[k][1]) >> 2;
3204 }
3205 }
3206 return;
3207 case MESA_FORMAT_RGB332:
3208 {
3209 GLuint i, j, k;
3210 const GLubyte *rowA = (const GLubyte *) srcRowA;
3211 const GLubyte *rowB = (const GLubyte *) srcRowB;
3212 GLubyte *dst = (GLubyte *) dstRow;
3213 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3214 i++, j += colStride, k += colStride) {
3215 const GLint rowAr0 = rowA[j] & 0x3;
3216 const GLint rowAr1 = rowA[k] & 0x3;
3217 const GLint rowBr0 = rowB[j] & 0x3;
3218 const GLint rowBr1 = rowB[k] & 0x3;
3219 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
3220 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
3221 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
3222 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
3223 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
3224 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
3225 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
3226 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
3227 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3228 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3229 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3230 dst[i] = (blue << 5) | (green << 2) | red;
3231 }
3232 }
3233 return;
3234 case MESA_FORMAT_A8:
3235 case MESA_FORMAT_L8:
3236 case MESA_FORMAT_I8:
3237 case MESA_FORMAT_CI8:
3238 {
3239 GLuint i, j, k;
3240 const GLubyte *rowA = (const GLubyte *) srcRowA;
3241 const GLubyte *rowB = (const GLubyte *) srcRowB;
3242 GLubyte *dst = (GLubyte *) dstRow;
3243 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3244 i++, j += colStride, k += colStride) {
3245 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
3246 }
3247 }
3248 return;
3249 case MESA_FORMAT_RGBA_FLOAT32:
3250 {
3251 GLuint i, j, k;
3252 const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA;
3253 const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB;
3254 GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow;
3255 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3256 i++, j += colStride, k += colStride) {
3257 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3258 rowB[j][0] + rowB[k][0]) * 0.25F;
3259 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3260 rowB[j][1] + rowB[k][1]) * 0.25F;
3261 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3262 rowB[j][2] + rowB[k][2]) * 0.25F;
3263 dst[i][3] = (rowA[j][3] + rowA[k][3] +
3264 rowB[j][3] + rowB[k][3]) * 0.25F;
3265 }
3266 }
3267 return;
3268 case MESA_FORMAT_RGBA_FLOAT16:
3269 {
3270 GLuint i, j, k, comp;
3271 const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA;
3272 const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB;
3273 GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow;
3274 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3275 i++, j += colStride, k += colStride) {
3276 for (comp = 0; comp < 4; comp++) {
3277 GLfloat aj, ak, bj, bk;
3278 aj = _mesa_half_to_float(rowA[j][comp]);
3279 ak = _mesa_half_to_float(rowA[k][comp]);
3280 bj = _mesa_half_to_float(rowB[j][comp]);
3281 bk = _mesa_half_to_float(rowB[k][comp]);
3282 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3283 }
3284 }
3285 }
3286 return;
3287 case MESA_FORMAT_RGB_FLOAT32:
3288 {
3289 GLuint i, j, k;
3290 const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA;
3291 const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB;
3292 GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow;
3293 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3294 i++, j += colStride, k += colStride) {
3295 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3296 rowB[j][0] + rowB[k][0]) * 0.25F;
3297 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3298 rowB[j][1] + rowB[k][1]) * 0.25F;
3299 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3300 rowB[j][2] + rowB[k][2]) * 0.25F;
3301 }
3302 }
3303 return;
3304 case MESA_FORMAT_RGB_FLOAT16:
3305 {
3306 GLuint i, j, k, comp;
3307 const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA;
3308 const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB;
3309 GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow;
3310 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3311 i++, j += colStride, k += colStride) {
3312 for (comp = 0; comp < 3; comp++) {
3313 GLfloat aj, ak, bj, bk;
3314 aj = _mesa_half_to_float(rowA[j][comp]);
3315 ak = _mesa_half_to_float(rowA[k][comp]);
3316 bj = _mesa_half_to_float(rowB[j][comp]);
3317 bk = _mesa_half_to_float(rowB[k][comp]);
3318 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3319 }
3320 }
3321 }
3322 return;
3323 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
3324 {
3325 GLuint i, j, k;
3326 const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA;
3327 const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB;
3328 GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow;
3329 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3330 i++, j += colStride, k += colStride) {
3331 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3332 rowB[j][0] + rowB[k][0]) * 0.25F;
3333 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3334 rowB[j][1] + rowB[k][1]) * 0.25F;
3335 }
3336 }
3337 return;
3338 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
3339 {
3340 GLuint i, j, k, comp;
3341 const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA;
3342 const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB;
3343 GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow;
3344 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3345 i++, j += colStride, k += colStride) {
3346 for (comp = 0; comp < 2; comp++) {
3347 GLfloat aj, ak, bj, bk;
3348 aj = _mesa_half_to_float(rowA[j][comp]);
3349 ak = _mesa_half_to_float(rowA[k][comp]);
3350 bj = _mesa_half_to_float(rowB[j][comp]);
3351 bk = _mesa_half_to_float(rowB[k][comp]);
3352 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3353 }
3354 }
3355 }
3356 return;
3357 case MESA_FORMAT_ALPHA_FLOAT32:
3358 case MESA_FORMAT_LUMINANCE_FLOAT32:
3359 case MESA_FORMAT_INTENSITY_FLOAT32:
3360 {
3361 GLuint i, j, k;
3362 const GLfloat *rowA = (const GLfloat *) srcRowA;
3363 const GLfloat *rowB = (const GLfloat *) srcRowB;
3364 GLfloat *dst = (GLfloat *) dstRow;
3365 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3366 i++, j += colStride, k += colStride) {
3367 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
3368 }
3369 }
3370 return;
3371 case MESA_FORMAT_ALPHA_FLOAT16:
3372 case MESA_FORMAT_LUMINANCE_FLOAT16:
3373 case MESA_FORMAT_INTENSITY_FLOAT16:
3374 {
3375 GLuint i, j, k;
3376 const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
3377 const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
3378 GLhalfARB *dst = (GLhalfARB *) dstRow;
3379 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3380 i++, j += colStride, k += colStride) {
3381 GLfloat aj, ak, bj, bk;
3382 aj = _mesa_half_to_float(rowA[j]);
3383 ak = _mesa_half_to_float(rowA[k]);
3384 bj = _mesa_half_to_float(rowB[j]);
3385 bk = _mesa_half_to_float(rowB[k]);
3386 dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3387 }
3388 }
3389 return;
3390
3391 default:
3392 _mesa_problem(NULL, "bad format in do_row()");
3393 }
3394 }
3395
3396
3397 /*
3398 * These functions generate a 1/2-size mipmap image from a source image.
3399 * Texture borders are handled by copying or averaging the source image's
3400 * border texels, depending on the scale-down factor.
3401 */
3402
3403 static void
3404 make_1d_mipmap(const struct gl_texture_format *format, GLint border,
3405 GLint srcWidth, const GLubyte *srcPtr,
3406 GLint dstWidth, GLubyte *dstPtr)
3407 {
3408 const GLint bpt = format->TexelBytes;
3409 const GLubyte *src;
3410 GLubyte *dst;
3411
3412 /* skip the border pixel, if any */
3413 src = srcPtr + border * bpt;
3414 dst = dstPtr + border * bpt;
3415
3416 /* we just duplicate the input row, kind of hack, saves code */
3417 do_row(format, srcWidth - 2 * border, src, src,
3418 dstWidth - 2 * border, dst);
3419
3420 if (border) {
3421 /* copy left-most pixel from source */
3422 MEMCPY(dstPtr, srcPtr, bpt);
3423 /* copy right-most pixel from source */
3424 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
3425 srcPtr + (srcWidth - 1) * bpt,
3426 bpt);
3427 }
3428 }
3429
3430
3431 static void
3432 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
3433 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
3434 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
3435 {
3436 const GLint bpt = format->TexelBytes;
3437 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
3438 const GLint dstWidthNB = dstWidth - 2 * border;
3439 const GLint dstHeightNB = dstHeight - 2 * border;
3440 const GLint srcRowStride = bpt * srcWidth;
3441 const GLint dstRowStride = bpt * dstWidth;
3442 const GLubyte *srcA, *srcB;
3443 GLubyte *dst;
3444 GLint row;
3445
3446 /* Compute src and dst pointers, skipping any border */
3447 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
3448 if (srcHeight > 1)
3449 srcB = srcA + srcRowStride;
3450 else
3451 srcB = srcA;
3452 dst = dstPtr + border * ((dstWidth + 1) * bpt);
3453
3454 for (row = 0; row < dstHeightNB; row++) {
3455 do_row(format, srcWidthNB, srcA, srcB,
3456 dstWidthNB, dst);
3457 srcA += 2 * srcRowStride;
3458 srcB += 2 * srcRowStride;
3459 dst += dstRowStride;
3460 }
3461
3462 /* This is ugly but probably won't be used much */
3463 if (border > 0) {
3464 /* fill in dest border */
3465 /* lower-left border pixel */
3466 MEMCPY(dstPtr, srcPtr, bpt);
3467 /* lower-right border pixel */
3468 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
3469 srcPtr + (srcWidth - 1) * bpt, bpt);
3470 /* upper-left border pixel */
3471 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
3472 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
3473 /* upper-right border pixel */
3474 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
3475 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
3476 /* lower border */
3477 do_row(format, srcWidthNB,
3478 srcPtr + bpt,
3479 srcPtr + bpt,
3480 dstWidthNB, dstPtr + bpt);
3481 /* upper border */
3482 do_row(format, srcWidthNB,
3483 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
3484 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
3485 dstWidthNB,
3486 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
3487 /* left and right borders */
3488 if (srcHeight == dstHeight) {
3489 /* copy border pixel from src to dst */
3490 for (row = 1; row < srcHeight; row++) {
3491 MEMCPY(dstPtr + dstWidth * row * bpt,
3492 srcPtr + srcWidth * row * bpt, bpt);
3493 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
3494 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
3495 }
3496 }
3497 else {
3498 /* average two src pixels each dest pixel */
3499 for (row = 0; row < dstHeightNB; row += 2) {
3500 do_row(format, 1,
3501 srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
3502 srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
3503 1, dstPtr + (dstWidth * row + 1) * bpt);
3504 do_row(format, 1,
3505 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
3506 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
3507 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
3508 }
3509 }
3510 }
3511 }
3512
3513
3514 static void
3515 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
3516 GLint srcWidth, GLint srcHeight, GLint srcDepth,
3517 const GLubyte *srcPtr,
3518 GLint dstWidth, GLint dstHeight, GLint dstDepth,
3519 GLubyte *dstPtr)
3520 {
3521 const GLint bpt = format->TexelBytes;
3522 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
3523 const GLint srcDepthNB = srcDepth - 2 * border;
3524 const GLint dstWidthNB = dstWidth - 2 * border;
3525 const GLint dstHeightNB = dstHeight - 2 * border;
3526 const GLint dstDepthNB = dstDepth - 2 * border;
3527 GLvoid *tmpRowA, *tmpRowB;
3528 GLint img, row;
3529 GLint bytesPerSrcImage, bytesPerDstImage;
3530 GLint bytesPerSrcRow, bytesPerDstRow;
3531 GLint srcImageOffset, srcRowOffset;
3532
3533 (void) srcDepthNB; /* silence warnings */
3534
3535 /* Need two temporary row buffers */
3536 tmpRowA = _mesa_malloc(srcWidth * bpt);
3537 if (!tmpRowA)
3538 return;
3539 tmpRowB = _mesa_malloc(srcWidth * bpt);
3540 if (!tmpRowB) {
3541 _mesa_free(tmpRowA);
3542 return;
3543 }
3544
3545 bytesPerSrcImage = srcWidth * srcHeight * bpt;
3546 bytesPerDstImage = dstWidth * dstHeight * bpt;
3547
3548 bytesPerSrcRow = srcWidth * bpt;
3549 bytesPerDstRow = dstWidth * bpt;
3550
3551 /* Offset between adjacent src images to be averaged together */
3552 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
3553
3554 /* Offset between adjacent src rows to be averaged together */
3555 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
3556
3557 /*
3558 * Need to average together up to 8 src pixels for each dest pixel.
3559 * Break that down into 3 operations:
3560 * 1. take two rows from source image and average them together.
3561 * 2. take two rows from next source image and average them together.
3562 * 3. take the two averaged rows and average them for the final dst row.
3563 */
3564
3565 /*
3566 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3567 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3568 */
3569
3570 for (img = 0; img < dstDepthNB; img++) {
3571 /* first source image pointer, skipping border */
3572 const GLubyte *imgSrcA = srcPtr
3573 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
3574 + img * (bytesPerSrcImage + srcImageOffset);
3575 /* second source image pointer, skipping border */
3576 const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
3577 /* address of the dest image, skipping border */
3578 GLubyte *imgDst = dstPtr
3579 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
3580 + img * bytesPerDstImage;
3581
3582 /* setup the four source row pointers and the dest row pointer */
3583 const GLubyte *srcImgARowA = imgSrcA;
3584 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
3585 const GLubyte *srcImgBRowA = imgSrcB;
3586 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
3587 GLubyte *dstImgRow = imgDst;
3588
3589 for (row = 0; row < dstHeightNB; row++) {
3590 /* Average together two rows from first src image */
3591 do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
3592 srcWidthNB, tmpRowA);
3593 /* Average together two rows from second src image */
3594 do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
3595 srcWidthNB, tmpRowB);
3596 /* Average together the temp rows to make the final row */
3597 do_row(format, srcWidthNB, tmpRowA, tmpRowB,
3598 dstWidthNB, dstImgRow);
3599 /* advance to next rows */
3600 srcImgARowA += bytesPerSrcRow + srcRowOffset;
3601 srcImgARowB += bytesPerSrcRow + srcRowOffset;
3602 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
3603 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
3604 dstImgRow += bytesPerDstRow;
3605 }
3606 }
3607
3608 _mesa_free(tmpRowA);
3609 _mesa_free(tmpRowB);
3610
3611 /* Luckily we can leverage the make_2d_mipmap() function here! */
3612 if (border > 0) {
3613 /* do front border image */
3614 make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
3615 dstWidth, dstHeight, dstPtr);
3616 /* do back border image */
3617 make_2d_mipmap(format, 1, srcWidth, srcHeight,
3618 srcPtr + bytesPerSrcImage * (srcDepth - 1),
3619 dstWidth, dstHeight,
3620 dstPtr + bytesPerDstImage * (dstDepth - 1));
3621 /* do four remaining border edges that span the image slices */
3622 if (srcDepth == dstDepth) {
3623 /* just copy border pixels from src to dst */
3624 for (img = 0; img < dstDepthNB; img++) {
3625 const GLubyte *src;
3626 GLubyte *dst;
3627
3628 /* do border along [img][row=0][col=0] */
3629 src = srcPtr + (img + 1) * bytesPerSrcImage;
3630 dst = dstPtr + (img + 1) * bytesPerDstImage;
3631 MEMCPY(dst, src, bpt);
3632
3633 /* do border along [img][row=dstHeight-1][col=0] */
3634 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3635 + (srcHeight - 1) * bytesPerSrcRow;
3636 dst = dstPtr + (img + 1) * bytesPerDstImage
3637 + (dstHeight - 1) * bytesPerDstRow;
3638 MEMCPY(dst, src, bpt);
3639
3640 /* do border along [img][row=0][col=dstWidth-1] */
3641 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3642 + (srcWidth - 1) * bpt;
3643 dst = dstPtr + (img + 1) * bytesPerDstImage
3644 + (dstWidth - 1) * bpt;
3645 MEMCPY(dst, src, bpt);
3646
3647 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3648 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3649 + (bytesPerSrcImage - bpt);
3650 dst = dstPtr + (img + 1) * bytesPerDstImage
3651 + (bytesPerDstImage - bpt);
3652 MEMCPY(dst, src, bpt);
3653 }
3654 }
3655 else {
3656 /* average border pixels from adjacent src image pairs */
3657 ASSERT(srcDepthNB == 2 * dstDepthNB);
3658 for (img = 0; img < dstDepthNB; img++) {
3659 const GLubyte *src;
3660 GLubyte *dst;
3661
3662 /* do border along [img][row=0][col=0] */
3663 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
3664 dst = dstPtr + (img + 1) * bytesPerDstImage;
3665 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3666
3667 /* do border along [img][row=dstHeight-1][col=0] */
3668 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3669 + (srcHeight - 1) * bytesPerSrcRow;
3670 dst = dstPtr + (img + 1) * bytesPerDstImage
3671 + (dstHeight - 1) * bytesPerDstRow;
3672 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3673
3674 /* do border along [img][row=0][col=dstWidth-1] */
3675 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3676 + (srcWidth - 1) * bpt;
3677 dst = dstPtr + (img + 1) * bytesPerDstImage
3678 + (dstWidth - 1) * bpt;
3679 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3680
3681 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3682 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3683 + (bytesPerSrcImage - bpt);
3684 dst = dstPtr + (img + 1) * bytesPerDstImage
3685 + (bytesPerDstImage - bpt);
3686 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3687 }
3688 }
3689 }
3690 }
3691
3692
3693 /*
3694 * For GL_SGIX_generate_mipmap:
3695 * Generate a complete set of mipmaps from texObj's base-level image.
3696 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3697 */
3698 void
3699 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
3700 const struct gl_texture_unit *texUnit,
3701 struct gl_texture_object *texObj)
3702 {
3703 const struct gl_texture_image *srcImage;
3704 const struct gl_texture_format *convertFormat;
3705 const GLubyte *srcData = NULL;
3706 GLubyte *dstData = NULL;
3707 GLint level, maxLevels;
3708
3709 ASSERT(texObj);
3710 /* XXX choose cube map face here??? */
3711 srcImage = texObj->Image[0][texObj->BaseLevel];
3712 ASSERT(srcImage);
3713
3714 maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
3715 ASSERT(maxLevels > 0); /* bad target */
3716
3717 /* Find convertFormat - the format that do_row() will process */
3718 if (srcImage->IsCompressed) {
3719 /* setup for compressed textures */
3720 GLuint row;
3721 GLint components, size;
3722 GLchan *dst;
3723
3724 assert(texObj->Target == GL_TEXTURE_2D);
3725
3726 if (srcImage->_BaseFormat == GL_RGB) {
3727 convertFormat = &_mesa_texformat_rgb;
3728 components = 3;
3729 }
3730 else if (srcImage->_BaseFormat == GL_RGBA) {
3731 convertFormat = &_mesa_texformat_rgba;
3732 components = 4;
3733 }
3734 else {
3735 _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
3736 return;
3737 }
3738
3739 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3740 size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
3741 * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
3742 /* 20 extra bytes, just be safe when calling last FetchTexel */
3743 srcData = (GLubyte *) _mesa_malloc(size);
3744 if (!srcData) {
3745 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3746 return;
3747 }
3748 dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */
3749 if (!dstData) {
3750 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3751 _mesa_free((void *) srcData);
3752 return;
3753 }
3754
3755 /* decompress base image here */
3756 dst = (GLchan *) srcData;
3757 for (row = 0; row < srcImage->Height; row++) {
3758 GLuint col;
3759 for (col = 0; col < srcImage->Width; col++) {
3760 srcImage->FetchTexelc(srcImage, col, row, 0, dst);
3761 dst += components;
3762 }
3763 }
3764 }
3765 else {
3766 /* uncompressed */
3767 convertFormat = srcImage->TexFormat;
3768 }
3769
3770 for (level = texObj->BaseLevel; level < texObj->MaxLevel
3771 && level < maxLevels - 1; level++) {
3772 /* generate image[level+1] from image[level] */
3773 const struct gl_texture_image *srcImage;
3774 struct gl_texture_image *dstImage;
3775 GLint srcWidth, srcHeight, srcDepth;
3776 GLint dstWidth, dstHeight, dstDepth;
3777 GLint border, bytesPerTexel;
3778
3779 /* get src image parameters */
3780 srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3781 ASSERT(srcImage);
3782 srcWidth = srcImage->Width;
3783 srcHeight = srcImage->Height;
3784 srcDepth = srcImage->Depth;
3785 border = srcImage->Border;
3786
3787 /* compute next (level+1) image size */
3788 if (srcWidth - 2 * border > 1) {
3789 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
3790 }
3791 else {
3792 dstWidth = srcWidth; /* can't go smaller */
3793 }
3794 if (srcHeight - 2 * border > 1) {
3795 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
3796 }
3797 else {
3798 dstHeight = srcHeight; /* can't go smaller */
3799 }
3800 if (srcDepth - 2 * border > 1) {
3801 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
3802 }
3803 else {
3804 dstDepth = srcDepth; /* can't go smaller */
3805 }
3806
3807 if (dstWidth == srcWidth &&
3808 dstHeight == srcHeight &&
3809 dstDepth == srcDepth) {
3810 /* all done */
3811 if (srcImage->IsCompressed) {
3812 _mesa_free((void *) srcData);
3813 _mesa_free(dstData);
3814 }
3815 return;
3816 }
3817
3818 /* get dest gl_texture_image */
3819 dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
3820 if (!dstImage) {
3821 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3822 return;
3823 }
3824
3825 /* Free old image data */
3826 if (dstImage->Data)
3827 ctx->Driver.FreeTexImageData(ctx, dstImage);
3828
3829 /* initialize new image */
3830 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
3831 dstDepth, border, srcImage->InternalFormat);
3832 dstImage->DriverData = NULL;
3833 dstImage->TexFormat = srcImage->TexFormat;
3834 dstImage->FetchTexelc = srcImage->FetchTexelc;
3835 dstImage->FetchTexelf = srcImage->FetchTexelf;
3836 ASSERT(dstImage->TexFormat);
3837 ASSERT(dstImage->FetchTexelc);
3838 ASSERT(dstImage->FetchTexelf);
3839
3840 /* Alloc new teximage data buffer.
3841 * Setup src and dest data pointers.
3842 */
3843 if (dstImage->IsCompressed) {
3844 ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
3845 dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize);
3846 if (!dstImage->Data) {
3847 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3848 return;
3849 }
3850 /* srcData and dstData are already set */
3851 ASSERT(srcData);
3852 ASSERT(dstData);
3853 }
3854 else {
3855 bytesPerTexel = srcImage->TexFormat->TexelBytes;
3856 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
3857 dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight
3858 * dstDepth * bytesPerTexel);
3859 if (!dstImage->Data) {
3860 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3861 return;
3862 }
3863 srcData = (const GLubyte *) srcImage->Data;
3864 dstData = (GLubyte *) dstImage->Data;
3865 }
3866
3867 /*
3868 * We use simple 2x2 averaging to compute the next mipmap level.
3869 */
3870 switch (target) {
3871 case GL_TEXTURE_1D:
3872 make_1d_mipmap(convertFormat, border,
3873 srcWidth, srcData,
3874 dstWidth, dstData);
3875 break;
3876 case GL_TEXTURE_2D:
3877 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3878 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3879 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3880 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3881 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3882 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3883 make_2d_mipmap(convertFormat, border,
3884 srcWidth, srcHeight, srcData,
3885 dstWidth, dstHeight, dstData);
3886 break;
3887 case GL_TEXTURE_3D:
3888 make_3d_mipmap(convertFormat, border,
3889 srcWidth, srcHeight, srcDepth, srcData,
3890 dstWidth, dstHeight, dstDepth, dstData);
3891 break;
3892 case GL_TEXTURE_RECTANGLE_NV:
3893 /* no mipmaps, do nothing */
3894 break;
3895 default:
3896 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
3897 return;
3898 }
3899
3900 if (dstImage->IsCompressed) {
3901 GLubyte *temp;
3902 /* compress image from dstData into dstImage->Data */
3903 const GLenum srcFormat = convertFormat->BaseFormat;
3904 GLint dstRowStride
3905 = _mesa_compressed_row_stride(srcImage->InternalFormat, dstWidth);
3906 ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
3907 dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat,
3908 dstImage->TexFormat,
3909 dstImage->Data,
3910 0, 0, 0, /* dstX/Y/Zoffset */
3911 dstRowStride, 0, /* strides */
3912 dstWidth, dstHeight, 1, /* size */
3913 srcFormat, CHAN_TYPE,
3914 dstData, /* src data, actually */
3915 &ctx->DefaultPacking);
3916 /* swap src and dest pointers */
3917 temp = (GLubyte *) srcData;
3918 srcData = dstData;
3919 dstData = temp;
3920 }
3921
3922 } /* loop over mipmap levels */
3923 }
3924
3925
3926 /**
3927 * Helper function for drivers which need to rescale texture images to
3928 * certain aspect ratios.
3929 * Nearest filtering only (for broken hardware that can't support
3930 * all aspect ratios). This can be made a lot faster, but I don't
3931 * really care enough...
3932 */
3933 void
3934 _mesa_rescale_teximage2d (GLuint bytesPerPixel,
3935 GLuint srcStrideInPixels,
3936 GLuint dstRowStride,
3937 GLint srcWidth, GLint srcHeight,
3938 GLint dstWidth, GLint dstHeight,
3939 const GLvoid *srcImage, GLvoid *dstImage)
3940 {
3941 GLint row, col;
3942
3943 #define INNER_LOOP( TYPE, HOP, WOP ) \
3944 for ( row = 0 ; row < dstHeight ; row++ ) { \
3945 GLint srcRow = row HOP hScale; \
3946 for ( col = 0 ; col < dstWidth ; col++ ) { \
3947 GLint srcCol = col WOP wScale; \
3948 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3949 } \
3950 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3951 } \
3952
3953 #define RESCALE_IMAGE( TYPE ) \
3954 do { \
3955 const TYPE *src = (const TYPE *)srcImage; \
3956 TYPE *dst = (TYPE *)dstImage; \
3957 \
3958 if ( srcHeight < dstHeight ) { \
3959 const GLint hScale = dstHeight / srcHeight; \
3960 if ( srcWidth < dstWidth ) { \
3961 const GLint wScale = dstWidth / srcWidth; \
3962 INNER_LOOP( TYPE, /, / ); \
3963 } \
3964 else { \
3965 const GLint wScale = srcWidth / dstWidth; \
3966 INNER_LOOP( TYPE, /, * ); \
3967 } \
3968 } \
3969 else { \
3970 const GLint hScale = srcHeight / dstHeight; \
3971 if ( srcWidth < dstWidth ) { \
3972 const GLint wScale = dstWidth / srcWidth; \
3973 INNER_LOOP( TYPE, *, / ); \
3974 } \
3975 else { \
3976 const GLint wScale = srcWidth / dstWidth; \
3977 INNER_LOOP( TYPE, *, * ); \
3978 } \
3979 } \
3980 } while (0)
3981
3982 switch ( bytesPerPixel ) {
3983 case 4:
3984 RESCALE_IMAGE( GLuint );
3985 break;
3986
3987 case 2:
3988 RESCALE_IMAGE( GLushort );
3989 break;
3990
3991 case 1:
3992 RESCALE_IMAGE( GLubyte );
3993 break;
3994 default:
3995 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3996 }
3997 }
3998
3999
4000 /**
4001 * Upscale an image by replication, not (typical) stretching.
4002 * We use this when the image width or height is less than a
4003 * certain size (4, 8) and we need to upscale an image.
4004 */
4005 void
4006 _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight,
4007 GLsizei outWidth, GLsizei outHeight,
4008 GLint comps, const GLchan *src, GLint srcRowStride,
4009 GLchan *dest )
4010 {
4011 GLint i, j, k;
4012
4013 ASSERT(outWidth >= inWidth);
4014 ASSERT(outHeight >= inHeight);
4015 #if 0
4016 ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
4017 ASSERT((outWidth & 3) == 0);
4018 ASSERT((outHeight & 3) == 0);
4019 #endif
4020
4021 for (i = 0; i < outHeight; i++) {
4022 const GLint ii = i % inHeight;
4023 for (j = 0; j < outWidth; j++) {
4024 const GLint jj = j % inWidth;
4025 for (k = 0; k < comps; k++) {
4026 dest[(i * outWidth + j) * comps + k]
4027 = src[ii * srcRowStride + jj * comps + k];
4028 }
4029 }
4030 }
4031 }
4032
4033
4034
4035 /**
4036 * This is the software fallback for Driver.GetTexImage().
4037 * All error checking will have been done before this routine is called.
4038 */
4039 void
4040 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
4041 GLenum format, GLenum type, GLvoid *pixels,
4042 const struct gl_texture_object *texObj,
4043 const struct gl_texture_image *texImage)
4044 {
4045 GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
4046
4047 if (ctx->Pack.BufferObj->Name) {
4048 /* pack texture image into a PBO */
4049 GLubyte *buf;
4050 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
4051 texImage->Height, texImage->Depth,
4052 format, type, pixels)) {
4053 _mesa_error(ctx, GL_INVALID_OPERATION,
4054 "glGetTexImage(invalid PBO access)");
4055 return;
4056 }
4057 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4058 GL_WRITE_ONLY_ARB,
4059 ctx->Pack.BufferObj);
4060 if (!buf) {
4061 /* buffer is already mapped - that's an error */
4062 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
4063 return;
4064 }
4065 pixels = ADD_POINTERS(buf, pixels);
4066 }
4067 else if (!pixels) {
4068 /* not an error */
4069 return;
4070 }
4071
4072 {
4073 const GLint width = texImage->Width;
4074 const GLint height = texImage->Height;
4075 const GLint depth = texImage->Depth;
4076 GLint img, row;
4077 for (img = 0; img < depth; img++) {
4078 for (row = 0; row < height; row++) {
4079 /* compute destination address in client memory */
4080 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
4081 width, height, format, type,
4082 img, row, 0);
4083 assert(dest);
4084
4085 if (format == GL_COLOR_INDEX) {
4086 GLuint indexRow[MAX_WIDTH];
4087 GLint col;
4088 /* Can't use FetchTexel here because that returns RGBA */
4089 if (texImage->TexFormat->IndexBits == 8) {
4090 const GLubyte *src = (const GLubyte *) texImage->Data;
4091 src += width * (img * texImage->Height + row);
4092 for (col = 0; col < width; col++) {
4093 indexRow[col] = src[col];
4094 }
4095 }
4096 else if (texImage->TexFormat->IndexBits == 16) {
4097 const GLushort *src = (const GLushort *) texImage->Data;
4098 src += width * (img * texImage->Height + row);
4099 for (col = 0; col < width; col++) {
4100 indexRow[col] = src[col];
4101 }
4102 }
4103 else {
4104 _mesa_problem(ctx,
4105 "Color index problem in _mesa_GetTexImage");
4106 }
4107 _mesa_pack_index_span(ctx, width, type, dest,
4108 indexRow, &ctx->Pack,
4109 0 /* no image transfer */);
4110 }
4111 else if (format == GL_DEPTH_COMPONENT) {
4112 GLfloat depthRow[MAX_WIDTH];
4113 GLint col;
4114 for (col = 0; col < width; col++) {
4115 (*texImage->FetchTexelf)(texImage, col, row, img,
4116 depthRow + col);
4117 }
4118 _mesa_pack_depth_span(ctx, width, dest, type,
4119 depthRow, &ctx->Pack);
4120 }
4121 else if (format == GL_DEPTH_STENCIL_EXT) {
4122 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4123 const GLuint *src = (const GLuint *) texImage->Data;
4124 src += width * row + width * height * img;
4125 _mesa_memcpy(dest, src, width * sizeof(GLuint));
4126 if (ctx->Pack.SwapBytes) {
4127 _mesa_swap4((GLuint *) dest, width);
4128 }
4129 }
4130 else if (format == GL_YCBCR_MESA) {
4131 /* No pixel transfer */
4132 const GLint rowstride = texImage->RowStride;
4133 MEMCPY(dest,
4134 (const GLushort *) texImage->Data + row * rowstride,
4135 width * sizeof(GLushort));
4136 /* check for byte swapping */
4137 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
4138 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
4139 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
4140 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
4141 if (!ctx->Pack.SwapBytes)
4142 _mesa_swap2((GLushort *) dest, width);
4143 }
4144 else if (ctx->Pack.SwapBytes) {
4145 _mesa_swap2((GLushort *) dest, width);
4146 }
4147 }
4148 else {
4149 /* general case: convert row to RGBA format */
4150 GLfloat rgba[MAX_WIDTH][4];
4151 GLint col;
4152 for (col = 0; col < width; col++) {
4153 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
4154 }
4155 _mesa_pack_rgba_span_float(ctx, width,
4156 (const GLfloat (*)[4]) rgba,
4157 format, type, dest, &ctx->Pack,
4158 0 /* no image transfer */);
4159 } /* format */
4160 } /* row */
4161 } /* img */
4162 }
4163
4164 if (ctx->Pack.BufferObj->Name) {
4165 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4166 ctx->Pack.BufferObj);
4167 }
4168 }
4169
4170
4171
4172 /**
4173 * This is the software fallback for Driver.GetCompressedTexImage().
4174 * All error checking will have been done before this routine is called.
4175 */
4176 void
4177 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
4178 GLvoid *img,
4179 const struct gl_texture_object *texObj,
4180 const struct gl_texture_image *texImage)
4181 {
4182 if (ctx->Pack.BufferObj->Name) {
4183 /* pack texture image into a PBO */
4184 GLubyte *buf;
4185 if ((const GLubyte *) img + texImage->CompressedSize >
4186 (const GLubyte *) ctx->Pack.BufferObj->Size) {
4187 _mesa_error(ctx, GL_INVALID_OPERATION,
4188 "glGetCompressedTexImage(invalid PBO access)");
4189 return;
4190 }
4191 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4192 GL_WRITE_ONLY_ARB,
4193 ctx->Pack.BufferObj);
4194 if (!buf) {
4195 /* buffer is already mapped - that's an error */
4196 _mesa_error(ctx, GL_INVALID_OPERATION,
4197 "glGetCompressedTexImage(PBO is mapped)");
4198 return;
4199 }
4200 img = ADD_POINTERS(buf, img);
4201 }
4202 else if (!img) {
4203 /* not an error */
4204 return;
4205 }
4206
4207 /* just memcpy, no pixelstore or pixel transfer */
4208 MEMCPY(img, texImage->Data, texImage->CompressedSize);
4209
4210 if (ctx->Pack.BufferObj->Name) {
4211 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4212 ctx->Pack.BufferObj);
4213 }
4214 }