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