OSDN Git Service

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