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