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