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