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