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