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