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