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