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