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