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