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      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3204      if (!tempImage)
3205         return GL_FALSE;
3206      for (img = 0; img < srcDepth; img++) {
3207         GLubyte *dstRow = dstSlices[img];
3208         for (row = 0; row < srcHeight; row++) {
3209            GLbyte *dstTexel = (GLbyte *) dstRow;
3210            GLint i;
3211            if (is_unsigned) {
3212               for (i = 0; i < srcWidth * components; i++) {
3213                  dstTexel[i] = (GLbyte) MIN2(src[i], 0x7f);
3214               }
3215            } else {
3216               for (i = 0; i < srcWidth * components; i++) {
3217                  dstTexel[i] = (GLbyte) CLAMP((GLint) src[i], -0x80, 0x7f);
3218               }
3219            }
3220            dstRow += dstRowStride;
3221            src += srcWidth * components;
3222         }
3223      }
3224
3225      free((void *) tempImage);
3226   }
3227   return GL_TRUE;
3228}
3229
3230
3231/* non-normalized, signed int16 */
3232static GLboolean
3233_mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
3234{
3235   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3236   const GLint components = _mesa_components_in_format(baseFormat);
3237
3238   ASSERT(dstFormat == MESA_FORMAT_R_INT16 ||
3239          dstFormat == MESA_FORMAT_RG_INT16 ||
3240          dstFormat == MESA_FORMAT_RGB_INT16 ||
3241          dstFormat == MESA_FORMAT_RGBA_INT16 ||
3242          dstFormat == MESA_FORMAT_ALPHA_INT16 ||
3243          dstFormat == MESA_FORMAT_LUMINANCE_INT16 ||
3244          dstFormat == MESA_FORMAT_INTENSITY_INT16 ||
3245          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT16);
3246   ASSERT(baseInternalFormat == GL_RGBA ||
3247          baseInternalFormat == GL_RGB ||
3248          baseInternalFormat == GL_RG ||
3249          baseInternalFormat == GL_RED ||
3250          baseInternalFormat == GL_ALPHA ||
3251          baseInternalFormat == GL_LUMINANCE ||
3252          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3253          baseInternalFormat == GL_INTENSITY);
3254   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLshort));
3255
3256   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3257    * to integer formats.
3258    */
3259   if (!srcPacking->SwapBytes &&
3260       baseInternalFormat == srcFormat &&
3261       srcType == GL_SHORT) {
3262      /* simple memcpy path */
3263      memcpy_texture(ctx, dims,
3264                     dstFormat,
3265                     dstRowStride, dstSlices,
3266                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3267                     srcAddr, srcPacking);
3268   }
3269   else {
3270      /* general path */
3271      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
3272						     baseInternalFormat,
3273						     baseFormat,
3274						     srcWidth, srcHeight, srcDepth,
3275						     srcFormat, srcType,
3276						     srcAddr,
3277						     srcPacking);
3278      const GLuint *src = tempImage;
3279      GLint img, row;
3280      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3281      if (!tempImage)
3282         return GL_FALSE;
3283      for (img = 0; img < srcDepth; img++) {
3284         GLubyte *dstRow = dstSlices[img];
3285         for (row = 0; row < srcHeight; row++) {
3286            GLshort *dstTexel = (GLshort *) dstRow;
3287            GLint i;
3288            if (is_unsigned) {
3289               for (i = 0; i < srcWidth * components; i++) {
3290                  dstTexel[i] = (GLshort) MIN2(src[i], 0x7fff);
3291               }
3292            } else {
3293               for (i = 0; i < srcWidth * components; i++) {
3294                  dstTexel[i] = (GLshort)CLAMP((GLint) src[i], -0x8000, 0x7fff);
3295               }
3296            }
3297            dstRow += dstRowStride;
3298            src += srcWidth * components;
3299         }
3300      }
3301
3302      free((void *) tempImage);
3303   }
3304   return GL_TRUE;
3305}
3306
3307
3308/* non-normalized, signed int32 */
3309static GLboolean
3310_mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
3311{
3312   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3313   const GLint components = _mesa_components_in_format(baseFormat);
3314
3315   ASSERT(dstFormat == MESA_FORMAT_R_INT32 ||
3316          dstFormat == MESA_FORMAT_RG_INT32 ||
3317          dstFormat == MESA_FORMAT_RGB_INT32 ||
3318          dstFormat == MESA_FORMAT_RGBA_INT32 ||
3319          dstFormat == MESA_FORMAT_ALPHA_INT32 ||
3320          dstFormat == MESA_FORMAT_INTENSITY_INT32 ||
3321          dstFormat == MESA_FORMAT_LUMINANCE_INT32 ||
3322          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT32);
3323   ASSERT(baseInternalFormat == GL_RGBA ||
3324          baseInternalFormat == GL_RGB ||
3325          baseInternalFormat == GL_RG ||
3326          baseInternalFormat == GL_RED ||
3327          baseInternalFormat == GL_ALPHA ||
3328          baseInternalFormat == GL_LUMINANCE ||
3329          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3330          baseInternalFormat == GL_INTENSITY);
3331   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLint));
3332
3333   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3334    * to integer formats.
3335    */
3336   if (!srcPacking->SwapBytes &&
3337       baseInternalFormat == srcFormat &&
3338       srcType == GL_INT) {
3339      /* simple memcpy path */
3340      memcpy_texture(ctx, dims,
3341                     dstFormat,
3342                     dstRowStride, dstSlices,
3343                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3344                     srcAddr, srcPacking);
3345   }
3346   else {
3347      /* general path */
3348      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
3349						     baseInternalFormat,
3350						     baseFormat,
3351						     srcWidth, srcHeight, srcDepth,
3352						     srcFormat, srcType,
3353						     srcAddr,
3354						     srcPacking);
3355      const GLuint *src = tempImage;
3356      GLint img, row;
3357      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3358      if (!tempImage)
3359         return GL_FALSE;
3360      for (img = 0; img < srcDepth; img++) {
3361         GLubyte *dstRow = dstSlices[img];
3362         for (row = 0; row < srcHeight; row++) {
3363            GLint *dstTexel = (GLint *) dstRow;
3364            GLint i;
3365            if (is_unsigned) {
3366               for (i = 0; i < srcWidth * components; i++) {
3367                  dstTexel[i] = (GLint) MIN2(src[i], 0x7fffffff);
3368               }
3369            } else {
3370               for (i = 0; i < srcWidth * components; i++) {
3371                  dstTexel[i] = (GLint) src[i];
3372               }
3373            }
3374            dstRow += dstRowStride;
3375            src += srcWidth * components;
3376         }
3377      }
3378
3379      free((void *) tempImage);
3380   }
3381   return GL_TRUE;
3382}
3383
3384
3385/* non-normalized, unsigned int8 */
3386static GLboolean
3387_mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
3388{
3389   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3390   const GLint components = _mesa_components_in_format(baseFormat);
3391
3392   ASSERT(dstFormat == MESA_FORMAT_R_UINT8 ||
3393          dstFormat == MESA_FORMAT_RG_UINT8 ||
3394          dstFormat == MESA_FORMAT_RGB_UINT8 ||
3395          dstFormat == MESA_FORMAT_RGBA_UINT8 ||
3396          dstFormat == MESA_FORMAT_ALPHA_UINT8 ||
3397          dstFormat == MESA_FORMAT_INTENSITY_UINT8 ||
3398          dstFormat == MESA_FORMAT_LUMINANCE_UINT8 ||
3399          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT8);
3400   ASSERT(baseInternalFormat == GL_RGBA ||
3401          baseInternalFormat == GL_RGB ||
3402          baseInternalFormat == GL_RG ||
3403          baseInternalFormat == GL_RED ||
3404          baseInternalFormat == GL_ALPHA ||
3405          baseInternalFormat == GL_LUMINANCE ||
3406          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3407          baseInternalFormat == GL_INTENSITY);
3408   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLubyte));
3409
3410   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3411    * to integer formats.
3412    */
3413   if (!srcPacking->SwapBytes &&
3414       baseInternalFormat == srcFormat &&
3415       srcType == GL_UNSIGNED_BYTE) {
3416      /* simple memcpy path */
3417      memcpy_texture(ctx, dims,
3418                     dstFormat,
3419                     dstRowStride, dstSlices,
3420                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3421                     srcAddr, srcPacking);
3422   }
3423   else {
3424      /* general path */
3425      const GLuint *tempImage =
3426         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
3427                              srcWidth, srcHeight, srcDepth,
3428                              srcFormat, srcType, srcAddr, srcPacking);
3429      const GLuint *src = tempImage;
3430      GLint img, row;
3431      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3432      if (!tempImage)
3433         return GL_FALSE;
3434      for (img = 0; img < srcDepth; img++) {
3435         GLubyte *dstRow = dstSlices[img];
3436         for (row = 0; row < srcHeight; row++) {
3437            GLubyte *dstTexel = (GLubyte *) dstRow;
3438            GLint i;
3439            if (is_unsigned) {
3440               for (i = 0; i < srcWidth * components; i++) {
3441                  dstTexel[i] = (GLubyte) MIN2(src[i], 0xff);
3442               }
3443            } else {
3444               for (i = 0; i < srcWidth * components; i++) {
3445                  dstTexel[i] = (GLubyte) CLAMP((GLint) src[i], 0, 0xff);
3446               }
3447            }
3448            dstRow += dstRowStride;
3449            src += srcWidth * components;
3450         }
3451      }
3452
3453      free((void *) tempImage);
3454   }
3455   return GL_TRUE;
3456}
3457
3458
3459/* non-normalized, unsigned int16 */
3460static GLboolean
3461_mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
3462{
3463   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3464   const GLint components = _mesa_components_in_format(baseFormat);
3465
3466   ASSERT(dstFormat == MESA_FORMAT_R_UINT16 ||
3467          dstFormat == MESA_FORMAT_RG_UINT16 ||
3468          dstFormat == MESA_FORMAT_RGB_UINT16 ||
3469          dstFormat == MESA_FORMAT_RGBA_UINT16 ||
3470          dstFormat == MESA_FORMAT_ALPHA_UINT16 ||
3471          dstFormat == MESA_FORMAT_INTENSITY_UINT16 ||
3472          dstFormat == MESA_FORMAT_LUMINANCE_UINT16 ||
3473          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT16);
3474   ASSERT(baseInternalFormat == GL_RGBA ||
3475          baseInternalFormat == GL_RGB ||
3476          baseInternalFormat == GL_RG ||
3477          baseInternalFormat == GL_RED ||
3478          baseInternalFormat == GL_ALPHA ||
3479          baseInternalFormat == GL_LUMINANCE ||
3480          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3481          baseInternalFormat == GL_INTENSITY);
3482   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLushort));
3483
3484   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3485    * to integer formats.
3486    */
3487   if (!srcPacking->SwapBytes &&
3488       baseInternalFormat == srcFormat &&
3489       srcType == GL_UNSIGNED_SHORT) {
3490      /* simple memcpy path */
3491      memcpy_texture(ctx, dims,
3492                     dstFormat,
3493                     dstRowStride, dstSlices,
3494                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3495                     srcAddr, srcPacking);
3496   }
3497   else {
3498      /* general path */
3499      const GLuint *tempImage =
3500         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
3501                              srcWidth, srcHeight, srcDepth,
3502                              srcFormat, srcType, srcAddr, srcPacking);
3503      const GLuint *src = tempImage;
3504      GLint img, row;
3505      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3506      if (!tempImage)
3507         return GL_FALSE;
3508      for (img = 0; img < srcDepth; img++) {
3509         GLubyte *dstRow = dstSlices[img];
3510         for (row = 0; row < srcHeight; row++) {
3511            GLushort *dstTexel = (GLushort *) dstRow;
3512            GLint i;
3513            if (is_unsigned) {
3514               for (i = 0; i < srcWidth * components; i++) {
3515                  dstTexel[i] = (GLushort) MIN2(src[i], 0xffff);
3516              }
3517            } else {
3518               for (i = 0; i < srcWidth * components; i++) {
3519                  dstTexel[i] = (GLushort) CLAMP((GLint) src[i], 0, 0xffff);
3520               }
3521            }
3522            dstRow += dstRowStride;
3523            src += srcWidth * components;
3524         }
3525      }
3526
3527      free((void *) tempImage);
3528   }
3529   return GL_TRUE;
3530}
3531
3532
3533/* non-normalized, unsigned int32 */
3534static GLboolean
3535_mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
3536{
3537   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3538   const GLint components = _mesa_components_in_format(baseFormat);
3539
3540   ASSERT(dstFormat == MESA_FORMAT_R_UINT32 ||
3541          dstFormat == MESA_FORMAT_RG_UINT32 ||
3542          dstFormat == MESA_FORMAT_RGB_UINT32 ||
3543          dstFormat == MESA_FORMAT_RGBA_UINT32 ||
3544          dstFormat == MESA_FORMAT_ALPHA_UINT32 ||
3545          dstFormat == MESA_FORMAT_INTENSITY_UINT32 ||
3546          dstFormat == MESA_FORMAT_LUMINANCE_UINT32 ||
3547          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT32);
3548   ASSERT(baseInternalFormat == GL_RGBA ||
3549          baseInternalFormat == GL_RGB ||
3550          baseInternalFormat == GL_RG ||
3551          baseInternalFormat == GL_RED ||
3552          baseInternalFormat == GL_ALPHA ||
3553          baseInternalFormat == GL_LUMINANCE ||
3554          baseInternalFormat == GL_LUMINANCE_ALPHA ||
3555          baseInternalFormat == GL_INTENSITY);
3556   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLuint));
3557
3558   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
3559    * to integer formats.
3560    */
3561   if (!srcPacking->SwapBytes &&
3562       baseInternalFormat == srcFormat &&
3563       srcType == GL_UNSIGNED_INT) {
3564      /* simple memcpy path */
3565      memcpy_texture(ctx, dims,
3566                     dstFormat,
3567                     dstRowStride, dstSlices,
3568                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3569                     srcAddr, srcPacking);
3570   }
3571   else {
3572      /* general path */
3573      const GLuint *tempImage =
3574         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
3575                              srcWidth, srcHeight, srcDepth,
3576                              srcFormat, srcType, srcAddr, srcPacking);
3577      const GLuint *src = tempImage;
3578      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3579      GLint img, row;
3580      if (!tempImage)
3581         return GL_FALSE;
3582      for (img = 0; img < srcDepth; img++) {
3583         GLubyte *dstRow = dstSlices[img];
3584         for (row = 0; row < srcHeight; row++) {
3585            GLuint *dstTexel = (GLuint *) dstRow;
3586            GLint i;
3587            if (is_unsigned) {
3588               for (i = 0; i < srcWidth * components; i++) {
3589                  dstTexel[i] = src[i];
3590               }
3591            } else {
3592               for (i = 0; i < srcWidth * components; i++) {
3593                  dstTexel[i] = MAX2((GLint) src[i], 0);
3594               }
3595            }
3596            dstRow += dstRowStride;
3597            src += srcWidth * components;
3598         }
3599      }
3600
3601      free((void *) tempImage);
3602   }
3603   return GL_TRUE;
3604}
3605
3606
3607
3608
3609#if FEATURE_EXT_texture_sRGB
3610static GLboolean
3611_mesa_texstore_srgb8(TEXSTORE_PARAMS)
3612{
3613   gl_format newDstFormat;
3614   GLboolean k;
3615
3616   ASSERT(dstFormat == MESA_FORMAT_SRGB8);
3617
3618   /* reuse normal rgb texstore code */
3619   newDstFormat = MESA_FORMAT_RGB888;
3620
3621   k = _mesa_texstore_rgb888(ctx, dims, baseInternalFormat,
3622                             newDstFormat,
3623                             dstRowStride, dstSlices,
3624                             srcWidth, srcHeight, srcDepth,
3625                             srcFormat, srcType,
3626                             srcAddr, srcPacking);
3627   return k;
3628}
3629
3630
3631static GLboolean
3632_mesa_texstore_srgba8(TEXSTORE_PARAMS)
3633{
3634   gl_format newDstFormat;
3635   GLboolean k;
3636
3637   ASSERT(dstFormat == MESA_FORMAT_SRGBA8);
3638
3639   /* reuse normal rgba texstore code */
3640   newDstFormat = MESA_FORMAT_RGBA8888;
3641   k = _mesa_texstore_rgba8888(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_sargb8(TEXSTORE_PARAMS)
3653{
3654   gl_format newDstFormat;
3655   GLboolean k;
3656
3657   ASSERT(dstFormat == MESA_FORMAT_SARGB8);
3658
3659   /* reuse normal rgba texstore code */
3660   newDstFormat = MESA_FORMAT_ARGB8888;
3661
3662   k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
3663                               newDstFormat,
3664                               dstRowStride, dstSlices,
3665                               srcWidth, srcHeight, srcDepth,
3666                               srcFormat, srcType,
3667                               srcAddr, srcPacking);
3668   return k;
3669}
3670
3671
3672static GLboolean
3673_mesa_texstore_sl8(TEXSTORE_PARAMS)
3674{
3675   gl_format newDstFormat;
3676   GLboolean k;
3677
3678   ASSERT(dstFormat == MESA_FORMAT_SL8);
3679
3680   newDstFormat = MESA_FORMAT_L8;
3681
3682   /* _mesa_textore_a8 handles luminance8 too */
3683   k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat,
3684                             newDstFormat,
3685                             dstRowStride, dstSlices,
3686                             srcWidth, srcHeight, srcDepth,
3687                             srcFormat, srcType,
3688                             srcAddr, srcPacking);
3689   return k;
3690}
3691
3692
3693static GLboolean
3694_mesa_texstore_sla8(TEXSTORE_PARAMS)
3695{
3696   gl_format newDstFormat;
3697   GLboolean k;
3698
3699   ASSERT(dstFormat == MESA_FORMAT_SLA8);
3700
3701   /* reuse normal luminance/alpha texstore code */
3702   newDstFormat = MESA_FORMAT_AL88;
3703
3704   k = _mesa_texstore_unorm88(ctx, dims, baseInternalFormat,
3705			      newDstFormat,
3706			      dstRowStride, dstSlices,
3707			      srcWidth, srcHeight, srcDepth,
3708			      srcFormat, srcType,
3709			      srcAddr, srcPacking);
3710   return k;
3711}
3712
3713#else
3714
3715/* these are used only in texstore_funcs[] below */
3716#define _mesa_texstore_srgb8 NULL
3717#define _mesa_texstore_srgba8 NULL
3718#define _mesa_texstore_sargb8 NULL
3719#define _mesa_texstore_sl8 NULL
3720#define _mesa_texstore_sla8 NULL
3721
3722#endif /* FEATURE_EXT_texture_sRGB */
3723
3724static GLboolean
3725_mesa_texstore_rgb9_e5(TEXSTORE_PARAMS)
3726{
3727   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3728
3729   ASSERT(dstFormat == MESA_FORMAT_RGB9_E5_FLOAT);
3730   ASSERT(baseInternalFormat == GL_RGB);
3731
3732   if (!ctx->_ImageTransferState &&
3733       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
3734                                            srcPacking->SwapBytes)) {
3735      /* simple memcpy path */
3736      memcpy_texture(ctx, dims,
3737                     dstFormat,
3738                     dstRowStride, dstSlices,
3739                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3740                     srcAddr, srcPacking);
3741   }
3742   else {
3743      /* general path */
3744      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3745                                                 baseInternalFormat,
3746                                                 baseFormat,
3747                                                 srcWidth, srcHeight, srcDepth,
3748                                                 srcFormat, srcType, srcAddr,
3749                                                 srcPacking,
3750                                                 ctx->_ImageTransferState);
3751      const GLfloat *srcRow = tempImage;
3752      GLint img, row, col;
3753      if (!tempImage)
3754         return GL_FALSE;
3755      for (img = 0; img < srcDepth; img++) {
3756         GLubyte *dstRow = dstSlices[img];
3757         for (row = 0; row < srcHeight; row++) {
3758            GLuint *dstUI = (GLuint*)dstRow;
3759            for (col = 0; col < srcWidth; col++) {
3760               dstUI[col] = float3_to_rgb9e5(&srcRow[col * 3]);
3761            }
3762            dstRow += dstRowStride;
3763            srcRow += srcWidth * 3;
3764         }
3765      }
3766
3767      free((void *) tempImage);
3768   }
3769   return GL_TRUE;
3770}
3771
3772static GLboolean
3773_mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS)
3774{
3775   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3776
3777   ASSERT(dstFormat == MESA_FORMAT_R11_G11_B10_FLOAT);
3778   ASSERT(baseInternalFormat == GL_RGB);
3779
3780   if (!ctx->_ImageTransferState &&
3781       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
3782                                            srcPacking->SwapBytes)) {
3783      /* simple memcpy path */
3784      memcpy_texture(ctx, dims,
3785                     dstFormat,
3786                     dstRowStride, dstSlices,
3787                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3788                     srcAddr, srcPacking);
3789   }
3790   else {
3791      /* general path */
3792      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
3793                                                 baseInternalFormat,
3794                                                 baseFormat,
3795                                                 srcWidth, srcHeight, srcDepth,
3796                                                 srcFormat, srcType, srcAddr,
3797                                                 srcPacking,
3798                                                 ctx->_ImageTransferState);
3799      const GLfloat *srcRow = tempImage;
3800      GLint img, row, col;
3801      if (!tempImage)
3802         return GL_FALSE;
3803      for (img = 0; img < srcDepth; img++) {
3804         GLubyte *dstRow = dstSlices[img];
3805         for (row = 0; row < srcHeight; row++) {
3806            GLuint *dstUI = (GLuint*)dstRow;
3807            for (col = 0; col < srcWidth; col++) {
3808               dstUI[col] = float3_to_r11g11b10f(&srcRow[col * 3]);
3809            }
3810            dstRow += dstRowStride;
3811            srcRow += srcWidth * 3;
3812         }
3813      }
3814
3815      free((void *) tempImage);
3816   }
3817   return GL_TRUE;
3818}
3819
3820
3821static GLboolean
3822_mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
3823{
3824   ASSERT(dstFormat == MESA_FORMAT_Z32_FLOAT_X24S8);
3825   ASSERT(srcFormat == GL_DEPTH_STENCIL ||
3826          srcFormat == GL_DEPTH_COMPONENT ||
3827          srcFormat == GL_STENCIL_INDEX);
3828   ASSERT(srcFormat != GL_DEPTH_STENCIL ||
3829          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
3830
3831   if (srcFormat == GL_DEPTH_STENCIL &&
3832       ctx->Pixel.DepthScale == 1.0f &&
3833       ctx->Pixel.DepthBias == 0.0f &&
3834       !srcPacking->SwapBytes) {
3835      /* simple path */
3836      memcpy_texture(ctx, dims,
3837                     dstFormat,
3838                     dstRowStride, dstSlices,
3839                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3840                     srcAddr, srcPacking);
3841   }
3842   else if (srcFormat == GL_DEPTH_COMPONENT ||
3843            srcFormat == GL_STENCIL_INDEX) {
3844      GLint img, row;
3845      const GLint srcRowStride
3846         = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
3847         / sizeof(uint64_t);
3848
3849      /* In case we only upload depth we need to preserve the stencil */
3850      for (img = 0; img < srcDepth; img++) {
3851         uint64_t *dstRow = (uint64_t *) dstSlices[img];
3852         const uint64_t *src
3853            = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr,
3854                  srcWidth, srcHeight,
3855                  srcFormat, srcType,
3856                  img, 0, 0);
3857         for (row = 0; row < srcHeight; row++) {
3858            /* The unpack functions with:
3859             *    dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
3860             * only write their own dword, so the other dword (stencil
3861             * or depth) is preserved. */
3862            if (srcFormat != GL_STENCIL_INDEX)
3863               _mesa_unpack_depth_span(ctx, srcWidth,
3864                                       GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
3865                                       dstRow, /* dst addr */
3866                                       ~0U, srcType, src, srcPacking);
3867
3868            if (srcFormat != GL_DEPTH_COMPONENT)
3869               _mesa_unpack_stencil_span(ctx, srcWidth,
3870                                         GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
3871                                         dstRow, /* dst addr */
3872                                         srcType, src, srcPacking,
3873                                         ctx->_ImageTransferState);
3874
3875            src += srcRowStride;
3876            dstRow += dstRowStride / sizeof(uint64_t);
3877         }
3878      }
3879   }
3880   return GL_TRUE;
3881}
3882
3883static GLboolean
3884_mesa_texstore_argb2101010_uint(TEXSTORE_PARAMS)
3885{
3886   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3887
3888   ASSERT(dstFormat == MESA_FORMAT_ARGB2101010_UINT);
3889   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
3890
3891   if (baseInternalFormat == GL_RGBA &&
3892       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
3893                                            srcPacking->SwapBytes)) {
3894      /* simple memcpy path */
3895      memcpy_texture(ctx, dims,
3896                     dstFormat,
3897                     dstRowStride, dstSlices,
3898                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3899                     srcAddr, srcPacking);
3900   }
3901   else {
3902      /* general path */
3903      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
3904                                                     baseInternalFormat,
3905                                                     baseFormat,
3906                                                     srcWidth, srcHeight,
3907                                                     srcDepth, srcFormat,
3908                                                     srcType, srcAddr,
3909                                                     srcPacking);
3910      const GLuint *src = tempImage;
3911      GLint img, row, col;
3912      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3913      if (!tempImage)
3914         return GL_FALSE;
3915      for (img = 0; img < srcDepth; img++) {
3916         GLubyte *dstRow = dstSlices[img];
3917
3918         for (row = 0; row < srcHeight; row++) {
3919            GLuint *dstUI = (GLuint *) dstRow;
3920            if (is_unsigned) {
3921               for (col = 0; col < srcWidth; col++) {
3922                  GLushort a,r,g,b;
3923                  r = MIN2(src[RCOMP], 0x3ff);
3924                  g = MIN2(src[GCOMP], 0x3ff);
3925                  b = MIN2(src[BCOMP], 0x3ff);
3926                  a = MIN2(src[ACOMP], 0x003);
3927                  dstUI[col] = (a << 30) | (r << 20) | (g << 10) | (b);
3928                  src += 4;
3929               }
3930            } else {
3931               for (col = 0; col < srcWidth; col++) {
3932                  GLushort a,r,g,b;
3933                  r = CLAMP((GLint) src[RCOMP], 0, 0x3ff);
3934                  g = CLAMP((GLint) src[GCOMP], 0, 0x3ff);
3935                  b = CLAMP((GLint) src[BCOMP], 0, 0x3ff);
3936                  a = CLAMP((GLint) src[ACOMP], 0, 0x003);
3937                  dstUI[col] = (a << 30) | (r << 20) | (g << 10) | (b);
3938                  src += 4;
3939               }
3940            }
3941            dstRow += dstRowStride;
3942         }
3943      }
3944      free((void *) tempImage);
3945   }
3946   return GL_TRUE;
3947}
3948
3949static GLboolean
3950_mesa_texstore_abgr2101010_uint(TEXSTORE_PARAMS)
3951{
3952   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
3953
3954   ASSERT(dstFormat == MESA_FORMAT_ABGR2101010_UINT);
3955   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
3956
3957   if (baseInternalFormat == GL_RGBA &&
3958       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
3959                                            srcPacking->SwapBytes)) {
3960      /* simple memcpy path */
3961      memcpy_texture(ctx, dims,
3962                     dstFormat,
3963                     dstRowStride, dstSlices,
3964                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
3965                     srcAddr, srcPacking);
3966   }
3967   else {
3968      /* general path */
3969      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
3970                                                     baseInternalFormat,
3971                                                     baseFormat,
3972                                                     srcWidth, srcHeight,
3973                                                     srcDepth, srcFormat,
3974                                                     srcType, srcAddr,
3975                                                     srcPacking);
3976      const GLuint *src = tempImage;
3977      GLint img, row, col;
3978      GLboolean is_unsigned = _mesa_is_type_unsigned(srcType);
3979      if (!tempImage)
3980         return GL_FALSE;
3981      for (img = 0; img < srcDepth; img++) {
3982         GLubyte *dstRow = dstSlices[img];
3983
3984         for (row = 0; row < srcHeight; row++) {
3985            GLuint *dstUI = (GLuint *) dstRow;
3986            if (is_unsigned) {
3987               for (col = 0; col < srcWidth; col++) {
3988                  GLushort a,r,g,b;
3989                  r = MIN2(src[RCOMP], 0x3ff);
3990                  g = MIN2(src[GCOMP], 0x3ff);
3991                  b = MIN2(src[BCOMP], 0x3ff);
3992                  a = MIN2(src[ACOMP], 0x003);
3993                  dstUI[col] = (a << 30) | (b << 20) | (g << 10) | (r);
3994                  src += 4;
3995               }
3996            } else {
3997               for (col = 0; col < srcWidth; col++) {
3998                  GLushort a,r,g,b;
3999                  r = CLAMP((GLint) src[RCOMP], 0, 0x3ff);
4000                  g = CLAMP((GLint) src[GCOMP], 0, 0x3ff);
4001                  b = CLAMP((GLint) src[BCOMP], 0, 0x3ff);
4002                  a = CLAMP((GLint) src[ACOMP], 0, 0x003);
4003                  dstUI[col] = (a << 30) | (b << 20) | (g << 10) | (r);
4004                  src += 4;
4005               }
4006            }
4007            dstRow += dstRowStride;
4008         }
4009      }
4010      free((void *) tempImage);
4011   }
4012   return GL_TRUE;
4013}
4014
4015static GLboolean
4016_mesa_texstore_null(TEXSTORE_PARAMS)
4017{
4018   (void) ctx; (void) dims;
4019   (void) baseInternalFormat;
4020   (void) dstFormat;
4021   (void) dstRowStride; (void) dstSlices,
4022   (void) srcWidth; (void) srcHeight; (void) srcDepth;
4023   (void) srcFormat; (void) srcType;
4024   (void) srcAddr;
4025   (void) srcPacking;
4026
4027   /* should never happen */
4028   _mesa_problem(NULL, "_mesa_texstore_null() is called");
4029   return GL_FALSE;
4030}
4031
4032
4033/**
4034 * Return the StoreTexImageFunc pointer to store an image in the given format.
4035 */
4036static StoreTexImageFunc
4037_mesa_get_texstore_func(gl_format format)
4038{
4039   static StoreTexImageFunc table[MESA_FORMAT_COUNT];
4040   static GLboolean initialized = GL_FALSE;
4041
4042   if (!initialized) {
4043      table[MESA_FORMAT_NONE] = _mesa_texstore_null;
4044
4045      table[MESA_FORMAT_RGBA8888] = _mesa_texstore_rgba8888;
4046      table[MESA_FORMAT_RGBA8888_REV] = _mesa_texstore_rgba8888;
4047      table[MESA_FORMAT_ARGB8888] = _mesa_texstore_argb8888;
4048      table[MESA_FORMAT_ARGB8888_REV] = _mesa_texstore_argb8888;
4049      table[MESA_FORMAT_RGBX8888] = _mesa_texstore_rgba8888;
4050      table[MESA_FORMAT_RGBX8888_REV] = _mesa_texstore_rgba8888;
4051      table[MESA_FORMAT_XRGB8888] = _mesa_texstore_argb8888;
4052      table[MESA_FORMAT_XRGB8888_REV] = _mesa_texstore_argb8888;
4053      table[MESA_FORMAT_RGB888] = _mesa_texstore_rgb888;
4054      table[MESA_FORMAT_BGR888] = _mesa_texstore_bgr888;
4055      table[MESA_FORMAT_RGB565] = _mesa_texstore_rgb565;
4056      table[MESA_FORMAT_RGB565_REV] = _mesa_texstore_rgb565;
4057      table[MESA_FORMAT_ARGB4444] = _mesa_texstore_argb4444;
4058      table[MESA_FORMAT_ARGB4444_REV] = _mesa_texstore_argb4444;
4059      table[MESA_FORMAT_RGBA5551] = _mesa_texstore_rgba5551;
4060      table[MESA_FORMAT_ARGB1555] = _mesa_texstore_argb1555;
4061      table[MESA_FORMAT_ARGB1555_REV] = _mesa_texstore_argb1555;
4062      table[MESA_FORMAT_AL44] = _mesa_texstore_unorm44;
4063      table[MESA_FORMAT_AL88] = _mesa_texstore_unorm88;
4064      table[MESA_FORMAT_AL88_REV] = _mesa_texstore_unorm88;
4065      table[MESA_FORMAT_AL1616] = _mesa_texstore_unorm1616;
4066      table[MESA_FORMAT_AL1616_REV] = _mesa_texstore_unorm1616;
4067      table[MESA_FORMAT_RGB332] = _mesa_texstore_rgb332;
4068      table[MESA_FORMAT_A8] = _mesa_texstore_unorm8;
4069      table[MESA_FORMAT_A16] = _mesa_texstore_unorm16;
4070      table[MESA_FORMAT_L8] = _mesa_texstore_unorm8;
4071      table[MESA_FORMAT_L16] = _mesa_texstore_unorm16;
4072      table[MESA_FORMAT_I8] = _mesa_texstore_unorm8;
4073      table[MESA_FORMAT_I16] = _mesa_texstore_unorm16;
4074      table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr;
4075      table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr;
4076      table[MESA_FORMAT_R8] = _mesa_texstore_unorm8;
4077      table[MESA_FORMAT_GR88] = _mesa_texstore_unorm88;
4078      table[MESA_FORMAT_RG88] = _mesa_texstore_unorm88;
4079      table[MESA_FORMAT_R16] = _mesa_texstore_unorm16;
4080      table[MESA_FORMAT_RG1616] = _mesa_texstore_unorm1616;
4081      table[MESA_FORMAT_RG1616_REV] = _mesa_texstore_unorm1616;
4082      table[MESA_FORMAT_ARGB2101010] = _mesa_texstore_argb2101010;
4083      table[MESA_FORMAT_Z24_S8] = _mesa_texstore_z24_s8;
4084      table[MESA_FORMAT_S8_Z24] = _mesa_texstore_s8_z24;
4085      table[MESA_FORMAT_Z16] = _mesa_texstore_z16;
4086      table[MESA_FORMAT_X8_Z24] = _mesa_texstore_x8_z24;
4087      table[MESA_FORMAT_Z24_X8] = _mesa_texstore_z24_x8;
4088      table[MESA_FORMAT_Z32] = _mesa_texstore_z32;
4089      table[MESA_FORMAT_S8] = _mesa_texstore_s8;
4090      table[MESA_FORMAT_SRGB8] = _mesa_texstore_srgb8;
4091      table[MESA_FORMAT_SRGBA8] = _mesa_texstore_srgba8;
4092      table[MESA_FORMAT_SARGB8] = _mesa_texstore_sargb8;
4093      table[MESA_FORMAT_SL8] = _mesa_texstore_sl8;
4094      table[MESA_FORMAT_SLA8] = _mesa_texstore_sla8;
4095      table[MESA_FORMAT_SRGB_DXT1] = _mesa_texstore_rgb_dxt1;
4096      table[MESA_FORMAT_SRGBA_DXT1] = _mesa_texstore_rgba_dxt1;
4097      table[MESA_FORMAT_SRGBA_DXT3] = _mesa_texstore_rgba_dxt3;
4098      table[MESA_FORMAT_SRGBA_DXT5] = _mesa_texstore_rgba_dxt5;
4099      table[MESA_FORMAT_RGB_FXT1] = _mesa_texstore_rgb_fxt1;
4100      table[MESA_FORMAT_RGBA_FXT1] = _mesa_texstore_rgba_fxt1;
4101      table[MESA_FORMAT_RGB_DXT1] = _mesa_texstore_rgb_dxt1;
4102      table[MESA_FORMAT_RGBA_DXT1] = _mesa_texstore_rgba_dxt1;
4103      table[MESA_FORMAT_RGBA_DXT3] = _mesa_texstore_rgba_dxt3;
4104      table[MESA_FORMAT_RGBA_DXT5] = _mesa_texstore_rgba_dxt5;
4105      table[MESA_FORMAT_RGBA_FLOAT32] = _mesa_texstore_rgba_float32;
4106      table[MESA_FORMAT_RGBA_FLOAT16] = _mesa_texstore_rgba_float16;
4107      table[MESA_FORMAT_RGB_FLOAT32] = _mesa_texstore_rgba_float32;
4108      table[MESA_FORMAT_RGB_FLOAT16] = _mesa_texstore_rgba_float16;
4109      table[MESA_FORMAT_ALPHA_FLOAT32] = _mesa_texstore_rgba_float32;
4110      table[MESA_FORMAT_ALPHA_FLOAT16] = _mesa_texstore_rgba_float16;
4111      table[MESA_FORMAT_LUMINANCE_FLOAT32] = _mesa_texstore_rgba_float32;
4112      table[MESA_FORMAT_LUMINANCE_FLOAT16] = _mesa_texstore_rgba_float16;
4113      table[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32] = _mesa_texstore_rgba_float32;
4114      table[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16] = _mesa_texstore_rgba_float16;
4115      table[MESA_FORMAT_INTENSITY_FLOAT32] = _mesa_texstore_rgba_float32;
4116      table[MESA_FORMAT_INTENSITY_FLOAT16] = _mesa_texstore_rgba_float16;
4117      table[MESA_FORMAT_R_FLOAT32] = _mesa_texstore_rgba_float32;
4118      table[MESA_FORMAT_R_FLOAT16] = _mesa_texstore_rgba_float16;
4119      table[MESA_FORMAT_RG_FLOAT32] = _mesa_texstore_rgba_float32;
4120      table[MESA_FORMAT_RG_FLOAT16] = _mesa_texstore_rgba_float16;
4121      table[MESA_FORMAT_DUDV8] = _mesa_texstore_dudv8;
4122      table[MESA_FORMAT_SIGNED_R8] = _mesa_texstore_snorm8;
4123      table[MESA_FORMAT_SIGNED_RG88_REV] = _mesa_texstore_snorm88;
4124      table[MESA_FORMAT_SIGNED_RGBX8888] = _mesa_texstore_signed_rgbx8888;
4125      table[MESA_FORMAT_SIGNED_RGBA8888] = _mesa_texstore_signed_rgba8888;
4126      table[MESA_FORMAT_SIGNED_RGBA8888_REV] = _mesa_texstore_signed_rgba8888;
4127      table[MESA_FORMAT_SIGNED_R16] = _mesa_texstore_snorm16;
4128      table[MESA_FORMAT_SIGNED_GR1616] = _mesa_texstore_snorm1616;
4129      table[MESA_FORMAT_SIGNED_RGB_16] = _mesa_texstore_signed_rgba_16;
4130      table[MESA_FORMAT_SIGNED_RGBA_16] = _mesa_texstore_signed_rgba_16;
4131      table[MESA_FORMAT_RGBA_16] = _mesa_texstore_rgba_16;
4132      table[MESA_FORMAT_RED_RGTC1] = _mesa_texstore_red_rgtc1;
4133      table[MESA_FORMAT_SIGNED_RED_RGTC1] = _mesa_texstore_signed_red_rgtc1;
4134      table[MESA_FORMAT_RG_RGTC2] = _mesa_texstore_rg_rgtc2;
4135      table[MESA_FORMAT_SIGNED_RG_RGTC2] = _mesa_texstore_signed_rg_rgtc2;
4136      table[MESA_FORMAT_L_LATC1] = _mesa_texstore_red_rgtc1;
4137      table[MESA_FORMAT_SIGNED_L_LATC1] = _mesa_texstore_signed_red_rgtc1;
4138      table[MESA_FORMAT_LA_LATC2] = _mesa_texstore_rg_rgtc2;
4139      table[MESA_FORMAT_SIGNED_LA_LATC2] = _mesa_texstore_signed_rg_rgtc2;
4140      table[MESA_FORMAT_ETC1_RGB8] = _mesa_texstore_etc1_rgb8;
4141      table[MESA_FORMAT_SIGNED_A8] = _mesa_texstore_snorm8;
4142      table[MESA_FORMAT_SIGNED_L8] = _mesa_texstore_snorm8;
4143      table[MESA_FORMAT_SIGNED_AL88] = _mesa_texstore_snorm88;
4144      table[MESA_FORMAT_SIGNED_I8] = _mesa_texstore_snorm8;
4145      table[MESA_FORMAT_SIGNED_A16] = _mesa_texstore_snorm16;
4146      table[MESA_FORMAT_SIGNED_L16] = _mesa_texstore_snorm16;
4147      table[MESA_FORMAT_SIGNED_AL1616] = _mesa_texstore_snorm1616;
4148      table[MESA_FORMAT_SIGNED_I16] = _mesa_texstore_snorm16;
4149      table[MESA_FORMAT_RGB9_E5_FLOAT] = _mesa_texstore_rgb9_e5;
4150      table[MESA_FORMAT_R11_G11_B10_FLOAT] = _mesa_texstore_r11_g11_b10f;
4151      table[MESA_FORMAT_Z32_FLOAT] = _mesa_texstore_z32;
4152      table[MESA_FORMAT_Z32_FLOAT_X24S8] = _mesa_texstore_z32f_x24s8;
4153
4154      table[MESA_FORMAT_ALPHA_UINT8] = _mesa_texstore_rgba_uint8;
4155      table[MESA_FORMAT_ALPHA_UINT16] = _mesa_texstore_rgba_uint16;
4156      table[MESA_FORMAT_ALPHA_UINT32] = _mesa_texstore_rgba_uint32;
4157      table[MESA_FORMAT_ALPHA_INT8] = _mesa_texstore_rgba_int8;
4158      table[MESA_FORMAT_ALPHA_INT16] = _mesa_texstore_rgba_int16;
4159      table[MESA_FORMAT_ALPHA_INT32] = _mesa_texstore_rgba_int32;
4160
4161      table[MESA_FORMAT_INTENSITY_UINT8] = _mesa_texstore_rgba_uint8;
4162      table[MESA_FORMAT_INTENSITY_UINT16] = _mesa_texstore_rgba_uint16;
4163      table[MESA_FORMAT_INTENSITY_UINT32] = _mesa_texstore_rgba_uint32;
4164      table[MESA_FORMAT_INTENSITY_INT8] = _mesa_texstore_rgba_int8;
4165      table[MESA_FORMAT_INTENSITY_INT16] = _mesa_texstore_rgba_int16;
4166      table[MESA_FORMAT_INTENSITY_INT32] = _mesa_texstore_rgba_int32;
4167
4168      table[MESA_FORMAT_LUMINANCE_UINT8] = _mesa_texstore_rgba_uint8;
4169      table[MESA_FORMAT_LUMINANCE_UINT16] = _mesa_texstore_rgba_uint16;
4170      table[MESA_FORMAT_LUMINANCE_UINT32] = _mesa_texstore_rgba_uint32;
4171      table[MESA_FORMAT_LUMINANCE_INT8] = _mesa_texstore_rgba_int8;
4172      table[MESA_FORMAT_LUMINANCE_INT16] = _mesa_texstore_rgba_int16;
4173      table[MESA_FORMAT_LUMINANCE_INT32] = _mesa_texstore_rgba_int32;
4174
4175      table[MESA_FORMAT_LUMINANCE_ALPHA_UINT8] = _mesa_texstore_rgba_uint8;
4176      table[MESA_FORMAT_LUMINANCE_ALPHA_UINT16] = _mesa_texstore_rgba_uint16;
4177      table[MESA_FORMAT_LUMINANCE_ALPHA_UINT32] = _mesa_texstore_rgba_uint32;
4178      table[MESA_FORMAT_LUMINANCE_ALPHA_INT8] = _mesa_texstore_rgba_int8;
4179      table[MESA_FORMAT_LUMINANCE_ALPHA_INT16] = _mesa_texstore_rgba_int16;
4180      table[MESA_FORMAT_LUMINANCE_ALPHA_INT32] = _mesa_texstore_rgba_int32;
4181
4182      table[MESA_FORMAT_R_INT8] = _mesa_texstore_rgba_int8;
4183      table[MESA_FORMAT_RG_INT8] = _mesa_texstore_rgba_int8;
4184      table[MESA_FORMAT_RGB_INT8] = _mesa_texstore_rgba_int8;
4185      table[MESA_FORMAT_RGBA_INT8] = _mesa_texstore_rgba_int8;
4186      table[MESA_FORMAT_R_INT16] = _mesa_texstore_rgba_int16;
4187      table[MESA_FORMAT_RG_INT16] = _mesa_texstore_rgba_int16;
4188      table[MESA_FORMAT_RGB_INT16] = _mesa_texstore_rgba_int16;
4189      table[MESA_FORMAT_RGBA_INT16] = _mesa_texstore_rgba_int16;
4190      table[MESA_FORMAT_R_INT32] = _mesa_texstore_rgba_int32;
4191      table[MESA_FORMAT_RG_INT32] = _mesa_texstore_rgba_int32;
4192      table[MESA_FORMAT_RGB_INT32] = _mesa_texstore_rgba_int32;
4193      table[MESA_FORMAT_RGBA_INT32] = _mesa_texstore_rgba_int32;
4194
4195      table[MESA_FORMAT_R_UINT8] = _mesa_texstore_rgba_uint8;
4196      table[MESA_FORMAT_RG_UINT8] = _mesa_texstore_rgba_uint8;
4197      table[MESA_FORMAT_RGB_UINT8] = _mesa_texstore_rgba_uint8;
4198      table[MESA_FORMAT_RGBA_UINT8] = _mesa_texstore_rgba_uint8;
4199      table[MESA_FORMAT_R_UINT16] = _mesa_texstore_rgba_uint16;
4200      table[MESA_FORMAT_RG_UINT16] = _mesa_texstore_rgba_uint16;
4201      table[MESA_FORMAT_RGB_UINT16] = _mesa_texstore_rgba_uint16;
4202      table[MESA_FORMAT_RGBA_UINT16] = _mesa_texstore_rgba_uint16;
4203      table[MESA_FORMAT_R_UINT32] = _mesa_texstore_rgba_uint32;
4204      table[MESA_FORMAT_RG_UINT32] = _mesa_texstore_rgba_uint32;
4205      table[MESA_FORMAT_RGB_UINT32] = _mesa_texstore_rgba_uint32;
4206      table[MESA_FORMAT_RGBA_UINT32] = _mesa_texstore_rgba_uint32;
4207
4208      table[MESA_FORMAT_ARGB2101010_UINT] = _mesa_texstore_argb2101010_uint;
4209      table[MESA_FORMAT_ABGR2101010_UINT] = _mesa_texstore_abgr2101010_uint;
4210      initialized = GL_TRUE;
4211   }
4212
4213   ASSERT(table[format]);
4214   return table[format];
4215}
4216
4217
4218/**
4219 * Store user data into texture memory.
4220 * Called via glTex[Sub]Image1/2/3D()
4221 */
4222GLboolean
4223_mesa_texstore(TEXSTORE_PARAMS)
4224{
4225   StoreTexImageFunc storeImage;
4226   GLboolean success;
4227
4228   storeImage = _mesa_get_texstore_func(dstFormat);
4229
4230   success = storeImage(ctx, dims, baseInternalFormat,
4231                        dstFormat,
4232                        dstRowStride, dstSlices,
4233                        srcWidth, srcHeight, srcDepth,
4234                        srcFormat, srcType, srcAddr, srcPacking);
4235   return success;
4236}
4237
4238
4239/**
4240 * Normally, we'll only _write_ texel data to a texture when we map it.
4241 * But if the user is providing depth or stencil values and the texture
4242 * image is a combined depth/stencil format, we'll actually read from
4243 * the texture buffer too (in order to insert the depth or stencil values.
4244 * \param userFormat  the user-provided image format
4245 * \param texFormat  the destination texture format
4246 */
4247static GLbitfield
4248get_read_write_mode(GLenum userFormat, gl_format texFormat)
4249{
4250   if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT)
4251       && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL)
4252      return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
4253   else
4254      return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
4255}
4256
4257
4258/**
4259 * Helper function for storing 1D, 2D, 3D whole and subimages into texture
4260 * memory.
4261 * The source of the image data may be user memory or a PBO.  In the later
4262 * case, we'll map the PBO, copy from it, then unmap it.
4263 */
4264static void
4265store_texsubimage(struct gl_context *ctx,
4266                  struct gl_texture_image *texImage,
4267                  GLint xoffset, GLint yoffset, GLint zoffset,
4268                  GLint width, GLint height, GLint depth,
4269                  GLenum format, GLenum type, const GLvoid *pixels,
4270                  const struct gl_pixelstore_attrib *packing,
4271                  const char *caller)
4272
4273{
4274   const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat);
4275   const GLenum target = texImage->TexObject->Target;
4276   GLboolean success = GL_FALSE;
4277   GLuint dims, slice, numSlices = 1, sliceOffset = 0;
4278   GLint srcImageStride = 0;
4279   const GLubyte *src;
4280
4281   assert(xoffset + width <= texImage->Width);
4282   assert(yoffset + height <= texImage->Height);
4283   assert(zoffset + depth <= texImage->Depth);
4284
4285   switch (target) {
4286   case GL_TEXTURE_1D:
4287      dims = 1;
4288      break;
4289   case GL_TEXTURE_2D_ARRAY:
4290   case GL_TEXTURE_3D:
4291      dims = 3;
4292      break;
4293   default:
4294      dims = 2;
4295   }
4296
4297   /* get pointer to src pixels (may be in a pbo which we'll map here) */
4298   src = (const GLubyte *)
4299      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
4300                                  format, type, pixels, packing, caller);
4301   if (!src)
4302      return;
4303
4304   /* compute slice info (and do some sanity checks) */
4305   switch (target) {
4306   case GL_TEXTURE_2D:
4307   case GL_TEXTURE_RECTANGLE:
4308   case GL_TEXTURE_CUBE_MAP:
4309      /* one image slice, nothing special needs to be done */
4310      break;
4311   case GL_TEXTURE_1D:
4312      assert(height == 1);
4313      assert(depth == 1);
4314      assert(yoffset == 0);
4315      assert(zoffset == 0);
4316      break;
4317   case GL_TEXTURE_1D_ARRAY:
4318      assert(depth == 1);
4319      assert(zoffset == 0);
4320      numSlices = height;
4321      sliceOffset = yoffset;
4322      height = 1;
4323      yoffset = 0;
4324      srcImageStride = _mesa_image_row_stride(packing, width, format, type);
4325      break;
4326   case GL_TEXTURE_2D_ARRAY:
4327      numSlices = depth;
4328      sliceOffset = zoffset;
4329      depth = 1;
4330      zoffset = 0;
4331      srcImageStride = _mesa_image_image_stride(packing, width, height,
4332                                                format, type);
4333      break;
4334   case GL_TEXTURE_3D:
4335      /* we'll store 3D images as a series of slices */
4336      numSlices = depth;
4337      sliceOffset = zoffset;
4338      srcImageStride = _mesa_image_image_stride(packing, width, height,
4339                                                format, type);
4340      break;
4341   default:
4342      _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target);
4343      return;
4344   }
4345
4346   assert(numSlices == 1 || srcImageStride != 0);
4347
4348   for (slice = 0; slice < numSlices; slice++) {
4349      GLubyte *dstMap;
4350      GLint dstRowStride;
4351
4352      ctx->Driver.MapTextureImage(ctx, texImage,
4353                                  slice + sliceOffset,
4354                                  xoffset, yoffset, width, height,
4355                                  mapMode, &dstMap, &dstRowStride);
4356      if (dstMap) {
4357         /* Note: we're only storing a 2D (or 1D) slice at a time but we need
4358          * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
4359          * used for 3D images.
4360          */
4361         success = _mesa_texstore(ctx, dims, texImage->_BaseFormat,
4362                                  texImage->TexFormat,
4363                                  dstRowStride,
4364                                  &dstMap,
4365                                  width, height, 1,  /* w, h, d */
4366                                  format, type, src, packing);
4367
4368         ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
4369      }
4370
4371      src += srcImageStride;
4372
4373      if (!success)
4374         break;
4375   }
4376
4377   if (!success)
4378      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
4379
4380   _mesa_unmap_teximage_pbo(ctx, packing);
4381}
4382
4383
4384
4385/**
4386 * Fallback code for ctx->Driver.TexImage().
4387 * Basically, allocate storage for the texture image, then copy the
4388 * user's image into it.
4389 */
4390void
4391_mesa_store_teximage(struct gl_context *ctx,
4392                     GLuint dims,
4393                     struct gl_texture_image *texImage,
4394                     GLenum format, GLenum type, const GLvoid *pixels,
4395                     const struct gl_pixelstore_attrib *packing)
4396{
4397   assert(dims == 1 || dims == 2 || dims == 3);
4398
4399   if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
4400      return;
4401
4402   /* allocate storage for texture data */
4403   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
4404      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
4405      return;
4406   }
4407
4408   store_texsubimage(ctx, texImage,
4409                     0, 0, 0, texImage->Width, texImage->Height, texImage->Depth,
4410                     format, type, pixels, packing, "glTexImage");
4411}
4412
4413
4414/*
4415 * Fallback for Driver.TexSubImage().
4416 */
4417void
4418_mesa_store_texsubimage(struct gl_context *ctx, GLuint dims,
4419                        struct gl_texture_image *texImage,
4420                        GLint xoffset, GLint yoffset, GLint zoffset,
4421                        GLint width, GLint height, GLint depth,
4422                        GLenum format, GLenum type, const void *pixels,
4423                        const struct gl_pixelstore_attrib *packing)
4424{
4425   store_texsubimage(ctx, texImage,
4426                     xoffset, yoffset, zoffset, width, height, depth,
4427                     format, type, pixels, packing, "glTexSubImage");
4428}
4429
4430
4431/**
4432 * Fallback for Driver.CompressedTexImage()
4433 */
4434void
4435_mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims,
4436                                struct gl_texture_image *texImage,
4437                                GLsizei imageSize, const GLvoid *data)
4438{
4439   /* only 2D compressed images are supported at this time */
4440   if (dims != 2) {
4441      _mesa_problem(ctx, "Unexpected glCompressedTexImage1D/3D call");
4442      return;
4443   }
4444
4445   /* This is pretty simple, because unlike the general texstore path we don't
4446    * have to worry about the usual image unpacking or image transfer
4447    * operations.
4448    */
4449   ASSERT(texImage);
4450   ASSERT(texImage->Width > 0);
4451   ASSERT(texImage->Height > 0);
4452   ASSERT(texImage->Depth == 1);
4453
4454   /* allocate storage for texture data */
4455   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
4456      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
4457      return;
4458   }
4459
4460   _mesa_store_compressed_texsubimage(ctx, dims, texImage,
4461                                      0, 0, 0,
4462                                      texImage->Width, texImage->Height, texImage->Depth,
4463                                      texImage->TexFormat,
4464                                      imageSize, data);
4465}
4466
4467
4468/**
4469 * Fallback for Driver.CompressedTexSubImage()
4470 */
4471void
4472_mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
4473                                   struct gl_texture_image *texImage,
4474                                   GLint xoffset, GLint yoffset, GLint zoffset,
4475                                   GLsizei width, GLsizei height, GLsizei depth,
4476                                   GLenum format,
4477                                   GLsizei imageSize, const GLvoid *data)
4478{
4479   GLint bytesPerRow, dstRowStride, srcRowStride;
4480   GLint i, rows;
4481   GLubyte *dstMap;
4482   const GLubyte *src;
4483   const gl_format texFormat = texImage->TexFormat;
4484   GLuint bw, bh;
4485
4486   if (dims != 2) {
4487      _mesa_problem(ctx, "Unexpected 1D/3D compressed texsubimage call");
4488      return;
4489   }
4490
4491   _mesa_get_format_block_size(texFormat, &bw, &bh);
4492
4493   /* get pointer to src pixels (may be in a pbo which we'll map here) */
4494   data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
4495                                                 &ctx->Unpack,
4496                                                 "glCompressedTexSubImage2D");
4497   if (!data)
4498      return;
4499
4500   srcRowStride = _mesa_format_row_stride(texFormat, width);
4501   src = (const GLubyte *) data;
4502
4503   /* Map dest texture buffer */
4504   ctx->Driver.MapTextureImage(ctx, texImage, 0,
4505                               xoffset, yoffset, width, height,
4506                               GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
4507                               &dstMap, &dstRowStride);
4508
4509   if (dstMap) {
4510      bytesPerRow = srcRowStride;  /* bytes per row of blocks */
4511      rows = (height + bh - 1) / bh;  /* rows in blocks */
4512
4513      /* copy rows of blocks */
4514      for (i = 0; i < rows; i++) {
4515         memcpy(dstMap, src, bytesPerRow);
4516         dstMap += dstRowStride;
4517         src += srcRowStride;
4518      }
4519
4520      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
4521   }
4522   else {
4523      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
4524   }
4525
4526   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
4527}
4528