teximage.c revision 9fd2b0a698163b397b0a17493e52b27273e51b63
1
2/*
3 * Mesa 3-D graphics library
4 * Version:  3.3
5 *
6 * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27#ifdef PC_HEADER
28#include "all.h"
29#else
30#include "glheader.h"
31#include "context.h"
32#include "image.h"
33#include "mem.h"
34#include "mmath.h"
35#include "span.h"
36#include "teximage.h"
37#include "texstate.h"
38#include "types.h"
39#endif
40
41
42/*
43 * NOTES:
44 *
45 * Mesa's native texture datatype is GLubyte.  Native formats are
46 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
47 * and GL_COLOR_INDEX.
48 * Device drivers are free to implement any internal format they want.
49 */
50
51
52/*
53 * Compute log base 2 of n.
54 * If n isn't an exact power of two return -1.
55 * If n<0 return -1.
56 */
57static int
58logbase2( int n )
59{
60   GLint i = 1;
61   GLint log2 = 0;
62
63   if (n<0) {
64      return -1;
65   }
66
67   while ( n > i ) {
68      i *= 2;
69      log2++;
70   }
71   if (i != n) {
72      return -1;
73   }
74   else {
75      return log2;
76   }
77}
78
79
80
81/*
82 * Given an internal texture format enum or 1, 2, 3, 4 return the
83 * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
84 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
85 * Return -1 if invalid enum.
86 */
87GLint
88_mesa_base_tex_format( GLint format )
89{
90   switch (format) {
91      case GL_ALPHA:
92      case GL_ALPHA4:
93      case GL_ALPHA8:
94      case GL_ALPHA12:
95      case GL_ALPHA16:
96         return GL_ALPHA;
97      case 1:
98      case GL_LUMINANCE:
99      case GL_LUMINANCE4:
100      case GL_LUMINANCE8:
101      case GL_LUMINANCE12:
102      case GL_LUMINANCE16:
103         return GL_LUMINANCE;
104      case 2:
105      case GL_LUMINANCE_ALPHA:
106      case GL_LUMINANCE4_ALPHA4:
107      case GL_LUMINANCE6_ALPHA2:
108      case GL_LUMINANCE8_ALPHA8:
109      case GL_LUMINANCE12_ALPHA4:
110      case GL_LUMINANCE12_ALPHA12:
111      case GL_LUMINANCE16_ALPHA16:
112         return GL_LUMINANCE_ALPHA;
113      case GL_INTENSITY:
114      case GL_INTENSITY4:
115      case GL_INTENSITY8:
116      case GL_INTENSITY12:
117      case GL_INTENSITY16:
118         return GL_INTENSITY;
119      case 3:
120      case GL_RGB:
121      case GL_R3_G3_B2:
122      case GL_RGB4:
123      case GL_RGB5:
124      case GL_RGB8:
125      case GL_RGB10:
126      case GL_RGB12:
127      case GL_RGB16:
128         return GL_RGB;
129      case 4:
130      case GL_RGBA:
131      case GL_RGBA2:
132      case GL_RGBA4:
133      case GL_RGB5_A1:
134      case GL_RGBA8:
135      case GL_RGB10_A2:
136      case GL_RGBA12:
137      case GL_RGBA16:
138         return GL_RGBA;
139      case GL_COLOR_INDEX:
140      case GL_COLOR_INDEX1_EXT:
141      case GL_COLOR_INDEX2_EXT:
142      case GL_COLOR_INDEX4_EXT:
143      case GL_COLOR_INDEX8_EXT:
144      case GL_COLOR_INDEX12_EXT:
145      case GL_COLOR_INDEX16_EXT:
146         return GL_COLOR_INDEX;
147      default:
148         return -1;  /* error */
149   }
150}
151
152
153
154/*
155 * Given an internal texture format enum or 1, 2, 3, 4 return the
156 * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
157 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.  Return the
158 * number of components for the format.  Return -1 if invalid enum.
159 */
160static GLint
161components_in_intformat( GLint format )
162{
163   switch (format) {
164      case GL_ALPHA:
165      case GL_ALPHA4:
166      case GL_ALPHA8:
167      case GL_ALPHA12:
168      case GL_ALPHA16:
169         return 1;
170      case 1:
171      case GL_LUMINANCE:
172      case GL_LUMINANCE4:
173      case GL_LUMINANCE8:
174      case GL_LUMINANCE12:
175      case GL_LUMINANCE16:
176         return 1;
177      case 2:
178      case GL_LUMINANCE_ALPHA:
179      case GL_LUMINANCE4_ALPHA4:
180      case GL_LUMINANCE6_ALPHA2:
181      case GL_LUMINANCE8_ALPHA8:
182      case GL_LUMINANCE12_ALPHA4:
183      case GL_LUMINANCE12_ALPHA12:
184      case GL_LUMINANCE16_ALPHA16:
185         return 2;
186      case GL_INTENSITY:
187      case GL_INTENSITY4:
188      case GL_INTENSITY8:
189      case GL_INTENSITY12:
190      case GL_INTENSITY16:
191         return 1;
192      case 3:
193      case GL_RGB:
194      case GL_R3_G3_B2:
195      case GL_RGB4:
196      case GL_RGB5:
197      case GL_RGB8:
198      case GL_RGB10:
199      case GL_RGB12:
200      case GL_RGB16:
201         return 3;
202      case 4:
203      case GL_RGBA:
204      case GL_RGBA2:
205      case GL_RGBA4:
206      case GL_RGB5_A1:
207      case GL_RGBA8:
208      case GL_RGB10_A2:
209      case GL_RGBA12:
210      case GL_RGBA16:
211         return 4;
212      case GL_COLOR_INDEX:
213      case GL_COLOR_INDEX1_EXT:
214      case GL_COLOR_INDEX2_EXT:
215      case GL_COLOR_INDEX4_EXT:
216      case GL_COLOR_INDEX8_EXT:
217      case GL_COLOR_INDEX12_EXT:
218      case GL_COLOR_INDEX16_EXT:
219         return 1;
220      default:
221         return -1;  /* error */
222   }
223}
224
225
226
227/*
228 * Examine the texImage->Format field and set the Red, Green, Blue, etc
229 * texel component sizes to default values.
230 * These fields are set only here by core Mesa but device drivers may
231 * overwritting these fields to indicate true texel resolution.
232 */
233static void
234set_teximage_component_sizes( struct gl_texture_image *texImage )
235{
236   switch (texImage->Format) {
237      case GL_ALPHA:
238         texImage->RedBits = 0;
239         texImage->GreenBits = 0;
240         texImage->BlueBits = 0;
241         texImage->AlphaBits = 8;
242         texImage->IntensityBits = 0;
243         texImage->LuminanceBits = 0;
244         texImage->IndexBits = 0;
245         break;
246      case GL_LUMINANCE:
247         texImage->RedBits = 0;
248         texImage->GreenBits = 0;
249         texImage->BlueBits = 0;
250         texImage->AlphaBits = 0;
251         texImage->IntensityBits = 0;
252         texImage->LuminanceBits = 8;
253         texImage->IndexBits = 0;
254         break;
255      case GL_LUMINANCE_ALPHA:
256         texImage->RedBits = 0;
257         texImage->GreenBits = 0;
258         texImage->BlueBits = 0;
259         texImage->AlphaBits = 8;
260         texImage->IntensityBits = 0;
261         texImage->LuminanceBits = 8;
262         texImage->IndexBits = 0;
263         break;
264      case GL_INTENSITY:
265         texImage->RedBits = 0;
266         texImage->GreenBits = 0;
267         texImage->BlueBits = 0;
268         texImage->AlphaBits = 0;
269         texImage->IntensityBits = 8;
270         texImage->LuminanceBits = 0;
271         texImage->IndexBits = 0;
272         break;
273      case GL_RED:
274         texImage->RedBits = 8;
275         texImage->GreenBits = 0;
276         texImage->BlueBits = 0;
277         texImage->AlphaBits = 0;
278         texImage->IntensityBits = 0;
279         texImage->LuminanceBits = 0;
280         texImage->IndexBits = 0;
281         break;
282      case GL_GREEN:
283         texImage->RedBits = 0;
284         texImage->GreenBits = 8;
285         texImage->BlueBits = 0;
286         texImage->AlphaBits = 0;
287         texImage->IntensityBits = 0;
288         texImage->LuminanceBits = 0;
289         texImage->IndexBits = 0;
290         break;
291      case GL_BLUE:
292         texImage->RedBits = 0;
293         texImage->GreenBits = 0;
294         texImage->BlueBits = 8;
295         texImage->AlphaBits = 0;
296         texImage->IntensityBits = 0;
297         texImage->LuminanceBits = 0;
298         texImage->IndexBits = 0;
299         break;
300      case GL_RGB:
301      case GL_BGR:
302         texImage->RedBits = 8;
303         texImage->GreenBits = 8;
304         texImage->BlueBits = 8;
305         texImage->AlphaBits = 0;
306         texImage->IntensityBits = 0;
307         texImage->LuminanceBits = 0;
308         texImage->IndexBits = 0;
309         break;
310      case GL_RGBA:
311      case GL_BGRA:
312      case GL_ABGR_EXT:
313         texImage->RedBits = 8;
314         texImage->GreenBits = 8;
315         texImage->BlueBits = 8;
316         texImage->AlphaBits = 8;
317         texImage->IntensityBits = 0;
318         texImage->LuminanceBits = 0;
319         texImage->IndexBits = 0;
320         break;
321      case GL_COLOR_INDEX:
322         texImage->RedBits = 0;
323         texImage->GreenBits = 0;
324         texImage->BlueBits = 0;
325         texImage->AlphaBits = 0;
326         texImage->IntensityBits = 0;
327         texImage->LuminanceBits = 0;
328         texImage->IndexBits = 8;
329         break;
330      default:
331         gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
332   }
333}
334
335
336
337/*
338 * Return new gl_texture_image struct with all fields initialized to zero.
339 */
340struct gl_texture_image *
341gl_alloc_texture_image( void )
342{
343   return CALLOC_STRUCT(gl_texture_image);
344}
345
346
347
348/*
349 * Initialize most fields of a gl_texture_image struct.
350 */
351static void
352init_texture_image( struct gl_texture_image *img,
353                    GLsizei width, GLsizei height, GLsizei depth,
354                    GLint border, GLenum internalFormat )
355{
356   ASSERT(img);
357   ASSERT(!img->Data);
358   img->Format = (GLenum) _mesa_base_tex_format(internalFormat);
359   set_teximage_component_sizes( img );
360   img->IntFormat = (GLenum) internalFormat;
361   img->Border = border;
362   img->Width = width;
363   img->Height = height;
364   img->Depth = depth;
365   img->WidthLog2 = logbase2(width - 2 * border);
366   if (height == 1)  /* 1-D texture */
367      img->HeightLog2 = 0;
368   else
369      img->HeightLog2 = logbase2(height - 2 * border);
370   if (depth == 1)   /* 2-D texture */
371      img->DepthLog2 = 0;
372   else
373      img->DepthLog2 = logbase2(depth - 2 * border);
374   img->Width2 = 1 << img->WidthLog2;
375   img->Height2 = 1 << img->HeightLog2;
376   img->Depth2 = 1 << img->DepthLog2;
377   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
378}
379
380
381
382void
383gl_free_texture_image( struct gl_texture_image *teximage )
384{
385   if (teximage->Data) {
386      FREE( teximage->Data );
387      teximage->Data = NULL;
388   }
389   FREE( teximage );
390}
391
392
393
394/* Need this to prevent an out-of-bounds memory access when using
395 * X86 optimized code.
396 */
397#ifdef USE_X86_ASM
398#  define EXTRA_BYTE 1
399#else
400#  define EXTRA_BYTE 0
401#endif
402
403
404
405/*
406 * Called by glTexImage[123]D.  Fill in a texture image with data given
407 * by the client.  All pixel transfer and unpack modes are handled here.
408 * NOTE: All texture image parameters should have already been error checked.
409 */
410static void
411make_texture_image( GLcontext *ctx,
412                    struct gl_texture_image *texImage,
413                    GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
414                    const struct gl_pixelstore_attrib *unpacking)
415{
416   GLint components, numPixels;
417   GLint internalFormat, width, height, depth, border;
418
419   ASSERT(ctx);
420   ASSERT(texImage);
421   ASSERT(!texImage->Data);
422   ASSERT(pixels);
423   ASSERT(unpacking);
424
425   internalFormat = texImage->IntFormat;
426   width = texImage->Width;
427   height = texImage->Height;
428   depth = texImage->Depth;
429   border = texImage->Border;
430   components = components_in_intformat(internalFormat);
431
432   ASSERT(width > 0);
433   ASSERT(height > 0);
434   ASSERT(depth > 0);
435   ASSERT(border == 0 || border == 1);
436   ASSERT(pixels);
437   ASSERT(unpacking);
438   ASSERT(components);
439
440   numPixels = width * height * depth;
441
442   texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
443   if (!texImage->Data)
444      return;      /* out of memory */
445
446   /*
447    * OK, the texture image struct has been initialized and the texture
448    * image memory has been allocated.
449    * Now fill in the texture image from the source data.
450    * This includes applying the pixel transfer operations.
451    */
452
453   /* try common 2D texture cases first */
454   if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
455       && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
456       && srcType == GL_UNSIGNED_BYTE && depth == 1) {
457
458      if (srcFormat == internalFormat ||
459          (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
460          (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
461          (srcFormat == GL_RGB && internalFormat == 3) ||
462          (srcFormat == GL_RGBA && internalFormat == 4)) {
463         /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
464          * GL_LUMINANCE_ALPHA, etc. texture formats.
465          */
466         const GLubyte *src = (const GLubyte *) _mesa_image_address(
467            unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
468         const GLint srcStride = _mesa_image_row_stride(unpacking, width,
469                                                        srcFormat, srcType);
470         GLubyte *dst = texImage->Data;
471         GLint dstBytesPerRow = width * components * sizeof(GLubyte);
472         if (srcStride == dstBytesPerRow) {
473            MEMCPY(dst, src, height * dstBytesPerRow);
474         }
475         else {
476            GLint i;
477            for (i = 0; i < height; i++) {
478               MEMCPY(dst, src, dstBytesPerRow);
479               src += srcStride;
480               dst += dstBytesPerRow;
481            }
482         }
483         return;  /* all done */
484      }
485      else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
486         /* commonly used by Quake */
487         const GLubyte *src = (const GLubyte *) _mesa_image_address(
488            unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
489         const GLint srcStride = _mesa_image_row_stride(unpacking, width,
490                                                        srcFormat, srcType);
491         GLubyte *dst = texImage->Data;
492         GLint i, j;
493         for (i = 0; i < height; i++) {
494            const GLubyte *s = src;
495            for (j = 0; j < width; j++) {
496               *dst++ = *s++;  /*red*/
497               *dst++ = *s++;  /*green*/
498               *dst++ = *s++;  /*blue*/
499               s++;            /*alpha*/
500            }
501            src += srcStride;
502         }
503         return;  /* all done */
504      }
505   }
506
507
508   /*
509    * General case solutions
510    */
511   if (texImage->Format == GL_COLOR_INDEX) {
512      /* color index texture */
513      const GLint destBytesPerRow = width * components * sizeof(GLubyte);
514      const GLenum dstType = GL_UNSIGNED_BYTE;
515      GLubyte *dest = texImage->Data;
516      GLint img, row;
517      for (img = 0; img < depth; img++) {
518         for (row = 0; row < height; row++) {
519            const GLvoid *source = _mesa_image_address(unpacking,
520                pixels, width, height, srcFormat, srcType, img, row, 0);
521            _mesa_unpack_index_span(ctx, width, dstType, dest,
522                                    srcType, source, unpacking, GL_TRUE);
523            dest += destBytesPerRow;
524         }
525      }
526   }
527   else {
528      /* regular, color texture */
529      const GLint destBytesPerRow = width * components * sizeof(GLubyte);
530      const GLenum dstFormat = texImage->Format;
531      GLubyte *dest = texImage->Data;
532      GLint img, row;
533      for (img = 0; img < depth; img++) {
534         for (row = 0; row < height; row++) {
535            const GLvoid *source = _mesa_image_address(unpacking,
536                   pixels, width, height, srcFormat, srcType, img, row, 0);
537            _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
538                   srcFormat, srcType, source, unpacking, GL_TRUE);
539            dest += destBytesPerRow;
540         }
541      }
542   }
543}
544
545
546
547/*
548 * glTexImage[123]D can accept a NULL image pointer.  In this case we
549 * create a texture image with unspecified image contents per the OpenGL
550 * spec.  This function creates an empty image for the given texture image.
551 */
552static void
553make_null_texture( struct gl_texture_image *texImage )
554{
555   GLint components;
556   GLint numPixels;
557
558   ASSERT(texImage);
559   ASSERT(!texImage->Data);
560
561   components = components_in_intformat(texImage->IntFormat);
562   numPixels = texImage->Width * texImage->Height * texImage->Depth;
563
564   texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
565
566   /*
567    * Let's see if anyone finds this.  If glTexImage2D() is called with
568    * a NULL image pointer then load the texture image with something
569    * interesting instead of leaving it indeterminate.
570    */
571   if (texImage->Data) {
572      static const char message[8][32] = {
573         "   X   X  XXXXX   XXX     X    ",
574         "   XX XX  X      X   X   X X   ",
575         "   X X X  X      X      X   X  ",
576         "   X   X  XXXX    XXX   XXXXX  ",
577         "   X   X  X          X  X   X  ",
578         "   X   X  X      X   X  X   X  ",
579         "   X   X  XXXXX   XXX   X   X  ",
580         "                               "
581      };
582
583      GLubyte *imgPtr = texImage->Data;
584      GLint i, j, k;
585      for (i = 0; i < texImage->Height; i++) {
586         GLint srcRow = 7 - i % 8;
587         for (j = 0; j < texImage->Width; j++) {
588            GLint srcCol = j % 32;
589            GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
590            for (k=0;k<components;k++) {
591               *imgPtr++ = (GLubyte) texel;
592            }
593         }
594      }
595   }
596}
597
598
599
600/*
601 * Test glTexImage[123]D() parameters for errors.
602 * Input:
603 *         dimensions - must be 1 or 2 or 3
604 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
605 */
606static GLboolean
607texture_error_check( GLcontext *ctx, GLenum target,
608                     GLint level, GLint internalFormat,
609                     GLenum format, GLenum type,
610                     GLuint dimensions,
611                     GLint width, GLint height,
612                     GLint depth, GLint border )
613{
614   GLboolean isProxy;
615   GLint iformat;
616
617   if (dimensions == 1) {
618      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
619      if (target != GL_TEXTURE_1D && !isProxy) {
620         gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
621         return GL_TRUE;
622      }
623   }
624   else if (dimensions == 2) {
625      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
626      if (target != GL_TEXTURE_2D && !isProxy) {
627          gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
628          return GL_TRUE;
629      }
630   }
631   else if (dimensions == 3) {
632      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
633      if (target != GL_TEXTURE_3D && !isProxy) {
634         gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
635         return GL_TRUE;
636      }
637   }
638   else {
639      gl_problem( ctx, "bad dims in texture_error_check" );
640      return GL_TRUE;
641   }
642
643   /* Border */
644   if (border != 0 && border != 1) {
645      if (!isProxy) {
646         char message[100];
647         sprintf(message, "glTexImage%dD(border)", dimensions);
648         gl_error(ctx, GL_INVALID_VALUE, message);
649      }
650      return GL_TRUE;
651   }
652
653   /* Width */
654   if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
655       || logbase2( width - 2 * border ) < 0) {
656      if (!isProxy) {
657         char message[100];
658         sprintf(message, "glTexImage%dD(width)", dimensions);
659         gl_error(ctx, GL_INVALID_VALUE, message);
660      }
661      return GL_TRUE;
662   }
663
664   /* Height */
665   if (dimensions >= 2) {
666      if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
667          || logbase2( height - 2 * border ) < 0) {
668         if (!isProxy) {
669            char message[100];
670            sprintf(message, "glTexImage%dD(height)", dimensions);
671            gl_error(ctx, GL_INVALID_VALUE, message);
672         }
673         return GL_TRUE;
674      }
675   }
676
677   /* Depth */
678   if (dimensions >= 3) {
679      if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
680          || logbase2( depth - 2 * border ) < 0) {
681         if (!isProxy) {
682            gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
683         }
684         return GL_TRUE;
685      }
686   }
687
688   /* Level */
689   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
690      if (!isProxy) {
691         char message[100];
692         sprintf(message, "glTexImage%dD(level)", dimensions);
693         gl_error(ctx, GL_INVALID_VALUE, message);
694      }
695      return GL_TRUE;
696   }
697
698   iformat = _mesa_base_tex_format( internalFormat );
699   if (iformat < 0) {
700      if (!isProxy) {
701         char message[100];
702         sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
703         gl_error(ctx, GL_INVALID_VALUE, message);
704      }
705      return GL_TRUE;
706   }
707
708   if (!_mesa_is_legal_format_and_type( format, type )) {
709      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
710       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
711       */
712      if (!isProxy) {
713         char message[100];
714         sprintf(message, "glTexImage%dD(format or type)", dimensions);
715         gl_error(ctx, GL_INVALID_OPERATION, message);
716      }
717      return GL_TRUE;
718   }
719
720   /* if we get here, the parameters are OK */
721   return GL_FALSE;
722}
723
724
725
726/*
727 * Test glTexSubImage[123]D() parameters for errors.
728 * Input:
729 *         dimensions - must be 1 or 2 or 3
730 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
731 */
732static GLboolean
733subtexture_error_check( GLcontext *ctx, GLuint dimensions,
734                        GLenum target, GLint level,
735                        GLint xoffset, GLint yoffset, GLint zoffset,
736                        GLint width, GLint height, GLint depth,
737                        GLenum format, GLenum type )
738{
739   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
740   struct gl_texture_image *destTex;
741
742   if (dimensions == 1) {
743      if (target != GL_TEXTURE_1D) {
744         gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
745         return GL_TRUE;
746      }
747   }
748   else if (dimensions == 2) {
749      if (target != GL_TEXTURE_2D) {
750         gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
751         return GL_TRUE;
752      }
753   }
754   else if (dimensions == 3) {
755      if (target != GL_TEXTURE_3D) {
756         gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
757         return GL_TRUE;
758      }
759   }
760   else {
761      gl_problem( ctx, "bad dims in texture_error_check" );
762      return GL_TRUE;
763   }
764
765   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
766      gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
767      return GL_TRUE;
768   }
769
770   if (width < 0) {
771      char message[100];
772      sprintf(message, "glTexSubImage%dD(width)", dimensions);
773      gl_error(ctx, GL_INVALID_VALUE, message);
774      return GL_TRUE;
775   }
776   if (height < 0 && dimensions > 1) {
777      char message[100];
778      sprintf(message, "glTexSubImage%dD(height)", dimensions);
779      gl_error(ctx, GL_INVALID_VALUE, message);
780      return GL_TRUE;
781   }
782   if (depth < 0 && dimensions > 2) {
783      char message[100];
784      sprintf(message, "glTexSubImage%dD(depth)", dimensions);
785      gl_error(ctx, GL_INVALID_VALUE, message);
786      return GL_TRUE;
787   }
788
789   destTex = texUnit->CurrentD[2]->Image[level];
790   if (!destTex) {
791      gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
792      return GL_TRUE;
793   }
794
795   if (xoffset < -((GLint)destTex->Border)) {
796      gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
797      return GL_TRUE;
798   }
799   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
800      gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
801      return GL_TRUE;
802   }
803   if (dimensions > 1) {
804      if (yoffset < -((GLint)destTex->Border)) {
805         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
806         return GL_TRUE;
807      }
808      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
809         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
810         return GL_TRUE;
811      }
812   }
813   if (dimensions > 2) {
814      if (zoffset < -((GLint)destTex->Border)) {
815         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
816         return GL_TRUE;
817      }
818      if (zoffset + depth  > (GLint) (destTex->Depth+destTex->Border)) {
819         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
820         return GL_TRUE;
821      }
822   }
823
824   if (!_mesa_is_legal_format_and_type(format, type)) {
825      char message[100];
826      sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
827      gl_error(ctx, GL_INVALID_ENUM, message);
828      return GL_TRUE;
829   }
830
831   return GL_FALSE;
832}
833
834
835/*
836 * Test glCopyTexImage[12]D() parameters for errors.
837 * Input:  dimensions - must be 1 or 2 or 3
838 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
839 */
840static GLboolean
841copytexture_error_check( GLcontext *ctx, GLuint dimensions,
842                         GLenum target, GLint level, GLint internalFormat,
843                         GLint width, GLint height, GLint border )
844{
845   GLint iformat;
846
847   if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
848      gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
849      return GL_TRUE;
850   }
851
852   if (dimensions == 1 && target != GL_TEXTURE_1D) {
853      gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
854      return GL_TRUE;
855   }
856   else if (dimensions == 2 && target != GL_TEXTURE_2D) {
857      gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
858      return GL_TRUE;
859   }
860
861   /* Border */
862   if (border!=0 && border!=1) {
863      char message[100];
864      sprintf(message, "glCopyTexImage%dD(border)", dimensions);
865      gl_error(ctx, GL_INVALID_VALUE, message);
866      return GL_TRUE;
867   }
868
869   /* Width */
870   if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
871       || logbase2( width - 2 * border ) < 0) {
872      char message[100];
873      sprintf(message, "glCopyTexImage%dD(width)", dimensions);
874      gl_error(ctx, GL_INVALID_VALUE, message);
875      return GL_TRUE;
876   }
877
878   /* Height */
879   if (dimensions >= 2) {
880      if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
881          || logbase2( height - 2 * border ) < 0) {
882         char message[100];
883         sprintf(message, "glCopyTexImage%dD(height)", dimensions);
884         gl_error(ctx, GL_INVALID_VALUE, message);
885         return GL_TRUE;
886      }
887   }
888
889   /* Level */
890   if (level<0 || level>=ctx->Const.MaxTextureLevels) {
891      char message[100];
892      sprintf(message, "glCopyTexImage%dD(level)", dimensions);
893      gl_error(ctx, GL_INVALID_VALUE, message);
894      return GL_TRUE;
895   }
896
897   iformat = _mesa_base_tex_format( internalFormat );
898   if (iformat < 0) {
899      char message[100];
900      sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
901      gl_error(ctx, GL_INVALID_VALUE, message);
902      return GL_TRUE;
903   }
904
905   /* if we get here, the parameters are OK */
906   return GL_FALSE;
907}
908
909
910static GLboolean
911copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
912                             GLenum target, GLint level,
913                             GLint xoffset, GLint yoffset, GLint zoffset,
914                             GLsizei width, GLsizei height )
915{
916   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
917   struct gl_texture_image *teximage;
918
919   if (dimensions == 1 && target != GL_TEXTURE_1D) {
920      gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
921      return GL_TRUE;
922   }
923   else if (dimensions == 2 && target != GL_TEXTURE_2D) {
924      gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
925      return GL_TRUE;
926   }
927   else if (dimensions == 3 && target != GL_TEXTURE_3D) {
928      gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
929      return GL_TRUE;
930   }
931
932   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
933      char message[100];
934      sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
935      gl_error(ctx, GL_INVALID_VALUE, message);
936      return GL_TRUE;
937   }
938
939   if (width < 0) {
940      char message[100];
941      sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
942      gl_error(ctx, GL_INVALID_VALUE, message);
943      return GL_TRUE;
944   }
945   if (dimensions > 1 && height < 0) {
946      char message[100];
947      sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
948      gl_error(ctx, GL_INVALID_VALUE, message);
949      return GL_TRUE;
950   }
951
952   teximage = texUnit->CurrentD[dimensions]->Image[level];
953   if (!teximage) {
954      char message[100];
955      sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
956      gl_error(ctx, GL_INVALID_OPERATION, message);
957      return GL_TRUE;
958   }
959
960   if (xoffset < -((GLint)teximage->Border)) {
961      char message[100];
962      sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
963      gl_error(ctx, GL_INVALID_VALUE, message);
964      return GL_TRUE;
965   }
966   if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
967      char message[100];
968      sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
969      gl_error(ctx, GL_INVALID_VALUE, message);
970      return GL_TRUE;
971   }
972   if (dimensions > 1) {
973      if (yoffset < -((GLint)teximage->Border)) {
974         char message[100];
975         sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
976         gl_error(ctx, GL_INVALID_VALUE, message);
977         return GL_TRUE;
978      }
979      /* NOTE: we're adding the border here, not subtracting! */
980      if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
981         char message[100];
982         sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
983         gl_error(ctx, GL_INVALID_VALUE, message);
984         return GL_TRUE;
985      }
986   }
987
988   if (dimensions > 2) {
989      if (zoffset < -((GLint)teximage->Border)) {
990         char message[100];
991         sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
992         gl_error(ctx, GL_INVALID_VALUE, message);
993         return GL_TRUE;
994      }
995      if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
996         char message[100];
997         sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
998         gl_error(ctx, GL_INVALID_VALUE, message);
999         return GL_TRUE;
1000      }
1001   }
1002
1003   /* if we get here, the parameters are OK */
1004   return GL_FALSE;
1005}
1006
1007
1008
1009
1010/*
1011 * Called from the API.  Note that width includes the border.
1012 */
1013void
1014_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1015                  GLsizei width, GLint border, GLenum format,
1016                  GLenum type, const GLvoid *pixels )
1017{
1018   GET_CURRENT_CONTEXT(ctx);
1019   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1020
1021   if (target==GL_TEXTURE_1D) {
1022      struct gl_texture_unit *texUnit;
1023      struct gl_texture_object *texObj;
1024      struct gl_texture_image *texImage;
1025
1026      if (texture_error_check( ctx, target, level, internalFormat,
1027                               format, type, 1, width, 1, 1, border )) {
1028         return;   /* error in texture image was detected */
1029      }
1030
1031      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1032      texObj = texUnit->CurrentD[1];
1033      texImage = texObj->Image[level];
1034
1035      if (!texImage) {
1036         texImage = gl_alloc_texture_image();
1037         texObj->Image[level] = texImage;
1038         if (!texImage) {
1039            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1040            return;
1041         }
1042      }
1043      else if (texImage->Data) {
1044         FREE(texImage->Data);
1045         texImage->Data = NULL;
1046      }
1047
1048      /* setup the teximage struct's fields */
1049      init_texture_image(texImage, width, 1, 1, border, internalFormat);
1050
1051      /* process the texture image */
1052      if (pixels) {
1053         GLboolean retain = GL_TRUE;
1054         GLboolean success = GL_FALSE;
1055         if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1056             && ctx->Driver.TexImage1D) {
1057            /* let device driver try to use raw image */
1058            success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1059                                                 type, pixels, &ctx->Unpack,
1060                                                 texObj, texImage, &retain);
1061         }
1062         if (retain || !success) {
1063            /* make internal copy of the texture image */
1064            make_texture_image(ctx, texImage, format, type,
1065                               pixels, &ctx->Unpack);
1066            if (!success && ctx->Driver.TexImage1D) {
1067               /* let device driver try to use unpacked image */
1068               (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1069                                          GL_UNSIGNED_BYTE, texImage->Data,
1070                                          &_mesa_native_packing,
1071                                          texObj, texImage, &retain);
1072            }
1073         }
1074         if (!retain && texImage->Data) {
1075            FREE(texImage->Data);
1076            texImage->Data = NULL;
1077         }
1078      }
1079      else {
1080         make_null_texture(texImage);
1081         if (ctx->Driver.TexImage1D) {
1082            GLboolean retain;
1083            (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1084                                       GL_UNSIGNED_BYTE, texImage->Data,
1085                                       &_mesa_native_packing,
1086                                       texObj, texImage, &retain);
1087         }
1088      }
1089
1090      /* state update */
1091      gl_put_texobj_on_dirty_list( ctx, texObj );
1092      ctx->NewState |= NEW_TEXTURING;
1093   }
1094   else if (target==GL_PROXY_TEXTURE_1D) {
1095      /* Proxy texture: check for errors and update proxy state */
1096      if (texture_error_check( ctx, target, level, internalFormat,
1097                               format, type, 1, width, 1, 1, border )) {
1098         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1099            MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1100                    sizeof(struct gl_texture_image) );
1101         }
1102      }
1103      else {
1104         ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1105         set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
1106         ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat;
1107         ctx->Texture.Proxy1D->Image[level]->Border = border;
1108         ctx->Texture.Proxy1D->Image[level]->Width = width;
1109         ctx->Texture.Proxy1D->Image[level]->Height = 1;
1110         ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1111      }
1112   }
1113   else {
1114      gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1115      return;
1116   }
1117}
1118
1119
1120void
1121_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1122                  GLsizei width, GLsizei height, GLint border,
1123                  GLenum format, GLenum type,
1124                  const GLvoid *pixels )
1125{
1126   GET_CURRENT_CONTEXT(ctx);
1127   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1128
1129   if (target==GL_TEXTURE_2D) {
1130      struct gl_texture_unit *texUnit;
1131      struct gl_texture_object *texObj;
1132      struct gl_texture_image *texImage;
1133
1134      if (texture_error_check( ctx, target, level, internalFormat,
1135                               format, type, 2, width, height, 1, border )) {
1136         return;   /* error in texture image was detected */
1137      }
1138
1139      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1140      texObj = texUnit->CurrentD[2];
1141      texImage = texObj->Image[level];
1142
1143      if (!texImage) {
1144         texImage = gl_alloc_texture_image();
1145         texObj->Image[level] = texImage;
1146         if (!texImage) {
1147            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1148            return;
1149         }
1150      }
1151      else if (texImage->Data) {
1152         FREE(texImage->Data);
1153         texImage->Data = NULL;
1154      }
1155
1156      /* setup the teximage struct's fields */
1157      init_texture_image(texImage, width, height, 1, border, internalFormat);
1158
1159      /* process the texture image */
1160      if (pixels) {
1161         GLboolean retain = GL_TRUE;
1162         GLboolean success = GL_FALSE;
1163         if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1164             && ctx->Driver.TexImage2D) {
1165            /* let device driver try to use raw image */
1166            success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1167                                                 type, pixels, &ctx->Unpack,
1168                                                 texObj, texImage, &retain);
1169         }
1170         if (retain || !success) {
1171            /* make internal copy of the texture image */
1172            make_texture_image(ctx, texImage, format, type,
1173                               pixels, &ctx->Unpack);
1174            if (!success && ctx->Driver.TexImage2D) {
1175               /* let device driver try to use unpacked image */
1176               (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1177                                          GL_UNSIGNED_BYTE, texImage->Data,
1178                                          &_mesa_native_packing,
1179                                          texObj, texImage, &retain);
1180            }
1181         }
1182         if (!retain && texImage->Data) {
1183            FREE(texImage->Data);
1184            texImage->Data = NULL;
1185         }
1186      }
1187      else {
1188         make_null_texture(texImage);
1189         if (ctx->Driver.TexImage2D) {
1190            GLboolean retain;
1191            (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1192                                       GL_UNSIGNED_BYTE, texImage->Data,
1193                                       &_mesa_native_packing,
1194                                       texObj, texImage, &retain);
1195         }
1196      }
1197
1198#define OLD_DD_TEXTURE
1199#ifdef OLD_DD_TEXTURE
1200      /* XXX this will be removed in the future */
1201      if (ctx->Driver.TexImage) {
1202         (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1203                                  texImage );
1204      }
1205#endif
1206
1207      /* state update */
1208      gl_put_texobj_on_dirty_list( ctx, texObj );
1209      ctx->NewState |= NEW_TEXTURING;
1210   }
1211   else if (target==GL_PROXY_TEXTURE_2D) {
1212      /* Proxy texture: check for errors and update proxy state */
1213      if (texture_error_check( ctx, target, level, internalFormat,
1214                               format, type, 2, width, height, 1, border )) {
1215         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1216            MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1217                    sizeof(struct gl_texture_image) );
1218         }
1219      }
1220      else {
1221         ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1222         set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
1223         ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat;
1224         ctx->Texture.Proxy2D->Image[level]->Border = border;
1225         ctx->Texture.Proxy2D->Image[level]->Width = width;
1226         ctx->Texture.Proxy2D->Image[level]->Height = height;
1227         ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1228      }
1229   }
1230   else {
1231      gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1232      return;
1233   }
1234}
1235
1236
1237
1238/*
1239 * Called by the API or display list executor.
1240 * Note that width and height include the border.
1241 */
1242void
1243_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1244                  GLsizei width, GLsizei height, GLsizei depth,
1245                  GLint border, GLenum format, GLenum type,
1246                  const GLvoid *pixels )
1247{
1248   GET_CURRENT_CONTEXT(ctx);
1249   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1250
1251   if (target==GL_TEXTURE_3D_EXT) {
1252      struct gl_texture_unit *texUnit;
1253      struct gl_texture_object *texObj;
1254      struct gl_texture_image *texImage;
1255      if (texture_error_check( ctx, target, level, internalFormat,
1256                               format, type, 3, width, height, depth,
1257                               border )) {
1258         return;   /* error in texture image was detected */
1259      }
1260
1261      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1262      texObj = texUnit->CurrentD[3];
1263      texImage = texObj->Image[level];
1264
1265      if (!texImage) {
1266         texImage = gl_alloc_texture_image();
1267         texObj->Image[level] = texImage;
1268         if (!texImage) {
1269            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1270            return;
1271         }
1272      }
1273      else if (texImage->Data) {
1274         FREE(texImage->Data);
1275         texImage->Data = NULL;
1276      }
1277
1278      /* setup the teximage struct's fields */
1279      init_texture_image(texImage, width, height, depth,
1280                         border, internalFormat);
1281
1282      /* process the texture image */
1283      if (pixels) {
1284         GLboolean retain = GL_TRUE;
1285         GLboolean success = GL_FALSE;
1286         if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1287             && ctx->Driver.TexImage3D) {
1288            /* let device driver try to use raw image */
1289            success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1290                                                 type, pixels, &ctx->Unpack,
1291                                                 texObj, texImage, &retain);
1292         }
1293         if (retain || !success) {
1294            /* make internal copy of the texture image */
1295            make_texture_image(ctx, texImage, format, type,
1296                               pixels, &ctx->Unpack);
1297            if (!success && ctx->Driver.TexImage3D) {
1298               /* let device driver try to use unpacked image */
1299               (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1300                                          GL_UNSIGNED_BYTE, texImage->Data,
1301                                          &_mesa_native_packing,
1302                                          texObj, texImage, &retain);
1303            }
1304         }
1305         if (!retain && texImage->Data) {
1306            FREE(texImage->Data);
1307            texImage->Data = NULL;
1308         }
1309      }
1310      else {
1311         make_null_texture(texImage);
1312         if (ctx->Driver.TexImage3D) {
1313            GLboolean retain;
1314            (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1315                                       GL_UNSIGNED_BYTE, texImage->Data,
1316                                       &_mesa_native_packing,
1317                                       texObj, texImage, &retain);
1318         }
1319      }
1320
1321      /* state update */
1322      gl_put_texobj_on_dirty_list( ctx, texObj );
1323      ctx->NewState |= NEW_TEXTURING;
1324   }
1325   else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1326      /* Proxy texture: check for errors and update proxy state */
1327      if (texture_error_check( ctx, target, level, internalFormat,
1328                               format, type, 3, width, height, depth,
1329                               border )) {
1330         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1331            MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1332                    sizeof(struct gl_texture_image) );
1333         }
1334      }
1335      else {
1336         ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1337         set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
1338         ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat;
1339         ctx->Texture.Proxy3D->Image[level]->Border = border;
1340         ctx->Texture.Proxy3D->Image[level]->Width = width;
1341         ctx->Texture.Proxy3D->Image[level]->Height = height;
1342         ctx->Texture.Proxy3D->Image[level]->Depth  = depth;
1343      }
1344   }
1345   else {
1346      gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1347      return;
1348   }
1349}
1350
1351
1352void
1353_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1354                     GLsizei width, GLsizei height, GLsizei depth,
1355                     GLint border, GLenum format, GLenum type,
1356                     const GLvoid *pixels )
1357{
1358   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1359                    depth, border, format, type, pixels);
1360}
1361
1362
1363/*
1364 * Fetch a texture image from the device driver.
1365 * Store the results in the given texture object at the given mipmap level.
1366 */
1367static void
1368get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1369                          const struct gl_texture_object *texObj )
1370{
1371   GLvoid *image;
1372   GLenum imgFormat, imgType;
1373   GLboolean freeImage;
1374   struct gl_texture_image *texImage;
1375   GLint destComponents, numPixels, srcBytesPerTexel;
1376
1377   if (!ctx->Driver.GetTexImage)
1378      return;
1379
1380   image = (*ctx->Driver.GetTexImage)( ctx, target, level,
1381                                       &imgFormat, &imgType, &freeImage);
1382   if (!image)
1383      return;
1384
1385   texImage = texObj->Image[level];
1386   ASSERT(texImage);
1387   if (!texImage)
1388      return;
1389
1390   destComponents = components_in_intformat(texImage->Format);
1391   assert(destComponents > 0);
1392   numPixels = texImage->Width * texImage->Height * texImage->Depth;
1393   assert(numPixels > 0);
1394   srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
1395   assert(srcBytesPerTexel > 0);
1396
1397   if (!texImage->Data) {
1398      /* Allocate memory for the texture image data */
1399      texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1400   }
1401
1402   if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1403      /* We got lucky!  The driver's format and type match Mesa's format. */
1404      if (texImage->Data) {
1405         MEMCPY(texImage->Data, image, numPixels * destComponents);
1406      }
1407   }
1408   else {
1409      /* Convert the texture image from the driver's format to Mesa's
1410       * internal format.
1411       */
1412      const GLint width = texImage->Width;
1413      const GLint height = texImage->Height;
1414      const GLint depth = texImage->Depth;
1415      const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1416      const GLint srcBytesPerRow = width * srcBytesPerTexel;
1417      const GLenum dstType = GL_UNSIGNED_BYTE;
1418      const GLenum dstFormat = texImage->Format;
1419      const GLubyte *srcPtr = (const GLubyte *) image;
1420      GLubyte *destPtr = texImage->Data;
1421
1422      if (texImage->Format == GL_COLOR_INDEX) {
1423         /* color index texture */
1424         GLint img, row;
1425         assert(imgFormat == GL_COLOR_INDEX);
1426         for (img = 0; img < depth; img++) {
1427            for (row = 0; row < height; row++) {
1428               _mesa_unpack_index_span(ctx, width, dstType, destPtr,
1429                             imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1430               destPtr += destBytesPerRow;
1431               srcPtr += srcBytesPerRow;
1432            }
1433         }
1434      }
1435      else {
1436         /* color texture */
1437         GLint img, row;
1438         for (img = 0; img < depth; img++) {
1439            for (row = 0; row < height; row++) {
1440               _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
1441                  imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1442               destPtr += destBytesPerRow;
1443               srcPtr += srcBytesPerRow;
1444            }
1445         }
1446      }
1447   }
1448
1449   if (freeImage)
1450      FREE(image);
1451}
1452
1453
1454void
1455_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1456                   GLenum type, GLvoid *pixels )
1457{
1458   GET_CURRENT_CONTEXT(ctx);
1459   const struct gl_texture_object *texObj;
1460   struct gl_texture_image *texImage;
1461   GLboolean discardImage;
1462
1463   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1464
1465   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1466      gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1467      return;
1468   }
1469
1470   if (_mesa_sizeof_type(type) <= 0) {
1471      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1472      return;
1473   }
1474
1475   if (_mesa_components_in_format(format) <= 0) {
1476      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1477      return;
1478   }
1479
1480   if (!pixels)
1481      return;
1482
1483   switch (target) {
1484      case GL_TEXTURE_1D:
1485         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1486         break;
1487      case GL_TEXTURE_2D:
1488         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1489         break;
1490      case GL_TEXTURE_3D:
1491         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1492         break;
1493      default:
1494         gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1495         return;
1496   }
1497
1498   texImage = texObj->Image[level];
1499   if (!texImage) {
1500      /* invalid mipmap level */
1501      return;
1502   }
1503
1504   if (!texImage->Data) {
1505      /* try to get the texture image from the device driver */
1506      get_teximage_from_driver(ctx, target, level, texObj);
1507      discardImage = GL_TRUE;
1508   }
1509   else {
1510      discardImage = GL_FALSE;
1511   }
1512
1513   if (texImage->Data) {
1514      GLint width = texImage->Width;
1515      GLint height = texImage->Height;
1516      GLint row;
1517
1518      for (row = 0; row < height; row++) {
1519         /* compute destination address in client memory */
1520         GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1521                                                width, height,
1522                                                format, type, 0, row, 0);
1523
1524         assert(dest);
1525         if (texImage->Format == GL_RGBA) {
1526            const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
1527            _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1528                                  format, type, dest, &ctx->Pack, GL_TRUE );
1529         }
1530         else {
1531            /* fetch RGBA row from texture image then pack it in client mem */
1532            GLubyte rgba[MAX_WIDTH][4];
1533            GLint i;
1534            const GLubyte *src;
1535            switch (texImage->Format) {
1536               case GL_ALPHA:
1537                  src = texImage->Data + row * width * sizeof(GLubyte);
1538                  for (i = 0; i < width; i++) {
1539                     rgba[i][RCOMP] = 255;
1540                     rgba[i][GCOMP] = 255;
1541                     rgba[i][BCOMP] = 255;
1542                     rgba[i][ACOMP] = src[i];
1543                  }
1544                  break;
1545               case GL_LUMINANCE:
1546                  src = texImage->Data + row * width * sizeof(GLubyte);
1547                  for (i = 0; i < width; i++) {
1548                     rgba[i][RCOMP] = src[i];
1549                     rgba[i][GCOMP] = src[i];
1550                     rgba[i][BCOMP] = src[i];
1551                     rgba[i][ACOMP] = 255;
1552                   }
1553                  break;
1554               case GL_LUMINANCE_ALPHA:
1555                  src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1556                  for (i = 0; i < width; i++) {
1557                     rgba[i][RCOMP] = src[i*2+0];
1558                     rgba[i][GCOMP] = src[i*2+0];
1559                     rgba[i][BCOMP] = src[i*2+0];
1560                     rgba[i][ACOMP] = src[i*2+1];
1561                  }
1562                  break;
1563               case GL_INTENSITY:
1564                  src = texImage->Data + row * width * sizeof(GLubyte);
1565                  for (i = 0; i < width; i++) {
1566                     rgba[i][RCOMP] = src[i];
1567                     rgba[i][GCOMP] = src[i];
1568                     rgba[i][BCOMP] = src[i];
1569                     rgba[i][ACOMP] = 255;
1570                  }
1571                  break;
1572               case GL_RGB:
1573                  src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1574                  for (i = 0; i < width; i++) {
1575                     rgba[i][RCOMP] = src[i*3+0];
1576                     rgba[i][GCOMP] = src[i*3+1];
1577                     rgba[i][BCOMP] = src[i*3+2];
1578                     rgba[i][ACOMP] = 255;
1579                  }
1580                  break;
1581               case GL_RGBA:
1582                  /* this special case should have been handled above! */
1583                  gl_problem( ctx, "error 1 in gl_GetTexImage" );
1584                  break;
1585               case GL_COLOR_INDEX:
1586                  gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1587                  break;
1588               default:
1589                  gl_problem( ctx, "bad format in gl_GetTexImage" );
1590            }
1591            _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1592                                  format, type, dest, &ctx->Pack, GL_TRUE );
1593         }
1594      }
1595
1596      /* if we got the teximage from the device driver we'll discard it now */
1597      if (discardImage) {
1598         FREE(texImage->Data);
1599         texImage->Data = NULL;
1600      }
1601   }
1602}
1603
1604
1605
1606void
1607_mesa_TexSubImage1D( GLenum target, GLint level,
1608                     GLint xoffset, GLsizei width,
1609                     GLenum format, GLenum type,
1610                     const GLvoid *pixels )
1611{
1612   GET_CURRENT_CONTEXT(ctx);
1613   struct gl_texture_unit *texUnit;
1614   struct gl_texture_object *texObj;
1615   struct gl_texture_image *texImage;
1616   GLboolean success = GL_FALSE;
1617
1618   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1619                              width, 1, 1, format, type)) {
1620      return;   /* error was detected */
1621   }
1622
1623   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1624   texObj = texUnit->CurrentD[1];
1625   texImage = texObj->Image[level];
1626   assert(texImage);
1627
1628   if (width == 0 || !pixels)
1629      return;  /* no-op, not an error */
1630
1631
1632   if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1633       && ctx->Driver.TexSubImage1D) {
1634      success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1635                                              width, format, type, pixels,
1636                                              &ctx->Unpack, texObj, texImage );
1637   }
1638   if (!success) {
1639      /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1640
1641      const GLint texComponents = components_in_intformat(texImage->Format);
1642      const GLenum texFormat = texImage->Format;
1643      const GLint xoffsetb = xoffset + texImage->Border;
1644      GLboolean retain = GL_TRUE;
1645      if (!texImage->Data) {
1646         get_teximage_from_driver( ctx, target, level, texObj );
1647         if (!texImage->Data) {
1648            make_null_texture(texImage);
1649         }
1650         if (!texImage->Data)
1651            return;  /* we're really out of luck! */
1652      }
1653
1654      if (texFormat == GL_COLOR_INDEX) {
1655         /* color index texture */
1656         GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1657         const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1658                                                 1, format, type, 0, 0, 0);
1659         _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1660                                 type, src, &ctx->Unpack, GL_TRUE);
1661      }
1662      else {
1663         /* color texture */
1664         GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1665         const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1666                                                 1, format, type, 0, 0, 0);
1667         _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1668                                       type, src, &ctx->Unpack, GL_TRUE);
1669      }
1670
1671      if (ctx->Driver.TexImage1D) {
1672         (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1673                                    GL_UNSIGNED_BYTE, texImage->Data,
1674                                    &_mesa_native_packing, texObj, texImage,
1675                                    &retain );
1676      }
1677
1678      if (!retain && texImage->Data) {
1679         FREE(texImage->Data);
1680         texImage->Data = NULL;
1681      }
1682   }
1683
1684   /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
1685}
1686
1687
1688void
1689_mesa_TexSubImage2D( GLenum target, GLint level,
1690                     GLint xoffset, GLint yoffset,
1691                     GLsizei width, GLsizei height,
1692                     GLenum format, GLenum type,
1693                     const GLvoid *pixels )
1694{
1695   GET_CURRENT_CONTEXT(ctx);
1696   struct gl_texture_unit *texUnit;
1697   struct gl_texture_object *texObj;
1698   struct gl_texture_image *texImage;
1699   GLboolean success = GL_FALSE;
1700
1701   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1702                              width, height, 1, format, type)) {
1703      return;   /* error was detected */
1704   }
1705
1706   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1707   texObj = texUnit->CurrentD[2];
1708   texImage = texObj->Image[level];
1709   assert(texImage);
1710
1711   if (width == 0 || height == 0 || !pixels)
1712      return;  /* no-op, not an error */
1713
1714   if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1715       && ctx->Driver.TexSubImage2D) {
1716      success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
1717                                     yoffset, width, height, format, type,
1718                                     pixels, &ctx->Unpack, texObj, texImage );
1719   }
1720   if (!success) {
1721      /* XXX if Driver.TexSubImage2D, unpack image and try again? */
1722
1723      const GLint texComponents = components_in_intformat(texImage->Format);
1724      const GLenum texFormat = texImage->Format;
1725      const GLint xoffsetb = xoffset + texImage->Border;
1726      const GLint yoffsetb = yoffset + texImage->Border;
1727      const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
1728                                                     format, type);
1729      const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
1730      GLboolean retain = GL_TRUE;
1731
1732      if (!texImage->Data) {
1733         get_teximage_from_driver( ctx, target, level, texObj );
1734         if (!texImage->Data) {
1735            make_null_texture(texImage);
1736         }
1737         if (!texImage->Data)
1738            return;  /* we're really out of luck! */
1739      }
1740
1741      if (texFormat == GL_COLOR_INDEX) {
1742         /* color index texture */
1743         GLubyte *dst = texImage->Data
1744                    + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1745         const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1746                                     width, height, format, type, 0, 0, 0);
1747         GLint row;
1748         for (row = 0; row < height; row++) {
1749            _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
1750                                 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1751            src += srcStride;
1752            dst += dstStride;
1753         }
1754      }
1755      else {
1756         /* color texture */
1757         GLubyte *dst = texImage->Data
1758                    + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1759         const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1760                                     width, height, format, type, 0, 0, 0);
1761         GLint row;
1762         for (row = 0; row < height; row++) {
1763            _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1764                           type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1765            src += srcStride;
1766            dst += dstStride;
1767         }
1768      }
1769
1770      if (ctx->Driver.TexImage2D) {
1771         (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
1772                                   GL_UNSIGNED_BYTE, texImage->Data,
1773                                   &_mesa_native_packing, texObj, texImage,
1774                                   &retain);
1775      }
1776
1777      if (!retain && texImage->Data) {
1778         FREE(texImage->Data);
1779         texImage->Data = NULL;
1780      }
1781
1782#ifdef OLD_DD_TEXTURE
1783      /* XXX this will be removed in the future */
1784      if (ctx->Driver.TexSubImage) {
1785         (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
1786                                    xoffset, yoffset, width, height,
1787                                    texImage->IntFormat, texImage);
1788      }
1789      else if (ctx->Driver.TexImage) {
1790         (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
1791                                 level, texImage->IntFormat, texImage );
1792      }
1793#endif
1794   }
1795}
1796
1797
1798
1799void
1800_mesa_TexSubImage3D( GLenum target, GLint level,
1801                     GLint xoffset, GLint yoffset, GLint zoffset,
1802                     GLsizei width, GLsizei height, GLsizei depth,
1803                     GLenum format, GLenum type,
1804                     const GLvoid *pixels )
1805{
1806   GET_CURRENT_CONTEXT(ctx);
1807   struct gl_texture_unit *texUnit;
1808   struct gl_texture_object *texObj;
1809   struct gl_texture_image *texImage;
1810   GLboolean success = GL_FALSE;
1811
1812   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1813                              width, height, depth, format, type)) {
1814      return;   /* error was detected */
1815   }
1816
1817   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1818   texObj = texUnit->CurrentD[3];
1819   texImage = texObj->Image[level];
1820   assert(texImage);
1821
1822   if (width == 0 || height == 0 || height == 0 || !pixels)
1823      return;  /* no-op, not an error */
1824
1825   if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1826       && ctx->Driver.TexSubImage3D) {
1827      success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
1828                                yoffset, zoffset, width, height, depth, format,
1829                                type, pixels, &ctx->Unpack, texObj, texImage );
1830   }
1831   if (!success) {
1832      /* XXX if Driver.TexSubImage3D, unpack image and try again? */
1833
1834      const GLint texComponents = components_in_intformat(texImage->Format);
1835      const GLenum texFormat = texImage->Format;
1836      const GLint xoffsetb = xoffset + texImage->Border;
1837      const GLint yoffsetb = yoffset + texImage->Border;
1838      const GLint zoffsetb = zoffset + texImage->Border;
1839      const GLint texWidth = texImage->Width;
1840      const GLint dstRectArea = texWidth * texImage->Height;
1841      const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
1842                                                     width, format, type);
1843      const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
1844      GLboolean retain = GL_TRUE;
1845
1846      if (texFormat == GL_COLOR_INDEX) {
1847         /* color index texture */
1848         GLint img, row;
1849         for (img = 0; img < depth; img++) {
1850            const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1851                                    width, height, format, type, img, 0, 0);
1852            GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1853                     + yoffsetb * texWidth + xoffsetb) * texComponents;
1854            for (row = 0; row < height; row++) {
1855               _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1856                         type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1857               src += srcStride;
1858               dst += dstStride;
1859            }
1860         }
1861      }
1862      else {
1863         /* color texture */
1864         GLint img, row;
1865         for (img = 0; img < depth; img++) {
1866            const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1867                                     width, height, format, type, img, 0, 0);
1868            GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1869                     + yoffsetb * texWidth + xoffsetb) * texComponents;
1870            for (row = 0; row < height; row++) {
1871               _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1872                   format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1873               src += srcStride;
1874               dst += dstStride;
1875            }
1876         }
1877      }
1878
1879      if (ctx->Driver.TexImage3D) {
1880         (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
1881                                   GL_UNSIGNED_BYTE, texImage->Data,
1882                                   &_mesa_native_packing, texObj, texImage,
1883                                   &retain);
1884      }
1885
1886      if (!retain && texImage->Data) {
1887         FREE(texImage->Data);
1888         texImage->Data = NULL;
1889      }
1890   }
1891}
1892
1893
1894
1895/*
1896 * Read an RGBA image from the frame buffer.
1897 * This is used by glCopyTexSubImage[12]D().
1898 * Input:  ctx - the context
1899 *         x, y - lower left corner
1900 *         width, height - size of region to read
1901 * Return: pointer to block of GL_RGBA, GLubyte data.
1902 */
1903static GLubyte *
1904read_color_image( GLcontext *ctx, GLint x, GLint y,
1905                  GLsizei width, GLsizei height )
1906{
1907   GLint stride, i;
1908   GLubyte *image, *dst;
1909
1910   image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
1911   if (!image)
1912      return NULL;
1913
1914   /* Select buffer to read from */
1915   (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1916                                 ctx->Pixel.DriverReadBuffer );
1917
1918   dst = image;
1919   stride = width * 4 * sizeof(GLubyte);
1920   for (i = 0; i < height; i++) {
1921      gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1922                         (GLubyte (*)[4]) dst );
1923      dst += stride;
1924   }
1925
1926   /* Read from draw buffer (the default) */
1927   (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1928                                 ctx->Color.DriverDrawBuffer );
1929
1930   return image;
1931}
1932
1933
1934
1935void
1936_mesa_CopyTexImage1D( GLenum target, GLint level,
1937                      GLenum internalFormat,
1938                      GLint x, GLint y,
1939                      GLsizei width, GLint border )
1940{
1941   GET_CURRENT_CONTEXT(ctx);
1942   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
1943
1944   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1945                               width, 1, border))
1946      return;
1947
1948   if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
1949       || !ctx->Driver.CopyTexImage1D
1950       || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
1951                         internalFormat, x, y, width, border))
1952   {
1953      GLubyte *image  = read_color_image( ctx, x, y, width, 1 );
1954      if (!image) {
1955         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
1956         return;
1957      }
1958      (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
1959                                border, GL_RGBA, GL_UNSIGNED_BYTE, image );
1960      FREE(image);
1961   }
1962}
1963
1964
1965
1966void
1967_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1968                      GLint x, GLint y, GLsizei width, GLsizei height,
1969                      GLint border )
1970{
1971   GET_CURRENT_CONTEXT(ctx);
1972   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
1973
1974   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1975                               width, height, border))
1976      return;
1977
1978   if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
1979       || !ctx->Driver.CopyTexImage2D
1980       || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
1981                         internalFormat, x, y, width, height, border))
1982   {
1983      GLubyte *image  = read_color_image( ctx, x, y, width, height );
1984      if (!image) {
1985         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
1986         return;
1987      }
1988      (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
1989                      height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
1990      FREE(image);
1991   }
1992}
1993
1994
1995
1996/*
1997 * Do the work of glCopyTexSubImage[123]D.
1998 */
1999static void
2000copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2001                    GLint width, GLint height,
2002                    GLint srcx, GLint srcy,
2003                    GLint dstx, GLint dsty, GLint dstz )
2004{
2005   GLint i;
2006   GLint format, components, rectarea;
2007   GLint texwidth, texheight, zoffset;
2008
2009   /* dst[xyz] may be negative if we have a texture border! */
2010   dstx += dest->Border;
2011   dsty += dest->Border;
2012   dstz += dest->Border;
2013   texwidth = dest->Width;
2014   texheight = dest->Height;
2015   rectarea = texwidth * texheight;
2016   zoffset = dstz * rectarea;
2017   format = dest->Format;
2018   components = components_in_intformat( format );
2019
2020   /* Select buffer to read from */
2021   (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2022                                 ctx->Pixel.DriverReadBuffer );
2023
2024   for (i = 0;i < height; i++) {
2025      GLubyte rgba[MAX_WIDTH][4];
2026      GLubyte *dst;
2027      gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
2028      dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2029      _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2030                                    GL_RGBA, GL_UNSIGNED_BYTE, rgba,
2031                                    &_mesa_native_packing, GL_TRUE);
2032   }
2033
2034   /* Read from draw buffer (the default) */
2035   (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2036                                 ctx->Color.DriverDrawBuffer );
2037}
2038
2039
2040
2041
2042void
2043_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2044                         GLint xoffset, GLint x, GLint y, GLsizei width )
2045{
2046   GET_CURRENT_CONTEXT(ctx);
2047   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2048
2049   if (copytexsubimage_error_check(ctx, 1, target, level,
2050                                   xoffset, 0, 0, width, 1))
2051      return;
2052
2053   if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2054       || !ctx->Driver.CopyTexSubImage1D
2055       || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2056                                            xoffset, x, y, width)) {
2057      struct gl_texture_unit *texUnit;
2058      struct gl_texture_image *teximage;
2059      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2060      teximage = texUnit->CurrentD[1]->Image[level];
2061      assert(teximage);
2062      if (teximage->Data) {
2063         copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
2064         /* tell driver about the change */
2065         /* XXX this is obsolete */
2066         if (ctx->Driver.TexImage) {
2067            (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2068                                     texUnit->CurrentD[1],
2069                                     level, teximage->IntFormat, teximage );
2070         }
2071      }
2072   }
2073}
2074
2075
2076
2077void
2078_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2079                         GLint xoffset, GLint yoffset,
2080                         GLint x, GLint y, GLsizei width, GLsizei height )
2081{
2082   GET_CURRENT_CONTEXT(ctx);
2083   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2084
2085   if (copytexsubimage_error_check(ctx, 2, target, level,
2086                                   xoffset, yoffset, 0, width, height))
2087      return;
2088
2089   if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2090       || !ctx->Driver.CopyTexSubImage2D
2091       || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2092                                xoffset, yoffset, x, y, width, height )) {
2093      struct gl_texture_unit *texUnit;
2094      struct gl_texture_image *teximage;
2095      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2096      teximage = texUnit->CurrentD[2]->Image[level];
2097      assert(teximage);
2098      if (teximage->Data) {
2099         copy_tex_sub_image(ctx, teximage, width, height,
2100                            x, y, xoffset, yoffset, 0);
2101         /* tell driver about the change */
2102         /* XXX this is obsolete */
2103         if (ctx->Driver.TexImage) {
2104            (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2105                                     texUnit->CurrentD[2],
2106                                     level, teximage->IntFormat, teximage );
2107	 }
2108      }
2109   }
2110}
2111
2112
2113
2114void
2115_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2116                         GLint xoffset, GLint yoffset, GLint zoffset,
2117                         GLint x, GLint y, GLsizei width, GLsizei height )
2118{
2119   GET_CURRENT_CONTEXT(ctx);
2120   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2121
2122   if (copytexsubimage_error_check(ctx, 3, target, level,
2123                    xoffset, yoffset, zoffset, width, height))
2124      return;
2125
2126   if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2127       || !ctx->Driver.CopyTexSubImage3D
2128       || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2129                     xoffset, yoffset, zoffset, x, y, width, height )) {
2130      struct gl_texture_unit *texUnit;
2131      struct gl_texture_image *teximage;
2132      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2133      teximage = texUnit->CurrentD[3]->Image[level];
2134      assert(teximage);
2135      if (teximage->Data) {
2136         copy_tex_sub_image(ctx, teximage, width, height,
2137                            x, y, xoffset, yoffset, zoffset);
2138         /* tell driver about the change */
2139         /* XXX this is obsolete */
2140         if (ctx->Driver.TexImage) {
2141            (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2142                                     texUnit->CurrentD[3],
2143                                     level, teximage->IntFormat, teximage );
2144         }
2145      }
2146   }
2147}
2148