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