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