mesa: sort texstore_funcs[] array, remove search loop
[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_NONE, NULL },
3184 { MESA_FORMAT_RGBA8888, _mesa_texstore_rgba8888 },
3185 { MESA_FORMAT_RGBA8888_REV, _mesa_texstore_rgba8888 },
3186 { MESA_FORMAT_ARGB8888, _mesa_texstore_argb8888 },
3187 { MESA_FORMAT_ARGB8888_REV, _mesa_texstore_argb8888 },
3188 { MESA_FORMAT_RGB888, _mesa_texstore_rgb888 },
3189 { MESA_FORMAT_BGR888, _mesa_texstore_bgr888 },
3190 { MESA_FORMAT_RGB565, _mesa_texstore_rgb565 },
3191 { MESA_FORMAT_RGB565_REV, _mesa_texstore_rgb565 },
3192 { MESA_FORMAT_RGBA4444, _mesa_texstore_rgba4444 },
3193 { MESA_FORMAT_ARGB4444, _mesa_texstore_argb4444 },
3194 { MESA_FORMAT_ARGB4444_REV, _mesa_texstore_argb4444 },
3195 { MESA_FORMAT_RGBA5551, _mesa_texstore_rgba5551 },
3196 { MESA_FORMAT_ARGB1555, _mesa_texstore_argb1555 },
3197 { MESA_FORMAT_ARGB1555_REV, _mesa_texstore_argb1555 },
3198 { MESA_FORMAT_AL88, _mesa_texstore_al88 },
3199 { MESA_FORMAT_AL88_REV, _mesa_texstore_al88 },
3200 { MESA_FORMAT_RGB332, _mesa_texstore_rgb332 },
3201 { MESA_FORMAT_A8, _mesa_texstore_a8 },
3202 { MESA_FORMAT_L8, _mesa_texstore_a8 },
3203 { MESA_FORMAT_I8, _mesa_texstore_a8 },
3204 { MESA_FORMAT_CI8, _mesa_texstore_ci8 },
3205 { MESA_FORMAT_YCBCR, _mesa_texstore_ycbcr },
3206 { MESA_FORMAT_YCBCR_REV, _mesa_texstore_ycbcr },
3207 { MESA_FORMAT_Z24_S8, _mesa_texstore_z24_s8 },
3208 { MESA_FORMAT_S8_Z24, _mesa_texstore_s8_z24 },
3209 { MESA_FORMAT_Z16, _mesa_texstore_z16 },
3210 { MESA_FORMAT_Z32, _mesa_texstore_z32 },
3211 { MESA_FORMAT_S8, NULL/*_mesa_texstore_s8*/ },
3212 { MESA_FORMAT_SRGB8, _mesa_texstore_srgb8 },
3213 { MESA_FORMAT_SRGBA8, _mesa_texstore_srgba8 },
3214 { MESA_FORMAT_SARGB8, _mesa_texstore_sargb8 },
3215 { MESA_FORMAT_SL8, _mesa_texstore_sl8 },
3216 { MESA_FORMAT_SLA8, _mesa_texstore_sla8 },
3217 { MESA_FORMAT_SRGB_DXT1, _mesa_texstore_rgb_dxt1 },
3218 { MESA_FORMAT_SRGBA_DXT1, _mesa_texstore_rgba_dxt1 },
3219 { MESA_FORMAT_SRGBA_DXT3, _mesa_texstore_rgba_dxt3 },
3220 { MESA_FORMAT_SRGBA_DXT5, _mesa_texstore_rgba_dxt5 },
3221 { MESA_FORMAT_RGB_FXT1, _mesa_texstore_rgb_fxt1 },
3222 { MESA_FORMAT_RGBA_FXT1, _mesa_texstore_rgba_fxt1 },
3223 { MESA_FORMAT_RGB_DXT1, _mesa_texstore_rgb_dxt1 },
3224 { MESA_FORMAT_RGBA_DXT1, _mesa_texstore_rgba_dxt1 },
3225 { MESA_FORMAT_RGBA_DXT3, _mesa_texstore_rgba_dxt3 },
3226 { MESA_FORMAT_RGBA_DXT5, _mesa_texstore_rgba_dxt5 },
3227 { MESA_FORMAT_RGBA, _mesa_texstore_rgba },
3228 { MESA_FORMAT_RGB, _mesa_texstore_rgba },
3229 { MESA_FORMAT_ALPHA, _mesa_texstore_rgba },
3230 { MESA_FORMAT_LUMINANCE, _mesa_texstore_rgba },
3231 { MESA_FORMAT_LUMINANCE_ALPHA, _mesa_texstore_rgba },
3232 { MESA_FORMAT_INTENSITY, _mesa_texstore_rgba },
3233 { MESA_FORMAT_RGBA_FLOAT32, _mesa_texstore_rgba_float32 },
3234 { MESA_FORMAT_RGBA_FLOAT16, _mesa_texstore_rgba_float16 },
3235 { MESA_FORMAT_RGB_FLOAT32, _mesa_texstore_rgba_float32 },
3236 { MESA_FORMAT_RGB_FLOAT16, _mesa_texstore_rgba_float16 },
3237 { MESA_FORMAT_ALPHA_FLOAT32, _mesa_texstore_rgba_float32 },
3238 { MESA_FORMAT_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
3239 { MESA_FORMAT_LUMINANCE_FLOAT32, _mesa_texstore_rgba_float32 },
3240 { MESA_FORMAT_LUMINANCE_FLOAT16, _mesa_texstore_rgba_float16 },
3241 { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, _mesa_texstore_rgba_float32 },
3242 { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
3243 { MESA_FORMAT_INTENSITY_FLOAT32, _mesa_texstore_rgba_float32 },
3244 { MESA_FORMAT_INTENSITY_FLOAT16, _mesa_texstore_rgba_float16 },
3245 { MESA_FORMAT_DUDV8, _mesa_texstore_dudv8 },
3246 { MESA_FORMAT_SIGNED_RGBA8888, _mesa_texstore_signed_rgba8888 },
3247 { MESA_FORMAT_SIGNED_RGBA8888_REV, _mesa_texstore_signed_rgba8888 },
3248 };
3249
3250
3251 /**
3252 * Return the StoreTexImageFunc pointer to store an image in the given format.
3253 */
3254 StoreTexImageFunc
3255 _mesa_get_texstore_func(gl_format format)
3256 {
3257 GLuint i;
3258 #ifdef DEBUG
3259 for (i = 0; i < MESA_FORMAT_COUNT; i++) {
3260 ASSERT(texstore_funcs[i].Name == i);
3261 }
3262 #endif
3263 ASSERT(texstore_funcs[format].Name == format);
3264 return texstore_funcs[format].Store;
3265 }
3266
3267
3268
3269 /**
3270 * Check if an unpack PBO is active prior to fetching a texture image.
3271 * If so, do bounds checking and map the buffer into main memory.
3272 * Any errors detected will be recorded.
3273 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
3274 */
3275 const GLvoid *
3276 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
3277 GLsizei width, GLsizei height, GLsizei depth,
3278 GLenum format, GLenum type, const GLvoid *pixels,
3279 const struct gl_pixelstore_attrib *unpack,
3280 const char *funcName)
3281 {
3282 GLubyte *buf;
3283
3284 if (!_mesa_is_bufferobj(unpack->BufferObj)) {
3285 /* no PBO */
3286 return pixels;
3287 }
3288 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
3289 format, type, pixels)) {
3290 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
3291 return NULL;
3292 }
3293
3294 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
3295 GL_READ_ONLY_ARB, unpack->BufferObj);
3296 if (!buf) {
3297 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
3298 return NULL;
3299 }
3300
3301 return ADD_POINTERS(buf, pixels);
3302 }
3303
3304
3305 /**
3306 * Check if an unpack PBO is active prior to fetching a compressed texture
3307 * image.
3308 * If so, do bounds checking and map the buffer into main memory.
3309 * Any errors detected will be recorded.
3310 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
3311 */
3312 const GLvoid *
3313 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
3314 GLsizei imageSize, const GLvoid *pixels,
3315 const struct gl_pixelstore_attrib *packing,
3316 const char *funcName)
3317 {
3318 GLubyte *buf;
3319
3320 if (!_mesa_is_bufferobj(packing->BufferObj)) {
3321 /* not using a PBO - return pointer unchanged */
3322 return pixels;
3323 }
3324 if ((const GLubyte *) pixels + imageSize >
3325 ((const GLubyte *) 0) + packing->BufferObj->Size) {
3326 /* out of bounds read! */
3327 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
3328 return NULL;
3329 }
3330
3331 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
3332 GL_READ_ONLY_ARB, packing->BufferObj);
3333 if (!buf) {
3334 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
3335 return NULL;
3336 }
3337
3338 return ADD_POINTERS(buf, pixels);
3339 }
3340
3341
3342 /**
3343 * This function must be called after either of the validate_pbo_*_teximage()
3344 * functions. It unmaps the PBO buffer if it was mapped earlier.
3345 */
3346 void
3347 _mesa_unmap_teximage_pbo(GLcontext *ctx,
3348 const struct gl_pixelstore_attrib *unpack)
3349 {
3350 if (_mesa_is_bufferobj(unpack->BufferObj)) {
3351 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
3352 unpack->BufferObj);
3353 }
3354 }
3355
3356
3357
3358 /**
3359 * Adaptor for fetching a GLchan texel from a float-valued texture.
3360 */
3361 static void
3362 fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
3363 GLint i, GLint j, GLint k, GLchan *texelOut)
3364 {
3365 GLfloat temp[4];
3366 GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat->MesaFormat);
3367
3368 ASSERT(texImage->FetchTexelf);
3369 texImage->FetchTexelf(texImage, i, j, k, temp);
3370 if (baseFormat == GL_DEPTH_COMPONENT ||
3371 baseFormat == GL_DEPTH_STENCIL_EXT) {
3372 /* just one channel */
3373 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
3374 }
3375 else {
3376 /* four channels */
3377 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
3378 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
3379 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
3380 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
3381 }
3382 }
3383
3384
3385 /**
3386 * Adaptor for fetching a float texel from a GLchan-valued texture.
3387 */
3388 static void
3389 fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
3390 GLint i, GLint j, GLint k, GLfloat *texelOut)
3391 {
3392 GLchan temp[4];
3393 GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat->MesaFormat);
3394
3395 ASSERT(texImage->FetchTexelc);
3396 texImage->FetchTexelc(texImage, i, j, k, temp);
3397 if (baseFormat == GL_DEPTH_COMPONENT ||
3398 baseFormat == GL_DEPTH_STENCIL_EXT) {
3399 /* just one channel */
3400 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
3401 }
3402 else {
3403 /* four channels */
3404 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
3405 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
3406 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
3407 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
3408 }
3409 }
3410
3411
3412 /**
3413 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
3414 */
3415 void
3416 _mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
3417 {
3418 ASSERT(dims == 1 || dims == 2 || dims == 3);
3419 ASSERT(texImage->TexFormat);
3420
3421 texImage->FetchTexelf =
3422 _mesa_get_texel_fetch_func(texImage->TexFormat->MesaFormat, dims);
3423
3424 /* now check if we need to use a float/chan adaptor */
3425 if (!texImage->FetchTexelc) {
3426 texImage->FetchTexelc = fetch_texel_float_to_chan;
3427 }
3428 else if (!texImage->FetchTexelf) {
3429 texImage->FetchTexelf = fetch_texel_chan_to_float;
3430 }
3431
3432
3433 ASSERT(texImage->FetchTexelc);
3434 ASSERT(texImage->FetchTexelf);
3435 }
3436
3437
3438 static void
3439 compute_texture_size(GLcontext *ctx, struct gl_texture_image *texImage)
3440 {
3441 texImage->IsCompressed =
3442 _mesa_is_format_compressed(texImage->TexFormat->MesaFormat);
3443
3444 if (texImage->IsCompressed) {
3445 texImage->CompressedSize =
3446 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
3447 texImage->Height, texImage->Depth,
3448 texImage->TexFormat->MesaFormat);
3449 }
3450 else {
3451 /* non-compressed format */
3452 texImage->CompressedSize = 0;
3453 }
3454 }
3455
3456
3457
3458 /**
3459 * This is the software fallback for Driver.TexImage1D()
3460 * and Driver.CopyTexImage1D().
3461 * \sa _mesa_store_teximage2d()
3462 * Note that the width may not be the actual texture width since it may
3463 * be changed by convolution w/ GL_REDUCE. The texImage->Width field will
3464 * have the actual texture size.
3465 */
3466 void
3467 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3468 GLint internalFormat,
3469 GLint width, GLint border,
3470 GLenum format, GLenum type, const GLvoid *pixels,
3471 const struct gl_pixelstore_attrib *packing,
3472 struct gl_texture_object *texObj,
3473 struct gl_texture_image *texImage)
3474 {
3475 GLint sizeInBytes;
3476 (void) border;
3477
3478 texImage->TexFormat
3479 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
3480 ASSERT(texImage->TexFormat);
3481
3482 _mesa_set_fetch_functions(texImage, 1);
3483 compute_texture_size(ctx, texImage);
3484
3485 /* allocate memory */
3486 if (texImage->IsCompressed)
3487 sizeInBytes = texImage->CompressedSize;
3488 else
3489 sizeInBytes = texImage->Width * _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
3490 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3491 if (!texImage->Data) {
3492 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
3493 return;
3494 }
3495
3496 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3497 pixels, packing, "glTexImage1D");
3498 if (!pixels) {
3499 /* Note: we check for a NULL image pointer here, _after_ we allocated
3500 * memory for the texture. That's what the GL spec calls for.
3501 */
3502 return;
3503 }
3504 else {
3505 const GLint dstRowStride = 0;
3506 GLboolean success;
3507 const StoreTexImageFunc storeImage =
3508 _mesa_get_texstore_func(texImage->TexFormat->MesaFormat);
3509
3510 ASSERT(storeImage);
3511
3512 success = storeImage(ctx, 1, texImage->_BaseFormat,
3513 texImage->TexFormat,
3514 texImage->Data,
3515 0, 0, 0, /* dstX/Y/Zoffset */
3516 dstRowStride,
3517 texImage->ImageOffsets,
3518 width, 1, 1,
3519 format, type, pixels, packing);
3520 if (!success) {
3521 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
3522 }
3523 }
3524
3525 _mesa_unmap_teximage_pbo(ctx, packing);
3526 }
3527
3528
3529 /**
3530 * This is the software fallback for Driver.TexImage2D()
3531 * and Driver.CopyTexImage2D().
3532 *
3533 * This function is oriented toward storing images in main memory, rather
3534 * than VRAM. Device driver's can easily plug in their own replacement.
3535 *
3536 * Note: width and height may be pre-convolved dimensions, but
3537 * texImage->Width and texImage->Height will be post-convolved dimensions.
3538 */
3539 void
3540 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3541 GLint internalFormat,
3542 GLint width, GLint height, GLint border,
3543 GLenum format, GLenum type, const void *pixels,
3544 const struct gl_pixelstore_attrib *packing,
3545 struct gl_texture_object *texObj,
3546 struct gl_texture_image *texImage)
3547 {
3548 GLint texelBytes, sizeInBytes;
3549 (void) border;
3550
3551 texImage->TexFormat
3552 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
3553 ASSERT(texImage->TexFormat);
3554
3555 _mesa_set_fetch_functions(texImage, 2);
3556 compute_texture_size(ctx, texImage);
3557
3558 texelBytes = _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
3559
3560 /* allocate memory */
3561 if (texImage->IsCompressed)
3562 sizeInBytes = texImage->CompressedSize;
3563 else
3564 sizeInBytes = texImage->Width * texImage->Height * texelBytes;
3565 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3566 if (!texImage->Data) {
3567 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
3568 return;
3569 }
3570
3571 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3572 pixels, packing, "glTexImage2D");
3573 if (!pixels) {
3574 /* Note: we check for a NULL image pointer here, _after_ we allocated
3575 * memory for the texture. That's what the GL spec calls for.
3576 */
3577 return;
3578 }
3579 else {
3580 GLint dstRowStride;
3581 GLboolean success;
3582 const StoreTexImageFunc storeImage =
3583 _mesa_get_texstore_func(texImage->TexFormat->MesaFormat);
3584
3585 ASSERT(storeImage);
3586
3587 if (texImage->IsCompressed) {
3588 dstRowStride
3589 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3590 }
3591 else {
3592 dstRowStride = texImage->RowStride * texelBytes;
3593 }
3594
3595 success = storeImage(ctx, 2, texImage->_BaseFormat,
3596 texImage->TexFormat,
3597 texImage->Data,
3598 0, 0, 0, /* dstX/Y/Zoffset */
3599 dstRowStride,
3600 texImage->ImageOffsets,
3601 width, height, 1,
3602 format, type, pixels, packing);
3603 if (!success) {
3604 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
3605 }
3606 }
3607
3608 _mesa_unmap_teximage_pbo(ctx, packing);
3609 }
3610
3611
3612
3613 /**
3614 * This is the software fallback for Driver.TexImage3D()
3615 * and Driver.CopyTexImage3D().
3616 * \sa _mesa_store_teximage2d()
3617 */
3618 void
3619 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3620 GLint internalFormat,
3621 GLint width, GLint height, GLint depth, GLint border,
3622 GLenum format, GLenum type, const void *pixels,
3623 const struct gl_pixelstore_attrib *packing,
3624 struct gl_texture_object *texObj,
3625 struct gl_texture_image *texImage)
3626 {
3627 GLint texelBytes, sizeInBytes;
3628 (void) border;
3629
3630 texImage->TexFormat
3631 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
3632 ASSERT(texImage->TexFormat);
3633
3634 _mesa_set_fetch_functions(texImage, 3);
3635 compute_texture_size(ctx, texImage);
3636
3637 texelBytes = _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
3638
3639 /* allocate memory */
3640 if (texImage->IsCompressed)
3641 sizeInBytes = texImage->CompressedSize;
3642 else
3643 sizeInBytes = width * height * depth * texelBytes;
3644 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3645 if (!texImage->Data) {
3646 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3647 return;
3648 }
3649
3650 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3651 type, pixels, packing, "glTexImage3D");
3652 if (!pixels) {
3653 /* Note: we check for a NULL image pointer here, _after_ we allocated
3654 * memory for the texture. That's what the GL spec calls for.
3655 */
3656 return;
3657 }
3658 else {
3659 GLint dstRowStride;
3660 GLboolean success;
3661 const StoreTexImageFunc storeImage =
3662 _mesa_get_texstore_func(texImage->TexFormat->MesaFormat);
3663
3664 ASSERT(storeImage);
3665
3666 if (texImage->IsCompressed) {
3667 dstRowStride
3668 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3669 }
3670 else {
3671 dstRowStride = texImage->RowStride * texelBytes;
3672 }
3673
3674 success = storeImage(ctx, 3, texImage->_BaseFormat,
3675 texImage->TexFormat,
3676 texImage->Data,
3677 0, 0, 0, /* dstX/Y/Zoffset */
3678 dstRowStride,
3679 texImage->ImageOffsets,
3680 width, height, depth,
3681 format, type, pixels, packing);
3682 if (!success) {
3683 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3684 }
3685 }
3686
3687 _mesa_unmap_teximage_pbo(ctx, packing);
3688 }
3689
3690
3691
3692
3693 /*
3694 * This is the software fallback for Driver.TexSubImage1D()
3695 * and Driver.CopyTexSubImage1D().
3696 */
3697 void
3698 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
3699 GLint xoffset, GLint width,
3700 GLenum format, GLenum type, const void *pixels,
3701 const struct gl_pixelstore_attrib *packing,
3702 struct gl_texture_object *texObj,
3703 struct gl_texture_image *texImage)
3704 {
3705 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3706 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3707 pixels, packing, "glTexSubImage1D");
3708 if (!pixels)
3709 return;
3710
3711 {
3712 const GLint dstRowStride = 0;
3713 GLboolean success;
3714 const StoreTexImageFunc storeImage =
3715 _mesa_get_texstore_func(texImage->TexFormat->MesaFormat);
3716
3717 ASSERT(storeImage);
3718
3719 success = storeImage(ctx, 1, texImage->_BaseFormat,
3720 texImage->TexFormat,
3721 texImage->Data,
3722 xoffset, 0, 0, /* offsets */
3723 dstRowStride,
3724 texImage->ImageOffsets,
3725 width, 1, 1,
3726 format, type, pixels, packing);
3727 if (!success) {
3728 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
3729 }
3730 }
3731
3732 _mesa_unmap_teximage_pbo(ctx, packing);
3733 }
3734
3735
3736
3737 /**
3738 * This is the software fallback for Driver.TexSubImage2D()
3739 * and Driver.CopyTexSubImage2D().
3740 */
3741 void
3742 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
3743 GLint xoffset, GLint yoffset,
3744 GLint width, GLint height,
3745 GLenum format, GLenum type, const void *pixels,
3746 const struct gl_pixelstore_attrib *packing,
3747 struct gl_texture_object *texObj,
3748 struct gl_texture_image *texImage)
3749 {
3750 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3751 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3752 pixels, packing, "glTexSubImage2D");
3753 if (!pixels)
3754 return;
3755
3756 {
3757 GLint dstRowStride = 0;
3758 GLboolean success;
3759 const StoreTexImageFunc storeImage =
3760 _mesa_get_texstore_func(texImage->TexFormat->MesaFormat);
3761
3762 ASSERT(storeImage);
3763
3764 if (texImage->IsCompressed) {
3765 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3766 texImage->Width);
3767 }
3768 else {
3769 dstRowStride = texImage->RowStride *
3770 _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
3771 }
3772
3773 success = storeImage(ctx, 2, texImage->_BaseFormat,
3774 texImage->TexFormat,
3775 texImage->Data,
3776 xoffset, yoffset, 0,
3777 dstRowStride,
3778 texImage->ImageOffsets,
3779 width, height, 1,
3780 format, type, pixels, packing);
3781 if (!success) {
3782 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
3783 }
3784 }
3785
3786 _mesa_unmap_teximage_pbo(ctx, packing);
3787 }
3788
3789
3790 /*
3791 * This is the software fallback for Driver.TexSubImage3D().
3792 * and Driver.CopyTexSubImage3D().
3793 */
3794 void
3795 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
3796 GLint xoffset, GLint yoffset, GLint zoffset,
3797 GLint width, GLint height, GLint depth,
3798 GLenum format, GLenum type, const void *pixels,
3799 const struct gl_pixelstore_attrib *packing,
3800 struct gl_texture_object *texObj,
3801 struct gl_texture_image *texImage)
3802 {
3803 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3804 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3805 type, pixels, packing,
3806 "glTexSubImage3D");
3807 if (!pixels)
3808 return;
3809
3810 {
3811 GLint dstRowStride;
3812 GLboolean success;
3813 const StoreTexImageFunc storeImage =
3814 _mesa_get_texstore_func(texImage->TexFormat->MesaFormat);
3815
3816 ASSERT(storeImage);
3817
3818 if (texImage->IsCompressed) {
3819 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3820 texImage->Width);
3821 }
3822 else {
3823 dstRowStride = texImage->RowStride *
3824 _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
3825 }
3826
3827 success = storeImage(ctx, 3, texImage->_BaseFormat,
3828 texImage->TexFormat,
3829 texImage->Data,
3830 xoffset, yoffset, zoffset,
3831 dstRowStride,
3832 texImage->ImageOffsets,
3833 width, height, depth,
3834 format, type, pixels, packing);
3835 if (!success) {
3836 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
3837 }
3838 }
3839
3840 _mesa_unmap_teximage_pbo(ctx, packing);
3841 }
3842
3843
3844 /*
3845 * Fallback for Driver.CompressedTexImage1D()
3846 */
3847 void
3848 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3849 GLint internalFormat,
3850 GLint width, GLint border,
3851 GLsizei imageSize, const GLvoid *data,
3852 struct gl_texture_object *texObj,
3853 struct gl_texture_image *texImage)
3854 {
3855 /* this space intentionally left blank */
3856 (void) ctx;
3857 (void) target; (void) level;
3858 (void) internalFormat;
3859 (void) width; (void) border;
3860 (void) imageSize; (void) data;
3861 (void) texObj;
3862 (void) texImage;
3863 }
3864
3865
3866
3867 /**
3868 * Fallback for Driver.CompressedTexImage2D()
3869 */
3870 void
3871 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3872 GLint internalFormat,
3873 GLint width, GLint height, GLint border,
3874 GLsizei imageSize, const GLvoid *data,
3875 struct gl_texture_object *texObj,
3876 struct gl_texture_image *texImage)
3877 {
3878 (void) width; (void) height; (void) border;
3879
3880 /* This is pretty simple, basically just do a memcpy without worrying
3881 * about the usual image unpacking or image transfer operations.
3882 */
3883 ASSERT(texObj);
3884 ASSERT(texImage);
3885 ASSERT(texImage->Width > 0);
3886 ASSERT(texImage->Height > 0);
3887 ASSERT(texImage->Depth == 1);
3888 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
3889
3890 texImage->TexFormat
3891 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 0, 0);
3892 ASSERT(texImage->TexFormat);
3893
3894 _mesa_set_fetch_functions(texImage, 2);
3895 compute_texture_size(ctx, texImage);
3896
3897 /* allocate storage */
3898 texImage->Data = _mesa_alloc_texmemory(imageSize);
3899 if (!texImage->Data) {
3900 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3901 return;
3902 }
3903
3904 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3905 &ctx->Unpack,
3906 "glCompressedTexImage2D");
3907 if (!data)
3908 return;
3909
3910 /* copy the data */
3911 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
3912 MEMCPY(texImage->Data, data, imageSize);
3913
3914 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3915 }
3916
3917
3918
3919 /*
3920 * Fallback for Driver.CompressedTexImage3D()
3921 */
3922 void
3923 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3924 GLint internalFormat,
3925 GLint width, GLint height, GLint depth,
3926 GLint border,
3927 GLsizei imageSize, const GLvoid *data,
3928 struct gl_texture_object *texObj,
3929 struct gl_texture_image *texImage)
3930 {
3931 /* this space intentionally left blank */
3932 (void) ctx;
3933 (void) target; (void) level;
3934 (void) internalFormat;
3935 (void) width; (void) height; (void) depth;
3936 (void) border;
3937 (void) imageSize; (void) data;
3938 (void) texObj;
3939 (void) texImage;
3940 }
3941
3942
3943
3944 /**
3945 * Fallback for Driver.CompressedTexSubImage1D()
3946 */
3947 void
3948 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
3949 GLint level,
3950 GLint xoffset, GLsizei width,
3951 GLenum format,
3952 GLsizei imageSize, const GLvoid *data,
3953 struct gl_texture_object *texObj,
3954 struct gl_texture_image *texImage)
3955 {
3956 /* there are no compressed 1D texture formats yet */
3957 (void) ctx;
3958 (void) target; (void) level;
3959 (void) xoffset; (void) width;
3960 (void) format;
3961 (void) imageSize; (void) data;
3962 (void) texObj;
3963 (void) texImage;
3964 }
3965
3966
3967 /**
3968 * Fallback for Driver.CompressedTexSubImage2D()
3969 */
3970 void
3971 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
3972 GLint level,
3973 GLint xoffset, GLint yoffset,
3974 GLsizei width, GLsizei height,
3975 GLenum format,
3976 GLsizei imageSize, const GLvoid *data,
3977 struct gl_texture_object *texObj,
3978 struct gl_texture_image *texImage)
3979 {
3980 GLint bytesPerRow, destRowStride, srcRowStride;
3981 GLint i, rows;
3982 GLubyte *dest;
3983 const GLubyte *src;
3984 const gl_format texFormat = texImage->TexFormat->MesaFormat;
3985
3986 (void) format;
3987
3988 /* these should have been caught sooner */
3989 ASSERT((width & 3) == 0 || width == 2 || width == 1);
3990 ASSERT((height & 3) == 0 || height == 2 || height == 1);
3991 ASSERT((xoffset & 3) == 0);
3992 ASSERT((yoffset & 3) == 0);
3993
3994 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3995 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3996 &ctx->Unpack,
3997 "glCompressedTexSubImage2D");
3998 if (!data)
3999 return;
4000
4001 srcRowStride = _mesa_compressed_row_stride(texFormat, width);
4002 src = (const GLubyte *) data;
4003
4004 destRowStride = _mesa_compressed_row_stride(texFormat, texImage->Width);
4005 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
4006 texFormat,
4007 texImage->Width,
4008 (GLubyte *) texImage->Data);
4009
4010 bytesPerRow = srcRowStride;
4011 rows = height / 4;
4012
4013 for (i = 0; i < rows; i++) {
4014 MEMCPY(dest, src, bytesPerRow);
4015 dest += destRowStride;
4016 src += srcRowStride;
4017 }
4018
4019 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
4020 }
4021
4022
4023 /**
4024 * Fallback for Driver.CompressedTexSubImage3D()
4025 */
4026 void
4027 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
4028 GLint level,
4029 GLint xoffset, GLint yoffset, GLint zoffset,
4030 GLsizei width, GLsizei height, GLsizei depth,
4031 GLenum format,
4032 GLsizei imageSize, const GLvoid *data,
4033 struct gl_texture_object *texObj,
4034 struct gl_texture_image *texImage)
4035 {
4036 /* there are no compressed 3D texture formats yet */
4037 (void) ctx;
4038 (void) target; (void) level;
4039 (void) xoffset; (void) yoffset; (void) zoffset;
4040 (void) width; (void) height; (void) depth;
4041 (void) format;
4042 (void) imageSize; (void) data;
4043 (void) texObj;
4044 (void) texImage;
4045 }