texstore.c revision 8f04c12e0ad876baa7eb9ed379e2b00150b376e0
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.1
4 *
5 * Copyright (C) 1999-2004  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 = 1000, ONE = 1001;
69
70/**
71 * When promoting texture formats (see below) we need to compute the
72 * mapping of dest components back to source components.
73 * This function does that.
74 * \param logicalBaseFormat  the logical format of the texture
75 * \param textureBaseFormat  the final texture format
76 * \return map[4]  the four mapping values
77 */
78static void
79compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
80                          GLint map[4])
81{
82   /* compute mapping from dest components back to src components */
83   switch (logicalBaseFormat) {
84   case GL_LUMINANCE:
85      map[0] = map[1] = map[2] = 0;
86      if (textureBaseFormat == GL_RGBA)
87         map[3] = ONE;
88      break;
89   case GL_ALPHA:
90      ASSERT(textureBaseFormat == GL_RGBA);
91      map[0] = map[1] = map[2] = ZERO;
92      map[3] = 0;
93      break;
94   case GL_INTENSITY:
95      map[0] = map[1] = map[2] = 0;
96      if (textureBaseFormat == GL_RGBA)
97         map[3] = 0;
98      break;
99   case GL_LUMINANCE_ALPHA:
100      ASSERT(textureBaseFormat == GL_RGBA);
101      map[0] = map[1] = map[2] = 0;
102      map[3] = 1;
103      break;
104   case GL_RGB:
105      ASSERT(textureBaseFormat == GL_RGBA);
106      map[0] = 0;
107      map[1] = 1;
108      map[2] = 2;
109      map[3] = ONE;
110      break;
111   default:
112      _mesa_problem(NULL, "Unexpected logicalBaseFormat");
113      map[0] = map[1] = map[2] = map[3] = 0;
114   }
115}
116
117
118/**
119 * Make a temporary (color) texture image with GLfloat components.
120 * Apply all needed pixel unpacking and pixel transfer operations.
121 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
122 * Suppose the user specifies GL_LUMINANCE as the internal texture format
123 * but the graphics hardware doesn't support luminance textures.  So, might
124 * use an RGB hardware format instead.
125 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
126 *
127 * \param ctx  the rendering context
128 * \param dims  image dimensions: 1, 2 or 3
129 * \param logicalBaseFormat  basic texture derived from the user's
130 *    internal texture format value
131 * \param textureBaseFormat  the actual basic format of the texture
132 * \param srcWidth  source image width
133 * \param srcHeight  source image height
134 * \param srcDepth  source image depth
135 * \param srcFormat  source image format
136 * \param srcType  source image type
137 * \param srcAddr  source image address
138 * \param srcPacking  source image pixel packing
139 * \return resulting image with format = textureBaseFormat and type = GLfloat.
140 */
141static GLfloat *
142make_temp_float_image(GLcontext *ctx, GLuint dims,
143                      GLenum logicalBaseFormat,
144                      GLenum textureBaseFormat,
145                      GLint srcWidth, GLint srcHeight, GLint srcDepth,
146                      GLenum srcFormat, GLenum srcType,
147                      const GLvoid *srcAddr,
148                      const struct gl_pixelstore_attrib *srcPacking)
149{
150   GLuint transferOps = ctx->_ImageTransferState;
151   GLfloat *tempImage;
152
153   ASSERT(dims >= 1 && dims <= 3);
154
155   ASSERT(logicalBaseFormat == GL_RGBA ||
156          logicalBaseFormat == GL_RGB ||
157          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
158          logicalBaseFormat == GL_LUMINANCE ||
159          logicalBaseFormat == GL_ALPHA ||
160          logicalBaseFormat == GL_INTENSITY ||
161          logicalBaseFormat == GL_COLOR_INDEX ||
162          logicalBaseFormat == GL_DEPTH_COMPONENT);
163
164   ASSERT(textureBaseFormat == GL_RGBA ||
165          textureBaseFormat == GL_RGB ||
166          textureBaseFormat == GL_LUMINANCE_ALPHA ||
167          textureBaseFormat == GL_LUMINANCE ||
168          textureBaseFormat == GL_ALPHA ||
169          textureBaseFormat == GL_INTENSITY ||
170          textureBaseFormat == GL_COLOR_INDEX ||
171          textureBaseFormat == GL_DEPTH_COMPONENT);
172
173   /* conventional color image */
174
175   if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
176       (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
177       (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
178      /* need image convolution */
179      const GLuint preConvTransferOps
180         = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
181      const GLuint postConvTransferOps
182         = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
183      GLint img, row;
184      GLint convWidth, convHeight;
185      GLfloat *convImage;
186
187      /* pre-convolution image buffer (3D) */
188      tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
189                                           * 4 * sizeof(GLfloat));
190      if (!tempImage)
191         return NULL;
192
193      /* post-convolution image buffer (2D) */
194      convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight
195                                           * 4 * sizeof(GLfloat));
196      if (!convImage) {
197         _mesa_free(tempImage);
198         return NULL;
199      }
200
201      /* loop over 3D image slices */
202      for (img = 0; img < srcDepth; img++) {
203         GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4);
204
205         /* unpack and do transfer ops up to convolution */
206         for (row = 0; row < srcHeight; row++) {
207            const GLvoid *src = _mesa_image_address(srcPacking,
208                                              srcAddr, srcWidth, srcHeight,
209                                              srcFormat, srcType, img, row, 0);
210            _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
211                                          srcFormat, srcType, src,
212                                          srcPacking,
213                                          preConvTransferOps);
214            dst += srcWidth * 4;
215         }
216
217         /* do convolution */
218         {
219            GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
220            convWidth = srcWidth;
221            convHeight = srcHeight;
222            if (dims == 1) {
223               ASSERT(ctx->Pixel.Convolution1DEnabled);
224               _mesa_convolve_1d_image(ctx, &convWidth, src, convImage);
225            }
226            else {
227               if (ctx->Pixel.Convolution2DEnabled) {
228                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
229                                          src, convImage);
230               }
231               else {
232                  ASSERT(ctx->Pixel.Separable2DEnabled);
233                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
234                                           src, convImage);
235               }
236            }
237         }
238
239         /* do post-convolution transfer and pack into tempImage */
240         {
241            const GLfloat *src = convImage;
242            GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
243            for (row = 0; row < convHeight; row++) {
244               _mesa_pack_rgba_span_float(ctx, convWidth,
245                                          (const GLfloat (*)[4]) src,
246                                          logicalBaseFormat, GL_FLOAT,
247                                          dst, &ctx->DefaultPacking,
248                                          postConvTransferOps);
249               src += convWidth * 4;
250               dst += convWidth * 4;
251            }
252         }
253      } /* loop over 3D image slices */
254
255      _mesa_free(convImage);
256
257      /* might need these below */
258      srcWidth = convWidth;
259      srcHeight = convHeight;
260   }
261   else {
262      /* no convolution */
263      const GLint components = _mesa_components_in_format(logicalBaseFormat);
264      const GLint srcStride = _mesa_image_row_stride(srcPacking,
265                                                 srcWidth, srcFormat, srcType);
266      GLfloat *dst;
267      GLint img, row;
268
269      tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
270                                           * components * sizeof(GLfloat));
271      if (!tempImage)
272         return NULL;
273
274      dst = tempImage;
275      for (img = 0; img < srcDepth; img++) {
276         const GLubyte *src
277            = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr,
278                                                    srcWidth, srcHeight,
279                                                    srcFormat, srcType,
280                                                    img, 0, 0);
281         for (row = 0; row < srcHeight; row++) {
282            _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
283                                          dst, srcFormat, srcType, src,
284                                          srcPacking, transferOps);
285            dst += srcWidth * components;
286            src += srcStride;
287         }
288      }
289   }
290
291   if (logicalBaseFormat != textureBaseFormat) {
292      /* more work */
293      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
294      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
295      GLfloat *newImage;
296      GLint i, n;
297      GLint map[4];
298
299      /* we only promote up to RGB and RGBA formats for now */
300      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA);
301
302      /* The actual texture format should have at least as many components
303       * as the logical texture format.
304       */
305      ASSERT(texComponents >= logComponents);
306
307      newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
308                                          * texComponents * sizeof(GLfloat));
309      if (!newImage) {
310         _mesa_free(tempImage);
311         return NULL;
312      }
313
314      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
315
316      n = srcWidth * srcHeight * srcDepth;
317      for (i = 0; i < n; i++) {
318         GLint k;
319         for (k = 0; k < texComponents; k++) {
320            GLint j = map[k];
321            if (j == ZERO)
322               newImage[i * texComponents + k] = 0.0F;
323            else if (j == ONE)
324               newImage[i * texComponents + k] = 1.0F;
325            else
326               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
327         }
328      }
329
330      _mesa_free(tempImage);
331      tempImage = newImage;
332   }
333
334   return tempImage;
335}
336
337
338/**
339 * Make a temporary (color) texture image with GLchan components.
340 * Apply all needed pixel unpacking and pixel transfer operations.
341 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
342 * Suppose the user specifies GL_LUMINANCE as the internal texture format
343 * but the graphics hardware doesn't support luminance textures.  So, might
344 * use an RGB hardware format instead.
345 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
346 *
347 * \param ctx  the rendering context
348 * \param dims  image dimensions: 1, 2 or 3
349 * \param logicalBaseFormat  basic texture derived from the user's
350 *    internal texture format value
351 * \param textureBaseFormat  the actual basic format of the texture
352 * \param srcWidth  source image width
353 * \param srcHeight  source image height
354 * \param srcDepth  source image depth
355 * \param srcFormat  source image format
356 * \param srcType  source image type
357 * \param srcAddr  source image address
358 * \param srcPacking  source image pixel packing
359 * \return resulting image with format = textureBaseFormat and type = GLchan.
360 */
361GLchan *
362_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
363                           GLenum logicalBaseFormat,
364                           GLenum textureBaseFormat,
365                           GLint srcWidth, GLint srcHeight, GLint srcDepth,
366                           GLenum srcFormat, GLenum srcType,
367                           const GLvoid *srcAddr,
368                           const struct gl_pixelstore_attrib *srcPacking)
369{
370   GLuint transferOps = ctx->_ImageTransferState;
371   const GLint components = _mesa_components_in_format(logicalBaseFormat);
372   GLboolean freeSrcImage = GL_FALSE;
373   GLint img, row;
374   GLchan *tempImage, *dst;
375
376   ASSERT(dims >= 1 && dims <= 3);
377
378   ASSERT(logicalBaseFormat == GL_RGBA ||
379          logicalBaseFormat == GL_RGB ||
380          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
381          logicalBaseFormat == GL_LUMINANCE ||
382          logicalBaseFormat == GL_ALPHA ||
383          logicalBaseFormat == GL_INTENSITY);
384
385   ASSERT(textureBaseFormat == GL_RGBA ||
386          textureBaseFormat == GL_RGB ||
387          textureBaseFormat == GL_LUMINANCE_ALPHA ||
388          textureBaseFormat == GL_LUMINANCE ||
389          textureBaseFormat == GL_ALPHA ||
390          textureBaseFormat == GL_INTENSITY);
391
392   if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
393       (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
394       (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
395      /* get convolved image */
396      GLfloat *convImage = make_temp_float_image(ctx, dims,
397                                                 logicalBaseFormat,
398                                                 logicalBaseFormat,
399                                                 srcWidth, srcHeight, srcDepth,
400                                                 srcFormat, srcType,
401                                                 srcAddr, srcPacking);
402      if (!convImage)
403         return NULL;
404      /* the convolved image is our new source image */
405      srcAddr = convImage;
406      srcFormat = logicalBaseFormat;
407      srcType = GL_FLOAT;
408      srcPacking = &ctx->DefaultPacking;
409      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
410      transferOps = 0;
411      freeSrcImage = GL_TRUE;
412   }
413
414   /* unpack and transfer the source image */
415   tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
416                                       * components * sizeof(GLchan));
417   if (!tempImage)
418      return NULL;
419
420   dst = tempImage;
421   for (img = 0; img < srcDepth; img++) {
422      const GLint srcStride = _mesa_image_row_stride(srcPacking,
423                                                     srcWidth, srcFormat,
424                                                     srcType);
425      const GLubyte *src
426         = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr,
427                                                 srcWidth, srcHeight,
428                                                 srcFormat, srcType,
429                                                 img, 0, 0);
430      for (row = 0; row < srcHeight; row++) {
431         _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat,
432                                      dst, srcFormat, srcType, src,
433                                      srcPacking, transferOps);
434         dst += srcWidth * components;
435         src += srcStride;
436      }
437   }
438
439   /* If we made a temporary image for convolution, free it here */
440   if (freeSrcImage) {
441      _mesa_free((void *) srcAddr);
442   }
443
444   if (logicalBaseFormat != textureBaseFormat) {
445      /* one more conversion step */
446      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
447      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
448      GLchan *newImage;
449      GLint i, n;
450      GLint map[4];
451
452      /* we only promote up to RGB and RGBA formats for now */
453      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA);
454
455      /* The actual texture format should have at least as many components
456       * as the logical texture format.
457       */
458      ASSERT(texComponents >= logComponents);
459
460      newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
461                                          * texComponents * sizeof(GLchan));
462      if (!newImage) {
463         _mesa_free(tempImage);
464         return NULL;
465      }
466
467      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
468
469      n = srcWidth * srcHeight * srcDepth;
470      for (i = 0; i < n; i++) {
471         GLint k;
472         for (k = 0; k < texComponents; k++) {
473            GLint j = map[k];
474            if (j == ZERO)
475               newImage[i * texComponents + k] = 0;
476            else if (j == ONE)
477               newImage[i * texComponents + k] = CHAN_MAX;
478            else
479               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
480         }
481      }
482
483      _mesa_free(tempImage);
484      tempImage = newImage;
485   }
486
487   return tempImage;
488}
489
490
491
492/**
493 * Teximage storage routine for when a simple memcpy will do.
494 * No pixel transfer operations or special texel encodings allowed.
495 * 1D, 2D and 3D images supported.
496 */
497static void
498memcpy_texture(const struct gl_texture_format *dstFormat,
499               GLvoid *dstAddr,
500               GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
501               GLint dstRowStride, GLint dstImageStride,
502               GLint srcWidth, GLint srcHeight, GLint srcDepth,
503               GLenum srcFormat, GLenum srcType,
504               const GLvoid *srcAddr,
505               const struct gl_pixelstore_attrib *srcPacking)
506{
507   const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
508                                                     srcFormat, srcType);
509   const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
510                                      srcWidth, srcHeight, srcFormat, srcType);
511   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(srcPacking,
512                    srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
513   const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
514   const GLint bytesPerImage = srcHeight * bytesPerRow;
515   const GLint bytesPerTexture = srcDepth * bytesPerImage;
516   GLubyte *dstImage = (GLubyte *) dstAddr
517                     + dstZoffset * dstImageStride
518                     + dstYoffset * dstRowStride
519                     + dstXoffset * dstFormat->TexelBytes;
520
521   if (dstRowStride == srcRowStride &&
522       dstRowStride == bytesPerRow &&
523       ((dstImageStride == srcImageStride &&
524         dstImageStride == bytesPerImage) ||
525        (srcDepth == 1))) {
526      /* one big memcpy */
527      _mesa_memcpy(dstImage, srcImage, bytesPerTexture);
528   }
529   else {
530      GLint img, row;
531      for (img = 0; img < srcDepth; img++) {
532         const GLubyte *srcRow = srcImage;
533         GLubyte *dstRow = dstImage;
534         for (row = 0; row < srcHeight; row++) {
535            _mesa_memcpy(dstRow, srcRow, bytesPerRow);
536            dstRow += dstRowStride;
537            srcRow += srcRowStride;
538         }
539         srcImage += srcImageStride;
540         dstImage += dstImageStride;
541      }
542   }
543}
544
545
546
547/**
548 * Store an image in any of the formats:
549 *   _mesa_texformat_rgba
550 *   _mesa_texformat_rgb
551 *   _mesa_texformat_alpha
552 *   _mesa_texformat_luminance
553 *   _mesa_texformat_luminance_alpha
554 *   _mesa_texformat_intensity
555 *
556 * \param dims  either 1 or 2 or 3
557 * \param baseInternalFormat  user-specified base internal format
558 * \param dstFormat  destination Mesa texture format
559 * \param dstAddr  destination image address
560 * \param dstX/Y/Zoffset  destination x/y/z offset (ala TexSubImage), in texels
561 * \param dstRowStride  destination image row stride, in bytes
562 * \param dstImageStride  destination image layer stride, in bytes
563 * \param srcWidth/Height/Depth  source image size, in pixels
564 * \param srcFormat  incoming image format
565 * \param srcType  incoming image data type
566 * \param srcAddr  source image address
567 * \param srcPacking  source image packing parameters
568 */
569GLboolean
570_mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
571                    GLenum baseInternalFormat,
572                    const struct gl_texture_format *dstFormat,
573                    GLvoid *dstAddr,
574                    GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
575                    GLint dstRowStride, GLint dstImageStride,
576                    GLint srcWidth, GLint srcHeight, GLint srcDepth,
577                    GLenum srcFormat, GLenum srcType,
578                    const GLvoid *srcAddr,
579                    const struct gl_pixelstore_attrib *srcPacking)
580{
581   const GLint components = _mesa_components_in_format(baseInternalFormat);
582
583   ASSERT(dstFormat == &_mesa_texformat_rgba ||
584          dstFormat == &_mesa_texformat_rgb ||
585          dstFormat == &_mesa_texformat_alpha ||
586          dstFormat == &_mesa_texformat_luminance ||
587          dstFormat == &_mesa_texformat_luminance_alpha ||
588          dstFormat == &_mesa_texformat_intensity);
589   ASSERT(baseInternalFormat == GL_RGBA ||
590          baseInternalFormat == GL_RGB ||
591          baseInternalFormat == GL_ALPHA ||
592          baseInternalFormat == GL_LUMINANCE ||
593          baseInternalFormat == GL_LUMINANCE_ALPHA ||
594          baseInternalFormat == GL_INTENSITY);
595   ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan));
596
597   if (!ctx->_ImageTransferState &&
598       !srcPacking->SwapBytes &&
599       baseInternalFormat == srcFormat &&
600       srcType == CHAN_TYPE) {
601      /* simple memcpy path */
602      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
603                     dstRowStride, dstImageStride,
604                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
605                     srcAddr, srcPacking);
606   }
607   else if (!ctx->_ImageTransferState &&
608            !srcPacking->SwapBytes &&
609            dstFormat == &_mesa_texformat_rgb &&
610            srcFormat == GL_RGBA &&
611            srcType == CHAN_TYPE) {
612      /* extract RGB from RGBA */
613      int img, row, col;
614      GLchan *dstImage = (GLchan *) (GLubyte *) dstAddr
615                       + dstZoffset * dstImageStride
616                       + dstYoffset * dstRowStride
617                       + dstXoffset * dstFormat->TexelBytes;
618      for (img = 0; img < srcDepth; img++) {
619         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
620                                                 srcWidth, srcFormat, srcType);
621         GLchan *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth,
622                                              srcHeight, srcFormat, srcType,
623                                              img, 0, 0);
624         GLchan *dstRow = dstImage;
625         for (row = 0; row < srcHeight; row++) {
626            for (col = 0; col < srcWidth; col++) {
627               dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
628               dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
629               dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
630            }
631            dstRow += dstRowStride;
632            srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
633         }
634         dstImage += dstImageStride;
635      }
636   }
637   else {
638      /* general path */
639      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
640                                                 baseInternalFormat,
641                                                 dstFormat->BaseFormat,
642                                                 srcWidth, srcHeight, srcDepth,
643                                                 srcFormat, srcType, srcAddr,
644                                                 srcPacking);
645      const GLchan *src = tempImage;
646      const GLint bytesPerRow = srcWidth * components * sizeof(GLchan);
647      GLubyte *dstImage = (GLubyte *) dstAddr
648                        + dstZoffset * dstImageStride
649                        + dstYoffset * dstRowStride
650                        + dstXoffset * dstFormat->TexelBytes;
651      GLint img, row;
652      if (!tempImage)
653         return GL_FALSE;
654      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
655      for (img = 0; img < srcDepth; img++) {
656         GLubyte *dstRow = dstImage;
657         for (row = 0; row < srcHeight; row++) {
658            _mesa_memcpy(dstRow, src, bytesPerRow);
659            dstRow += dstRowStride;
660            src += srcWidth * components;
661         }
662         dstImage += dstImageStride;
663      }
664
665      _mesa_free((void *) tempImage);
666   }
667   return GL_TRUE;
668}
669
670
671/**
672 * Store a color index texture image
673 */
674GLboolean
675_mesa_texstore_color_index(STORE_PARAMS)
676{
677   ASSERT(dstFormat == &_mesa_texformat_color_index);
678   ASSERT(dstFormat->TexelBytes == 1 * sizeof(GLchan));
679
680   if (!ctx->_ImageTransferState &&
681       !srcPacking->SwapBytes &&
682       baseInternalFormat == GL_COLOR_INDEX &&
683       srcFormat == GL_COLOR_INDEX &&
684       srcType == CHAN_TYPE) {
685      /* simple memcpy path */
686      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
687                     dstRowStride, dstImageStride,
688                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
689                     srcAddr, srcPacking);
690   }
691   else {
692      /* general path */
693      GLubyte *dstImage = (GLubyte *) dstAddr
694                        + dstZoffset * dstImageStride
695                        + dstYoffset * dstRowStride
696                        + dstXoffset * dstFormat->TexelBytes;
697      GLint img, row;
698      for (img = 0; img < srcDepth; img++) {
699         GLubyte *dstRow = dstImage;
700         for (row = 0; row < srcHeight; row++) {
701            const GLvoid *src = _mesa_image_address(srcPacking,
702                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
703            _mesa_unpack_index_span(ctx, srcWidth, CHAN_TYPE, dstRow,
704                                    srcType, src, srcPacking,
705                                    ctx->_ImageTransferState);
706            dstRow += dstRowStride;
707         }
708         dstImage += dstImageStride;
709      }
710   }
711   return GL_TRUE;
712}
713
714
715/**
716 * Store a floating point depth component texture image.
717 */
718GLboolean
719_mesa_texstore_depth_component_float32(STORE_PARAMS)
720{
721   ASSERT(dstFormat == &_mesa_texformat_depth_component_float32);
722   ASSERT(dstFormat->TexelBytes == sizeof(GLfloat));
723
724   if (!ctx->_ImageTransferState &&
725       !srcPacking->SwapBytes &&
726       baseInternalFormat == GL_DEPTH_COMPONENT &&
727       srcFormat == GL_DEPTH_COMPONENT &&
728       srcType == GL_FLOAT) {
729      /* simple memcpy path */
730      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
731                     dstRowStride, dstImageStride,
732                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
733                     srcAddr, srcPacking);
734   }
735   else {
736      /* general path */
737      GLubyte *dstImage = (GLubyte *) dstAddr
738                        + dstZoffset * dstImageStride
739                        + dstYoffset * dstRowStride
740                        + dstXoffset * dstFormat->TexelBytes;
741      GLint img, row;
742      for (img = 0; img < srcDepth; img++) {
743         GLubyte *dstRow = dstImage;
744         for (row = 0; row < srcHeight; row++) {
745            const GLvoid *src = _mesa_image_address(srcPacking,
746                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
747            _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) dstRow,
748                                    srcType, src, srcPacking);
749            dstRow += dstRowStride;
750         }
751         dstImage += dstImageStride;
752      }
753   }
754   return GL_TRUE;
755}
756
757
758/**
759 * Store a 16-bit integer depth component texture image.
760 */
761GLboolean
762_mesa_texstore_depth_component16(STORE_PARAMS)
763{
764   ASSERT(dstFormat == &_mesa_texformat_depth_component16);
765   ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
766
767   if (!ctx->_ImageTransferState &&
768       !srcPacking->SwapBytes &&
769       baseInternalFormat == GL_DEPTH_COMPONENT &&
770       srcFormat == GL_DEPTH_COMPONENT &&
771       srcType == GL_UNSIGNED_SHORT) {
772      /* simple memcpy path */
773      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
774                     dstRowStride, dstImageStride,
775                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
776                     srcAddr, srcPacking);
777   }
778   else {
779      /* general path */
780      GLubyte *dstImage = (GLubyte *) dstAddr
781                        + dstZoffset * dstImageStride
782                        + dstYoffset * dstRowStride
783                        + dstXoffset * dstFormat->TexelBytes;
784      GLint img, row, col;
785      for (img = 0; img < srcDepth; img++) {
786         GLubyte *dstRow = dstImage;
787         for (row = 0; row < srcHeight; row++) {
788            GLfloat depthTemp[MAX_WIDTH];
789            const GLvoid *src = _mesa_image_address(srcPacking,
790                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
791            GLushort *dst16 = (GLushort *) dstRow;
792            _mesa_unpack_depth_span(ctx, srcWidth, depthTemp,
793                                    srcType, src, srcPacking);
794            for (col = 0; col < srcWidth; col++) {
795               dst16[col] = (GLushort) (depthTemp[col] * 65535.0F);
796            }
797            dstRow += dstRowStride;
798         }
799         dstImage += dstImageStride;
800      }
801   }
802   return GL_TRUE;
803}
804
805
806
807
808/**
809 * Store an rgb565 texture image.
810 */
811GLboolean
812_mesa_texstore_rgb565(STORE_PARAMS)
813{
814   ASSERT(dstFormat == &_mesa_texformat_rgb565);
815   ASSERT(dstFormat->TexelBytes == 2);
816
817   if (!ctx->_ImageTransferState &&
818       !srcPacking->SwapBytes &&
819       baseInternalFormat == GL_RGB &&
820       srcFormat == GL_RGB &&
821       srcType == GL_UNSIGNED_SHORT_5_6_5) {
822      /* simple memcpy path */
823      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
824                     dstRowStride, dstImageStride,
825                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
826                     srcAddr, srcPacking);
827   }
828   else if (!ctx->_ImageTransferState &&
829            !srcPacking->SwapBytes &&
830            baseInternalFormat == GL_RGB &&
831            srcFormat == GL_RGB &&
832            srcType == GL_UNSIGNED_BYTE &&
833            dims == 2) {
834      /* do optimized tex store */
835      const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
836                                                        srcFormat, srcType);
837      const GLubyte *src = (const GLubyte *)
838         _mesa_image_address(srcPacking, srcAddr, srcWidth, srcHeight,
839                             srcFormat, srcType, 0, 0, 0);
840      GLubyte *dst = (GLubyte *) dstAddr
841                   + dstZoffset * dstImageStride
842                   + dstYoffset * dstRowStride
843                   + dstXoffset * dstFormat->TexelBytes;
844      GLint row, col;
845      for (row = 0; row < srcHeight; row++) {
846         const GLubyte *srcUB = (const GLubyte *) src;
847         GLushort *dstUS = (GLushort *) dst;
848         for (col = 0; col < srcWidth; col++) {
849            dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
850            srcUB += 3;
851         }
852         dst += dstRowStride;
853         src += srcRowStride;
854      }
855   }
856   else {
857      /* general path */
858      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
859                                                 baseInternalFormat,
860                                                 dstFormat->BaseFormat,
861                                                 srcWidth, srcHeight, srcDepth,
862                                                 srcFormat, srcType, srcAddr,
863                                                 srcPacking);
864      const GLchan *src = tempImage;
865      GLubyte *dstImage = (GLubyte *) dstAddr
866                        + dstZoffset * dstImageStride
867                        + dstYoffset * dstRowStride
868                        + dstXoffset * dstFormat->TexelBytes;
869      GLint img, row, col;
870      if (!tempImage)
871         return GL_FALSE;
872      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
873      for (img = 0; img < srcDepth; img++) {
874         GLubyte *dstRow = dstImage;
875         for (row = 0; row < srcHeight; row++) {
876            GLushort *dstUS = (GLushort *) dstRow;
877            for (col = 0; col < srcWidth; col++) {
878               dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
879                                            CHAN_TO_UBYTE(src[GCOMP]),
880                                            CHAN_TO_UBYTE(src[BCOMP]) );
881               src += 3;
882            }
883            dstRow += dstRowStride;
884         }
885         dstImage += dstImageStride;
886      }
887      _mesa_free((void *) tempImage);
888   }
889   return GL_TRUE;
890}
891
892
893GLboolean
894_mesa_texstore_rgba8888(STORE_PARAMS)
895{
896   const GLuint ui = 1;
897   const GLubyte littleEndian = *((const GLubyte *) &ui);
898
899   ASSERT(dstFormat == &_mesa_texformat_rgba8888);
900   ASSERT(dstFormat->TexelBytes == 4);
901
902   if (!ctx->_ImageTransferState &&
903       !srcPacking->SwapBytes &&
904       baseInternalFormat == GL_RGBA &&
905       srcFormat == GL_RGBA &&
906       ((srcType == GL_UNSIGNED_INT_8_8_8_8_REV && littleEndian) ||
907        (srcType == GL_UNSIGNED_INT_8_8_8_8 && !littleEndian))) {
908      /* simple memcpy path */
909      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
910                     dstRowStride, dstImageStride,
911                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
912                     srcAddr, srcPacking);
913   }
914   else {
915      /* general path */
916      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
917                                                 baseInternalFormat,
918                                                 dstFormat->BaseFormat,
919                                                 srcWidth, srcHeight, srcDepth,
920                                                 srcFormat, srcType, srcAddr,
921                                                 srcPacking);
922      const GLchan *src = tempImage;
923      GLubyte *dstImage = (GLubyte *) dstAddr
924                        + dstZoffset * dstImageStride
925                        + dstYoffset * dstRowStride
926                        + dstXoffset * dstFormat->TexelBytes;
927      GLint img, row, col;
928      if (!tempImage)
929         return GL_FALSE;
930      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
931      for (img = 0; img < srcDepth; img++) {
932         GLubyte *dstRow = dstImage;
933         for (row = 0; row < srcHeight; row++) {
934            GLuint *dstUI = (GLuint *) dstRow;
935            for (col = 0; col < srcWidth; col++) {
936               dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
937                                             CHAN_TO_UBYTE(src[GCOMP]),
938                                             CHAN_TO_UBYTE(src[BCOMP]),
939                                             CHAN_TO_UBYTE(src[ACOMP]) );
940               src += 4;
941            }
942            dstRow += dstRowStride;
943         }
944         dstImage += dstImageStride;
945      }
946      _mesa_free((void *) tempImage);
947   }
948   return GL_TRUE;
949}
950
951
952GLboolean
953_mesa_texstore_argb8888(STORE_PARAMS)
954{
955   const GLuint ui = 1;
956   const GLubyte littleEndian = *((const GLubyte *) &ui);
957
958   ASSERT(dstFormat == &_mesa_texformat_argb8888);
959   ASSERT(dstFormat->TexelBytes == 4);
960
961   if (!ctx->_ImageTransferState &&
962       !srcPacking->SwapBytes &&
963       baseInternalFormat == GL_RGBA &&
964       srcFormat == GL_BGRA &&
965       ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
966        (srcType == GL_UNSIGNED_INT_8_8_8_8_REV && littleEndian) ||
967        (srcType == GL_UNSIGNED_INT_8_8_8_8 && !littleEndian))) {
968      /* simple memcpy path */
969      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
970                     dstRowStride, dstImageStride,
971                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
972                     srcAddr, srcPacking);
973   }
974   else {
975      /* general path */
976      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
977                                                 baseInternalFormat,
978                                                 dstFormat->BaseFormat,
979                                                 srcWidth, srcHeight, srcDepth,
980                                                 srcFormat, srcType, srcAddr,
981                                                 srcPacking);
982      const GLchan *src = tempImage;
983      GLubyte *dstImage = (GLubyte *) dstAddr
984                        + dstZoffset * dstImageStride
985                        + dstYoffset * dstRowStride
986                        + dstXoffset * dstFormat->TexelBytes;
987      GLint img, row, col;
988      if (!tempImage)
989         return GL_FALSE;
990      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
991      for (img = 0; img < srcDepth; img++) {
992         GLubyte *dstRow = dstImage;
993         for (row = 0; row < srcHeight; row++) {
994            GLuint *dstUI = (GLuint *) dstRow;
995            for (col = 0; col < srcWidth; col++) {
996               dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
997                                             CHAN_TO_UBYTE(src[RCOMP]),
998                                             CHAN_TO_UBYTE(src[GCOMP]),
999                                             CHAN_TO_UBYTE(src[BCOMP]) );
1000               src += 4;
1001            }
1002            dstRow += dstRowStride;
1003         }
1004         dstImage += dstImageStride;
1005      }
1006      _mesa_free((void *) tempImage);
1007   }
1008   return GL_TRUE;
1009}
1010
1011
1012
1013GLboolean
1014_mesa_texstore_rgb888(STORE_PARAMS)
1015{
1016   const GLuint ui = 1;
1017   const GLubyte littleEndian = *((const GLubyte *) &ui);
1018
1019   ASSERT(dstFormat == &_mesa_texformat_rgb888);
1020   ASSERT(dstFormat->TexelBytes == 3);
1021
1022   if (!ctx->_ImageTransferState &&
1023       !srcPacking->SwapBytes &&
1024       baseInternalFormat == GL_RGB &&
1025       srcFormat == GL_BGR &&
1026       srcType == GL_UNSIGNED_BYTE &&
1027       littleEndian) {
1028      /* simple memcpy path */
1029      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1030                     dstRowStride, dstImageStride,
1031                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1032                     srcAddr, srcPacking);
1033   }
1034   else if (!ctx->_ImageTransferState &&
1035            !srcPacking->SwapBytes &&
1036            srcFormat == GL_RGBA &&
1037            srcType == GL_UNSIGNED_BYTE) {
1038      /* extract BGR from RGBA */
1039      int img, row, col;
1040      GLubyte *dstImage = (GLubyte *) dstAddr
1041                        + dstZoffset * dstImageStride
1042                        + dstYoffset * dstRowStride
1043                        + dstXoffset * dstFormat->TexelBytes;
1044      for (img = 0; img < srcDepth; img++) {
1045         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1046                                                 srcWidth, srcFormat, srcType);
1047         GLubyte *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth,
1048                                              srcHeight, srcFormat, srcType,
1049                                              img, 0, 0);
1050         GLubyte *dstRow = dstImage;
1051         for (row = 0; row < srcHeight; row++) {
1052            for (col = 0; col < srcWidth; col++) {
1053               dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1054               dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1055               dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1056            }
1057            dstRow += dstRowStride;
1058            srcRow += srcRowStride;
1059         }
1060         dstImage += dstImageStride;
1061      }
1062   }
1063   else {
1064      /* general path */
1065      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1066                                                 baseInternalFormat,
1067                                                 dstFormat->BaseFormat,
1068                                                 srcWidth, srcHeight, srcDepth,
1069                                                 srcFormat, srcType, srcAddr,
1070                                                 srcPacking);
1071      const GLchan *src = (const GLubyte *) tempImage;
1072      GLubyte *dstImage = (GLubyte *) dstAddr
1073                        + dstZoffset * dstImageStride
1074                        + dstYoffset * dstRowStride
1075                        + dstXoffset * dstFormat->TexelBytes;
1076      GLint img, row, col;
1077      if (!tempImage)
1078         return GL_FALSE;
1079      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1080      for (img = 0; img < srcDepth; img++) {
1081         GLubyte *dstRow = dstImage;
1082         for (row = 0; row < srcHeight; row++) {
1083#if 0
1084            if (littleEndian) {
1085               for (col = 0; col < srcWidth; col++) {
1086                  dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1087                  dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1088                  dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1089                  srcUB += 3;
1090               }
1091            }
1092            else {
1093               for (col = 0; col < srcWidth; col++) {
1094                  dstRow[col * 3 + 0] = srcUB[BCOMP];
1095                  dstRow[col * 3 + 1] = srcUB[GCOMP];
1096                  dstRow[col * 3 + 2] = srcUB[RCOMP];
1097                  srcUB += 3;
1098               }
1099            }
1100#else
1101            for (col = 0; col < srcWidth; col++) {
1102               dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1103               dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1104               dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1105               src += 3;
1106            }
1107#endif
1108            dstRow += dstRowStride;
1109         }
1110         dstImage += dstImageStride;
1111      }
1112      _mesa_free((void *) tempImage);
1113   }
1114   return GL_TRUE;
1115}
1116
1117
1118GLboolean
1119_mesa_texstore_argb4444(STORE_PARAMS)
1120{
1121   const GLuint ui = 1;
1122   const GLubyte littleEndian = *((const GLubyte *) &ui);
1123
1124   ASSERT(dstFormat == &_mesa_texformat_argb4444);
1125   ASSERT(dstFormat->TexelBytes == 2);
1126
1127   if (!ctx->_ImageTransferState &&
1128       !srcPacking->SwapBytes &&
1129       baseInternalFormat == GL_RGBA &&
1130       srcFormat == GL_BGRA &&
1131       ((srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV && littleEndian) ||
1132        (srcType == GL_UNSIGNED_SHORT_4_4_4_4 && !littleEndian))) {
1133      /* simple memcpy path */
1134      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1135                     dstRowStride, dstImageStride,
1136                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1137                     srcAddr, srcPacking);
1138   }
1139   else {
1140      /* general path */
1141      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1142                                                 baseInternalFormat,
1143                                                 dstFormat->BaseFormat,
1144                                                 srcWidth, srcHeight, srcDepth,
1145                                                 srcFormat, srcType, srcAddr,
1146                                                 srcPacking);
1147      const GLchan *src = tempImage;
1148      GLubyte *dstImage = (GLubyte *) dstAddr
1149                        + dstZoffset * dstImageStride
1150                        + dstYoffset * dstRowStride
1151                        + dstXoffset * dstFormat->TexelBytes;
1152      GLint img, row, col;
1153      if (!tempImage)
1154         return GL_FALSE;
1155      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1156      for (img = 0; img < srcDepth; img++) {
1157         GLubyte *dstRow = dstImage;
1158         for (row = 0; row < srcHeight; row++) {
1159            GLushort *dstUS = (GLushort *) dstRow;
1160            for (col = 0; col < srcWidth; col++) {
1161               dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1162                                             CHAN_TO_UBYTE(src[RCOMP]),
1163                                             CHAN_TO_UBYTE(src[GCOMP]),
1164                                             CHAN_TO_UBYTE(src[BCOMP]) );
1165               src += 4;
1166            }
1167            dstRow += dstRowStride;
1168         }
1169         dstImage += dstImageStride;
1170      }
1171      _mesa_free((void *) tempImage);
1172   }
1173   return GL_TRUE;
1174}
1175
1176
1177GLboolean
1178_mesa_texstore_argb1555(STORE_PARAMS)
1179{
1180   const GLuint ui = 1;
1181   const GLubyte littleEndian = *((const GLubyte *) &ui);
1182
1183   ASSERT(dstFormat == &_mesa_texformat_argb1555);
1184   ASSERT(dstFormat->TexelBytes == 2);
1185
1186   if (!ctx->_ImageTransferState &&
1187       !srcPacking->SwapBytes &&
1188       baseInternalFormat == GL_RGBA &&
1189       srcFormat == GL_BGRA &&
1190       ((srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV && littleEndian) ||
1191        (srcType == GL_UNSIGNED_SHORT_5_5_5_1 && !littleEndian))) {
1192      /* simple memcpy path */
1193      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1194                     dstRowStride, dstImageStride,
1195                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1196                     srcAddr, srcPacking);
1197   }
1198   else {
1199      /* general path */
1200      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1201                                                 baseInternalFormat,
1202                                                 dstFormat->BaseFormat,
1203                                                 srcWidth, srcHeight, srcDepth,
1204                                                 srcFormat, srcType, srcAddr,
1205                                                 srcPacking);
1206      const GLchan *src =tempImage;
1207      GLubyte *dstImage = (GLubyte *) dstAddr
1208                        + dstZoffset * dstImageStride
1209                        + dstYoffset * dstRowStride
1210                        + dstXoffset * dstFormat->TexelBytes;
1211      GLint img, row, col;
1212      if (!tempImage)
1213         return GL_FALSE;
1214      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1215      for (img = 0; img < srcDepth; img++) {
1216         GLubyte *dstRow = dstImage;
1217         for (row = 0; row < srcHeight; row++) {
1218            GLushort *dstUS = (GLushort *) dstRow;
1219            for (col = 0; col < srcWidth; col++) {
1220               dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
1221                                             CHAN_TO_UBYTE(src[RCOMP]),
1222                                             CHAN_TO_UBYTE(src[GCOMP]),
1223                                             CHAN_TO_UBYTE(src[BCOMP]) );
1224               src += 4;
1225            }
1226            dstRow += dstRowStride;
1227         }
1228         dstImage += dstImageStride;
1229      }
1230      _mesa_free((void *) tempImage);
1231   }
1232   return GL_TRUE;
1233}
1234
1235
1236GLboolean
1237_mesa_texstore_al88(STORE_PARAMS)
1238{
1239   const GLuint ui = 1;
1240   const GLubyte littleEndian = *((const GLubyte *) &ui);
1241
1242   ASSERT(dstFormat == &_mesa_texformat_al88);
1243   ASSERT(dstFormat->TexelBytes == 2);
1244
1245   if (!ctx->_ImageTransferState &&
1246       !srcPacking->SwapBytes &&
1247       baseInternalFormat == GL_LUMINANCE_ALPHA &&
1248       srcFormat == GL_LUMINANCE_ALPHA &&
1249       srcType == GL_UNSIGNED_BYTE &&
1250       littleEndian) {
1251      /* simple memcpy path */
1252      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1253                     dstRowStride, dstImageStride,
1254                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1255                     srcAddr, srcPacking);
1256   }
1257   else {
1258      /* general path */
1259      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1260                                                 baseInternalFormat,
1261                                                 dstFormat->BaseFormat,
1262                                                 srcWidth, srcHeight, srcDepth,
1263                                                 srcFormat, srcType, srcAddr,
1264                                                 srcPacking);
1265      const GLchan *src = tempImage;
1266      GLubyte *dstImage = (GLubyte *) dstAddr
1267                        + dstZoffset * dstImageStride
1268                        + dstYoffset * dstRowStride
1269                        + dstXoffset * dstFormat->TexelBytes;
1270      GLint img, row, col;
1271      if (!tempImage)
1272         return GL_FALSE;
1273      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1274      for (img = 0; img < srcDepth; img++) {
1275         GLubyte *dstRow = dstImage;
1276         for (row = 0; row < srcHeight; row++) {
1277            GLushort *dstUS = (GLushort *) dstRow;
1278            for (col = 0; col < srcWidth; col++) {
1279               dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[ACOMP]),
1280                                           CHAN_TO_UBYTE(src[RCOMP]) );
1281               src += 2;
1282            }
1283            dstRow += dstRowStride;
1284         }
1285         dstImage += dstImageStride;
1286      }
1287      _mesa_free((void *) tempImage);
1288   }
1289   return GL_TRUE;
1290}
1291
1292
1293GLboolean
1294_mesa_texstore_rgb332(STORE_PARAMS)
1295{
1296   ASSERT(dstFormat == &_mesa_texformat_rgb332);
1297   ASSERT(dstFormat->TexelBytes == 1);
1298
1299   if (!ctx->_ImageTransferState &&
1300       !srcPacking->SwapBytes &&
1301       baseInternalFormat == GL_RGB &&
1302       srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
1303      /* simple memcpy path */
1304      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1305                     dstRowStride, dstImageStride,
1306                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1307                     srcAddr, srcPacking);
1308   }
1309   else {
1310      /* general path */
1311      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1312                                                 baseInternalFormat,
1313                                                 dstFormat->BaseFormat,
1314                                                 srcWidth, srcHeight, srcDepth,
1315                                                 srcFormat, srcType, srcAddr,
1316                                                 srcPacking);
1317      const GLchan *src = tempImage;
1318      GLubyte *dstImage = (GLubyte *) dstAddr
1319                        + dstZoffset * dstImageStride
1320                        + dstYoffset * dstRowStride
1321                        + dstXoffset * dstFormat->TexelBytes;
1322      GLint img, row, col;
1323      if (!tempImage)
1324         return GL_FALSE;
1325      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1326      for (img = 0; img < srcDepth; img++) {
1327         GLubyte *dstRow = dstImage;
1328         for (row = 0; row < srcHeight; row++) {
1329            for (col = 0; col < srcWidth; col++) {
1330               dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
1331                                             CHAN_TO_UBYTE(src[GCOMP]),
1332                                             CHAN_TO_UBYTE(src[BCOMP]) );
1333               src += 3;
1334            }
1335            dstRow += dstRowStride;
1336         }
1337         dstImage += dstImageStride;
1338      }
1339      _mesa_free((void *) tempImage);
1340   }
1341   return GL_TRUE;
1342}
1343
1344
1345
1346/**
1347 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1348 */
1349GLboolean
1350_mesa_texstore_a8(STORE_PARAMS)
1351{
1352   ASSERT(dstFormat == &_mesa_texformat_a8 ||
1353          dstFormat == &_mesa_texformat_l8 ||
1354          dstFormat == &_mesa_texformat_i8);
1355   ASSERT(dstFormat->TexelBytes == 1);
1356
1357   if (!ctx->_ImageTransferState &&
1358       !srcPacking->SwapBytes &&
1359       baseInternalFormat == srcFormat &&
1360       srcType == GL_UNSIGNED_BYTE) {
1361      /* simple memcpy path */
1362      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1363                     dstRowStride, dstImageStride,
1364                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1365                     srcAddr, srcPacking);
1366   }
1367   else {
1368      /* general path */
1369      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1370                                                 baseInternalFormat,
1371                                                 dstFormat->BaseFormat,
1372                                                 srcWidth, srcHeight, srcDepth,
1373                                                 srcFormat, srcType, srcAddr,
1374                                                 srcPacking);
1375      const GLchan *src = tempImage;
1376      GLubyte *dstImage = (GLubyte *) dstAddr
1377                        + dstZoffset * dstImageStride
1378                        + dstYoffset * dstRowStride
1379                        + dstXoffset * dstFormat->TexelBytes;
1380      GLint img, row, col;
1381      if (!tempImage)
1382         return GL_FALSE;
1383      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1384      for (img = 0; img < srcDepth; img++) {
1385         GLubyte *dstRow = dstImage;
1386         for (row = 0; row < srcHeight; row++) {
1387            for (col = 0; col < srcWidth; col++) {
1388               dstRow[col] = CHAN_TO_UBYTE(src[col]);
1389            }
1390            dstRow += dstRowStride;
1391            src += srcWidth;
1392         }
1393         dstImage += dstImageStride;
1394      }
1395      _mesa_free((void *) tempImage);
1396   }
1397   return GL_TRUE;
1398}
1399
1400
1401
1402GLboolean
1403_mesa_texstore_ci8(STORE_PARAMS)
1404{
1405   ASSERT(dstFormat == &_mesa_texformat_ci8);
1406   ASSERT(dstFormat->TexelBytes == 1);
1407   ASSERT(baseInternalFormat == GL_COLOR_INDEX);
1408
1409   if (!ctx->_ImageTransferState &&
1410       !srcPacking->SwapBytes &&
1411       srcFormat == GL_COLOR_INDEX &&
1412       srcType == GL_UNSIGNED_BYTE) {
1413      /* simple memcpy path */
1414      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1415                     dstRowStride, dstImageStride,
1416                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1417                     srcAddr, srcPacking);
1418   }
1419   else {
1420      /* general path */
1421      GLubyte *dstImage = (GLubyte *) dstAddr
1422                        + dstZoffset * dstImageStride
1423                        + dstYoffset * dstRowStride
1424                        + dstXoffset * dstFormat->TexelBytes;
1425      GLint img, row;
1426      for (img = 0; img < srcDepth; img++) {
1427         GLubyte *dstRow = dstImage;
1428         for (row = 0; row < srcHeight; row++) {
1429            const GLvoid *src = _mesa_image_address(srcPacking,
1430                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1431            _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
1432                                    srcType, src, srcPacking,
1433                                    ctx->_ImageTransferState);
1434            dstRow += dstRowStride;
1435         }
1436         dstImage += dstImageStride;
1437      }
1438   }
1439   return GL_TRUE;
1440}
1441
1442
1443/**
1444 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1445 */
1446GLboolean
1447_mesa_texstore_ycbcr(STORE_PARAMS)
1448{
1449   const GLuint ui = 1;
1450   const GLubyte littleEndian = *((const GLubyte *) &ui);
1451
1452   ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
1453          (dstFormat == &_mesa_texformat_ycbcr_rev));
1454   ASSERT(dstFormat->TexelBytes == 2);
1455   ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1456   ASSERT(srcFormat == GL_YCBCR_MESA);
1457   ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
1458          (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
1459   ASSERT(baseInternalFormat == GL_YCBCR_MESA);
1460
1461   /* always just memcpy since no pixel transfer ops apply */
1462   memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1463                  dstRowStride, dstImageStride,
1464                  srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1465                  srcAddr, srcPacking);
1466
1467   /* Check if we need byte swapping */
1468   /* XXX the logic here _might_ be wrong */
1469   if (srcPacking->SwapBytes ^
1470       (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
1471       (dstFormat == &_mesa_texformat_ycbcr_rev) ^
1472       !littleEndian) {
1473      GLushort *pImage = (GLushort *) ((GLubyte *) dstAddr
1474                                       + dstZoffset * dstImageStride
1475                                       + dstYoffset * dstRowStride
1476                                       + dstXoffset * dstFormat->TexelBytes);
1477      GLint img, row;
1478      for (img = 0; img < srcDepth; img++) {
1479         GLushort *pRow = pImage;
1480         for (row = 0; row < srcHeight; row++) {
1481            _mesa_swap2(pRow, srcWidth);
1482            pRow += dstRowStride;
1483         }
1484         pImage += dstImageStride;
1485      }
1486   }
1487   return GL_TRUE;
1488}
1489
1490
1491
1492
1493/**
1494 * Store an image in any of the formats:
1495 *   _mesa_texformat_rgba_float32
1496 *   _mesa_texformat_rgb_float32
1497 *   _mesa_texformat_alpha_float32
1498 *   _mesa_texformat_luminance_float32
1499 *   _mesa_texformat_luminance_alpha_float32
1500 *   _mesa_texformat_intensity_float32
1501 */
1502GLboolean
1503_mesa_texstore_rgba_float32(STORE_PARAMS)
1504{
1505   const GLint components = _mesa_components_in_format(baseInternalFormat);
1506
1507   ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
1508          dstFormat == &_mesa_texformat_rgb_float32 ||
1509          dstFormat == &_mesa_texformat_alpha_float32 ||
1510          dstFormat == &_mesa_texformat_luminance_float32 ||
1511          dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
1512          dstFormat == &_mesa_texformat_intensity_float32);
1513   ASSERT(baseInternalFormat == GL_RGBA ||
1514          baseInternalFormat == GL_RGB ||
1515          baseInternalFormat == GL_ALPHA ||
1516          baseInternalFormat == GL_LUMINANCE ||
1517          baseInternalFormat == GL_LUMINANCE_ALPHA ||
1518          baseInternalFormat == GL_INTENSITY);
1519   ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
1520
1521   if (!ctx->_ImageTransferState &&
1522       !srcPacking->SwapBytes &&
1523       baseInternalFormat == srcFormat &&
1524       srcType == GL_FLOAT) {
1525      /* simple memcpy path */
1526      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1527                     dstRowStride, dstImageStride,
1528                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1529                     srcAddr, srcPacking);
1530   }
1531   else {
1532      /* general path */
1533      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
1534                                                 baseInternalFormat,
1535                                                 dstFormat->BaseFormat,
1536                                                 srcWidth, srcHeight, srcDepth,
1537                                                 srcFormat, srcType, srcAddr,
1538                                                 srcPacking);
1539      const GLfloat *src = tempImage;
1540      const GLint bytesPerRow = srcWidth * components * sizeof(GLfloat);
1541      GLubyte *dstImage = (GLubyte *) dstAddr
1542                        + dstZoffset * dstImageStride
1543                        + dstYoffset * dstRowStride
1544                        + dstXoffset * dstFormat->TexelBytes;
1545      GLint img, row;
1546      if (!tempImage)
1547         return GL_FALSE;
1548      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1549      for (img = 0; img < srcDepth; img++) {
1550         GLubyte *dst = dstImage;
1551         for (row = 0; row < srcHeight; row++) {
1552            _mesa_memcpy(dst, src, bytesPerRow);
1553            dst += dstRowStride;
1554            src += srcWidth * components;
1555         }
1556         dstImage += dstImageStride;
1557      }
1558
1559      _mesa_free((void *) tempImage);
1560   }
1561   return GL_TRUE;
1562}
1563
1564
1565/**
1566 * As above, but store 16-bit floats.
1567 */
1568GLboolean
1569_mesa_texstore_rgba_float16(STORE_PARAMS)
1570{
1571   const GLint components = _mesa_components_in_format(baseInternalFormat);
1572
1573   ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
1574          dstFormat == &_mesa_texformat_rgb_float16 ||
1575          dstFormat == &_mesa_texformat_alpha_float16 ||
1576          dstFormat == &_mesa_texformat_luminance_float16 ||
1577          dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
1578          dstFormat == &_mesa_texformat_intensity_float16);
1579   ASSERT(baseInternalFormat == GL_RGBA ||
1580          baseInternalFormat == GL_RGB ||
1581          baseInternalFormat == GL_ALPHA ||
1582          baseInternalFormat == GL_LUMINANCE ||
1583          baseInternalFormat == GL_LUMINANCE_ALPHA ||
1584          baseInternalFormat == GL_INTENSITY);
1585   ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
1586
1587   if (!ctx->_ImageTransferState &&
1588       !srcPacking->SwapBytes &&
1589       baseInternalFormat == srcFormat &&
1590       srcType == GL_HALF_FLOAT_ARB) {
1591      /* simple memcpy path */
1592      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1593                     dstRowStride, dstImageStride,
1594                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1595                     srcAddr, srcPacking);
1596   }
1597   else {
1598      /* general path */
1599      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
1600                                                 baseInternalFormat,
1601                                                 dstFormat->BaseFormat,
1602                                                 srcWidth, srcHeight, srcDepth,
1603                                                 srcFormat, srcType, srcAddr,
1604                                                 srcPacking);
1605      const GLfloat *src = tempImage;
1606      GLubyte *dstImage = (GLubyte *) dstAddr
1607                        + dstZoffset * dstImageStride
1608                        + dstYoffset * dstRowStride
1609                        + dstXoffset * dstFormat->TexelBytes;
1610      GLint img, row;
1611      if (!tempImage)
1612         return GL_FALSE;
1613      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1614      for (img = 0; img < srcDepth; img++) {
1615         GLubyte *dstRow = dstImage;
1616         for (row = 0; row < srcHeight; row++) {
1617            GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
1618            GLint i;
1619            for (i = 0; i < srcWidth * components; i++) {
1620               dstTexel[i] = _mesa_float_to_half(src[i]);
1621            }
1622            dstRow += dstRowStride;
1623            src += srcWidth * components;
1624         }
1625         dstImage += dstImageStride;
1626      }
1627
1628      _mesa_free((void *) tempImage);
1629   }
1630   return GL_TRUE;
1631}
1632
1633
1634
1635/**
1636 * Validate acces to a PBO for texture data.
1637 *
1638 * \todo If the PBO is really resident in VRAM, this won't work; the
1639 * device driver should check for that and do the right thing.
1640 */
1641static const GLvoid *
1642validate_pbo_teximage( GLsizei width, GLsizei height, GLsizei depth,
1643                       GLenum format, GLenum type, const GLvoid *pixels,
1644                       const struct gl_pixelstore_attrib *unpack )
1645{
1646   if (unpack->BufferObj->Name == 0) {
1647      /* no PBO */
1648      return pixels;
1649   }
1650   else if (_mesa_validate_pbo_access(unpack, width, height, depth, format,
1651                                      type, pixels)) {
1652      return ADD_POINTERS(unpack->BufferObj->Data, pixels);
1653   }
1654   /* bad access! */
1655   return NULL;
1656}
1657
1658
1659/**
1660 * Validate that unpacking compressed texture image data from a PBO
1661 * won't go out of bounds.
1662 *
1663 * \todo If the PBO is really resident in VRAM, this won't work; the
1664 * device driver should check for that and do the right thing.
1665 */
1666static const GLvoid *
1667validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels,
1668                               const struct gl_pixelstore_attrib *packing)
1669{
1670   if (packing->BufferObj->Name == 0) {
1671      /* not using a PBO - return pointer unchanged */
1672      return pixels;
1673   }
1674   else {
1675      /* using a PBO */
1676      if ((const GLubyte *) pixels + imageSize >
1677          (const GLubyte *) packing->BufferObj->Size) {
1678         /* out of bounds read! */
1679         return NULL;
1680      }
1681      /* OK! */
1682      return ADD_POINTERS(packing->BufferObj->Data, pixels);
1683   }
1684}
1685
1686
1687
1688/*
1689 * This is the software fallback for Driver.TexImage1D()
1690 * and Driver.CopyTexImage1D().
1691 */
1692void
1693_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
1694                       GLint internalFormat,
1695                       GLint width, GLint border,
1696                       GLenum format, GLenum type, const GLvoid *pixels,
1697                       const struct gl_pixelstore_attrib *packing,
1698                       struct gl_texture_object *texObj,
1699                       struct gl_texture_image *texImage)
1700{
1701   GLint postConvWidth = width;
1702   GLint sizeInBytes;
1703
1704   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
1705      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1706   }
1707
1708   /* choose the texture format */
1709   assert(ctx->Driver.ChooseTextureFormat);
1710   texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
1711                                                         format, type);
1712   assert(texImage->TexFormat);
1713   texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
1714   texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
1715
1716   /* allocate memory */
1717   if (texImage->IsCompressed)
1718      sizeInBytes = texImage->CompressedSize;
1719   else
1720      sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes;
1721   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
1722   if (!texImage->Data) {
1723      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1724      return;
1725   }
1726
1727   pixels = validate_pbo_teximage(width, 1, 1, format, type, pixels, packing);
1728   if (!pixels)
1729      return;
1730
1731   {
1732      const GLint dstRowStride = 0, dstImageStride = 0;
1733      GLboolean success;
1734      ASSERT(texImage->TexFormat->StoreImage);
1735      success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format,
1736                                                texImage->TexFormat,
1737                                                texImage->Data,
1738                                                0, 0, 0,  /* dstX/Y/Zoffset */
1739                                                dstRowStride, dstImageStride,
1740                                                width, 1, 1,
1741                                                format, type, pixels, packing);
1742      if (!success) {
1743         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1744         return;
1745      }
1746   }
1747
1748   /* GL_SGIS_generate_mipmap */
1749   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1750      _mesa_generate_mipmap(ctx, target,
1751                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1752                            texObj);
1753   }
1754}
1755
1756
1757/*
1758 * This is the software fallback for Driver.TexImage2D()
1759 * and Driver.CopyTexImage2D().
1760 * Reasons why a driver might override this function:
1761 *  - Special memory allocation needs
1762 *  - Unusual row/image strides
1763 *  - Special housekeeping
1764 */
1765void
1766_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
1767                       GLint internalFormat,
1768                       GLint width, GLint height, GLint border,
1769                       GLenum format, GLenum type, const void *pixels,
1770                       const struct gl_pixelstore_attrib *packing,
1771                       struct gl_texture_object *texObj,
1772                       struct gl_texture_image *texImage)
1773{
1774   GLint postConvWidth = width, postConvHeight = height;
1775   GLint texelBytes, sizeInBytes;
1776
1777   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
1778      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1779                                         &postConvHeight);
1780   }
1781
1782   /* choose the texture format */
1783   assert(ctx->Driver.ChooseTextureFormat);
1784   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1785                                          internalFormat, format, type);
1786   assert(texImage->TexFormat);
1787   texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
1788   texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
1789
1790   texelBytes = texImage->TexFormat->TexelBytes;
1791
1792   /* allocate memory */
1793   if (texImage->IsCompressed)
1794      sizeInBytes = texImage->CompressedSize;
1795   else
1796      sizeInBytes = postConvWidth * postConvHeight * texelBytes;
1797   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
1798   if (!texImage->Data) {
1799      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1800      return;
1801   }
1802
1803   pixels = validate_pbo_teximage(width, height, 1,
1804                                  format, type, pixels, packing);
1805   if (!pixels)
1806      return;
1807
1808   {
1809      GLint dstRowStride, dstImageStride = 0;
1810      GLboolean success;
1811      if (texImage->IsCompressed) {
1812         dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width);
1813      }
1814      else {
1815         dstRowStride = width * texImage->TexFormat->TexelBytes;
1816      }
1817      ASSERT(texImage->TexFormat->StoreImage);
1818      success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
1819                                                texImage->TexFormat,
1820                                                texImage->Data,
1821                                                0, 0, 0,  /* dstX/Y/Zoffset */
1822                                                dstRowStride, dstImageStride,
1823                                                width, height, 1,
1824                                                format, type, pixels, packing);
1825      if (!success) {
1826         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1827         return;
1828      }
1829   }
1830
1831   /* GL_SGIS_generate_mipmap */
1832   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1833      _mesa_generate_mipmap(ctx, target,
1834                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1835                            texObj);
1836   }
1837}
1838
1839
1840
1841/*
1842 * This is the software fallback for Driver.TexImage3D()
1843 * and Driver.CopyTexImage3D().
1844 */
1845void
1846_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
1847                       GLint internalFormat,
1848                       GLint width, GLint height, GLint depth, GLint border,
1849                       GLenum format, GLenum type, const void *pixels,
1850                       const struct gl_pixelstore_attrib *packing,
1851                       struct gl_texture_object *texObj,
1852                       struct gl_texture_image *texImage)
1853{
1854   GLint texelBytes, sizeInBytes;
1855
1856   /* choose the texture format */
1857   assert(ctx->Driver.ChooseTextureFormat);
1858   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1859                                          internalFormat, format, type);
1860   assert(texImage->TexFormat);
1861   texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
1862   texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
1863
1864   texelBytes = texImage->TexFormat->TexelBytes;
1865
1866   /* allocate memory */
1867   if (texImage->IsCompressed)
1868      sizeInBytes = texImage->CompressedSize;
1869   else
1870      sizeInBytes = width * height * depth * texelBytes;
1871   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
1872   if (!texImage->Data) {
1873      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1874      return;
1875   }
1876
1877   pixels = validate_pbo_teximage(width, height, depth,
1878                                  format, type, pixels, packing);
1879   if (!pixels)
1880      return;
1881
1882   /* unpack image, apply transfer ops and store in texImage->Data */
1883   {
1884      GLint dstRowStride, dstImageStride;
1885      GLboolean success;
1886      if (texImage->IsCompressed) {
1887         dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width);
1888         dstImageStride = 0;
1889      }
1890      else {
1891         dstRowStride = width * texImage->TexFormat->TexelBytes;
1892         dstImageStride = dstRowStride * height;
1893      }
1894      ASSERT(texImage->TexFormat->StoreImage);
1895      success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format,
1896                                                texImage->TexFormat,
1897                                                texImage->Data,
1898                                                0, 0, 0,  /* dstX/Y/Zoffset */
1899                                                dstRowStride, dstImageStride,
1900                                                width, height, depth,
1901                                                format, type, pixels, packing);
1902      if (!success) {
1903         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1904         return;
1905      }
1906   }
1907
1908   /* GL_SGIS_generate_mipmap */
1909   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1910      _mesa_generate_mipmap(ctx, target,
1911                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1912                            texObj);
1913   }
1914}
1915
1916
1917
1918
1919/*
1920 * This is the software fallback for Driver.TexSubImage1D()
1921 * and Driver.CopyTexSubImage1D().
1922 */
1923void
1924_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
1925                          GLint xoffset, GLint width,
1926                          GLenum format, GLenum type, const void *pixels,
1927                          const struct gl_pixelstore_attrib *packing,
1928                          struct gl_texture_object *texObj,
1929                          struct gl_texture_image *texImage)
1930{
1931   pixels = validate_pbo_teximage(width, 1, 1,
1932                                  format, type, pixels, packing);
1933   if (!pixels)
1934      return;
1935
1936   {
1937      const GLint dstRowStride = 0, dstImageStride = 0;
1938      GLboolean success;
1939      ASSERT(texImage->TexFormat->StoreImage);
1940      success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format,
1941                                                texImage->TexFormat,
1942                                                texImage->Data,
1943                                                xoffset, 0, 0,  /* offsets */
1944                                                dstRowStride, dstImageStride,
1945                                                width, 1, 1,
1946                                                format, type, pixels, packing);
1947      if (!success) {
1948         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
1949         return;
1950      }
1951   }
1952
1953   /* GL_SGIS_generate_mipmap */
1954   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1955      _mesa_generate_mipmap(ctx, target,
1956                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1957                            texObj);
1958   }
1959}
1960
1961
1962
1963/**
1964 * This is the software fallback for Driver.TexSubImage2D()
1965 * and Driver.CopyTexSubImage2D().
1966 */
1967void
1968_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
1969                          GLint xoffset, GLint yoffset,
1970                          GLint width, GLint height,
1971                          GLenum format, GLenum type, const void *pixels,
1972                          const struct gl_pixelstore_attrib *packing,
1973                          struct gl_texture_object *texObj,
1974                          struct gl_texture_image *texImage)
1975{
1976   pixels = validate_pbo_teximage(width, height, 1,
1977                                  format, type, pixels, packing);
1978   if (!pixels)
1979      return;
1980
1981   {
1982      GLint dstRowStride = 0, dstImageStride = 0;
1983      GLboolean success;
1984      if (texImage->IsCompressed) {
1985         dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
1986                                                    texImage->Width);
1987      }
1988      else {
1989         dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
1990      }
1991      ASSERT(texImage->TexFormat->StoreImage);
1992      success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
1993                                                texImage->TexFormat,
1994                                                texImage->Data,
1995                                                xoffset, yoffset, 0,
1996                                                dstRowStride, dstImageStride,
1997                                                width, height, 1,
1998                                                format, type, pixels, packing);
1999      if (!success) {
2000         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2001         return;
2002      }
2003   }
2004
2005   /* GL_SGIS_generate_mipmap */
2006   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2007      _mesa_generate_mipmap(ctx, target,
2008                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2009                            texObj);
2010   }
2011}
2012
2013
2014/*
2015 * This is the software fallback for Driver.TexSubImage3D().
2016 * and Driver.CopyTexSubImage3D().
2017 */
2018void
2019_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
2020                          GLint xoffset, GLint yoffset, GLint zoffset,
2021                          GLint width, GLint height, GLint depth,
2022                          GLenum format, GLenum type, const void *pixels,
2023                          const struct gl_pixelstore_attrib *packing,
2024                          struct gl_texture_object *texObj,
2025                          struct gl_texture_image *texImage)
2026{
2027   pixels = validate_pbo_teximage(width, height, depth,
2028                                  format, type, pixels, packing);
2029   if (!pixels)
2030      return;
2031
2032   {
2033      GLint dstRowStride, dstImageStride;
2034      GLboolean success;
2035      if (texImage->IsCompressed) {
2036         dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
2037                                                    texImage->Width);
2038         dstImageStride = 0; /* XXX fix */
2039      }
2040      else {
2041         dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2042         dstImageStride = dstRowStride * texImage->Height;
2043      }
2044      ASSERT(texImage->TexFormat->StoreImage);
2045      success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format,
2046                                                texImage->TexFormat,
2047                                                texImage->Data,
2048                                                xoffset, yoffset, zoffset,
2049                                                dstRowStride, dstImageStride,
2050                                                width, height, depth,
2051                                                format, type, pixels, packing);
2052      if (!success) {
2053         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
2054         return;
2055      }
2056   }
2057
2058   /* GL_SGIS_generate_mipmap */
2059   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2060      _mesa_generate_mipmap(ctx, target,
2061                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2062                            texObj);
2063   }
2064}
2065
2066
2067/*
2068 * Fallback for Driver.CompressedTexImage1D()
2069 */
2070void
2071_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2072                                  GLint internalFormat,
2073                                  GLint width, GLint border,
2074                                  GLsizei imageSize, const GLvoid *data,
2075                                  struct gl_texture_object *texObj,
2076                                  struct gl_texture_image *texImage)
2077{
2078   /* this space intentionally left blank */
2079}
2080
2081
2082
2083/*
2084 * Fallback for Driver.CompressedTexImage2D()
2085 */
2086void
2087_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2088                                  GLint internalFormat,
2089                                  GLint width, GLint height, GLint border,
2090                                  GLsizei imageSize, const GLvoid *data,
2091                                  struct gl_texture_object *texObj,
2092                                  struct gl_texture_image *texImage)
2093{
2094   /* This is pretty simple, basically just do a memcpy without worrying
2095    * about the usual image unpacking or image transfer operations.
2096    */
2097   ASSERT(texObj);
2098   ASSERT(texImage);
2099   ASSERT(texImage->Width > 0);
2100   ASSERT(texImage->Height > 0);
2101   ASSERT(texImage->Depth == 1);
2102   ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
2103
2104   /* choose the texture format */
2105   assert(ctx->Driver.ChooseTextureFormat);
2106   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2107                                          internalFormat, 0, 0);
2108   assert(texImage->TexFormat);
2109   texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2110   texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2111
2112   /* allocate storage */
2113   texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
2114   if (!texImage->Data) {
2115      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2116      return;
2117   }
2118
2119   data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
2120   if (!data)
2121      return;
2122
2123   /* copy the data */
2124   ASSERT(texImage->CompressedSize == (GLuint) imageSize);
2125   MEMCPY(texImage->Data, data, imageSize);
2126
2127   /* GL_SGIS_generate_mipmap */
2128   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2129      _mesa_generate_mipmap(ctx, target,
2130                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2131                            texObj);
2132   }
2133}
2134
2135
2136
2137/*
2138 * Fallback for Driver.CompressedTexImage3D()
2139 */
2140void
2141_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2142                                  GLint internalFormat,
2143                                  GLint width, GLint height, GLint depth,
2144                                  GLint border,
2145                                  GLsizei imageSize, const GLvoid *data,
2146                                  struct gl_texture_object *texObj,
2147                                  struct gl_texture_image *texImage)
2148{
2149   /* this space intentionally left blank */
2150}
2151
2152
2153
2154/**
2155 * Fallback for Driver.CompressedTexSubImage1D()
2156 */
2157void
2158_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
2159                                     GLint level,
2160                                     GLint xoffset, GLsizei width,
2161                                     GLenum format,
2162                                     GLsizei imageSize, const GLvoid *data,
2163                                     struct gl_texture_object *texObj,
2164                                     struct gl_texture_image *texImage)
2165{
2166   /* this space intentionally left blank */
2167}
2168
2169
2170/**
2171 * Fallback for Driver.CompressedTexSubImage2D()
2172 */
2173void
2174_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
2175                                     GLint level,
2176                                     GLint xoffset, GLint yoffset,
2177                                     GLsizei width, GLsizei height,
2178                                     GLenum format,
2179                                     GLsizei imageSize, const GLvoid *data,
2180                                     struct gl_texture_object *texObj,
2181                                     struct gl_texture_image *texImage)
2182{
2183   GLint bytesPerRow, destRowStride, srcRowStride;
2184   GLint i, rows;
2185   GLubyte *dest;
2186   const GLubyte *src;
2187
2188   /* these should have been caught sooner */
2189   ASSERT((width & 3) == 0 || width == 2 || width == 1);
2190   ASSERT((height & 3) == 0 || height == 2 || height == 1);
2191   ASSERT((xoffset & 3) == 0);
2192   ASSERT((yoffset & 3) == 0);
2193
2194   data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
2195   if (!data)
2196      return;
2197
2198   srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
2199   src = (const GLubyte *) data;
2200
2201   destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
2202                                               texImage->Width);
2203   dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
2204                                         texImage->IntFormat,
2205                                         texImage->Width,
2206                              (GLubyte*) texImage->Data);
2207
2208   bytesPerRow = srcRowStride;
2209   rows = height / 4;
2210
2211   for (i = 0; i < rows; i++) {
2212      MEMCPY(dest, src, bytesPerRow);
2213      dest += destRowStride;
2214      src += srcRowStride;
2215   }
2216
2217   /* GL_SGIS_generate_mipmap */
2218   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2219      _mesa_generate_mipmap(ctx, target,
2220                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2221                            texObj);
2222   }
2223}
2224
2225
2226/**
2227 * Fallback for Driver.CompressedTexSubImage3D()
2228 */
2229void
2230_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
2231                                GLint level,
2232                                GLint xoffset, GLint yoffset, GLint zoffset,
2233                                GLsizei width, GLsizei height, GLsizei depth,
2234                                GLenum format,
2235                                GLsizei imageSize, const GLvoid *data,
2236                                struct gl_texture_object *texObj,
2237                                struct gl_texture_image *texImage)
2238{
2239   /* this space intentionally left blank */
2240}
2241
2242
2243/*
2244 * Average together two rows of a source image to produce a single new
2245 * row in the dest image.  It's legal for the two source rows to point
2246 * to the same data.  The source width must be equal to either the
2247 * dest width or two times the dest width.
2248 */
2249static void
2250do_row(const struct gl_texture_format *format, GLint srcWidth,
2251       const GLvoid *srcRowA, const GLvoid *srcRowB,
2252       GLint dstWidth, GLvoid *dstRow)
2253{
2254   const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
2255   const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
2256
2257   /* This assertion is no longer valid with non-power-of-2 textures
2258   assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2259   */
2260
2261   switch (format->MesaFormat) {
2262   case MESA_FORMAT_RGBA:
2263      {
2264         GLuint i, j, k;
2265         const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
2266         const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
2267         GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
2268         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2269              i++, j += colStride, k += colStride) {
2270            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2271                         rowB[j][0] + rowB[k][0]) / 4;
2272            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2273                         rowB[j][1] + rowB[k][1]) / 4;
2274            dst[i][2] = (rowA[j][2] + rowA[k][2] +
2275                         rowB[j][2] + rowB[k][2]) / 4;
2276            dst[i][3] = (rowA[j][3] + rowA[k][3] +
2277                         rowB[j][3] + rowB[k][3]) / 4;
2278         }
2279      }
2280      return;
2281   case MESA_FORMAT_RGB:
2282      {
2283         GLuint i, j, k;
2284         const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
2285         const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
2286         GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
2287         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2288              i++, j += colStride, k += colStride) {
2289            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2290                         rowB[j][0] + rowB[k][0]) / 4;
2291            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2292                         rowB[j][1] + rowB[k][1]) / 4;
2293            dst[i][2] = (rowA[j][2] + rowA[k][2] +
2294                         rowB[j][2] + rowB[k][2]) / 4;
2295         }
2296      }
2297      return;
2298   case MESA_FORMAT_ALPHA:
2299   case MESA_FORMAT_LUMINANCE:
2300   case MESA_FORMAT_INTENSITY:
2301   case MESA_FORMAT_COLOR_INDEX:
2302      {
2303         GLuint i, j, k;
2304         const GLchan *rowA = (const GLchan *) srcRowA;
2305         const GLchan *rowB = (const GLchan *) srcRowB;
2306         GLchan *dst = (GLchan *) dstRow;
2307         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2308              i++, j += colStride, k += colStride) {
2309            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
2310         }
2311      }
2312      return;
2313   case MESA_FORMAT_LUMINANCE_ALPHA:
2314      {
2315         GLuint i, j, k;
2316         const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
2317         const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
2318         GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
2319         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2320              i++, j += colStride, k += colStride) {
2321            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2322                         rowB[j][0] + rowB[k][0]) / 4;
2323            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2324                         rowB[j][1] + rowB[k][1]) / 4;
2325         }
2326      }
2327      return;
2328   case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32:
2329      {
2330         GLuint i, j, k;
2331         const GLfloat *rowA = (const GLfloat *) srcRowA;
2332         const GLfloat *rowB = (const GLfloat *) srcRowB;
2333         GLfloat *dst = (GLfloat *) dstRow;
2334         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2335              i++, j += colStride, k += colStride) {
2336            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
2337         }
2338      }
2339      return;
2340   case MESA_FORMAT_DEPTH_COMPONENT16:
2341      {
2342         GLuint i, j, k;
2343         const GLushort *rowA = (const GLushort *) srcRowA;
2344         const GLushort *rowB = (const GLushort *) srcRowB;
2345         GLushort *dst = (GLushort *) dstRow;
2346         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2347              i++, j += colStride, k += colStride) {
2348            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
2349         }
2350      }
2351      return;
2352   /* Begin hardware formats */
2353   case MESA_FORMAT_RGBA8888:
2354   case MESA_FORMAT_ARGB8888:
2355      {
2356         GLuint i, j, k;
2357         const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
2358         const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
2359         GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
2360         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2361              i++, j += colStride, k += colStride) {
2362            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2363                         rowB[j][0] + rowB[k][0]) / 4;
2364            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2365                         rowB[j][1] + rowB[k][1]) / 4;
2366            dst[i][2] = (rowA[j][2] + rowA[k][2] +
2367                         rowB[j][2] + rowB[k][2]) / 4;
2368            dst[i][3] = (rowA[j][3] + rowA[k][3] +
2369                         rowB[j][3] + rowB[k][3]) / 4;
2370         }
2371      }
2372      return;
2373   case MESA_FORMAT_RGB888:
2374      {
2375         GLuint i, j, k;
2376         const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
2377         const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
2378         GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
2379         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2380              i++, j += colStride, k += colStride) {
2381            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2382                         rowB[j][0] + rowB[k][0]) / 4;
2383            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2384                         rowB[j][1] + rowB[k][1]) / 4;
2385            dst[i][2] = (rowA[j][2] + rowA[k][2] +
2386                         rowB[j][2] + rowB[k][2]) / 4;
2387         }
2388      }
2389      return;
2390   case MESA_FORMAT_RGB565:
2391      {
2392         GLuint i, j, k;
2393         const GLushort *rowA = (const GLushort *) srcRowA;
2394         const GLushort *rowB = (const GLushort *) srcRowB;
2395         GLushort *dst = (GLushort *) dstRow;
2396         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2397              i++, j += colStride, k += colStride) {
2398            const GLint rowAr0 = rowA[j] & 0x1f;
2399            const GLint rowAr1 = rowA[k] & 0x1f;
2400            const GLint rowBr0 = rowB[j] & 0x1f;
2401            const GLint rowBr1 = rowB[k] & 0x1f;
2402            const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
2403            const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
2404            const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
2405            const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
2406            const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
2407            const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
2408            const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
2409            const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
2410            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
2411            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
2412            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
2413            dst[i] = (blue << 11) | (green << 5) | red;
2414         }
2415      }
2416      return;
2417   case MESA_FORMAT_ARGB4444:
2418      {
2419         GLuint i, j, k;
2420         const GLushort *rowA = (const GLushort *) srcRowA;
2421         const GLushort *rowB = (const GLushort *) srcRowB;
2422         GLushort *dst = (GLushort *) dstRow;
2423         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2424              i++, j += colStride, k += colStride) {
2425            const GLint rowAr0 = rowA[j] & 0xf;
2426            const GLint rowAr1 = rowA[k] & 0xf;
2427            const GLint rowBr0 = rowB[j] & 0xf;
2428            const GLint rowBr1 = rowB[k] & 0xf;
2429            const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
2430            const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
2431            const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
2432            const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
2433            const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
2434            const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
2435            const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
2436            const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
2437            const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
2438            const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
2439            const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
2440            const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
2441            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
2442            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
2443            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
2444            const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
2445            dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
2446         }
2447      }
2448      return;
2449   case MESA_FORMAT_ARGB1555:
2450      {
2451         GLuint i, j, k;
2452         const GLushort *rowA = (const GLushort *) srcRowA;
2453         const GLushort *rowB = (const GLushort *) srcRowB;
2454         GLushort *dst = (GLushort *) dstRow;
2455         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2456              i++, j += colStride, k += colStride) {
2457            const GLint rowAr0 = rowA[j] & 0x1f;
2458            const GLint rowAr1 = rowA[k] & 0x1f;
2459            const GLint rowBr0 = rowB[j] & 0x1f;
2460            const GLint rowBr1 = rowB[k] & 0xf;
2461            const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
2462            const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
2463            const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
2464            const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
2465            const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
2466            const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
2467            const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
2468            const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
2469            const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
2470            const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
2471            const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
2472            const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
2473            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
2474            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
2475            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
2476            const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
2477            dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
2478         }
2479      }
2480      return;
2481   case MESA_FORMAT_AL88:
2482      {
2483         GLuint i, j, k;
2484         const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
2485         const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
2486         GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
2487         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2488              i++, j += colStride, k += colStride) {
2489            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2490                         rowB[j][0] + rowB[k][0]) >> 2;
2491            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2492                         rowB[j][1] + rowB[k][1]) >> 2;
2493         }
2494      }
2495      return;
2496   case MESA_FORMAT_RGB332:
2497      {
2498         GLuint i, j, k;
2499         const GLubyte *rowA = (const GLubyte *) srcRowA;
2500         const GLubyte *rowB = (const GLubyte *) srcRowB;
2501         GLubyte *dst = (GLubyte *) dstRow;
2502         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2503              i++, j += colStride, k += colStride) {
2504            const GLint rowAr0 = rowA[j] & 0x3;
2505            const GLint rowAr1 = rowA[k] & 0x3;
2506            const GLint rowBr0 = rowB[j] & 0x3;
2507            const GLint rowBr1 = rowB[k] & 0x3;
2508            const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
2509            const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
2510            const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
2511            const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
2512            const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
2513            const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
2514            const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
2515            const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
2516            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
2517            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
2518            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
2519            dst[i] = (blue << 5) | (green << 2) | red;
2520         }
2521      }
2522      return;
2523   case MESA_FORMAT_A8:
2524   case MESA_FORMAT_L8:
2525   case MESA_FORMAT_I8:
2526   case MESA_FORMAT_CI8:
2527      {
2528         GLuint i, j, k;
2529         const GLubyte *rowA = (const GLubyte *) srcRowA;
2530         const GLubyte *rowB = (const GLubyte *) srcRowB;
2531         GLubyte *dst = (GLubyte *) dstRow;
2532         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2533              i++, j += colStride, k += colStride) {
2534            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
2535         }
2536      }
2537      return;
2538   case MESA_FORMAT_RGBA_FLOAT32:
2539      {
2540         GLuint i, j, k;
2541         const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA;
2542         const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB;
2543         GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow;
2544         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2545              i++, j += colStride, k += colStride) {
2546            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2547                         rowB[j][0] + rowB[k][0]) * 0.25F;
2548            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2549                         rowB[j][1] + rowB[k][1]) * 0.25F;
2550            dst[i][2] = (rowA[j][2] + rowA[k][2] +
2551                         rowB[j][2] + rowB[k][2]) * 0.25F;
2552            dst[i][3] = (rowA[j][3] + rowA[k][3] +
2553                         rowB[j][3] + rowB[k][3]) * 0.25F;
2554         }
2555      }
2556      return;
2557   case MESA_FORMAT_RGBA_FLOAT16:
2558      {
2559         GLuint i, j, k, comp;
2560         const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA;
2561         const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB;
2562         GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow;
2563         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2564              i++, j += colStride, k += colStride) {
2565            for (comp = 0; comp < 4; comp++) {
2566               GLfloat aj, ak, bj, bk;
2567               aj = _mesa_half_to_float(rowA[j][comp]);
2568               ak = _mesa_half_to_float(rowA[k][comp]);
2569               bj = _mesa_half_to_float(rowB[j][comp]);
2570               bk = _mesa_half_to_float(rowB[k][comp]);
2571               dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
2572            }
2573         }
2574      }
2575      return;
2576   case MESA_FORMAT_RGB_FLOAT32:
2577      {
2578         GLuint i, j, k;
2579         const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA;
2580         const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB;
2581         GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow;
2582         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2583              i++, j += colStride, k += colStride) {
2584            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2585                         rowB[j][0] + rowB[k][0]) * 0.25F;
2586            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2587                         rowB[j][1] + rowB[k][1]) * 0.25F;
2588            dst[i][2] = (rowA[j][2] + rowA[k][2] +
2589                         rowB[j][2] + rowB[k][2]) * 0.25F;
2590         }
2591      }
2592      return;
2593   case MESA_FORMAT_RGB_FLOAT16:
2594      {
2595         GLuint i, j, k, comp;
2596         const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA;
2597         const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB;
2598         GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow;
2599         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2600              i++, j += colStride, k += colStride) {
2601            for (comp = 0; comp < 3; comp++) {
2602               GLfloat aj, ak, bj, bk;
2603               aj = _mesa_half_to_float(rowA[j][comp]);
2604               ak = _mesa_half_to_float(rowA[k][comp]);
2605               bj = _mesa_half_to_float(rowB[j][comp]);
2606               bk = _mesa_half_to_float(rowB[k][comp]);
2607               dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
2608            }
2609         }
2610      }
2611      return;
2612   case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
2613      {
2614         GLuint i, j, k;
2615         const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA;
2616         const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB;
2617         GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow;
2618         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2619              i++, j += colStride, k += colStride) {
2620            dst[i][0] = (rowA[j][0] + rowA[k][0] +
2621                         rowB[j][0] + rowB[k][0]) * 0.25F;
2622            dst[i][1] = (rowA[j][1] + rowA[k][1] +
2623                         rowB[j][1] + rowB[k][1]) * 0.25F;
2624         }
2625      }
2626      return;
2627   case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
2628      {
2629         GLuint i, j, k, comp;
2630         const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA;
2631         const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB;
2632         GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow;
2633         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2634              i++, j += colStride, k += colStride) {
2635            for (comp = 0; comp < 2; comp++) {
2636               GLfloat aj, ak, bj, bk;
2637               aj = _mesa_half_to_float(rowA[j][comp]);
2638               ak = _mesa_half_to_float(rowA[k][comp]);
2639               bj = _mesa_half_to_float(rowB[j][comp]);
2640               bk = _mesa_half_to_float(rowB[k][comp]);
2641               dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
2642            }
2643         }
2644      }
2645      return;
2646   case MESA_FORMAT_ALPHA_FLOAT32:
2647   case MESA_FORMAT_LUMINANCE_FLOAT32:
2648   case MESA_FORMAT_INTENSITY_FLOAT32:
2649      {
2650         GLuint i, j, k;
2651         const GLfloat *rowA = (const GLfloat *) srcRowA;
2652         const GLfloat *rowB = (const GLfloat *) srcRowB;
2653         GLfloat *dst = (GLfloat *) dstRow;
2654         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2655              i++, j += colStride, k += colStride) {
2656            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
2657         }
2658      }
2659      return;
2660   case MESA_FORMAT_ALPHA_FLOAT16:
2661   case MESA_FORMAT_LUMINANCE_FLOAT16:
2662   case MESA_FORMAT_INTENSITY_FLOAT16:
2663      {
2664         GLuint i, j, k;
2665         const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
2666         const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
2667         GLhalfARB *dst = (GLhalfARB *) dstRow;
2668         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2669              i++, j += colStride, k += colStride) {
2670            GLfloat aj, ak, bj, bk;
2671            aj = _mesa_half_to_float(rowA[j]);
2672            ak = _mesa_half_to_float(rowA[k]);
2673            bj = _mesa_half_to_float(rowB[j]);
2674            bk = _mesa_half_to_float(rowB[k]);
2675            dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
2676         }
2677      }
2678      return;
2679
2680   default:
2681      _mesa_problem(NULL, "bad format in do_row()");
2682   }
2683}
2684
2685
2686/*
2687 * These functions generate a 1/2-size mipmap image from a source image.
2688 * Texture borders are handled by copying or averaging the source image's
2689 * border texels, depending on the scale-down factor.
2690 */
2691
2692static void
2693make_1d_mipmap(const struct gl_texture_format *format, GLint border,
2694               GLint srcWidth, const GLubyte *srcPtr,
2695               GLint dstWidth, GLubyte *dstPtr)
2696{
2697   const GLint bpt = format->TexelBytes;
2698   const GLubyte *src;
2699   GLubyte *dst;
2700
2701   /* skip the border pixel, if any */
2702   src = srcPtr + border * bpt;
2703   dst = dstPtr + border * bpt;
2704
2705   /* we just duplicate the input row, kind of hack, saves code */
2706   do_row(format, srcWidth - 2 * border, src, src,
2707          dstWidth - 2 * border, dst);
2708
2709   if (border) {
2710      /* copy left-most pixel from source */
2711      MEMCPY(dstPtr, srcPtr, bpt);
2712      /* copy right-most pixel from source */
2713      MEMCPY(dstPtr + (dstWidth - 1) * bpt,
2714             srcPtr + (srcWidth - 1) * bpt,
2715             bpt);
2716   }
2717}
2718
2719
2720static void
2721make_2d_mipmap(const struct gl_texture_format *format, GLint border,
2722               GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
2723               GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
2724{
2725   const GLint bpt = format->TexelBytes;
2726   const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
2727   const GLint dstWidthNB = dstWidth - 2 * border;
2728   const GLint dstHeightNB = dstHeight - 2 * border;
2729   const GLint srcRowStride = bpt * srcWidth;
2730   const GLint dstRowStride = bpt * dstWidth;
2731   const GLubyte *srcA, *srcB;
2732   GLubyte *dst;
2733   GLint row;
2734
2735   /* Compute src and dst pointers, skipping any border */
2736   srcA = srcPtr + border * ((srcWidth + 1) * bpt);
2737   if (srcHeight > 1)
2738      srcB = srcA + srcRowStride;
2739   else
2740      srcB = srcA;
2741   dst = dstPtr + border * ((dstWidth + 1) * bpt);
2742
2743   for (row = 0; row < dstHeightNB; row++) {
2744      do_row(format, srcWidthNB, srcA, srcB,
2745             dstWidthNB, dst);
2746      srcA += 2 * srcRowStride;
2747      srcB += 2 * srcRowStride;
2748      dst += dstRowStride;
2749   }
2750
2751   /* This is ugly but probably won't be used much */
2752   if (border > 0) {
2753      /* fill in dest border */
2754      /* lower-left border pixel */
2755      MEMCPY(dstPtr, srcPtr, bpt);
2756      /* lower-right border pixel */
2757      MEMCPY(dstPtr + (dstWidth - 1) * bpt,
2758             srcPtr + (srcWidth - 1) * bpt, bpt);
2759      /* upper-left border pixel */
2760      MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
2761             srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
2762      /* upper-right border pixel */
2763      MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
2764             srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
2765      /* lower border */
2766      do_row(format, srcWidthNB,
2767             srcPtr + bpt,
2768             srcPtr + bpt,
2769             dstWidthNB, dstPtr + bpt);
2770      /* upper border */
2771      do_row(format, srcWidthNB,
2772             srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
2773             srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
2774             dstWidthNB,
2775             dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
2776      /* left and right borders */
2777      if (srcHeight == dstHeight) {
2778         /* copy border pixel from src to dst */
2779         for (row = 1; row < srcHeight; row++) {
2780            MEMCPY(dstPtr + dstWidth * row * bpt,
2781                   srcPtr + srcWidth * row * bpt, bpt);
2782            MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
2783                   srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
2784         }
2785      }
2786      else {
2787         /* average two src pixels each dest pixel */
2788         for (row = 0; row < dstHeightNB; row += 2) {
2789            do_row(format, 1,
2790                   srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
2791                   srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
2792                   1, dstPtr + (dstWidth * row + 1) * bpt);
2793            do_row(format, 1,
2794                   srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
2795                   srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
2796                   1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
2797         }
2798      }
2799   }
2800}
2801
2802
2803static void
2804make_3d_mipmap(const struct gl_texture_format *format, GLint border,
2805               GLint srcWidth, GLint srcHeight, GLint srcDepth,
2806               const GLubyte *srcPtr,
2807               GLint dstWidth, GLint dstHeight, GLint dstDepth,
2808               GLubyte *dstPtr)
2809{
2810   const GLint bpt = format->TexelBytes;
2811   const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
2812   const GLint srcDepthNB = srcDepth - 2 * border;
2813   const GLint dstWidthNB = dstWidth - 2 * border;
2814   const GLint dstHeightNB = dstHeight - 2 * border;
2815   const GLint dstDepthNB = dstDepth - 2 * border;
2816   GLvoid *tmpRowA, *tmpRowB;
2817   GLint img, row;
2818   GLint bytesPerSrcImage, bytesPerDstImage;
2819   GLint bytesPerSrcRow, bytesPerDstRow;
2820   GLint srcImageOffset, srcRowOffset;
2821
2822   (void) srcDepthNB; /* silence warnings */
2823
2824   /* Need two temporary row buffers */
2825   tmpRowA = MALLOC(srcWidth * bpt);
2826   if (!tmpRowA)
2827      return;
2828   tmpRowB = MALLOC(srcWidth * bpt);
2829   if (!tmpRowB) {
2830      FREE(tmpRowA);
2831      return;
2832   }
2833
2834   bytesPerSrcImage = srcWidth * srcHeight * bpt;
2835   bytesPerDstImage = dstWidth * dstHeight * bpt;
2836
2837   bytesPerSrcRow = srcWidth * bpt;
2838   bytesPerDstRow = dstWidth * bpt;
2839
2840   /* Offset between adjacent src images to be averaged together */
2841   srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
2842
2843   /* Offset between adjacent src rows to be averaged together */
2844   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
2845
2846   /*
2847    * Need to average together up to 8 src pixels for each dest pixel.
2848    * Break that down into 3 operations:
2849    *   1. take two rows from source image and average them together.
2850    *   2. take two rows from next source image and average them together.
2851    *   3. take the two averaged rows and average them for the final dst row.
2852    */
2853
2854   /*
2855   _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
2856          srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
2857   */
2858
2859   for (img = 0; img < dstDepthNB; img++) {
2860      /* first source image pointer, skipping border */
2861      const GLubyte *imgSrcA = srcPtr
2862         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
2863         + img * (bytesPerSrcImage + srcImageOffset);
2864      /* second source image pointer, skipping border */
2865      const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
2866      /* address of the dest image, skipping border */
2867      GLubyte *imgDst = dstPtr
2868         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
2869         + img * bytesPerDstImage;
2870
2871      /* setup the four source row pointers and the dest row pointer */
2872      const GLubyte *srcImgARowA = imgSrcA;
2873      const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
2874      const GLubyte *srcImgBRowA = imgSrcB;
2875      const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
2876      GLubyte *dstImgRow = imgDst;
2877
2878      for (row = 0; row < dstHeightNB; row++) {
2879         /* Average together two rows from first src image */
2880         do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
2881                srcWidthNB, tmpRowA);
2882         /* Average together two rows from second src image */
2883         do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
2884                srcWidthNB, tmpRowB);
2885         /* Average together the temp rows to make the final row */
2886         do_row(format, srcWidthNB, tmpRowA, tmpRowB,
2887                dstWidthNB, dstImgRow);
2888         /* advance to next rows */
2889         srcImgARowA += bytesPerSrcRow + srcRowOffset;
2890         srcImgARowB += bytesPerSrcRow + srcRowOffset;
2891         srcImgBRowA += bytesPerSrcRow + srcRowOffset;
2892         srcImgBRowB += bytesPerSrcRow + srcRowOffset;
2893         dstImgRow += bytesPerDstRow;
2894      }
2895   }
2896
2897   FREE(tmpRowA);
2898   FREE(tmpRowB);
2899
2900   /* Luckily we can leverage the make_2d_mipmap() function here! */
2901   if (border > 0) {
2902      /* do front border image */
2903      make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
2904                     dstWidth, dstHeight, dstPtr);
2905      /* do back border image */
2906      make_2d_mipmap(format, 1, srcWidth, srcHeight,
2907                     srcPtr + bytesPerSrcImage * (srcDepth - 1),
2908                     dstWidth, dstHeight,
2909                     dstPtr + bytesPerDstImage * (dstDepth - 1));
2910      /* do four remaining border edges that span the image slices */
2911      if (srcDepth == dstDepth) {
2912         /* just copy border pixels from src to dst */
2913         for (img = 0; img < dstDepthNB; img++) {
2914            const GLubyte *src;
2915            GLubyte *dst;
2916
2917            /* do border along [img][row=0][col=0] */
2918            src = srcPtr + (img + 1) * bytesPerSrcImage;
2919            dst = dstPtr + (img + 1) * bytesPerDstImage;
2920            MEMCPY(dst, src, bpt);
2921
2922            /* do border along [img][row=dstHeight-1][col=0] */
2923            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
2924                         + (srcHeight - 1) * bytesPerSrcRow;
2925            dst = dstPtr + (img + 1) * bytesPerDstImage
2926                         + (dstHeight - 1) * bytesPerDstRow;
2927            MEMCPY(dst, src, bpt);
2928
2929            /* do border along [img][row=0][col=dstWidth-1] */
2930            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
2931                         + (srcWidth - 1) * bpt;
2932            dst = dstPtr + (img + 1) * bytesPerDstImage
2933                         + (dstWidth - 1) * bpt;
2934            MEMCPY(dst, src, bpt);
2935
2936            /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
2937            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
2938                         + (bytesPerSrcImage - bpt);
2939            dst = dstPtr + (img + 1) * bytesPerDstImage
2940                         + (bytesPerDstImage - bpt);
2941            MEMCPY(dst, src, bpt);
2942         }
2943      }
2944      else {
2945         /* average border pixels from adjacent src image pairs */
2946         ASSERT(srcDepthNB == 2 * dstDepthNB);
2947         for (img = 0; img < dstDepthNB; img++) {
2948            const GLubyte *src;
2949            GLubyte *dst;
2950
2951            /* do border along [img][row=0][col=0] */
2952            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
2953            dst = dstPtr + (img + 1) * bytesPerDstImage;
2954            do_row(format, 1, src, src + srcImageOffset, 1, dst);
2955
2956            /* do border along [img][row=dstHeight-1][col=0] */
2957            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
2958                         + (srcHeight - 1) * bytesPerSrcRow;
2959            dst = dstPtr + (img + 1) * bytesPerDstImage
2960                         + (dstHeight - 1) * bytesPerDstRow;
2961            do_row(format, 1, src, src + srcImageOffset, 1, dst);
2962
2963            /* do border along [img][row=0][col=dstWidth-1] */
2964            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
2965                         + (srcWidth - 1) * bpt;
2966            dst = dstPtr + (img + 1) * bytesPerDstImage
2967                         + (dstWidth - 1) * bpt;
2968            do_row(format, 1, src, src + srcImageOffset, 1, dst);
2969
2970            /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
2971            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
2972                         + (bytesPerSrcImage - bpt);
2973            dst = dstPtr + (img + 1) * bytesPerDstImage
2974                         + (bytesPerDstImage - bpt);
2975            do_row(format, 1, src, src + srcImageOffset, 1, dst);
2976         }
2977      }
2978   }
2979}
2980
2981
2982/*
2983 * For GL_SGIX_generate_mipmap:
2984 * Generate a complete set of mipmaps from texObj's base-level image.
2985 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
2986 */
2987void
2988_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
2989                      const struct gl_texture_unit *texUnit,
2990                      struct gl_texture_object *texObj)
2991{
2992   const struct gl_texture_image *srcImage;
2993   const struct gl_texture_format *convertFormat;
2994   const GLubyte *srcData = NULL;
2995   GLubyte *dstData = NULL;
2996   GLint level, maxLevels;
2997
2998   ASSERT(texObj);
2999   srcImage = texObj->Image[0][texObj->BaseLevel];
3000   ASSERT(srcImage);
3001
3002   maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
3003   ASSERT(maxLevels > 0);  /* bad target */
3004
3005   /* Find convertFormat - the format that do_row() will process */
3006   if (srcImage->IsCompressed) {
3007      /* setup for compressed textures */
3008      GLuint row;
3009      GLint  components, size;
3010      GLchan *dst;
3011
3012      assert(texObj->Target == GL_TEXTURE_2D);
3013
3014      if (srcImage->Format == GL_RGB) {
3015         convertFormat = &_mesa_texformat_rgb;
3016         components = 3;
3017      }
3018      else if (srcImage->Format == GL_RGBA) {
3019         convertFormat = &_mesa_texformat_rgba;
3020         components = 4;
3021      }
3022      else {
3023         _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps");
3024         return;
3025      }
3026
3027      /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3028      size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE)
3029         * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
3030      /* 20 extra bytes, just be safe when calling last FetchTexel */
3031      srcData = (GLubyte *) MALLOC(size);
3032      if (!srcData) {
3033         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3034         return;
3035      }
3036      dstData = (GLubyte *) MALLOC(size / 2);  /* 1/4 would probably be OK */
3037      if (!dstData) {
3038         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3039         FREE((void *) srcData);
3040         return;
3041      }
3042
3043      /* decompress base image here */
3044      dst = (GLchan *) srcData;
3045      for (row = 0; row < srcImage->Height; row++) {
3046         GLuint col;
3047         for (col = 0; col < srcImage->Width; col++) {
3048            srcImage->FetchTexelc(srcImage, col, row, 0, dst);
3049            dst += components;
3050         }
3051      }
3052   }
3053   else {
3054      /* uncompressed */
3055      convertFormat = srcImage->TexFormat;
3056   }
3057
3058   for (level = texObj->BaseLevel; level < texObj->MaxLevel
3059           && level < maxLevels - 1; level++) {
3060      /* generate image[level+1] from image[level] */
3061      const struct gl_texture_image *srcImage;
3062      struct gl_texture_image *dstImage;
3063      GLint srcWidth, srcHeight, srcDepth;
3064      GLint dstWidth, dstHeight, dstDepth;
3065      GLint border, bytesPerTexel;
3066
3067      /* get src image parameters */
3068      srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3069      ASSERT(srcImage);
3070      srcWidth = srcImage->Width;
3071      srcHeight = srcImage->Height;
3072      srcDepth = srcImage->Depth;
3073      border = srcImage->Border;
3074
3075      /* compute next (level+1) image size */
3076      if (srcWidth - 2 * border > 1) {
3077         dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
3078      }
3079      else {
3080         dstWidth = srcWidth; /* can't go smaller */
3081      }
3082      if (srcHeight - 2 * border > 1) {
3083         dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
3084      }
3085      else {
3086         dstHeight = srcHeight; /* can't go smaller */
3087      }
3088      if (srcDepth - 2 * border > 1) {
3089         dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
3090      }
3091      else {
3092         dstDepth = srcDepth; /* can't go smaller */
3093      }
3094
3095      if (dstWidth == srcWidth &&
3096          dstHeight == srcHeight &&
3097          dstDepth == srcDepth) {
3098         /* all done */
3099         if (srcImage->IsCompressed) {
3100            FREE((void *) srcData);
3101            FREE(dstData);
3102         }
3103         return;
3104      }
3105
3106      /* get dest gl_texture_image */
3107      dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
3108      if (!dstImage) {
3109         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3110         return;
3111      }
3112
3113      /* Free old image data */
3114      if (dstImage->Data)
3115         MESA_PBUFFER_FREE(dstImage->Data);
3116
3117      /* initialize new image */
3118      _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
3119                                 dstDepth, border, srcImage->IntFormat);
3120      dstImage->DriverData = NULL;
3121      dstImage->TexFormat = srcImage->TexFormat;
3122      dstImage->FetchTexelc = srcImage->FetchTexelc;
3123      dstImage->FetchTexelf = srcImage->FetchTexelf;
3124      ASSERT(dstImage->TexFormat);
3125      ASSERT(dstImage->FetchTexelc);
3126      ASSERT(dstImage->FetchTexelf);
3127
3128      /* Alloc new teximage data buffer.
3129       * Setup src and dest data pointers.
3130       */
3131      if (dstImage->IsCompressed) {
3132         ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
3133         dstImage->Data = MESA_PBUFFER_ALLOC(dstImage->CompressedSize);
3134         if (!dstImage->Data) {
3135            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3136            return;
3137         }
3138         /* srcData and dstData are already set */
3139         ASSERT(srcData);
3140         ASSERT(dstData);
3141      }
3142      else {
3143         bytesPerTexel = srcImage->TexFormat->TexelBytes;
3144         ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
3145         dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth
3146                                             * bytesPerTexel);
3147         if (!dstImage->Data) {
3148            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3149            return;
3150         }
3151         srcData = (const GLubyte *) srcImage->Data;
3152         dstData = (GLubyte *) dstImage->Data;
3153      }
3154
3155      /*
3156       * We use simple 2x2 averaging to compute the next mipmap level.
3157       */
3158      switch (target) {
3159         case GL_TEXTURE_1D:
3160            make_1d_mipmap(convertFormat, border,
3161                           srcWidth, srcData,
3162                           dstWidth, dstData);
3163            break;
3164         case GL_TEXTURE_2D:
3165         case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3166         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3167         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3168         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3169         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3170         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3171            make_2d_mipmap(convertFormat, border,
3172                           srcWidth, srcHeight, srcData,
3173                           dstWidth, dstHeight, dstData);
3174            break;
3175         case GL_TEXTURE_3D:
3176            make_3d_mipmap(convertFormat, border,
3177                           srcWidth, srcHeight, srcDepth, srcData,
3178                           dstWidth, dstHeight, dstDepth, dstData);
3179            break;
3180         case GL_TEXTURE_RECTANGLE_NV:
3181            /* no mipmaps, do nothing */
3182            break;
3183         default:
3184            _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
3185            return;
3186      }
3187
3188      if (dstImage->IsCompressed) {
3189         GLubyte *temp;
3190         /* compress image from dstData into dstImage->Data */
3191         const GLenum srcFormat = convertFormat->BaseFormat;
3192         GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat,
3193                                                          dstWidth);
3194         ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
3195         dstImage->TexFormat->StoreImage(ctx, 2, dstImage->Format,
3196                                         dstImage->TexFormat,
3197                                         dstImage->Data,
3198                                         0, 0, 0, /* dstX/Y/Zoffset */
3199                                         dstRowStride, 0, /* strides */
3200                                         dstWidth, dstHeight, 1, /* size */
3201                                         srcFormat, CHAN_TYPE,
3202                                         dstData, /* src data, actually */
3203                                         &ctx->DefaultPacking);
3204         /* swap src and dest pointers */
3205         temp = (GLubyte *) srcData;
3206         srcData = dstData;
3207         dstData = temp;
3208      }
3209
3210   } /* loop over mipmap levels */
3211}
3212