Long obsolete.
[mesa.git] / src / mesa / main / texstore.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.1
4 *
5 * Copyright (C) 1999-2006 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 GLfloat depthScale = (GLfloat) 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 GLfloat depthScale = 65535.0f;
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
1447 int img, row, col;
1448 for (img = 0; img < srcDepth; img++) {
1449 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1450 srcWidth, srcFormat, srcType);
1451 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1452 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1453 GLubyte *dstRow = (GLubyte *) dstAddr
1454 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1455 + dstYoffset * dstRowStride
1456 + dstXoffset * dstFormat->TexelBytes;
1457 for (row = 0; row < srcHeight; row++) {
1458 for (col = 0; col < srcWidth; col++) {
1459 dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP];
1460 dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP];
1461 dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP];
1462 dstRow[col * 4 + 3] = 0xff;
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 && littleEndian)) {
1475 GLint img, row, col;
1476 /* For some reason, streaming copies to write-combined regions
1477 * are extremely sensitive to the characteristics of how the
1478 * source data is retrieved. By reordering the source reads to
1479 * be in-order, the speed of this operation increases by half.
1480 * Strangely the same isn't required for the RGB path, above.
1481 */
1482 for (img = 0; img < srcDepth; img++) {
1483 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1484 srcWidth, srcFormat, srcType);
1485 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1486 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1487 GLubyte *dstRow = (GLubyte *) dstAddr
1488 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1489 + dstYoffset * dstRowStride
1490 + dstXoffset * dstFormat->TexelBytes;
1491
1492 for (row = 0; row < srcHeight; row++) {
1493 for (col = 0; col < srcWidth; col++) {
1494 *(GLuint *)(dstRow + col * 4) = (srcRow[col * 4 + RCOMP] << 16 |
1495 srcRow[col * 4 + GCOMP] << 8 |
1496 srcRow[col * 4 + BCOMP] << 0 |
1497 srcRow[col * 4 + ACOMP] << 24);
1498 }
1499 dstRow += dstRowStride;
1500 srcRow += srcRowStride;
1501 }
1502 }
1503 }
1504 else if (!ctx->_ImageTransferState &&
1505 !srcPacking->SwapBytes &&
1506 dstFormat == &_mesa_texformat_argb8888 &&
1507 srcFormat == GL_RGBA &&
1508 baseInternalFormat == GL_RGBA &&
1509 srcType == GL_UNSIGNED_BYTE) {
1510
1511 GLint img, row, col;
1512 for (img = 0; img < srcDepth; img++) {
1513 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1514 srcWidth, srcFormat, srcType);
1515 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1516 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1517 GLubyte *dstRow = (GLubyte *) dstAddr
1518 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1519 + dstYoffset * dstRowStride
1520 + dstXoffset * dstFormat->TexelBytes;
1521 for (row = 0; row < srcHeight; row++) {
1522 for (col = 0; col < srcWidth; col++) {
1523 dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP];
1524 dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP];
1525 dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP];
1526 dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP];
1527 }
1528 dstRow += dstRowStride;
1529 srcRow += srcRowStride;
1530 }
1531 }
1532 }
1533 else if (!ctx->_ImageTransferState &&
1534 (srcType == GL_UNSIGNED_BYTE ||
1535 srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1536 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1537 can_swizzle(baseInternalFormat) &&
1538 can_swizzle(srcFormat)) {
1539
1540 GLubyte dstmap[4];
1541
1542 /* dstmap - how to swizzle from RGBA to dst format:
1543 */
1544 if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) ||
1545 (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) {
1546 dstmap[3] = 3; /* alpha */
1547 dstmap[2] = 0; /* red */
1548 dstmap[1] = 1; /* green */
1549 dstmap[0] = 2; /* blue */
1550 }
1551 else {
1552 assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) ||
1553 (!littleEndian && dstFormat == &_mesa_texformat_argb8888));
1554 dstmap[3] = 2;
1555 dstmap[2] = 1;
1556 dstmap[1] = 0;
1557 dstmap[0] = 3;
1558 }
1559
1560 _mesa_swizzle_ubyte_image(ctx, dims,
1561 srcFormat,
1562 srcType,
1563
1564 baseInternalFormat,
1565 dstmap, 4,
1566 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1567 dstRowStride,
1568 dstImageOffsets,
1569 srcWidth, srcHeight, srcDepth, srcAddr,
1570 srcPacking);
1571 }
1572 else {
1573 /* general path */
1574 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1575 baseInternalFormat,
1576 dstFormat->BaseFormat,
1577 srcWidth, srcHeight, srcDepth,
1578 srcFormat, srcType, srcAddr,
1579 srcPacking);
1580 const GLchan *src = tempImage;
1581 GLint img, row, col;
1582 if (!tempImage)
1583 return GL_FALSE;
1584 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1585 for (img = 0; img < srcDepth; img++) {
1586 GLubyte *dstRow = (GLubyte *) dstAddr
1587 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1588 + dstYoffset * dstRowStride
1589 + dstXoffset * dstFormat->TexelBytes;
1590 for (row = 0; row < srcHeight; row++) {
1591 GLuint *dstUI = (GLuint *) dstRow;
1592 if (dstFormat == &_mesa_texformat_argb8888) {
1593 for (col = 0; col < srcWidth; col++) {
1594 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1595 CHAN_TO_UBYTE(src[RCOMP]),
1596 CHAN_TO_UBYTE(src[GCOMP]),
1597 CHAN_TO_UBYTE(src[BCOMP]) );
1598 src += 4;
1599 }
1600 }
1601 else {
1602 for (col = 0; col < srcWidth; col++) {
1603 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1604 CHAN_TO_UBYTE(src[RCOMP]),
1605 CHAN_TO_UBYTE(src[GCOMP]),
1606 CHAN_TO_UBYTE(src[BCOMP]) );
1607 src += 4;
1608 }
1609 }
1610 dstRow += dstRowStride;
1611 }
1612 }
1613 _mesa_free((void *) tempImage);
1614 }
1615 return GL_TRUE;
1616 }
1617
1618
1619 GLboolean
1620 _mesa_texstore_rgb888(TEXSTORE_PARAMS)
1621 {
1622 const GLboolean littleEndian = _mesa_little_endian();
1623
1624 ASSERT(dstFormat == &_mesa_texformat_rgb888);
1625 ASSERT(dstFormat->TexelBytes == 3);
1626
1627 if (!ctx->_ImageTransferState &&
1628 !srcPacking->SwapBytes &&
1629 baseInternalFormat == GL_RGB &&
1630 srcFormat == GL_BGR &&
1631 srcType == GL_UNSIGNED_BYTE &&
1632 littleEndian) {
1633 /* simple memcpy path */
1634 memcpy_texture(ctx, dims,
1635 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1636 dstRowStride,
1637 dstImageOffsets,
1638 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1639 srcAddr, srcPacking);
1640 }
1641 else if (!ctx->_ImageTransferState &&
1642 !srcPacking->SwapBytes &&
1643 srcFormat == GL_RGBA &&
1644 srcType == GL_UNSIGNED_BYTE) {
1645 /* extract RGB from RGBA */
1646 GLint img, row, col;
1647 for (img = 0; img < srcDepth; img++) {
1648 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1649 srcWidth, srcFormat, srcType);
1650 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1651 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1652 GLubyte *dstRow = (GLubyte *) dstAddr
1653 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1654 + dstYoffset * dstRowStride
1655 + dstXoffset * dstFormat->TexelBytes;
1656 for (row = 0; row < srcHeight; row++) {
1657 for (col = 0; col < srcWidth; col++) {
1658 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1659 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1660 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1661 }
1662 dstRow += dstRowStride;
1663 srcRow += srcRowStride;
1664 }
1665 }
1666 }
1667 else if (!ctx->_ImageTransferState &&
1668 srcType == GL_UNSIGNED_BYTE &&
1669 can_swizzle(baseInternalFormat) &&
1670 can_swizzle(srcFormat)) {
1671
1672 GLubyte dstmap[4];
1673
1674 /* dstmap - how to swizzle from RGBA to dst format:
1675 */
1676 dstmap[0] = 2;
1677 dstmap[1] = 1;
1678 dstmap[2] = 0;
1679 dstmap[3] = ONE; /* ? */
1680
1681 _mesa_swizzle_ubyte_image(ctx, dims,
1682 srcFormat,
1683 srcType,
1684 baseInternalFormat,
1685 dstmap, 3,
1686 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1687 dstRowStride, dstImageOffsets,
1688 srcWidth, srcHeight, srcDepth, srcAddr,
1689 srcPacking);
1690 }
1691 else {
1692 /* general path */
1693 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1694 baseInternalFormat,
1695 dstFormat->BaseFormat,
1696 srcWidth, srcHeight, srcDepth,
1697 srcFormat, srcType, srcAddr,
1698 srcPacking);
1699 const GLchan *src = (const GLchan *) tempImage;
1700 GLint img, row, col;
1701 if (!tempImage)
1702 return GL_FALSE;
1703 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1704 for (img = 0; img < srcDepth; img++) {
1705 GLubyte *dstRow = (GLubyte *) dstAddr
1706 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1707 + dstYoffset * dstRowStride
1708 + dstXoffset * dstFormat->TexelBytes;
1709 for (row = 0; row < srcHeight; row++) {
1710 #if 0
1711 if (littleEndian) {
1712 for (col = 0; col < srcWidth; col++) {
1713 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1714 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1715 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1716 srcUB += 3;
1717 }
1718 }
1719 else {
1720 for (col = 0; col < srcWidth; col++) {
1721 dstRow[col * 3 + 0] = srcUB[BCOMP];
1722 dstRow[col * 3 + 1] = srcUB[GCOMP];
1723 dstRow[col * 3 + 2] = srcUB[RCOMP];
1724 srcUB += 3;
1725 }
1726 }
1727 #else
1728 for (col = 0; col < srcWidth; col++) {
1729 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1730 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1731 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1732 src += 3;
1733 }
1734 #endif
1735 dstRow += dstRowStride;
1736 }
1737 }
1738 _mesa_free((void *) tempImage);
1739 }
1740 return GL_TRUE;
1741 }
1742
1743
1744 GLboolean
1745 _mesa_texstore_bgr888(TEXSTORE_PARAMS)
1746 {
1747 const GLboolean littleEndian = _mesa_little_endian();
1748
1749 ASSERT(dstFormat == &_mesa_texformat_bgr888);
1750 ASSERT(dstFormat->TexelBytes == 3);
1751
1752 if (!ctx->_ImageTransferState &&
1753 !srcPacking->SwapBytes &&
1754 baseInternalFormat == GL_RGB &&
1755 srcFormat == GL_RGB &&
1756 srcType == GL_UNSIGNED_BYTE &&
1757 littleEndian) {
1758 /* simple memcpy path */
1759 memcpy_texture(ctx, dims,
1760 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1761 dstRowStride,
1762 dstImageOffsets,
1763 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1764 srcAddr, srcPacking);
1765 }
1766 else if (!ctx->_ImageTransferState &&
1767 !srcPacking->SwapBytes &&
1768 srcFormat == GL_RGBA &&
1769 srcType == GL_UNSIGNED_BYTE) {
1770 /* extract BGR from RGBA */
1771 int img, row, col;
1772 for (img = 0; img < srcDepth; img++) {
1773 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1774 srcWidth, srcFormat, srcType);
1775 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1776 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1777 GLubyte *dstRow = (GLubyte *) dstAddr
1778 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1779 + dstYoffset * dstRowStride
1780 + dstXoffset * dstFormat->TexelBytes;
1781 for (row = 0; row < srcHeight; row++) {
1782 for (col = 0; col < srcWidth; col++) {
1783 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1784 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1785 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1786 }
1787 dstRow += dstRowStride;
1788 srcRow += srcRowStride;
1789 }
1790 }
1791 }
1792 else if (!ctx->_ImageTransferState &&
1793 srcType == GL_UNSIGNED_BYTE &&
1794 can_swizzle(baseInternalFormat) &&
1795 can_swizzle(srcFormat)) {
1796
1797 GLubyte dstmap[4];
1798
1799 /* dstmap - how to swizzle from RGBA to dst format:
1800 */
1801 dstmap[0] = 0;
1802 dstmap[1] = 1;
1803 dstmap[2] = 2;
1804 dstmap[3] = ONE; /* ? */
1805
1806 _mesa_swizzle_ubyte_image(ctx, dims,
1807 srcFormat,
1808 srcType,
1809 baseInternalFormat,
1810 dstmap, 3,
1811 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1812 dstRowStride, dstImageOffsets,
1813 srcWidth, srcHeight, srcDepth, srcAddr,
1814 srcPacking);
1815 }
1816 else {
1817 /* general path */
1818 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1819 baseInternalFormat,
1820 dstFormat->BaseFormat,
1821 srcWidth, srcHeight, srcDepth,
1822 srcFormat, srcType, srcAddr,
1823 srcPacking);
1824 const GLchan *src = (const GLchan *) tempImage;
1825 GLint img, row, col;
1826 if (!tempImage)
1827 return GL_FALSE;
1828 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1829 for (img = 0; img < srcDepth; img++) {
1830 GLubyte *dstRow = (GLubyte *) dstAddr
1831 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1832 + dstYoffset * dstRowStride
1833 + dstXoffset * dstFormat->TexelBytes;
1834 for (row = 0; row < srcHeight; row++) {
1835 for (col = 0; col < srcWidth; col++) {
1836 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1837 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1838 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1839 src += 3;
1840 }
1841 dstRow += dstRowStride;
1842 }
1843 }
1844 _mesa_free((void *) tempImage);
1845 }
1846 return GL_TRUE;
1847 }
1848
1849
1850 GLboolean
1851 _mesa_texstore_argb4444(TEXSTORE_PARAMS)
1852 {
1853 ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
1854 dstFormat == &_mesa_texformat_argb4444_rev);
1855 ASSERT(dstFormat->TexelBytes == 2);
1856
1857 if (!ctx->_ImageTransferState &&
1858 !srcPacking->SwapBytes &&
1859 dstFormat == &_mesa_texformat_argb4444 &&
1860 baseInternalFormat == GL_RGBA &&
1861 srcFormat == GL_BGRA &&
1862 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1863 /* simple memcpy path */
1864 memcpy_texture(ctx, dims,
1865 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1866 dstRowStride,
1867 dstImageOffsets,
1868 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1869 srcAddr, srcPacking);
1870 }
1871 else {
1872 /* general path */
1873 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1874 baseInternalFormat,
1875 dstFormat->BaseFormat,
1876 srcWidth, srcHeight, srcDepth,
1877 srcFormat, srcType, srcAddr,
1878 srcPacking);
1879 const GLchan *src = tempImage;
1880 GLint img, row, col;
1881 if (!tempImage)
1882 return GL_FALSE;
1883 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1884 for (img = 0; img < srcDepth; img++) {
1885 GLubyte *dstRow = (GLubyte *) dstAddr
1886 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1887 + dstYoffset * dstRowStride
1888 + dstXoffset * dstFormat->TexelBytes;
1889 for (row = 0; row < srcHeight; row++) {
1890 GLushort *dstUS = (GLushort *) dstRow;
1891 if (dstFormat == &_mesa_texformat_argb4444) {
1892 for (col = 0; col < srcWidth; col++) {
1893 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1894 CHAN_TO_UBYTE(src[RCOMP]),
1895 CHAN_TO_UBYTE(src[GCOMP]),
1896 CHAN_TO_UBYTE(src[BCOMP]) );
1897 src += 4;
1898 }
1899 }
1900 else {
1901 for (col = 0; col < srcWidth; col++) {
1902 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
1903 CHAN_TO_UBYTE(src[RCOMP]),
1904 CHAN_TO_UBYTE(src[GCOMP]),
1905 CHAN_TO_UBYTE(src[BCOMP]) );
1906 src += 4;
1907 }
1908 }
1909 dstRow += dstRowStride;
1910 }
1911 }
1912 _mesa_free((void *) tempImage);
1913 }
1914 return GL_TRUE;
1915 }
1916
1917
1918
1919 GLboolean
1920 _mesa_texstore_argb1555(TEXSTORE_PARAMS)
1921 {
1922 ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
1923 dstFormat == &_mesa_texformat_argb1555_rev);
1924 ASSERT(dstFormat->TexelBytes == 2);
1925
1926 if (!ctx->_ImageTransferState &&
1927 !srcPacking->SwapBytes &&
1928 dstFormat == &_mesa_texformat_argb1555 &&
1929 baseInternalFormat == GL_RGBA &&
1930 srcFormat == GL_BGRA &&
1931 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
1932 /* simple memcpy path */
1933 memcpy_texture(ctx, dims,
1934 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1935 dstRowStride,
1936 dstImageOffsets,
1937 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1938 srcAddr, srcPacking);
1939 }
1940 else {
1941 /* general path */
1942 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1943 baseInternalFormat,
1944 dstFormat->BaseFormat,
1945 srcWidth, srcHeight, srcDepth,
1946 srcFormat, srcType, srcAddr,
1947 srcPacking);
1948 const GLchan *src =tempImage;
1949 GLint img, row, col;
1950 if (!tempImage)
1951 return GL_FALSE;
1952 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1953 for (img = 0; img < srcDepth; img++) {
1954 GLubyte *dstRow = (GLubyte *) dstAddr
1955 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
1956 + dstYoffset * dstRowStride
1957 + dstXoffset * dstFormat->TexelBytes;
1958 for (row = 0; row < srcHeight; row++) {
1959 GLushort *dstUS = (GLushort *) dstRow;
1960 if (dstFormat == &_mesa_texformat_argb1555) {
1961 for (col = 0; col < srcWidth; col++) {
1962 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
1963 CHAN_TO_UBYTE(src[RCOMP]),
1964 CHAN_TO_UBYTE(src[GCOMP]),
1965 CHAN_TO_UBYTE(src[BCOMP]) );
1966 src += 4;
1967 }
1968 }
1969 else {
1970 for (col = 0; col < srcWidth; col++) {
1971 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
1972 CHAN_TO_UBYTE(src[RCOMP]),
1973 CHAN_TO_UBYTE(src[GCOMP]),
1974 CHAN_TO_UBYTE(src[BCOMP]) );
1975 src += 4;
1976 }
1977 }
1978 dstRow += dstRowStride;
1979 }
1980 }
1981 _mesa_free((void *) tempImage);
1982 }
1983 return GL_TRUE;
1984 }
1985
1986
1987 GLboolean
1988 _mesa_texstore_al88(TEXSTORE_PARAMS)
1989 {
1990 const GLboolean littleEndian = _mesa_little_endian();
1991
1992 ASSERT(dstFormat == &_mesa_texformat_al88 ||
1993 dstFormat == &_mesa_texformat_al88_rev);
1994 ASSERT(dstFormat->TexelBytes == 2);
1995
1996 if (!ctx->_ImageTransferState &&
1997 !srcPacking->SwapBytes &&
1998 dstFormat == &_mesa_texformat_al88 &&
1999 baseInternalFormat == GL_LUMINANCE_ALPHA &&
2000 srcFormat == GL_LUMINANCE_ALPHA &&
2001 srcType == GL_UNSIGNED_BYTE &&
2002 littleEndian) {
2003 /* simple memcpy path */
2004 memcpy_texture(ctx, dims,
2005 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2006 dstRowStride,
2007 dstImageOffsets,
2008 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2009 srcAddr, srcPacking);
2010 }
2011 else if (!ctx->_ImageTransferState &&
2012 littleEndian &&
2013 srcType == GL_UNSIGNED_BYTE &&
2014 can_swizzle(baseInternalFormat) &&
2015 can_swizzle(srcFormat)) {
2016
2017 GLubyte dstmap[4];
2018
2019 /* dstmap - how to swizzle from RGBA to dst format:
2020 */
2021 if ((littleEndian && dstFormat == &_mesa_texformat_al88) ||
2022 (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) {
2023 dstmap[0] = 0;
2024 dstmap[1] = 3;
2025 }
2026 else {
2027 dstmap[0] = 3;
2028 dstmap[1] = 0;
2029 }
2030 dstmap[2] = ZERO; /* ? */
2031 dstmap[3] = ONE; /* ? */
2032
2033 _mesa_swizzle_ubyte_image(ctx, dims,
2034 srcFormat,
2035 srcType,
2036 baseInternalFormat,
2037 dstmap, 2,
2038 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2039 dstRowStride, dstImageOffsets,
2040 srcWidth, srcHeight, srcDepth, srcAddr,
2041 srcPacking);
2042 }
2043 else {
2044 /* general path */
2045 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2046 baseInternalFormat,
2047 dstFormat->BaseFormat,
2048 srcWidth, srcHeight, srcDepth,
2049 srcFormat, srcType, srcAddr,
2050 srcPacking);
2051 const GLchan *src = tempImage;
2052 GLint img, row, col;
2053 if (!tempImage)
2054 return GL_FALSE;
2055 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2056 for (img = 0; img < srcDepth; img++) {
2057 GLubyte *dstRow = (GLubyte *) dstAddr
2058 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2059 + dstYoffset * dstRowStride
2060 + dstXoffset * dstFormat->TexelBytes;
2061 for (row = 0; row < srcHeight; row++) {
2062 GLushort *dstUS = (GLushort *) dstRow;
2063 if (dstFormat == &_mesa_texformat_al88) {
2064 for (col = 0; col < srcWidth; col++) {
2065 /* src[0] is luminance, src[1] is alpha */
2066 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
2067 CHAN_TO_UBYTE(src[0]) );
2068 src += 2;
2069 }
2070 }
2071 else {
2072 for (col = 0; col < srcWidth; col++) {
2073 /* src[0] is luminance, src[1] is alpha */
2074 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
2075 CHAN_TO_UBYTE(src[0]) );
2076 src += 2;
2077 }
2078 }
2079 dstRow += dstRowStride;
2080 }
2081 }
2082 _mesa_free((void *) tempImage);
2083 }
2084 return GL_TRUE;
2085 }
2086
2087
2088 GLboolean
2089 _mesa_texstore_rgb332(TEXSTORE_PARAMS)
2090 {
2091 ASSERT(dstFormat == &_mesa_texformat_rgb332);
2092 ASSERT(dstFormat->TexelBytes == 1);
2093
2094 if (!ctx->_ImageTransferState &&
2095 !srcPacking->SwapBytes &&
2096 baseInternalFormat == GL_RGB &&
2097 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
2098 /* simple memcpy path */
2099 memcpy_texture(ctx, dims,
2100 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2101 dstRowStride,
2102 dstImageOffsets,
2103 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2104 srcAddr, srcPacking);
2105 }
2106 else {
2107 /* general path */
2108 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2109 baseInternalFormat,
2110 dstFormat->BaseFormat,
2111 srcWidth, srcHeight, srcDepth,
2112 srcFormat, srcType, srcAddr,
2113 srcPacking);
2114 const GLchan *src = tempImage;
2115 GLint img, row, col;
2116 if (!tempImage)
2117 return GL_FALSE;
2118 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2119 for (img = 0; img < srcDepth; img++) {
2120 GLubyte *dstRow = (GLubyte *) dstAddr
2121 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2122 + dstYoffset * dstRowStride
2123 + dstXoffset * dstFormat->TexelBytes;
2124 for (row = 0; row < srcHeight; row++) {
2125 for (col = 0; col < srcWidth; col++) {
2126 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
2127 CHAN_TO_UBYTE(src[GCOMP]),
2128 CHAN_TO_UBYTE(src[BCOMP]) );
2129 src += 3;
2130 }
2131 dstRow += dstRowStride;
2132 }
2133 }
2134 _mesa_free((void *) tempImage);
2135 }
2136 return GL_TRUE;
2137 }
2138
2139
2140 /**
2141 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2142 */
2143 GLboolean
2144 _mesa_texstore_a8(TEXSTORE_PARAMS)
2145 {
2146 ASSERT(dstFormat == &_mesa_texformat_a8 ||
2147 dstFormat == &_mesa_texformat_l8 ||
2148 dstFormat == &_mesa_texformat_i8);
2149 ASSERT(dstFormat->TexelBytes == 1);
2150
2151 if (!ctx->_ImageTransferState &&
2152 !srcPacking->SwapBytes &&
2153 baseInternalFormat == srcFormat &&
2154 srcType == GL_UNSIGNED_BYTE) {
2155 /* simple memcpy path */
2156 memcpy_texture(ctx, dims,
2157 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2158 dstRowStride,
2159 dstImageOffsets,
2160 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2161 srcAddr, srcPacking);
2162 }
2163 else if (!ctx->_ImageTransferState &&
2164 srcType == GL_UNSIGNED_BYTE &&
2165 can_swizzle(baseInternalFormat) &&
2166 can_swizzle(srcFormat)) {
2167
2168 GLubyte dstmap[4];
2169
2170 /* dstmap - how to swizzle from RGBA to dst format:
2171 */
2172 if (dstFormat == &_mesa_texformat_a8) {
2173 dstmap[0] = 3;
2174 }
2175 else {
2176 dstmap[0] = 0;
2177 }
2178 dstmap[1] = ZERO; /* ? */
2179 dstmap[2] = ZERO; /* ? */
2180 dstmap[3] = ONE; /* ? */
2181
2182 _mesa_swizzle_ubyte_image(ctx, dims,
2183 srcFormat,
2184 srcType,
2185 baseInternalFormat,
2186 dstmap, 1,
2187 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2188 dstRowStride, dstImageOffsets,
2189 srcWidth, srcHeight, srcDepth, srcAddr,
2190 srcPacking);
2191 }
2192 else {
2193 /* general path */
2194 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2195 baseInternalFormat,
2196 dstFormat->BaseFormat,
2197 srcWidth, srcHeight, srcDepth,
2198 srcFormat, srcType, srcAddr,
2199 srcPacking);
2200 const GLchan *src = tempImage;
2201 GLint img, row, col;
2202 if (!tempImage)
2203 return GL_FALSE;
2204 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2205 for (img = 0; img < srcDepth; img++) {
2206 GLubyte *dstRow = (GLubyte *) dstAddr
2207 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2208 + dstYoffset * dstRowStride
2209 + dstXoffset * dstFormat->TexelBytes;
2210 for (row = 0; row < srcHeight; row++) {
2211 for (col = 0; col < srcWidth; col++) {
2212 dstRow[col] = CHAN_TO_UBYTE(src[col]);
2213 }
2214 dstRow += dstRowStride;
2215 src += srcWidth;
2216 }
2217 }
2218 _mesa_free((void *) tempImage);
2219 }
2220 return GL_TRUE;
2221 }
2222
2223
2224
2225 GLboolean
2226 _mesa_texstore_ci8(TEXSTORE_PARAMS)
2227 {
2228 (void) dims; (void) baseInternalFormat;
2229 ASSERT(dstFormat == &_mesa_texformat_ci8);
2230 ASSERT(dstFormat->TexelBytes == 1);
2231 ASSERT(baseInternalFormat == GL_COLOR_INDEX);
2232
2233 if (!ctx->_ImageTransferState &&
2234 !srcPacking->SwapBytes &&
2235 srcFormat == GL_COLOR_INDEX &&
2236 srcType == GL_UNSIGNED_BYTE) {
2237 /* simple memcpy path */
2238 memcpy_texture(ctx, dims,
2239 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2240 dstRowStride,
2241 dstImageOffsets,
2242 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2243 srcAddr, srcPacking);
2244 }
2245 else {
2246 /* general path */
2247 GLint img, row;
2248 for (img = 0; img < srcDepth; img++) {
2249 GLubyte *dstRow = (GLubyte *) dstAddr
2250 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2251 + dstYoffset * dstRowStride
2252 + dstXoffset * dstFormat->TexelBytes;
2253 for (row = 0; row < srcHeight; row++) {
2254 const GLvoid *src = _mesa_image_address(dims, srcPacking,
2255 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
2256 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
2257 srcType, src, srcPacking,
2258 ctx->_ImageTransferState);
2259 dstRow += dstRowStride;
2260 }
2261 }
2262 }
2263 return GL_TRUE;
2264 }
2265
2266
2267 /**
2268 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
2269 */
2270 GLboolean
2271 _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
2272 {
2273 const GLboolean littleEndian = _mesa_little_endian();
2274 (void) ctx; (void) dims; (void) baseInternalFormat;
2275
2276 ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
2277 (dstFormat == &_mesa_texformat_ycbcr_rev));
2278 ASSERT(dstFormat->TexelBytes == 2);
2279 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
2280 ASSERT(srcFormat == GL_YCBCR_MESA);
2281 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
2282 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
2283 ASSERT(baseInternalFormat == GL_YCBCR_MESA);
2284
2285 /* always just memcpy since no pixel transfer ops apply */
2286 memcpy_texture(ctx, dims,
2287 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2288 dstRowStride,
2289 dstImageOffsets,
2290 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2291 srcAddr, srcPacking);
2292
2293 /* Check if we need byte swapping */
2294 /* XXX the logic here _might_ be wrong */
2295 if (srcPacking->SwapBytes ^
2296 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
2297 (dstFormat == &_mesa_texformat_ycbcr_rev) ^
2298 !littleEndian) {
2299 GLint img, row;
2300 for (img = 0; img < srcDepth; img++) {
2301 GLubyte *dstRow = (GLubyte *) dstAddr
2302 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2303 + dstYoffset * dstRowStride
2304 + dstXoffset * dstFormat->TexelBytes;
2305 for (row = 0; row < srcHeight; row++) {
2306 _mesa_swap2((GLushort *) dstRow, srcWidth);
2307 dstRow += dstRowStride;
2308 }
2309 }
2310 }
2311 return GL_TRUE;
2312 }
2313
2314
2315
2316 /**
2317 * Store a combined depth/stencil texture image.
2318 */
2319 GLboolean
2320 _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
2321 {
2322 ASSERT(dstFormat == &_mesa_texformat_z24_s8);
2323 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
2324 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
2325
2326 if (!ctx->_ImageTransferState &&
2327 !srcPacking->SwapBytes) {
2328 /* simple path */
2329 memcpy_texture(ctx, dims,
2330 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2331 dstRowStride,
2332 dstImageOffsets,
2333 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2334 srcAddr, srcPacking);
2335 }
2336 else {
2337 /* general path */
2338 const GLint srcRowStride
2339 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
2340 / sizeof(GLuint);
2341 GLint img, row;
2342
2343 for (img = 0; img < srcDepth; img++) {
2344 GLuint *dstRow = (GLuint *) dstAddr
2345 + dstImageOffsets[dstZoffset + img]
2346 + dstYoffset * dstRowStride / sizeof(GLuint)
2347 + dstXoffset;
2348 const GLuint *src
2349 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2350 srcWidth, srcHeight,
2351 srcFormat, srcType,
2352 img, 0, 0);
2353 for (row = 0; row < srcHeight; row++) {
2354 GLubyte stencil[MAX_WIDTH];
2355 GLint i;
2356 /* the 24 depth bits will be in the high position: */
2357 _mesa_unpack_depth_span(ctx, srcWidth,
2358 GL_UNSIGNED_INT, /* dst type */
2359 dstRow, /* dst addr */
2360 (GLfloat) 0xffffff, /* depthScale */
2361 srcType, src, srcPacking);
2362 /* get the 8-bit stencil values */
2363 _mesa_unpack_stencil_span(ctx, srcWidth,
2364 GL_UNSIGNED_BYTE, /* dst type */
2365 stencil, /* dst addr */
2366 srcType, src, srcPacking,
2367 ctx->_ImageTransferState);
2368 /* merge stencil values into depth values */
2369 for (i = 0; i < srcWidth; i++)
2370 dstRow[i] |= stencil[i];
2371
2372 src += srcRowStride;
2373 dstRow += dstRowStride / sizeof(GLuint);
2374 }
2375 }
2376 }
2377 return GL_TRUE;
2378 }
2379
2380
2381
2382 /**
2383 * Store an image in any of the formats:
2384 * _mesa_texformat_rgba_float32
2385 * _mesa_texformat_rgb_float32
2386 * _mesa_texformat_alpha_float32
2387 * _mesa_texformat_luminance_float32
2388 * _mesa_texformat_luminance_alpha_float32
2389 * _mesa_texformat_intensity_float32
2390 */
2391 GLboolean
2392 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
2393 {
2394 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
2395
2396 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
2397 dstFormat == &_mesa_texformat_rgb_float32 ||
2398 dstFormat == &_mesa_texformat_alpha_float32 ||
2399 dstFormat == &_mesa_texformat_luminance_float32 ||
2400 dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
2401 dstFormat == &_mesa_texformat_intensity_float32);
2402 ASSERT(baseInternalFormat == GL_RGBA ||
2403 baseInternalFormat == GL_RGB ||
2404 baseInternalFormat == GL_ALPHA ||
2405 baseInternalFormat == GL_LUMINANCE ||
2406 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2407 baseInternalFormat == GL_INTENSITY);
2408 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
2409
2410 if (!ctx->_ImageTransferState &&
2411 !srcPacking->SwapBytes &&
2412 baseInternalFormat == srcFormat &&
2413 srcType == GL_FLOAT) {
2414 /* simple memcpy path */
2415 memcpy_texture(ctx, dims,
2416 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2417 dstRowStride,
2418 dstImageOffsets,
2419 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2420 srcAddr, srcPacking);
2421 }
2422 else {
2423 /* general path */
2424 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2425 baseInternalFormat,
2426 dstFormat->BaseFormat,
2427 srcWidth, srcHeight, srcDepth,
2428 srcFormat, srcType, srcAddr,
2429 srcPacking);
2430 const GLfloat *srcRow = tempImage;
2431 GLint bytesPerRow;
2432 GLint img, row;
2433 if (!tempImage)
2434 return GL_FALSE;
2435 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2436 bytesPerRow = srcWidth * components * sizeof(GLfloat);
2437 for (img = 0; img < srcDepth; img++) {
2438 GLubyte *dstRow = (GLubyte *) dstAddr
2439 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2440 + dstYoffset * dstRowStride
2441 + dstXoffset * dstFormat->TexelBytes;
2442 for (row = 0; row < srcHeight; row++) {
2443 _mesa_memcpy(dstRow, srcRow, bytesPerRow);
2444 dstRow += dstRowStride;
2445 srcRow += srcWidth * components;
2446 }
2447 }
2448
2449 _mesa_free((void *) tempImage);
2450 }
2451 return GL_TRUE;
2452 }
2453
2454
2455 /**
2456 * As above, but store 16-bit floats.
2457 */
2458 GLboolean
2459 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
2460 {
2461 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
2462
2463 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
2464 dstFormat == &_mesa_texformat_rgb_float16 ||
2465 dstFormat == &_mesa_texformat_alpha_float16 ||
2466 dstFormat == &_mesa_texformat_luminance_float16 ||
2467 dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
2468 dstFormat == &_mesa_texformat_intensity_float16);
2469 ASSERT(baseInternalFormat == GL_RGBA ||
2470 baseInternalFormat == GL_RGB ||
2471 baseInternalFormat == GL_ALPHA ||
2472 baseInternalFormat == GL_LUMINANCE ||
2473 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2474 baseInternalFormat == GL_INTENSITY);
2475 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
2476
2477 if (!ctx->_ImageTransferState &&
2478 !srcPacking->SwapBytes &&
2479 baseInternalFormat == srcFormat &&
2480 srcType == GL_HALF_FLOAT_ARB) {
2481 /* simple memcpy path */
2482 memcpy_texture(ctx, dims,
2483 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2484 dstRowStride,
2485 dstImageOffsets,
2486 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2487 srcAddr, srcPacking);
2488 }
2489 else {
2490 /* general path */
2491 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2492 baseInternalFormat,
2493 dstFormat->BaseFormat,
2494 srcWidth, srcHeight, srcDepth,
2495 srcFormat, srcType, srcAddr,
2496 srcPacking);
2497 const GLfloat *src = tempImage;
2498 GLint img, row;
2499 if (!tempImage)
2500 return GL_FALSE;
2501 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2502 for (img = 0; img < srcDepth; img++) {
2503 GLubyte *dstRow = (GLubyte *) dstAddr
2504 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
2505 + dstYoffset * dstRowStride
2506 + dstXoffset * dstFormat->TexelBytes;
2507 for (row = 0; row < srcHeight; row++) {
2508 GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
2509 GLint i;
2510 for (i = 0; i < srcWidth * components; i++) {
2511 dstTexel[i] = _mesa_float_to_half(src[i]);
2512 }
2513 dstRow += dstRowStride;
2514 src += srcWidth * components;
2515 }
2516 }
2517
2518 _mesa_free((void *) tempImage);
2519 }
2520 return GL_TRUE;
2521 }
2522
2523
2524 #if FEATURE_EXT_texture_sRGB
2525 GLboolean
2526 _mesa_texstore_srgb8(TEXSTORE_PARAMS)
2527 {
2528 const GLboolean littleEndian = _mesa_little_endian();
2529 const struct gl_texture_format *newDstFormat;
2530 StoreTexImageFunc store;
2531 GLboolean k;
2532
2533 ASSERT(dstFormat == &_mesa_texformat_srgb8);
2534
2535 /* reuse normal rgb texstore code */
2536 if (littleEndian) {
2537 newDstFormat = &_mesa_texformat_bgr888;
2538 store = _mesa_texstore_bgr888;
2539 }
2540 else {
2541 newDstFormat = &_mesa_texformat_rgb888;
2542 store = _mesa_texstore_rgb888;
2543 }
2544
2545 k = store(ctx, dims, baseInternalFormat,
2546 newDstFormat, dstAddr,
2547 dstXoffset, dstYoffset, dstZoffset,
2548 dstRowStride, dstImageOffsets,
2549 srcWidth, srcHeight, srcDepth,
2550 srcFormat, srcType,
2551 srcAddr, srcPacking);
2552 return k;
2553 }
2554
2555
2556 GLboolean
2557 _mesa_texstore_srgba8(TEXSTORE_PARAMS)
2558 {
2559 const GLboolean littleEndian = _mesa_little_endian();
2560 const struct gl_texture_format *newDstFormat;
2561 GLboolean k;
2562
2563 ASSERT(dstFormat == &_mesa_texformat_srgba8);
2564
2565 /* reuse normal rgba texstore code */
2566 if (littleEndian)
2567 newDstFormat = &_mesa_texformat_rgba8888_rev;
2568 else
2569 newDstFormat = &_mesa_texformat_rgba8888;
2570
2571 k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
2572 newDstFormat, dstAddr,
2573 dstXoffset, dstYoffset, dstZoffset,
2574 dstRowStride, dstImageOffsets,
2575 srcWidth, srcHeight, srcDepth,
2576 srcFormat, srcType,
2577 srcAddr, srcPacking);
2578 return k;
2579 }
2580
2581
2582 GLboolean
2583 _mesa_texstore_sl8(TEXSTORE_PARAMS)
2584 {
2585 const struct gl_texture_format *newDstFormat;
2586 GLboolean k;
2587
2588 ASSERT(dstFormat == &_mesa_texformat_sl8);
2589
2590 newDstFormat = &_mesa_texformat_l8;
2591
2592 /* _mesa_textore_a8 handles luminance8 too */
2593 k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
2594 newDstFormat, dstAddr,
2595 dstXoffset, dstYoffset, dstZoffset,
2596 dstRowStride, dstImageOffsets,
2597 srcWidth, srcHeight, srcDepth,
2598 srcFormat, srcType,
2599 srcAddr, srcPacking);
2600 return k;
2601 }
2602
2603
2604 GLboolean
2605 _mesa_texstore_sla8(TEXSTORE_PARAMS)
2606 {
2607 const GLboolean littleEndian = _mesa_little_endian();
2608 const struct gl_texture_format *newDstFormat;
2609 GLboolean k;
2610
2611 ASSERT(dstFormat == &_mesa_texformat_sla8);
2612
2613 /* reuse normal luminance/alpha texstore code */
2614 if (littleEndian)
2615 newDstFormat = &_mesa_texformat_al88;
2616 else
2617 newDstFormat = &_mesa_texformat_al88_rev;
2618
2619 k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
2620 newDstFormat, dstAddr,
2621 dstXoffset, dstYoffset, dstZoffset,
2622 dstRowStride, dstImageOffsets,
2623 srcWidth, srcHeight, srcDepth,
2624 srcFormat, srcType,
2625 srcAddr, srcPacking);
2626 return k;
2627 }
2628
2629 #endif /* FEATURE_EXT_texture_sRGB */
2630
2631
2632 /**
2633 * Check if an unpack PBO is active prior to fetching a texture image.
2634 * If so, do bounds checking and map the buffer into main memory.
2635 * Any errors detected will be recorded.
2636 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2637 */
2638 const GLvoid *
2639 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
2640 GLsizei width, GLsizei height, GLsizei depth,
2641 GLenum format, GLenum type, const GLvoid *pixels,
2642 const struct gl_pixelstore_attrib *unpack,
2643 const char *funcName)
2644 {
2645 GLubyte *buf;
2646
2647 if (unpack->BufferObj->Name == 0) {
2648 /* no PBO */
2649 return pixels;
2650 }
2651 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
2652 format, type, pixels)) {
2653 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2654 return NULL;
2655 }
2656
2657 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2658 GL_READ_ONLY_ARB, unpack->BufferObj);
2659 if (!buf) {
2660 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2661 return NULL;
2662 }
2663
2664 return ADD_POINTERS(buf, pixels);
2665 }
2666
2667
2668 /**
2669 * Check if an unpack PBO is active prior to fetching a compressed texture
2670 * image.
2671 * If so, do bounds checking and map the buffer into main memory.
2672 * Any errors detected will be recorded.
2673 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2674 */
2675 const GLvoid *
2676 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
2677 GLsizei imageSize, const GLvoid *pixels,
2678 const struct gl_pixelstore_attrib *packing,
2679 const char *funcName)
2680 {
2681 GLubyte *buf;
2682
2683 if (packing->BufferObj->Name == 0) {
2684 /* not using a PBO - return pointer unchanged */
2685 return pixels;
2686 }
2687 if ((const GLubyte *) pixels + imageSize >
2688 ((const GLubyte *) 0) + packing->BufferObj->Size) {
2689 /* out of bounds read! */
2690 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2691 return NULL;
2692 }
2693
2694 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2695 GL_READ_ONLY_ARB, packing->BufferObj);
2696 if (!buf) {
2697 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2698 return NULL;
2699 }
2700
2701 return ADD_POINTERS(buf, pixels);
2702 }
2703
2704
2705 /**
2706 * This function must be called after either of the validate_pbo_*_teximage()
2707 * functions. It unmaps the PBO buffer if it was mapped earlier.
2708 */
2709 void
2710 _mesa_unmap_teximage_pbo(GLcontext *ctx,
2711 const struct gl_pixelstore_attrib *unpack)
2712 {
2713 if (unpack->BufferObj->Name) {
2714 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2715 unpack->BufferObj);
2716 }
2717 }
2718
2719
2720
2721 /**
2722 * Adaptor for fetching a GLchan texel from a float-valued texture.
2723 */
2724 static void
2725 fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
2726 GLint i, GLint j, GLint k, GLchan *texelOut)
2727 {
2728 GLfloat temp[4];
2729 ASSERT(texImage->FetchTexelf);
2730 texImage->FetchTexelf(texImage, i, j, k, temp);
2731 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
2732 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
2733 /* just one channel */
2734 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2735 }
2736 else {
2737 /* four channels */
2738 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2739 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
2740 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
2741 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
2742 }
2743 }
2744
2745
2746 /**
2747 * Adaptor for fetching a float texel from a GLchan-valued texture.
2748 */
2749 static void
2750 fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
2751 GLint i, GLint j, GLint k, GLfloat *texelOut)
2752 {
2753 GLchan temp[4];
2754 ASSERT(texImage->FetchTexelc);
2755 texImage->FetchTexelc(texImage, i, j, k, temp);
2756 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
2757 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
2758 /* just one channel */
2759 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2760 }
2761 else {
2762 /* four channels */
2763 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2764 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
2765 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
2766 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
2767 }
2768 }
2769
2770
2771 /**
2772 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2773 */
2774 void
2775 _mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
2776 {
2777 ASSERT(dims == 1 || dims == 2 || dims == 3);
2778 ASSERT(texImage->TexFormat);
2779
2780 switch (dims) {
2781 case 1:
2782 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
2783 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
2784 break;
2785 case 2:
2786 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2787 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2788 break;
2789 case 3:
2790 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
2791 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
2792 break;
2793 default:
2794 ;
2795 }
2796
2797 /* now check if we need to use a float/chan adaptor */
2798 if (!texImage->FetchTexelc) {
2799 texImage->FetchTexelc = fetch_texel_float_to_chan;
2800 }
2801 else if (!texImage->FetchTexelf) {
2802 texImage->FetchTexelf = fetch_texel_chan_to_float;
2803 }
2804
2805
2806 ASSERT(texImage->FetchTexelc);
2807 ASSERT(texImage->FetchTexelf);
2808 }
2809
2810
2811 /**
2812 * Choose the actual storage format for a new texture image.
2813 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
2814 * Also set some other texImage fields related to texture compression, etc.
2815 * \param ctx rendering context
2816 * \param texImage the gl_texture_image
2817 * \param dims texture dimensions (1, 2 or 3)
2818 * \param format the user-specified format parameter
2819 * \param type the user-specified type parameter
2820 * \param internalFormat the user-specified internal format hint
2821 */
2822 static void
2823 choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage,
2824 GLuint dims,
2825 GLenum format, GLenum type, GLint internalFormat)
2826 {
2827 ASSERT(dims == 1 || dims == 2 || dims == 3);
2828 ASSERT(ctx->Driver.ChooseTextureFormat);
2829
2830 texImage->TexFormat
2831 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2832
2833 ASSERT(texImage->TexFormat);
2834
2835 _mesa_set_fetch_functions(texImage, dims);
2836
2837 if (texImage->TexFormat->TexelBytes == 0) {
2838 /* must be a compressed format */
2839 texImage->IsCompressed = GL_TRUE;
2840 texImage->CompressedSize =
2841 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
2842 texImage->Height, texImage->Depth,
2843 texImage->TexFormat->MesaFormat);
2844 }
2845 else {
2846 /* non-compressed format */
2847 texImage->IsCompressed = GL_FALSE;
2848 texImage->CompressedSize = 0;
2849 }
2850 }
2851
2852
2853
2854 /*
2855 * This is the software fallback for Driver.TexImage1D()
2856 * and Driver.CopyTexImage1D().
2857 * \sa _mesa_store_teximage2d()
2858 */
2859 void
2860 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2861 GLint internalFormat,
2862 GLint width, GLint border,
2863 GLenum format, GLenum type, const GLvoid *pixels,
2864 const struct gl_pixelstore_attrib *packing,
2865 struct gl_texture_object *texObj,
2866 struct gl_texture_image *texImage)
2867 {
2868 GLint postConvWidth = width;
2869 GLint sizeInBytes;
2870 (void) border;
2871
2872 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2873 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2874 }
2875
2876 choose_texture_format(ctx, texImage, 1, format, type, internalFormat);
2877
2878 /* allocate memory */
2879 if (texImage->IsCompressed)
2880 sizeInBytes = texImage->CompressedSize;
2881 else
2882 sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes;
2883 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2884 if (!texImage->Data) {
2885 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2886 return;
2887 }
2888
2889 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2890 pixels, packing, "glTexImage1D");
2891 if (!pixels) {
2892 /* Note: we check for a NULL image pointer here, _after_ we allocated
2893 * memory for the texture. That's what the GL spec calls for.
2894 */
2895 return;
2896 }
2897 else {
2898 const GLint dstRowStride = 0;
2899 GLboolean success;
2900 ASSERT(texImage->TexFormat->StoreImage);
2901 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
2902 texImage->TexFormat,
2903 texImage->Data,
2904 0, 0, 0, /* dstX/Y/Zoffset */
2905 dstRowStride,
2906 texImage->ImageOffsets,
2907 width, 1, 1,
2908 format, type, pixels, packing);
2909 if (!success) {
2910 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2911 }
2912 }
2913
2914 /* GL_SGIS_generate_mipmap */
2915 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2916 _mesa_generate_mipmap(ctx, target,
2917 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2918 texObj);
2919 }
2920
2921 _mesa_unmap_teximage_pbo(ctx, packing);
2922 }
2923
2924
2925 /**
2926 * This is the software fallback for Driver.TexImage2D()
2927 * and Driver.CopyTexImage2D().
2928 *
2929 * This function is oriented toward storing images in main memory, rather
2930 * than VRAM. Device driver's can easily plug in their own replacement.
2931 *
2932 * Note: width and height may be pre-convolved dimensions, but
2933 * texImage->Width and texImage->Height will be post-convolved dimensions.
2934 */
2935 void
2936 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2937 GLint internalFormat,
2938 GLint width, GLint height, GLint border,
2939 GLenum format, GLenum type, const void *pixels,
2940 const struct gl_pixelstore_attrib *packing,
2941 struct gl_texture_object *texObj,
2942 struct gl_texture_image *texImage)
2943 {
2944 GLint postConvWidth = width, postConvHeight = height;
2945 GLint texelBytes, sizeInBytes;
2946 (void) border;
2947
2948 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2949 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2950 &postConvHeight);
2951 }
2952
2953 choose_texture_format(ctx, texImage, 2, format, type, internalFormat);
2954
2955 texelBytes = texImage->TexFormat->TexelBytes;
2956
2957 /* allocate memory */
2958 if (texImage->IsCompressed)
2959 sizeInBytes = texImage->CompressedSize;
2960 else
2961 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
2962 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2963 if (!texImage->Data) {
2964 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2965 return;
2966 }
2967
2968 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2969 pixels, packing, "glTexImage2D");
2970 if (!pixels) {
2971 /* Note: we check for a NULL image pointer here, _after_ we allocated
2972 * memory for the texture. That's what the GL spec calls for.
2973 */
2974 return;
2975 }
2976 else {
2977 GLint dstRowStride;
2978 GLboolean success;
2979 if (texImage->IsCompressed) {
2980 dstRowStride
2981 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
2982 }
2983 else {
2984 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
2985 }
2986 ASSERT(texImage->TexFormat->StoreImage);
2987 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
2988 texImage->TexFormat,
2989 texImage->Data,
2990 0, 0, 0, /* dstX/Y/Zoffset */
2991 dstRowStride,
2992 texImage->ImageOffsets,
2993 width, height, 1,
2994 format, type, pixels, packing);
2995 if (!success) {
2996 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2997 }
2998 }
2999
3000 /* GL_SGIS_generate_mipmap */
3001 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3002 _mesa_generate_mipmap(ctx, target,
3003 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3004 texObj);
3005 }
3006
3007 _mesa_unmap_teximage_pbo(ctx, packing);
3008 }
3009
3010
3011
3012 /**
3013 * This is the software fallback for Driver.TexImage3D()
3014 * and Driver.CopyTexImage3D().
3015 * \sa _mesa_store_teximage2d()
3016 */
3017 void
3018 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3019 GLint internalFormat,
3020 GLint width, GLint height, GLint depth, GLint border,
3021 GLenum format, GLenum type, const void *pixels,
3022 const struct gl_pixelstore_attrib *packing,
3023 struct gl_texture_object *texObj,
3024 struct gl_texture_image *texImage)
3025 {
3026 GLint texelBytes, sizeInBytes;
3027 (void) border;
3028
3029 choose_texture_format(ctx, texImage, 3, format, type, internalFormat);
3030
3031 texelBytes = texImage->TexFormat->TexelBytes;
3032
3033 /* allocate memory */
3034 if (texImage->IsCompressed)
3035 sizeInBytes = texImage->CompressedSize;
3036 else
3037 sizeInBytes = width * height * depth * texelBytes;
3038 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
3039 if (!texImage->Data) {
3040 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3041 return;
3042 }
3043
3044 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3045 type, pixels, packing, "glTexImage3D");
3046 if (!pixels) {
3047 /* Note: we check for a NULL image pointer here, _after_ we allocated
3048 * memory for the texture. That's what the GL spec calls for.
3049 */
3050 return;
3051 }
3052 else {
3053 GLint dstRowStride;
3054 GLboolean success;
3055 if (texImage->IsCompressed) {
3056 dstRowStride
3057 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
3058 }
3059 else {
3060 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3061 }
3062 ASSERT(texImage->TexFormat->StoreImage);
3063 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
3064 texImage->TexFormat,
3065 texImage->Data,
3066 0, 0, 0, /* dstX/Y/Zoffset */
3067 dstRowStride,
3068 texImage->ImageOffsets,
3069 width, height, depth,
3070 format, type, pixels, packing);
3071 if (!success) {
3072 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
3073 }
3074 }
3075
3076 /* GL_SGIS_generate_mipmap */
3077 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3078 _mesa_generate_mipmap(ctx, target,
3079 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3080 texObj);
3081 }
3082
3083 _mesa_unmap_teximage_pbo(ctx, packing);
3084 }
3085
3086
3087
3088
3089 /*
3090 * This is the software fallback for Driver.TexSubImage1D()
3091 * and Driver.CopyTexSubImage1D().
3092 */
3093 void
3094 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
3095 GLint xoffset, GLint width,
3096 GLenum format, GLenum type, const void *pixels,
3097 const struct gl_pixelstore_attrib *packing,
3098 struct gl_texture_object *texObj,
3099 struct gl_texture_image *texImage)
3100 {
3101 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3102 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
3103 pixels, packing, "glTexSubImage1D");
3104 if (!pixels)
3105 return;
3106
3107 {
3108 const GLint dstRowStride = 0;
3109 GLboolean success;
3110 ASSERT(texImage->TexFormat->StoreImage);
3111 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
3112 texImage->TexFormat,
3113 texImage->Data,
3114 xoffset, 0, 0, /* offsets */
3115 dstRowStride,
3116 texImage->ImageOffsets,
3117 width, 1, 1,
3118 format, type, pixels, packing);
3119 if (!success) {
3120 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
3121 }
3122 }
3123
3124 /* GL_SGIS_generate_mipmap */
3125 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3126 _mesa_generate_mipmap(ctx, target,
3127 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3128 texObj);
3129 }
3130
3131 _mesa_unmap_teximage_pbo(ctx, packing);
3132 }
3133
3134
3135
3136 /**
3137 * This is the software fallback for Driver.TexSubImage2D()
3138 * and Driver.CopyTexSubImage2D().
3139 */
3140 void
3141 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
3142 GLint xoffset, GLint yoffset,
3143 GLint width, GLint height,
3144 GLenum format, GLenum type, const void *pixels,
3145 const struct gl_pixelstore_attrib *packing,
3146 struct gl_texture_object *texObj,
3147 struct gl_texture_image *texImage)
3148 {
3149 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3150 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
3151 pixels, packing, "glTexSubImage2D");
3152 if (!pixels)
3153 return;
3154
3155 {
3156 GLint dstRowStride = 0;
3157 GLboolean success;
3158 if (texImage->IsCompressed) {
3159 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3160 texImage->Width);
3161 }
3162 else {
3163 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3164 }
3165 ASSERT(texImage->TexFormat->StoreImage);
3166 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
3167 texImage->TexFormat,
3168 texImage->Data,
3169 xoffset, yoffset, 0,
3170 dstRowStride,
3171 texImage->ImageOffsets,
3172 width, height, 1,
3173 format, type, pixels, packing);
3174 if (!success) {
3175 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
3176 }
3177 }
3178
3179 /* GL_SGIS_generate_mipmap */
3180 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3181 _mesa_generate_mipmap(ctx, target,
3182 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3183 texObj);
3184 }
3185
3186 _mesa_unmap_teximage_pbo(ctx, packing);
3187 }
3188
3189
3190 /*
3191 * This is the software fallback for Driver.TexSubImage3D().
3192 * and Driver.CopyTexSubImage3D().
3193 */
3194 void
3195 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
3196 GLint xoffset, GLint yoffset, GLint zoffset,
3197 GLint width, GLint height, GLint depth,
3198 GLenum format, GLenum type, const void *pixels,
3199 const struct gl_pixelstore_attrib *packing,
3200 struct gl_texture_object *texObj,
3201 struct gl_texture_image *texImage)
3202 {
3203 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3204 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
3205 type, pixels, packing,
3206 "glTexSubImage3D");
3207 if (!pixels)
3208 return;
3209
3210 {
3211 GLint dstRowStride;
3212 GLboolean success;
3213 if (texImage->IsCompressed) {
3214 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
3215 texImage->Width);
3216 }
3217 else {
3218 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
3219 }
3220 ASSERT(texImage->TexFormat->StoreImage);
3221 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
3222 texImage->TexFormat,
3223 texImage->Data,
3224 xoffset, yoffset, zoffset,
3225 dstRowStride,
3226 texImage->ImageOffsets,
3227 width, height, depth,
3228 format, type, pixels, packing);
3229 if (!success) {
3230 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
3231 }
3232 }
3233
3234 /* GL_SGIS_generate_mipmap */
3235 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3236 _mesa_generate_mipmap(ctx, target,
3237 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3238 texObj);
3239 }
3240
3241 _mesa_unmap_teximage_pbo(ctx, packing);
3242 }
3243
3244
3245 /*
3246 * Fallback for Driver.CompressedTexImage1D()
3247 */
3248 void
3249 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
3250 GLint internalFormat,
3251 GLint width, GLint border,
3252 GLsizei imageSize, const GLvoid *data,
3253 struct gl_texture_object *texObj,
3254 struct gl_texture_image *texImage)
3255 {
3256 /* this space intentionally left blank */
3257 (void) ctx;
3258 (void) target; (void) level;
3259 (void) internalFormat;
3260 (void) width; (void) border;
3261 (void) imageSize; (void) data;
3262 (void) texObj;
3263 (void) texImage;
3264 }
3265
3266
3267
3268 /**
3269 * Fallback for Driver.CompressedTexImage2D()
3270 */
3271 void
3272 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
3273 GLint internalFormat,
3274 GLint width, GLint height, GLint border,
3275 GLsizei imageSize, const GLvoid *data,
3276 struct gl_texture_object *texObj,
3277 struct gl_texture_image *texImage)
3278 {
3279 (void) width; (void) height; (void) border;
3280
3281 /* This is pretty simple, basically just do a memcpy without worrying
3282 * about the usual image unpacking or image transfer operations.
3283 */
3284 ASSERT(texObj);
3285 ASSERT(texImage);
3286 ASSERT(texImage->Width > 0);
3287 ASSERT(texImage->Height > 0);
3288 ASSERT(texImage->Depth == 1);
3289 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
3290
3291 choose_texture_format(ctx, texImage, 2, 0, 0, internalFormat);
3292
3293 /* allocate storage */
3294 texImage->Data = _mesa_alloc_texmemory(imageSize);
3295 if (!texImage->Data) {
3296 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3297 return;
3298 }
3299
3300 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3301 &ctx->Unpack,
3302 "glCompressedTexImage2D");
3303 if (!data)
3304 return;
3305
3306 /* copy the data */
3307 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
3308 MEMCPY(texImage->Data, data, imageSize);
3309
3310 /* GL_SGIS_generate_mipmap */
3311 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3312 _mesa_generate_mipmap(ctx, target,
3313 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3314 texObj);
3315 }
3316
3317 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3318 }
3319
3320
3321
3322 /*
3323 * Fallback for Driver.CompressedTexImage3D()
3324 */
3325 void
3326 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
3327 GLint internalFormat,
3328 GLint width, GLint height, GLint depth,
3329 GLint border,
3330 GLsizei imageSize, const GLvoid *data,
3331 struct gl_texture_object *texObj,
3332 struct gl_texture_image *texImage)
3333 {
3334 /* this space intentionally left blank */
3335 (void) ctx;
3336 (void) target; (void) level;
3337 (void) internalFormat;
3338 (void) width; (void) height; (void) depth;
3339 (void) border;
3340 (void) imageSize; (void) data;
3341 (void) texObj;
3342 (void) texImage;
3343 }
3344
3345
3346
3347 /**
3348 * Fallback for Driver.CompressedTexSubImage1D()
3349 */
3350 void
3351 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
3352 GLint level,
3353 GLint xoffset, GLsizei width,
3354 GLenum format,
3355 GLsizei imageSize, const GLvoid *data,
3356 struct gl_texture_object *texObj,
3357 struct gl_texture_image *texImage)
3358 {
3359 /* there are no compressed 1D texture formats yet */
3360 (void) ctx;
3361 (void) target; (void) level;
3362 (void) xoffset; (void) width;
3363 (void) format;
3364 (void) imageSize; (void) data;
3365 (void) texObj;
3366 (void) texImage;
3367 }
3368
3369
3370 /**
3371 * Fallback for Driver.CompressedTexSubImage2D()
3372 */
3373 void
3374 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
3375 GLint level,
3376 GLint xoffset, GLint yoffset,
3377 GLsizei width, GLsizei height,
3378 GLenum format,
3379 GLsizei imageSize, const GLvoid *data,
3380 struct gl_texture_object *texObj,
3381 struct gl_texture_image *texImage)
3382 {
3383 GLint bytesPerRow, destRowStride, srcRowStride;
3384 GLint i, rows;
3385 GLubyte *dest;
3386 const GLubyte *src;
3387 const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
3388
3389 (void) format;
3390
3391 /* these should have been caught sooner */
3392 ASSERT((width & 3) == 0 || width == 2 || width == 1);
3393 ASSERT((height & 3) == 0 || height == 2 || height == 1);
3394 ASSERT((xoffset & 3) == 0);
3395 ASSERT((yoffset & 3) == 0);
3396
3397 /* get pointer to src pixels (may be in a pbo which we'll map here) */
3398 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
3399 &ctx->Unpack,
3400 "glCompressedTexSubImage2D");
3401 if (!data)
3402 return;
3403
3404 srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
3405 src = (const GLubyte *) data;
3406
3407 destRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width);
3408 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
3409 texImage->TexFormat->MesaFormat,
3410 texImage->Width,
3411 (GLubyte *) texImage->Data);
3412
3413 bytesPerRow = srcRowStride;
3414 rows = height / 4;
3415
3416 for (i = 0; i < rows; i++) {
3417 MEMCPY(dest, src, bytesPerRow);
3418 dest += destRowStride;
3419 src += srcRowStride;
3420 }
3421
3422 /* GL_SGIS_generate_mipmap */
3423 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
3424 _mesa_generate_mipmap(ctx, target,
3425 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
3426 texObj);
3427 }
3428
3429 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
3430 }
3431
3432
3433 /**
3434 * Fallback for Driver.CompressedTexSubImage3D()
3435 */
3436 void
3437 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
3438 GLint level,
3439 GLint xoffset, GLint yoffset, GLint zoffset,
3440 GLsizei width, GLsizei height, GLsizei depth,
3441 GLenum format,
3442 GLsizei imageSize, const GLvoid *data,
3443 struct gl_texture_object *texObj,
3444 struct gl_texture_image *texImage)
3445 {
3446 /* there are no compressed 3D texture formats yet */
3447 (void) ctx;
3448 (void) target; (void) level;
3449 (void) xoffset; (void) yoffset; (void) zoffset;
3450 (void) width; (void) height; (void) depth;
3451 (void) format;
3452 (void) imageSize; (void) data;
3453 (void) texObj;
3454 (void) texImage;
3455 }
3456
3457
3458
3459
3460 #if FEATURE_EXT_texture_sRGB
3461
3462 /**
3463 * Test if given texture image is an sRGB format.
3464 */
3465 static GLboolean
3466 is_srgb_teximage(const struct gl_texture_image *texImage)
3467 {
3468 switch (texImage->TexFormat->MesaFormat) {
3469 case MESA_FORMAT_SRGB8:
3470 case MESA_FORMAT_SRGBA8:
3471 case MESA_FORMAT_SL8:
3472 case MESA_FORMAT_SLA8:
3473 return GL_TRUE;
3474 default:
3475 return GL_FALSE;
3476 }
3477 }
3478
3479 #endif /* FEATURE_EXT_texture_sRGB */
3480
3481
3482 /**
3483 * This is the software fallback for Driver.GetTexImage().
3484 * All error checking will have been done before this routine is called.
3485 */
3486 void
3487 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
3488 GLenum format, GLenum type, GLvoid *pixels,
3489 struct gl_texture_object *texObj,
3490 struct gl_texture_image *texImage)
3491 {
3492 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
3493
3494 if (ctx->Pack.BufferObj->Name) {
3495 /* Packing texture image into a PBO.
3496 * Map the (potentially) VRAM-based buffer into our process space so
3497 * we can write into it with the code below.
3498 * A hardware driver might use a sophisticated blit to move the
3499 * texture data to the PBO if the PBO is in VRAM along with the texture.
3500 */
3501 GLubyte *buf = (GLubyte *)
3502 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3503 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
3504 if (!buf) {
3505 /* buffer is already mapped - that's an error */
3506 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
3507 return;
3508 }
3509 /* <pixels> was an offset into the PBO.
3510 * Now make it a real, client-side pointer inside the mapped region.
3511 */
3512 pixels = ADD_POINTERS(buf, pixels);
3513 }
3514 else if (!pixels) {
3515 /* not an error */
3516 return;
3517 }
3518
3519 {
3520 const GLint width = texImage->Width;
3521 const GLint height = texImage->Height;
3522 const GLint depth = texImage->Depth;
3523 GLint img, row;
3524 for (img = 0; img < depth; img++) {
3525 for (row = 0; row < height; row++) {
3526 /* compute destination address in client memory */
3527 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
3528 width, height, format, type,
3529 img, row, 0);
3530 assert(dest);
3531
3532 if (format == GL_COLOR_INDEX) {
3533 GLuint indexRow[MAX_WIDTH];
3534 GLint col;
3535 /* Can't use FetchTexel here because that returns RGBA */
3536 if (texImage->TexFormat->IndexBits == 8) {
3537 const GLubyte *src = (const GLubyte *) texImage->Data;
3538 src += width * (img * texImage->Height + row);
3539 for (col = 0; col < width; col++) {
3540 indexRow[col] = src[col];
3541 }
3542 }
3543 else if (texImage->TexFormat->IndexBits == 16) {
3544 const GLushort *src = (const GLushort *) texImage->Data;
3545 src += width * (img * texImage->Height + row);
3546 for (col = 0; col < width; col++) {
3547 indexRow[col] = src[col];
3548 }
3549 }
3550 else {
3551 _mesa_problem(ctx,
3552 "Color index problem in _mesa_GetTexImage");
3553 }
3554 _mesa_pack_index_span(ctx, width, type, dest,
3555 indexRow, &ctx->Pack,
3556 0 /* no image transfer */);
3557 }
3558 else if (format == GL_DEPTH_COMPONENT) {
3559 GLfloat depthRow[MAX_WIDTH];
3560 GLint col;
3561 for (col = 0; col < width; col++) {
3562 (*texImage->FetchTexelf)(texImage, col, row, img,
3563 depthRow + col);
3564 }
3565 _mesa_pack_depth_span(ctx, width, dest, type,
3566 depthRow, &ctx->Pack);
3567 }
3568 else if (format == GL_DEPTH_STENCIL_EXT) {
3569 /* XXX Note: we're bypassing texImage->FetchTexel()! */
3570 const GLuint *src = (const GLuint *) texImage->Data;
3571 src += width * row + width * height * img;
3572 _mesa_memcpy(dest, src, width * sizeof(GLuint));
3573 if (ctx->Pack.SwapBytes) {
3574 _mesa_swap4((GLuint *) dest, width);
3575 }
3576 }
3577 else if (format == GL_YCBCR_MESA) {
3578 /* No pixel transfer */
3579 const GLint rowstride = texImage->RowStride;
3580 MEMCPY(dest,
3581 (const GLushort *) texImage->Data + row * rowstride,
3582 width * sizeof(GLushort));
3583 /* check for byte swapping */
3584 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
3585 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
3586 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
3587 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
3588 if (!ctx->Pack.SwapBytes)
3589 _mesa_swap2((GLushort *) dest, width);
3590 }
3591 else if (ctx->Pack.SwapBytes) {
3592 _mesa_swap2((GLushort *) dest, width);
3593 }
3594 }
3595 #if FEATURE_EXT_texture_sRGB
3596 else if (is_srgb_teximage(texImage)) {
3597 /* no pixel transfer and no non-linear to linear conversion */
3598 const GLint comps = texImage->TexFormat->TexelBytes;
3599 const GLint rowstride = comps * texImage->RowStride;
3600 MEMCPY(dest,
3601 (const GLubyte *) texImage->Data + row * rowstride,
3602 comps * width * sizeof(GLubyte));
3603 }
3604 #endif /* FEATURE_EXT_texture_sRGB */
3605 else {
3606 /* general case: convert row to RGBA format */
3607 GLfloat rgba[MAX_WIDTH][4];
3608 GLint col;
3609 for (col = 0; col < width; col++) {
3610 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
3611 if (texImage->TexFormat->BaseFormat == GL_ALPHA) {
3612 rgba[col][RCOMP] = 0.0;
3613 rgba[col][GCOMP] = 0.0;
3614 rgba[col][BCOMP] = 0.0;
3615 }
3616 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) {
3617 rgba[col][GCOMP] = 0.0;
3618 rgba[col][BCOMP] = 0.0;
3619 rgba[col][ACOMP] = 1.0;
3620 }
3621 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) {
3622 rgba[col][GCOMP] = 0.0;
3623 rgba[col][BCOMP] = 0.0;
3624 }
3625 else if (texImage->TexFormat->BaseFormat == GL_INTENSITY) {
3626 rgba[col][GCOMP] = 0.0;
3627 rgba[col][BCOMP] = 0.0;
3628 rgba[col][ACOMP] = 1.0;
3629 }
3630 }
3631 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
3632 format, type, dest,
3633 &ctx->Pack, 0x0 /*image xfer ops*/);
3634 } /* format */
3635 } /* row */
3636 } /* img */
3637 }
3638
3639 if (ctx->Pack.BufferObj->Name) {
3640 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3641 ctx->Pack.BufferObj);
3642 }
3643 }
3644
3645
3646
3647 /**
3648 * This is the software fallback for Driver.GetCompressedTexImage().
3649 * All error checking will have been done before this routine is called.
3650 */
3651 void
3652 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
3653 GLvoid *img,
3654 const struct gl_texture_object *texObj,
3655 const struct gl_texture_image *texImage)
3656 {
3657 GLuint size;
3658
3659 if (ctx->Pack.BufferObj->Name) {
3660 /* pack texture image into a PBO */
3661 GLubyte *buf;
3662 if ((const GLubyte *) img + texImage->CompressedSize >
3663 (const GLubyte *) ctx->Pack.BufferObj->Size) {
3664 _mesa_error(ctx, GL_INVALID_OPERATION,
3665 "glGetCompressedTexImage(invalid PBO access)");
3666 return;
3667 }
3668 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3669 GL_WRITE_ONLY_ARB,
3670 ctx->Pack.BufferObj);
3671 if (!buf) {
3672 /* buffer is already mapped - that's an error */
3673 _mesa_error(ctx, GL_INVALID_OPERATION,
3674 "glGetCompressedTexImage(PBO is mapped)");
3675 return;
3676 }
3677 img = ADD_POINTERS(buf, img);
3678 }
3679 else if (!img) {
3680 /* not an error */
3681 return;
3682 }
3683
3684 /* don't use texImage->CompressedSize since that may be padded out */
3685 size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height,
3686 texImage->Depth,
3687 texImage->TexFormat->MesaFormat);
3688
3689 /* just memcpy, no pixelstore or pixel transfer */
3690 _mesa_memcpy(img, texImage->Data, size);
3691
3692 if (ctx->Pack.BufferObj->Name) {
3693 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3694 ctx->Pack.BufferObj);
3695 }
3696 }