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