mesa: add new signed rgba texture format
[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, GL_FALSE);
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_BYTE:
802 case GL_UNSIGNED_BYTE:
803 return map_identity;
804 case GL_UNSIGNED_INT_8_8_8_8:
805 return _mesa_little_endian() ? map_3210 : map_identity;
806 case GL_UNSIGNED_INT_8_8_8_8_REV:
807 return _mesa_little_endian() ? map_identity : map_3210;
808 default:
809 return NULL;
810 }
811 }
812
813 /* Mapping required if input type is
814 */
815 static const GLubyte *
816 byteswap_mapping( GLboolean swapBytes,
817 GLenum srcType )
818 {
819 if (!swapBytes)
820 return map_identity;
821
822 switch (srcType) {
823 case GL_BYTE:
824 case GL_UNSIGNED_BYTE:
825 return map_identity;
826 case GL_UNSIGNED_INT_8_8_8_8:
827 case GL_UNSIGNED_INT_8_8_8_8_REV:
828 return map_3210;
829 default:
830 return NULL;
831 }
832 }
833
834
835
836 /**
837 * Transfer a GLubyte texture image with component swizzling.
838 */
839 static void
840 _mesa_swizzle_ubyte_image(GLcontext *ctx,
841 GLuint dimensions,
842 GLenum srcFormat,
843 GLenum srcType,
844
845 GLenum baseInternalFormat,
846
847 const GLubyte *rgba2dst,
848 GLuint dstComponents,
849
850 GLvoid *dstAddr,
851 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
852 GLint dstRowStride,
853 const GLuint *dstImageOffsets,
854
855 GLint srcWidth, GLint srcHeight, GLint srcDepth,
856 const GLvoid *srcAddr,
857 const struct gl_pixelstore_attrib *srcPacking )
858 {
859 GLint srcComponents = _mesa_components_in_format(srcFormat);
860 const GLubyte *srctype2ubyte, *swap;
861 GLubyte map[4], src2base[6], base2rgba[6];
862 GLint i;
863 const GLint srcRowStride =
864 _mesa_image_row_stride(srcPacking, srcWidth,
865 srcFormat, GL_UNSIGNED_BYTE);
866 const GLint srcImageStride
867 = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat,
868 GL_UNSIGNED_BYTE);
869 const GLubyte *srcImage
870 = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr,
871 srcWidth, srcHeight, srcFormat,
872 GL_UNSIGNED_BYTE, 0, 0, 0);
873
874 (void) ctx;
875
876 /* Translate from src->baseInternal->GL_RGBA->dst. This will
877 * correctly deal with RGBA->RGB->RGBA conversions where the final
878 * A value must be 0xff regardless of the incoming alpha values.
879 */
880 compute_component_mapping(srcFormat, baseInternalFormat, src2base);
881 compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba);
882 swap = byteswap_mapping(srcPacking->SwapBytes, srcType);
883 srctype2ubyte = type_mapping(srcType);
884
885
886 for (i = 0; i < 4; i++)
887 map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]];
888
889 /* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
890
891 if (srcComponents == dstComponents &&
892 srcRowStride == dstRowStride &&
893 srcRowStride == srcWidth * srcComponents &&
894 dimensions < 3) {
895 /* 1 and 2D images only */
896 GLubyte *dstImage = (GLubyte *) dstAddr
897 + dstYoffset * dstRowStride
898 + dstXoffset * dstComponents;
899 swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
900 srcWidth * srcHeight);
901 }
902 else {
903 GLint img, row;
904 for (img = 0; img < srcDepth; img++) {
905 const GLubyte *srcRow = srcImage;
906 GLubyte *dstRow = (GLubyte *) dstAddr
907 + dstImageOffsets[dstZoffset + img] * dstComponents
908 + dstYoffset * dstRowStride
909 + dstXoffset * dstComponents;
910 for (row = 0; row < srcHeight; row++) {
911 swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
912 dstRow += dstRowStride;
913 srcRow += srcRowStride;
914 }
915 srcImage += srcImageStride;
916 }
917 }
918 }
919
920
921 /**
922 * Teximage storage routine for when a simple memcpy will do.
923 * No pixel transfer operations or special texel encodings allowed.
924 * 1D, 2D and 3D images supported.
925 */
926 static void
927 memcpy_texture(GLcontext *ctx,
928 GLuint dimensions,
929 const struct gl_texture_format *dstFormat,
930 GLvoid *dstAddr,
931 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
932 GLint dstRowStride,
933 const GLuint *dstImageOffsets,
934 GLint srcWidth, GLint srcHeight, GLint srcDepth,
935 GLenum srcFormat, GLenum srcType,
936 const GLvoid *srcAddr,
937 const struct gl_pixelstore_attrib *srcPacking)
938 {
939 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
940 srcFormat, srcType);
941 const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
942 srcWidth, srcHeight, srcFormat, srcType);
943 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
944 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
945 const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
946
947 #if 0
948 /* XXX update/re-enable for dstImageOffsets array */
949 const GLint bytesPerImage = srcHeight * bytesPerRow;
950 const GLint bytesPerTexture = srcDepth * bytesPerImage;
951 GLubyte *dstImage = (GLubyte *) dstAddr
952 + dstZoffset * dstImageStride
953 + dstYoffset * dstRowStride
954 + dstXoffset * dstFormat->TexelBytes;
955
956 if (dstRowStride == srcRowStride &&
957 dstRowStride == bytesPerRow &&
958 ((dstImageStride == srcImageStride &&
959 dstImageStride == bytesPerImage) ||
960 (srcDepth == 1))) {
961 /* one big memcpy */
962 ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
963 }
964 else
965 {
966 GLint img, row;
967 for (img = 0; img < srcDepth; img++) {
968 const GLubyte *srcRow = srcImage;
969 GLubyte *dstRow = dstImage;
970 for (row = 0; row < srcHeight; row++) {
971 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
972 dstRow += dstRowStride;
973 srcRow += srcRowStride;
974 }
975 srcImage += srcImageStride;
976 dstImage += dstImageStride;
977 }
978 }
979 #endif
980
981 GLint img, row;
982 for (img = 0; img < srcDepth; img++) {
983 const GLubyte *srcRow = srcImage;
984 GLubyte *dstRow = (GLubyte *) dstAddr
985 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
986 + dstYoffset * dstRowStride
987 + dstXoffset * dstFormat->TexelBytes;
988 for (row = 0; row < srcHeight; row++) {
989 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
990 dstRow += dstRowStride;
991 srcRow += srcRowStride;
992 }
993 srcImage += srcImageStride;
994 }
995 }
996
997
998
999 /**
1000 * Store an image in any of the formats:
1001 * _mesa_texformat_rgba
1002 * _mesa_texformat_rgb
1003 * _mesa_texformat_alpha
1004 * _mesa_texformat_luminance
1005 * _mesa_texformat_luminance_alpha
1006 * _mesa_texformat_intensity
1007 *
1008 */
1009 GLboolean
1010 _mesa_texstore_rgba(TEXSTORE_PARAMS)
1011 {
1012 const GLint components = _mesa_components_in_format(baseInternalFormat);
1013
1014 ASSERT(dstFormat == &_mesa_texformat_rgba ||
1015 dstFormat == &_mesa_texformat_rgb ||
1016 dstFormat == &_mesa_texformat_alpha ||
1017 dstFormat == &_mesa_texformat_luminance ||
1018 dstFormat == &_mesa_texformat_luminance_alpha ||
1019 dstFormat == &_mesa_texformat_intensity);
1020 ASSERT(baseInternalFormat == GL_RGBA ||
1021 baseInternalFormat == GL_RGB ||
1022 baseInternalFormat == GL_ALPHA ||
1023 baseInternalFormat == GL_LUMINANCE ||
1024 baseInternalFormat == GL_LUMINANCE_ALPHA ||
1025 baseInternalFormat == GL_INTENSITY);
1026 ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan));
1027
1028 if (!ctx->_ImageTransferState &&
1029 !srcPacking->SwapBytes &&
1030 baseInternalFormat == srcFormat &&
1031 srcType == CHAN_TYPE) {
1032 /* simple memcpy path */
1033 memcpy_texture(ctx, dims,
1034 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1035 dstRowStride,
1036 dstImageOffsets,
1037 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1038 srcAddr, srcPacking);
1039 }
1040 else if (!ctx->_ImageTransferState &&
1041 !srcPacking->SwapBytes &&
1042 dstFormat == &_mesa_texformat_rgb &&
1043 srcFormat == GL_RGBA &&
1044 srcType == CHAN_TYPE) {
1045 /* extract RGB from RGBA */
1046 GLint img, row, col;
1047 for (img = 0; img < srcDepth; img++) {
1048 GLchan *dstImage = (GLchan *)
1049 ((GLubyte *) dstAddr
1050 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1051 + dstYoffset * dstRowStride
1052 + dstXoffset * dstFormat->TexelBytes);
1053
1054 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1055 srcWidth, srcFormat, srcType);
1056 GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
1057 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1058 GLchan *dstRow = dstImage;
1059 for (row = 0; row < srcHeight; row++) {
1060 for (col = 0; col < srcWidth; col++) {
1061 dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
1062 dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
1063 dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
1064 }
1065 dstRow += dstRowStride / sizeof(GLchan);
1066 srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
1067 }
1068 }
1069 }
1070 else if (!ctx->_ImageTransferState &&
1071 CHAN_TYPE == GL_UNSIGNED_BYTE &&
1072 (srcType == GL_UNSIGNED_BYTE ||
1073 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1074 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1075 can_swizzle(baseInternalFormat) &&
1076 can_swizzle(srcFormat)) {
1077
1078 const GLubyte *dstmap;
1079 GLuint components;
1080
1081 /* dstmap - how to swizzle from RGBA to dst format:
1082 */
1083 if (dstFormat == &_mesa_texformat_rgba) {
1084 dstmap = mappings[IDX_RGBA].from_rgba;
1085 components = 4;
1086 }
1087 else if (dstFormat == &_mesa_texformat_rgb) {
1088 dstmap = mappings[IDX_RGB].from_rgba;
1089 components = 3;
1090 }
1091 else if (dstFormat == &_mesa_texformat_alpha) {
1092 dstmap = mappings[IDX_ALPHA].from_rgba;
1093 components = 1;
1094 }
1095 else if (dstFormat == &_mesa_texformat_luminance) {
1096 dstmap = mappings[IDX_LUMINANCE].from_rgba;
1097 components = 1;
1098 }
1099 else if (dstFormat == &_mesa_texformat_luminance_alpha) {
1100 dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba;
1101 components = 2;
1102 }
1103 else if (dstFormat == &_mesa_texformat_intensity) {
1104 dstmap = mappings[IDX_INTENSITY].from_rgba;
1105 components = 1;
1106 }
1107 else {
1108 _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba");
1109 return GL_FALSE;
1110 }
1111
1112 _mesa_swizzle_ubyte_image(ctx, dims,
1113 srcFormat,
1114 srcType,
1115 baseInternalFormat,
1116 dstmap, components,
1117 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1118 dstRowStride, dstImageOffsets,
1119 srcWidth, srcHeight, srcDepth, srcAddr,
1120 srcPacking);
1121 }
1122 else {
1123 /* general path */
1124 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1125 baseInternalFormat,
1126 dstFormat->BaseFormat,
1127 srcWidth, srcHeight, srcDepth,
1128 srcFormat, srcType, srcAddr,
1129 srcPacking);
1130 const GLchan *src = tempImage;
1131 GLint bytesPerRow;
1132 GLint img, row;
1133 if (!tempImage)
1134 return GL_FALSE;
1135 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1136 bytesPerRow = srcWidth * components * sizeof(GLchan);
1137 for (img = 0; img < srcDepth; img++) {
1138 GLubyte *dstRow = (GLubyte *) dstAddr
1139 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1140 + dstYoffset * dstRowStride
1141 + dstXoffset * dstFormat->TexelBytes;
1142 for (row = 0; row < srcHeight; row++) {
1143 _mesa_memcpy(dstRow, src, bytesPerRow);
1144 dstRow += dstRowStride;
1145 src += srcWidth * components;
1146 }
1147 }
1148
1149 _mesa_free((void *) tempImage);
1150 }
1151 return GL_TRUE;
1152 }
1153
1154
1155 /**
1156 * Store a 32-bit integer depth component texture image.
1157 */
1158 GLboolean
1159 _mesa_texstore_z32(TEXSTORE_PARAMS)
1160 {
1161 const GLuint depthScale = 0xffffffff;
1162 (void) dims;
1163 ASSERT(dstFormat == &_mesa_texformat_z32);
1164 ASSERT(dstFormat->TexelBytes == sizeof(GLuint));
1165
1166 if (ctx->Pixel.DepthScale == 1.0f &&
1167 ctx->Pixel.DepthBias == 0.0f &&
1168 !srcPacking->SwapBytes &&
1169 baseInternalFormat == GL_DEPTH_COMPONENT &&
1170 srcFormat == GL_DEPTH_COMPONENT &&
1171 srcType == GL_UNSIGNED_INT) {
1172 /* simple memcpy path */
1173 memcpy_texture(ctx, dims,
1174 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1175 dstRowStride,
1176 dstImageOffsets,
1177 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1178 srcAddr, srcPacking);
1179 }
1180 else {
1181 /* general path */
1182 GLint img, row;
1183 for (img = 0; img < srcDepth; img++) {
1184 GLubyte *dstRow = (GLubyte *) dstAddr
1185 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1186 + dstYoffset * dstRowStride
1187 + dstXoffset * dstFormat->TexelBytes;
1188 for (row = 0; row < srcHeight; row++) {
1189 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1190 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1191 _mesa_unpack_depth_span(ctx, srcWidth,
1192 GL_UNSIGNED_INT, (GLuint *) dstRow,
1193 depthScale, srcType, src, srcPacking);
1194 dstRow += dstRowStride;
1195 }
1196 }
1197 }
1198 return GL_TRUE;
1199 }
1200
1201 #define STRIDE_3D 0
1202
1203 /**
1204 * Store a 16-bit integer depth component texture image.
1205 */
1206 GLboolean
1207 _mesa_texstore_z16(TEXSTORE_PARAMS)
1208 {
1209 const GLuint depthScale = 0xffff;
1210 (void) dims;
1211 ASSERT(dstFormat == &_mesa_texformat_z16);
1212 ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
1213
1214 if (ctx->Pixel.DepthScale == 1.0f &&
1215 ctx->Pixel.DepthBias == 0.0f &&
1216 !srcPacking->SwapBytes &&
1217 baseInternalFormat == GL_DEPTH_COMPONENT &&
1218 srcFormat == GL_DEPTH_COMPONENT &&
1219 srcType == GL_UNSIGNED_SHORT) {
1220 /* simple memcpy path */
1221 memcpy_texture(ctx, dims,
1222 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1223 dstRowStride,
1224 dstImageOffsets,
1225 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1226 srcAddr, srcPacking);
1227 }
1228 else {
1229 /* general path */
1230 GLint img, row;
1231 for (img = 0; img < srcDepth; img++) {
1232 GLubyte *dstRow = (GLubyte *) dstAddr
1233 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1234 + dstYoffset * dstRowStride
1235 + dstXoffset * dstFormat->TexelBytes;
1236 for (row = 0; row < srcHeight; row++) {
1237 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1238 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1239 GLushort *dst16 = (GLushort *) dstRow;
1240 _mesa_unpack_depth_span(ctx, srcWidth,
1241 GL_UNSIGNED_SHORT, dst16, depthScale,
1242 srcType, src, srcPacking);
1243 dstRow += dstRowStride;
1244 }
1245 }
1246 }
1247 return GL_TRUE;
1248 }
1249
1250
1251 /**
1252 * Store an rgb565 or rgb565_rev texture image.
1253 */
1254 GLboolean
1255 _mesa_texstore_rgb565(TEXSTORE_PARAMS)
1256 {
1257 ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
1258 dstFormat == &_mesa_texformat_rgb565_rev);
1259 ASSERT(dstFormat->TexelBytes == 2);
1260
1261 if (!ctx->_ImageTransferState &&
1262 !srcPacking->SwapBytes &&
1263 dstFormat == &_mesa_texformat_rgb565 &&
1264 baseInternalFormat == GL_RGB &&
1265 srcFormat == GL_RGB &&
1266 srcType == GL_UNSIGNED_SHORT_5_6_5) {
1267 /* simple memcpy path */
1268 memcpy_texture(ctx, dims,
1269 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1270 dstRowStride,
1271 dstImageOffsets,
1272 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1273 srcAddr, srcPacking);
1274 }
1275 else if (!ctx->_ImageTransferState &&
1276 !srcPacking->SwapBytes &&
1277 baseInternalFormat == GL_RGB &&
1278 srcFormat == GL_RGB &&
1279 srcType == GL_UNSIGNED_BYTE &&
1280 dims == 2) {
1281 /* do optimized tex store */
1282 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
1283 srcFormat, srcType);
1284 const GLubyte *src = (const GLubyte *)
1285 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
1286 srcFormat, srcType, 0, 0, 0);
1287 GLubyte *dst = (GLubyte *) dstAddr
1288 + dstYoffset * dstRowStride
1289 + dstXoffset * dstFormat->TexelBytes;
1290 GLint row, col;
1291 for (row = 0; row < srcHeight; row++) {
1292 const GLubyte *srcUB = (const GLubyte *) src;
1293 GLushort *dstUS = (GLushort *) dst;
1294 /* check for byteswapped format */
1295 if (dstFormat == &_mesa_texformat_rgb565) {
1296 for (col = 0; col < srcWidth; col++) {
1297 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
1298 srcUB += 3;
1299 }
1300 }
1301 else {
1302 for (col = 0; col < srcWidth; col++) {
1303 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
1304 srcUB += 3;
1305 }
1306 }
1307 dst += dstRowStride;
1308 src += srcRowStride;
1309 }
1310 }
1311 else {
1312 /* general path */
1313 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1314 baseInternalFormat,
1315 dstFormat->BaseFormat,
1316 srcWidth, srcHeight, srcDepth,
1317 srcFormat, srcType, srcAddr,
1318 srcPacking);
1319 const GLchan *src = tempImage;
1320 GLint img, row, col;
1321 if (!tempImage)
1322 return GL_FALSE;
1323 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1324 for (img = 0; img < srcDepth; img++) {
1325 GLubyte *dstRow = (GLubyte *) dstAddr
1326 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1327 + dstYoffset * dstRowStride
1328 + dstXoffset * dstFormat->TexelBytes;
1329 for (row = 0; row < srcHeight; row++) {
1330 GLushort *dstUS = (GLushort *) dstRow;
1331 /* check for byteswapped format */
1332 if (dstFormat == &_mesa_texformat_rgb565) {
1333 for (col = 0; col < srcWidth; col++) {
1334 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
1335 CHAN_TO_UBYTE(src[GCOMP]),
1336 CHAN_TO_UBYTE(src[BCOMP]) );
1337 src += 3;
1338 }
1339 }
1340 else {
1341 for (col = 0; col < srcWidth; col++) {
1342 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
1343 CHAN_TO_UBYTE(src[GCOMP]),
1344 CHAN_TO_UBYTE(src[BCOMP]) );
1345 src += 3;
1346 }
1347 }
1348 dstRow += dstRowStride;
1349 }
1350 }
1351 _mesa_free((void *) tempImage);
1352 }
1353 return GL_TRUE;
1354 }
1355
1356
1357 /**
1358 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1359 */
1360 GLboolean
1361 _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
1362 {
1363 const GLboolean littleEndian = _mesa_little_endian();
1364
1365 ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
1366 dstFormat == &_mesa_texformat_rgba8888_rev);
1367 ASSERT(dstFormat->TexelBytes == 4);
1368
1369 if (!ctx->_ImageTransferState &&
1370 !srcPacking->SwapBytes &&
1371 dstFormat == &_mesa_texformat_rgba8888 &&
1372 baseInternalFormat == GL_RGBA &&
1373 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1374 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1375 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
1376 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
1377 /* simple memcpy path */
1378 memcpy_texture(ctx, dims,
1379 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1380 dstRowStride,
1381 dstImageOffsets,
1382 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1383 srcAddr, srcPacking);
1384 }
1385 else if (!ctx->_ImageTransferState &&
1386 !srcPacking->SwapBytes &&
1387 dstFormat == &_mesa_texformat_rgba8888_rev &&
1388 baseInternalFormat == GL_RGBA &&
1389 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
1390 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1391 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1392 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
1393 /* simple memcpy path */
1394 memcpy_texture(ctx, dims,
1395 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1396 dstRowStride,
1397 dstImageOffsets,
1398 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1399 srcAddr, srcPacking);
1400 }
1401 else if (!ctx->_ImageTransferState &&
1402 (srcType == GL_UNSIGNED_BYTE ||
1403 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1404 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1405 can_swizzle(baseInternalFormat) &&
1406 can_swizzle(srcFormat)) {
1407
1408 GLubyte dstmap[4];
1409
1410 /* dstmap - how to swizzle from RGBA to dst format:
1411 */
1412 if ((littleEndian && dstFormat == &_mesa_texformat_rgba8888) ||
1413 (!littleEndian && dstFormat == &_mesa_texformat_rgba8888_rev)) {
1414 dstmap[3] = 0;
1415 dstmap[2] = 1;
1416 dstmap[1] = 2;
1417 dstmap[0] = 3;
1418 }
1419 else {
1420 dstmap[3] = 3;
1421 dstmap[2] = 2;
1422 dstmap[1] = 1;
1423 dstmap[0] = 0;
1424 }
1425
1426 _mesa_swizzle_ubyte_image(ctx, dims,
1427 srcFormat,
1428 srcType,
1429 baseInternalFormat,
1430 dstmap, 4,
1431 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1432 dstRowStride, dstImageOffsets,
1433 srcWidth, srcHeight, srcDepth, srcAddr,
1434 srcPacking);
1435 }
1436 else {
1437 /* general path */
1438 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1439 baseInternalFormat,
1440 dstFormat->BaseFormat,
1441 srcWidth, srcHeight, srcDepth,
1442 srcFormat, srcType, srcAddr,
1443 srcPacking);
1444 const GLchan *src = tempImage;
1445 GLint img, row, col;
1446 if (!tempImage)
1447 return GL_FALSE;
1448 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1449 for (img = 0; img < srcDepth; img++) {
1450 GLubyte *dstRow = (GLubyte *) dstAddr
1451 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1452 + dstYoffset * dstRowStride
1453 + dstXoffset * dstFormat->TexelBytes;
1454 for (row = 0; row < srcHeight; row++) {
1455 GLuint *dstUI = (GLuint *) dstRow;
1456 if (dstFormat == &_mesa_texformat_rgba8888) {
1457 for (col = 0; col < srcWidth; col++) {
1458 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
1459 CHAN_TO_UBYTE(src[GCOMP]),
1460 CHAN_TO_UBYTE(src[BCOMP]),
1461 CHAN_TO_UBYTE(src[ACOMP]) );
1462 src += 4;
1463 }
1464 }
1465 else {
1466 for (col = 0; col < srcWidth; col++) {
1467 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
1468 CHAN_TO_UBYTE(src[GCOMP]),
1469 CHAN_TO_UBYTE(src[BCOMP]),
1470 CHAN_TO_UBYTE(src[ACOMP]) );
1471 src += 4;
1472 }
1473 }
1474 dstRow += dstRowStride;
1475 }
1476 }
1477 _mesa_free((void *) tempImage);
1478 }
1479 return GL_TRUE;
1480 }
1481
1482
1483 GLboolean
1484 _mesa_texstore_argb8888(TEXSTORE_PARAMS)
1485 {
1486 const GLboolean littleEndian = _mesa_little_endian();
1487
1488 ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
1489 dstFormat == &_mesa_texformat_argb8888_rev);
1490 ASSERT(dstFormat->TexelBytes == 4);
1491
1492 if (!ctx->_ImageTransferState &&
1493 !srcPacking->SwapBytes &&
1494 dstFormat == &_mesa_texformat_argb8888 &&
1495 baseInternalFormat == GL_RGBA &&
1496 srcFormat == GL_BGRA &&
1497 ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1498 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
1499 /* simple memcpy path (little endian) */
1500 memcpy_texture(ctx, dims,
1501 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1502 dstRowStride,
1503 dstImageOffsets,
1504 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1505 srcAddr, srcPacking);
1506 }
1507 else if (!ctx->_ImageTransferState &&
1508 !srcPacking->SwapBytes &&
1509 dstFormat == &_mesa_texformat_argb8888_rev &&
1510 baseInternalFormat == GL_RGBA &&
1511 srcFormat == GL_BGRA &&
1512 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1513 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
1514 /* simple memcpy path (big endian) */
1515 memcpy_texture(ctx, dims,
1516 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1517 dstRowStride,
1518 dstImageOffsets,
1519 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1520 srcAddr, srcPacking);
1521 }
1522 else if (!ctx->_ImageTransferState &&
1523 !srcPacking->SwapBytes &&
1524 dstFormat == &_mesa_texformat_argb8888 &&
1525 srcFormat == GL_RGB &&
1526 (baseInternalFormat == GL_RGBA ||
1527 baseInternalFormat == GL_RGB) &&
1528 srcType == GL_UNSIGNED_BYTE) {
1529 int img, row, col;
1530 for (img = 0; img < srcDepth; img++) {
1531 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1532 srcWidth, srcFormat, srcType);
1533 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1534 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1535 GLubyte *dstRow = (GLubyte *) dstAddr
1536 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1537 + dstYoffset * dstRowStride
1538 + dstXoffset * dstFormat->TexelBytes;
1539 for (row = 0; row < srcHeight; row++) {
1540 GLuint *d4 = (GLuint *) dstRow;
1541 for (col = 0; col < srcWidth; col++) {
1542 d4[col] = PACK_COLOR_8888(0xff,
1543 srcRow[col * 3 + RCOMP],
1544 srcRow[col * 3 + GCOMP],
1545 srcRow[col * 3 + BCOMP]);
1546 }
1547 dstRow += dstRowStride;
1548 srcRow += srcRowStride;
1549 }
1550 }
1551 }
1552 else if (!ctx->_ImageTransferState &&
1553 !srcPacking->SwapBytes &&
1554 dstFormat == &_mesa_texformat_argb8888 &&
1555 srcFormat == GL_RGBA &&
1556 baseInternalFormat == GL_RGBA &&
1557 srcType == GL_UNSIGNED_BYTE) {
1558 /* same as above case, but src data has alpha too */
1559 GLint img, row, col;
1560 /* For some reason, streaming copies to write-combined regions
1561 * are extremely sensitive to the characteristics of how the
1562 * source data is retrieved. By reordering the source reads to
1563 * be in-order, the speed of this operation increases by half.
1564 * Strangely the same isn't required for the RGB path, above.
1565 */
1566 for (img = 0; img < srcDepth; img++) {
1567 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1568 srcWidth, srcFormat, srcType);
1569 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1570 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1571 GLubyte *dstRow = (GLubyte *) dstAddr
1572 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1573 + dstYoffset * dstRowStride
1574 + dstXoffset * dstFormat->TexelBytes;
1575 for (row = 0; row < srcHeight; row++) {
1576 GLuint *d4 = (GLuint *) dstRow;
1577 for (col = 0; col < srcWidth; col++) {
1578 d4[col] = PACK_COLOR_8888(srcRow[col * 4 + ACOMP],
1579 srcRow[col * 4 + RCOMP],
1580 srcRow[col * 4 + GCOMP],
1581 srcRow[col * 4 + BCOMP]);
1582 }
1583 dstRow += dstRowStride;
1584 srcRow += srcRowStride;
1585 }
1586 }
1587 }
1588 else if (!ctx->_ImageTransferState &&
1589 (srcType == GL_UNSIGNED_BYTE ||
1590 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1591 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1592 can_swizzle(baseInternalFormat) &&
1593 can_swizzle(srcFormat)) {
1594
1595 GLubyte dstmap[4];
1596
1597 /* dstmap - how to swizzle from RGBA to dst format:
1598 */
1599 if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) ||
1600 (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) {
1601 dstmap[3] = 3; /* alpha */
1602 dstmap[2] = 0; /* red */
1603 dstmap[1] = 1; /* green */
1604 dstmap[0] = 2; /* blue */
1605 }
1606 else {
1607 assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) ||
1608 (!littleEndian && dstFormat == &_mesa_texformat_argb8888));
1609 dstmap[3] = 2;
1610 dstmap[2] = 1;
1611 dstmap[1] = 0;
1612 dstmap[0] = 3;
1613 }
1614
1615 _mesa_swizzle_ubyte_image(ctx, dims,
1616 srcFormat,
1617 srcType,
1618
1619 baseInternalFormat,
1620 dstmap, 4,
1621 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1622 dstRowStride,
1623 dstImageOffsets,
1624 srcWidth, srcHeight, srcDepth, srcAddr,
1625 srcPacking);
1626 }
1627 else {
1628 /* general path */
1629 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1630 baseInternalFormat,
1631 dstFormat->BaseFormat,
1632 srcWidth, srcHeight, srcDepth,
1633 srcFormat, srcType, srcAddr,
1634 srcPacking);
1635 const GLchan *src = tempImage;
1636 GLint img, row, col;
1637 if (!tempImage)
1638 return GL_FALSE;
1639 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1640 for (img = 0; img < srcDepth; img++) {
1641 GLubyte *dstRow = (GLubyte *) dstAddr
1642 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1643 + dstYoffset * dstRowStride
1644 + dstXoffset * dstFormat->TexelBytes;
1645 for (row = 0; row < srcHeight; row++) {
1646 GLuint *dstUI = (GLuint *) dstRow;
1647 if (dstFormat == &_mesa_texformat_argb8888) {
1648 for (col = 0; col < srcWidth; col++) {
1649 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1650 CHAN_TO_UBYTE(src[RCOMP]),
1651 CHAN_TO_UBYTE(src[GCOMP]),
1652 CHAN_TO_UBYTE(src[BCOMP]) );
1653 src += 4;
1654 }
1655 }
1656 else {
1657 for (col = 0; col < srcWidth; col++) {
1658 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1659 CHAN_TO_UBYTE(src[RCOMP]),
1660 CHAN_TO_UBYTE(src[GCOMP]),
1661 CHAN_TO_UBYTE(src[BCOMP]) );
1662 src += 4;
1663 }
1664 }
1665 dstRow += dstRowStride;
1666 }
1667 }
1668 _mesa_free((void *) tempImage);
1669 }
1670 return GL_TRUE;
1671 }
1672
1673
1674 GLboolean
1675 _mesa_texstore_rgb888(TEXSTORE_PARAMS)
1676 {
1677 const GLboolean littleEndian = _mesa_little_endian();
1678
1679 ASSERT(dstFormat == &_mesa_texformat_rgb888);
1680 ASSERT(dstFormat->TexelBytes == 3);
1681
1682 if (!ctx->_ImageTransferState &&
1683 !srcPacking->SwapBytes &&
1684 baseInternalFormat == GL_RGB &&
1685 srcFormat == GL_BGR &&
1686 srcType == GL_UNSIGNED_BYTE &&
1687 littleEndian) {
1688 /* simple memcpy path */
1689 memcpy_texture(ctx, dims,
1690 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1691 dstRowStride,
1692 dstImageOffsets,
1693 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1694 srcAddr, srcPacking);
1695 }
1696 else if (!ctx->_ImageTransferState &&
1697 !srcPacking->SwapBytes &&
1698 srcFormat == GL_RGBA &&
1699 srcType == GL_UNSIGNED_BYTE) {
1700 /* extract RGB from RGBA */
1701 GLint img, row, col;
1702 for (img = 0; img < srcDepth; img++) {
1703 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1704 srcWidth, srcFormat, srcType);
1705 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1706 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1707 GLubyte *dstRow = (GLubyte *) dstAddr
1708 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1709 + dstYoffset * dstRowStride
1710 + dstXoffset * dstFormat->TexelBytes;
1711 for (row = 0; row < srcHeight; row++) {
1712 for (col = 0; col < srcWidth; col++) {
1713 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1714 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1715 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1716 }
1717 dstRow += dstRowStride;
1718 srcRow += srcRowStride;
1719 }
1720 }
1721 }
1722 else if (!ctx->_ImageTransferState &&
1723 srcType == GL_UNSIGNED_BYTE &&
1724 can_swizzle(baseInternalFormat) &&
1725 can_swizzle(srcFormat)) {
1726
1727 GLubyte dstmap[4];
1728
1729 /* dstmap - how to swizzle from RGBA to dst format:
1730 */
1731 dstmap[0] = 2;
1732 dstmap[1] = 1;
1733 dstmap[2] = 0;
1734 dstmap[3] = ONE; /* ? */
1735
1736 _mesa_swizzle_ubyte_image(ctx, dims,
1737 srcFormat,
1738 srcType,
1739 baseInternalFormat,
1740 dstmap, 3,
1741 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1742 dstRowStride, dstImageOffsets,
1743 srcWidth, srcHeight, srcDepth, srcAddr,
1744 srcPacking);
1745 }
1746 else {
1747 /* general path */
1748 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1749 baseInternalFormat,
1750 dstFormat->BaseFormat,
1751 srcWidth, srcHeight, srcDepth,
1752 srcFormat, srcType, srcAddr,
1753 srcPacking);
1754 const GLchan *src = (const GLchan *) tempImage;
1755 GLint img, row, col;
1756 if (!tempImage)
1757 return GL_FALSE;
1758 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1759 for (img = 0; img < srcDepth; img++) {
1760 GLubyte *dstRow = (GLubyte *) dstAddr
1761 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1762 + dstYoffset * dstRowStride
1763 + dstXoffset * dstFormat->TexelBytes;
1764 for (row = 0; row < srcHeight; row++) {
1765 #if 0
1766 if (littleEndian) {
1767 for (col = 0; col < srcWidth; col++) {
1768 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1769 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1770 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1771 srcUB += 3;
1772 }
1773 }
1774 else {
1775 for (col = 0; col < srcWidth; col++) {
1776 dstRow[col * 3 + 0] = srcUB[BCOMP];
1777 dstRow[col * 3 + 1] = srcUB[GCOMP];
1778 dstRow[col * 3 + 2] = srcUB[RCOMP];
1779 srcUB += 3;
1780 }
1781 }
1782 #else
1783 for (col = 0; col < srcWidth; col++) {
1784 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1785 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1786 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1787 src += 3;
1788 }
1789 #endif
1790 dstRow += dstRowStride;
1791 }
1792 }
1793 _mesa_free((void *) tempImage);
1794 }
1795 return GL_TRUE;
1796 }
1797
1798
1799 GLboolean
1800 _mesa_texstore_bgr888(TEXSTORE_PARAMS)
1801 {
1802 const GLboolean littleEndian = _mesa_little_endian();
1803
1804 ASSERT(dstFormat == &_mesa_texformat_bgr888);
1805 ASSERT(dstFormat->TexelBytes == 3);
1806
1807 if (!ctx->_ImageTransferState &&
1808 !srcPacking->SwapBytes &&
1809 baseInternalFormat == GL_RGB &&
1810 srcFormat == GL_RGB &&
1811 srcType == GL_UNSIGNED_BYTE &&
1812 littleEndian) {
1813 /* simple memcpy path */
1814 memcpy_texture(ctx, dims,
1815 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1816 dstRowStride,
1817 dstImageOffsets,
1818 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1819 srcAddr, srcPacking);
1820 }
1821 else if (!ctx->_ImageTransferState &&
1822 !srcPacking->SwapBytes &&
1823 srcFormat == GL_RGBA &&
1824 srcType == GL_UNSIGNED_BYTE) {
1825 /* extract BGR from RGBA */
1826 int img, row, col;
1827 for (img = 0; img < srcDepth; img++) {
1828 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1829 srcWidth, srcFormat, srcType);
1830 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1831 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1832 GLubyte *dstRow = (GLubyte *) dstAddr
1833 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1834 + dstYoffset * dstRowStride
1835 + dstXoffset * dstFormat->TexelBytes;
1836 for (row = 0; row < srcHeight; row++) {
1837 for (col = 0; col < srcWidth; col++) {
1838 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1839 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1840 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1841 }
1842 dstRow += dstRowStride;
1843 srcRow += srcRowStride;
1844 }
1845 }
1846 }
1847 else if (!ctx->_ImageTransferState &&
1848 srcType == GL_UNSIGNED_BYTE &&
1849 can_swizzle(baseInternalFormat) &&
1850 can_swizzle(srcFormat)) {
1851
1852 GLubyte dstmap[4];
1853
1854 /* dstmap - how to swizzle from RGBA to dst format:
1855 */
1856 dstmap[0] = 0;
1857 dstmap[1] = 1;
1858 dstmap[2] = 2;
1859 dstmap[3] = ONE; /* ? */
1860
1861 _mesa_swizzle_ubyte_image(ctx, dims,
1862 srcFormat,
1863 srcType,
1864 baseInternalFormat,
1865 dstmap, 3,
1866 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1867 dstRowStride, dstImageOffsets,
1868 srcWidth, srcHeight, srcDepth, srcAddr,
1869 srcPacking);
1870 }
1871 else {
1872 /* general path */
1873 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1874 baseInternalFormat,
1875 dstFormat->BaseFormat,
1876 srcWidth, srcHeight, srcDepth,
1877 srcFormat, srcType, srcAddr,
1878 srcPacking);
1879 const GLchan *src = (const GLchan *) tempImage;
1880 GLint img, row, col;
1881 if (!tempImage)
1882 return GL_FALSE;
1883 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1884 for (img = 0; img < srcDepth; img++) {
1885 GLubyte *dstRow = (GLubyte *) dstAddr
1886 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1887 + dstYoffset * dstRowStride
1888 + dstXoffset * dstFormat->TexelBytes;
1889 for (row = 0; row < srcHeight; row++) {
1890 for (col = 0; col < srcWidth; col++) {
1891 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1892 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1893 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1894 src += 3;
1895 }
1896 dstRow += dstRowStride;
1897 }
1898 }
1899 _mesa_free((void *) tempImage);
1900 }
1901 return GL_TRUE;
1902 }
1903
1904 GLboolean
1905 _mesa_texstore_rgba4444(TEXSTORE_PARAMS)
1906 {
1907 ASSERT(dstFormat == &_mesa_texformat_rgba4444);
1908 ASSERT(dstFormat->TexelBytes == 2);
1909
1910 if (!ctx->_ImageTransferState &&
1911 !srcPacking->SwapBytes &&
1912 dstFormat == &_mesa_texformat_rgba4444 &&
1913 baseInternalFormat == GL_RGBA &&
1914 srcFormat == GL_RGBA &&
1915 srcType == GL_UNSIGNED_SHORT_4_4_4_4){
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 for (col = 0; col < srcWidth; col++) {
1945 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[RCOMP]),
1946 CHAN_TO_UBYTE(src[GCOMP]),
1947 CHAN_TO_UBYTE(src[BCOMP]),
1948 CHAN_TO_UBYTE(src[ACOMP]) );
1949 src += 4;
1950 }
1951 dstRow += dstRowStride;
1952 }
1953 }
1954 _mesa_free((void *) tempImage);
1955 }
1956 return GL_TRUE;
1957 }
1958
1959 GLboolean
1960 _mesa_texstore_argb4444(TEXSTORE_PARAMS)
1961 {
1962 ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
1963 dstFormat == &_mesa_texformat_argb4444_rev);
1964 ASSERT(dstFormat->TexelBytes == 2);
1965
1966 if (!ctx->_ImageTransferState &&
1967 !srcPacking->SwapBytes &&
1968 dstFormat == &_mesa_texformat_argb4444 &&
1969 baseInternalFormat == GL_RGBA &&
1970 srcFormat == GL_BGRA &&
1971 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1972 /* simple memcpy path */
1973 memcpy_texture(ctx, dims,
1974 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1975 dstRowStride,
1976 dstImageOffsets,
1977 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1978 srcAddr, srcPacking);
1979 }
1980 else {
1981 /* general path */
1982 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1983 baseInternalFormat,
1984 dstFormat->BaseFormat,
1985 srcWidth, srcHeight, srcDepth,
1986 srcFormat, srcType, srcAddr,
1987 srcPacking);
1988 const GLchan *src = tempImage;
1989 GLint img, row, col;
1990 if (!tempImage)
1991 return GL_FALSE;
1992 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1993 for (img = 0; img < srcDepth; img++) {
1994 GLubyte *dstRow = (GLubyte *) dstAddr
1995 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1996 + dstYoffset * dstRowStride
1997 + dstXoffset * dstFormat->TexelBytes;
1998 for (row = 0; row < srcHeight; row++) {
1999 GLushort *dstUS = (GLushort *) dstRow;
2000 if (dstFormat == &_mesa_texformat_argb4444) {
2001 for (col = 0; col < srcWidth; col++) {
2002 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
2003 CHAN_TO_UBYTE(src[RCOMP]),
2004 CHAN_TO_UBYTE(src[GCOMP]),
2005 CHAN_TO_UBYTE(src[BCOMP]) );
2006 src += 4;
2007 }
2008 }
2009 else {
2010 for (col = 0; col < srcWidth; col++) {
2011 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
2012 CHAN_TO_UBYTE(src[RCOMP]),
2013 CHAN_TO_UBYTE(src[GCOMP]),
2014 CHAN_TO_UBYTE(src[BCOMP]) );
2015 src += 4;
2016 }
2017 }
2018 dstRow += dstRowStride;
2019 }
2020 }
2021 _mesa_free((void *) tempImage);
2022 }
2023 return GL_TRUE;
2024 }
2025
2026 GLboolean
2027 _mesa_texstore_rgba5551(TEXSTORE_PARAMS)
2028 {
2029 ASSERT(dstFormat == &_mesa_texformat_rgba5551);
2030 ASSERT(dstFormat->TexelBytes == 2);
2031
2032 if (!ctx->_ImageTransferState &&
2033 !srcPacking->SwapBytes &&
2034 dstFormat == &_mesa_texformat_rgba5551 &&
2035 baseInternalFormat == GL_RGBA &&
2036 srcFormat == GL_RGBA &&
2037 srcType == GL_UNSIGNED_SHORT_5_5_5_1) {
2038 /* simple memcpy path */
2039 memcpy_texture(ctx, dims,
2040 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2041 dstRowStride,
2042 dstImageOffsets,
2043 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2044 srcAddr, srcPacking);
2045 }
2046 else {
2047 /* general path */
2048 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2049 baseInternalFormat,
2050 dstFormat->BaseFormat,
2051 srcWidth, srcHeight, srcDepth,
2052 srcFormat, srcType, srcAddr,
2053 srcPacking);
2054 const GLchan *src =tempImage;
2055 GLint img, row, col;
2056 if (!tempImage)
2057 return GL_FALSE;
2058 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2059 for (img = 0; img < srcDepth; img++) {
2060 GLubyte *dstRow = (GLubyte *) dstAddr
2061 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2062 + dstYoffset * dstRowStride
2063 + dstXoffset * dstFormat->TexelBytes;
2064 for (row = 0; row < srcHeight; row++) {
2065 GLushort *dstUS = (GLushort *) dstRow;
2066 for (col = 0; col < srcWidth; col++) {
2067 dstUS[col] = PACK_COLOR_5551( CHAN_TO_UBYTE(src[RCOMP]),
2068 CHAN_TO_UBYTE(src[GCOMP]),
2069 CHAN_TO_UBYTE(src[BCOMP]),
2070 CHAN_TO_UBYTE(src[ACOMP]) );
2071 src += 4;
2072 }
2073 dstRow += dstRowStride;
2074 }
2075 }
2076 _mesa_free((void *) tempImage);
2077 }
2078 return GL_TRUE;
2079 }
2080
2081 GLboolean
2082 _mesa_texstore_argb1555(TEXSTORE_PARAMS)
2083 {
2084 ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
2085 dstFormat == &_mesa_texformat_argb1555_rev);
2086 ASSERT(dstFormat->TexelBytes == 2);
2087
2088 if (!ctx->_ImageTransferState &&
2089 !srcPacking->SwapBytes &&
2090 dstFormat == &_mesa_texformat_argb1555 &&
2091 baseInternalFormat == GL_RGBA &&
2092 srcFormat == GL_BGRA &&
2093 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
2094 /* simple memcpy path */
2095 memcpy_texture(ctx, dims,
2096 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2097 dstRowStride,
2098 dstImageOffsets,
2099 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2100 srcAddr, srcPacking);
2101 }
2102 else {
2103 /* general path */
2104 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2105 baseInternalFormat,
2106 dstFormat->BaseFormat,
2107 srcWidth, srcHeight, srcDepth,
2108 srcFormat, srcType, srcAddr,
2109 srcPacking);
2110 const GLchan *src =tempImage;
2111 GLint img, row, col;
2112 if (!tempImage)
2113 return GL_FALSE;
2114 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2115 for (img = 0; img < srcDepth; img++) {
2116 GLubyte *dstRow = (GLubyte *) dstAddr
2117 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2118 + dstYoffset * dstRowStride
2119 + dstXoffset * dstFormat->TexelBytes;
2120 for (row = 0; row < srcHeight; row++) {
2121 GLushort *dstUS = (GLushort *) dstRow;
2122 if (dstFormat == &_mesa_texformat_argb1555) {
2123 for (col = 0; col < srcWidth; col++) {
2124 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
2125 CHAN_TO_UBYTE(src[RCOMP]),
2126 CHAN_TO_UBYTE(src[GCOMP]),
2127 CHAN_TO_UBYTE(src[BCOMP]) );
2128 src += 4;
2129 }
2130 }
2131 else {
2132 for (col = 0; col < srcWidth; col++) {
2133 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
2134 CHAN_TO_UBYTE(src[RCOMP]),
2135 CHAN_TO_UBYTE(src[GCOMP]),
2136 CHAN_TO_UBYTE(src[BCOMP]) );
2137 src += 4;
2138 }
2139 }
2140 dstRow += dstRowStride;
2141 }
2142 }
2143 _mesa_free((void *) tempImage);
2144 }
2145 return GL_TRUE;
2146 }
2147
2148
2149 GLboolean
2150 _mesa_texstore_al88(TEXSTORE_PARAMS)
2151 {
2152 const GLboolean littleEndian = _mesa_little_endian();
2153
2154 ASSERT(dstFormat == &_mesa_texformat_al88 ||
2155 dstFormat == &_mesa_texformat_al88_rev);
2156 ASSERT(dstFormat->TexelBytes == 2);
2157
2158 if (!ctx->_ImageTransferState &&
2159 !srcPacking->SwapBytes &&
2160 dstFormat == &_mesa_texformat_al88 &&
2161 baseInternalFormat == GL_LUMINANCE_ALPHA &&
2162 srcFormat == GL_LUMINANCE_ALPHA &&
2163 srcType == GL_UNSIGNED_BYTE &&
2164 littleEndian) {
2165 /* simple memcpy path */
2166 memcpy_texture(ctx, dims,
2167 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2168 dstRowStride,
2169 dstImageOffsets,
2170 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2171 srcAddr, srcPacking);
2172 }
2173 else if (!ctx->_ImageTransferState &&
2174 littleEndian &&
2175 srcType == GL_UNSIGNED_BYTE &&
2176 can_swizzle(baseInternalFormat) &&
2177 can_swizzle(srcFormat)) {
2178
2179 GLubyte dstmap[4];
2180
2181 /* dstmap - how to swizzle from RGBA to dst format:
2182 */
2183 if ((littleEndian && dstFormat == &_mesa_texformat_al88) ||
2184 (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) {
2185 dstmap[0] = 0;
2186 dstmap[1] = 3;
2187 }
2188 else {
2189 dstmap[0] = 3;
2190 dstmap[1] = 0;
2191 }
2192 dstmap[2] = ZERO; /* ? */
2193 dstmap[3] = ONE; /* ? */
2194
2195 _mesa_swizzle_ubyte_image(ctx, dims,
2196 srcFormat,
2197 srcType,
2198 baseInternalFormat,
2199 dstmap, 2,
2200 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2201 dstRowStride, dstImageOffsets,
2202 srcWidth, srcHeight, srcDepth, srcAddr,
2203 srcPacking);
2204 }
2205 else {
2206 /* general path */
2207 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2208 baseInternalFormat,
2209 dstFormat->BaseFormat,
2210 srcWidth, srcHeight, srcDepth,
2211 srcFormat, srcType, srcAddr,
2212 srcPacking);
2213 const GLchan *src = tempImage;
2214 GLint img, row, col;
2215 if (!tempImage)
2216 return GL_FALSE;
2217 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2218 for (img = 0; img < srcDepth; img++) {
2219 GLubyte *dstRow = (GLubyte *) dstAddr
2220 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2221 + dstYoffset * dstRowStride
2222 + dstXoffset * dstFormat->TexelBytes;
2223 for (row = 0; row < srcHeight; row++) {
2224 GLushort *dstUS = (GLushort *) dstRow;
2225 if (dstFormat == &_mesa_texformat_al88) {
2226 for (col = 0; col < srcWidth; col++) {
2227 /* src[0] is luminance, src[1] is alpha */
2228 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
2229 CHAN_TO_UBYTE(src[0]) );
2230 src += 2;
2231 }
2232 }
2233 else {
2234 for (col = 0; col < srcWidth; col++) {
2235 /* src[0] is luminance, src[1] is alpha */
2236 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
2237 CHAN_TO_UBYTE(src[0]) );
2238 src += 2;
2239 }
2240 }
2241 dstRow += dstRowStride;
2242 }
2243 }
2244 _mesa_free((void *) tempImage);
2245 }
2246 return GL_TRUE;
2247 }
2248
2249
2250 GLboolean
2251 _mesa_texstore_rgb332(TEXSTORE_PARAMS)
2252 {
2253 ASSERT(dstFormat == &_mesa_texformat_rgb332);
2254 ASSERT(dstFormat->TexelBytes == 1);
2255
2256 if (!ctx->_ImageTransferState &&
2257 !srcPacking->SwapBytes &&
2258 baseInternalFormat == GL_RGB &&
2259 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
2260 /* simple memcpy path */
2261 memcpy_texture(ctx, dims,
2262 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2263 dstRowStride,
2264 dstImageOffsets,
2265 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2266 srcAddr, srcPacking);
2267 }
2268 else {
2269 /* general path */
2270 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2271 baseInternalFormat,
2272 dstFormat->BaseFormat,
2273 srcWidth, srcHeight, srcDepth,
2274 srcFormat, srcType, srcAddr,
2275 srcPacking);
2276 const GLchan *src = tempImage;
2277 GLint img, row, col;
2278 if (!tempImage)
2279 return GL_FALSE;
2280 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2281 for (img = 0; img < srcDepth; img++) {
2282 GLubyte *dstRow = (GLubyte *) dstAddr
2283 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2284 + dstYoffset * dstRowStride
2285 + dstXoffset * dstFormat->TexelBytes;
2286 for (row = 0; row < srcHeight; row++) {
2287 for (col = 0; col < srcWidth; col++) {
2288 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
2289 CHAN_TO_UBYTE(src[GCOMP]),
2290 CHAN_TO_UBYTE(src[BCOMP]) );
2291 src += 3;
2292 }
2293 dstRow += dstRowStride;
2294 }
2295 }
2296 _mesa_free((void *) tempImage);
2297 }
2298 return GL_TRUE;
2299 }
2300
2301
2302 /**
2303 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2304 */
2305 GLboolean
2306 _mesa_texstore_a8(TEXSTORE_PARAMS)
2307 {
2308 ASSERT(dstFormat == &_mesa_texformat_a8 ||
2309 dstFormat == &_mesa_texformat_l8 ||
2310 dstFormat == &_mesa_texformat_i8);
2311 ASSERT(dstFormat->TexelBytes == 1);
2312
2313 if (!ctx->_ImageTransferState &&
2314 !srcPacking->SwapBytes &&
2315 baseInternalFormat == srcFormat &&
2316 srcType == GL_UNSIGNED_BYTE) {
2317 /* simple memcpy path */
2318 memcpy_texture(ctx, dims,
2319 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2320 dstRowStride,
2321 dstImageOffsets,
2322 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2323 srcAddr, srcPacking);
2324 }
2325 else if (!ctx->_ImageTransferState &&
2326 srcType == GL_UNSIGNED_BYTE &&
2327 can_swizzle(baseInternalFormat) &&
2328 can_swizzle(srcFormat)) {
2329
2330 GLubyte dstmap[4];
2331
2332 /* dstmap - how to swizzle from RGBA to dst format:
2333 */
2334 if (dstFormat == &_mesa_texformat_a8) {
2335 dstmap[0] = 3;
2336 }
2337 else {
2338 dstmap[0] = 0;
2339 }
2340 dstmap[1] = ZERO; /* ? */
2341 dstmap[2] = ZERO; /* ? */
2342 dstmap[3] = ONE; /* ? */
2343
2344 _mesa_swizzle_ubyte_image(ctx, dims,
2345 srcFormat,
2346 srcType,
2347 baseInternalFormat,
2348 dstmap, 1,
2349 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2350 dstRowStride, dstImageOffsets,
2351 srcWidth, srcHeight, srcDepth, srcAddr,
2352 srcPacking);
2353 }
2354 else {
2355 /* general path */
2356 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2357 baseInternalFormat,
2358 dstFormat->BaseFormat,
2359 srcWidth, srcHeight, srcDepth,
2360 srcFormat, srcType, srcAddr,
2361 srcPacking);
2362 const GLchan *src = tempImage;
2363 GLint img, row, col;
2364 if (!tempImage)
2365 return GL_FALSE;
2366 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2367 for (img = 0; img < srcDepth; img++) {
2368 GLubyte *dstRow = (GLubyte *) dstAddr
2369 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2370 + dstYoffset * dstRowStride
2371 + dstXoffset * dstFormat->TexelBytes;
2372 for (row = 0; row < srcHeight; row++) {
2373 for (col = 0; col < srcWidth; col++) {
2374 dstRow[col] = CHAN_TO_UBYTE(src[col]);
2375 }
2376 dstRow += dstRowStride;
2377 src += srcWidth;
2378 }
2379 }
2380 _mesa_free((void *) tempImage);
2381 }
2382 return GL_TRUE;
2383 }
2384
2385
2386
2387 GLboolean
2388 _mesa_texstore_ci8(TEXSTORE_PARAMS)
2389 {
2390 (void) dims; (void) baseInternalFormat;
2391 ASSERT(dstFormat == &_mesa_texformat_ci8);
2392 ASSERT(dstFormat->TexelBytes == 1);
2393 ASSERT(baseInternalFormat == GL_COLOR_INDEX);
2394
2395 if (!ctx->_ImageTransferState &&
2396 !srcPacking->SwapBytes &&
2397 srcFormat == GL_COLOR_INDEX &&
2398 srcType == GL_UNSIGNED_BYTE) {
2399 /* simple memcpy path */
2400 memcpy_texture(ctx, dims,
2401 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2402 dstRowStride,
2403 dstImageOffsets,
2404 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2405 srcAddr, srcPacking);
2406 }
2407 else {
2408 /* general path */
2409 GLint img, row;
2410 for (img = 0; img < srcDepth; img++) {
2411 GLubyte *dstRow = (GLubyte *) dstAddr
2412 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2413 + dstYoffset * dstRowStride
2414 + dstXoffset * dstFormat->TexelBytes;
2415 for (row = 0; row < srcHeight; row++) {
2416 const GLvoid *src = _mesa_image_address(dims, srcPacking,
2417 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
2418 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
2419 srcType, src, srcPacking,
2420 ctx->_ImageTransferState);
2421 dstRow += dstRowStride;
2422 }
2423 }
2424 }
2425 return GL_TRUE;
2426 }
2427
2428
2429 /**
2430 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2431 */
2432 GLboolean
2433 _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
2434 {
2435 const GLboolean littleEndian = _mesa_little_endian();
2436 (void) ctx; (void) dims; (void) baseInternalFormat;
2437
2438 ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
2439 (dstFormat == &_mesa_texformat_ycbcr_rev));
2440 ASSERT(dstFormat->TexelBytes == 2);
2441 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
2442 ASSERT(srcFormat == GL_YCBCR_MESA);
2443 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
2444 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
2445 ASSERT(baseInternalFormat == GL_YCBCR_MESA);
2446
2447 /* always just memcpy since no pixel transfer ops apply */
2448 memcpy_texture(ctx, dims,
2449 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2450 dstRowStride,
2451 dstImageOffsets,
2452 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2453 srcAddr, srcPacking);
2454
2455 /* Check if we need byte swapping */
2456 /* XXX the logic here _might_ be wrong */
2457 if (srcPacking->SwapBytes ^
2458 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
2459 (dstFormat == &_mesa_texformat_ycbcr_rev) ^
2460 !littleEndian) {
2461 GLint img, row;
2462 for (img = 0; img < srcDepth; img++) {
2463 GLubyte *dstRow = (GLubyte *) dstAddr
2464 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2465 + dstYoffset * dstRowStride
2466 + dstXoffset * dstFormat->TexelBytes;
2467 for (row = 0; row < srcHeight; row++) {
2468 _mesa_swap2((GLushort *) dstRow, srcWidth);
2469 dstRow += dstRowStride;
2470 }
2471 }
2472 }
2473 return GL_TRUE;
2474 }
2475
2476 GLboolean
2477 _mesa_texstore_dudv8(TEXSTORE_PARAMS)
2478 {
2479 const GLboolean littleEndian = _mesa_little_endian();
2480
2481 ASSERT(dstFormat == &_mesa_texformat_dudv8);
2482 ASSERT(dstFormat->TexelBytes == 2);
2483 ASSERT(ctx->Extensions.ATI_envmap_bumpmap);
2484 ASSERT((srcFormat == GL_DU8DV8_ATI) ||
2485 (srcFormat == GL_DUDV_ATI));
2486 ASSERT(baseInternalFormat == GL_DUDV_ATI);
2487
2488 if (!srcPacking->SwapBytes && srcType == GL_BYTE &&
2489 littleEndian) {
2490 /* simple memcpy path */
2491 memcpy_texture(ctx, dims,
2492 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2493 dstRowStride,
2494 dstImageOffsets,
2495 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2496 srcAddr, srcPacking);
2497 }
2498 else if (srcType == GL_BYTE) {
2499
2500 GLubyte dstmap[4];
2501
2502 /* dstmap - how to swizzle from RGBA to dst format:
2503 */
2504 if (littleEndian) {
2505 dstmap[0] = 0;
2506 dstmap[1] = 3;
2507 }
2508 else {
2509 dstmap[0] = 3;
2510 dstmap[1] = 0;
2511 }
2512 dstmap[2] = ZERO; /* ? */
2513 dstmap[3] = ONE; /* ? */
2514
2515 _mesa_swizzle_ubyte_image(ctx, dims,
2516 GL_LUMINANCE_ALPHA, /* hack */
2517 GL_UNSIGNED_BYTE, /* hack */
2518 GL_LUMINANCE_ALPHA, /* hack */
2519 dstmap, 2,
2520 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2521 dstRowStride, dstImageOffsets,
2522 srcWidth, srcHeight, srcDepth, srcAddr,
2523 srcPacking);
2524 }
2525 else {
2526 /* general path - note this is defined for 2d textures only */
2527 const GLint components = _mesa_components_in_format(baseInternalFormat);
2528 const GLint srcStride = _mesa_image_row_stride(srcPacking,
2529 srcWidth, srcFormat, srcType);
2530 GLbyte *tempImage, *dst, *src;
2531 GLint row;
2532
2533 tempImage = (GLbyte *) _mesa_malloc(srcWidth * srcHeight * srcDepth
2534 * components * sizeof(GLbyte));
2535 if (!tempImage)
2536 return GL_FALSE;
2537
2538 src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr,
2539 srcWidth, srcHeight,
2540 srcFormat, srcType,
2541 0, 0, 0);
2542
2543 dst = tempImage;
2544 for (row = 0; row < srcHeight; row++) {
2545 _mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat,
2546 dst, srcFormat, srcType, src,
2547 srcPacking, 0);
2548 dst += srcWidth * components;
2549 src += srcStride;
2550 }
2551
2552 src = tempImage;
2553 dst = (GLbyte *) dstAddr
2554 + dstYoffset * dstRowStride
2555 + dstXoffset * dstFormat->TexelBytes;
2556 for (row = 0; row < srcHeight; row++) {
2557 memcpy(dst, src, srcWidth * dstFormat->TexelBytes);
2558 dst += dstRowStride;
2559 src += srcWidth * dstFormat->TexelBytes;
2560 }
2561 _mesa_free((void *) tempImage);
2562 }
2563 return GL_TRUE;
2564 }
2565
2566 /**
2567 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
2568 */
2569 GLboolean
2570 _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
2571 {
2572 const GLboolean littleEndian = _mesa_little_endian();
2573
2574 ASSERT(dstFormat == &_mesa_texformat_signed_rgba8888);
2575 ASSERT(dstFormat->TexelBytes == 4);
2576
2577 if (!ctx->_ImageTransferState &&
2578 !srcPacking->SwapBytes &&
2579 dstFormat == &_mesa_texformat_signed_rgba8888 &&
2580 baseInternalFormat == GL_RGBA &&
2581 ((srcFormat == GL_RGBA && srcType == GL_BYTE && !littleEndian) ||
2582 (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
2583 /* simple memcpy path */
2584 memcpy_texture(ctx, dims,
2585 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2586 dstRowStride,
2587 dstImageOffsets,
2588 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2589 srcAddr, srcPacking);
2590 }
2591 else if (!ctx->_ImageTransferState &&
2592 (srcType == GL_BYTE) &&
2593 can_swizzle(baseInternalFormat) &&
2594 can_swizzle(srcFormat)) {
2595
2596 GLubyte dstmap[4];
2597
2598 /* dstmap - how to swizzle from RGBA to dst format:
2599 */
2600 if (littleEndian && dstFormat == &_mesa_texformat_signed_rgba8888) {
2601 dstmap[3] = 0;
2602 dstmap[2] = 1;
2603 dstmap[1] = 2;
2604 dstmap[0] = 3;
2605 }
2606 else {
2607 dstmap[3] = 3;
2608 dstmap[2] = 2;
2609 dstmap[1] = 1;
2610 dstmap[0] = 0;
2611 }
2612
2613 _mesa_swizzle_ubyte_image(ctx, dims,
2614 srcFormat,
2615 srcType,
2616 baseInternalFormat,
2617 dstmap, 4,
2618 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2619 dstRowStride, dstImageOffsets,
2620 srcWidth, srcHeight, srcDepth, srcAddr,
2621 srcPacking);
2622 }
2623 else {
2624 /* general path */
2625 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2626 baseInternalFormat,
2627 dstFormat->BaseFormat,
2628 srcWidth, srcHeight, srcDepth,
2629 srcFormat, srcType, srcAddr,
2630 srcPacking);
2631 const GLfloat *srcRow = tempImage;
2632 GLint img, row, col;
2633 if (!tempImage)
2634 return GL_FALSE;
2635 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2636 for (img = 0; img < srcDepth; img++) {
2637 GLubyte *dstRow = (GLubyte *) dstAddr
2638 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2639 + dstYoffset * dstRowStride
2640 + dstXoffset * dstFormat->TexelBytes;
2641 for (row = 0; row < srcHeight; row++) {
2642 GLuint *dstUI = (GLuint *) dstRow;
2643 if (dstFormat == &_mesa_texformat_signed_rgba8888) {
2644 for (col = 0; col < srcWidth; col++) {
2645 dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
2646 FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
2647 FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
2648 FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
2649 srcRow += 4;
2650 }
2651 }
2652 dstRow += dstRowStride;
2653 }
2654 }
2655 _mesa_free((void *) tempImage);
2656 }
2657 return GL_TRUE;
2658 }
2659
2660 /**
2661 * Store a combined depth/stencil texture image.
2662 */
2663 GLboolean
2664 _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
2665 {
2666 const GLfloat depthScale = (GLfloat) 0xffffff;
2667
2668 ASSERT(dstFormat == &_mesa_texformat_z24_s8);
2669 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
2670 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
2671
2672 if (ctx->Pixel.DepthScale == 1.0f &&
2673 ctx->Pixel.DepthBias == 0.0f &&
2674 !srcPacking->SwapBytes) {
2675 /* simple path */
2676 memcpy_texture(ctx, dims,
2677 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2678 dstRowStride,
2679 dstImageOffsets,
2680 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2681 srcAddr, srcPacking);
2682 }
2683 else {
2684 /* general path */
2685 const GLint srcRowStride
2686 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
2687 / sizeof(GLuint);
2688 GLint img, row;
2689
2690 for (img = 0; img < srcDepth; img++) {
2691 GLuint *dstRow = (GLuint *) dstAddr
2692 + dstImageOffsets[dstZoffset + img]
2693 + dstYoffset * dstRowStride / sizeof(GLuint)
2694 + dstXoffset;
2695 const GLuint *src
2696 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2697 srcWidth, srcHeight,
2698 srcFormat, srcType,
2699 img, 0, 0);
2700 for (row = 0; row < srcHeight; row++) {
2701 GLubyte stencil[MAX_WIDTH];
2702 GLint i;
2703 /* the 24 depth bits will be in the high position: */
2704 _mesa_unpack_depth_span(ctx, srcWidth,
2705 GL_UNSIGNED_INT_24_8_EXT, /* dst type */
2706 dstRow, /* dst addr */
2707 (GLuint) depthScale,
2708 srcType, src, srcPacking);
2709 /* get the 8-bit stencil values */
2710 _mesa_unpack_stencil_span(ctx, srcWidth,
2711 GL_UNSIGNED_BYTE, /* dst type */
2712 stencil, /* dst addr */
2713 srcType, src, srcPacking,
2714 ctx->_ImageTransferState);
2715 /* merge stencil values into depth values */
2716 for (i = 0; i < srcWidth; i++)
2717 dstRow[i] |= stencil[i];
2718
2719 src += srcRowStride;
2720 dstRow += dstRowStride / sizeof(GLuint);
2721 }
2722 }
2723 }
2724 return GL_TRUE;
2725 }
2726
2727
2728 /**
2729 * Store a combined depth/stencil texture image.
2730 */
2731 GLboolean
2732 _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
2733 {
2734 const GLuint depthScale = 0xffffff;
2735 const GLint srcRowStride
2736 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
2737 / sizeof(GLuint);
2738 GLint img, row;
2739
2740 ASSERT(dstFormat == &_mesa_texformat_s8_z24);
2741 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
2742 ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
2743
2744 /* In case we only upload depth we need to preserve the stencil */
2745 if (srcFormat == GL_DEPTH_COMPONENT) {
2746 for (img = 0; img < srcDepth; img++) {
2747 GLuint *dstRow = (GLuint *) dstAddr
2748 + dstImageOffsets[dstZoffset + img]
2749 + dstYoffset * dstRowStride / sizeof(GLuint)
2750 + dstXoffset;
2751 const GLuint *src
2752 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2753 srcWidth, srcHeight,
2754 srcFormat, srcType,
2755 img, 0, 0);
2756 for (row = 0; row < srcHeight; row++) {
2757 GLuint depth[MAX_WIDTH];
2758 GLint i;
2759 _mesa_unpack_depth_span(ctx, srcWidth,
2760 GL_UNSIGNED_INT, /* dst type */
2761 depth, /* dst addr */
2762 depthScale,
2763 srcType, src, srcPacking);
2764
2765 for (i = 0; i < srcWidth; i++)
2766 dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
2767
2768 src += srcRowStride;
2769 dstRow += dstRowStride / sizeof(GLuint);
2770 }
2771 }
2772 }
2773 else {
2774 for (img = 0; img < srcDepth; img++) {
2775 GLuint *dstRow = (GLuint *) dstAddr
2776 + dstImageOffsets[dstZoffset + img]
2777 + dstYoffset * dstRowStride / sizeof(GLuint)
2778 + dstXoffset;
2779 const GLuint *src
2780 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2781 srcWidth, srcHeight,
2782 srcFormat, srcType,
2783 img, 0, 0);
2784 for (row = 0; row < srcHeight; row++) {
2785 GLubyte stencil[MAX_WIDTH];
2786 GLint i;
2787 /* the 24 depth bits will be in the low position: */
2788 _mesa_unpack_depth_span(ctx, srcWidth,
2789 GL_UNSIGNED_INT, /* dst type */
2790 dstRow, /* dst addr */
2791 depthScale,
2792 srcType, src, srcPacking);
2793 /* get the 8-bit stencil values */
2794 _mesa_unpack_stencil_span(ctx, srcWidth,
2795 GL_UNSIGNED_BYTE, /* dst type */
2796 stencil, /* dst addr */
2797 srcType, src, srcPacking,
2798 ctx->_ImageTransferState);
2799 /* merge stencil values into depth values */
2800 for (i = 0; i < srcWidth; i++)
2801 dstRow[i] |= stencil[i] << 24;
2802
2803 src += srcRowStride;
2804 dstRow += dstRowStride / sizeof(GLuint);
2805 }
2806 }
2807 }
2808 return GL_TRUE;
2809 }
2810
2811 /**
2812 * Store an image in any of the formats:
2813 * _mesa_texformat_rgba_float32
2814 * _mesa_texformat_rgb_float32
2815 * _mesa_texformat_alpha_float32
2816 * _mesa_texformat_luminance_float32
2817 * _mesa_texformat_luminance_alpha_float32
2818 * _mesa_texformat_intensity_float32
2819 */
2820 GLboolean
2821 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
2822 {
2823 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
2824
2825 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
2826 dstFormat == &_mesa_texformat_rgb_float32 ||
2827 dstFormat == &_mesa_texformat_alpha_float32 ||
2828 dstFormat == &_mesa_texformat_luminance_float32 ||
2829 dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
2830 dstFormat == &_mesa_texformat_intensity_float32);
2831 ASSERT(baseInternalFormat == GL_RGBA ||
2832 baseInternalFormat == GL_RGB ||
2833 baseInternalFormat == GL_ALPHA ||
2834 baseInternalFormat == GL_LUMINANCE ||
2835 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2836 baseInternalFormat == GL_INTENSITY);
2837 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
2838
2839 if (!ctx->_ImageTransferState &&
2840 !srcPacking->SwapBytes &&
2841 baseInternalFormat == srcFormat &&
2842 srcType == GL_FLOAT) {
2843 /* simple memcpy path */
2844 memcpy_texture(ctx, dims,
2845 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2846 dstRowStride,
2847 dstImageOffsets,
2848 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2849 srcAddr, srcPacking);
2850 }
2851 else {
2852 /* general path */
2853 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2854 baseInternalFormat,
2855 dstFormat->BaseFormat,
2856 srcWidth, srcHeight, srcDepth,
2857 srcFormat, srcType, srcAddr,
2858 srcPacking);
2859 const GLfloat *srcRow = tempImage;
2860 GLint bytesPerRow;
2861 GLint img, row;
2862 if (!tempImage)
2863 return GL_FALSE;
2864 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2865 bytesPerRow = srcWidth * components * sizeof(GLfloat);
2866 for (img = 0; img < srcDepth; img++) {
2867 GLubyte *dstRow = (GLubyte *) dstAddr
2868 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2869 + dstYoffset * dstRowStride
2870 + dstXoffset * dstFormat->TexelBytes;
2871 for (row = 0; row < srcHeight; row++) {
2872 _mesa_memcpy(dstRow, srcRow, bytesPerRow);
2873 dstRow += dstRowStride;
2874 srcRow += srcWidth * components;
2875 }
2876 }
2877
2878 _mesa_free((void *) tempImage);
2879 }
2880 return GL_TRUE;
2881 }
2882
2883
2884 /**
2885 * As above, but store 16-bit floats.
2886 */
2887 GLboolean
2888 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
2889 {
2890 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
2891
2892 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
2893 dstFormat == &_mesa_texformat_rgb_float16 ||
2894 dstFormat == &_mesa_texformat_alpha_float16 ||
2895 dstFormat == &_mesa_texformat_luminance_float16 ||
2896 dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
2897 dstFormat == &_mesa_texformat_intensity_float16);
2898 ASSERT(baseInternalFormat == GL_RGBA ||
2899 baseInternalFormat == GL_RGB ||
2900 baseInternalFormat == GL_ALPHA ||
2901 baseInternalFormat == GL_LUMINANCE ||
2902 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2903 baseInternalFormat == GL_INTENSITY);
2904 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
2905
2906 if (!ctx->_ImageTransferState &&
2907 !srcPacking->SwapBytes &&
2908 baseInternalFormat == srcFormat &&
2909 srcType == GL_HALF_FLOAT_ARB) {
2910 /* simple memcpy path */
2911 memcpy_texture(ctx, dims,
2912 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2913 dstRowStride,
2914 dstImageOffsets,
2915 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2916 srcAddr, srcPacking);
2917 }
2918 else {
2919 /* general path */
2920 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2921 baseInternalFormat,
2922 dstFormat->BaseFormat,
2923 srcWidth, srcHeight, srcDepth,
2924 srcFormat, srcType, srcAddr,
2925 srcPacking);
2926 const GLfloat *src = tempImage;
2927 GLint img, row;
2928 if (!tempImage)
2929 return GL_FALSE;
2930 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2931 for (img = 0; img < srcDepth; img++) {
2932 GLubyte *dstRow = (GLubyte *) dstAddr
2933 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2934 + dstYoffset * dstRowStride
2935 + dstXoffset * dstFormat->TexelBytes;
2936 for (row = 0; row < srcHeight; row++) {
2937 GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
2938 GLint i;
2939 for (i = 0; i < srcWidth * components; i++) {
2940 dstTexel[i] = _mesa_float_to_half(src[i]);
2941 }
2942 dstRow += dstRowStride;
2943 src += srcWidth * components;
2944 }
2945 }
2946
2947 _mesa_free((void *) tempImage);
2948 }
2949 return GL_TRUE;
2950 }
2951
2952
2953 #if FEATURE_EXT_texture_sRGB
2954 GLboolean
2955 _mesa_texstore_srgb8(TEXSTORE_PARAMS)
2956 {
2957 const struct gl_texture_format *newDstFormat;
2958 StoreTexImageFunc store;
2959 GLboolean k;
2960
2961 ASSERT(dstFormat == &_mesa_texformat_srgb8);
2962
2963 /* reuse normal rgb texstore code */
2964 newDstFormat = &_mesa_texformat_rgb888;
2965 store = _mesa_texstore_rgb888;
2966
2967 k = store(ctx, dims, baseInternalFormat,
2968 newDstFormat, dstAddr,
2969 dstXoffset, dstYoffset, dstZoffset,
2970 dstRowStride, dstImageOffsets,
2971 srcWidth, srcHeight, srcDepth,
2972 srcFormat, srcType,
2973 srcAddr, srcPacking);
2974 return k;
2975 }
2976
2977
2978 GLboolean
2979 _mesa_texstore_srgba8(TEXSTORE_PARAMS)
2980 {
2981 const struct gl_texture_format *newDstFormat;
2982 GLboolean k;
2983
2984 ASSERT(dstFormat == &_mesa_texformat_srgba8);
2985
2986 /* reuse normal rgba texstore code */
2987 newDstFormat = &_mesa_texformat_rgba8888;
2988
2989 k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
2990 newDstFormat, dstAddr,
2991 dstXoffset, dstYoffset, dstZoffset,
2992 dstRowStride, dstImageOffsets,
2993 srcWidth, srcHeight, srcDepth,
2994 srcFormat, srcType,
2995 srcAddr, srcPacking);
2996 return k;
2997 }
2998
2999
3000 GLboolean
3001 _mesa_texstore_sargb8(TEXSTORE_PARAMS)
3002 {
3003 const struct gl_texture_format *newDstFormat;
3004 GLboolean k;
3005
3006 ASSERT(dstFormat == &_mesa_texformat_sargb8);
3007
3008 /* reuse normal rgba texstore code */
3009 newDstFormat = &_mesa_texformat_argb8888;
3010
3011 k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
3012 newDstFormat, dstAddr,
3013 dstXoffset, dstYoffset, dstZoffset,
3014 dstRowStride, dstImageOffsets,
3015 srcWidth, srcHeight, srcDepth,
3016 srcFormat, srcType,
3017 srcAddr, srcPacking);
3018 return k;
3019 }
3020
3021
3022 GLboolean
3023 _mesa_texstore_sl8(TEXSTORE_PARAMS)
3024 {
3025 const struct gl_texture_format *newDstFormat;
3026 GLboolean k;
3027
3028 ASSERT(dstFormat == &_mesa_texformat_sl8);
3029
3030 newDstFormat = &_mesa_texformat_l8;
3031
3032 /* _mesa_textore_a8 handles luminance8 too */
3033 k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
3034 newDstFormat, dstAddr,
3035 dstXoffset, dstYoffset, dstZoffset,
3036 dstRowStride, dstImageOffsets,
3037 srcWidth, srcHeight, srcDepth,
3038 srcFormat, srcType,
3039 srcAddr, srcPacking);
3040 return k;
3041 }
3042
3043
3044 GLboolean
3045 _mesa_texstore_sla8(TEXSTORE_PARAMS)
3046 {
3047 const struct gl_texture_format *newDstFormat;
3048 GLboolean k;
3049
3050 ASSERT(dstFormat == &_mesa_texformat_sla8);
3051
3052 /* reuse normal luminance/alpha texstore code */
3053 newDstFormat = &_mesa_texformat_al88;
3054
3055 k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
3056 newDstFormat, dstAddr,
3057 dstXoffset, dstYoffset, dstZoffset,
3058 dstRowStride, dstImageOffsets,
3059 srcWidth, srcHeight, srcDepth,
3060 srcFormat, srcType,
3061 srcAddr, srcPacking);
3062 return k;
3063 }
3064
3065 #endif /* FEATURE_EXT_texture_sRGB */
3066
3067
3068 /**
3069 * Check if an unpack PBO is active prior to fetching a texture image.
3070 * If so, do bounds checking and map the buffer into main memory.
3071 * Any errors detected will be recorded.
3072 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
3073 */
3074 const GLvoid *
3075 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
3076 GLsizei width, GLsizei height, GLsizei depth,
3077 GLenum format, GLenum type, const GLvoid *pixels,
3078 const struct gl_pixelstore_attrib *unpack,
3079 const char *funcName)
3080 {
3081 GLubyte *buf;
3082
3083 if (unpack->BufferObj->Name == 0) {
3084 /* no PBO */
3085 return pixels;
3086 }
3087 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
3088 format, type, pixels)) {
3089 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
3090 return NULL;
3091 }
3092
3093 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
3094 GL_READ_ONLY_ARB, unpack->BufferObj);
3095 if (!buf) {
3096 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
3097 return NULL;
3098 }
3099
3100 return ADD_POINTERS(buf, pixels);
3101 }
3102
3103
3104 /**
3105 * Check if an unpack PBO is active prior to fetching a compressed texture
3106 * image.
3107 * If so, do bounds checking and map the buffer into main memory.
3108 * Any errors detected will be recorded.
3109 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
3110 */
3111 const GLvoid *
3112 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
3113 GLsizei imageSize, const GLvoid *pixels,
3114 const struct gl_pixelstore_attrib *packing,
3115 const char *funcName)
3116 {
3117 GLubyte *buf;
3118
3119 if (packing->BufferObj->Name == 0) {
3120 /* not using a PBO - return pointer unchanged */
3121 return pixels;
3122 }
3123 if ((const GLubyte *) pixels + imageSize >
3124 ((const GLubyte *) 0) + packing->BufferObj->Size) {
3125 /* out of bounds read! */
3126 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
3127 return NULL;
3128 }
3129
3130 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
3131 GL_READ_ONLY_ARB, packing->BufferObj);
3132 if (!buf) {
3133 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
3134 return NULL;
3135 }
3136
3137 return ADD_POINTERS(buf, pixels);
3138 }
3139
3140
3141 /**
3142 * This function must be called after either of the validate_pbo_*_teximage()
3143 * functions. It unmaps the PBO buffer if it was mapped earlier.
3144 */
3145 void
3146 _mesa_unmap_teximage_pbo(GLcontext *ctx,
3147 const struct gl_pixelstore_attrib *unpack)
3148 {
3149 if (unpack->BufferObj->Name) {
3150 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
3151 unpack->BufferObj);
3152 }
3153 }
3154
3155
3156
3157 /**
3158 * Adaptor for fetching a GLchan texel from a float-valued texture.
3159 */
3160 static void
3161 fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
3162 GLint i, GLint j, GLint k, GLchan *texelOut)
3163 {
3164 GLfloat temp[4];
3165 ASSERT(texImage->FetchTexelf);
3166 texImage->FetchTexelf(texImage, i, j, k, temp);
3167 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
3168 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
3169 /* just one channel */
3170 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
3171 }
3172 else {
3173 /* four channels */
3174 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
3175 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
3176 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
3177 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
3178 }
3179 }
3180
3181
3182 /**
3183 * Adaptor for fetching a float texel from a GLchan-valued texture.
3184 */
3185 static void
3186 fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
3187 GLint i, GLint j, GLint k, GLfloat *texelOut)
3188 {
3189 GLchan temp[4];
3190 ASSERT(texImage->FetchTexelc);
3191 texImage->FetchTexelc(texImage, i, j, k, temp);
3192 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
3193 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
3194 /* just one channel */
3195 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
3196 }
3197 else {
3198 /* four channels */
3199 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
3200 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
3201 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
3202 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
3203 }
3204 }
3205
3206
3207 /**
3208 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
3209 */
3210 void
3211 _mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
3212 {
3213 ASSERT(dims == 1 || dims == 2 || dims == 3);
3214 ASSERT(texImage->TexFormat);
3215
3216 switch (dims) {
3217 case 1:
3218 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
3219 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
3220 break;
3221 case 2:
3222 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
3223 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
3224 break;
3225 case 3:
3226 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
3227 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
3228 break;
3229 default:
3230 ;
3231 }
3232
3233 /* now check if we need to use a float/chan adaptor */
3234 if (!texImage->FetchTexelc) {
3235 texImage->FetchTexelc = fetch_texel_float_to_chan;
3236 }
3237 else if (!texImage->FetchTexelf) {
3238 texImage->FetchTexelf = fetch_texel_chan_to_float;
3239 }
3240
3241
3242 ASSERT(texImage->FetchTexelc);
3243 ASSERT(texImage->FetchTexelf);
3244 }
3245
3246
3247 /**
3248 * Choose the actual storage format for a new texture image.
3249 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
3250 * Also set some other texImage fields related to texture compression, etc.
3251 * \param ctx rendering context
3252 * \param texImage the gl_texture_image
3253 * \param dims texture dimensions (1, 2 or 3)
3254 * \param format the user-specified format parameter
3255 * \param type the user-specified type parameter
3256 * \param internalFormat the user-specified internal format hint
3257 */
3258 static void
3259 choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage,
3260 GLuint dims,
3261 GLenum format, GLenum type, GLint internalFormat)
3262 {
3263 ASSERT(dims == 1 || dims == 2 || dims == 3);
3264 ASSERT(ctx->Driver.ChooseTextureFormat);
3265
3266 texImage->TexFormat
3267 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
3268
3269 ASSERT(texImage->TexFormat);
3270
3271 _mesa_set_fetch_functions(texImage, dims);
3272
3273 if (texImage->TexFormat->TexelBytes == 0) {
3274 /* must be a compressed format */
3275 texImage->IsCompressed = GL_TRUE;
3276 texImage->CompressedSize =
3277 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
3278 texImage->Height, texImage->Depth,
3279 texImage->TexFormat->MesaFormat);
3280 }
3281 else {
3282 /* non-compressed format */
3283 texImage->IsCompressed = GL_FALSE;
3284 texImage->CompressedSize = 0;
3285 }
3286 }
3287
3288
3289
3290 /**
3291 * This is the software fallback for Driver.TexImage1D()
3292 * and Driver.CopyTexImage1D().
3293 * \sa _mesa_store_teximage2d()
3294 * Note that the width may not be the actual texture width since it may
3295 * be changed by convolution w/ GL_REDUCE. The texImage->Width field will
3296 * have the actual texture size.
3297 */
3298 void
3299 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3300 GLint internalFormat,
3301 GLint width, GLint border,
3302 GLenum format, GLenum type, const GLvoid *pixels,
3303 const struct gl_pixelstore_attrib *packing,
3304 struct gl_texture_object *texObj,
3305 struct gl_texture_image *texImage)
3306 {
3307 GLint sizeInBytes;
3308 (void) border;
3309
3310 choose_texture_format(ctx, texImage, 1, format, type, internalFormat);
3311
3312 /* allocate memory */
3313 if (texImage->IsCompressed)
3314 sizeInBytes = texImage->CompressedSize;
3315 else
3316 sizeInBytes = texImage->Width * texImage->TexFormat->TexelBytes;
3317 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3318 if (!texImage->Data) {
3319 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
3320 return;
3321 }
3322
3323 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3324 pixels, packing, "glTexImage1D");
3325 if (!pixels) {
3326 /* Note: we check for a NULL image pointer here, _after_ we allocated
3327 * memory for the texture. That's what the GL spec calls for.
3328 */
3329 return;
3330 }
3331 else {
3332 const GLint dstRowStride = 0;
3333 GLboolean success;
3334 ASSERT(texImage->TexFormat->StoreImage);
3335 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
3336 texImage->TexFormat,
3337 texImage->Data,
3338 0, 0, 0, /* dstX/Y/Zoffset */
3339 dstRowStride,
3340 texImage->ImageOffsets,
3341 width, 1, 1,
3342 format, type, pixels, packing);
3343 if (!success) {
3344 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
3345 }
3346 }
3347
3348 /* GL_SGIS_generate_mipmap */
3349 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3350 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3351 }
3352
3353 _mesa_unmap_teximage_pbo(ctx, packing);
3354 }
3355
3356
3357 /**
3358 * This is the software fallback for Driver.TexImage2D()
3359 * and Driver.CopyTexImage2D().
3360 *
3361 * This function is oriented toward storing images in main memory, rather
3362 * than VRAM. Device driver's can easily plug in their own replacement.
3363 *
3364 * Note: width and height may be pre-convolved dimensions, but
3365 * texImage->Width and texImage->Height will be post-convolved dimensions.
3366 */
3367 void
3368 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3369 GLint internalFormat,
3370 GLint width, GLint height, GLint border,
3371 GLenum format, GLenum type, const void *pixels,
3372 const struct gl_pixelstore_attrib *packing,
3373 struct gl_texture_object *texObj,
3374 struct gl_texture_image *texImage)
3375 {
3376 GLint texelBytes, sizeInBytes;
3377 (void) border;
3378
3379 choose_texture_format(ctx, texImage, 2, format, type, internalFormat);
3380
3381 texelBytes = texImage->TexFormat->TexelBytes;
3382
3383 /* allocate memory */
3384 if (texImage->IsCompressed)
3385 sizeInBytes = texImage->CompressedSize;
3386 else
3387 sizeInBytes = texImage->Width * texImage->Height * texelBytes;
3388 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3389 if (!texImage->Data) {
3390 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
3391 return;
3392 }
3393
3394 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3395 pixels, packing, "glTexImage2D");
3396 if (!pixels) {
3397 /* Note: we check for a NULL image pointer here, _after_ we allocated
3398 * memory for the texture. That's what the GL spec calls for.
3399 */
3400 return;
3401 }
3402 else {
3403 GLint dstRowStride;
3404 GLboolean success;
3405 if (texImage->IsCompressed) {
3406 dstRowStride
3407 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3408 }
3409 else {
3410 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3411 }
3412 ASSERT(texImage->TexFormat->StoreImage);
3413 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
3414 texImage->TexFormat,
3415 texImage->Data,
3416 0, 0, 0, /* dstX/Y/Zoffset */
3417 dstRowStride,
3418 texImage->ImageOffsets,
3419 width, height, 1,
3420 format, type, pixels, packing);
3421 if (!success) {
3422 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
3423 }
3424 }
3425
3426 /* GL_SGIS_generate_mipmap */
3427 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3428 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3429 }
3430
3431 _mesa_unmap_teximage_pbo(ctx, packing);
3432 }
3433
3434
3435
3436 /**
3437 * This is the software fallback for Driver.TexImage3D()
3438 * and Driver.CopyTexImage3D().
3439 * \sa _mesa_store_teximage2d()
3440 */
3441 void
3442 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3443 GLint internalFormat,
3444 GLint width, GLint height, GLint depth, GLint border,
3445 GLenum format, GLenum type, const void *pixels,
3446 const struct gl_pixelstore_attrib *packing,
3447 struct gl_texture_object *texObj,
3448 struct gl_texture_image *texImage)
3449 {
3450 GLint texelBytes, sizeInBytes;
3451 (void) border;
3452
3453 choose_texture_format(ctx, texImage, 3, format, type, internalFormat);
3454
3455 texelBytes = texImage->TexFormat->TexelBytes;
3456
3457 /* allocate memory */
3458 if (texImage->IsCompressed)
3459 sizeInBytes = texImage->CompressedSize;
3460 else
3461 sizeInBytes = width * height * depth * texelBytes;
3462 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3463 if (!texImage->Data) {
3464 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3465 return;
3466 }
3467
3468 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3469 type, pixels, packing, "glTexImage3D");
3470 if (!pixels) {
3471 /* Note: we check for a NULL image pointer here, _after_ we allocated
3472 * memory for the texture. That's what the GL spec calls for.
3473 */
3474 return;
3475 }
3476 else {
3477 GLint dstRowStride;
3478 GLboolean success;
3479 if (texImage->IsCompressed) {
3480 dstRowStride
3481 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3482 }
3483 else {
3484 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3485 }
3486 ASSERT(texImage->TexFormat->StoreImage);
3487 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
3488 texImage->TexFormat,
3489 texImage->Data,
3490 0, 0, 0, /* dstX/Y/Zoffset */
3491 dstRowStride,
3492 texImage->ImageOffsets,
3493 width, height, depth,
3494 format, type, pixels, packing);
3495 if (!success) {
3496 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3497 }
3498 }
3499
3500 /* GL_SGIS_generate_mipmap */
3501 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3502 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3503 }
3504
3505 _mesa_unmap_teximage_pbo(ctx, packing);
3506 }
3507
3508
3509
3510
3511 /*
3512 * This is the software fallback for Driver.TexSubImage1D()
3513 * and Driver.CopyTexSubImage1D().
3514 */
3515 void
3516 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
3517 GLint xoffset, GLint width,
3518 GLenum format, GLenum type, const void *pixels,
3519 const struct gl_pixelstore_attrib *packing,
3520 struct gl_texture_object *texObj,
3521 struct gl_texture_image *texImage)
3522 {
3523 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3524 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3525 pixels, packing, "glTexSubImage1D");
3526 if (!pixels)
3527 return;
3528
3529 {
3530 const GLint dstRowStride = 0;
3531 GLboolean success;
3532 ASSERT(texImage->TexFormat->StoreImage);
3533 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
3534 texImage->TexFormat,
3535 texImage->Data,
3536 xoffset, 0, 0, /* offsets */
3537 dstRowStride,
3538 texImage->ImageOffsets,
3539 width, 1, 1,
3540 format, type, pixels, packing);
3541 if (!success) {
3542 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
3543 }
3544 }
3545
3546 /* GL_SGIS_generate_mipmap */
3547 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3548 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3549 }
3550
3551 _mesa_unmap_teximage_pbo(ctx, packing);
3552 }
3553
3554
3555
3556 /**
3557 * This is the software fallback for Driver.TexSubImage2D()
3558 * and Driver.CopyTexSubImage2D().
3559 */
3560 void
3561 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
3562 GLint xoffset, GLint yoffset,
3563 GLint width, GLint height,
3564 GLenum format, GLenum type, const void *pixels,
3565 const struct gl_pixelstore_attrib *packing,
3566 struct gl_texture_object *texObj,
3567 struct gl_texture_image *texImage)
3568 {
3569 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3570 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3571 pixels, packing, "glTexSubImage2D");
3572 if (!pixels)
3573 return;
3574
3575 {
3576 GLint dstRowStride = 0;
3577 GLboolean success;
3578 if (texImage->IsCompressed) {
3579 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3580 texImage->Width);
3581 }
3582 else {
3583 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3584 }
3585 ASSERT(texImage->TexFormat->StoreImage);
3586 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
3587 texImage->TexFormat,
3588 texImage->Data,
3589 xoffset, yoffset, 0,
3590 dstRowStride,
3591 texImage->ImageOffsets,
3592 width, height, 1,
3593 format, type, pixels, packing);
3594 if (!success) {
3595 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
3596 }
3597 }
3598
3599 /* GL_SGIS_generate_mipmap */
3600 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3601 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3602 }
3603
3604 _mesa_unmap_teximage_pbo(ctx, packing);
3605 }
3606
3607
3608 /*
3609 * This is the software fallback for Driver.TexSubImage3D().
3610 * and Driver.CopyTexSubImage3D().
3611 */
3612 void
3613 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
3614 GLint xoffset, GLint yoffset, GLint zoffset,
3615 GLint width, GLint height, GLint depth,
3616 GLenum format, GLenum type, const void *pixels,
3617 const struct gl_pixelstore_attrib *packing,
3618 struct gl_texture_object *texObj,
3619 struct gl_texture_image *texImage)
3620 {
3621 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3622 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3623 type, pixels, packing,
3624 "glTexSubImage3D");
3625 if (!pixels)
3626 return;
3627
3628 {
3629 GLint dstRowStride;
3630 GLboolean success;
3631 if (texImage->IsCompressed) {
3632 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3633 texImage->Width);
3634 }
3635 else {
3636 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3637 }
3638 ASSERT(texImage->TexFormat->StoreImage);
3639 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
3640 texImage->TexFormat,
3641 texImage->Data,
3642 xoffset, yoffset, zoffset,
3643 dstRowStride,
3644 texImage->ImageOffsets,
3645 width, height, depth,
3646 format, type, pixels, packing);
3647 if (!success) {
3648 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
3649 }
3650 }
3651
3652 /* GL_SGIS_generate_mipmap */
3653 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3654 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3655 }
3656
3657 _mesa_unmap_teximage_pbo(ctx, packing);
3658 }
3659
3660
3661 /*
3662 * Fallback for Driver.CompressedTexImage1D()
3663 */
3664 void
3665 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3666 GLint internalFormat,
3667 GLint width, GLint border,
3668 GLsizei imageSize, const GLvoid *data,
3669 struct gl_texture_object *texObj,
3670 struct gl_texture_image *texImage)
3671 {
3672 /* this space intentionally left blank */
3673 (void) ctx;
3674 (void) target; (void) level;
3675 (void) internalFormat;
3676 (void) width; (void) border;
3677 (void) imageSize; (void) data;
3678 (void) texObj;
3679 (void) texImage;
3680 }
3681
3682
3683
3684 /**
3685 * Fallback for Driver.CompressedTexImage2D()
3686 */
3687 void
3688 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3689 GLint internalFormat,
3690 GLint width, GLint height, GLint border,
3691 GLsizei imageSize, const GLvoid *data,
3692 struct gl_texture_object *texObj,
3693 struct gl_texture_image *texImage)
3694 {
3695 (void) width; (void) height; (void) border;
3696
3697 /* This is pretty simple, basically just do a memcpy without worrying
3698 * about the usual image unpacking or image transfer operations.
3699 */
3700 ASSERT(texObj);
3701 ASSERT(texImage);
3702 ASSERT(texImage->Width > 0);
3703 ASSERT(texImage->Height > 0);
3704 ASSERT(texImage->Depth == 1);
3705 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
3706
3707 choose_texture_format(ctx, texImage, 2, 0, 0, internalFormat);
3708
3709 /* allocate storage */
3710 texImage->Data = _mesa_alloc_texmemory(imageSize);
3711 if (!texImage->Data) {
3712 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3713 return;
3714 }
3715
3716 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3717 &ctx->Unpack,
3718 "glCompressedTexImage2D");
3719 if (!data)
3720 return;
3721
3722 /* copy the data */
3723 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
3724 MEMCPY(texImage->Data, data, imageSize);
3725
3726 /* GL_SGIS_generate_mipmap */
3727 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3728 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3729 }
3730
3731 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3732 }
3733
3734
3735
3736 /*
3737 * Fallback for Driver.CompressedTexImage3D()
3738 */
3739 void
3740 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3741 GLint internalFormat,
3742 GLint width, GLint height, GLint depth,
3743 GLint border,
3744 GLsizei imageSize, const GLvoid *data,
3745 struct gl_texture_object *texObj,
3746 struct gl_texture_image *texImage)
3747 {
3748 /* this space intentionally left blank */
3749 (void) ctx;
3750 (void) target; (void) level;
3751 (void) internalFormat;
3752 (void) width; (void) height; (void) depth;
3753 (void) border;
3754 (void) imageSize; (void) data;
3755 (void) texObj;
3756 (void) texImage;
3757 }
3758
3759
3760
3761 /**
3762 * Fallback for Driver.CompressedTexSubImage1D()
3763 */
3764 void
3765 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
3766 GLint level,
3767 GLint xoffset, GLsizei width,
3768 GLenum format,
3769 GLsizei imageSize, const GLvoid *data,
3770 struct gl_texture_object *texObj,
3771 struct gl_texture_image *texImage)
3772 {
3773 /* there are no compressed 1D texture formats yet */
3774 (void) ctx;
3775 (void) target; (void) level;
3776 (void) xoffset; (void) width;
3777 (void) format;
3778 (void) imageSize; (void) data;
3779 (void) texObj;
3780 (void) texImage;
3781 }
3782
3783
3784 /**
3785 * Fallback for Driver.CompressedTexSubImage2D()
3786 */
3787 void
3788 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
3789 GLint level,
3790 GLint xoffset, GLint yoffset,
3791 GLsizei width, GLsizei height,
3792 GLenum format,
3793 GLsizei imageSize, const GLvoid *data,
3794 struct gl_texture_object *texObj,
3795 struct gl_texture_image *texImage)
3796 {
3797 GLint bytesPerRow, destRowStride, srcRowStride;
3798 GLint i, rows;
3799 GLubyte *dest;
3800 const GLubyte *src;
3801 const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
3802
3803 (void) format;
3804
3805 /* these should have been caught sooner */
3806 ASSERT((width & 3) == 0 || width == 2 || width == 1);
3807 ASSERT((height & 3) == 0 || height == 2 || height == 1);
3808 ASSERT((xoffset & 3) == 0);
3809 ASSERT((yoffset & 3) == 0);
3810
3811 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3812 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3813 &ctx->Unpack,
3814 "glCompressedTexSubImage2D");
3815 if (!data)
3816 return;
3817
3818 srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
3819 src = (const GLubyte *) data;
3820
3821 destRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width);
3822 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
3823 texImage->TexFormat->MesaFormat,
3824 texImage->Width,
3825 (GLubyte *) texImage->Data);
3826
3827 bytesPerRow = srcRowStride;
3828 rows = height / 4;
3829
3830 for (i = 0; i < rows; i++) {
3831 MEMCPY(dest, src, bytesPerRow);
3832 dest += destRowStride;
3833 src += srcRowStride;
3834 }
3835
3836 /* GL_SGIS_generate_mipmap */
3837 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3838 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3839 }
3840
3841 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3842 }
3843
3844
3845 /**
3846 * Fallback for Driver.CompressedTexSubImage3D()
3847 */
3848 void
3849 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
3850 GLint level,
3851 GLint xoffset, GLint yoffset, GLint zoffset,
3852 GLsizei width, GLsizei height, GLsizei depth,
3853 GLenum format,
3854 GLsizei imageSize, const GLvoid *data,
3855 struct gl_texture_object *texObj,
3856 struct gl_texture_image *texImage)
3857 {
3858 /* there are no compressed 3D texture formats yet */
3859 (void) ctx;
3860 (void) target; (void) level;
3861 (void) xoffset; (void) yoffset; (void) zoffset;
3862 (void) width; (void) height; (void) depth;
3863 (void) format;
3864 (void) imageSize; (void) data;
3865 (void) texObj;
3866 (void) texImage;
3867 }
3868
3869
3870
3871
3872 #if FEATURE_EXT_texture_sRGB
3873
3874 /**
3875 * Test if given texture image is an sRGB format.
3876 */
3877 static GLboolean
3878 is_srgb_teximage(const struct gl_texture_image *texImage)
3879 {
3880 switch (texImage->TexFormat->MesaFormat) {
3881 case MESA_FORMAT_SRGB8:
3882 case MESA_FORMAT_SRGBA8:
3883 case MESA_FORMAT_SARGB8:
3884 case MESA_FORMAT_SL8:
3885 case MESA_FORMAT_SLA8:
3886 case MESA_FORMAT_SRGB_DXT1:
3887 case MESA_FORMAT_SRGBA_DXT1:
3888 case MESA_FORMAT_SRGBA_DXT3:
3889 case MESA_FORMAT_SRGBA_DXT5:
3890 return GL_TRUE;
3891 default:
3892 return GL_FALSE;
3893 }
3894 }
3895
3896
3897 /**
3898 * Convert a float value from linear space to a
3899 * non-linear sRGB value in [0, 255].
3900 * Not terribly efficient.
3901 */
3902 static INLINE GLfloat
3903 linear_to_nonlinear(GLfloat cl)
3904 {
3905 /* can't have values outside [0, 1] */
3906 GLfloat cs;
3907 if (cl < 0.0031308) {
3908 cs = 12.92 * cl;
3909 }
3910 else {
3911 cs = 1.055 * _mesa_pow(cl, 0.41666) - 0.055;
3912 }
3913 return cs;
3914 }
3915
3916 #endif /* FEATURE_EXT_texture_sRGB */
3917
3918 static INLINE GLboolean
3919 type_with_negative_values(GLenum type)
3920 {
3921 switch (type) {
3922 case GL_BYTE:
3923 case GL_SHORT:
3924 case GL_INT:
3925 case GL_FLOAT:
3926 case GL_HALF_FLOAT_ARB:
3927 return GL_TRUE;
3928 default:
3929 return GL_FALSE;
3930 }
3931 }
3932
3933 /**
3934 * This is the software fallback for Driver.GetTexImage().
3935 * All error checking will have been done before this routine is called.
3936 */
3937 void
3938 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
3939 GLenum format, GLenum type, GLvoid *pixels,
3940 struct gl_texture_object *texObj,
3941 struct gl_texture_image *texImage)
3942 {
3943 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
3944
3945 if (ctx->Pack.BufferObj->Name) {
3946 /* Packing texture image into a PBO.
3947 * Map the (potentially) VRAM-based buffer into our process space so
3948 * we can write into it with the code below.
3949 * A hardware driver might use a sophisticated blit to move the
3950 * texture data to the PBO if the PBO is in VRAM along with the texture.
3951 */
3952 GLubyte *buf = (GLubyte *)
3953 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3954 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
3955 if (!buf) {
3956 /* buffer is already mapped - that's an error */
3957 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
3958 return;
3959 }
3960 /* <pixels> was an offset into the PBO.
3961 * Now make it a real, client-side pointer inside the mapped region.
3962 */
3963 pixels = ADD_POINTERS(buf, pixels);
3964 }
3965 else if (!pixels) {
3966 /* not an error */
3967 return;
3968 }
3969
3970 {
3971 const GLint width = texImage->Width;
3972 const GLint height = texImage->Height;
3973 const GLint depth = texImage->Depth;
3974 GLint img, row;
3975 for (img = 0; img < depth; img++) {
3976 for (row = 0; row < height; row++) {
3977 /* compute destination address in client memory */
3978 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
3979 width, height, format, type,
3980 img, row, 0);
3981 assert(dest);
3982
3983 if (format == GL_COLOR_INDEX) {
3984 GLuint indexRow[MAX_WIDTH];
3985 GLint col;
3986 /* Can't use FetchTexel here because that returns RGBA */
3987 if (texImage->TexFormat->IndexBits == 8) {
3988 const GLubyte *src = (const GLubyte *) texImage->Data;
3989 src += width * (img * texImage->Height + row);
3990 for (col = 0; col < width; col++) {
3991 indexRow[col] = src[col];
3992 }
3993 }
3994 else if (texImage->TexFormat->IndexBits == 16) {
3995 const GLushort *src = (const GLushort *) texImage->Data;
3996 src += width * (img * texImage->Height + row);
3997 for (col = 0; col < width; col++) {
3998 indexRow[col] = src[col];
3999 }
4000 }
4001 else {
4002 _mesa_problem(ctx,
4003 "Color index problem in _mesa_GetTexImage");
4004 }
4005 _mesa_pack_index_span(ctx, width, type, dest,
4006 indexRow, &ctx->Pack,
4007 0 /* no image transfer */);
4008 }
4009 else if (format == GL_DEPTH_COMPONENT) {
4010 GLfloat depthRow[MAX_WIDTH];
4011 GLint col;
4012 for (col = 0; col < width; col++) {
4013 (*texImage->FetchTexelf)(texImage, col, row, img,
4014 depthRow + col);
4015 }
4016 _mesa_pack_depth_span(ctx, width, dest, type,
4017 depthRow, &ctx->Pack);
4018 }
4019 else if (format == GL_DEPTH_STENCIL_EXT) {
4020 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4021 const GLuint *src = (const GLuint *) texImage->Data;
4022 src += width * row + width * height * img;
4023 _mesa_memcpy(dest, src, width * sizeof(GLuint));
4024 if (ctx->Pack.SwapBytes) {
4025 _mesa_swap4((GLuint *) dest, width);
4026 }
4027 }
4028 else if (format == GL_YCBCR_MESA) {
4029 /* No pixel transfer */
4030 const GLint rowstride = texImage->RowStride;
4031 MEMCPY(dest,
4032 (const GLushort *) texImage->Data + row * rowstride,
4033 width * sizeof(GLushort));
4034 /* check for byte swapping */
4035 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
4036 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
4037 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
4038 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
4039 if (!ctx->Pack.SwapBytes)
4040 _mesa_swap2((GLushort *) dest, width);
4041 }
4042 else if (ctx->Pack.SwapBytes) {
4043 _mesa_swap2((GLushort *) dest, width);
4044 }
4045 }
4046 #if FEATURE_EXT_texture_sRGB
4047 else if (is_srgb_teximage(texImage)) {
4048 /* special case this since need to backconvert values */
4049 /* convert row to RGBA format */
4050 GLfloat rgba[MAX_WIDTH][4];
4051 GLint col;
4052 GLbitfield transferOps = 0x0;
4053
4054 for (col = 0; col < width; col++) {
4055 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
4056 if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) {
4057 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
4058 rgba[col][GCOMP] = 0.0;
4059 rgba[col][BCOMP] = 0.0;
4060 }
4061 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) {
4062 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
4063 rgba[col][GCOMP] = 0.0;
4064 rgba[col][BCOMP] = 0.0;
4065 }
4066 else if (texImage->TexFormat->BaseFormat == GL_RGB ||
4067 texImage->TexFormat->BaseFormat == GL_RGBA) {
4068 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
4069 rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
4070 rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
4071 }
4072 }
4073 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
4074 format, type, dest,
4075 &ctx->Pack, transferOps, GL_TRUE);
4076 }
4077 #endif /* FEATURE_EXT_texture_sRGB */
4078 else {
4079 /* general case: convert row to RGBA format */
4080 GLfloat rgba[MAX_WIDTH][4];
4081 GLint col;
4082 GLbitfield transferOps = 0x0;
4083
4084 /* clamp does not apply to GetTexImage (final conversion)?
4085 Looks like we need clamp though when going from format containing
4086 negative values to unsigned format */
4087
4088 if (!type_with_negative_values(type) &&
4089 (texImage->TexFormat->DataType == GL_FLOAT ||
4090 texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED))
4091 transferOps |= IMAGE_CLAMP_BIT;
4092
4093 for (col = 0; col < width; col++) {
4094 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
4095 if (texImage->TexFormat->BaseFormat == GL_ALPHA) {
4096 rgba[col][RCOMP] = 0.0;
4097 rgba[col][GCOMP] = 0.0;
4098 rgba[col][BCOMP] = 0.0;
4099 }
4100 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) {
4101 rgba[col][GCOMP] = 0.0;
4102 rgba[col][BCOMP] = 0.0;
4103 rgba[col][ACOMP] = 1.0;
4104 }
4105 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) {
4106 rgba[col][GCOMP] = 0.0;
4107 rgba[col][BCOMP] = 0.0;
4108 }
4109 else if (texImage->TexFormat->BaseFormat == GL_INTENSITY) {
4110 rgba[col][GCOMP] = 0.0;
4111 rgba[col][BCOMP] = 0.0;
4112 rgba[col][ACOMP] = 1.0;
4113 }
4114 }
4115 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
4116 format, type, dest,
4117 &ctx->Pack, transferOps, GL_TRUE);
4118 } /* format */
4119 } /* row */
4120 } /* img */
4121 }
4122
4123 if (ctx->Pack.BufferObj->Name) {
4124 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4125 ctx->Pack.BufferObj);
4126 }
4127 }
4128
4129
4130
4131 /**
4132 * This is the software fallback for Driver.GetCompressedTexImage().
4133 * All error checking will have been done before this routine is called.
4134 */
4135 void
4136 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
4137 GLvoid *img,
4138 struct gl_texture_object *texObj,
4139 struct gl_texture_image *texImage)
4140 {
4141 GLuint size;
4142
4143 if (ctx->Pack.BufferObj->Name) {
4144 /* pack texture image into a PBO */
4145 GLubyte *buf;
4146 if ((const GLubyte *) img + texImage->CompressedSize >
4147 (const GLubyte *) ctx->Pack.BufferObj->Size) {
4148 _mesa_error(ctx, GL_INVALID_OPERATION,
4149 "glGetCompressedTexImage(invalid PBO access)");
4150 return;
4151 }
4152 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4153 GL_WRITE_ONLY_ARB,
4154 ctx->Pack.BufferObj);
4155 if (!buf) {
4156 /* buffer is already mapped - that's an error */
4157 _mesa_error(ctx, GL_INVALID_OPERATION,
4158 "glGetCompressedTexImage(PBO is mapped)");
4159 return;
4160 }
4161 img = ADD_POINTERS(buf, img);
4162 }
4163 else if (!img) {
4164 /* not an error */
4165 return;
4166 }
4167
4168 /* don't use texImage->CompressedSize since that may be padded out */
4169 size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height,
4170 texImage->Depth,
4171 texImage->TexFormat->MesaFormat);
4172
4173 /* just memcpy, no pixelstore or pixel transfer */
4174 _mesa_memcpy(img, texImage->Data, size);
4175
4176 if (ctx->Pack.BufferObj->Name) {
4177 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4178 ctx->Pack.BufferObj);
4179 }
4180 }