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