OSDN Git Service

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