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