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