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