texstore.c revision 0ecbb0ab7472fe5cb33be13a8307e16f875254e5
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, 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 "image.h"
59#include "macros.h"
60#include "mipmap.h"
61#include "mfeatures.h"
62#include "mtypes.h"
63#include "pack.h"
64#include "pbo.h"
65#include "imports.h"
66#include "pack.h"
67#include "texcompress.h"
68#include "texcompress_fxt1.h"
69#include "texcompress_rgtc.h"
70#include "texcompress_s3tc.h"
71#include "teximage.h"
72#include "texstore.h"
73#include "enums.h"
74
75
76enum {
77   ZERO = 4,
78   ONE = 5
79};
80
81
82/**
83 * Texture image storage function.
84 */
85typedef GLboolean (*StoreTexImageFunc)(TEXSTORE_PARAMS);
86
87
88/**
89 * Return GL_TRUE if the given image format is one that be converted
90 * to another format by swizzling.
91 */
92static GLboolean
93can_swizzle(GLenum logicalBaseFormat)
94{
95   switch (logicalBaseFormat) {
96   case GL_RGBA:
97   case GL_RGB:
98   case GL_LUMINANCE_ALPHA:
99   case GL_INTENSITY:
100   case GL_ALPHA:
101   case GL_LUMINANCE:
102   case GL_RED:
103   case GL_GREEN:
104   case GL_BLUE:
105   case GL_BGR:
106   case GL_BGRA:
107   case GL_ABGR_EXT:
108   case GL_RG:
109      return GL_TRUE;
110   default:
111      return GL_FALSE;
112   }
113}
114
115
116
117enum {
118   IDX_LUMINANCE = 0,
119   IDX_ALPHA,
120   IDX_INTENSITY,
121   IDX_LUMINANCE_ALPHA,
122   IDX_RGB,
123   IDX_RGBA,
124   IDX_RED,
125   IDX_GREEN,
126   IDX_BLUE,
127   IDX_BGR,
128   IDX_BGRA,
129   IDX_ABGR,
130   IDX_RG,
131   MAX_IDX
132};
133
134#define MAP1(x)       MAP4(x, ZERO, ZERO, ZERO)
135#define MAP2(x,y)     MAP4(x, y, ZERO, ZERO)
136#define MAP3(x,y,z)   MAP4(x, y, z, ZERO)
137#define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
138
139
140static const struct {
141   GLubyte format_idx;
142   GLubyte to_rgba[6];
143   GLubyte from_rgba[6];
144} mappings[MAX_IDX] =
145{
146   {
147      IDX_LUMINANCE,
148      MAP4(0,0,0,ONE),
149      MAP1(0)
150   },
151
152   {
153      IDX_ALPHA,
154      MAP4(ZERO, ZERO, ZERO, 0),
155      MAP1(3)
156   },
157
158   {
159      IDX_INTENSITY,
160      MAP4(0, 0, 0, 0),
161      MAP1(0),
162   },
163
164   {
165      IDX_LUMINANCE_ALPHA,
166      MAP4(0,0,0,1),
167      MAP2(0,3)
168   },
169
170   {
171      IDX_RGB,
172      MAP4(0,1,2,ONE),
173      MAP3(0,1,2)
174   },
175
176   {
177      IDX_RGBA,
178      MAP4(0,1,2,3),
179      MAP4(0,1,2,3),
180   },
181
182   {
183      IDX_RED,
184      MAP4(0, ZERO, ZERO, ONE),
185      MAP1(0),
186   },
187
188   {
189      IDX_GREEN,
190      MAP4(ZERO, 0, ZERO, ONE),
191      MAP1(1),
192   },
193
194   {
195      IDX_BLUE,
196      MAP4(ZERO, ZERO, 0, ONE),
197      MAP1(2),
198   },
199
200   {
201      IDX_BGR,
202      MAP4(2,1,0,ONE),
203      MAP3(2,1,0)
204   },
205
206   {
207      IDX_BGRA,
208      MAP4(2,1,0,3),
209      MAP4(2,1,0,3)
210   },
211
212   {
213      IDX_ABGR,
214      MAP4(3,2,1,0),
215      MAP4(3,2,1,0)
216   },
217
218   {
219      IDX_RG,
220      MAP4(0, 1, ZERO, ONE),
221      MAP2(0, 1)
222   },
223};
224
225
226
227/**
228 * Convert a GL image format enum to an IDX_* value (see above).
229 */
230static int
231get_map_idx(GLenum value)
232{
233   switch (value) {
234   case GL_LUMINANCE: return IDX_LUMINANCE;
235   case GL_ALPHA: return IDX_ALPHA;
236   case GL_INTENSITY: return IDX_INTENSITY;
237   case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA;
238   case GL_RGB: return IDX_RGB;
239   case GL_RGBA: return IDX_RGBA;
240   case GL_RED: return IDX_RED;
241   case GL_GREEN: return IDX_GREEN;
242   case GL_BLUE: return IDX_BLUE;
243   case GL_BGR: return IDX_BGR;
244   case GL_BGRA: return IDX_BGRA;
245   case GL_ABGR_EXT: return IDX_ABGR;
246   case GL_RG: return IDX_RG;
247   default:
248      _mesa_problem(NULL, "Unexpected inFormat");
249      return 0;
250   }
251}
252
253
254/**
255 * When promoting texture formats (see below) we need to compute the
256 * mapping of dest components back to source components.
257 * This function does that.
258 * \param inFormat  the incoming format of the texture
259 * \param outFormat  the final texture format
260 * \return map[6]  a full 6-component map
261 */
262static void
263compute_component_mapping(GLenum inFormat, GLenum outFormat,
264			  GLubyte *map)
265{
266   const int inFmt = get_map_idx(inFormat);
267   const int outFmt = get_map_idx(outFormat);
268   const GLubyte *in2rgba = mappings[inFmt].to_rgba;
269   const GLubyte *rgba2out = mappings[outFmt].from_rgba;
270   int i;
271
272   for (i = 0; i < 4; i++)
273      map[i] = in2rgba[rgba2out[i]];
274
275   map[ZERO] = ZERO;
276   map[ONE] = ONE;
277
278#if 0
279   printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
280	  inFormat, _mesa_lookup_enum_by_nr(inFormat),
281	  outFormat, _mesa_lookup_enum_by_nr(outFormat),
282	  map[0],
283	  map[1],
284	  map[2],
285	  map[3],
286	  map[4],
287	  map[5]);
288#endif
289}
290
291
292/**
293 * Make a temporary (color) texture image with GLfloat components.
294 * Apply all needed pixel unpacking and pixel transfer operations.
295 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
296 * Suppose the user specifies GL_LUMINANCE as the internal texture format
297 * but the graphics hardware doesn't support luminance textures.  So, we might
298 * use an RGB hardware format instead.
299 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
300 *
301 * \param ctx  the rendering context
302 * \param dims  image dimensions: 1, 2 or 3
303 * \param logicalBaseFormat  basic texture derived from the user's
304 *    internal texture format value
305 * \param textureBaseFormat  the actual basic format of the texture
306 * \param srcWidth  source image width
307 * \param srcHeight  source image height
308 * \param srcDepth  source image depth
309 * \param srcFormat  source image format
310 * \param srcType  source image type
311 * \param srcAddr  source image address
312 * \param srcPacking  source image pixel packing
313 * \return resulting image with format = textureBaseFormat and type = GLfloat.
314 */
315GLfloat *
316_mesa_make_temp_float_image(struct gl_context *ctx, GLuint dims,
317			    GLenum logicalBaseFormat,
318			    GLenum textureBaseFormat,
319			    GLint srcWidth, GLint srcHeight, GLint srcDepth,
320			    GLenum srcFormat, GLenum srcType,
321			    const GLvoid *srcAddr,
322			    const struct gl_pixelstore_attrib *srcPacking,
323			    GLbitfield transferOps)
324{
325   GLfloat *tempImage;
326   const GLint components = _mesa_components_in_format(logicalBaseFormat);
327   const GLint srcStride =
328      _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
329   GLfloat *dst;
330   GLint img, row;
331
332   ASSERT(dims >= 1 && dims <= 3);
333
334   ASSERT(logicalBaseFormat == GL_RGBA ||
335          logicalBaseFormat == GL_RGB ||
336          logicalBaseFormat == GL_RG ||
337          logicalBaseFormat == GL_RED ||
338          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
339          logicalBaseFormat == GL_LUMINANCE ||
340          logicalBaseFormat == GL_ALPHA ||
341          logicalBaseFormat == GL_INTENSITY ||
342          logicalBaseFormat == GL_COLOR_INDEX ||
343          logicalBaseFormat == GL_DEPTH_COMPONENT);
344
345   ASSERT(textureBaseFormat == GL_RGBA ||
346          textureBaseFormat == GL_RGB ||
347          textureBaseFormat == GL_RG ||
348          textureBaseFormat == GL_RED ||
349          textureBaseFormat == GL_LUMINANCE_ALPHA ||
350          textureBaseFormat == GL_LUMINANCE ||
351          textureBaseFormat == GL_ALPHA ||
352          textureBaseFormat == GL_INTENSITY ||
353          textureBaseFormat == GL_COLOR_INDEX ||
354          textureBaseFormat == GL_DEPTH_COMPONENT);
355
356   tempImage = (GLfloat *) malloc(srcWidth * srcHeight * srcDepth
357				  * components * sizeof(GLfloat));
358   if (!tempImage)
359      return NULL;
360
361   dst = tempImage;
362   for (img = 0; img < srcDepth; img++) {
363      const GLubyte *src
364	 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
365						 srcWidth, srcHeight,
366						 srcFormat, srcType,
367						 img, 0, 0);
368      for (row = 0; row < srcHeight; row++) {
369	 _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
370				       dst, srcFormat, srcType, src,
371				       srcPacking, transferOps);
372	 dst += srcWidth * components;
373	 src += srcStride;
374      }
375   }
376
377   if (logicalBaseFormat != textureBaseFormat) {
378      /* more work */
379      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
380      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
381      GLfloat *newImage;
382      GLint i, n;
383      GLubyte map[6];
384
385      /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
386      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
387             textureBaseFormat == GL_LUMINANCE_ALPHA);
388
389      /* The actual texture format should have at least as many components
390       * as the logical texture format.
391       */
392      ASSERT(texComponents >= logComponents);
393
394      newImage = (GLfloat *) malloc(srcWidth * srcHeight * srcDepth
395                                          * texComponents * sizeof(GLfloat));
396      if (!newImage) {
397         free(tempImage);
398         return NULL;
399      }
400
401      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
402
403      n = srcWidth * srcHeight * srcDepth;
404      for (i = 0; i < n; i++) {
405         GLint k;
406         for (k = 0; k < texComponents; k++) {
407            GLint j = map[k];
408            if (j == ZERO)
409               newImage[i * texComponents + k] = 0.0F;
410            else if (j == ONE)
411               newImage[i * texComponents + k] = 1.0F;
412            else
413               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
414         }
415      }
416
417      free(tempImage);
418      tempImage = newImage;
419   }
420
421   return tempImage;
422}
423
424
425/**
426 * Make temporary image with uint pixel values.  Used for unsigned
427 * integer-valued textures.
428 */
429static GLuint *
430make_temp_uint_image(struct gl_context *ctx, GLuint dims,
431                     GLenum logicalBaseFormat,
432                     GLenum textureBaseFormat,
433                     GLint srcWidth, GLint srcHeight, GLint srcDepth,
434                     GLenum srcFormat, GLenum srcType,
435                     const GLvoid *srcAddr,
436                     const struct gl_pixelstore_attrib *srcPacking)
437{
438   GLuint *tempImage;
439   const GLint components = _mesa_components_in_format(logicalBaseFormat);
440   const GLint srcStride =
441      _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
442   GLuint *dst;
443   GLint img, row;
444
445   ASSERT(dims >= 1 && dims <= 3);
446
447   ASSERT(logicalBaseFormat == GL_RGBA ||
448          logicalBaseFormat == GL_RGB ||
449          logicalBaseFormat == GL_RG ||
450          logicalBaseFormat == GL_RED ||
451          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
452          logicalBaseFormat == GL_LUMINANCE ||
453          logicalBaseFormat == GL_INTENSITY ||
454          logicalBaseFormat == GL_ALPHA);
455
456   ASSERT(textureBaseFormat == GL_RGBA ||
457          textureBaseFormat == GL_RGB ||
458          textureBaseFormat == GL_RG ||
459          textureBaseFormat == GL_RED ||
460          textureBaseFormat == GL_LUMINANCE_ALPHA ||
461          textureBaseFormat == GL_LUMINANCE ||
462          textureBaseFormat == GL_ALPHA);
463
464   tempImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth
465                                 * components * sizeof(GLuint));
466   if (!tempImage)
467      return NULL;
468
469   dst = tempImage;
470   for (img = 0; img < srcDepth; img++) {
471      const GLubyte *src
472	 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
473						 srcWidth, srcHeight,
474						 srcFormat, srcType,
475						 img, 0, 0);
476      for (row = 0; row < srcHeight; row++) {
477	 _mesa_unpack_color_span_uint(ctx, srcWidth, logicalBaseFormat,
478                                      dst, srcFormat, srcType, src,
479                                      srcPacking);
480	 dst += srcWidth * components;
481	 src += srcStride;
482      }
483   }
484
485   if (logicalBaseFormat != textureBaseFormat) {
486      /* more work */
487      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
488      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
489      GLuint *newImage;
490      GLint i, n;
491      GLubyte map[6];
492
493      /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
494      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
495             textureBaseFormat == GL_LUMINANCE_ALPHA);
496
497      /* The actual texture format should have at least as many components
498       * as the logical texture format.
499       */
500      ASSERT(texComponents >= logComponents);
501
502      newImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth
503                                   * texComponents * sizeof(GLuint));
504      if (!newImage) {
505         free(tempImage);
506         return NULL;
507      }
508
509      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
510
511      n = srcWidth * srcHeight * srcDepth;
512      for (i = 0; i < n; i++) {
513         GLint k;
514         for (k = 0; k < texComponents; k++) {
515            GLint j = map[k];
516            if (j == ZERO)
517               newImage[i * texComponents + k] = 0.0F;
518            else if (j == ONE)
519               newImage[i * texComponents + k] = 1.0F;
520            else
521               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
522         }
523      }
524
525      free(tempImage);
526      tempImage = newImage;
527   }
528
529   return tempImage;
530}
531
532
533
534/**
535 * Make a temporary (color) texture image with GLchan components.
536 * Apply all needed pixel unpacking and pixel transfer operations.
537 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
538 * Suppose the user specifies GL_LUMINANCE as the internal texture format
539 * but the graphics hardware doesn't support luminance textures.  So, we might
540 * use an RGB hardware format instead.
541 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
542 *
543 * \param ctx  the rendering context
544 * \param dims  image dimensions: 1, 2 or 3
545 * \param logicalBaseFormat  basic texture derived from the user's
546 *    internal texture format value
547 * \param textureBaseFormat  the actual basic format of the texture
548 * \param srcWidth  source image width
549 * \param srcHeight  source image height
550 * \param srcDepth  source image depth
551 * \param srcFormat  source image format
552 * \param srcType  source image type
553 * \param srcAddr  source image address
554 * \param srcPacking  source image pixel packing
555 * \return resulting image with format = textureBaseFormat and type = GLchan.
556 */
557GLchan *
558_mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
559                           GLenum logicalBaseFormat,
560                           GLenum textureBaseFormat,
561                           GLint srcWidth, GLint srcHeight, GLint srcDepth,
562                           GLenum srcFormat, GLenum srcType,
563                           const GLvoid *srcAddr,
564                           const struct gl_pixelstore_attrib *srcPacking)
565{
566   GLuint transferOps = ctx->_ImageTransferState;
567   const GLint components = _mesa_components_in_format(logicalBaseFormat);
568   GLint img, row;
569   GLchan *tempImage, *dst;
570
571   ASSERT(dims >= 1 && dims <= 3);
572
573   ASSERT(logicalBaseFormat == GL_RGBA ||
574          logicalBaseFormat == GL_RGB ||
575          logicalBaseFormat == GL_RG ||
576          logicalBaseFormat == GL_RED ||
577          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
578          logicalBaseFormat == GL_LUMINANCE ||
579          logicalBaseFormat == GL_ALPHA ||
580          logicalBaseFormat == GL_INTENSITY);
581
582   ASSERT(textureBaseFormat == GL_RGBA ||
583          textureBaseFormat == GL_RGB ||
584          textureBaseFormat == GL_RG ||
585          textureBaseFormat == GL_RED ||
586          textureBaseFormat == GL_LUMINANCE_ALPHA ||
587          textureBaseFormat == GL_LUMINANCE ||
588          textureBaseFormat == GL_ALPHA ||
589          textureBaseFormat == GL_INTENSITY);
590
591   /* unpack and transfer the source image */
592   tempImage = (GLchan *) malloc(srcWidth * srcHeight * srcDepth
593                                       * components * sizeof(GLchan));
594   if (!tempImage) {
595      return NULL;
596   }
597
598   dst = tempImage;
599   for (img = 0; img < srcDepth; img++) {
600      const GLint srcStride =
601         _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
602      const GLubyte *src =
603         (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
604                                               srcWidth, srcHeight,
605                                               srcFormat, srcType,
606                                               img, 0, 0);
607      for (row = 0; row < srcHeight; row++) {
608         _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
609                                      srcFormat, srcType, src, srcPacking,
610                                      transferOps);
611         dst += srcWidth * components;
612         src += srcStride;
613      }
614   }
615
616   if (logicalBaseFormat != textureBaseFormat) {
617      /* one more conversion step */
618      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
619      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
620      GLchan *newImage;
621      GLint i, n;
622      GLubyte map[6];
623
624      /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
625      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
626             textureBaseFormat == GL_LUMINANCE_ALPHA);
627
628      /* The actual texture format should have at least as many components
629       * as the logical texture format.
630       */
631      ASSERT(texComponents >= logComponents);
632
633      newImage = (GLchan *) malloc(srcWidth * srcHeight * srcDepth
634                                         * texComponents * sizeof(GLchan));
635      if (!newImage) {
636         free(tempImage);
637         return NULL;
638      }
639
640      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
641
642      n = srcWidth * srcHeight * srcDepth;
643      for (i = 0; i < n; i++) {
644         GLint k;
645         for (k = 0; k < texComponents; k++) {
646            GLint j = map[k];
647            if (j == ZERO)
648               newImage[i * texComponents + k] = 0;
649            else if (j == ONE)
650               newImage[i * texComponents + k] = CHAN_MAX;
651            else
652               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
653         }
654      }
655
656      free(tempImage);
657      tempImage = newImage;
658   }
659
660   return tempImage;
661}
662
663
664/**
665 * Copy GLubyte pixels from <src> to <dst> with swizzling.
666 * \param dst  destination pixels
667 * \param dstComponents  number of color components in destination pixels
668 * \param src  source pixels
669 * \param srcComponents  number of color components in source pixels
670 * \param map  the swizzle mapping.  map[X] says where to find the X component
671 *             in the source image's pixels.  For example, if the source image
672 *             is GL_BGRA and X = red, map[0] yields 2.
673 * \param count  number of pixels to copy/swizzle.
674 */
675static void
676swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
677             GLuint srcComponents, const GLubyte *map, GLuint count)
678{
679#define SWZ_CPY(dst, src, count, dstComps, srcComps) \
680   do {                                              \
681      GLuint i;                                      \
682      for (i = 0; i < count; i++) {                  \
683         GLuint j;                                   \
684         if (srcComps == 4) {                        \
685            COPY_4UBV(tmp, src);                     \
686         }                                           \
687         else {                                      \
688            for (j = 0; j < srcComps; j++) {         \
689               tmp[j] = src[j];                      \
690            }                                        \
691         }                                           \
692         src += srcComps;                            \
693         for (j = 0; j < dstComps; j++) {            \
694            dst[j] = tmp[map[j]];                    \
695         }                                           \
696         dst += dstComps;                            \
697      }                                              \
698   } while (0)
699
700   GLubyte tmp[6];
701
702   tmp[ZERO] = 0x0;
703   tmp[ONE] = 0xff;
704
705   ASSERT(srcComponents <= 4);
706   ASSERT(dstComponents <= 4);
707
708   switch (dstComponents) {
709   case 4:
710      switch (srcComponents) {
711      case 4:
712         SWZ_CPY(dst, src, count, 4, 4);
713         break;
714      case 3:
715         SWZ_CPY(dst, src, count, 4, 3);
716         break;
717      case 2:
718         SWZ_CPY(dst, src, count, 4, 2);
719         break;
720      case 1:
721         SWZ_CPY(dst, src, count, 4, 1);
722         break;
723      default:
724         ;
725      }
726      break;
727   case 3:
728      switch (srcComponents) {
729      case 4:
730         SWZ_CPY(dst, src, count, 3, 4);
731         break;
732      case 3:
733         SWZ_CPY(dst, src, count, 3, 3);
734         break;
735      case 2:
736         SWZ_CPY(dst, src, count, 3, 2);
737         break;
738      case 1:
739         SWZ_CPY(dst, src, count, 3, 1);
740         break;
741      default:
742         ;
743      }
744      break;
745   case 2:
746      switch (srcComponents) {
747      case 4:
748         SWZ_CPY(dst, src, count, 2, 4);
749         break;
750      case 3:
751         SWZ_CPY(dst, src, count, 2, 3);
752         break;
753      case 2:
754         SWZ_CPY(dst, src, count, 2, 2);
755         break;
756      case 1:
757         SWZ_CPY(dst, src, count, 2, 1);
758         break;
759      default:
760         ;
761      }
762      break;
763   case 1:
764      switch (srcComponents) {
765      case 4:
766         SWZ_CPY(dst, src, count, 1, 4);
767         break;
768      case 3:
769         SWZ_CPY(dst, src, count, 1, 3);
770         break;
771      case 2:
772         SWZ_CPY(dst, src, count, 1, 2);
773         break;
774      case 1:
775         SWZ_CPY(dst, src, count, 1, 1);
776         break;
777      default:
778         ;
779      }
780      break;
781   default:
782      ;
783   }
784#undef SWZ_CPY
785}
786
787
788
789static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE };
790static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE };
791
792
793/**
794 * For 1-byte/pixel formats (or 8_8_8_8 packed formats), return a
795 * mapping array depending on endianness.
796 */
797static const GLubyte *
798type_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
814/**
815 * For 1-byte/pixel formats (or 8_8_8_8 packed formats), return a
816 * mapping array depending on pixelstore byte swapping state.
817 */
818static const GLubyte *
819byteswap_mapping( GLboolean swapBytes,
820		  GLenum srcType )
821{
822   if (!swapBytes)
823      return map_identity;
824
825   switch (srcType) {
826   case GL_BYTE:
827   case GL_UNSIGNED_BYTE:
828      return map_identity;
829   case GL_UNSIGNED_INT_8_8_8_8:
830   case GL_UNSIGNED_INT_8_8_8_8_REV:
831      return map_3210;
832   default:
833      return NULL;
834   }
835}
836
837
838
839/**
840 * Transfer a GLubyte texture image with component swizzling.
841 */
842static void
843_mesa_swizzle_ubyte_image(struct gl_context *ctx,
844			  GLuint dimensions,
845			  GLenum srcFormat,
846			  GLenum srcType,
847
848			  GLenum baseInternalFormat,
849
850			  const GLubyte *rgba2dst,
851			  GLuint dstComponents,
852
853			  GLvoid *dstAddr,
854			  GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
855			  GLint dstRowStride,
856                          const GLuint *dstImageOffsets,
857
858			  GLint srcWidth, GLint srcHeight, GLint srcDepth,
859			  const GLvoid *srcAddr,
860			  const struct gl_pixelstore_attrib *srcPacking )
861{
862   GLint srcComponents = _mesa_components_in_format(srcFormat);
863   const GLubyte *srctype2ubyte, *swap;
864   GLubyte map[4], src2base[6], base2rgba[6];
865   GLint i;
866   const GLint srcRowStride =
867      _mesa_image_row_stride(srcPacking, srcWidth,
868                             srcFormat, GL_UNSIGNED_BYTE);
869   const GLint srcImageStride
870      = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat,
871                                 GL_UNSIGNED_BYTE);
872   const GLubyte *srcImage
873      = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr,
874                                              srcWidth, srcHeight, srcFormat,
875                                              GL_UNSIGNED_BYTE, 0, 0, 0);
876
877   (void) ctx;
878
879   /* Translate from src->baseInternal->GL_RGBA->dst.  This will
880    * correctly deal with RGBA->RGB->RGBA conversions where the final
881    * A value must be 0xff regardless of the incoming alpha values.
882    */
883   compute_component_mapping(srcFormat, baseInternalFormat, src2base);
884   compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba);
885   swap = byteswap_mapping(srcPacking->SwapBytes, srcType);
886   srctype2ubyte = type_mapping(srcType);
887
888
889   for (i = 0; i < 4; i++)
890      map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]];
891
892/*    printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]);  */
893
894   if (srcComponents == dstComponents &&
895       srcRowStride == dstRowStride &&
896       srcRowStride == srcWidth * srcComponents &&
897       dimensions < 3) {
898      /* 1 and 2D images only */
899      GLubyte *dstImage = (GLubyte *) dstAddr
900         + dstYoffset * dstRowStride
901         + dstXoffset * dstComponents;
902      swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
903		   srcWidth * srcHeight);
904   }
905   else {
906      GLint img, row;
907      for (img = 0; img < srcDepth; img++) {
908         const GLubyte *srcRow = srcImage;
909         GLubyte *dstRow = (GLubyte *) dstAddr
910            + dstImageOffsets[dstZoffset + img] * dstComponents
911            + dstYoffset * dstRowStride
912            + dstXoffset * dstComponents;
913         for (row = 0; row < srcHeight; row++) {
914	    swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
915            dstRow += dstRowStride;
916            srcRow += srcRowStride;
917         }
918         srcImage += srcImageStride;
919      }
920   }
921}
922
923
924/**
925 * Teximage storage routine for when a simple memcpy will do.
926 * No pixel transfer operations or special texel encodings allowed.
927 * 1D, 2D and 3D images supported.
928 */
929static void
930memcpy_texture(struct gl_context *ctx,
931	       GLuint dimensions,
932               gl_format dstFormat,
933               GLvoid *dstAddr,
934               GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
935               GLint dstRowStride,
936               const GLuint *dstImageOffsets,
937               GLint srcWidth, GLint srcHeight, GLint srcDepth,
938               GLenum srcFormat, GLenum srcType,
939               const GLvoid *srcAddr,
940               const struct gl_pixelstore_attrib *srcPacking)
941{
942   const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
943                                                     srcFormat, srcType);
944   const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
945                                      srcWidth, srcHeight, srcFormat, srcType);
946   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
947        srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
948   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
949   const GLint bytesPerRow = srcWidth * texelBytes;
950
951#if 0
952   /* XXX update/re-enable for dstImageOffsets array */
953   const GLint bytesPerImage = srcHeight * bytesPerRow;
954   const GLint bytesPerTexture = srcDepth * bytesPerImage;
955   GLubyte *dstImage = (GLubyte *) dstAddr
956                     + dstZoffset * dstImageStride
957                     + dstYoffset * dstRowStride
958                     + dstXoffset * texelBytes;
959
960   if (dstRowStride == srcRowStride &&
961       dstRowStride == bytesPerRow &&
962       ((dstImageStride == srcImageStride &&
963         dstImageStride == bytesPerImage) ||
964        (srcDepth == 1))) {
965      /* one big memcpy */
966      ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
967   }
968   else
969   {
970      GLint img, row;
971      for (img = 0; img < srcDepth; img++) {
972         const GLubyte *srcRow = srcImage;
973         GLubyte *dstRow = dstImage;
974         for (row = 0; row < srcHeight; row++) {
975            ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
976            dstRow += dstRowStride;
977            srcRow += srcRowStride;
978         }
979         srcImage += srcImageStride;
980         dstImage += dstImageStride;
981      }
982   }
983#endif
984
985   GLint img, row;
986   for (img = 0; img < srcDepth; img++) {
987      const GLubyte *srcRow = srcImage;
988      GLubyte *dstRow = (GLubyte *) dstAddr
989         + dstImageOffsets[dstZoffset + img] * texelBytes
990         + dstYoffset * dstRowStride
991         + dstXoffset * texelBytes;
992      for (row = 0; row < srcHeight; row++) {
993         ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
994         dstRow += dstRowStride;
995         srcRow += srcRowStride;
996      }
997      srcImage += srcImageStride;
998   }
999}
1000
1001
1002
1003/**
1004 * Store a 32-bit integer depth component texture image.
1005 */
1006static GLboolean
1007_mesa_texstore_z32(TEXSTORE_PARAMS)
1008{
1009   const GLuint depthScale = 0xffffffff;
1010   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1011   (void) dims;
1012   ASSERT(dstFormat == MESA_FORMAT_Z32);
1013   ASSERT(texelBytes == sizeof(GLuint));
1014
1015   if (ctx->Pixel.DepthScale == 1.0f &&
1016       ctx->Pixel.DepthBias == 0.0f &&
1017       !srcPacking->SwapBytes &&
1018       baseInternalFormat == GL_DEPTH_COMPONENT &&
1019       srcFormat == GL_DEPTH_COMPONENT &&
1020       srcType == GL_UNSIGNED_INT) {
1021      /* simple memcpy path */
1022      memcpy_texture(ctx, dims,
1023                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1024                     dstRowStride,
1025                     dstImageOffsets,
1026                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1027                     srcAddr, srcPacking);
1028   }
1029   else {
1030      /* general path */
1031      GLint img, row;
1032      for (img = 0; img < srcDepth; img++) {
1033         GLubyte *dstRow = (GLubyte *) dstAddr
1034            + dstImageOffsets[dstZoffset + img] * texelBytes
1035            + dstYoffset * dstRowStride
1036            + dstXoffset * texelBytes;
1037         for (row = 0; row < srcHeight; row++) {
1038            const GLvoid *src = _mesa_image_address(dims, srcPacking,
1039                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1040            _mesa_unpack_depth_span(ctx, srcWidth,
1041                                    GL_UNSIGNED_INT, (GLuint *) dstRow,
1042                                    depthScale, srcType, src, srcPacking);
1043            dstRow += dstRowStride;
1044         }
1045      }
1046   }
1047   return GL_TRUE;
1048}
1049
1050
1051/**
1052 * Store a 24-bit integer depth component texture image.
1053 */
1054static GLboolean
1055_mesa_texstore_x8_z24(TEXSTORE_PARAMS)
1056{
1057   const GLuint depthScale = 0xffffff;
1058   const GLuint texelBytes = 4;
1059
1060   (void) dims;
1061   ASSERT(dstFormat == MESA_FORMAT_X8_Z24);
1062
1063   {
1064      /* general path */
1065      GLint img, row;
1066      for (img = 0; img < srcDepth; img++) {
1067         GLubyte *dstRow = (GLubyte *) dstAddr
1068            + dstImageOffsets[dstZoffset + img] * texelBytes
1069            + dstYoffset * dstRowStride
1070            + dstXoffset * texelBytes;
1071         for (row = 0; row < srcHeight; row++) {
1072            const GLvoid *src = _mesa_image_address(dims, srcPacking,
1073                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1074            _mesa_unpack_depth_span(ctx, srcWidth,
1075                                    GL_UNSIGNED_INT, (GLuint *) dstRow,
1076                                    depthScale, srcType, src, srcPacking);
1077            dstRow += dstRowStride;
1078         }
1079      }
1080   }
1081   return GL_TRUE;
1082}
1083
1084
1085/**
1086 * Store a 24-bit integer depth component texture image.
1087 */
1088static GLboolean
1089_mesa_texstore_z24_x8(TEXSTORE_PARAMS)
1090{
1091   const GLuint depthScale = 0xffffff;
1092   const GLuint texelBytes = 4;
1093
1094   (void) dims;
1095   ASSERT(dstFormat == MESA_FORMAT_Z24_X8);
1096
1097   {
1098      /* general path */
1099      GLint img, row;
1100      for (img = 0; img < srcDepth; img++) {
1101         GLubyte *dstRow = (GLubyte *) dstAddr
1102            + dstImageOffsets[dstZoffset + img] * texelBytes
1103            + dstYoffset * dstRowStride
1104            + dstXoffset * texelBytes;
1105         for (row = 0; row < srcHeight; row++) {
1106            const GLvoid *src = _mesa_image_address(dims, srcPacking,
1107                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1108            GLuint *dst = (GLuint *) dstRow;
1109            GLint i;
1110            _mesa_unpack_depth_span(ctx, srcWidth,
1111                                    GL_UNSIGNED_INT, dst,
1112                                    depthScale, srcType, src, srcPacking);
1113            for (i = 0; i < srcWidth; i++)
1114               dst[i] <<= 8;
1115            dstRow += dstRowStride;
1116         }
1117      }
1118   }
1119   return GL_TRUE;
1120}
1121
1122
1123/**
1124 * Store a 16-bit integer depth component texture image.
1125 */
1126static GLboolean
1127_mesa_texstore_z16(TEXSTORE_PARAMS)
1128{
1129   const GLuint depthScale = 0xffff;
1130   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1131   (void) dims;
1132   ASSERT(dstFormat == MESA_FORMAT_Z16);
1133   ASSERT(texelBytes == sizeof(GLushort));
1134
1135   if (ctx->Pixel.DepthScale == 1.0f &&
1136       ctx->Pixel.DepthBias == 0.0f &&
1137       !srcPacking->SwapBytes &&
1138       baseInternalFormat == GL_DEPTH_COMPONENT &&
1139       srcFormat == GL_DEPTH_COMPONENT &&
1140       srcType == GL_UNSIGNED_SHORT) {
1141      /* simple memcpy path */
1142      memcpy_texture(ctx, dims,
1143                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1144                     dstRowStride,
1145                     dstImageOffsets,
1146                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1147                     srcAddr, srcPacking);
1148   }
1149   else {
1150      /* general path */
1151      GLint img, row;
1152      for (img = 0; img < srcDepth; img++) {
1153         GLubyte *dstRow = (GLubyte *) dstAddr
1154            + dstImageOffsets[dstZoffset + img] * texelBytes
1155            + dstYoffset * dstRowStride
1156            + dstXoffset * texelBytes;
1157         for (row = 0; row < srcHeight; row++) {
1158            const GLvoid *src = _mesa_image_address(dims, srcPacking,
1159                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1160            GLushort *dst16 = (GLushort *) dstRow;
1161            _mesa_unpack_depth_span(ctx, srcWidth,
1162                                    GL_UNSIGNED_SHORT, dst16, depthScale,
1163                                    srcType, src, srcPacking);
1164            dstRow += dstRowStride;
1165         }
1166      }
1167   }
1168   return GL_TRUE;
1169}
1170
1171
1172/**
1173 * Store an rgb565 or rgb565_rev texture image.
1174 */
1175static GLboolean
1176_mesa_texstore_rgb565(TEXSTORE_PARAMS)
1177{
1178   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1179   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1180
1181   ASSERT(dstFormat == MESA_FORMAT_RGB565 ||
1182          dstFormat == MESA_FORMAT_RGB565_REV);
1183   ASSERT(texelBytes == 2);
1184
1185   if (!ctx->_ImageTransferState &&
1186       !srcPacking->SwapBytes &&
1187       dstFormat == MESA_FORMAT_RGB565 &&
1188       baseInternalFormat == GL_RGB &&
1189       srcFormat == GL_RGB &&
1190       srcType == GL_UNSIGNED_SHORT_5_6_5) {
1191      /* simple memcpy path */
1192      memcpy_texture(ctx, dims,
1193                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1194                     dstRowStride,
1195                     dstImageOffsets,
1196                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1197                     srcAddr, srcPacking);
1198   }
1199   else if (!ctx->_ImageTransferState &&
1200            !srcPacking->SwapBytes &&
1201            baseInternalFormat == GL_RGB &&
1202            srcFormat == GL_RGB &&
1203            srcType == GL_UNSIGNED_BYTE &&
1204            dims == 2) {
1205      /* do optimized tex store */
1206      const GLint srcRowStride =
1207         _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
1208      const GLubyte *src = (const GLubyte *)
1209         _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
1210                             srcFormat, srcType, 0, 0, 0);
1211      GLubyte *dst = (GLubyte *) dstAddr
1212                   + dstYoffset * dstRowStride
1213                   + dstXoffset * texelBytes;
1214      GLint row, col;
1215      for (row = 0; row < srcHeight; row++) {
1216         const GLubyte *srcUB = (const GLubyte *) src;
1217         GLushort *dstUS = (GLushort *) dst;
1218         /* check for byteswapped format */
1219         if (dstFormat == MESA_FORMAT_RGB565) {
1220            for (col = 0; col < srcWidth; col++) {
1221               dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
1222               srcUB += 3;
1223            }
1224         }
1225         else {
1226            for (col = 0; col < srcWidth; col++) {
1227               dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
1228               srcUB += 3;
1229            }
1230         }
1231         dst += dstRowStride;
1232         src += srcRowStride;
1233      }
1234   }
1235   else {
1236      /* general path */
1237      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1238                                                 baseInternalFormat,
1239                                                 baseFormat,
1240                                                 srcWidth, srcHeight, srcDepth,
1241                                                 srcFormat, srcType, srcAddr,
1242                                                 srcPacking);
1243      const GLchan *src = tempImage;
1244      GLint img, row, col;
1245      if (!tempImage)
1246         return GL_FALSE;
1247      for (img = 0; img < srcDepth; img++) {
1248         GLubyte *dstRow = (GLubyte *) dstAddr
1249            + dstImageOffsets[dstZoffset + img] * texelBytes
1250            + dstYoffset * dstRowStride
1251            + dstXoffset * texelBytes;
1252         for (row = 0; row < srcHeight; row++) {
1253            GLushort *dstUS = (GLushort *) dstRow;
1254            /* check for byteswapped format */
1255            if (dstFormat == MESA_FORMAT_RGB565) {
1256               for (col = 0; col < srcWidth; col++) {
1257                  dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
1258                                               CHAN_TO_UBYTE(src[GCOMP]),
1259                                               CHAN_TO_UBYTE(src[BCOMP]) );
1260                  src += 3;
1261               }
1262            }
1263            else {
1264               for (col = 0; col < srcWidth; col++) {
1265                  dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
1266                                                   CHAN_TO_UBYTE(src[GCOMP]),
1267                                                   CHAN_TO_UBYTE(src[BCOMP]) );
1268                  src += 3;
1269               }
1270            }
1271            dstRow += dstRowStride;
1272         }
1273      }
1274      free((void *) tempImage);
1275   }
1276   return GL_TRUE;
1277}
1278
1279
1280/**
1281 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
1282 */
1283static GLboolean
1284_mesa_texstore_rgba8888(TEXSTORE_PARAMS)
1285{
1286   const GLboolean littleEndian = _mesa_little_endian();
1287   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1288   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1289
1290   ASSERT(dstFormat == MESA_FORMAT_RGBA8888 ||
1291          dstFormat == MESA_FORMAT_RGBA8888_REV);
1292   ASSERT(texelBytes == 4);
1293
1294   if (!ctx->_ImageTransferState &&
1295       !srcPacking->SwapBytes &&
1296       dstFormat == MESA_FORMAT_RGBA8888 &&
1297       baseInternalFormat == GL_RGBA &&
1298      ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1299       (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1300       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
1301       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
1302       /* simple memcpy path */
1303      memcpy_texture(ctx, dims,
1304                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1305                     dstRowStride,
1306                     dstImageOffsets,
1307                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1308                     srcAddr, srcPacking);
1309   }
1310   else if (!ctx->_ImageTransferState &&
1311       !srcPacking->SwapBytes &&
1312       dstFormat == MESA_FORMAT_RGBA8888_REV &&
1313       baseInternalFormat == GL_RGBA &&
1314      ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
1315       (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1316       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1317       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
1318      /* simple memcpy path */
1319      memcpy_texture(ctx, dims,
1320                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1321                     dstRowStride,
1322                     dstImageOffsets,
1323                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1324                     srcAddr, srcPacking);
1325   }
1326   else if (!ctx->_ImageTransferState &&
1327	    (srcType == GL_UNSIGNED_BYTE ||
1328	     srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1329	     srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1330	    can_swizzle(baseInternalFormat) &&
1331	    can_swizzle(srcFormat)) {
1332
1333      GLubyte dstmap[4];
1334
1335      /* dstmap - how to swizzle from RGBA to dst format:
1336       */
1337      if ((littleEndian && dstFormat == MESA_FORMAT_RGBA8888) ||
1338	  (!littleEndian && dstFormat == MESA_FORMAT_RGBA8888_REV)) {
1339	 dstmap[3] = 0;
1340	 dstmap[2] = 1;
1341	 dstmap[1] = 2;
1342	 dstmap[0] = 3;
1343      }
1344      else {
1345	 dstmap[3] = 3;
1346	 dstmap[2] = 2;
1347	 dstmap[1] = 1;
1348	 dstmap[0] = 0;
1349      }
1350
1351      _mesa_swizzle_ubyte_image(ctx, dims,
1352				srcFormat,
1353				srcType,
1354				baseInternalFormat,
1355				dstmap, 4,
1356				dstAddr, dstXoffset, dstYoffset, dstZoffset,
1357				dstRowStride, dstImageOffsets,
1358				srcWidth, srcHeight, srcDepth, srcAddr,
1359				srcPacking);
1360   }
1361   else {
1362      /* general path */
1363      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1364                                                 baseInternalFormat,
1365                                                 baseFormat,
1366                                                 srcWidth, srcHeight, srcDepth,
1367                                                 srcFormat, srcType, srcAddr,
1368                                                 srcPacking);
1369      const GLchan *src = tempImage;
1370      GLint img, row, col;
1371      if (!tempImage)
1372         return GL_FALSE;
1373      for (img = 0; img < srcDepth; img++) {
1374         GLubyte *dstRow = (GLubyte *) dstAddr
1375            + dstImageOffsets[dstZoffset + img] * texelBytes
1376            + dstYoffset * dstRowStride
1377            + dstXoffset * texelBytes;
1378         for (row = 0; row < srcHeight; row++) {
1379            GLuint *dstUI = (GLuint *) dstRow;
1380            if (dstFormat == MESA_FORMAT_RGBA8888) {
1381               for (col = 0; col < srcWidth; col++) {
1382                  dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
1383                                                CHAN_TO_UBYTE(src[GCOMP]),
1384                                                CHAN_TO_UBYTE(src[BCOMP]),
1385                                                CHAN_TO_UBYTE(src[ACOMP]) );
1386                  src += 4;
1387               }
1388            }
1389            else {
1390               for (col = 0; col < srcWidth; col++) {
1391                  dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
1392                                                    CHAN_TO_UBYTE(src[GCOMP]),
1393                                                    CHAN_TO_UBYTE(src[BCOMP]),
1394                                                    CHAN_TO_UBYTE(src[ACOMP]) );
1395                  src += 4;
1396               }
1397            }
1398            dstRow += dstRowStride;
1399         }
1400      }
1401      free((void *) tempImage);
1402   }
1403   return GL_TRUE;
1404}
1405
1406
1407static GLboolean
1408_mesa_texstore_argb8888(TEXSTORE_PARAMS)
1409{
1410   const GLboolean littleEndian = _mesa_little_endian();
1411   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1412   const GLenum baseFormat = GL_RGBA;
1413
1414   ASSERT(dstFormat == MESA_FORMAT_ARGB8888 ||
1415          dstFormat == MESA_FORMAT_ARGB8888_REV ||
1416          dstFormat == MESA_FORMAT_XRGB8888 ||
1417          dstFormat == MESA_FORMAT_XRGB8888_REV );
1418   ASSERT(texelBytes == 4);
1419
1420   if (!ctx->_ImageTransferState &&
1421       !srcPacking->SwapBytes &&
1422       (dstFormat == MESA_FORMAT_ARGB8888 ||
1423        dstFormat == MESA_FORMAT_XRGB8888) &&
1424       baseInternalFormat == GL_RGBA &&
1425       srcFormat == GL_BGRA &&
1426       ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1427        srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
1428      /* simple memcpy path (little endian) */
1429      memcpy_texture(ctx, dims,
1430                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1431                     dstRowStride,
1432                     dstImageOffsets,
1433                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1434                     srcAddr, srcPacking);
1435   }
1436   else if (!ctx->_ImageTransferState &&
1437       !srcPacking->SwapBytes &&
1438       (dstFormat == MESA_FORMAT_ARGB8888_REV ||
1439        dstFormat == MESA_FORMAT_XRGB8888_REV) &&
1440       baseInternalFormat == GL_RGBA &&
1441       srcFormat == GL_BGRA &&
1442       ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1443        srcType == GL_UNSIGNED_INT_8_8_8_8)) {
1444      /* simple memcpy path (big endian) */
1445      memcpy_texture(ctx, dims,
1446                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1447                     dstRowStride,
1448                     dstImageOffsets,
1449                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1450                     srcAddr, srcPacking);
1451   }
1452   else if (!ctx->_ImageTransferState &&
1453            !srcPacking->SwapBytes &&
1454	    (dstFormat == MESA_FORMAT_ARGB8888 ||
1455             dstFormat == MESA_FORMAT_XRGB8888) &&
1456            srcFormat == GL_RGB &&
1457	    (baseInternalFormat == GL_RGBA ||
1458	     baseInternalFormat == GL_RGB) &&
1459            srcType == GL_UNSIGNED_BYTE) {
1460      int img, row, col;
1461      for (img = 0; img < srcDepth; img++) {
1462         const GLint srcRowStride =
1463            _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
1464         GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1465                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1466         GLubyte *dstRow = (GLubyte *) dstAddr
1467            + dstImageOffsets[dstZoffset + img] * texelBytes
1468            + dstYoffset * dstRowStride
1469            + dstXoffset * texelBytes;
1470         for (row = 0; row < srcHeight; row++) {
1471            GLuint *d4 = (GLuint *) dstRow;
1472            for (col = 0; col < srcWidth; col++) {
1473               d4[col] = PACK_COLOR_8888(0xff,
1474                                         srcRow[col * 3 + RCOMP],
1475                                         srcRow[col * 3 + GCOMP],
1476                                         srcRow[col * 3 + BCOMP]);
1477            }
1478            dstRow += dstRowStride;
1479            srcRow += srcRowStride;
1480         }
1481      }
1482   }
1483   else if (!ctx->_ImageTransferState &&
1484            !srcPacking->SwapBytes &&
1485	    dstFormat == MESA_FORMAT_ARGB8888 &&
1486            srcFormat == GL_RGBA &&
1487	    baseInternalFormat == GL_RGBA &&
1488            srcType == GL_UNSIGNED_BYTE) {
1489      /* same as above case, but src data has alpha too */
1490      GLint img, row, col;
1491      /* For some reason, streaming copies to write-combined regions
1492       * are extremely sensitive to the characteristics of how the
1493       * source data is retrieved.  By reordering the source reads to
1494       * be in-order, the speed of this operation increases by half.
1495       * Strangely the same isn't required for the RGB path, above.
1496       */
1497      for (img = 0; img < srcDepth; img++) {
1498         const GLint srcRowStride =
1499            _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
1500         GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1501                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1502         GLubyte *dstRow = (GLubyte *) dstAddr
1503            + dstImageOffsets[dstZoffset + img] * texelBytes
1504            + dstYoffset * dstRowStride
1505            + dstXoffset * texelBytes;
1506         for (row = 0; row < srcHeight; row++) {
1507            GLuint *d4 = (GLuint *) dstRow;
1508            for (col = 0; col < srcWidth; col++) {
1509               d4[col] = PACK_COLOR_8888(srcRow[col * 4 + ACOMP],
1510                                         srcRow[col * 4 + RCOMP],
1511                                         srcRow[col * 4 + GCOMP],
1512                                         srcRow[col * 4 + BCOMP]);
1513            }
1514            dstRow += dstRowStride;
1515            srcRow += srcRowStride;
1516         }
1517      }
1518   }
1519   else if (!ctx->_ImageTransferState &&
1520	    (srcType == GL_UNSIGNED_BYTE ||
1521	     srcType == GL_UNSIGNED_INT_8_8_8_8 ||
1522	     srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
1523	    can_swizzle(baseInternalFormat) &&
1524	    can_swizzle(srcFormat)) {
1525
1526      GLubyte dstmap[4];
1527
1528      /* dstmap - how to swizzle from RGBA to dst format:
1529       */
1530      if ((littleEndian && dstFormat == MESA_FORMAT_ARGB8888) ||
1531          (littleEndian && dstFormat == MESA_FORMAT_XRGB8888) ||
1532	  (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV) ||
1533	  (!littleEndian && dstFormat == MESA_FORMAT_XRGB8888_REV)) {
1534	 dstmap[3] = 3;		/* alpha */
1535	 dstmap[2] = 0;		/* red */
1536	 dstmap[1] = 1;		/* green */
1537	 dstmap[0] = 2;		/* blue */
1538      }
1539      else {
1540	 assert((littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV) ||
1541		(!littleEndian && dstFormat == MESA_FORMAT_ARGB8888) ||
1542		(littleEndian && dstFormat == MESA_FORMAT_XRGB8888_REV) ||
1543		(!littleEndian && dstFormat == MESA_FORMAT_XRGB8888));
1544	 dstmap[3] = 2;
1545	 dstmap[2] = 1;
1546	 dstmap[1] = 0;
1547	 dstmap[0] = 3;
1548      }
1549
1550      _mesa_swizzle_ubyte_image(ctx, dims,
1551				srcFormat,
1552				srcType,
1553				baseInternalFormat,
1554				dstmap, 4,
1555				dstAddr, dstXoffset, dstYoffset, dstZoffset,
1556				dstRowStride,
1557                                dstImageOffsets,
1558				srcWidth, srcHeight, srcDepth, srcAddr,
1559				srcPacking);
1560   }
1561   else {
1562      /* general path */
1563      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1564                                                 baseInternalFormat,
1565                                                 baseFormat,
1566                                                 srcWidth, srcHeight, srcDepth,
1567                                                 srcFormat, srcType, srcAddr,
1568                                                 srcPacking);
1569      const GLchan *src = tempImage;
1570      GLint img, row, col;
1571      if (!tempImage)
1572         return GL_FALSE;
1573      for (img = 0; img < srcDepth; img++) {
1574         GLubyte *dstRow = (GLubyte *) dstAddr
1575            + dstImageOffsets[dstZoffset + img] * texelBytes
1576            + dstYoffset * dstRowStride
1577            + dstXoffset * texelBytes;
1578         for (row = 0; row < srcHeight; row++) {
1579            GLuint *dstUI = (GLuint *) dstRow;
1580            if (dstFormat == MESA_FORMAT_ARGB8888) {
1581               for (col = 0; col < srcWidth; col++) {
1582                  dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1583                                                CHAN_TO_UBYTE(src[RCOMP]),
1584                                                CHAN_TO_UBYTE(src[GCOMP]),
1585                                                CHAN_TO_UBYTE(src[BCOMP]) );
1586                  src += 4;
1587               }
1588            }
1589            else if (dstFormat == MESA_FORMAT_XRGB8888) {
1590               for (col = 0; col < srcWidth; col++) {
1591                  dstUI[col] = PACK_COLOR_8888( 0xff,
1592                                                CHAN_TO_UBYTE(src[RCOMP]),
1593                                                CHAN_TO_UBYTE(src[GCOMP]),
1594                                                CHAN_TO_UBYTE(src[BCOMP]) );
1595                  src += 4;
1596               }
1597            }
1598            else {
1599               for (col = 0; col < srcWidth; col++) {
1600                  dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1601                                                    CHAN_TO_UBYTE(src[RCOMP]),
1602                                                    CHAN_TO_UBYTE(src[GCOMP]),
1603                                                    CHAN_TO_UBYTE(src[BCOMP]) );
1604                  src += 4;
1605               }
1606            }
1607            dstRow += dstRowStride;
1608         }
1609      }
1610      free((void *) tempImage);
1611   }
1612   return GL_TRUE;
1613}
1614
1615
1616static GLboolean
1617_mesa_texstore_rgb888(TEXSTORE_PARAMS)
1618{
1619   const GLboolean littleEndian = _mesa_little_endian();
1620   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1621   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1622
1623   ASSERT(dstFormat == MESA_FORMAT_RGB888);
1624   ASSERT(texelBytes == 3);
1625
1626   if (!ctx->_ImageTransferState &&
1627       !srcPacking->SwapBytes &&
1628       baseInternalFormat == GL_RGB &&
1629       srcFormat == GL_BGR &&
1630       srcType == GL_UNSIGNED_BYTE &&
1631       littleEndian) {
1632      /* simple memcpy path */
1633      memcpy_texture(ctx, dims,
1634                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1635                     dstRowStride,
1636                     dstImageOffsets,
1637                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1638                     srcAddr, srcPacking);
1639   }
1640   else if (!ctx->_ImageTransferState &&
1641            !srcPacking->SwapBytes &&
1642            srcFormat == GL_RGBA &&
1643            srcType == GL_UNSIGNED_BYTE) {
1644      /* extract RGB from RGBA */
1645      GLint img, row, col;
1646      for (img = 0; img < srcDepth; img++) {
1647         const GLint srcRowStride =
1648            _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
1649         GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1650                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1651         GLubyte *dstRow = (GLubyte *) dstAddr
1652            + dstImageOffsets[dstZoffset + img] * texelBytes
1653            + dstYoffset * dstRowStride
1654            + dstXoffset * texelBytes;
1655         for (row = 0; row < srcHeight; row++) {
1656            for (col = 0; col < srcWidth; col++) {
1657               dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1658               dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1659               dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1660            }
1661            dstRow += dstRowStride;
1662            srcRow += srcRowStride;
1663         }
1664      }
1665   }
1666   else if (!ctx->_ImageTransferState &&
1667	    srcType == GL_UNSIGNED_BYTE &&
1668	    can_swizzle(baseInternalFormat) &&
1669	    can_swizzle(srcFormat)) {
1670
1671      GLubyte dstmap[4];
1672
1673      /* dstmap - how to swizzle from RGBA to dst format:
1674       */
1675      dstmap[0] = 2;
1676      dstmap[1] = 1;
1677      dstmap[2] = 0;
1678      dstmap[3] = ONE;		/* ? */
1679
1680      _mesa_swizzle_ubyte_image(ctx, dims,
1681				srcFormat,
1682				srcType,
1683				baseInternalFormat,
1684				dstmap, 3,
1685				dstAddr, dstXoffset, dstYoffset, dstZoffset,
1686				dstRowStride, dstImageOffsets,
1687				srcWidth, srcHeight, srcDepth, srcAddr,
1688				srcPacking);
1689   }
1690   else {
1691      /* general path */
1692      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1693                                                 baseInternalFormat,
1694                                                 baseFormat,
1695                                                 srcWidth, srcHeight, srcDepth,
1696                                                 srcFormat, srcType, srcAddr,
1697                                                 srcPacking);
1698      const GLchan *src = (const GLchan *) tempImage;
1699      GLint img, row, col;
1700      if (!tempImage)
1701         return GL_FALSE;
1702      for (img = 0; img < srcDepth; img++) {
1703         GLubyte *dstRow = (GLubyte *) dstAddr
1704            + dstImageOffsets[dstZoffset + img] * texelBytes
1705            + dstYoffset * dstRowStride
1706            + dstXoffset * texelBytes;
1707         for (row = 0; row < srcHeight; row++) {
1708#if 0
1709            if (littleEndian) {
1710               for (col = 0; col < srcWidth; col++) {
1711                  dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1712                  dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1713                  dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1714                  srcUB += 3;
1715               }
1716            }
1717            else {
1718               for (col = 0; col < srcWidth; col++) {
1719                  dstRow[col * 3 + 0] = srcUB[BCOMP];
1720                  dstRow[col * 3 + 1] = srcUB[GCOMP];
1721                  dstRow[col * 3 + 2] = srcUB[RCOMP];
1722                  srcUB += 3;
1723               }
1724            }
1725#else
1726            for (col = 0; col < srcWidth; col++) {
1727               dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1728               dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1729               dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1730               src += 3;
1731            }
1732#endif
1733            dstRow += dstRowStride;
1734         }
1735      }
1736      free((void *) tempImage);
1737   }
1738   return GL_TRUE;
1739}
1740
1741
1742static GLboolean
1743_mesa_texstore_bgr888(TEXSTORE_PARAMS)
1744{
1745   const GLboolean littleEndian = _mesa_little_endian();
1746   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1747   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1748
1749   ASSERT(dstFormat == MESA_FORMAT_BGR888);
1750   ASSERT(texelBytes == 3);
1751
1752   if (!ctx->_ImageTransferState &&
1753       !srcPacking->SwapBytes &&
1754       baseInternalFormat == GL_RGB &&
1755       srcFormat == GL_RGB &&
1756       srcType == GL_UNSIGNED_BYTE &&
1757       littleEndian) {
1758      /* simple memcpy path */
1759      memcpy_texture(ctx, dims,
1760                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1761                     dstRowStride,
1762                     dstImageOffsets,
1763                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1764                     srcAddr, srcPacking);
1765   }
1766   else if (!ctx->_ImageTransferState &&
1767            !srcPacking->SwapBytes &&
1768            srcFormat == GL_RGBA &&
1769            srcType == GL_UNSIGNED_BYTE) {
1770      /* extract BGR from RGBA */
1771      int img, row, col;
1772      for (img = 0; img < srcDepth; img++) {
1773         const GLint srcRowStride =
1774            _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
1775         GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1776                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1777         GLubyte *dstRow = (GLubyte *) dstAddr
1778            + dstImageOffsets[dstZoffset + img] * texelBytes
1779            + dstYoffset * dstRowStride
1780            + dstXoffset * texelBytes;
1781         for (row = 0; row < srcHeight; row++) {
1782            for (col = 0; col < srcWidth; col++) {
1783               dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1784               dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1785               dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1786            }
1787            dstRow += dstRowStride;
1788            srcRow += srcRowStride;
1789         }
1790      }
1791   }
1792   else if (!ctx->_ImageTransferState &&
1793	    srcType == GL_UNSIGNED_BYTE &&
1794	    can_swizzle(baseInternalFormat) &&
1795	    can_swizzle(srcFormat)) {
1796
1797      GLubyte dstmap[4];
1798
1799      /* dstmap - how to swizzle from RGBA to dst format:
1800       */
1801      dstmap[0] = 0;
1802      dstmap[1] = 1;
1803      dstmap[2] = 2;
1804      dstmap[3] = ONE;		/* ? */
1805
1806      _mesa_swizzle_ubyte_image(ctx, dims,
1807				srcFormat,
1808				srcType,
1809				baseInternalFormat,
1810				dstmap, 3,
1811				dstAddr, dstXoffset, dstYoffset, dstZoffset,
1812				dstRowStride, dstImageOffsets,
1813				srcWidth, srcHeight, srcDepth, srcAddr,
1814				srcPacking);
1815   }
1816   else {
1817      /* general path */
1818      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1819                                                 baseInternalFormat,
1820                                                 baseFormat,
1821                                                 srcWidth, srcHeight, srcDepth,
1822                                                 srcFormat, srcType, srcAddr,
1823                                                 srcPacking);
1824      const GLchan *src = (const GLchan *) tempImage;
1825      GLint img, row, col;
1826      if (!tempImage)
1827         return GL_FALSE;
1828      for (img = 0; img < srcDepth; img++) {
1829         GLubyte *dstRow = (GLubyte *) dstAddr
1830            + dstImageOffsets[dstZoffset + img] * texelBytes
1831            + dstYoffset * dstRowStride
1832            + dstXoffset * texelBytes;
1833         for (row = 0; row < srcHeight; row++) {
1834            for (col = 0; col < srcWidth; col++) {
1835               dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1836               dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1837               dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1838               src += 3;
1839            }
1840            dstRow += dstRowStride;
1841         }
1842      }
1843      free((void *) tempImage);
1844   }
1845   return GL_TRUE;
1846}
1847
1848
1849static GLboolean
1850_mesa_texstore_argb4444(TEXSTORE_PARAMS)
1851{
1852   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1853   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1854
1855   ASSERT(dstFormat == MESA_FORMAT_ARGB4444 ||
1856          dstFormat == MESA_FORMAT_ARGB4444_REV);
1857   ASSERT(texelBytes == 2);
1858
1859   if (!ctx->_ImageTransferState &&
1860       !srcPacking->SwapBytes &&
1861       dstFormat == MESA_FORMAT_ARGB4444 &&
1862       baseInternalFormat == GL_RGBA &&
1863       srcFormat == GL_BGRA &&
1864       srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1865      /* simple memcpy path */
1866      memcpy_texture(ctx, dims,
1867                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1868                     dstRowStride,
1869                     dstImageOffsets,
1870                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1871                     srcAddr, srcPacking);
1872   }
1873   else {
1874      /* general path */
1875      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1876                                                 baseInternalFormat,
1877                                                 baseFormat,
1878                                                 srcWidth, srcHeight, srcDepth,
1879                                                 srcFormat, srcType, srcAddr,
1880                                                 srcPacking);
1881      const GLchan *src = tempImage;
1882      GLint img, row, col;
1883      if (!tempImage)
1884         return GL_FALSE;
1885      for (img = 0; img < srcDepth; img++) {
1886         GLubyte *dstRow = (GLubyte *) dstAddr
1887            + dstImageOffsets[dstZoffset + img] * texelBytes
1888            + dstYoffset * dstRowStride
1889            + dstXoffset * texelBytes;
1890         for (row = 0; row < srcHeight; row++) {
1891            GLushort *dstUS = (GLushort *) dstRow;
1892            if (dstFormat == MESA_FORMAT_ARGB4444) {
1893               for (col = 0; col < srcWidth; col++) {
1894                  dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1895                                                CHAN_TO_UBYTE(src[RCOMP]),
1896                                                CHAN_TO_UBYTE(src[GCOMP]),
1897                                                CHAN_TO_UBYTE(src[BCOMP]) );
1898                  src += 4;
1899               }
1900            }
1901            else {
1902               for (col = 0; col < srcWidth; col++) {
1903                  dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
1904                                                    CHAN_TO_UBYTE(src[RCOMP]),
1905                                                    CHAN_TO_UBYTE(src[GCOMP]),
1906                                                    CHAN_TO_UBYTE(src[BCOMP]) );
1907                  src += 4;
1908               }
1909            }
1910            dstRow += dstRowStride;
1911         }
1912      }
1913      free((void *) tempImage);
1914   }
1915   return GL_TRUE;
1916}
1917
1918static GLboolean
1919_mesa_texstore_rgba5551(TEXSTORE_PARAMS)
1920{
1921   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1922   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1923
1924   ASSERT(dstFormat == MESA_FORMAT_RGBA5551);
1925   ASSERT(texelBytes == 2);
1926
1927   if (!ctx->_ImageTransferState &&
1928       !srcPacking->SwapBytes &&
1929       dstFormat == MESA_FORMAT_RGBA5551 &&
1930       baseInternalFormat == GL_RGBA &&
1931       srcFormat == GL_RGBA &&
1932       srcType == GL_UNSIGNED_SHORT_5_5_5_1) {
1933      /* simple memcpy path */
1934      memcpy_texture(ctx, dims,
1935                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1936                     dstRowStride,
1937                     dstImageOffsets,
1938                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1939                     srcAddr, srcPacking);
1940   }
1941   else {
1942      /* general path */
1943      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1944                                                 baseInternalFormat,
1945                                                 baseFormat,
1946                                                 srcWidth, srcHeight, srcDepth,
1947                                                 srcFormat, srcType, srcAddr,
1948                                                 srcPacking);
1949      const GLchan *src =tempImage;
1950      GLint img, row, col;
1951      if (!tempImage)
1952         return GL_FALSE;
1953      for (img = 0; img < srcDepth; img++) {
1954         GLubyte *dstRow = (GLubyte *) dstAddr
1955            + dstImageOffsets[dstZoffset + img] * texelBytes
1956            + dstYoffset * dstRowStride
1957            + dstXoffset * texelBytes;
1958         for (row = 0; row < srcHeight; row++) {
1959            GLushort *dstUS = (GLushort *) dstRow;
1960	    for (col = 0; col < srcWidth; col++) {
1961	       dstUS[col] = PACK_COLOR_5551( CHAN_TO_UBYTE(src[RCOMP]),
1962					     CHAN_TO_UBYTE(src[GCOMP]),
1963					     CHAN_TO_UBYTE(src[BCOMP]),
1964					     CHAN_TO_UBYTE(src[ACOMP]) );
1965	      src += 4;
1966	    }
1967            dstRow += dstRowStride;
1968         }
1969      }
1970      free((void *) tempImage);
1971   }
1972   return GL_TRUE;
1973}
1974
1975static GLboolean
1976_mesa_texstore_argb1555(TEXSTORE_PARAMS)
1977{
1978   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
1979   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
1980
1981   ASSERT(dstFormat == MESA_FORMAT_ARGB1555 ||
1982          dstFormat == MESA_FORMAT_ARGB1555_REV);
1983   ASSERT(texelBytes == 2);
1984
1985   if (!ctx->_ImageTransferState &&
1986       !srcPacking->SwapBytes &&
1987       dstFormat == MESA_FORMAT_ARGB1555 &&
1988       baseInternalFormat == GL_RGBA &&
1989       srcFormat == GL_BGRA &&
1990       srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
1991      /* simple memcpy path */
1992      memcpy_texture(ctx, dims,
1993                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1994                     dstRowStride,
1995                     dstImageOffsets,
1996                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1997                     srcAddr, srcPacking);
1998   }
1999   else {
2000      /* general path */
2001      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2002                                                 baseInternalFormat,
2003                                                 baseFormat,
2004                                                 srcWidth, srcHeight, srcDepth,
2005                                                 srcFormat, srcType, srcAddr,
2006                                                 srcPacking);
2007      const GLchan *src =tempImage;
2008      GLint img, row, col;
2009      if (!tempImage)
2010         return GL_FALSE;
2011      for (img = 0; img < srcDepth; img++) {
2012         GLubyte *dstRow = (GLubyte *) dstAddr
2013            + dstImageOffsets[dstZoffset + img] * texelBytes
2014            + dstYoffset * dstRowStride
2015            + dstXoffset * texelBytes;
2016         for (row = 0; row < srcHeight; row++) {
2017            GLushort *dstUS = (GLushort *) dstRow;
2018            if (dstFormat == MESA_FORMAT_ARGB1555) {
2019               for (col = 0; col < srcWidth; col++) {
2020                  dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
2021                                                CHAN_TO_UBYTE(src[RCOMP]),
2022                                                CHAN_TO_UBYTE(src[GCOMP]),
2023                                                CHAN_TO_UBYTE(src[BCOMP]) );
2024                  src += 4;
2025               }
2026            }
2027            else {
2028               for (col = 0; col < srcWidth; col++) {
2029                  dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
2030                                                    CHAN_TO_UBYTE(src[RCOMP]),
2031                                                    CHAN_TO_UBYTE(src[GCOMP]),
2032                                                    CHAN_TO_UBYTE(src[BCOMP]) );
2033                  src += 4;
2034               }
2035            }
2036            dstRow += dstRowStride;
2037         }
2038      }
2039      free((void *) tempImage);
2040   }
2041   return GL_TRUE;
2042}
2043
2044
2045static GLboolean
2046_mesa_texstore_argb2101010(TEXSTORE_PARAMS)
2047{
2048   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2049   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2050
2051   ASSERT(dstFormat == MESA_FORMAT_ARGB2101010);
2052   ASSERT(texelBytes == 4);
2053
2054   if (!ctx->_ImageTransferState &&
2055       !srcPacking->SwapBytes &&
2056       dstFormat == MESA_FORMAT_ARGB2101010 &&
2057       srcFormat == GL_BGRA &&
2058       srcType == GL_UNSIGNED_INT_2_10_10_10_REV &&
2059       baseInternalFormat == GL_RGBA) {
2060      /* simple memcpy path */
2061      memcpy_texture(ctx, dims,
2062                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2063                     dstRowStride,
2064                     dstImageOffsets,
2065                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2066                     srcAddr, srcPacking);
2067   }
2068   else {
2069      /* general path */
2070      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2071                                                 baseInternalFormat,
2072                                                 baseFormat,
2073                                                 srcWidth, srcHeight, srcDepth,
2074                                                 srcFormat, srcType, srcAddr,
2075                                                 srcPacking,
2076                                                 ctx->_ImageTransferState);
2077      const GLfloat *src = tempImage;
2078      GLint img, row, col;
2079      if (!tempImage)
2080         return GL_FALSE;
2081      for (img = 0; img < srcDepth; img++) {
2082         GLubyte *dstRow = (GLubyte *) dstAddr
2083            + dstImageOffsets[dstZoffset + img] * texelBytes
2084            + dstYoffset * dstRowStride
2085            + dstXoffset * texelBytes;
2086         if (baseInternalFormat == GL_RGBA) {
2087            for (row = 0; row < srcHeight; row++) {
2088               GLuint *dstUI = (GLuint *) dstRow;
2089               for (col = 0; col < srcWidth; col++) {
2090                  GLushort a,r,g,b;
2091
2092                  UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]);
2093                  UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
2094                  UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
2095                  UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
2096                  dstUI[col] = PACK_COLOR_2101010_US(a, r, g, b);
2097                  src += 4;
2098               }
2099               dstRow += dstRowStride;
2100            }
2101         } else if (baseInternalFormat == GL_RGB) {
2102            for (row = 0; row < srcHeight; row++) {
2103               GLuint *dstUI = (GLuint *) dstRow;
2104               for (col = 0; col < srcWidth; col++) {
2105                  GLushort r,g,b;
2106
2107                  UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
2108                  UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
2109                  UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
2110                  dstUI[col] = PACK_COLOR_2101010_US(0xffff, r, g, b);
2111                  src += 4;
2112               }
2113               dstRow += dstRowStride;
2114            }
2115         } else {
2116            ASSERT(0);
2117         }
2118      }
2119      free((void *) tempImage);
2120   }
2121   return GL_TRUE;
2122}
2123
2124
2125/**
2126 * Do texstore for 2-channel, 4-bit/channel, unsigned normalized formats.
2127 */
2128static GLboolean
2129_mesa_texstore_unorm44(TEXSTORE_PARAMS)
2130{
2131   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2132   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2133
2134   ASSERT(dstFormat == MESA_FORMAT_AL44);
2135   ASSERT(texelBytes == 1);
2136
2137   {
2138      /* general path */
2139      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2140                                                 baseInternalFormat,
2141                                                 baseFormat,
2142                                                 srcWidth, srcHeight, srcDepth,
2143                                                 srcFormat, srcType, srcAddr,
2144                                                 srcPacking);
2145      const GLchan *src = tempImage;
2146      GLint img, row, col;
2147      if (!tempImage)
2148         return GL_FALSE;
2149      for (img = 0; img < srcDepth; img++) {
2150         GLubyte *dstRow = (GLubyte *) dstAddr
2151            + dstImageOffsets[dstZoffset + img] * texelBytes
2152            + dstYoffset * dstRowStride
2153            + dstXoffset * texelBytes;
2154         for (row = 0; row < srcHeight; row++) {
2155            GLubyte *dstUS = (GLubyte *) dstRow;
2156            for (col = 0; col < srcWidth; col++) {
2157               /* src[0] is luminance, src[1] is alpha */
2158               dstUS[col] = PACK_COLOR_44( CHAN_TO_UBYTE(src[1]),
2159                                           CHAN_TO_UBYTE(src[0]) );
2160               src += 2;
2161            }
2162            dstRow += dstRowStride;
2163         }
2164      }
2165      free((void *) tempImage);
2166   }
2167   return GL_TRUE;
2168}
2169
2170
2171/**
2172 * Do texstore for 2-channel, 8-bit/channel, unsigned normalized formats.
2173 */
2174static GLboolean
2175_mesa_texstore_unorm88(TEXSTORE_PARAMS)
2176{
2177   const GLboolean littleEndian = _mesa_little_endian();
2178   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2179   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2180
2181   ASSERT(dstFormat == MESA_FORMAT_AL88 ||
2182          dstFormat == MESA_FORMAT_AL88_REV ||
2183          dstFormat == MESA_FORMAT_RG88 ||
2184          dstFormat == MESA_FORMAT_RG88_REV);
2185   ASSERT(texelBytes == 2);
2186
2187   if (!ctx->_ImageTransferState &&
2188       !srcPacking->SwapBytes &&
2189       ((dstFormat == MESA_FORMAT_AL88 &&
2190         baseInternalFormat == GL_LUMINANCE_ALPHA &&
2191         srcFormat == GL_LUMINANCE_ALPHA) ||
2192        (dstFormat == MESA_FORMAT_RG88 &&
2193         baseInternalFormat == srcFormat)) &&
2194       srcType == GL_UNSIGNED_BYTE &&
2195       littleEndian) {
2196      /* simple memcpy path */
2197      memcpy_texture(ctx, dims,
2198                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2199                     dstRowStride,
2200                     dstImageOffsets,
2201                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2202                     srcAddr, srcPacking);
2203   }
2204   else if (!ctx->_ImageTransferState &&
2205	    littleEndian &&
2206	    srcType == GL_UNSIGNED_BYTE &&
2207	    can_swizzle(baseInternalFormat) &&
2208	    can_swizzle(srcFormat)) {
2209      GLubyte dstmap[4];
2210
2211      /* dstmap - how to swizzle from RGBA to dst format:
2212       */
2213      if (dstFormat == MESA_FORMAT_AL88 || dstFormat == MESA_FORMAT_AL88_REV) {
2214	 if ((littleEndian && dstFormat == MESA_FORMAT_AL88) ||
2215	     (!littleEndian && dstFormat == MESA_FORMAT_AL88_REV)) {
2216	    dstmap[0] = 0;
2217	    dstmap[1] = 3;
2218	 }
2219	 else {
2220	    dstmap[0] = 3;
2221	    dstmap[1] = 0;
2222	 }
2223      }
2224      else {
2225	 if ((littleEndian && dstFormat == MESA_FORMAT_RG88) ||
2226	     (!littleEndian && dstFormat == MESA_FORMAT_RG88_REV)) {
2227	    dstmap[0] = 0;
2228	    dstmap[1] = 1;
2229	 }
2230	 else {
2231	    dstmap[0] = 1;
2232	    dstmap[1] = 0;
2233	 }
2234      }
2235      dstmap[2] = ZERO;		/* ? */
2236      dstmap[3] = ONE;		/* ? */
2237
2238      _mesa_swizzle_ubyte_image(ctx, dims,
2239				srcFormat,
2240				srcType,
2241				baseInternalFormat,
2242				dstmap, 2,
2243				dstAddr, dstXoffset, dstYoffset, dstZoffset,
2244				dstRowStride, dstImageOffsets,
2245				srcWidth, srcHeight, srcDepth, srcAddr,
2246				srcPacking);
2247   }
2248   else {
2249      /* general path */
2250      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2251                                                 baseInternalFormat,
2252                                                 baseFormat,
2253                                                 srcWidth, srcHeight, srcDepth,
2254                                                 srcFormat, srcType, srcAddr,
2255                                                 srcPacking);
2256      const GLchan *src = tempImage;
2257      GLint img, row, col;
2258      if (!tempImage)
2259         return GL_FALSE;
2260      for (img = 0; img < srcDepth; img++) {
2261         GLubyte *dstRow = (GLubyte *) dstAddr
2262            + dstImageOffsets[dstZoffset + img] * texelBytes
2263            + dstYoffset * dstRowStride
2264            + dstXoffset * texelBytes;
2265         for (row = 0; row < srcHeight; row++) {
2266            GLushort *dstUS = (GLushort *) dstRow;
2267            if (dstFormat == MESA_FORMAT_AL88 ||
2268		dstFormat == MESA_FORMAT_RG88) {
2269               for (col = 0; col < srcWidth; col++) {
2270                  /* src[0] is luminance, src[1] is alpha */
2271                 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
2272                                             CHAN_TO_UBYTE(src[0]) );
2273                 src += 2;
2274               }
2275            }
2276            else {
2277               for (col = 0; col < srcWidth; col++) {
2278                  /* src[0] is luminance, src[1] is alpha */
2279                 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
2280                                                 CHAN_TO_UBYTE(src[0]) );
2281                 src += 2;
2282               }
2283            }
2284            dstRow += dstRowStride;
2285         }
2286      }
2287      free((void *) tempImage);
2288   }
2289   return GL_TRUE;
2290}
2291
2292
2293/**
2294 * Do texstore for 2-channel, 16-bit/channel, unsigned normalized formats.
2295 */
2296static GLboolean
2297_mesa_texstore_unorm1616(TEXSTORE_PARAMS)
2298{
2299   const GLboolean littleEndian = _mesa_little_endian();
2300   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2301   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2302
2303   ASSERT(dstFormat == MESA_FORMAT_AL1616 ||
2304          dstFormat == MESA_FORMAT_AL1616_REV ||
2305	  dstFormat == MESA_FORMAT_RG1616 ||
2306          dstFormat == MESA_FORMAT_RG1616_REV);
2307   ASSERT(texelBytes == 4);
2308
2309   if (!ctx->_ImageTransferState &&
2310       !srcPacking->SwapBytes &&
2311       ((dstFormat == MESA_FORMAT_AL1616 &&
2312         baseInternalFormat == GL_LUMINANCE_ALPHA &&
2313         srcFormat == GL_LUMINANCE_ALPHA) ||
2314        (dstFormat == MESA_FORMAT_RG1616 &&
2315         baseInternalFormat == srcFormat)) &&
2316       srcType == GL_UNSIGNED_SHORT &&
2317       littleEndian) {
2318      /* simple memcpy path */
2319      memcpy_texture(ctx, dims,
2320                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2321                     dstRowStride,
2322                     dstImageOffsets,
2323                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2324                     srcAddr, srcPacking);
2325   }
2326   else {
2327      /* general path */
2328      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2329                                                 baseInternalFormat,
2330                                                 baseFormat,
2331                                                 srcWidth, srcHeight, srcDepth,
2332                                                 srcFormat, srcType, srcAddr,
2333                                                 srcPacking,
2334                                                 ctx->_ImageTransferState);
2335      const GLfloat *src = tempImage;
2336      GLint img, row, col;
2337      if (!tempImage)
2338         return GL_FALSE;
2339      for (img = 0; img < srcDepth; img++) {
2340         GLubyte *dstRow = (GLubyte *) dstAddr
2341            + dstImageOffsets[dstZoffset + img] * texelBytes
2342            + dstYoffset * dstRowStride
2343            + dstXoffset * texelBytes;
2344         for (row = 0; row < srcHeight; row++) {
2345            GLuint *dstUI = (GLuint *) dstRow;
2346            if (dstFormat == MESA_FORMAT_AL1616 ||
2347		dstFormat == MESA_FORMAT_RG1616) {
2348               for (col = 0; col < srcWidth; col++) {
2349		  GLushort l, a;
2350
2351		  UNCLAMPED_FLOAT_TO_USHORT(l, src[0]);
2352		  UNCLAMPED_FLOAT_TO_USHORT(a, src[1]);
2353		  dstUI[col] = PACK_COLOR_1616(a, l);
2354		  src += 2;
2355               }
2356            }
2357            else {
2358               for (col = 0; col < srcWidth; col++) {
2359		  GLushort l, a;
2360
2361		  UNCLAMPED_FLOAT_TO_USHORT(l, src[0]);
2362		  UNCLAMPED_FLOAT_TO_USHORT(a, src[1]);
2363		  dstUI[col] = PACK_COLOR_1616_REV(a, l);
2364		  src += 2;
2365               }
2366            }
2367            dstRow += dstRowStride;
2368         }
2369      }
2370      free((void *) tempImage);
2371   }
2372   return GL_TRUE;
2373}
2374
2375
2376/* Texstore for R16, A16, L16, I16. */
2377static GLboolean
2378_mesa_texstore_unorm16(TEXSTORE_PARAMS)
2379{
2380   const GLboolean littleEndian = _mesa_little_endian();
2381   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2382   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2383
2384   ASSERT(dstFormat == MESA_FORMAT_R16 ||
2385          dstFormat == MESA_FORMAT_A16 ||
2386          dstFormat == MESA_FORMAT_L16 ||
2387          dstFormat == MESA_FORMAT_I16);
2388   ASSERT(texelBytes == 2);
2389
2390   if (!ctx->_ImageTransferState &&
2391       !srcPacking->SwapBytes &&
2392       baseInternalFormat == srcFormat &&
2393       srcType == GL_UNSIGNED_SHORT &&
2394       littleEndian) {
2395      /* simple memcpy path */
2396      memcpy_texture(ctx, dims,
2397                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2398                     dstRowStride,
2399                     dstImageOffsets,
2400                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2401                     srcAddr, srcPacking);
2402   }
2403   else {
2404      /* general path */
2405      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2406                                                 baseInternalFormat,
2407                                                 baseFormat,
2408                                                 srcWidth, srcHeight, srcDepth,
2409                                                 srcFormat, srcType, srcAddr,
2410                                                 srcPacking,
2411                                                 ctx->_ImageTransferState);
2412      const GLfloat *src = tempImage;
2413      GLint img, row, col;
2414      if (!tempImage)
2415         return GL_FALSE;
2416      for (img = 0; img < srcDepth; img++) {
2417         GLubyte *dstRow = (GLubyte *) dstAddr
2418            + dstImageOffsets[dstZoffset + img] * texelBytes
2419            + dstYoffset * dstRowStride
2420            + dstXoffset * texelBytes;
2421         for (row = 0; row < srcHeight; row++) {
2422            GLushort *dstUS = (GLushort *) dstRow;
2423	    for (col = 0; col < srcWidth; col++) {
2424	       GLushort r;
2425
2426	       UNCLAMPED_FLOAT_TO_USHORT(r, src[0]);
2427	       dstUS[col] = r;
2428	       src += 1;
2429	    }
2430            dstRow += dstRowStride;
2431         }
2432      }
2433      free((void *) tempImage);
2434   }
2435   return GL_TRUE;
2436}
2437
2438
2439static GLboolean
2440_mesa_texstore_rgba_16(TEXSTORE_PARAMS)
2441{
2442   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2443   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2444
2445   ASSERT(dstFormat == MESA_FORMAT_RGBA_16);
2446   ASSERT(texelBytes == 8);
2447
2448   if (!ctx->_ImageTransferState &&
2449       !srcPacking->SwapBytes &&
2450       baseInternalFormat == GL_RGBA &&
2451       srcFormat == GL_RGBA &&
2452       srcType == GL_UNSIGNED_SHORT) {
2453      /* simple memcpy path */
2454      memcpy_texture(ctx, dims,
2455                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2456                     dstRowStride,
2457                     dstImageOffsets,
2458                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2459                     srcAddr, srcPacking);
2460   }
2461   else {
2462      /* general path */
2463      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2464                                                 baseInternalFormat,
2465                                                 baseFormat,
2466                                                 srcWidth, srcHeight, srcDepth,
2467                                                 srcFormat, srcType, srcAddr,
2468                                                 srcPacking,
2469                                                 ctx->_ImageTransferState);
2470      const GLfloat *src = tempImage;
2471      GLint img, row, col;
2472      if (!tempImage)
2473         return GL_FALSE;
2474      for (img = 0; img < srcDepth; img++) {
2475         GLubyte *dstRow = (GLubyte *) dstAddr
2476            + dstImageOffsets[dstZoffset + img] * texelBytes
2477            + dstYoffset * dstRowStride
2478            + dstXoffset * texelBytes;
2479         for (row = 0; row < srcHeight; row++) {
2480            GLushort *dstUS = (GLushort *) dstRow;
2481            for (col = 0; col < srcWidth; col++) {
2482               GLushort r, g, b, a;
2483
2484               UNCLAMPED_FLOAT_TO_USHORT(r, src[0]);
2485               UNCLAMPED_FLOAT_TO_USHORT(g, src[1]);
2486               UNCLAMPED_FLOAT_TO_USHORT(b, src[2]);
2487               UNCLAMPED_FLOAT_TO_USHORT(a, src[3]);
2488               dstUS[col*4+0] = r;
2489               dstUS[col*4+1] = g;
2490               dstUS[col*4+2] = b;
2491               dstUS[col*4+3] = a;
2492               src += 4;
2493            }
2494            dstRow += dstRowStride;
2495         }
2496      }
2497      free((void *) tempImage);
2498   }
2499   return GL_TRUE;
2500}
2501
2502
2503static GLboolean
2504_mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
2505{
2506   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2507   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2508
2509   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGB_16 ||
2510          dstFormat == MESA_FORMAT_SIGNED_RGBA_16);
2511
2512   if (!ctx->_ImageTransferState &&
2513       !srcPacking->SwapBytes &&
2514       baseInternalFormat == GL_RGBA &&
2515       dstFormat == MESA_FORMAT_SIGNED_RGBA_16 &&
2516       srcFormat == GL_RGBA &&
2517       srcType == GL_SHORT) {
2518      /* simple memcpy path */
2519      memcpy_texture(ctx, dims,
2520                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2521                     dstRowStride,
2522                     dstImageOffsets,
2523                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2524                     srcAddr, srcPacking);
2525   }
2526   else {
2527      /* general path */
2528      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2529                                                 baseInternalFormat,
2530                                                 baseFormat,
2531                                                 srcWidth, srcHeight, srcDepth,
2532                                                 srcFormat, srcType, srcAddr,
2533                                                 srcPacking,
2534                                                 ctx->_ImageTransferState);
2535      const GLfloat *src = tempImage;
2536      const GLuint comps = _mesa_get_format_bytes(dstFormat) / 2;
2537      GLint img, row, col;
2538
2539      if (!tempImage)
2540         return GL_FALSE;
2541
2542      /* Note: tempImage is always float[4] / RGBA.  We convert to 1, 2,
2543       * 3 or 4 components/pixel here.
2544       */
2545      for (img = 0; img < srcDepth; img++) {
2546         GLubyte *dstRow = (GLubyte *) dstAddr
2547            + dstImageOffsets[dstZoffset + img] * texelBytes
2548            + dstYoffset * dstRowStride
2549            + dstXoffset * texelBytes;
2550         for (row = 0; row < srcHeight; row++) {
2551            GLshort *dstRowS = (GLshort *) dstRow;
2552            if (dstFormat == MESA_FORMAT_SIGNED_RGBA_16) {
2553               for (col = 0; col < srcWidth; col++) {
2554                  GLuint c;
2555                  for (c = 0; c < comps; c++) {
2556                     GLshort p;
2557                     UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]);
2558                     dstRowS[col * comps + c] = p;
2559                  }
2560               }
2561               dstRow += dstRowStride;
2562               src += 4 * srcWidth;
2563            } else {
2564               for (col = 0; col < srcWidth; col++) {
2565                  GLuint c;
2566                  for (c = 0; c < comps; c++) {
2567                     GLshort p;
2568                     UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 3 + c]);
2569                     dstRowS[col * comps + c] = p;
2570                  }
2571               }
2572               dstRow += dstRowStride;
2573               src += 3 * srcWidth;
2574            }
2575         }
2576      }
2577      free((void *) tempImage);
2578   }
2579   return GL_TRUE;
2580}
2581
2582
2583static GLboolean
2584_mesa_texstore_rgb332(TEXSTORE_PARAMS)
2585{
2586   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2587   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2588
2589   ASSERT(dstFormat == MESA_FORMAT_RGB332);
2590   ASSERT(texelBytes == 1);
2591
2592   if (!ctx->_ImageTransferState &&
2593       !srcPacking->SwapBytes &&
2594       baseInternalFormat == GL_RGB &&
2595       srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
2596      /* simple memcpy path */
2597      memcpy_texture(ctx, dims,
2598                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2599                     dstRowStride,
2600                     dstImageOffsets,
2601                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2602                     srcAddr, srcPacking);
2603   }
2604   else {
2605      /* general path */
2606      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2607                                                 baseInternalFormat,
2608                                                 baseFormat,
2609                                                 srcWidth, srcHeight, srcDepth,
2610                                                 srcFormat, srcType, srcAddr,
2611                                                 srcPacking);
2612      const GLchan *src = tempImage;
2613      GLint img, row, col;
2614      if (!tempImage)
2615         return GL_FALSE;
2616      for (img = 0; img < srcDepth; img++) {
2617         GLubyte *dstRow = (GLubyte *) dstAddr
2618            + dstImageOffsets[dstZoffset + img] * texelBytes
2619            + dstYoffset * dstRowStride
2620            + dstXoffset * texelBytes;
2621         for (row = 0; row < srcHeight; row++) {
2622            for (col = 0; col < srcWidth; col++) {
2623               dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
2624                                             CHAN_TO_UBYTE(src[GCOMP]),
2625                                             CHAN_TO_UBYTE(src[BCOMP]) );
2626               src += 3;
2627            }
2628            dstRow += dstRowStride;
2629         }
2630      }
2631      free((void *) tempImage);
2632   }
2633   return GL_TRUE;
2634}
2635
2636
2637/**
2638 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
2639 */
2640static GLboolean
2641_mesa_texstore_unorm8(TEXSTORE_PARAMS)
2642{
2643   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2644   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2645
2646   ASSERT(dstFormat == MESA_FORMAT_A8 ||
2647          dstFormat == MESA_FORMAT_L8 ||
2648          dstFormat == MESA_FORMAT_I8 ||
2649          dstFormat == MESA_FORMAT_R8);
2650   ASSERT(texelBytes == 1);
2651
2652   if (!ctx->_ImageTransferState &&
2653       !srcPacking->SwapBytes &&
2654       baseInternalFormat == srcFormat &&
2655       srcType == GL_UNSIGNED_BYTE) {
2656      /* simple memcpy path */
2657      memcpy_texture(ctx, dims,
2658                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2659                     dstRowStride,
2660                     dstImageOffsets,
2661                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2662                     srcAddr, srcPacking);
2663   }
2664   else if (!ctx->_ImageTransferState &&
2665	    srcType == GL_UNSIGNED_BYTE &&
2666	    can_swizzle(baseInternalFormat) &&
2667	    can_swizzle(srcFormat)) {
2668      GLubyte dstmap[4];
2669
2670      /* dstmap - how to swizzle from RGBA to dst format:
2671       */
2672      if (dstFormat == MESA_FORMAT_A8) {
2673	 dstmap[0] = 3;
2674      }
2675      else {
2676	 dstmap[0] = 0;
2677      }
2678      dstmap[1] = ZERO;		/* ? */
2679      dstmap[2] = ZERO;		/* ? */
2680      dstmap[3] = ONE;		/* ? */
2681
2682      _mesa_swizzle_ubyte_image(ctx, dims,
2683				srcFormat,
2684				srcType,
2685				baseInternalFormat,
2686				dstmap, 1,
2687				dstAddr, dstXoffset, dstYoffset, dstZoffset,
2688				dstRowStride, dstImageOffsets,
2689				srcWidth, srcHeight, srcDepth, srcAddr,
2690				srcPacking);
2691   }
2692   else {
2693      /* general path */
2694      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
2695                                                 baseInternalFormat,
2696                                                 baseFormat,
2697                                                 srcWidth, srcHeight, srcDepth,
2698                                                 srcFormat, srcType, srcAddr,
2699                                                 srcPacking);
2700      const GLchan *src = tempImage;
2701      GLint img, row, col;
2702      if (!tempImage)
2703         return GL_FALSE;
2704      for (img = 0; img < srcDepth; img++) {
2705         GLubyte *dstRow = (GLubyte *) dstAddr
2706            + dstImageOffsets[dstZoffset + img] * texelBytes
2707            + dstYoffset * dstRowStride
2708            + dstXoffset * texelBytes;
2709         for (row = 0; row < srcHeight; row++) {
2710            for (col = 0; col < srcWidth; col++) {
2711               dstRow[col] = CHAN_TO_UBYTE(src[col]);
2712            }
2713            dstRow += dstRowStride;
2714            src += srcWidth;
2715         }
2716      }
2717      free((void *) tempImage);
2718   }
2719   return GL_TRUE;
2720}
2721
2722
2723
2724static GLboolean
2725_mesa_texstore_ci8(TEXSTORE_PARAMS)
2726{
2727   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2728
2729   (void) dims; (void) baseInternalFormat;
2730   ASSERT(dstFormat == MESA_FORMAT_CI8);
2731   ASSERT(texelBytes == 1);
2732   ASSERT(baseInternalFormat == GL_COLOR_INDEX);
2733
2734   if (!ctx->_ImageTransferState &&
2735       !srcPacking->SwapBytes &&
2736       srcFormat == GL_COLOR_INDEX &&
2737       srcType == GL_UNSIGNED_BYTE) {
2738      /* simple memcpy path */
2739      memcpy_texture(ctx, dims,
2740                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2741                     dstRowStride,
2742                     dstImageOffsets,
2743                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2744                     srcAddr, srcPacking);
2745   }
2746   else {
2747      /* general path */
2748      GLint img, row;
2749      for (img = 0; img < srcDepth; img++) {
2750         GLubyte *dstRow = (GLubyte *) dstAddr
2751            + dstImageOffsets[dstZoffset + img] * texelBytes
2752            + dstYoffset * dstRowStride
2753            + dstXoffset * texelBytes;
2754         for (row = 0; row < srcHeight; row++) {
2755            const GLvoid *src = _mesa_image_address(dims, srcPacking,
2756                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
2757            _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
2758                                    srcType, src, srcPacking,
2759                                    ctx->_ImageTransferState);
2760            dstRow += dstRowStride;
2761         }
2762      }
2763   }
2764   return GL_TRUE;
2765}
2766
2767
2768/**
2769 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
2770 */
2771static GLboolean
2772_mesa_texstore_ycbcr(TEXSTORE_PARAMS)
2773{
2774   const GLboolean littleEndian = _mesa_little_endian();
2775   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2776
2777   (void) ctx; (void) dims; (void) baseInternalFormat;
2778
2779   ASSERT((dstFormat == MESA_FORMAT_YCBCR) ||
2780          (dstFormat == MESA_FORMAT_YCBCR_REV));
2781   ASSERT(texelBytes == 2);
2782   ASSERT(ctx->Extensions.MESA_ycbcr_texture);
2783   ASSERT(srcFormat == GL_YCBCR_MESA);
2784   ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
2785          (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
2786   ASSERT(baseInternalFormat == GL_YCBCR_MESA);
2787
2788   /* always just memcpy since no pixel transfer ops apply */
2789   memcpy_texture(ctx, dims,
2790                  dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2791                  dstRowStride,
2792                  dstImageOffsets,
2793                  srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2794                  srcAddr, srcPacking);
2795
2796   /* Check if we need byte swapping */
2797   /* XXX the logic here _might_ be wrong */
2798   if (srcPacking->SwapBytes ^
2799       (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
2800       (dstFormat == MESA_FORMAT_YCBCR_REV) ^
2801       !littleEndian) {
2802      GLint img, row;
2803      for (img = 0; img < srcDepth; img++) {
2804         GLubyte *dstRow = (GLubyte *) dstAddr
2805            + dstImageOffsets[dstZoffset + img] * texelBytes
2806            + dstYoffset * dstRowStride
2807            + dstXoffset * texelBytes;
2808         for (row = 0; row < srcHeight; row++) {
2809            _mesa_swap2((GLushort *) dstRow, srcWidth);
2810            dstRow += dstRowStride;
2811         }
2812      }
2813   }
2814   return GL_TRUE;
2815}
2816
2817static GLboolean
2818_mesa_texstore_dudv8(TEXSTORE_PARAMS)
2819{
2820   const GLboolean littleEndian = _mesa_little_endian();
2821   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2822
2823   ASSERT(dstFormat == MESA_FORMAT_DUDV8);
2824   ASSERT(texelBytes == 2);
2825   ASSERT(ctx->Extensions.ATI_envmap_bumpmap);
2826   ASSERT((srcFormat == GL_DU8DV8_ATI) ||
2827	  (srcFormat == GL_DUDV_ATI));
2828   ASSERT(baseInternalFormat == GL_DUDV_ATI);
2829
2830   if (!srcPacking->SwapBytes && srcType == GL_BYTE &&
2831       littleEndian) {
2832      /* simple memcpy path */
2833      memcpy_texture(ctx, dims,
2834                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2835                     dstRowStride,
2836                     dstImageOffsets,
2837                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2838                     srcAddr, srcPacking);
2839   }
2840   else if (srcType == GL_BYTE) {
2841      GLubyte dstmap[4];
2842
2843      /* dstmap - how to swizzle from RGBA to dst format:
2844       */
2845      if (littleEndian) {
2846	 dstmap[0] = 0;
2847	 dstmap[1] = 3;
2848      }
2849      else {
2850	 dstmap[0] = 3;
2851	 dstmap[1] = 0;
2852      }
2853      dstmap[2] = ZERO;		/* ? */
2854      dstmap[3] = ONE;		/* ? */
2855
2856      _mesa_swizzle_ubyte_image(ctx, dims,
2857				GL_LUMINANCE_ALPHA, /* hack */
2858				GL_UNSIGNED_BYTE, /* hack */
2859				GL_LUMINANCE_ALPHA, /* hack */
2860				dstmap, 2,
2861				dstAddr, dstXoffset, dstYoffset, dstZoffset,
2862				dstRowStride, dstImageOffsets,
2863				srcWidth, srcHeight, srcDepth, srcAddr,
2864				srcPacking);
2865   }
2866   else {
2867      /* general path - note this is defined for 2d textures only */
2868      const GLint components = _mesa_components_in_format(baseInternalFormat);
2869      const GLint srcStride = _mesa_image_row_stride(srcPacking, srcWidth,
2870                                                     srcFormat, srcType);
2871      GLbyte *tempImage, *dst, *src;
2872      GLint row;
2873
2874      tempImage = (GLbyte *) malloc(srcWidth * srcHeight * srcDepth
2875                                          * components * sizeof(GLbyte));
2876      if (!tempImage)
2877         return GL_FALSE;
2878
2879      src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr,
2880                                           srcWidth, srcHeight,
2881                                           srcFormat, srcType,
2882                                           0, 0, 0);
2883
2884      dst = tempImage;
2885      for (row = 0; row < srcHeight; row++) {
2886         _mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat,
2887                                     dst, srcFormat, srcType, src,
2888                                     srcPacking, 0);
2889         dst += srcWidth * components;
2890         src += srcStride;
2891      }
2892
2893      src = tempImage;
2894      dst = (GLbyte *) dstAddr
2895            + dstYoffset * dstRowStride
2896            + dstXoffset * texelBytes;
2897      for (row = 0; row < srcHeight; row++) {
2898         memcpy(dst, src, srcWidth * texelBytes);
2899         dst += dstRowStride;
2900         src += srcWidth * texelBytes;
2901      }
2902      free((void *) tempImage);
2903   }
2904   return GL_TRUE;
2905}
2906
2907
2908/**
2909 * Store a texture in a signed normalized 8-bit format.
2910 */
2911static GLboolean
2912_mesa_texstore_snorm8(TEXSTORE_PARAMS)
2913{
2914   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2915   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2916
2917   ASSERT(dstFormat == MESA_FORMAT_SIGNED_A8 ||
2918          dstFormat == MESA_FORMAT_SIGNED_L8 ||
2919          dstFormat == MESA_FORMAT_SIGNED_I8 ||
2920          dstFormat == MESA_FORMAT_SIGNED_R8);
2921   ASSERT(texelBytes == 1);
2922
2923   if (!ctx->_ImageTransferState &&
2924       !srcPacking->SwapBytes &&
2925       baseInternalFormat == srcFormat &&
2926       srcType == GL_BYTE) {
2927      /* simple memcpy path */
2928      memcpy_texture(ctx, dims,
2929                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2930                     dstRowStride,
2931                     dstImageOffsets,
2932                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2933                     srcAddr, srcPacking);
2934   }
2935   else {
2936      /* general path */
2937      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2938                                                 baseInternalFormat,
2939                                                 baseFormat,
2940                                                 srcWidth, srcHeight, srcDepth,
2941                                                 srcFormat, srcType, srcAddr,
2942                                                 srcPacking,
2943                                                 ctx->_ImageTransferState);
2944      const GLfloat *src = tempImage;
2945      GLint img, row, col;
2946      if (!tempImage)
2947         return GL_FALSE;
2948      for (img = 0; img < srcDepth; img++) {
2949         GLbyte *dstRow = (GLbyte *) dstAddr
2950            + dstImageOffsets[dstZoffset + img] * texelBytes
2951            + dstYoffset * dstRowStride
2952            + dstXoffset * texelBytes;
2953         for (row = 0; row < srcHeight; row++) {
2954            for (col = 0; col < srcWidth; col++) {
2955               dstRow[col] = FLOAT_TO_BYTE_TEX(src[col]);
2956            }
2957            dstRow += dstRowStride;
2958            src += srcWidth;
2959         }
2960      }
2961      free((void *) tempImage);
2962   }
2963   return GL_TRUE;
2964}
2965
2966
2967/**
2968 * Store a texture in a signed normalized two-channel 16-bit format.
2969 */
2970static GLboolean
2971_mesa_texstore_snorm88(TEXSTORE_PARAMS)
2972{
2973   const GLboolean littleEndian = _mesa_little_endian();
2974   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
2975   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
2976
2977   ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL88 ||
2978          dstFormat == MESA_FORMAT_SIGNED_RG88_REV);
2979   ASSERT(texelBytes == 2);
2980
2981   if (!ctx->_ImageTransferState &&
2982       !srcPacking->SwapBytes &&
2983       baseInternalFormat == srcFormat &&
2984       srcType == GL_BYTE &&
2985       littleEndian) {
2986      /* simple memcpy path */
2987      memcpy_texture(ctx, dims,
2988                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2989                     dstRowStride,
2990                     dstImageOffsets,
2991                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2992                     srcAddr, srcPacking);
2993   }
2994   else {
2995      /* general path */
2996      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
2997                                                 baseInternalFormat,
2998                                                 baseFormat,
2999                                                 srcWidth, srcHeight, srcDepth,
3000                                                 srcFormat, srcType, srcAddr,
3001                                                 srcPacking,
3002                                                 ctx->_ImageTransferState);
3003      const GLfloat *src = tempImage;
3004      GLint img, row, col;
3005      if (!tempImage)
3006         return GL_FALSE;
3007      for (img = 0; img < srcDepth; img++) {
3008         GLbyte *dstRow = (GLbyte *) dstAddr
3009            + dstImageOffsets[dstZoffset + img] * texelBytes
3010            + dstYoffset * dstRowStride
3011            + dstXoffset * texelBytes;
3012         for (row = 0; row < srcHeight; row++) {
3013            GLbyte *dst = dstRow;
3014            for (col = 0; col < srcWidth; col++) {
3015               dst[0] = FLOAT_TO_BYTE_TEX(src[0]);
3016               dst[1] = FLOAT_TO_BYTE_TEX(src[1]);
3017               src += 2;
3018               dst += 2;
3019            }
3020            dstRow += dstRowStride;
3021         }
3022      }
3023      free((void *) tempImage);
3024   }
3025   return GL_TRUE;
3026}
3027
3028/* Texstore for signed R16, A16, L16, I16. */
3029static GLboolean
3030_mesa_texstore_snorm16(TEXSTORE_PARAMS)
3031{
3032   const GLboolean littleEndian = _mesa_little_endian();
3033   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3034   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3035
3036   ASSERT(dstFormat == MESA_FORMAT_SIGNED_R16 ||
3037          dstFormat == MESA_FORMAT_SIGNED_A16 ||
3038          dstFormat == MESA_FORMAT_SIGNED_L16 ||
3039          dstFormat == MESA_FORMAT_SIGNED_I16);
3040   ASSERT(texelBytes == 2);
3041
3042   if (!ctx->_ImageTransferState &&
3043       !srcPacking->SwapBytes &&
3044       baseInternalFormat == srcFormat &&
3045       srcType == GL_SHORT &&
3046       littleEndian) {
3047      /* simple memcpy path */
3048      memcpy_texture(ctx, dims,
3049                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3050                     dstRowStride,
3051                     dstImageOffsets,
3052                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3053                     srcAddr, srcPacking);
3054   }
3055   else {
3056      /* general path */
3057      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3058                                                 baseInternalFormat,
3059                                                 baseFormat,
3060                                                 srcWidth, srcHeight, srcDepth,
3061                                                 srcFormat, srcType, srcAddr,
3062                                                 srcPacking,
3063                                                 ctx->_ImageTransferState);
3064      const GLfloat *src = tempImage;
3065      GLint img, row, col;
3066      if (!tempImage)
3067         return GL_FALSE;
3068      for (img = 0; img < srcDepth; img++) {
3069         GLubyte *dstRow = (GLubyte *) dstAddr
3070            + dstImageOffsets[dstZoffset + img] * texelBytes
3071            + dstYoffset * dstRowStride
3072            + dstXoffset * texelBytes;
3073         for (row = 0; row < srcHeight; row++) {
3074            GLshort *dstUS = (GLshort *) dstRow;
3075	    for (col = 0; col < srcWidth; col++) {
3076	       GLushort r;
3077
3078	       UNCLAMPED_FLOAT_TO_SHORT(r, src[0]);
3079	       dstUS[col] = r;
3080	       src += 1;
3081	    }
3082            dstRow += dstRowStride;
3083         }
3084      }
3085      free((void *) tempImage);
3086   }
3087   return GL_TRUE;
3088}
3089
3090/**
3091 * Do texstore for 2-channel, 16-bit/channel, signed normalized formats.
3092 */
3093static GLboolean
3094_mesa_texstore_snorm1616(TEXSTORE_PARAMS)
3095{
3096   const GLboolean littleEndian = _mesa_little_endian();
3097   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3098   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3099
3100   ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL1616 ||
3101          dstFormat == MESA_FORMAT_SIGNED_GR1616);
3102   ASSERT(texelBytes == 4);
3103
3104   if (!ctx->_ImageTransferState &&
3105       !srcPacking->SwapBytes &&
3106       baseInternalFormat == srcFormat &&
3107       srcType == GL_SHORT &&
3108       littleEndian) {
3109      /* simple memcpy path */
3110      memcpy_texture(ctx, dims,
3111                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3112                     dstRowStride,
3113                     dstImageOffsets,
3114                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3115                     srcAddr, srcPacking);
3116   }
3117   else {
3118      /* general path */
3119      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3120                                                 baseInternalFormat,
3121                                                 baseFormat,
3122                                                 srcWidth, srcHeight, srcDepth,
3123                                                 srcFormat, srcType, srcAddr,
3124                                                 srcPacking,
3125                                                 ctx->_ImageTransferState);
3126      const GLfloat *src = tempImage;
3127      GLint img, row, col;
3128      if (!tempImage)
3129         return GL_FALSE;
3130      for (img = 0; img < srcDepth; img++) {
3131         GLubyte *dstRow = (GLubyte *) dstAddr
3132            + dstImageOffsets[dstZoffset + img] * texelBytes
3133            + dstYoffset * dstRowStride
3134            + dstXoffset * texelBytes;
3135         for (row = 0; row < srcHeight; row++) {
3136            GLshort *dst = (GLshort *) dstRow;
3137            for (col = 0; col < srcWidth; col++) {
3138               GLushort l, a;
3139
3140               UNCLAMPED_FLOAT_TO_SHORT(l, src[0]);
3141               UNCLAMPED_FLOAT_TO_SHORT(a, src[1]);
3142               dst[0] = l;
3143               dst[1] = a;
3144               src += 2;
3145               dst += 2;
3146            }
3147            dstRow += dstRowStride;
3148         }
3149      }
3150      free((void *) tempImage);
3151   }
3152   return GL_TRUE;
3153}
3154
3155/**
3156 * Store a texture in MESA_FORMAT_SIGNED_RGBX8888.
3157 */
3158static GLboolean
3159_mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS)
3160{
3161   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3162   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3163
3164   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGBX8888);
3165   ASSERT(texelBytes == 4);
3166
3167   {
3168      /* general path */
3169      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3170                                                 baseInternalFormat,
3171                                                 baseFormat,
3172                                                 srcWidth, srcHeight, srcDepth,
3173                                                 srcFormat, srcType, srcAddr,
3174                                                 srcPacking,
3175                                                 ctx->_ImageTransferState);
3176      const GLfloat *srcRow = tempImage;
3177      GLint img, row, col;
3178      if (!tempImage)
3179         return GL_FALSE;
3180      for (img = 0; img < srcDepth; img++) {
3181         GLbyte *dstRow = (GLbyte *) dstAddr
3182            + dstImageOffsets[dstZoffset + img] * texelBytes
3183            + dstYoffset * dstRowStride
3184            + dstXoffset * texelBytes;
3185         for (row = 0; row < srcHeight; row++) {
3186            GLbyte *dst = dstRow;
3187            for (col = 0; col < srcWidth; col++) {
3188               dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
3189               dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
3190               dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
3191               dst[0] = 127;
3192               srcRow += 3;
3193               dst += 4;
3194            }
3195            dstRow += dstRowStride;
3196         }
3197      }
3198      free((void *) tempImage);
3199   }
3200   return GL_TRUE;
3201}
3202
3203
3204
3205/**
3206 * Store a texture in MESA_FORMAT_SIGNED_RGBA8888 or
3207 * MESA_FORMAT_SIGNED_RGBA8888_REV
3208 */
3209static GLboolean
3210_mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
3211{
3212   const GLboolean littleEndian = _mesa_little_endian();
3213   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3214   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3215
3216   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGBA8888 ||
3217          dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV);
3218   ASSERT(texelBytes == 4);
3219
3220   if (!ctx->_ImageTransferState &&
3221       !srcPacking->SwapBytes &&
3222       dstFormat == MESA_FORMAT_SIGNED_RGBA8888 &&
3223       baseInternalFormat == GL_RGBA &&
3224      ((srcFormat == GL_RGBA && srcType == GL_BYTE && !littleEndian) ||
3225       (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
3226       /* simple memcpy path */
3227      memcpy_texture(ctx, dims,
3228                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3229                     dstRowStride,
3230                     dstImageOffsets,
3231                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3232                     srcAddr, srcPacking);
3233   }
3234   else if (!ctx->_ImageTransferState &&
3235       !srcPacking->SwapBytes &&
3236       dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV &&
3237       baseInternalFormat == GL_RGBA &&
3238      ((srcFormat == GL_RGBA && srcType == GL_BYTE && littleEndian) ||
3239       (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && !littleEndian))) {
3240      /* simple memcpy path */
3241      memcpy_texture(ctx, dims,
3242                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3243                     dstRowStride,
3244                     dstImageOffsets,
3245                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3246                     srcAddr, srcPacking);
3247   }
3248   else {
3249      /* general path */
3250      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3251                                                 baseInternalFormat,
3252                                                 baseFormat,
3253                                                 srcWidth, srcHeight, srcDepth,
3254                                                 srcFormat, srcType, srcAddr,
3255                                                 srcPacking,
3256                                                 ctx->_ImageTransferState);
3257      const GLfloat *srcRow = tempImage;
3258      GLint img, row, col;
3259      if (!tempImage)
3260         return GL_FALSE;
3261      for (img = 0; img < srcDepth; img++) {
3262         GLbyte *dstRow = (GLbyte *) dstAddr
3263            + dstImageOffsets[dstZoffset + img] * texelBytes
3264            + dstYoffset * dstRowStride
3265            + dstXoffset * texelBytes;
3266         for (row = 0; row < srcHeight; row++) {
3267            GLbyte *dst = dstRow;
3268            if (dstFormat == MESA_FORMAT_SIGNED_RGBA8888) {
3269               for (col = 0; col < srcWidth; col++) {
3270                  dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
3271                  dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
3272                  dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
3273                  dst[0] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]);
3274                  srcRow += 4;
3275                  dst += 4;
3276               }
3277            }
3278            else {
3279               for (col = 0; col < srcWidth; col++) {
3280                  dst[0] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
3281                  dst[1] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
3282                  dst[2] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
3283                  dst[3] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]);
3284                  srcRow += 4;
3285                  dst += 4;
3286               }
3287            }
3288            dstRow += dstRowStride;
3289         }
3290      }
3291      free((void *) tempImage);
3292   }
3293   return GL_TRUE;
3294}
3295
3296
3297/**
3298 * Store a combined depth/stencil texture image.
3299 */
3300static GLboolean
3301_mesa_texstore_z24_s8(TEXSTORE_PARAMS)
3302{
3303   const GLuint depthScale = 0xffffff;
3304   const GLint srcRowStride
3305      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
3306      / sizeof(GLuint);
3307   GLint img, row;
3308
3309   ASSERT(dstFormat == MESA_FORMAT_Z24_S8);
3310   ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
3311   ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
3312
3313   if (srcFormat != GL_DEPTH_COMPONENT && ctx->Pixel.DepthScale == 1.0f &&
3314       ctx->Pixel.DepthBias == 0.0f &&
3315       !srcPacking->SwapBytes) {
3316      /* simple path */
3317      memcpy_texture(ctx, dims,
3318                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3319                     dstRowStride,
3320                     dstImageOffsets,
3321                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3322                     srcAddr, srcPacking);
3323   }
3324   else if (srcFormat == GL_DEPTH_COMPONENT) {
3325      /* In case we only upload depth we need to preserve the stencil */
3326      for (img = 0; img < srcDepth; img++) {
3327	 GLuint *dstRow = (GLuint *) dstAddr
3328            + dstImageOffsets[dstZoffset + img]
3329            + dstYoffset * dstRowStride / sizeof(GLuint)
3330            + dstXoffset;
3331         const GLuint *src
3332            = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
3333                  srcWidth, srcHeight,
3334                  srcFormat, srcType,
3335                  img, 0, 0);
3336         for (row = 0; row < srcHeight; row++) {
3337            GLuint depth[MAX_WIDTH];
3338	    GLubyte stencil[MAX_WIDTH];
3339            GLint i;
3340	    GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
3341
3342	    if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
3343	       keepstencil = GL_TRUE;
3344	    }
3345            else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
3346	       keepdepth = GL_TRUE;
3347	    }
3348
3349	    if (keepdepth == GL_FALSE)
3350	       /* the 24 depth bits will be in the low position: */
3351	       _mesa_unpack_depth_span(ctx, srcWidth,
3352				       GL_UNSIGNED_INT, /* dst type */
3353				       keepstencil ? depth : dstRow, /* dst addr */
3354				       depthScale,
3355				       srcType, src, srcPacking);
3356
3357	    if (keepstencil == GL_FALSE)
3358	       /* get the 8-bit stencil values */
3359	       _mesa_unpack_stencil_span(ctx, srcWidth,
3360					 GL_UNSIGNED_BYTE, /* dst type */
3361					 stencil, /* dst addr */
3362					 srcType, src, srcPacking,
3363					 ctx->_ImageTransferState);
3364
3365	    for (i = 0; i < srcWidth; i++) {
3366	       if (keepstencil)
3367		  dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF);
3368	       else
3369		  dstRow[i] = (dstRow[i] & 0xFFFFFF00) | (stencil[i] & 0xFF);
3370	    }
3371
3372            src += srcRowStride;
3373            dstRow += dstRowStride / sizeof(GLuint);
3374         }
3375      }
3376   }
3377   return GL_TRUE;
3378}
3379
3380
3381/**
3382 * Store a combined depth/stencil texture image.
3383 */
3384static GLboolean
3385_mesa_texstore_s8_z24(TEXSTORE_PARAMS)
3386{
3387   const GLuint depthScale = 0xffffff;
3388   const GLint srcRowStride
3389      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
3390      / sizeof(GLuint);
3391   GLint img, row;
3392
3393   ASSERT(dstFormat == MESA_FORMAT_S8_Z24);
3394   ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT ||
3395          srcFormat == GL_DEPTH_COMPONENT ||
3396          srcFormat == GL_STENCIL_INDEX);
3397   ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT ||
3398          srcType == GL_UNSIGNED_INT_24_8_EXT);
3399
3400   for (img = 0; img < srcDepth; img++) {
3401      GLuint *dstRow = (GLuint *) dstAddr
3402	 + dstImageOffsets[dstZoffset + img]
3403	 + dstYoffset * dstRowStride / sizeof(GLuint)
3404	 + dstXoffset;
3405      const GLuint *src
3406	 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
3407						srcWidth, srcHeight,
3408						srcFormat, srcType,
3409						img, 0, 0);
3410      for (row = 0; row < srcHeight; row++) {
3411	 GLuint depth[MAX_WIDTH];
3412	 GLubyte stencil[MAX_WIDTH];
3413	 GLint i;
3414	 GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
3415
3416	 if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
3417	    keepstencil = GL_TRUE;
3418	 }
3419         else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
3420	    keepdepth = GL_TRUE;
3421	 }
3422
3423	 if (keepdepth == GL_FALSE)
3424	    /* the 24 depth bits will be in the low position: */
3425	    _mesa_unpack_depth_span(ctx, srcWidth,
3426				    GL_UNSIGNED_INT, /* dst type */
3427				    keepstencil ? depth : dstRow, /* dst addr */
3428				    depthScale,
3429				    srcType, src, srcPacking);
3430
3431	 if (keepstencil == GL_FALSE)
3432	    /* get the 8-bit stencil values */
3433	    _mesa_unpack_stencil_span(ctx, srcWidth,
3434				      GL_UNSIGNED_BYTE, /* dst type */
3435				      stencil, /* dst addr */
3436				      srcType, src, srcPacking,
3437				      ctx->_ImageTransferState);
3438
3439	 /* merge stencil values into depth values */
3440	 for (i = 0; i < srcWidth; i++) {
3441	    if (keepstencil)
3442	       dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
3443	    else
3444	       dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24);
3445
3446	 }
3447	 src += srcRowStride;
3448	 dstRow += dstRowStride / sizeof(GLuint);
3449      }
3450   }
3451   return GL_TRUE;
3452}
3453
3454
3455/**
3456 * Store simple 8-bit/value stencil texture data.
3457 */
3458static GLboolean
3459_mesa_texstore_s8(TEXSTORE_PARAMS)
3460{
3461   ASSERT(dstFormat == MESA_FORMAT_S8);
3462   ASSERT(srcFormat == GL_STENCIL_INDEX);
3463
3464   if (!ctx->_ImageTransferState &&
3465       !srcPacking->SwapBytes &&
3466       baseInternalFormat == srcFormat &&
3467       srcType == GL_UNSIGNED_BYTE) {
3468      /* simple memcpy path */
3469      memcpy_texture(ctx, dims,
3470                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3471                     dstRowStride,
3472                     dstImageOffsets,
3473                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3474                     srcAddr, srcPacking);
3475   }
3476   else {
3477      const GLint srcRowStride
3478	 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
3479	 / sizeof(GLuint);
3480      GLint img, row;
3481
3482      for (img = 0; img < srcDepth; img++) {
3483         GLubyte *dstRow = (GLubyte *) dstAddr
3484            + dstImageOffsets[dstZoffset + img]
3485            + dstYoffset * dstRowStride / sizeof(GLuint)
3486            + dstXoffset;
3487         const GLuint *src
3488            = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
3489                                                   srcWidth, srcHeight,
3490                                                   srcFormat, srcType,
3491                                                   img, 0, 0);
3492         for (row = 0; row < srcHeight; row++) {
3493            GLubyte stencil[MAX_WIDTH];
3494            GLint i;
3495
3496            /* get the 8-bit stencil values */
3497            _mesa_unpack_stencil_span(ctx, srcWidth,
3498                                      GL_UNSIGNED_BYTE, /* dst type */
3499                                      stencil, /* dst addr */
3500                                      srcType, src, srcPacking,
3501                                      ctx->_ImageTransferState);
3502            /* merge stencil values into depth values */
3503            for (i = 0; i < srcWidth; i++)
3504               dstRow[i] = stencil[i];
3505
3506            src += srcRowStride;
3507            dstRow += dstRowStride / sizeof(GLubyte);
3508         }
3509      }
3510
3511   }
3512
3513   return GL_TRUE;
3514}
3515
3516
3517/**
3518 * Store an image in any of the formats:
3519 *   _mesa_texformat_rgba_float32
3520 *   _mesa_texformat_rgb_float32
3521 *   _mesa_texformat_alpha_float32
3522 *   _mesa_texformat_luminance_float32
3523 *   _mesa_texformat_luminance_alpha_float32
3524 *   _mesa_texformat_intensity_float32
3525 */
3526static GLboolean
3527_mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
3528{
3529   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3530   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3531   const GLint components = _mesa_components_in_format(baseFormat);
3532
3533   ASSERT(dstFormat == MESA_FORMAT_RGBA_FLOAT32 ||
3534          dstFormat == MESA_FORMAT_RGB_FLOAT32 ||
3535          dstFormat == MESA_FORMAT_ALPHA_FLOAT32 ||
3536          dstFormat == MESA_FORMAT_LUMINANCE_FLOAT32 ||
3537          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32 ||
3538          dstFormat == MESA_FORMAT_INTENSITY_FLOAT32 ||
3539          dstFormat == MESA_FORMAT_R_FLOAT32 ||
3540          dstFormat == MESA_FORMAT_RG_FLOAT32);
3541   ASSERT(baseInternalFormat == GL_RGBA ||
3542          baseInternalFormat == GL_RGB ||
3543          baseInternalFormat == GL_ALPHA ||
3544          baseInternalFormat == GL_LUMINANCE ||
3545          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3546          baseInternalFormat == GL_INTENSITY ||
3547          baseInternalFormat == GL_RED ||
3548          baseInternalFormat == GL_RG);
3549   ASSERT(texelBytes == components * sizeof(GLfloat));
3550
3551   if (!ctx->_ImageTransferState &&
3552       !srcPacking->SwapBytes &&
3553       baseInternalFormat == srcFormat &&
3554       srcType == GL_FLOAT) {
3555      /* simple memcpy path */
3556      memcpy_texture(ctx, dims,
3557                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3558                     dstRowStride,
3559                     dstImageOffsets,
3560                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3561                     srcAddr, srcPacking);
3562   }
3563   else {
3564      /* general path */
3565      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3566                                                 baseInternalFormat,
3567                                                 baseFormat,
3568                                                 srcWidth, srcHeight, srcDepth,
3569                                                 srcFormat, srcType, srcAddr,
3570                                                 srcPacking,
3571                                                 ctx->_ImageTransferState);
3572      const GLfloat *srcRow = tempImage;
3573      GLint bytesPerRow;
3574      GLint img, row;
3575      if (!tempImage)
3576         return GL_FALSE;
3577      bytesPerRow = srcWidth * components * sizeof(GLfloat);
3578      for (img = 0; img < srcDepth; img++) {
3579         GLubyte *dstRow = (GLubyte *) dstAddr
3580            + dstImageOffsets[dstZoffset + img] * texelBytes
3581            + dstYoffset * dstRowStride
3582            + dstXoffset * texelBytes;
3583         for (row = 0; row < srcHeight; row++) {
3584            memcpy(dstRow, srcRow, bytesPerRow);
3585            dstRow += dstRowStride;
3586            srcRow += srcWidth * components;
3587         }
3588      }
3589
3590      free((void *) tempImage);
3591   }
3592   return GL_TRUE;
3593}
3594
3595
3596
3597/**
3598 * As above, but store 16-bit floats.
3599 */
3600static GLboolean
3601_mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
3602{
3603   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3604   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3605   const GLint components = _mesa_components_in_format(baseFormat);
3606
3607   ASSERT(dstFormat == MESA_FORMAT_RGBA_FLOAT16 ||
3608          dstFormat == MESA_FORMAT_RGB_FLOAT16 ||
3609          dstFormat == MESA_FORMAT_ALPHA_FLOAT16 ||
3610          dstFormat == MESA_FORMAT_LUMINANCE_FLOAT16 ||
3611          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16 ||
3612          dstFormat == MESA_FORMAT_INTENSITY_FLOAT16 ||
3613          dstFormat == MESA_FORMAT_R_FLOAT16 ||
3614          dstFormat == MESA_FORMAT_RG_FLOAT16);
3615   ASSERT(baseInternalFormat == GL_RGBA ||
3616          baseInternalFormat == GL_RGB ||
3617          baseInternalFormat == GL_ALPHA ||
3618          baseInternalFormat == GL_LUMINANCE ||
3619          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3620          baseInternalFormat == GL_INTENSITY ||
3621          baseInternalFormat == GL_RED ||
3622          baseInternalFormat == GL_RG);
3623   ASSERT(texelBytes == components * sizeof(GLhalfARB));
3624
3625   if (!ctx->_ImageTransferState &&
3626       !srcPacking->SwapBytes &&
3627       baseInternalFormat == srcFormat &&
3628       srcType == GL_HALF_FLOAT_ARB) {
3629      /* simple memcpy path */
3630      memcpy_texture(ctx, dims,
3631                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3632                     dstRowStride,
3633                     dstImageOffsets,
3634                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3635                     srcAddr, srcPacking);
3636   }
3637   else {
3638      /* general path */
3639      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3640                                                 baseInternalFormat,
3641                                                 baseFormat,
3642                                                 srcWidth, srcHeight, srcDepth,
3643                                                 srcFormat, srcType, srcAddr,
3644                                                 srcPacking,
3645                                                 ctx->_ImageTransferState);
3646      const GLfloat *src = tempImage;
3647      GLint img, row;
3648      if (!tempImage)
3649         return GL_FALSE;
3650      for (img = 0; img < srcDepth; img++) {
3651         GLubyte *dstRow = (GLubyte *) dstAddr
3652            + dstImageOffsets[dstZoffset + img] * texelBytes
3653            + dstYoffset * dstRowStride
3654            + dstXoffset * texelBytes;
3655         for (row = 0; row < srcHeight; row++) {
3656            GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
3657            GLint i;
3658            for (i = 0; i < srcWidth * components; i++) {
3659               dstTexel[i] = _mesa_float_to_half(src[i]);
3660            }
3661            dstRow += dstRowStride;
3662            src += srcWidth * components;
3663         }
3664      }
3665
3666      free((void *) tempImage);
3667   }
3668   return GL_TRUE;
3669}
3670
3671
3672/* non-normalized, signed int8 */
3673static GLboolean
3674_mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
3675{
3676   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3677   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3678   const GLint components = _mesa_components_in_format(baseFormat);
3679
3680   ASSERT(dstFormat == MESA_FORMAT_RGBA_INT8);
3681   ASSERT(baseInternalFormat == GL_RGBA ||
3682          baseInternalFormat == GL_RGB ||
3683          baseInternalFormat == GL_ALPHA ||
3684          baseInternalFormat == GL_LUMINANCE ||
3685          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3686          baseInternalFormat == GL_INTENSITY);
3687   ASSERT(texelBytes == components * sizeof(GLbyte));
3688
3689   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3690    * to integer formats.
3691    */
3692   if (!srcPacking->SwapBytes &&
3693       baseInternalFormat == srcFormat &&
3694       srcType == GL_BYTE) {
3695      /* simple memcpy path */
3696      memcpy_texture(ctx, dims,
3697                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3698                     dstRowStride,
3699                     dstImageOffsets,
3700                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3701                     srcAddr, srcPacking);
3702   }
3703   else {
3704      /* general path */
3705      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3706                                                 baseInternalFormat,
3707                                                 baseFormat,
3708                                                 srcWidth, srcHeight, srcDepth,
3709                                                 srcFormat, srcType, srcAddr,
3710                                                 srcPacking, 0x0);
3711      const GLfloat *src = tempImage;
3712      GLint img, row;
3713      if (!tempImage)
3714         return GL_FALSE;
3715      for (img = 0; img < srcDepth; img++) {
3716         GLubyte *dstRow = (GLubyte *) dstAddr
3717            + dstImageOffsets[dstZoffset + img] * texelBytes
3718            + dstYoffset * dstRowStride
3719            + dstXoffset * texelBytes;
3720         for (row = 0; row < srcHeight; row++) {
3721            GLbyte *dstTexel = (GLbyte *) dstRow;
3722            GLint i;
3723            for (i = 0; i < srcWidth * components; i++) {
3724               dstTexel[i] = (GLbyte) src[i];
3725            }
3726            dstRow += dstRowStride;
3727            src += srcWidth * components;
3728         }
3729      }
3730
3731      free((void *) tempImage);
3732   }
3733   return GL_TRUE;
3734}
3735
3736
3737/* non-normalized, signed int16 */
3738static GLboolean
3739_mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
3740{
3741   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3742   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3743   const GLint components = _mesa_components_in_format(baseFormat);
3744
3745   ASSERT(dstFormat == MESA_FORMAT_RGBA_INT16);
3746   ASSERT(baseInternalFormat == GL_RGBA ||
3747          baseInternalFormat == GL_RGB ||
3748          baseInternalFormat == GL_ALPHA ||
3749          baseInternalFormat == GL_LUMINANCE ||
3750          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3751          baseInternalFormat == GL_INTENSITY);
3752   ASSERT(texelBytes == components * sizeof(GLshort));
3753
3754   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3755    * to integer formats.
3756    */
3757   if (!srcPacking->SwapBytes &&
3758       baseInternalFormat == srcFormat &&
3759       srcType == GL_SHORT) {
3760      /* simple memcpy path */
3761      memcpy_texture(ctx, dims,
3762                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3763                     dstRowStride,
3764                     dstImageOffsets,
3765                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3766                     srcAddr, srcPacking);
3767   }
3768   else {
3769      /* general path */
3770      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3771                                                 baseInternalFormat,
3772                                                 baseFormat,
3773                                                 srcWidth, srcHeight, srcDepth,
3774                                                 srcFormat, srcType, srcAddr,
3775                                                 srcPacking, 0x0);
3776      const GLfloat *src = tempImage;
3777      GLint img, row;
3778      if (!tempImage)
3779         return GL_FALSE;
3780      for (img = 0; img < srcDepth; img++) {
3781         GLubyte *dstRow = (GLubyte *) dstAddr
3782            + dstImageOffsets[dstZoffset + img] * texelBytes
3783            + dstYoffset * dstRowStride
3784            + dstXoffset * texelBytes;
3785         for (row = 0; row < srcHeight; row++) {
3786            GLshort *dstTexel = (GLshort *) dstRow;
3787            GLint i;
3788            for (i = 0; i < srcWidth * components; i++) {
3789               dstTexel[i] = (GLint) src[i];
3790            }
3791            dstRow += dstRowStride;
3792            src += srcWidth * components;
3793         }
3794      }
3795
3796      free((void *) tempImage);
3797   }
3798   return GL_TRUE;
3799}
3800
3801
3802/* non-normalized, signed int32 */
3803static GLboolean
3804_mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
3805{
3806   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3807   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3808   const GLint components = _mesa_components_in_format(baseFormat);
3809
3810   ASSERT(dstFormat == MESA_FORMAT_RGBA_INT32);
3811   ASSERT(baseInternalFormat == GL_RGBA ||
3812          baseInternalFormat == GL_RGB ||
3813          baseInternalFormat == GL_ALPHA ||
3814          baseInternalFormat == GL_LUMINANCE ||
3815          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3816          baseInternalFormat == GL_INTENSITY);
3817   ASSERT(texelBytes == components * sizeof(GLint));
3818
3819   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3820    * to integer formats.
3821    */
3822   if (!srcPacking->SwapBytes &&
3823       baseInternalFormat == srcFormat &&
3824       srcType == GL_INT) {
3825      /* simple memcpy path */
3826      memcpy_texture(ctx, dims,
3827                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3828                     dstRowStride,
3829                     dstImageOffsets,
3830                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3831                     srcAddr, srcPacking);
3832   }
3833   else {
3834      /* general path */
3835      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3836                                                 baseInternalFormat,
3837                                                 baseFormat,
3838                                                 srcWidth, srcHeight, srcDepth,
3839                                                 srcFormat, srcType, srcAddr,
3840                                                 srcPacking, 0x0);
3841      const GLfloat *src = tempImage;
3842      GLint img, row;
3843      if (!tempImage)
3844         return GL_FALSE;
3845      for (img = 0; img < srcDepth; img++) {
3846         GLubyte *dstRow = (GLubyte *) dstAddr
3847            + dstImageOffsets[dstZoffset + img] * texelBytes
3848            + dstYoffset * dstRowStride
3849            + dstXoffset * texelBytes;
3850         for (row = 0; row < srcHeight; row++) {
3851            GLint *dstTexel = (GLint *) dstRow;
3852            GLint i;
3853            for (i = 0; i < srcWidth * components; i++) {
3854               dstTexel[i] = (GLint) src[i];
3855            }
3856            dstRow += dstRowStride;
3857            src += srcWidth * components;
3858         }
3859      }
3860
3861      free((void *) tempImage);
3862   }
3863   return GL_TRUE;
3864}
3865
3866
3867/* non-normalized, unsigned int8 */
3868static GLboolean
3869_mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
3870{
3871   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3872   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3873   const GLint components = _mesa_components_in_format(baseFormat);
3874
3875   ASSERT(dstFormat == MESA_FORMAT_RGBA_UINT8);
3876   ASSERT(baseInternalFormat == GL_RGBA ||
3877          baseInternalFormat == GL_RGB ||
3878          baseInternalFormat == GL_ALPHA ||
3879          baseInternalFormat == GL_LUMINANCE ||
3880          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3881          baseInternalFormat == GL_INTENSITY);
3882   ASSERT(texelBytes == components * sizeof(GLubyte));
3883
3884   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3885    * to integer formats.
3886    */
3887   if (!srcPacking->SwapBytes &&
3888       baseInternalFormat == srcFormat &&
3889       srcType == GL_UNSIGNED_BYTE) {
3890      /* simple memcpy path */
3891      memcpy_texture(ctx, dims,
3892                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3893                     dstRowStride,
3894                     dstImageOffsets,
3895                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3896                     srcAddr, srcPacking);
3897   }
3898   else {
3899      /* general path */
3900      const GLuint *tempImage =
3901         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
3902                              srcWidth, srcHeight, srcDepth,
3903                              srcFormat, srcType, srcAddr, srcPacking);
3904      const GLuint *src = tempImage;
3905      GLint img, row;
3906      if (!tempImage)
3907         return GL_FALSE;
3908      for (img = 0; img < srcDepth; img++) {
3909         GLubyte *dstRow = (GLubyte *) dstAddr
3910            + dstImageOffsets[dstZoffset + img] * texelBytes
3911            + dstYoffset * dstRowStride
3912            + dstXoffset * texelBytes;
3913         for (row = 0; row < srcHeight; row++) {
3914            GLubyte *dstTexel = (GLubyte *) dstRow;
3915            GLint i;
3916            for (i = 0; i < srcWidth * components; i++) {
3917               dstTexel[i] = (GLubyte) CLAMP(src[i], 0, 0xff);
3918            }
3919            dstRow += dstRowStride;
3920            src += srcWidth * components;
3921         }
3922      }
3923
3924      free((void *) tempImage);
3925   }
3926   return GL_TRUE;
3927}
3928
3929
3930/* non-normalized, unsigned int16 */
3931static GLboolean
3932_mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
3933{
3934   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3935   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3936   const GLint components = _mesa_components_in_format(baseFormat);
3937
3938   ASSERT(dstFormat == MESA_FORMAT_RGBA_UINT16);
3939   ASSERT(baseInternalFormat == GL_RGBA ||
3940          baseInternalFormat == GL_RGB ||
3941          baseInternalFormat == GL_ALPHA ||
3942          baseInternalFormat == GL_LUMINANCE ||
3943          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3944          baseInternalFormat == GL_INTENSITY);
3945   ASSERT(texelBytes == components * sizeof(GLushort));
3946
3947   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3948    * to integer formats.
3949    */
3950   if (!srcPacking->SwapBytes &&
3951       baseInternalFormat == srcFormat &&
3952       srcType == GL_UNSIGNED_SHORT) {
3953      /* simple memcpy path */
3954      memcpy_texture(ctx, dims,
3955                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
3956                     dstRowStride,
3957                     dstImageOffsets,
3958                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3959                     srcAddr, srcPacking);
3960   }
3961   else {
3962      /* general path */
3963      const GLuint *tempImage =
3964         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
3965                              srcWidth, srcHeight, srcDepth,
3966                              srcFormat, srcType, srcAddr, srcPacking);
3967      const GLuint *src = tempImage;
3968      GLint img, row;
3969      if (!tempImage)
3970         return GL_FALSE;
3971      for (img = 0; img < srcDepth; img++) {
3972         GLubyte *dstRow = (GLubyte *) dstAddr
3973            + dstImageOffsets[dstZoffset + img] * texelBytes
3974            + dstYoffset * dstRowStride
3975            + dstXoffset * texelBytes;
3976         for (row = 0; row < srcHeight; row++) {
3977            GLushort *dstTexel = (GLushort *) dstRow;
3978            GLint i;
3979            for (i = 0; i < srcWidth * components; i++) {
3980               dstTexel[i] = (GLushort) CLAMP(src[i], 0, 0xffff);
3981            }
3982            dstRow += dstRowStride;
3983            src += srcWidth * components;
3984         }
3985      }
3986
3987      free((void *) tempImage);
3988   }
3989   return GL_TRUE;
3990}
3991
3992
3993/* non-normalized, unsigned int32 */
3994static GLboolean
3995_mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
3996{
3997   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
3998   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3999   const GLint components = _mesa_components_in_format(baseFormat);
4000
4001   ASSERT(dstFormat == MESA_FORMAT_RGBA_UINT32);
4002   ASSERT(baseInternalFormat == GL_RGBA ||
4003          baseInternalFormat == GL_RGB ||
4004          baseInternalFormat == GL_ALPHA ||
4005          baseInternalFormat == GL_LUMINANCE ||
4006          baseInternalFormat == GL_LUMINANCE_ALPHA ||
4007          baseInternalFormat == GL_INTENSITY);
4008   ASSERT(texelBytes == components * sizeof(GLuint));
4009
4010   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
4011    * to integer formats.
4012    */
4013   if (!srcPacking->SwapBytes &&
4014       baseInternalFormat == srcFormat &&
4015       srcType == GL_UNSIGNED_INT) {
4016      /* simple memcpy path */
4017      memcpy_texture(ctx, dims,
4018                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
4019                     dstRowStride,
4020                     dstImageOffsets,
4021                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
4022                     srcAddr, srcPacking);
4023   }
4024   else {
4025      /* general path */
4026      const GLuint *tempImage =
4027         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
4028                              srcWidth, srcHeight, srcDepth,
4029                              srcFormat, srcType, srcAddr, srcPacking);
4030      const GLuint *src = tempImage;
4031      GLint img, row;
4032      if (!tempImage)
4033         return GL_FALSE;
4034      for (img = 0; img < srcDepth; img++) {
4035         GLubyte *dstRow = (GLubyte *) dstAddr
4036            + dstImageOffsets[dstZoffset + img] * texelBytes
4037            + dstYoffset * dstRowStride
4038            + dstXoffset * texelBytes;
4039         for (row = 0; row < srcHeight; row++) {
4040            GLuint *dstTexel = (GLuint *) dstRow;
4041            GLint i;
4042            for (i = 0; i < srcWidth * components; i++) {
4043               dstTexel[i] = src[i];
4044            }
4045            dstRow += dstRowStride;
4046            src += srcWidth * components;
4047         }
4048      }
4049
4050      free((void *) tempImage);
4051   }
4052   return GL_TRUE;
4053}
4054
4055
4056
4057
4058#if FEATURE_EXT_texture_sRGB
4059static GLboolean
4060_mesa_texstore_srgb8(TEXSTORE_PARAMS)
4061{
4062   gl_format newDstFormat;
4063   GLboolean k;
4064
4065   ASSERT(dstFormat == MESA_FORMAT_SRGB8);
4066
4067   /* reuse normal rgb texstore code */
4068   newDstFormat = MESA_FORMAT_RGB888;
4069
4070   k = _mesa_texstore_rgb888(ctx, dims, baseInternalFormat,
4071                             newDstFormat, dstAddr,
4072                             dstXoffset, dstYoffset, dstZoffset,
4073                             dstRowStride, dstImageOffsets,
4074                             srcWidth, srcHeight, srcDepth,
4075                             srcFormat, srcType,
4076                             srcAddr, srcPacking);
4077   return k;
4078}
4079
4080
4081static GLboolean
4082_mesa_texstore_srgba8(TEXSTORE_PARAMS)
4083{
4084   gl_format newDstFormat;
4085   GLboolean k;
4086
4087   ASSERT(dstFormat == MESA_FORMAT_SRGBA8);
4088
4089   /* reuse normal rgba texstore code */
4090   newDstFormat = MESA_FORMAT_RGBA8888;
4091   k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
4092                               newDstFormat, dstAddr,
4093                               dstXoffset, dstYoffset, dstZoffset,
4094                               dstRowStride, dstImageOffsets,
4095                               srcWidth, srcHeight, srcDepth,
4096                               srcFormat, srcType,
4097                               srcAddr, srcPacking);
4098   return k;
4099}
4100
4101
4102static GLboolean
4103_mesa_texstore_sargb8(TEXSTORE_PARAMS)
4104{
4105   gl_format newDstFormat;
4106   GLboolean k;
4107
4108   ASSERT(dstFormat == MESA_FORMAT_SARGB8);
4109
4110   /* reuse normal rgba texstore code */
4111   newDstFormat = MESA_FORMAT_ARGB8888;
4112
4113   k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
4114                               newDstFormat, dstAddr,
4115                               dstXoffset, dstYoffset, dstZoffset,
4116                               dstRowStride, dstImageOffsets,
4117                               srcWidth, srcHeight, srcDepth,
4118                               srcFormat, srcType,
4119                               srcAddr, srcPacking);
4120   return k;
4121}
4122
4123
4124static GLboolean
4125_mesa_texstore_sl8(TEXSTORE_PARAMS)
4126{
4127   gl_format newDstFormat;
4128   GLboolean k;
4129
4130   ASSERT(dstFormat == MESA_FORMAT_SL8);
4131
4132   newDstFormat = MESA_FORMAT_L8;
4133
4134   /* _mesa_textore_a8 handles luminance8 too */
4135   k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat,
4136                         newDstFormat, dstAddr,
4137                         dstXoffset, dstYoffset, dstZoffset,
4138                         dstRowStride, dstImageOffsets,
4139                         srcWidth, srcHeight, srcDepth,
4140                         srcFormat, srcType,
4141                         srcAddr, srcPacking);
4142   return k;
4143}
4144
4145
4146static GLboolean
4147_mesa_texstore_sla8(TEXSTORE_PARAMS)
4148{
4149   gl_format newDstFormat;
4150   GLboolean k;
4151
4152   ASSERT(dstFormat == MESA_FORMAT_SLA8);
4153
4154   /* reuse normal luminance/alpha texstore code */
4155   newDstFormat = MESA_FORMAT_AL88;
4156
4157   k = _mesa_texstore_unorm88(ctx, dims, baseInternalFormat,
4158			      newDstFormat, dstAddr,
4159			      dstXoffset, dstYoffset, dstZoffset,
4160			      dstRowStride, dstImageOffsets,
4161			      srcWidth, srcHeight, srcDepth,
4162			      srcFormat, srcType,
4163			      srcAddr, srcPacking);
4164   return k;
4165}
4166
4167#else
4168
4169/* these are used only in texstore_funcs[] below */
4170#define _mesa_texstore_srgb8 NULL
4171#define _mesa_texstore_srgba8 NULL
4172#define _mesa_texstore_sargb8 NULL
4173#define _mesa_texstore_sl8 NULL
4174#define _mesa_texstore_sla8 NULL
4175
4176#endif /* FEATURE_EXT_texture_sRGB */
4177
4178
4179
4180
4181/**
4182 * Table mapping MESA_FORMAT_* to _mesa_texstore_*()
4183 * XXX this is somewhat temporary.
4184 */
4185static const struct {
4186   gl_format Name;
4187   StoreTexImageFunc Store;
4188}
4189texstore_funcs[MESA_FORMAT_COUNT] =
4190{
4191   { MESA_FORMAT_NONE, NULL },
4192   { MESA_FORMAT_RGBA8888, _mesa_texstore_rgba8888 },
4193   { MESA_FORMAT_RGBA8888_REV, _mesa_texstore_rgba8888 },
4194   { MESA_FORMAT_ARGB8888, _mesa_texstore_argb8888 },
4195   { MESA_FORMAT_ARGB8888_REV, _mesa_texstore_argb8888 },
4196   { MESA_FORMAT_XRGB8888, _mesa_texstore_argb8888 },
4197   { MESA_FORMAT_XRGB8888_REV, _mesa_texstore_argb8888 },
4198   { MESA_FORMAT_RGB888, _mesa_texstore_rgb888 },
4199   { MESA_FORMAT_BGR888, _mesa_texstore_bgr888 },
4200   { MESA_FORMAT_RGB565, _mesa_texstore_rgb565 },
4201   { MESA_FORMAT_RGB565_REV, _mesa_texstore_rgb565 },
4202   { MESA_FORMAT_ARGB4444, _mesa_texstore_argb4444 },
4203   { MESA_FORMAT_ARGB4444_REV, _mesa_texstore_argb4444 },
4204   { MESA_FORMAT_RGBA5551, _mesa_texstore_rgba5551 },
4205   { MESA_FORMAT_ARGB1555, _mesa_texstore_argb1555 },
4206   { MESA_FORMAT_ARGB1555_REV, _mesa_texstore_argb1555 },
4207   { MESA_FORMAT_AL44, _mesa_texstore_unorm44 },
4208   { MESA_FORMAT_AL88, _mesa_texstore_unorm88 },
4209   { MESA_FORMAT_AL88_REV, _mesa_texstore_unorm88 },
4210   { MESA_FORMAT_AL1616, _mesa_texstore_unorm1616 },
4211   { MESA_FORMAT_AL1616_REV, _mesa_texstore_unorm1616 },
4212   { MESA_FORMAT_RGB332, _mesa_texstore_rgb332 },
4213   { MESA_FORMAT_A8, _mesa_texstore_unorm8 },
4214   { MESA_FORMAT_A16, _mesa_texstore_unorm16 },
4215   { MESA_FORMAT_L8, _mesa_texstore_unorm8 },
4216   { MESA_FORMAT_L16, _mesa_texstore_unorm16 },
4217   { MESA_FORMAT_I8, _mesa_texstore_unorm8 },
4218   { MESA_FORMAT_I16, _mesa_texstore_unorm16 },
4219   { MESA_FORMAT_CI8, _mesa_texstore_ci8 },
4220   { MESA_FORMAT_YCBCR, _mesa_texstore_ycbcr },
4221   { MESA_FORMAT_YCBCR_REV, _mesa_texstore_ycbcr },
4222   { MESA_FORMAT_R8, _mesa_texstore_unorm8 },
4223   { MESA_FORMAT_RG88, _mesa_texstore_unorm88 },
4224   { MESA_FORMAT_RG88_REV, _mesa_texstore_unorm88 },
4225   { MESA_FORMAT_R16, _mesa_texstore_unorm16 },
4226   { MESA_FORMAT_RG1616, _mesa_texstore_unorm1616 },
4227   { MESA_FORMAT_RG1616_REV, _mesa_texstore_unorm1616 },
4228   { MESA_FORMAT_ARGB2101010, _mesa_texstore_argb2101010 },
4229   { MESA_FORMAT_Z24_S8, _mesa_texstore_z24_s8 },
4230   { MESA_FORMAT_S8_Z24, _mesa_texstore_s8_z24 },
4231   { MESA_FORMAT_Z16, _mesa_texstore_z16 },
4232   { MESA_FORMAT_X8_Z24, _mesa_texstore_x8_z24 },
4233   { MESA_FORMAT_Z24_X8, _mesa_texstore_z24_x8 },
4234   { MESA_FORMAT_Z32, _mesa_texstore_z32 },
4235   { MESA_FORMAT_S8, _mesa_texstore_s8 },
4236   { MESA_FORMAT_SRGB8, _mesa_texstore_srgb8 },
4237   { MESA_FORMAT_SRGBA8, _mesa_texstore_srgba8 },
4238   { MESA_FORMAT_SARGB8, _mesa_texstore_sargb8 },
4239   { MESA_FORMAT_SL8, _mesa_texstore_sl8 },
4240   { MESA_FORMAT_SLA8, _mesa_texstore_sla8 },
4241   { MESA_FORMAT_SRGB_DXT1, _mesa_texstore_rgb_dxt1 },
4242   { MESA_FORMAT_SRGBA_DXT1, _mesa_texstore_rgba_dxt1 },
4243   { MESA_FORMAT_SRGBA_DXT3, _mesa_texstore_rgba_dxt3 },
4244   { MESA_FORMAT_SRGBA_DXT5, _mesa_texstore_rgba_dxt5 },
4245   { MESA_FORMAT_RGB_FXT1, _mesa_texstore_rgb_fxt1 },
4246   { MESA_FORMAT_RGBA_FXT1, _mesa_texstore_rgba_fxt1 },
4247   { MESA_FORMAT_RGB_DXT1, _mesa_texstore_rgb_dxt1 },
4248   { MESA_FORMAT_RGBA_DXT1, _mesa_texstore_rgba_dxt1 },
4249   { MESA_FORMAT_RGBA_DXT3, _mesa_texstore_rgba_dxt3 },
4250   { MESA_FORMAT_RGBA_DXT5, _mesa_texstore_rgba_dxt5 },
4251   { MESA_FORMAT_RGBA_FLOAT32, _mesa_texstore_rgba_float32 },
4252   { MESA_FORMAT_RGBA_FLOAT16, _mesa_texstore_rgba_float16 },
4253   { MESA_FORMAT_RGB_FLOAT32, _mesa_texstore_rgba_float32 },
4254   { MESA_FORMAT_RGB_FLOAT16, _mesa_texstore_rgba_float16 },
4255   { MESA_FORMAT_ALPHA_FLOAT32, _mesa_texstore_rgba_float32 },
4256   { MESA_FORMAT_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
4257   { MESA_FORMAT_LUMINANCE_FLOAT32, _mesa_texstore_rgba_float32 },
4258   { MESA_FORMAT_LUMINANCE_FLOAT16, _mesa_texstore_rgba_float16 },
4259   { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, _mesa_texstore_rgba_float32 },
4260   { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
4261   { MESA_FORMAT_INTENSITY_FLOAT32, _mesa_texstore_rgba_float32 },
4262   { MESA_FORMAT_INTENSITY_FLOAT16, _mesa_texstore_rgba_float16 },
4263   { MESA_FORMAT_R_FLOAT32, _mesa_texstore_rgba_float32 },
4264   { MESA_FORMAT_R_FLOAT16, _mesa_texstore_rgba_float16 },
4265   { MESA_FORMAT_RG_FLOAT32, _mesa_texstore_rgba_float32 },
4266   { MESA_FORMAT_RG_FLOAT16, _mesa_texstore_rgba_float16 },
4267
4268   { MESA_FORMAT_RGBA_INT8, _mesa_texstore_rgba_int8 },
4269   { MESA_FORMAT_RGBA_INT16, _mesa_texstore_rgba_int16 },
4270   { MESA_FORMAT_RGBA_INT32, _mesa_texstore_rgba_int32 },
4271   { MESA_FORMAT_RGBA_UINT8, _mesa_texstore_rgba_uint8 },
4272   { MESA_FORMAT_RGBA_UINT16, _mesa_texstore_rgba_uint16 },
4273   { MESA_FORMAT_RGBA_UINT32, _mesa_texstore_rgba_uint32 },
4274
4275   { MESA_FORMAT_DUDV8, _mesa_texstore_dudv8 },
4276
4277   { MESA_FORMAT_SIGNED_R8, _mesa_texstore_snorm8 },
4278   { MESA_FORMAT_SIGNED_RG88_REV, _mesa_texstore_snorm88 },
4279   { MESA_FORMAT_SIGNED_RGBX8888, _mesa_texstore_signed_rgbx8888 },
4280
4281   { MESA_FORMAT_SIGNED_RGBA8888, _mesa_texstore_signed_rgba8888 },
4282   { MESA_FORMAT_SIGNED_RGBA8888_REV, _mesa_texstore_signed_rgba8888 },
4283
4284   { MESA_FORMAT_SIGNED_R16, _mesa_texstore_snorm16 },
4285   { MESA_FORMAT_SIGNED_GR1616, _mesa_texstore_snorm1616 },
4286   { MESA_FORMAT_SIGNED_RGB_16, _mesa_texstore_signed_rgba_16 },
4287   { MESA_FORMAT_SIGNED_RGBA_16, _mesa_texstore_signed_rgba_16 },
4288   { MESA_FORMAT_RGBA_16, _mesa_texstore_rgba_16 },
4289
4290   { MESA_FORMAT_RED_RGTC1, _mesa_texstore_red_rgtc1 },
4291   { MESA_FORMAT_SIGNED_RED_RGTC1, _mesa_texstore_signed_red_rgtc1 },
4292   { MESA_FORMAT_RG_RGTC2, _mesa_texstore_rg_rgtc2 },
4293   { MESA_FORMAT_SIGNED_RG_RGTC2, _mesa_texstore_signed_rg_rgtc2 },
4294
4295   /* Re-use the R/RG texstore functions.
4296    * The code is generic enough to handle LATC too. */
4297   { MESA_FORMAT_L_LATC1, _mesa_texstore_red_rgtc1 },
4298   { MESA_FORMAT_SIGNED_L_LATC1, _mesa_texstore_signed_red_rgtc1 },
4299   { MESA_FORMAT_LA_LATC2, _mesa_texstore_rg_rgtc2 },
4300   { MESA_FORMAT_SIGNED_LA_LATC2, _mesa_texstore_signed_rg_rgtc2 },
4301
4302   { MESA_FORMAT_SIGNED_A8, _mesa_texstore_snorm8 },
4303   { MESA_FORMAT_SIGNED_L8, _mesa_texstore_snorm8 },
4304   { MESA_FORMAT_SIGNED_AL88, _mesa_texstore_snorm88 },
4305   { MESA_FORMAT_SIGNED_I8, _mesa_texstore_snorm8 },
4306
4307   { MESA_FORMAT_SIGNED_A16, _mesa_texstore_snorm16 },
4308   { MESA_FORMAT_SIGNED_L16, _mesa_texstore_snorm16 },
4309   { MESA_FORMAT_SIGNED_AL1616, _mesa_texstore_snorm1616 },
4310   { MESA_FORMAT_SIGNED_I16, _mesa_texstore_snorm16 },
4311};
4312
4313
4314static GLboolean
4315_mesa_texstore_null(TEXSTORE_PARAMS)
4316{
4317   (void) ctx; (void) dims;
4318   (void) baseInternalFormat;
4319   (void) dstFormat;
4320   (void) dstAddr;
4321   (void) dstXoffset; (void) dstYoffset; (void) dstZoffset;
4322   (void) dstRowStride; (void) dstImageOffsets;
4323   (void) srcWidth; (void) srcHeight; (void) srcDepth;
4324   (void) srcFormat; (void) srcType;
4325   (void) srcAddr;
4326   (void) srcPacking;
4327
4328   /* should never happen */
4329   _mesa_problem(NULL, "_mesa_texstore_null() is called");
4330   return GL_FALSE;
4331}
4332
4333
4334/**
4335 * Return the StoreTexImageFunc pointer to store an image in the given format.
4336 */
4337static StoreTexImageFunc
4338_mesa_get_texstore_func(gl_format format)
4339{
4340#ifdef DEBUG
4341   GLuint i;
4342   for (i = 0; i < MESA_FORMAT_COUNT; i++) {
4343      ASSERT(texstore_funcs[i].Name == i);
4344   }
4345#endif
4346   ASSERT(texstore_funcs[format].Name == format);
4347
4348   if (texstore_funcs[format].Store)
4349      return texstore_funcs[format].Store;
4350   else
4351      return _mesa_texstore_null;
4352}
4353
4354
4355/**
4356 * Store user data into texture memory.
4357 * Called via glTex[Sub]Image1/2/3D()
4358 */
4359GLboolean
4360_mesa_texstore(TEXSTORE_PARAMS)
4361{
4362   StoreTexImageFunc storeImage;
4363   GLboolean success;
4364
4365   storeImage = _mesa_get_texstore_func(dstFormat);
4366
4367   success = storeImage(ctx, dims, baseInternalFormat,
4368                        dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
4369                        dstRowStride, dstImageOffsets,
4370                        srcWidth, srcHeight, srcDepth,
4371                        srcFormat, srcType, srcAddr, srcPacking);
4372   return success;
4373}
4374
4375
4376/** Return texture size in bytes */
4377static GLuint
4378texture_size(const struct gl_texture_image *texImage)
4379{
4380   GLuint sz = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
4381                                       texImage->Height, texImage->Depth);
4382   return sz;
4383}
4384
4385
4386/** Return row stride in bytes */
4387static GLuint
4388texture_row_stride(const struct gl_texture_image *texImage)
4389{
4390   GLuint stride = _mesa_format_row_stride(texImage->TexFormat,
4391                                           texImage->Width);
4392   return stride;
4393}
4394
4395
4396
4397/**
4398 * This is the software fallback for Driver.TexImage1D()
4399 * and Driver.CopyTexImage1D().
4400 * \sa _mesa_store_teximage2d()
4401 */
4402void
4403_mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
4404                       GLint internalFormat,
4405                       GLint width, GLint border,
4406                       GLenum format, GLenum type, const GLvoid *pixels,
4407                       const struct gl_pixelstore_attrib *packing,
4408                       struct gl_texture_object *texObj,
4409                       struct gl_texture_image *texImage)
4410{
4411   GLuint sizeInBytes;
4412   (void) border;
4413
4414   /* allocate memory */
4415   sizeInBytes = texture_size(texImage);
4416   texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
4417   if (!texImage->Data) {
4418      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
4419      return;
4420   }
4421
4422   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
4423                                        pixels, packing, "glTexImage1D");
4424   if (!pixels) {
4425      /* Note: we check for a NULL image pointer here, _after_ we allocated
4426       * memory for the texture.  That's what the GL spec calls for.
4427       */
4428      return;
4429   }
4430   else {
4431      const GLint dstRowStride = 0;
4432      GLboolean success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
4433                                         texImage->TexFormat,
4434                                         texImage->Data,
4435                                         0, 0, 0,  /* dstX/Y/Zoffset */
4436                                         dstRowStride,
4437                                         texImage->ImageOffsets,
4438                                         width, 1, 1,
4439                                         format, type, pixels, packing);
4440      if (!success) {
4441         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
4442      }
4443   }
4444
4445   _mesa_unmap_teximage_pbo(ctx, packing);
4446}
4447
4448
4449/**
4450 * This is the software fallback for Driver.TexImage2D()
4451 * and Driver.CopyTexImage2D().
4452 *
4453 * This function is oriented toward storing images in main memory, rather
4454 * than VRAM.  Device driver's can easily plug in their own replacement.
4455 */
4456void
4457_mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
4458                       GLint internalFormat,
4459                       GLint width, GLint height, GLint border,
4460                       GLenum format, GLenum type, const void *pixels,
4461                       const struct gl_pixelstore_attrib *packing,
4462                       struct gl_texture_object *texObj,
4463                       struct gl_texture_image *texImage)
4464{
4465   GLuint sizeInBytes;
4466   (void) border;
4467
4468   /* allocate memory */
4469   sizeInBytes = texture_size(texImage);
4470   texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
4471   if (!texImage->Data) {
4472      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
4473      return;
4474   }
4475
4476   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
4477                                        pixels, packing, "glTexImage2D");
4478   if (!pixels) {
4479      /* Note: we check for a NULL image pointer here, _after_ we allocated
4480       * memory for the texture.  That's what the GL spec calls for.
4481       */
4482      return;
4483   }
4484   else {
4485      GLint dstRowStride = texture_row_stride(texImage);
4486      GLboolean success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
4487                                         texImage->TexFormat,
4488                                         texImage->Data,
4489                                         0, 0, 0,  /* dstX/Y/Zoffset */
4490                                         dstRowStride,
4491                                         texImage->ImageOffsets,
4492                                         width, height, 1,
4493                                         format, type, pixels, packing);
4494      if (!success) {
4495         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
4496      }
4497   }
4498
4499   _mesa_unmap_teximage_pbo(ctx, packing);
4500}
4501
4502
4503
4504/**
4505 * This is the software fallback for Driver.TexImage3D()
4506 * and Driver.CopyTexImage3D().
4507 * \sa _mesa_store_teximage2d()
4508 */
4509void
4510_mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
4511                       GLint internalFormat,
4512                       GLint width, GLint height, GLint depth, GLint border,
4513                       GLenum format, GLenum type, const void *pixels,
4514                       const struct gl_pixelstore_attrib *packing,
4515                       struct gl_texture_object *texObj,
4516                       struct gl_texture_image *texImage)
4517{
4518   GLuint sizeInBytes;
4519   (void) border;
4520
4521   /* allocate memory */
4522   sizeInBytes = texture_size(texImage);
4523   texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
4524   if (!texImage->Data) {
4525      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
4526      return;
4527   }
4528
4529   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
4530                                        type, pixels, packing, "glTexImage3D");
4531   if (!pixels) {
4532      /* Note: we check for a NULL image pointer here, _after_ we allocated
4533       * memory for the texture.  That's what the GL spec calls for.
4534       */
4535      return;
4536   }
4537   else {
4538      GLint dstRowStride = texture_row_stride(texImage);
4539      GLboolean success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
4540                                         texImage->TexFormat,
4541                                         texImage->Data,
4542                                         0, 0, 0,  /* dstX/Y/Zoffset */
4543                                         dstRowStride,
4544                                         texImage->ImageOffsets,
4545                                         width, height, depth,
4546                                         format, type, pixels, packing);
4547      if (!success) {
4548         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
4549      }
4550   }
4551
4552   _mesa_unmap_teximage_pbo(ctx, packing);
4553}
4554
4555
4556
4557
4558/*
4559 * This is the software fallback for Driver.TexSubImage1D()
4560 * and Driver.CopyTexSubImage1D().
4561 */
4562void
4563_mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level,
4564                          GLint xoffset, GLint width,
4565                          GLenum format, GLenum type, const void *pixels,
4566                          const struct gl_pixelstore_attrib *packing,
4567                          struct gl_texture_object *texObj,
4568                          struct gl_texture_image *texImage)
4569{
4570   /* get pointer to src pixels (may be in a pbo which we'll map here) */
4571   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
4572                                        pixels, packing, "glTexSubImage1D");
4573   if (!pixels)
4574      return;
4575
4576   {
4577      const GLint dstRowStride = 0;
4578      GLboolean success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
4579                                         texImage->TexFormat,
4580                                         texImage->Data,
4581                                         xoffset, 0, 0,  /* offsets */
4582                                         dstRowStride,
4583                                         texImage->ImageOffsets,
4584                                         width, 1, 1,
4585                                         format, type, pixels, packing);
4586      if (!success) {
4587         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
4588      }
4589   }
4590
4591   _mesa_unmap_teximage_pbo(ctx, packing);
4592}
4593
4594
4595
4596/**
4597 * This is the software fallback for Driver.TexSubImage2D()
4598 * and Driver.CopyTexSubImage2D().
4599 */
4600void
4601_mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level,
4602                          GLint xoffset, GLint yoffset,
4603                          GLint width, GLint height,
4604                          GLenum format, GLenum type, const void *pixels,
4605                          const struct gl_pixelstore_attrib *packing,
4606                          struct gl_texture_object *texObj,
4607                          struct gl_texture_image *texImage)
4608{
4609   /* get pointer to src pixels (may be in a pbo which we'll map here) */
4610   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
4611                                        pixels, packing, "glTexSubImage2D");
4612   if (!pixels)
4613      return;
4614
4615   {
4616      GLint dstRowStride = texture_row_stride(texImage);
4617      GLboolean success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
4618                                         texImage->TexFormat,
4619                                         texImage->Data,
4620                                         xoffset, yoffset, 0,
4621                                         dstRowStride,
4622                                         texImage->ImageOffsets,
4623                                         width, height, 1,
4624                                         format, type, pixels, packing);
4625      if (!success) {
4626         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
4627      }
4628   }
4629
4630   _mesa_unmap_teximage_pbo(ctx, packing);
4631}
4632
4633
4634/*
4635 * This is the software fallback for Driver.TexSubImage3D().
4636 * and Driver.CopyTexSubImage3D().
4637 */
4638void
4639_mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
4640                          GLint xoffset, GLint yoffset, GLint zoffset,
4641                          GLint width, GLint height, GLint depth,
4642                          GLenum format, GLenum type, const void *pixels,
4643                          const struct gl_pixelstore_attrib *packing,
4644                          struct gl_texture_object *texObj,
4645                          struct gl_texture_image *texImage)
4646{
4647   /* get pointer to src pixels (may be in a pbo which we'll map here) */
4648   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
4649                                        type, pixels, packing,
4650                                        "glTexSubImage3D");
4651   if (!pixels)
4652      return;
4653
4654   {
4655      GLint dstRowStride = texture_row_stride(texImage);
4656      GLboolean success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
4657                                         texImage->TexFormat,
4658                                         texImage->Data,
4659                                         xoffset, yoffset, zoffset,
4660                                         dstRowStride,
4661                                         texImage->ImageOffsets,
4662                                         width, height, depth,
4663                                         format, type, pixels, packing);
4664      if (!success) {
4665         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
4666      }
4667   }
4668
4669   _mesa_unmap_teximage_pbo(ctx, packing);
4670}
4671
4672
4673/*
4674 * Fallback for Driver.CompressedTexImage1D()
4675 */
4676void
4677_mesa_store_compressed_teximage1d(struct gl_context *ctx,
4678                                  GLenum target, GLint level,
4679                                  GLint internalFormat,
4680                                  GLint width, GLint border,
4681                                  GLsizei imageSize, const GLvoid *data,
4682                                  struct gl_texture_object *texObj,
4683                                  struct gl_texture_image *texImage)
4684{
4685   /* this space intentionally left blank */
4686   (void) ctx;
4687   (void) target; (void) level;
4688   (void) internalFormat;
4689   (void) width; (void) border;
4690   (void) imageSize; (void) data;
4691   (void) texObj;
4692   (void) texImage;
4693}
4694
4695
4696
4697/**
4698 * Fallback for Driver.CompressedTexImage2D()
4699 */
4700void
4701_mesa_store_compressed_teximage2d(struct gl_context *ctx,
4702                                  GLenum target, GLint level,
4703                                  GLint internalFormat,
4704                                  GLint width, GLint height, GLint border,
4705                                  GLsizei imageSize, const GLvoid *data,
4706                                  struct gl_texture_object *texObj,
4707                                  struct gl_texture_image *texImage)
4708{
4709   (void) width; (void) height; (void) border;
4710
4711   /* This is pretty simple, basically just do a memcpy without worrying
4712    * about the usual image unpacking or image transfer operations.
4713    */
4714   ASSERT(texObj);
4715   ASSERT(texImage);
4716   ASSERT(texImage->Width > 0);
4717   ASSERT(texImage->Height > 0);
4718   ASSERT(texImage->Depth == 1);
4719   ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
4720
4721   /* allocate storage */
4722   texImage->Data = _mesa_alloc_texmemory(imageSize);
4723   if (!texImage->Data) {
4724      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
4725      return;
4726   }
4727
4728   data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
4729                                                 &ctx->Unpack,
4730                                                 "glCompressedTexImage2D");
4731   if (!data)
4732      return;
4733
4734   /* copy the data */
4735   memcpy(texImage->Data, data, imageSize);
4736
4737   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
4738}
4739
4740
4741
4742/*
4743 * Fallback for Driver.CompressedTexImage3D()
4744 */
4745void
4746_mesa_store_compressed_teximage3d(struct gl_context *ctx,
4747                                  GLenum target, GLint level,
4748                                  GLint internalFormat,
4749                                  GLint width, GLint height, GLint depth,
4750                                  GLint border,
4751                                  GLsizei imageSize, const GLvoid *data,
4752                                  struct gl_texture_object *texObj,
4753                                  struct gl_texture_image *texImage)
4754{
4755   /* this space intentionally left blank */
4756   (void) ctx;
4757   (void) target; (void) level;
4758   (void) internalFormat;
4759   (void) width; (void) height; (void) depth;
4760   (void) border;
4761   (void) imageSize; (void) data;
4762   (void) texObj;
4763   (void) texImage;
4764}
4765
4766
4767
4768/**
4769 * Fallback for Driver.CompressedTexSubImage1D()
4770 */
4771void
4772_mesa_store_compressed_texsubimage1d(struct gl_context *ctx, GLenum target,
4773                                     GLint level,
4774                                     GLint xoffset, GLsizei width,
4775                                     GLenum format,
4776                                     GLsizei imageSize, const GLvoid *data,
4777                                     struct gl_texture_object *texObj,
4778                                     struct gl_texture_image *texImage)
4779{
4780   /* there are no compressed 1D texture formats yet */
4781   (void) ctx;
4782   (void) target; (void) level;
4783   (void) xoffset; (void) width;
4784   (void) format;
4785   (void) imageSize; (void) data;
4786   (void) texObj;
4787   (void) texImage;
4788}
4789
4790
4791/**
4792 * Fallback for Driver.CompressedTexSubImage2D()
4793 */
4794void
4795_mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
4796                                     GLint level,
4797                                     GLint xoffset, GLint yoffset,
4798                                     GLsizei width, GLsizei height,
4799                                     GLenum format,
4800                                     GLsizei imageSize, const GLvoid *data,
4801                                     struct gl_texture_object *texObj,
4802                                     struct gl_texture_image *texImage)
4803{
4804   GLint bytesPerRow, destRowStride, srcRowStride;
4805   GLint i, rows;
4806   GLubyte *dest;
4807   const GLubyte *src;
4808   const gl_format texFormat = texImage->TexFormat;
4809   const GLint destWidth = texImage->Width;
4810   GLuint bw, bh;
4811
4812   _mesa_get_format_block_size(texFormat, &bw, &bh);
4813
4814   (void) level;
4815   (void) format;
4816
4817   /* these should have been caught sooner */
4818   ASSERT((width % bw) == 0 || width == 2 || width == 1);
4819   ASSERT((height % bh) == 0 || height == 2 || height == 1);
4820   ASSERT((xoffset % bw) == 0);
4821   ASSERT((yoffset % bh) == 0);
4822
4823   /* get pointer to src pixels (may be in a pbo which we'll map here) */
4824   data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
4825                                                 &ctx->Unpack,
4826                                                 "glCompressedTexSubImage2D");
4827   if (!data)
4828      return;
4829
4830   srcRowStride = _mesa_format_row_stride(texFormat, width);
4831   src = (const GLubyte *) data;
4832
4833   destRowStride = _mesa_format_row_stride(texFormat, destWidth);
4834   dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
4835                                         texFormat, destWidth,
4836                                         (GLubyte *) texImage->Data);
4837
4838   bytesPerRow = srcRowStride;  /* bytes per row of blocks */
4839   rows = height / bh;  /* rows in blocks */
4840
4841   /* copy rows of blocks */
4842   for (i = 0; i < rows; i++) {
4843      memcpy(dest, src, bytesPerRow);
4844      dest += destRowStride;
4845      src += srcRowStride;
4846   }
4847
4848   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
4849}
4850
4851
4852/**
4853 * Fallback for Driver.CompressedTexSubImage3D()
4854 */
4855void
4856_mesa_store_compressed_texsubimage3d(struct gl_context *ctx, GLenum target,
4857                                GLint level,
4858                                GLint xoffset, GLint yoffset, GLint zoffset,
4859                                GLsizei width, GLsizei height, GLsizei depth,
4860                                GLenum format,
4861                                GLsizei imageSize, const GLvoid *data,
4862                                struct gl_texture_object *texObj,
4863                                struct gl_texture_image *texImage)
4864{
4865   /* there are no compressed 3D texture formats yet */
4866   (void) ctx;
4867   (void) target; (void) level;
4868   (void) xoffset; (void) yoffset; (void) zoffset;
4869   (void) width; (void) height; (void) depth;
4870   (void) format;
4871   (void) imageSize; (void) data;
4872   (void) texObj;
4873   (void) texImage;
4874}
4875