teximage.c revision c52fc9b49cbd6158da9e96ccd57a38197293a3e0
1/* $Id: teximage.c,v 1.48 2000/09/05 22:11:38 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
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 "convolve.h"
34#include "image.h"
35#include "mem.h"
36#include "mmath.h"
37#include "span.h"
38#include "state.h"
39#include "teximage.h"
40#include "texstate.h"
41#include "types.h"
42#endif
43
44
45/*
46 * NOTES:
47 *
48 * Mesa's native texture datatype is GLubyte.  Native formats are
49 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
50 * and GL_COLOR_INDEX.
51 * Device drivers are free to implement any internal format they want.
52 */
53
54
55#ifdef DEBUG
56static void PrintTexture(const struct gl_texture_image *img)
57{
58  int i, j, c;
59  GLubyte *data = img->Data;
60
61  if (!data) {
62     printf("No texture data\n");
63     return;
64  }
65
66  switch (img->Format) {
67     case GL_ALPHA:
68     case GL_LUMINANCE:
69     case GL_INTENSITY:
70     case GL_COLOR_INDEX:
71        c = 1;
72        break;
73     case GL_LUMINANCE_ALPHA:
74        c = 2;
75        break;
76     case GL_RGB:
77        c = 3;
78        break;
79     case GL_RGBA:
80        c = 4;
81        break;
82     default:
83        gl_problem(NULL, "error in PrintTexture\n");
84        return;
85  }
86
87
88  for (i = 0; i < img->Height; i++) {
89    for (j = 0; j < img->Width; j++) {
90      if (c==1)
91        printf("%02x  ", data[0]);
92      else if (c==2)
93        printf("%02x%02x  ", data[0], data[1]);
94      else if (c==3)
95        printf("%02x%02x%02x  ", data[0], data[1], data[2]);
96      else if (c==4)
97        printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
98      data += c;
99    }
100    printf("\n");
101  }
102}
103#endif
104
105
106
107/*
108 * Compute log base 2 of n.
109 * If n isn't an exact power of two return -1.
110 * If n<0 return -1.
111 */
112static int
113logbase2( int n )
114{
115   GLint i = 1;
116   GLint log2 = 0;
117
118   if (n<0) {
119      return -1;
120   }
121
122   while ( n > i ) {
123      i *= 2;
124      log2++;
125   }
126   if (i != n) {
127      return -1;
128   }
129   else {
130      return log2;
131   }
132}
133
134
135
136/*
137 * Given an internal texture format enum or 1, 2, 3, 4 return the
138 * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
139 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
140 * Return -1 if invalid enum.
141 */
142GLint
143_mesa_base_tex_format( GLcontext *ctx, GLint format )
144{
145  /*
146   * Ask the driver for the base format, if it doesn't
147   * know, it will return -1;
148   */
149   if (ctx->Driver.BaseCompressedTexFormat) {
150      GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
151      if (ifmt >= 0) {
152         return ifmt;
153      }
154   }
155   switch (format) {
156      case GL_ALPHA:
157      case GL_ALPHA4:
158      case GL_ALPHA8:
159      case GL_ALPHA12:
160      case GL_ALPHA16:
161         return GL_ALPHA;
162      case 1:
163      case GL_LUMINANCE:
164      case GL_LUMINANCE4:
165      case GL_LUMINANCE8:
166      case GL_LUMINANCE12:
167      case GL_LUMINANCE16:
168         return GL_LUMINANCE;
169      case 2:
170      case GL_LUMINANCE_ALPHA:
171      case GL_LUMINANCE4_ALPHA4:
172      case GL_LUMINANCE6_ALPHA2:
173      case GL_LUMINANCE8_ALPHA8:
174      case GL_LUMINANCE12_ALPHA4:
175      case GL_LUMINANCE12_ALPHA12:
176      case GL_LUMINANCE16_ALPHA16:
177         return GL_LUMINANCE_ALPHA;
178      case GL_INTENSITY:
179      case GL_INTENSITY4:
180      case GL_INTENSITY8:
181      case GL_INTENSITY12:
182      case GL_INTENSITY16:
183         return GL_INTENSITY;
184      case 3:
185      case GL_RGB:
186      case GL_R3_G3_B2:
187      case GL_RGB4:
188      case GL_RGB5:
189      case GL_RGB8:
190      case GL_RGB10:
191      case GL_RGB12:
192      case GL_RGB16:
193         return GL_RGB;
194      case 4:
195      case GL_RGBA:
196      case GL_RGBA2:
197      case GL_RGBA4:
198      case GL_RGB5_A1:
199      case GL_RGBA8:
200      case GL_RGB10_A2:
201      case GL_RGBA12:
202      case GL_RGBA16:
203         return GL_RGBA;
204      case GL_COLOR_INDEX:
205      case GL_COLOR_INDEX1_EXT:
206      case GL_COLOR_INDEX2_EXT:
207      case GL_COLOR_INDEX4_EXT:
208      case GL_COLOR_INDEX8_EXT:
209      case GL_COLOR_INDEX12_EXT:
210      case GL_COLOR_INDEX16_EXT:
211         return GL_COLOR_INDEX;
212      default:
213         return -1;  /* error */
214   }
215}
216
217
218
219/*
220 * Given an internal texture format enum or 1, 2, 3, 4 return the
221 * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
222 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.  Return the
223 * number of components for the format.  Return -1 if invalid enum.
224 */
225static GLint
226components_in_intformat( GLint format )
227{
228   switch (format) {
229      case GL_ALPHA:
230      case GL_ALPHA4:
231      case GL_ALPHA8:
232      case GL_ALPHA12:
233      case GL_ALPHA16:
234         return 1;
235      case 1:
236      case GL_LUMINANCE:
237      case GL_LUMINANCE4:
238      case GL_LUMINANCE8:
239      case GL_LUMINANCE12:
240      case GL_LUMINANCE16:
241         return 1;
242      case 2:
243      case GL_LUMINANCE_ALPHA:
244      case GL_LUMINANCE4_ALPHA4:
245      case GL_LUMINANCE6_ALPHA2:
246      case GL_LUMINANCE8_ALPHA8:
247      case GL_LUMINANCE12_ALPHA4:
248      case GL_LUMINANCE12_ALPHA12:
249      case GL_LUMINANCE16_ALPHA16:
250         return 2;
251      case GL_INTENSITY:
252      case GL_INTENSITY4:
253      case GL_INTENSITY8:
254      case GL_INTENSITY12:
255      case GL_INTENSITY16:
256         return 1;
257      case 3:
258      case GL_RGB:
259      case GL_R3_G3_B2:
260      case GL_RGB4:
261      case GL_RGB5:
262      case GL_RGB8:
263      case GL_RGB10:
264      case GL_RGB12:
265      case GL_RGB16:
266         return 3;
267      case 4:
268      case GL_RGBA:
269      case GL_RGBA2:
270      case GL_RGBA4:
271      case GL_RGB5_A1:
272      case GL_RGBA8:
273      case GL_RGB10_A2:
274      case GL_RGBA12:
275      case GL_RGBA16:
276         return 4;
277      case GL_COLOR_INDEX:
278      case GL_COLOR_INDEX1_EXT:
279      case GL_COLOR_INDEX2_EXT:
280      case GL_COLOR_INDEX4_EXT:
281      case GL_COLOR_INDEX8_EXT:
282      case GL_COLOR_INDEX12_EXT:
283      case GL_COLOR_INDEX16_EXT:
284         return 1;
285      default:
286         return -1;  /* error */
287   }
288}
289
290
291/*
292 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
293 * otherwise.
294 */
295static GLboolean
296is_compressed_format(GLcontext *ctx, GLenum internalFormat)
297{
298    if (ctx->Driver.IsCompressedFormat) {
299        return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
300    }
301    return GL_FALSE;
302}
303
304
305
306/*
307 * Examine the texImage->Format field and set the Red, Green, Blue, etc
308 * texel component sizes to default values.
309 * These fields are set only here by core Mesa but device drivers may
310 * overwritting these fields to indicate true texel resolution.
311 */
312static void
313set_teximage_component_sizes( struct gl_texture_image *texImage )
314{
315   switch (texImage->Format) {
316      case GL_ALPHA:
317         texImage->RedBits = 0;
318         texImage->GreenBits = 0;
319         texImage->BlueBits = 0;
320         texImage->AlphaBits = 8;
321         texImage->IntensityBits = 0;
322         texImage->LuminanceBits = 0;
323         texImage->IndexBits = 0;
324         break;
325      case GL_LUMINANCE:
326         texImage->RedBits = 0;
327         texImage->GreenBits = 0;
328         texImage->BlueBits = 0;
329         texImage->AlphaBits = 0;
330         texImage->IntensityBits = 0;
331         texImage->LuminanceBits = 8;
332         texImage->IndexBits = 0;
333         break;
334      case GL_LUMINANCE_ALPHA:
335         texImage->RedBits = 0;
336         texImage->GreenBits = 0;
337         texImage->BlueBits = 0;
338         texImage->AlphaBits = 8;
339         texImage->IntensityBits = 0;
340         texImage->LuminanceBits = 8;
341         texImage->IndexBits = 0;
342         break;
343      case GL_INTENSITY:
344         texImage->RedBits = 0;
345         texImage->GreenBits = 0;
346         texImage->BlueBits = 0;
347         texImage->AlphaBits = 0;
348         texImage->IntensityBits = 8;
349         texImage->LuminanceBits = 0;
350         texImage->IndexBits = 0;
351         break;
352      case GL_RED:
353         texImage->RedBits = 8;
354         texImage->GreenBits = 0;
355         texImage->BlueBits = 0;
356         texImage->AlphaBits = 0;
357         texImage->IntensityBits = 0;
358         texImage->LuminanceBits = 0;
359         texImage->IndexBits = 0;
360         break;
361      case GL_GREEN:
362         texImage->RedBits = 0;
363         texImage->GreenBits = 8;
364         texImage->BlueBits = 0;
365         texImage->AlphaBits = 0;
366         texImage->IntensityBits = 0;
367         texImage->LuminanceBits = 0;
368         texImage->IndexBits = 0;
369         break;
370      case GL_BLUE:
371         texImage->RedBits = 0;
372         texImage->GreenBits = 0;
373         texImage->BlueBits = 8;
374         texImage->AlphaBits = 0;
375         texImage->IntensityBits = 0;
376         texImage->LuminanceBits = 0;
377         texImage->IndexBits = 0;
378         break;
379      case GL_RGB:
380      case GL_BGR:
381         texImage->RedBits = 8;
382         texImage->GreenBits = 8;
383         texImage->BlueBits = 8;
384         texImage->AlphaBits = 0;
385         texImage->IntensityBits = 0;
386         texImage->LuminanceBits = 0;
387         texImage->IndexBits = 0;
388         break;
389      case GL_RGBA:
390      case GL_BGRA:
391      case GL_ABGR_EXT:
392         texImage->RedBits = 8;
393         texImage->GreenBits = 8;
394         texImage->BlueBits = 8;
395         texImage->AlphaBits = 8;
396         texImage->IntensityBits = 0;
397         texImage->LuminanceBits = 0;
398         texImage->IndexBits = 0;
399         break;
400      case GL_COLOR_INDEX:
401         texImage->RedBits = 0;
402         texImage->GreenBits = 0;
403         texImage->BlueBits = 0;
404         texImage->AlphaBits = 0;
405         texImage->IntensityBits = 0;
406         texImage->LuminanceBits = 0;
407         texImage->IndexBits = 8;
408         break;
409      default:
410         gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
411   }
412}
413
414
415static void
416set_tex_image(struct gl_texture_object *tObj,
417              GLenum target, GLint level,
418              struct gl_texture_image *texImage)
419{
420   ASSERT(tObj);
421   ASSERT(texImage);
422   switch (target) {
423      case GL_TEXTURE_2D:
424         tObj->Image[level] = texImage;
425         return;
426      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
427         tObj->Image[level] = texImage;
428         return;
429      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
430         tObj->NegX[level] = texImage;
431         return;
432      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
433         tObj->PosY[level] = texImage;
434         return;
435      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
436         tObj->NegY[level] = texImage;
437         return;
438      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
439         tObj->PosZ[level] = texImage;
440         return;
441      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
442         tObj->NegZ[level] = texImage;
443         return;
444      default:
445         gl_problem(NULL, "bad target in set_tex_image()");
446         return;
447   }
448}
449
450
451/*
452 * Return new gl_texture_image struct with all fields initialized to zero.
453 */
454struct gl_texture_image *
455_mesa_alloc_texture_image( void )
456{
457   return CALLOC_STRUCT(gl_texture_image);
458}
459
460
461
462/*
463 * Initialize most fields of a gl_texture_image struct.
464 */
465static void
466init_texture_image( GLcontext *ctx,
467                    struct gl_texture_image *img,
468                    GLsizei width, GLsizei height, GLsizei depth,
469                    GLint border, GLenum internalFormat )
470{
471   ASSERT(img);
472   ASSERT(!img->Data);
473   img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat);
474   set_teximage_component_sizes( img );
475   img->IntFormat = (GLenum) internalFormat;
476   img->Border = border;
477   img->Width = width;
478   img->Height = height;
479   img->Depth = depth;
480   img->WidthLog2 = logbase2(width - 2 * border);
481   if (height == 1)  /* 1-D texture */
482      img->HeightLog2 = 0;
483   else
484      img->HeightLog2 = logbase2(height - 2 * border);
485   if (depth == 1)   /* 2-D texture */
486      img->DepthLog2 = 0;
487   else
488      img->DepthLog2 = logbase2(depth - 2 * border);
489   img->Width2 = 1 << img->WidthLog2;
490   img->Height2 = 1 << img->HeightLog2;
491   img->Depth2 = 1 << img->DepthLog2;
492   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
493   img->IsCompressed = is_compressed_format(ctx, internalFormat);
494}
495
496
497
498void
499_mesa_free_texture_image( struct gl_texture_image *teximage )
500{
501   if (teximage->Data) {
502      FREE( teximage->Data );
503      teximage->Data = NULL;
504   }
505   FREE( teximage );
506}
507
508
509
510/*
511 * Return number of bytes of storage needed to store a compressed texture
512 * image.  Only the driver knows for sure.  If the driver can't help us,
513 * we must return 0.
514 */
515GLuint
516_mesa_compressed_image_size(GLcontext *ctx,
517                            GLenum internalFormat,
518                            GLint numDimensions,
519                            GLint width,
520                            GLint height,
521                            GLint depth)
522{
523   if (ctx->Driver.CompressedImageSize) {
524      return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat,
525                                                numDimensions,
526                                                width, height, depth);
527   }
528   else {
529      /* Shouldn't this be an internal error of some sort? */
530      return 0;
531   }
532}
533
534
535
536/*
537 * Given a texture unit and a texture target, return the corresponding
538 * texture object.
539 */
540struct gl_texture_object *
541_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
542                        GLenum target)
543{
544   switch (target) {
545      case GL_TEXTURE_1D:
546         return texUnit->CurrentD[1];
547      case GL_PROXY_TEXTURE_1D:
548         return ctx->Texture.Proxy1D;
549      case GL_TEXTURE_2D:
550         return texUnit->CurrentD[2];
551      case GL_PROXY_TEXTURE_2D:
552         return ctx->Texture.Proxy2D;
553      case GL_TEXTURE_3D:
554         return texUnit->CurrentD[3];
555      case GL_PROXY_TEXTURE_3D:
556         return ctx->Texture.Proxy3D;
557      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
558      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
559      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
560      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
561      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
562      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
563         return ctx->Extensions.HaveTextureCubeMap
564                ? texUnit->CurrentCubeMap : NULL;
565      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
566         return ctx->Extensions.HaveTextureCubeMap
567                ? ctx->Texture.ProxyCubeMap : NULL;
568      default:
569         gl_problem(NULL, "bad target in _mesa_select_tex_object()");
570         return NULL;
571   }
572}
573
574
575/*
576 * Return the texture image struct which corresponds to target and level
577 * for the given texture unit.
578 */
579struct gl_texture_image *
580_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
581                       GLenum target, GLint level)
582{
583   ASSERT(texUnit);
584   switch (target) {
585      case GL_TEXTURE_1D:
586         return texUnit->CurrentD[1]->Image[level];
587      case GL_PROXY_TEXTURE_1D:
588         return ctx->Texture.Proxy1D->Image[level];
589      case GL_TEXTURE_2D:
590         return texUnit->CurrentD[2]->Image[level];
591      case GL_PROXY_TEXTURE_2D:
592         return ctx->Texture.Proxy2D->Image[level];
593      case GL_TEXTURE_3D:
594         return texUnit->CurrentD[3]->Image[level];
595      case GL_PROXY_TEXTURE_3D:
596         return ctx->Texture.Proxy3D->Image[level];
597      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
598         if (ctx->Extensions.HaveTextureCubeMap)
599            return texUnit->CurrentCubeMap->Image[level];
600         else
601            return NULL;
602      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
603         if (ctx->Extensions.HaveTextureCubeMap)
604            return texUnit->CurrentCubeMap->NegX[level];
605         else
606            return NULL;
607      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
608         if (ctx->Extensions.HaveTextureCubeMap)
609            return texUnit->CurrentCubeMap->PosY[level];
610         else
611            return NULL;
612      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
613         if (ctx->Extensions.HaveTextureCubeMap)
614            return texUnit->CurrentCubeMap->NegY[level];
615         else
616            return NULL;
617      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
618         if (ctx->Extensions.HaveTextureCubeMap)
619            return texUnit->CurrentCubeMap->PosZ[level];
620         else
621            return NULL;
622      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
623         if (ctx->Extensions.HaveTextureCubeMap)
624            return texUnit->CurrentCubeMap->NegZ[level];
625         else
626            return NULL;
627      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
628         if (ctx->Extensions.HaveTextureCubeMap)
629            return ctx->Texture.ProxyCubeMap->Image[level];
630         else
631            return NULL;
632      default:
633         gl_problem(ctx, "bad target in _mesa_select_tex_image()");
634         return NULL;
635   }
636}
637
638
639
640/*
641 * Calling glTexImage and related functions when convolution is enabled
642 * with GL_REDUCE border mode causes some complications.
643 * The incoming image must be extra large so that the post-convolution
644 * image size is reduced to a power of two size (plus 2 * border).
645 * This function adjusts a texture width and height accordingly if
646 * convolution with GL_REDUCE is enabled.
647 */
648static void
649adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions,
650                                    GLsizei *width, GLsizei *height)
651{
652   if (ctx->Pixel.Convolution1DEnabled
653       && dimensions == 1
654       && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
655      *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
656   }
657   else if (ctx->Pixel.Convolution2DEnabled
658            && dimensions > 1
659            && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
660      *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
661      *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
662   }
663   else if (ctx->Pixel.Separable2DEnabled
664            && dimensions > 1
665            && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
666      *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
667      *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
668   }
669}
670
671
672
673/*
674 * This function is used to move user image data into a texture image.
675 * We handle full texture images and subtexture images.  We also take
676 * care of all image transfer operations here, including convolution.
677 * Input:
678 *         dstXoffset, dstYoffset, dstZoffset - offsets in pixels
679 *         dstRowStride, dstImageStride - strides in bytes
680 */
681static void
682fill_texture_image( GLcontext *ctx, GLuint dimensions,
683                    GLenum texFormat, GLubyte *texAddr,
684                    GLint srcWidth, GLint srcHeight, GLint srcDepth,
685                    GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
686                    GLint dstRowStride, GLint dstImageStride,
687                    GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr,
688                    const struct gl_pixelstore_attrib *srcPacking)
689{
690   GLint texComponents;
691
692   ASSERT(ctx);
693   ASSERT(dimensions >= 1 && dimensions <= 3);
694   ASSERT(texAddr);
695   ASSERT(srcWidth >= 1);
696   ASSERT(srcHeight >= 1);
697   ASSERT(srcDepth >= 1);
698   ASSERT(dstXoffset >= 0);
699   ASSERT(dstYoffset >= 0);
700   ASSERT(dstZoffset >= 0);
701   ASSERT(dstRowStride >= 0);
702   ASSERT(dstImageStride >= 0);
703   ASSERT(srcAddr);
704   ASSERT(srcPacking);
705
706   texComponents = components_in_intformat(texFormat);
707
708   /* try common 2D texture cases first */
709   if (!ctx->ImageTransferState && dimensions == 2
710       && srcType == GL_UNSIGNED_BYTE) {
711
712      if (srcFormat == texFormat) {
713         /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
714          * GL_LUMINANCE_ALPHA, etc. texture formats.  Use memcpy().
715          */
716         const GLubyte *src = (const GLubyte *) _mesa_image_address(
717                                   srcPacking, srcAddr, srcWidth, srcHeight,
718                                   srcFormat, srcType, 0, 0, 0);
719         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
720                                               srcWidth, srcFormat, srcType);
721         const GLint widthInBytes = srcWidth * texComponents;
722         GLubyte *dst = texAddr + dstYoffset * dstRowStride
723                      + dstXoffset * texComponents * sizeof(GLubyte);
724         if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
725            MEMCPY(dst, src, srcHeight * widthInBytes);
726         }
727         else {
728            GLint i;
729            for (i = 0; i < srcHeight; i++) {
730               MEMCPY(dst, src, widthInBytes);
731               src += srcRowStride;
732               dst += dstRowStride;
733            }
734         }
735         return;  /* all done */
736      }
737      else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
738         /* commonly used by Quake */
739         const GLubyte *src = (const GLubyte *) _mesa_image_address(
740                                   srcPacking, srcAddr, srcWidth, srcHeight,
741                                   srcFormat, srcType, 0, 0, 0);
742         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
743                                               srcWidth, srcFormat, srcType);
744         GLubyte *dst = texAddr + dstYoffset * dstRowStride
745                      + dstXoffset * texComponents * sizeof(GLubyte);
746         GLint i, j;
747         for (i = 0; i < srcHeight; i++) {
748            const GLubyte *s = src;
749            GLubyte *d = dst;
750            for (j = 0; j < srcWidth; j++) {
751               *d++ = *s++;  /*red*/
752               *d++ = *s++;  /*green*/
753               *d++ = *s++;  /*blue*/
754               s++;          /*alpha*/
755            }
756            src += srcRowStride;
757            dst += dstRowStride;
758         }
759         return;  /* all done */
760      }
761   }
762
763   /*
764    * General case solutions
765    */
766   if (texFormat == GL_COLOR_INDEX) {
767      /* color index texture */
768      const GLenum texType = GL_UNSIGNED_BYTE;
769      GLint img, row;
770      GLubyte *dest = texAddr + dstZoffset * dstImageStride
771                    + dstYoffset * dstRowStride
772                    + dstXoffset * texComponents * sizeof(GLubyte);
773      for (img = 0; img < srcDepth; img++) {
774         GLubyte *destRow = dest;
775         for (row = 0; row < srcHeight; row++) {
776            const GLvoid *src = _mesa_image_address(srcPacking,
777                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
778            _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
779                                    srcType, src, srcPacking,
780                                    ctx->ImageTransferState);
781            destRow += dstRowStride;
782         }
783         dest += dstImageStride;
784      }
785   }
786   else {
787      /* regular, color texture */
788      if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
789          (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
790          (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
791         /*
792          * Fill texture image with convolution
793          */
794         GLint img, row;
795         GLint convWidth = srcWidth, convHeight = srcHeight;
796         GLfloat *tmpImage, *convImage;
797         tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
798         if (!tmpImage) {
799            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
800            return;
801         }
802         convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
803         if (!convImage) {
804            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
805            FREE(tmpImage);
806            return;
807         }
808
809         for (img = 0; img < srcDepth; img++) {
810            const GLfloat *srcf;
811            GLfloat *dstf = tmpImage;
812            GLubyte *dest;
813
814            /* unpack and do transfer ops up to convolution */
815            for (row = 0; row < srcHeight; row++) {
816               const GLvoid *src = _mesa_image_address(srcPacking,
817                                              srcAddr, srcWidth, srcHeight,
818                                              srcFormat, srcType, img, row, 0);
819               _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
820                          srcFormat, srcType, src, srcPacking,
821                          ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
822                          GL_TRUE);
823               dstf += srcWidth * 4;
824            }
825
826            /* convolve */
827            if (dimensions == 1) {
828               ASSERT(ctx->Pixel.Convolution1DEnabled);
829               _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
830            }
831            else {
832               if (ctx->Pixel.Convolution2DEnabled) {
833                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
834                                          tmpImage, convImage);
835               }
836               else {
837                  ASSERT(ctx->Pixel.Separable2DEnabled);
838                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
839                                           tmpImage, convImage);
840               }
841            }
842
843            /* packing and transfer ops after convolution */
844            srcf = convImage;
845            dest = texAddr + (dstZoffset + img) * dstImageStride
846                 + dstYoffset * dstRowStride;
847            for (row = 0; row < convHeight; row++) {
848               _mesa_pack_float_rgba_span(ctx, convWidth,
849                                          (const GLfloat (*)[4]) srcf,
850                                          texFormat, GL_UNSIGNED_BYTE,
851                                          dest, &_mesa_native_packing,
852                                          ctx->ImageTransferState
853                                          & IMAGE_POST_CONVOLUTION_BITS);
854               srcf += convWidth * 4;
855               dest += dstRowStride;
856            }
857         }
858
859         FREE(convImage);
860         FREE(tmpImage);
861      }
862      else {
863         /*
864          * no convolution
865          */
866         GLint img, row;
867         GLubyte *dest = texAddr + dstZoffset * dstImageStride
868                       + dstYoffset * dstRowStride
869                       + dstXoffset * texComponents * sizeof(GLubyte);
870         for (img = 0; img < srcDepth; img++) {
871            GLubyte *destRow = dest;
872            for (row = 0; row < srcHeight; row++) {
873               const GLvoid *srcRow = _mesa_image_address(srcPacking,
874                                              srcAddr, srcWidth, srcHeight,
875                                              srcFormat, srcType, img, row, 0);
876               _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow,
877                                       srcFormat, srcType, srcRow, srcPacking,
878                                       ctx->ImageTransferState);
879               destRow += dstRowStride;
880            }
881            dest += dstImageStride;
882         }
883      }
884   }
885}
886
887
888
889/* Need this to prevent an out-of-bounds memory access when using
890 * X86 optimized code.
891 */
892#ifdef USE_X86_ASM
893#  define EXTRA_BYTE 1
894#else
895#  define EXTRA_BYTE 0
896#endif
897
898
899
900/*
901 * Called by glTexImage[123]D.  Fill in a texture image with data given
902 * by the client.  All pixel transfer and unpack modes are handled here.
903 * Input:  dimensions (1, 2, or 3)
904 *         texImage - destination texture image (we'll malloc the memory)
905 *         width, height, depth - size of source image
906 *         srcFormat, srcType - source image format and type
907 *         pixels - source image data
908 *         srcPacking - source image packing parameters
909 *
910 * NOTE: All texture image parameters should have already been error checked.
911 *
912 * NOTE: the texImage dimensions and source image dimensions must be correct
913 * with respect to convolution with border mode = reduce.
914 */
915static void
916make_texture_image( GLcontext *ctx, GLuint dimensions,
917                    struct gl_texture_image *texImage,
918                    GLint width, GLint height, GLint depth,
919                    GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
920                    const struct gl_pixelstore_attrib *srcPacking)
921{
922   const GLint internalFormat = texImage->IntFormat;
923   const GLint components = components_in_intformat(internalFormat);
924   GLint convWidth = width, convHeight = height;
925
926   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) {
927      _mesa_update_image_transfer_state(ctx);
928   }
929
930   if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
931      adjust_texture_size_for_convolution(ctx, dimensions,
932                                          &convWidth, &convHeight);
933   }
934
935   texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth
936                                       * components + EXTRA_BYTE);
937   if (!texImage->Data)
938      return;      /* out of memory */
939
940   fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data,
941                      width, height, depth, 0, 0, 0,
942                      convWidth * components * sizeof(GLubyte),
943                      convWidth * convHeight * components * sizeof(GLubyte),
944                      srcFormat, srcType, pixels, srcPacking);
945}
946
947
948
949/*
950 * glTexImage[123]D can accept a NULL image pointer.  In this case we
951 * create a texture image with unspecified image contents per the OpenGL
952 * spec.  This function creates an empty image for the given texture image.
953 */
954static void
955make_null_texture( struct gl_texture_image *texImage )
956{
957   GLint components;
958   GLint numPixels;
959
960   ASSERT(texImage);
961   ASSERT(!texImage->Data);
962
963   components = components_in_intformat(texImage->IntFormat);
964   numPixels = texImage->Width * texImage->Height * texImage->Depth;
965
966   texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
967
968   /*
969    * Let's see if anyone finds this.  If glTexImage2D() is called with
970    * a NULL image pointer then load the texture image with something
971    * interesting instead of leaving it indeterminate.
972    */
973   if (texImage->Data) {
974      static const char message[8][32] = {
975         "   X   X  XXXXX   XXX     X    ",
976         "   XX XX  X      X   X   X X   ",
977         "   X X X  X      X      X   X  ",
978         "   X   X  XXXX    XXX   XXXXX  ",
979         "   X   X  X          X  X   X  ",
980         "   X   X  X      X   X  X   X  ",
981         "   X   X  XXXXX   XXX   X   X  ",
982         "                               "
983      };
984
985      GLubyte *imgPtr = texImage->Data;
986      GLint i, j, k;
987      for (i = 0; i < texImage->Height; i++) {
988         GLint srcRow = 7 - i % 8;
989         for (j = 0; j < texImage->Width; j++) {
990            GLint srcCol = j % 32;
991            GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
992            for (k=0;k<components;k++) {
993               *imgPtr++ = (GLubyte) texel;
994            }
995         }
996      }
997   }
998}
999
1000
1001
1002/*
1003 * This is called when a proxy texture test fails, we set all the
1004 * image members (except DriverData) to zero.
1005 */
1006static void
1007clear_proxy_teximage(struct gl_texture_image *img)
1008{
1009   ASSERT(img);
1010   img->Format = 0;
1011   img->IntFormat = 0;
1012   img->RedBits = 0;
1013   img->GreenBits = 0;
1014   img->BlueBits = 0;
1015   img->AlphaBits = 0;
1016   img->IntensityBits = 0;
1017   img->LuminanceBits = 0;
1018   img->IndexBits = 0;
1019   img->Border = 0;
1020   img->Width = 0;
1021   img->Height = 0;
1022   img->Depth = 0;
1023   img->Width2 = 0;
1024   img->Height2 = 0;
1025   img->Depth2 = 0;
1026   img->WidthLog2 = 0;
1027   img->HeightLog2 = 0;
1028   img->DepthLog2 = 0;
1029   img->Data = NULL;
1030   img->IsCompressed = 0;
1031   img->CompressedSize = 0;
1032}
1033
1034
1035
1036/*
1037 * Test glTexImage[123]D() parameters for errors.
1038 * Input:
1039 *         dimensions - must be 1 or 2 or 3
1040 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
1041 */
1042static GLboolean
1043texture_error_check( GLcontext *ctx, GLenum target,
1044                     GLint level, GLint internalFormat,
1045                     GLenum format, GLenum type,
1046                     GLuint dimensions,
1047                     GLint width, GLint height,
1048                     GLint depth, GLint border )
1049{
1050   GLboolean isProxy;
1051   GLint iformat;
1052
1053   if (dimensions == 1) {
1054      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
1055      if (target != GL_TEXTURE_1D && !isProxy) {
1056         gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1057         return GL_TRUE;
1058      }
1059   }
1060   else if (dimensions == 2) {
1061      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
1062      if (target != GL_TEXTURE_2D && !isProxy &&
1063          !(ctx->Extensions.HaveTextureCubeMap &&
1064            target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1065            target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1066          gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1067          return GL_TRUE;
1068      }
1069   }
1070   else if (dimensions == 3) {
1071      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
1072      if (target != GL_TEXTURE_3D && !isProxy) {
1073         gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1074         return GL_TRUE;
1075      }
1076   }
1077   else {
1078      gl_problem( ctx, "bad dims in texture_error_check" );
1079      return GL_TRUE;
1080   }
1081
1082   /* Border */
1083   if (border != 0 && border != 1) {
1084      if (!isProxy) {
1085         char message[100];
1086         sprintf(message, "glTexImage%dD(border)", dimensions);
1087         gl_error(ctx, GL_INVALID_VALUE, message);
1088      }
1089      return GL_TRUE;
1090   }
1091
1092   /* Width */
1093   if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1094       || logbase2( width - 2 * border ) < 0) {
1095      if (!isProxy) {
1096         char message[100];
1097         sprintf(message, "glTexImage%dD(width)", dimensions);
1098         gl_error(ctx, GL_INVALID_VALUE, message);
1099      }
1100      return GL_TRUE;
1101   }
1102
1103   /* Height */
1104   if (dimensions >= 2) {
1105      if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1106          || logbase2( height - 2 * border ) < 0) {
1107         if (!isProxy) {
1108            char message[100];
1109            sprintf(message, "glTexImage%dD(height)", dimensions);
1110            gl_error(ctx, GL_INVALID_VALUE, message);
1111         }
1112         return GL_TRUE;
1113      }
1114   }
1115
1116   /* For cube map, width must equal height */
1117   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1118       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1119      if (width != height) {
1120         if (!isProxy) {
1121            gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1122         }
1123         return GL_TRUE;
1124      }
1125   }
1126
1127   /* Depth */
1128   if (dimensions >= 3) {
1129      if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1130          || logbase2( depth - 2 * border ) < 0) {
1131         if (!isProxy) {
1132            gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1133         }
1134         return GL_TRUE;
1135      }
1136   }
1137
1138   /* Level */
1139   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1140      if (!isProxy) {
1141         char message[100];
1142         sprintf(message, "glTexImage%dD(level)", dimensions);
1143         gl_error(ctx, GL_INVALID_VALUE, message);
1144      }
1145      return GL_TRUE;
1146   }
1147
1148   iformat = _mesa_base_tex_format( ctx, internalFormat );
1149   if (iformat < 0) {
1150      if (!isProxy) {
1151         char message[100];
1152         sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1153         gl_error(ctx, GL_INVALID_VALUE, message);
1154      }
1155      return GL_TRUE;
1156   }
1157
1158   if (!is_compressed_format(ctx, internalFormat)) {
1159      if (!_mesa_is_legal_format_and_type( format, type )) {
1160         /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1161          * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
1162          */
1163         if (!isProxy) {
1164            char message[100];
1165            sprintf(message, "glTexImage%dD(format or type)", dimensions);
1166            gl_error(ctx, GL_INVALID_OPERATION, message);
1167         }
1168         return GL_TRUE;
1169      }
1170   }
1171
1172   /* if we get here, the parameters are OK */
1173   return GL_FALSE;
1174}
1175
1176
1177
1178/*
1179 * Test glTexSubImage[123]D() parameters for errors.
1180 * Input:
1181 *         dimensions - must be 1 or 2 or 3
1182 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
1183 */
1184static GLboolean
1185subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1186                        GLenum target, GLint level,
1187                        GLint xoffset, GLint yoffset, GLint zoffset,
1188                        GLint width, GLint height, GLint depth,
1189                        GLenum format, GLenum type )
1190{
1191   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1192   struct gl_texture_image *destTex;
1193
1194   if (dimensions == 1) {
1195      if (target != GL_TEXTURE_1D) {
1196         gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1197         return GL_TRUE;
1198      }
1199   }
1200   else if (dimensions == 2) {
1201      if (ctx->Extensions.HaveTextureCubeMap) {
1202         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1203              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1204             target != GL_TEXTURE_2D) {
1205            gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1206            return GL_TRUE;
1207         }
1208      }
1209      else if (target != GL_TEXTURE_2D) {
1210         gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1211         return GL_TRUE;
1212      }
1213   }
1214   else if (dimensions == 3) {
1215      if (target != GL_TEXTURE_3D) {
1216         gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1217         return GL_TRUE;
1218      }
1219   }
1220   else {
1221      gl_problem( ctx, "bad dims in texture_error_check" );
1222      return GL_TRUE;
1223   }
1224
1225   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1226      gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1227      return GL_TRUE;
1228   }
1229
1230   if (width < 0) {
1231      char message[100];
1232      sprintf(message, "glTexSubImage%dD(width)", dimensions);
1233      gl_error(ctx, GL_INVALID_VALUE, message);
1234      return GL_TRUE;
1235   }
1236   if (height < 0 && dimensions > 1) {
1237      char message[100];
1238      sprintf(message, "glTexSubImage%dD(height)", dimensions);
1239      gl_error(ctx, GL_INVALID_VALUE, message);
1240      return GL_TRUE;
1241   }
1242   if (depth < 0 && dimensions > 2) {
1243      char message[100];
1244      sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1245      gl_error(ctx, GL_INVALID_VALUE, message);
1246      return GL_TRUE;
1247   }
1248
1249   destTex = texUnit->CurrentD[2]->Image[level];
1250   if (!destTex) {
1251      gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1252      return GL_TRUE;
1253   }
1254
1255   if (xoffset < -((GLint)destTex->Border)) {
1256      gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1257      return GL_TRUE;
1258   }
1259   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1260      gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1261      return GL_TRUE;
1262   }
1263   if (dimensions > 1) {
1264      if (yoffset < -((GLint)destTex->Border)) {
1265         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1266         return GL_TRUE;
1267      }
1268      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1269         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1270         return GL_TRUE;
1271      }
1272   }
1273   if (dimensions > 2) {
1274      if (zoffset < -((GLint)destTex->Border)) {
1275         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1276         return GL_TRUE;
1277      }
1278      if (zoffset + depth  > (GLint) (destTex->Depth+destTex->Border)) {
1279         gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1280         return GL_TRUE;
1281      }
1282   }
1283
1284   if (!is_compressed_format(ctx, destTex->IntFormat)) {
1285      if (!_mesa_is_legal_format_and_type(format, type)) {
1286         char message[100];
1287         sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1288         gl_error(ctx, GL_INVALID_ENUM, message);
1289         return GL_TRUE;
1290      }
1291   }
1292
1293   return GL_FALSE;
1294}
1295
1296
1297/*
1298 * Test glCopyTexImage[12]D() parameters for errors.
1299 * Input:  dimensions - must be 1 or 2 or 3
1300 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
1301 */
1302static GLboolean
1303copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1304                         GLenum target, GLint level, GLint internalFormat,
1305                         GLint width, GLint height, GLint border )
1306{
1307   GLint iformat;
1308
1309   if (dimensions == 1) {
1310      if (target != GL_TEXTURE_1D) {
1311         gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1312         return GL_TRUE;
1313      }
1314   }
1315   else if (dimensions == 2) {
1316      if (ctx->Extensions.HaveTextureCubeMap) {
1317         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1318              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1319             target != GL_TEXTURE_2D) {
1320            gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1321            return GL_TRUE;
1322         }
1323      }
1324      else if (target != GL_TEXTURE_2D) {
1325         gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1326         return GL_TRUE;
1327      }
1328   }
1329
1330   /* Border */
1331   if (border!=0 && border!=1) {
1332      char message[100];
1333      sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1334      gl_error(ctx, GL_INVALID_VALUE, message);
1335      return GL_TRUE;
1336   }
1337
1338   /* Width */
1339   if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1340       || logbase2( width - 2 * border ) < 0) {
1341      char message[100];
1342      sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1343      gl_error(ctx, GL_INVALID_VALUE, message);
1344      return GL_TRUE;
1345   }
1346
1347   /* Height */
1348   if (dimensions >= 2) {
1349      if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1350          || logbase2( height - 2 * border ) < 0) {
1351         char message[100];
1352         sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1353         gl_error(ctx, GL_INVALID_VALUE, message);
1354         return GL_TRUE;
1355      }
1356   }
1357
1358   /* For cube map, width must equal height */
1359   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1360       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1361      if (width != height) {
1362         gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1363         return GL_TRUE;
1364      }
1365   }
1366
1367   /* Level */
1368   if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1369      char message[100];
1370      sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1371      gl_error(ctx, GL_INVALID_VALUE, message);
1372      return GL_TRUE;
1373   }
1374
1375   iformat = _mesa_base_tex_format( ctx, internalFormat );
1376   if (iformat < 0) {
1377      char message[100];
1378      sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1379      gl_error(ctx, GL_INVALID_VALUE, message);
1380      return GL_TRUE;
1381   }
1382
1383   /* if we get here, the parameters are OK */
1384   return GL_FALSE;
1385}
1386
1387
1388static GLboolean
1389copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1390                             GLenum target, GLint level,
1391                             GLint xoffset, GLint yoffset, GLint zoffset,
1392                             GLsizei width, GLsizei height )
1393{
1394   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1395   struct gl_texture_image *teximage;
1396
1397   if (dimensions == 1) {
1398      if (target != GL_TEXTURE_1D) {
1399         gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1400         return GL_TRUE;
1401      }
1402   }
1403   else if (dimensions == 2) {
1404      if (ctx->Extensions.HaveTextureCubeMap) {
1405         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1406              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1407             target != GL_TEXTURE_2D) {
1408            gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1409            return GL_TRUE;
1410         }
1411      }
1412      else if (target != GL_TEXTURE_2D) {
1413         gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1414         return GL_TRUE;
1415      }
1416   }
1417   else if (dimensions == 3) {
1418      if (target != GL_TEXTURE_3D) {
1419         gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1420         return GL_TRUE;
1421      }
1422   }
1423
1424   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1425      char message[100];
1426      sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1427      gl_error(ctx, GL_INVALID_VALUE, message);
1428      return GL_TRUE;
1429   }
1430
1431   if (width < 0) {
1432      char message[100];
1433      sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1434      gl_error(ctx, GL_INVALID_VALUE, message);
1435      return GL_TRUE;
1436   }
1437   if (dimensions > 1 && height < 0) {
1438      char message[100];
1439      sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1440      gl_error(ctx, GL_INVALID_VALUE, message);
1441      return GL_TRUE;
1442   }
1443
1444   teximage = texUnit->CurrentD[dimensions]->Image[level];
1445   if (!teximage) {
1446      char message[100];
1447      sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1448      gl_error(ctx, GL_INVALID_OPERATION, message);
1449      return GL_TRUE;
1450   }
1451
1452   if (xoffset < -((GLint)teximage->Border)) {
1453      char message[100];
1454      sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1455      gl_error(ctx, GL_INVALID_VALUE, message);
1456      return GL_TRUE;
1457   }
1458   if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1459      char message[100];
1460      sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1461      gl_error(ctx, GL_INVALID_VALUE, message);
1462      return GL_TRUE;
1463   }
1464   if (dimensions > 1) {
1465      if (yoffset < -((GLint)teximage->Border)) {
1466         char message[100];
1467         sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1468         gl_error(ctx, GL_INVALID_VALUE, message);
1469         return GL_TRUE;
1470      }
1471      /* NOTE: we're adding the border here, not subtracting! */
1472      if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1473         char message[100];
1474         sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1475         gl_error(ctx, GL_INVALID_VALUE, message);
1476         return GL_TRUE;
1477      }
1478   }
1479
1480   if (dimensions > 2) {
1481      if (zoffset < -((GLint)teximage->Border)) {
1482         char message[100];
1483         sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1484         gl_error(ctx, GL_INVALID_VALUE, message);
1485         return GL_TRUE;
1486      }
1487      if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1488         char message[100];
1489         sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1490         gl_error(ctx, GL_INVALID_VALUE, message);
1491         return GL_TRUE;
1492      }
1493   }
1494
1495   /* if we get here, the parameters are OK */
1496   return GL_FALSE;
1497}
1498
1499
1500
1501
1502/*
1503 * Turn generic compressed formats into specific compressed format.
1504 * Some of the compressed formats we don't support, so we
1505 * fall back to the uncompressed format.  (See issue 15 of
1506 * the GL_ARB_texture_compression specification.)
1507 */
1508static GLint
1509get_specific_compressed_tex_format(GLcontext *ctx,
1510                                   GLint ifmt, GLint numDimensions)
1511{
1512   char message[100];
1513   GLint internalFormat = ifmt;
1514
1515   if (ctx->Extensions.HaveTextureCompression
1516       && ctx->Driver.SpecificCompressedTexFormat) {
1517      /*
1518       * First, ask the driver for the specific format.
1519       */
1520      switch (internalFormat) {
1521         case GL_COMPRESSED_ALPHA_ARB:
1522         case GL_COMPRESSED_LUMINANCE_ARB:
1523         case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1524         case GL_COMPRESSED_INTENSITY_ARB:
1525         case GL_COMPRESSED_RGB_ARB:
1526         case GL_COMPRESSED_RGBA_ARB:
1527            internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1528                                         (ctx, internalFormat, numDimensions);
1529            /* XXX shouldn't we return now? */
1530            break;
1531         default:
1532            /* silence compiler warnings */
1533            ;
1534      }
1535   }
1536
1537   /*
1538    * Now, convert any generic format left to an uncompressed
1539    * specific format.  If the driver does not support compression
1540    * of the format, we must drop back to the uncompressed format.
1541    * See issue 15 of the GL_ARB_texture_compression specification.
1542    */
1543   switch (internalFormat) {
1544      case GL_COMPRESSED_ALPHA_ARB:
1545         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1546            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1547            gl_error(ctx, GL_INVALID_VALUE, message);
1548            return -1;
1549         }
1550         internalFormat = GL_ALPHA;
1551         break;
1552      case GL_COMPRESSED_LUMINANCE_ARB:
1553         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1554            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1555            gl_error(ctx, GL_INVALID_VALUE, message);
1556            return -1;
1557         }
1558         internalFormat = GL_LUMINANCE;
1559         break;
1560      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1561         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1562            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1563            gl_error(ctx, GL_INVALID_VALUE, message);
1564            return -1;
1565         }
1566         internalFormat = GL_LUMINANCE_ALPHA;
1567         break;
1568      case GL_COMPRESSED_INTENSITY_ARB:
1569         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1570            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1571            gl_error(ctx, GL_INVALID_VALUE, message);
1572            return -1;
1573         }
1574         internalFormat = GL_INTENSITY;
1575         break;
1576      case GL_COMPRESSED_RGB_ARB:
1577         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1578            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1579            gl_error(ctx, GL_INVALID_VALUE, message);
1580            return -1;
1581         }
1582         internalFormat = GL_RGB;
1583         break;
1584      case GL_COMPRESSED_RGBA_ARB:
1585         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1586            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1587            gl_error(ctx, GL_INVALID_VALUE, message);
1588            return -1;
1589         }
1590         internalFormat = GL_RGBA;
1591         break;
1592      default:
1593         /* silence compiler warning */
1594         ;
1595   }
1596   return internalFormat;
1597}
1598
1599
1600
1601/*
1602 * Called from the API.  Note that width includes the border.
1603 */
1604void
1605_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1606                  GLsizei width, GLint border, GLenum format,
1607                  GLenum type, const GLvoid *pixels )
1608{
1609   GLsizei postConvWidth;
1610   GET_CURRENT_CONTEXT(ctx);
1611   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1612
1613   postConvWidth = width;
1614   adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1615
1616   if (target==GL_TEXTURE_1D) {
1617      struct gl_texture_unit *texUnit;
1618      struct gl_texture_object *texObj;
1619      struct gl_texture_image *texImage;
1620      GLint ifmt;
1621
1622      ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1);
1623      if (ifmt < 0) {
1624         /*
1625          * The error here is that we were sent a generic compressed
1626          * format, but the extension is not supported.
1627          */
1628         return;
1629      }
1630      else {
1631         internalFormat = ifmt;
1632      }
1633
1634      if (texture_error_check(ctx, target, level, internalFormat,
1635                              format, type, 1, postConvWidth, 1, 1, border)) {
1636         return;   /* error in texture image was detected */
1637      }
1638
1639      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1640      texObj = texUnit->CurrentD[1];
1641      texImage = texObj->Image[level];
1642
1643      if (!texImage) {
1644         texImage = _mesa_alloc_texture_image();
1645         texObj->Image[level] = texImage;
1646         if (!texImage) {
1647            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1648            return;
1649         }
1650      }
1651      else if (texImage->Data) {
1652         FREE(texImage->Data);
1653         texImage->Data = NULL;
1654      }
1655
1656      /* setup the teximage struct's fields */
1657      init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
1658
1659      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1660         _mesa_update_image_transfer_state(ctx);
1661
1662      /* process the texture image */
1663      if (pixels) {
1664         GLboolean retain = GL_TRUE;
1665         GLboolean success = GL_FALSE;
1666         if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
1667            /* let device driver try to use raw image */
1668            success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1669                                                 type, pixels, &ctx->Unpack,
1670                                                 texObj, texImage, &retain);
1671         }
1672         if (retain || !success) {
1673            /* make internal copy of the texture image */
1674            make_texture_image(ctx, 1, texImage, width, 1, 1,
1675                               format, type, pixels, &ctx->Unpack);
1676            if (!success && ctx->Driver.TexImage1D) {
1677               /* let device driver try to use unpacked image */
1678               (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1679                                          GL_UNSIGNED_BYTE, texImage->Data,
1680                                          &_mesa_native_packing,
1681                                          texObj, texImage, &retain);
1682            }
1683         }
1684         if (!retain && texImage->Data) {
1685            FREE(texImage->Data);
1686            texImage->Data = NULL;
1687         }
1688      }
1689      else {
1690         make_null_texture(texImage);
1691         if (ctx->Driver.TexImage1D) {
1692            GLboolean retain;
1693            (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1694                                       GL_UNSIGNED_BYTE, texImage->Data,
1695                                       &_mesa_native_packing,
1696                                       texObj, texImage, &retain);
1697         }
1698      }
1699
1700      /* state update */
1701      gl_put_texobj_on_dirty_list( ctx, texObj );
1702      ctx->NewState |= NEW_TEXTURING;
1703   }
1704   else if (target==GL_PROXY_TEXTURE_1D) {
1705      /* Proxy texture: check for errors and update proxy state */
1706      if (texture_error_check(ctx, target, level, internalFormat,
1707                              format, type, 1, postConvWidth, 1, 1, border)) {
1708         /* if error, clear all proxy texture image parameters */
1709         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1710            clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
1711         }
1712      }
1713      else {
1714         /* if no error, update proxy texture image parameters */
1715         init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
1716                            width, 1, 1, border, internalFormat);
1717      }
1718   }
1719   else {
1720      gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1721      return;
1722   }
1723}
1724
1725
1726void
1727_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1728                  GLsizei width, GLsizei height, GLint border,
1729                  GLenum format, GLenum type,
1730                  const GLvoid *pixels )
1731{
1732   GLsizei postConvWidth, postConvHeight;
1733   GET_CURRENT_CONTEXT(ctx);
1734   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1735
1736   postConvWidth = width;
1737   postConvHeight = height;
1738   adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1739
1740   if (target==GL_TEXTURE_2D ||
1741       (ctx->Extensions.HaveTextureCubeMap &&
1742        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1743        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1744      struct gl_texture_unit *texUnit;
1745      struct gl_texture_object *texObj;
1746      struct gl_texture_image *texImage;
1747      GLint ifmt;
1748
1749      ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2);
1750      if (ifmt < 0) {
1751         /*
1752          * The error here is that we were sent a generic compressed
1753          * format, but the extension is not supported.
1754          */
1755         return;
1756      }
1757      else {
1758         internalFormat = ifmt;
1759      }
1760
1761      if (texture_error_check(ctx, target, level, internalFormat,
1762                              format, type, 2, postConvWidth, postConvHeight,
1763                              1, border)) {
1764         return;   /* error in texture image was detected */
1765      }
1766
1767      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1768      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1769      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1770
1771      if (!texImage) {
1772         texImage = _mesa_alloc_texture_image();
1773         set_tex_image(texObj, target, level, texImage);
1774         /*texObj->Image[level] = texImage;*/
1775         if (!texImage) {
1776            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1777            return;
1778         }
1779      }
1780      else if (texImage->Data) {
1781         FREE(texImage->Data);
1782         texImage->Data = NULL;
1783      }
1784
1785      /* setup the teximage struct's fields */
1786      init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
1787                         1, border, internalFormat);
1788
1789      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1790         _mesa_update_image_transfer_state(ctx);
1791
1792      /* process the texture image */
1793      if (pixels) {
1794         GLboolean retain = GL_TRUE;
1795         GLboolean success = GL_FALSE;
1796         if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
1797            /* let device driver try to use raw image */
1798            success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1799                                                 type, pixels, &ctx->Unpack,
1800                                                 texObj, texImage, &retain);
1801         }
1802         if (retain || !success) {
1803            /* make internal copy of the texture image */
1804            make_texture_image(ctx, 2, texImage, width, height, 1,
1805                               format, type, pixels, &ctx->Unpack);
1806            if (!success && ctx->Driver.TexImage2D) {
1807               /* let device driver try to use unpacked image */
1808               (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1809                                          GL_UNSIGNED_BYTE, texImage->Data,
1810                                          &_mesa_native_packing,
1811                                          texObj, texImage, &retain);
1812            }
1813         }
1814         if (!retain && texImage->Data) {
1815            FREE(texImage->Data);
1816            texImage->Data = NULL;
1817         }
1818      }
1819      else {
1820         make_null_texture(texImage);
1821         if (ctx->Driver.TexImage2D) {
1822            GLboolean retain;
1823            (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1824                                       GL_UNSIGNED_BYTE, texImage->Data,
1825                                       &_mesa_native_packing,
1826                                       texObj, texImage, &retain);
1827         }
1828      }
1829
1830#define OLD_DD_TEXTURE
1831#ifdef OLD_DD_TEXTURE
1832      /* XXX this will be removed in the future */
1833      if (ctx->Driver.TexImage) {
1834         (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1835                                  texImage );
1836      }
1837#endif
1838
1839      /* state update */
1840      gl_put_texobj_on_dirty_list( ctx, texObj );
1841      ctx->NewState |= NEW_TEXTURING;
1842   }
1843   else if (target==GL_PROXY_TEXTURE_2D) {
1844      /* Proxy texture: check for errors and update proxy state */
1845      if (texture_error_check(ctx, target, level, internalFormat,
1846                          format, type, 2, postConvWidth, height, 1, border)) {
1847         /* if error, clear all proxy texture image parameters */
1848         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1849            clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
1850         }
1851      }
1852      else {
1853         /* if no error, update proxy texture image parameters */
1854         init_texture_image(ctx,
1855                            ctx->Texture.Proxy2D->Image[level],
1856                            width, height, 1, border, internalFormat);
1857      }
1858   }
1859   else {
1860      gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1861      return;
1862   }
1863}
1864
1865
1866
1867/*
1868 * Called by the API or display list executor.
1869 * Note that width and height include the border.
1870 */
1871void
1872_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1873                  GLsizei width, GLsizei height, GLsizei depth,
1874                  GLint border, GLenum format, GLenum type,
1875                  const GLvoid *pixels )
1876{
1877   GET_CURRENT_CONTEXT(ctx);
1878   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1879
1880   if (target==GL_TEXTURE_3D_EXT) {
1881      struct gl_texture_unit *texUnit;
1882      struct gl_texture_object *texObj;
1883      struct gl_texture_image *texImage;
1884      GLint ifmt;
1885
1886      ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3);
1887      if (ifmt < 0) {
1888         /*
1889          * The error here is that we were sent a generic compressed
1890          * format, but the extension is not supported.
1891          */
1892         return;
1893      }
1894      else {
1895         internalFormat = ifmt;
1896      }
1897
1898      if (texture_error_check(ctx, target, level, internalFormat,
1899                              format, type, 3, width, height, depth, border)) {
1900         return;   /* error in texture image was detected */
1901      }
1902
1903      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1904      texObj = texUnit->CurrentD[3];
1905      texImage = texObj->Image[level];
1906
1907      if (!texImage) {
1908         texImage = _mesa_alloc_texture_image();
1909         texObj->Image[level] = texImage;
1910         if (!texImage) {
1911            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1912            return;
1913         }
1914      }
1915      else if (texImage->Data) {
1916         FREE(texImage->Data);
1917         texImage->Data = NULL;
1918      }
1919
1920      /* setup the teximage struct's fields */
1921      init_texture_image(ctx, texImage, width, height, depth,
1922                         border, internalFormat);
1923
1924      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1925         _mesa_update_image_transfer_state(ctx);
1926
1927      /* process the texture image */
1928      if (pixels) {
1929         GLboolean retain = GL_TRUE;
1930         GLboolean success = GL_FALSE;
1931         if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
1932            /* let device driver try to use raw image */
1933            success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1934                                                 type, pixels, &ctx->Unpack,
1935                                                 texObj, texImage, &retain);
1936         }
1937         if (retain || !success) {
1938            /* make internal copy of the texture image */
1939            make_texture_image(ctx, 3, texImage, width, height, depth,
1940                               format, type, pixels, &ctx->Unpack);
1941            if (!success && ctx->Driver.TexImage3D) {
1942               /* let device driver try to use unpacked image */
1943               (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1944                                          GL_UNSIGNED_BYTE, texImage->Data,
1945                                          &_mesa_native_packing,
1946                                          texObj, texImage, &retain);
1947            }
1948         }
1949         if (!retain && texImage->Data) {
1950            FREE(texImage->Data);
1951            texImage->Data = NULL;
1952         }
1953      }
1954      else {
1955         make_null_texture(texImage);
1956         if (ctx->Driver.TexImage3D) {
1957            GLboolean retain;
1958            (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1959                                       GL_UNSIGNED_BYTE, texImage->Data,
1960                                       &_mesa_native_packing,
1961                                       texObj, texImage, &retain);
1962         }
1963      }
1964
1965      /* state update */
1966      gl_put_texobj_on_dirty_list( ctx, texObj );
1967      ctx->NewState |= NEW_TEXTURING;
1968   }
1969   else if (target==GL_PROXY_TEXTURE_3D) {
1970      /* Proxy texture: check for errors and update proxy state */
1971      if (texture_error_check(ctx, target, level, internalFormat,
1972                              format, type, 3, width, height, depth, border)) {
1973         /* if error, clear all proxy texture image parameters */
1974         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1975            clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
1976         }
1977      }
1978      else {
1979         /* if no error, update proxy texture image parameters */
1980         init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
1981                            width, height, depth, border, internalFormat);
1982      }
1983   }
1984   else {
1985      gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1986      return;
1987   }
1988}
1989
1990
1991void
1992_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1993                     GLsizei width, GLsizei height, GLsizei depth,
1994                     GLint border, GLenum format, GLenum type,
1995                     const GLvoid *pixels )
1996{
1997   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1998                    depth, border, format, type, pixels);
1999}
2000
2001
2002/*
2003 * Fetch a texture image from the device driver.
2004 * Store the results in the given texture object at the given mipmap level.
2005 */
2006void
2007_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2008                                const struct gl_texture_object *texObj )
2009{
2010   GLvoid *image;
2011   GLenum imgFormat, imgType;
2012   GLboolean freeImage;
2013   struct gl_texture_image *texImage;
2014   GLint destComponents, numPixels, srcBytesPerTexel;
2015
2016   if (!ctx->Driver.GetTexImage)
2017      return;
2018
2019   image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
2020                                       &imgFormat, &imgType, &freeImage);
2021   if (!image)
2022      return;
2023
2024   texImage = texObj->Image[level];
2025   ASSERT(texImage);
2026   if (!texImage)
2027      return;
2028
2029   destComponents = components_in_intformat(texImage->Format);
2030   assert(destComponents > 0);
2031   numPixels = texImage->Width * texImage->Height * texImage->Depth;
2032   assert(numPixels > 0);
2033   srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
2034   assert(srcBytesPerTexel > 0);
2035
2036   if (!texImage->Data) {
2037      /* Allocate memory for the texture image data */
2038      texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
2039   }
2040
2041   if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2042      /* We got lucky!  The driver's format and type match Mesa's format. */
2043      if (texImage->Data) {
2044         MEMCPY(texImage->Data, image, numPixels * destComponents);
2045      }
2046   }
2047   else {
2048      /* Convert the texture image from the driver's format to Mesa's
2049       * internal format.
2050       */
2051      const GLint width = texImage->Width;
2052      const GLint height = texImage->Height;
2053      const GLint depth = texImage->Depth;
2054      const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2055      const GLint srcBytesPerRow = width * srcBytesPerTexel;
2056      const GLenum dstType = GL_UNSIGNED_BYTE;
2057      const GLenum dstFormat = texImage->Format;
2058      const GLubyte *srcPtr = (const GLubyte *) image;
2059      GLubyte *destPtr = texImage->Data;
2060
2061      if (texImage->Format == GL_COLOR_INDEX) {
2062         /* color index texture */
2063         GLint img, row;
2064         assert(imgFormat == GL_COLOR_INDEX);
2065         for (img = 0; img < depth; img++) {
2066            for (row = 0; row < height; row++) {
2067               _mesa_unpack_index_span(ctx, width, dstType, destPtr,
2068                             imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2069               destPtr += destBytesPerRow;
2070               srcPtr += srcBytesPerRow;
2071            }
2072         }
2073      }
2074      else {
2075         /* color texture */
2076         GLint img, row;
2077         for (img = 0; img < depth; img++) {
2078            for (row = 0; row < height; row++) {
2079               _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
2080                  imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2081               destPtr += destBytesPerRow;
2082               srcPtr += srcBytesPerRow;
2083            }
2084         }
2085      }
2086   }
2087
2088   if (freeImage)
2089      FREE(image);
2090}
2091
2092
2093void
2094_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2095                   GLenum type, GLvoid *pixels )
2096{
2097   GET_CURRENT_CONTEXT(ctx);
2098   const struct gl_texture_unit *texUnit;
2099   const struct gl_texture_object *texObj;
2100   struct gl_texture_image *texImage;
2101   GLboolean discardImage;
2102
2103   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2104
2105   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2106      gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2107      return;
2108   }
2109
2110   if (_mesa_sizeof_type(type) <= 0) {
2111      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2112      return;
2113   }
2114
2115   if (_mesa_components_in_format(format) <= 0) {
2116      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2117      return;
2118   }
2119
2120   if (!pixels)
2121      return;
2122
2123   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2124   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2125   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2126   if (!texObj || !texImage ||
2127       target == GL_PROXY_TEXTURE_1D ||
2128       target == GL_PROXY_TEXTURE_2D ||
2129       target == GL_PROXY_TEXTURE_3D) {
2130      gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2131      return;
2132   }
2133
2134   if (!texImage) {
2135      /* invalid mipmap level */
2136      return;
2137   }
2138
2139   if (!texImage->Data) {
2140      /* try to get the texture image from the device driver */
2141      _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2142      discardImage = GL_TRUE;
2143   }
2144   else {
2145      discardImage = GL_FALSE;
2146   }
2147
2148   if (texImage->Data) {
2149      GLint width = texImage->Width;
2150      GLint height = texImage->Height;
2151      GLint row;
2152
2153      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2154         _mesa_update_image_transfer_state(ctx);
2155
2156      for (row = 0; row < height; row++) {
2157         /* compute destination address in client memory */
2158         GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2159                                                width, height,
2160                                                format, type, 0, row, 0);
2161
2162         assert(dest);
2163         if (texImage->Format == GL_RGBA) {
2164            const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
2165            /* XXX convolution */
2166            _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
2167                                  format, type, dest, &ctx->Pack,
2168                                  ctx->ImageTransferState );
2169         }
2170         else {
2171            /* fetch RGBA row from texture image then pack it in client mem */
2172            GLubyte rgba[MAX_WIDTH][4];
2173            GLint i;
2174            const GLubyte *src;
2175            switch (texImage->Format) {
2176               case GL_ALPHA:
2177                  src = texImage->Data + row * width * sizeof(GLubyte);
2178                  for (i = 0; i < width; i++) {
2179                     rgba[i][RCOMP] = 255;
2180                     rgba[i][GCOMP] = 255;
2181                     rgba[i][BCOMP] = 255;
2182                     rgba[i][ACOMP] = src[i];
2183                  }
2184                  break;
2185               case GL_LUMINANCE:
2186                  src = texImage->Data + row * width * sizeof(GLubyte);
2187                  for (i = 0; i < width; i++) {
2188                     rgba[i][RCOMP] = src[i];
2189                     rgba[i][GCOMP] = src[i];
2190                     rgba[i][BCOMP] = src[i];
2191                     rgba[i][ACOMP] = 255;
2192                   }
2193                  break;
2194               case GL_LUMINANCE_ALPHA:
2195                  src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2196                  for (i = 0; i < width; i++) {
2197                     rgba[i][RCOMP] = src[i*2+0];
2198                     rgba[i][GCOMP] = src[i*2+0];
2199                     rgba[i][BCOMP] = src[i*2+0];
2200                     rgba[i][ACOMP] = src[i*2+1];
2201                  }
2202                  break;
2203               case GL_INTENSITY:
2204                  src = texImage->Data + row * width * sizeof(GLubyte);
2205                  for (i = 0; i < width; i++) {
2206                     rgba[i][RCOMP] = src[i];
2207                     rgba[i][GCOMP] = src[i];
2208                     rgba[i][BCOMP] = src[i];
2209                     rgba[i][ACOMP] = 255;
2210                  }
2211                  break;
2212               case GL_RGB:
2213                  src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2214                  for (i = 0; i < width; i++) {
2215                     rgba[i][RCOMP] = src[i*3+0];
2216                     rgba[i][GCOMP] = src[i*3+1];
2217                     rgba[i][BCOMP] = src[i*3+2];
2218                     rgba[i][ACOMP] = 255;
2219                  }
2220                  break;
2221               case GL_RGBA:
2222                  /* this special case should have been handled above! */
2223                  gl_problem( ctx, "error 1 in gl_GetTexImage" );
2224                  break;
2225               case GL_COLOR_INDEX:
2226                  gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2227                  break;
2228               default:
2229                  gl_problem( ctx, "bad format in gl_GetTexImage" );
2230            }
2231            /* XXX convolution */
2232            _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
2233                                  format, type, dest, &ctx->Pack,
2234                                  ctx->ImageTransferState );
2235         }
2236      }
2237
2238      /* if we got the teximage from the device driver we'll discard it now */
2239      if (discardImage) {
2240         FREE(texImage->Data);
2241         texImage->Data = NULL;
2242      }
2243   }
2244}
2245
2246
2247
2248void
2249_mesa_TexSubImage1D( GLenum target, GLint level,
2250                     GLint xoffset, GLsizei width,
2251                     GLenum format, GLenum type,
2252                     const GLvoid *pixels )
2253{
2254   GET_CURRENT_CONTEXT(ctx);
2255   struct gl_texture_unit *texUnit;
2256   struct gl_texture_object *texObj;
2257   struct gl_texture_image *texImage;
2258   GLboolean success = GL_FALSE;
2259   GLsizei postConvWidth;
2260
2261   postConvWidth = width;
2262   adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2263
2264   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2265                              postConvWidth, 1, 1, format, type)) {
2266      return;   /* error was detected */
2267   }
2268
2269   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2270   texObj = texUnit->CurrentD[1];
2271   texImage = texObj->Image[level];
2272   assert(texImage);
2273
2274   if (width == 0 || !pixels)
2275      return;  /* no-op, not an error */
2276
2277   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2278      _mesa_update_image_transfer_state(ctx);
2279
2280   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
2281      success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2282                                              width, format, type, pixels,
2283                                              &ctx->Unpack, texObj, texImage );
2284   }
2285   if (!success) {
2286      /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2287      GLboolean retain = GL_TRUE;
2288      if (!texImage->Data) {
2289         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2290         if (!texImage->Data) {
2291            make_null_texture(texImage);
2292         }
2293         if (!texImage->Data)
2294            return;  /* we're really out of luck! */
2295      }
2296
2297      fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2298                         width, 1, 1, xoffset, 0, 0, /* size and offsets */
2299                         0, 0, /* strides */
2300                         format, type, pixels, &ctx->Unpack);
2301
2302      if (ctx->Driver.TexImage1D) {
2303         (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2304                                    GL_UNSIGNED_BYTE, texImage->Data,
2305                                    &_mesa_native_packing, texObj, texImage,
2306                                    &retain );
2307      }
2308
2309      if (!retain && texImage->Data) {
2310         FREE(texImage->Data);
2311         texImage->Data = NULL;
2312      }
2313   }
2314}
2315
2316
2317void
2318_mesa_TexSubImage2D( GLenum target, GLint level,
2319                     GLint xoffset, GLint yoffset,
2320                     GLsizei width, GLsizei height,
2321                     GLenum format, GLenum type,
2322                     const GLvoid *pixels )
2323{
2324   GET_CURRENT_CONTEXT(ctx);
2325   struct gl_texture_unit *texUnit;
2326   struct gl_texture_object *texObj;
2327   struct gl_texture_image *texImage;
2328   GLboolean success = GL_FALSE;
2329   GLsizei postConvWidth, postConvHeight;
2330
2331   postConvWidth = width;
2332   postConvHeight = height;
2333   adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2334
2335   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2336                             postConvWidth, postConvHeight, 1, format, type)) {
2337      return;   /* error was detected */
2338   }
2339
2340   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2341   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2342   texImage = texObj->Image[level];
2343   assert(texImage);
2344
2345   if (width == 0 || height == 0 || !pixels)
2346      return;  /* no-op, not an error */
2347
2348   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2349      _mesa_update_image_transfer_state(ctx);
2350
2351   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
2352      success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2353                                     yoffset, width, height, format, type,
2354                                     pixels, &ctx->Unpack, texObj, texImage );
2355   }
2356   if (!success) {
2357      /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2358      const GLint texComps = components_in_intformat(texImage->Format);
2359      const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2360      GLboolean retain = GL_TRUE;
2361
2362      if (!texImage->Data) {
2363         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2364         if (!texImage->Data) {
2365            make_null_texture(texImage);
2366         }
2367         if (!texImage->Data)
2368            return;  /* we're really out of luck! */
2369      }
2370
2371      fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2372                         width, height, 1, xoffset, yoffset, 0,
2373                         texRowStride, 0,
2374                         format, type, pixels, &ctx->Unpack);
2375
2376      if (ctx->Driver.TexImage2D) {
2377         (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2378                                   GL_UNSIGNED_BYTE, texImage->Data,
2379                                   &_mesa_native_packing, texObj, texImage,
2380                                   &retain);
2381      }
2382
2383      if (!retain && texImage->Data) {
2384         FREE(texImage->Data);
2385         texImage->Data = NULL;
2386      }
2387
2388#ifdef OLD_DD_TEXTURE
2389      /* XXX this will be removed in the future */
2390      if (ctx->Driver.TexSubImage) {
2391         (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2392                                    xoffset, yoffset, width, height,
2393                                    texImage->IntFormat, texImage);
2394      }
2395      else if (ctx->Driver.TexImage) {
2396         (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2397                                 level, texImage->IntFormat, texImage );
2398      }
2399#endif
2400   }
2401}
2402
2403
2404
2405void
2406_mesa_TexSubImage3D( GLenum target, GLint level,
2407                     GLint xoffset, GLint yoffset, GLint zoffset,
2408                     GLsizei width, GLsizei height, GLsizei depth,
2409                     GLenum format, GLenum type,
2410                     const GLvoid *pixels )
2411{
2412   GET_CURRENT_CONTEXT(ctx);
2413   struct gl_texture_unit *texUnit;
2414   struct gl_texture_object *texObj;
2415   struct gl_texture_image *texImage;
2416   GLboolean success = GL_FALSE;
2417
2418   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2419                              width, height, depth, format, type)) {
2420      return;   /* error was detected */
2421   }
2422
2423   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2424   texObj = texUnit->CurrentD[3];
2425   texImage = texObj->Image[level];
2426   assert(texImage);
2427
2428   if (width == 0 || height == 0 || height == 0 || !pixels)
2429      return;  /* no-op, not an error */
2430
2431   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2432      _mesa_update_image_transfer_state(ctx);
2433
2434   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
2435      success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2436                                yoffset, zoffset, width, height, depth, format,
2437                                type, pixels, &ctx->Unpack, texObj, texImage );
2438   }
2439   if (!success) {
2440      /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2441      const GLint texComps = components_in_intformat(texImage->Format);
2442      const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2443      const GLint texImgStride = texRowStride * texImage->Height;
2444      GLboolean retain = GL_TRUE;
2445
2446      if (!texImage->Data) {
2447         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2448         if (!texImage->Data) {
2449            make_null_texture(texImage);
2450         }
2451         if (!texImage->Data)
2452            return;  /* we're really out of luck! */
2453      }
2454
2455      fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2456                         width, height, depth, xoffset, yoffset, zoffset,
2457                         texRowStride, texImgStride,
2458                         format, type, pixels, &ctx->Unpack);
2459
2460      if (ctx->Driver.TexImage3D) {
2461         (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2462                                   GL_UNSIGNED_BYTE, texImage->Data,
2463                                   &_mesa_native_packing, texObj, texImage,
2464                                   &retain);
2465      }
2466
2467      if (!retain && texImage->Data) {
2468         FREE(texImage->Data);
2469         texImage->Data = NULL;
2470      }
2471   }
2472}
2473
2474
2475
2476/*
2477 * Read an RGBA image from the frame buffer.
2478 * This is used by glCopyTex[Sub]Image[12]D().
2479 * Input:  ctx - the context
2480 *         x, y - lower left corner
2481 *         width, height - size of region to read
2482 * Return: pointer to block of GL_RGBA, GLubyte data.
2483 */
2484static GLubyte *
2485read_color_image( GLcontext *ctx, GLint x, GLint y,
2486                  GLsizei width, GLsizei height )
2487{
2488   GLint stride, i;
2489   GLubyte *image, *dst;
2490
2491   image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
2492   if (!image)
2493      return NULL;
2494
2495   /* Select buffer to read from */
2496   (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2497                                 ctx->Pixel.DriverReadBuffer );
2498
2499   dst = image;
2500   stride = width * 4 * sizeof(GLubyte);
2501   for (i = 0; i < height; i++) {
2502      gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2503                         (GLubyte (*)[4]) dst );
2504      dst += stride;
2505   }
2506
2507   /* Read from draw buffer (the default) */
2508   (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2509                                 ctx->Color.DriverDrawBuffer );
2510
2511   return image;
2512}
2513
2514
2515
2516void
2517_mesa_CopyTexImage1D( GLenum target, GLint level,
2518                      GLenum internalFormat,
2519                      GLint x, GLint y,
2520                      GLsizei width, GLint border )
2521{
2522   GET_CURRENT_CONTEXT(ctx);
2523   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2524
2525   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2526                               width, 1, border))
2527      return;
2528
2529   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2530      _mesa_update_image_transfer_state(ctx);
2531
2532   if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
2533       || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2534                         internalFormat, x, y, width, border)) {
2535      struct gl_pixelstore_attrib unpackSave;
2536
2537      /* get image from framebuffer */
2538      GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2539      if (!image) {
2540         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2541         return;
2542      }
2543
2544      /* call glTexImage1D to redefine the texture */
2545      unpackSave = ctx->Unpack;
2546      ctx->Unpack = _mesa_native_packing;
2547      (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2548                                border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2549      ctx->Unpack = unpackSave;
2550
2551      FREE(image);
2552   }
2553}
2554
2555
2556
2557void
2558_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2559                      GLint x, GLint y, GLsizei width, GLsizei height,
2560                      GLint border )
2561{
2562   GET_CURRENT_CONTEXT(ctx);
2563   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2564
2565   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2566                               width, height, border))
2567      return;
2568
2569   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2570      _mesa_update_image_transfer_state(ctx);
2571
2572   if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
2573       || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2574                         internalFormat, x, y, width, height, border)) {
2575      struct gl_pixelstore_attrib unpackSave;
2576
2577      /* get image from framebuffer */
2578      GLubyte *image = read_color_image( ctx, x, y, width, height );
2579      if (!image) {
2580         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2581         return;
2582      }
2583
2584      /* call glTexImage2D to redefine the texture */
2585      unpackSave = ctx->Unpack;
2586      ctx->Unpack = _mesa_native_packing;
2587      (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2588                      height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2589      ctx->Unpack = unpackSave;
2590
2591      FREE(image);
2592   }
2593}
2594
2595
2596
2597void
2598_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2599                         GLint xoffset, GLint x, GLint y, GLsizei width )
2600{
2601   GET_CURRENT_CONTEXT(ctx);
2602   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2603
2604   if (copytexsubimage_error_check(ctx, 1, target, level,
2605                                   xoffset, 0, 0, width, 1))
2606      return;
2607
2608   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2609      _mesa_update_image_transfer_state(ctx);
2610
2611   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2612       || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2613                                            xoffset, x, y, width)) {
2614      struct gl_texture_unit *texUnit;
2615      struct gl_texture_image *teximage;
2616      struct gl_pixelstore_attrib unpackSave;
2617      GLubyte *image;
2618
2619      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2620      teximage = texUnit->CurrentD[1]->Image[level];
2621      assert(teximage);
2622
2623      /* get image from frame buffer */
2624      image = read_color_image(ctx, x, y, width, 1);
2625      if (!image) {
2626         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2627         return;
2628      }
2629
2630      /* now call glTexSubImage1D to do the real work */
2631      unpackSave = ctx->Unpack;
2632      ctx->Unpack = _mesa_native_packing;
2633      _mesa_TexSubImage1D(target, level, xoffset, width,
2634                          GL_RGBA, GL_UNSIGNED_BYTE, image);
2635      ctx->Unpack = unpackSave;
2636
2637      FREE(image);
2638   }
2639}
2640
2641
2642
2643void
2644_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2645                         GLint xoffset, GLint yoffset,
2646                         GLint x, GLint y, GLsizei width, GLsizei height )
2647{
2648   GET_CURRENT_CONTEXT(ctx);
2649   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2650
2651   if (copytexsubimage_error_check(ctx, 2, target, level,
2652                                   xoffset, yoffset, 0, width, height))
2653      return;
2654
2655   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2656      _mesa_update_image_transfer_state(ctx);
2657
2658   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2659       || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2660                                xoffset, yoffset, x, y, width, height )) {
2661      struct gl_texture_unit *texUnit;
2662      struct gl_texture_image *teximage;
2663      struct gl_pixelstore_attrib unpackSave;
2664      GLubyte *image;
2665
2666      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2667      teximage = texUnit->CurrentD[2]->Image[level];
2668      assert(teximage);
2669
2670      /* get image from frame buffer */
2671      image = read_color_image(ctx, x, y, width, height);
2672      if (!image) {
2673         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2674         return;
2675      }
2676
2677      /* now call glTexSubImage2D to do the real work */
2678      unpackSave = ctx->Unpack;
2679      ctx->Unpack = _mesa_native_packing;
2680      _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2681                          GL_RGBA, GL_UNSIGNED_BYTE, image);
2682      ctx->Unpack = unpackSave;
2683
2684      FREE(image);
2685   }
2686}
2687
2688
2689
2690void
2691_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2692                         GLint xoffset, GLint yoffset, GLint zoffset,
2693                         GLint x, GLint y, GLsizei width, GLsizei height )
2694{
2695   GET_CURRENT_CONTEXT(ctx);
2696   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2697
2698   if (copytexsubimage_error_check(ctx, 3, target, level,
2699                    xoffset, yoffset, zoffset, width, height))
2700      return;
2701
2702   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2703      _mesa_update_image_transfer_state(ctx);
2704
2705   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2706       || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2707                     xoffset, yoffset, zoffset, x, y, width, height )) {
2708      struct gl_texture_unit *texUnit;
2709      struct gl_texture_image *teximage;
2710      struct gl_pixelstore_attrib unpackSave;
2711      GLubyte *image;
2712
2713      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2714      teximage = texUnit->CurrentD[3]->Image[level];
2715      assert(teximage);
2716
2717      /* get image from frame buffer */
2718      image = read_color_image(ctx, x, y, width, height);
2719      if (!image) {
2720         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2721         return;
2722      }
2723
2724      /* now call glTexSubImage2D to do the real work */
2725      unpackSave = ctx->Unpack;
2726      ctx->Unpack = _mesa_native_packing;
2727      _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2728                          width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2729      ctx->Unpack = unpackSave;
2730
2731      FREE(image);
2732   }
2733}
2734
2735
2736
2737void
2738_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2739                              GLenum internalFormat, GLsizei width,
2740                              GLint border, GLsizei imageSize,
2741                              const GLvoid *data)
2742{
2743   GET_CURRENT_CONTEXT(ctx);
2744   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2745
2746   switch (internalFormat) {
2747      case GL_COMPRESSED_ALPHA_ARB:
2748      case GL_COMPRESSED_LUMINANCE_ARB:
2749      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2750      case GL_COMPRESSED_INTENSITY_ARB:
2751      case GL_COMPRESSED_RGB_ARB:
2752      case GL_COMPRESSED_RGBA_ARB:
2753         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2754         return;
2755      default:
2756         /* silence compiler warning */
2757         ;
2758   }
2759
2760   if (target == GL_TEXTURE_1D) {
2761      struct gl_texture_unit *texUnit;
2762      struct gl_texture_object *texObj;
2763      struct gl_texture_image *texImage;
2764      GLsizei computedImageSize;
2765
2766      if (texture_error_check(ctx, target, level, internalFormat,
2767                              GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2768         return;   /* error in texture image was detected */
2769      }
2770
2771      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2772      texObj = texUnit->CurrentD[1];
2773      texImage = texObj->Image[level];
2774
2775      if (!texImage) {
2776         texImage = _mesa_alloc_texture_image();
2777         texObj->Image[level] = texImage;
2778         if (!texImage) {
2779            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2780            return;
2781         }
2782      }
2783      else if (texImage->Data) {
2784         FREE(texImage->Data);
2785         texImage->Data = NULL;
2786      }
2787
2788      /* setup the teximage struct's fields */
2789      init_texture_image(ctx, texImage, width, 1, 1,
2790                         border, internalFormat);
2791
2792      /* process the texture image */
2793      if (data) {
2794         GLboolean retain = GL_TRUE;
2795         GLboolean success = GL_FALSE;
2796         if (ctx->Driver.CompressedTexImage1D) {
2797            success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2798                               imageSize, data, texObj, texImage, &retain);
2799         }
2800         if (retain || !success) {
2801            /* make internal copy of the texture image */
2802            computedImageSize = _mesa_compressed_image_size(ctx,
2803                                                        internalFormat,
2804                                                        1,    /* num dims */
2805                                                        width,
2806                                                        1,    /* height   */
2807                                                        1);   /* depth    */
2808            if (computedImageSize != imageSize) {
2809                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2810                return;
2811            }
2812            texImage->Data = MALLOC(computedImageSize);
2813            if (texImage->Data) {
2814               MEMCPY(texImage->Data, data, computedImageSize);
2815            }
2816         }
2817         if (!retain && texImage->Data) {
2818            FREE(texImage->Data);
2819            texImage->Data = NULL;
2820         }
2821      }
2822      else {
2823         make_null_texture(texImage);
2824         if (ctx->Driver.CompressedTexImage1D) {
2825            GLboolean retain;
2826            (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2827                                                texImage->Data, texObj,
2828                                                texImage, &retain);
2829         }
2830      }
2831
2832      /* state update */
2833      gl_put_texobj_on_dirty_list( ctx, texObj );
2834      ctx->NewState |= NEW_TEXTURING;
2835   }
2836   else if (target == GL_PROXY_TEXTURE_1D) {
2837      /* Proxy texture: check for errors and update proxy state */
2838      if (texture_error_check(ctx, target, level, internalFormat,
2839                              GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2840         /* if error, clear all proxy texture image parameters */
2841         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2842            clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
2843         }
2844      }
2845      else {
2846         /* if no error, update proxy texture image parameters */
2847         init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
2848                            width, 1, 1, border, internalFormat);
2849      }
2850   }
2851   else {
2852      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2853      return;
2854   }
2855}
2856
2857
2858void
2859_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2860                              GLenum internalFormat, GLsizei width,
2861                              GLsizei height, GLint border, GLsizei imageSize,
2862                              const GLvoid *data)
2863{
2864   GET_CURRENT_CONTEXT(ctx);
2865   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2866
2867   switch (internalFormat) {
2868      case GL_COMPRESSED_ALPHA_ARB:
2869      case GL_COMPRESSED_LUMINANCE_ARB:
2870      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2871      case GL_COMPRESSED_INTENSITY_ARB:
2872      case GL_COMPRESSED_RGB_ARB:
2873      case GL_COMPRESSED_RGBA_ARB:
2874         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2875         return;
2876      default:
2877         /* silence compiler warning */
2878         ;
2879   }
2880
2881   if (target==GL_TEXTURE_2D ||
2882       (ctx->Extensions.HaveTextureCubeMap &&
2883        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2884        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2885      struct gl_texture_unit *texUnit;
2886      struct gl_texture_object *texObj;
2887      struct gl_texture_image *texImage;
2888      GLsizei computedImageSize;
2889
2890      if (texture_error_check(ctx, target, level, internalFormat,
2891                              GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2892         return;   /* error in texture image was detected */
2893      }
2894
2895      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2896      texObj = texUnit->CurrentD[2];
2897      texImage = texObj->Image[level];
2898
2899      if (!texImage) {
2900         texImage = _mesa_alloc_texture_image();
2901         texObj->Image[level] = texImage;
2902         if (!texImage) {
2903            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2904            return;
2905         }
2906      }
2907      else if (texImage->Data) {
2908         FREE(texImage->Data);
2909         texImage->Data = NULL;
2910      }
2911
2912      /* setup the teximage struct's fields */
2913      init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
2914
2915      /* process the texture image */
2916      if (data) {
2917         GLboolean retain = GL_TRUE;
2918         GLboolean success = GL_FALSE;
2919         if (ctx->Driver.CompressedTexImage2D) {
2920            success = (*ctx->Driver.CompressedTexImage2D)( ctx,
2921                                                           target,
2922                                                           level,
2923                                                           imageSize,
2924                                                           data,
2925                                                           texObj,
2926                                                           texImage,
2927                                                           &retain);
2928         }
2929         if (retain || !success) {
2930            /* make internal copy of the texture image */
2931            computedImageSize = _mesa_compressed_image_size(ctx,
2932                                                           internalFormat,
2933                                                           2,    /* num dims */
2934                                                           width,
2935                                                           height,
2936                                                           1);   /* depth    */
2937            if (computedImageSize != imageSize) {
2938                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
2939                return;
2940            }
2941            texImage->Data = MALLOC(computedImageSize);
2942            if (texImage->Data) {
2943               MEMCPY(texImage->Data, data, computedImageSize);
2944            }
2945         }
2946         if (!retain && texImage->Data) {
2947            FREE(texImage->Data);
2948            texImage->Data = NULL;
2949         }
2950      }
2951      else {
2952         make_null_texture(texImage);
2953         if (ctx->Driver.CompressedTexImage2D) {
2954            GLboolean retain;
2955            (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
2956                                                 texImage->Data, texObj,
2957                                                 texImage, &retain);
2958         }
2959      }
2960
2961      /* state update */
2962      gl_put_texobj_on_dirty_list( ctx, texObj );
2963      ctx->NewState |= NEW_TEXTURING;
2964   }
2965   else if (target == GL_PROXY_TEXTURE_2D) {
2966      /* Proxy texture: check for errors and update proxy state */
2967      if (texture_error_check(ctx, target, level, internalFormat,
2968                              GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2969         /* if error, clear all proxy texture image parameters */
2970         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2971            clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
2972         }
2973      }
2974      else {
2975         /* if no error, update proxy texture image parameters */
2976         init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
2977                            width, 1, 1, border, internalFormat);
2978      }
2979   }
2980   else {
2981      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
2982      return;
2983   }
2984}
2985
2986
2987void
2988_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2989                              GLenum internalFormat, GLsizei width,
2990                              GLsizei height, GLsizei depth, GLint border,
2991                              GLsizei imageSize, const GLvoid *data)
2992{
2993   GET_CURRENT_CONTEXT(ctx);
2994   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
2995
2996   switch (internalFormat) {
2997      case GL_COMPRESSED_ALPHA_ARB:
2998      case GL_COMPRESSED_LUMINANCE_ARB:
2999      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3000      case GL_COMPRESSED_INTENSITY_ARB:
3001      case GL_COMPRESSED_RGB_ARB:
3002      case GL_COMPRESSED_RGBA_ARB:
3003         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3004         return;
3005      default:
3006         /* silence compiler warning */
3007         ;
3008   }
3009
3010   if (target == GL_TEXTURE_3D) {
3011      struct gl_texture_unit *texUnit;
3012      struct gl_texture_object *texObj;
3013      struct gl_texture_image *texImage;
3014      GLsizei computedImageSize;
3015
3016      if (texture_error_check(ctx, target, level, internalFormat,
3017                          GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3018         return;   /* error in texture image was detected */
3019      }
3020
3021      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3022      texObj = texUnit->CurrentD[3];
3023      texImage = texObj->Image[level];
3024
3025      if (!texImage) {
3026         texImage = _mesa_alloc_texture_image();
3027         texObj->Image[level] = texImage;
3028         if (!texImage) {
3029            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3030            return;
3031         }
3032      }
3033      else if (texImage->Data) {
3034         FREE(texImage->Data);
3035         texImage->Data = NULL;
3036      }
3037
3038      /* setup the teximage struct's fields */
3039      init_texture_image(ctx, texImage, width, height, depth,
3040                         border, internalFormat);
3041
3042      /* process the texture image */
3043      if (data) {
3044         GLboolean retain = GL_TRUE;
3045         GLboolean success = GL_FALSE;
3046         if (ctx->Driver.CompressedTexImage3D) {
3047            success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3048                                                          imageSize, data,
3049                                                          texObj, texImage,
3050                                                          &retain);
3051         }
3052         if (retain || !success) {
3053            /* make internal copy of the texture image */
3054            computedImageSize = _mesa_compressed_image_size(ctx,
3055                                                            internalFormat,
3056                                                            3,  /* num dims */
3057                                                            width,
3058                                                            height,
3059                                                            depth);
3060            if (computedImageSize != imageSize) {
3061                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3062                return;
3063            }
3064            texImage->Data = MALLOC(computedImageSize);
3065            if (texImage->Data) {
3066               MEMCPY(texImage->Data, data, computedImageSize);
3067            }
3068         }
3069         if (!retain && texImage->Data) {
3070            FREE(texImage->Data);
3071            texImage->Data = NULL;
3072         }
3073      }
3074      else {
3075         make_null_texture(texImage);
3076         if (ctx->Driver.CompressedTexImage3D) {
3077            GLboolean retain;
3078            (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3079                                                 texImage->Data, texObj,
3080                                                 texImage, &retain);
3081         }
3082      }
3083
3084      /* state update */
3085      gl_put_texobj_on_dirty_list( ctx, texObj );
3086      ctx->NewState |= NEW_TEXTURING;
3087   }
3088   else if (target == GL_PROXY_TEXTURE_3D) {
3089      /* Proxy texture: check for errors and update proxy state */
3090      if (texture_error_check(ctx, target, level, internalFormat,
3091                          GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3092         /* if error, clear all proxy texture image parameters */
3093         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3094            clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
3095         }
3096      }
3097      else {
3098         /* if no error, update proxy texture image parameters */
3099         init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3100                            width, 1, 1, border, internalFormat);
3101      }
3102   }
3103   else {
3104      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3105      return;
3106   }
3107}
3108
3109
3110void
3111_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3112                                 GLsizei width, GLenum format,
3113                                 GLsizei imageSize, const GLvoid *data)
3114{
3115   GET_CURRENT_CONTEXT(ctx);
3116   struct gl_texture_unit *texUnit;
3117   struct gl_texture_object *texObj;
3118   struct gl_texture_image *texImage;
3119   GLboolean success = GL_FALSE;
3120
3121   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3122                              width, 1, 1, format, GL_NONE)) {
3123      return;   /* error was detected */
3124   }
3125
3126   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3127   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3128   texImage = texObj->Image[level];
3129   assert(texImage);
3130
3131   if (width == 0 || !data)
3132      return;  /* no-op, not an error */
3133
3134   if (ctx->Driver.CompressedTexSubImage1D) {
3135      success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3136                   xoffset, width, format, imageSize, data, texObj, texImage);
3137   }
3138   if (!success) {
3139      /* XXX what else can we do? */
3140      gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3141      return;
3142   }
3143}
3144
3145
3146void
3147_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3148                                 GLint yoffset, GLsizei width, GLsizei height,
3149                                 GLenum format, GLsizei imageSize,
3150                                 const GLvoid *data)
3151{
3152   GET_CURRENT_CONTEXT(ctx);
3153   struct gl_texture_unit *texUnit;
3154   struct gl_texture_object *texObj;
3155   struct gl_texture_image *texImage;
3156   GLboolean success = GL_FALSE;
3157
3158   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3159                              width, height, 1, format, GL_NONE)) {
3160      return;   /* error was detected */
3161   }
3162
3163   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3164   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3165   texImage = texObj->Image[level];
3166   assert(texImage);
3167
3168   if (width == 0 || height == 0 || !data)
3169      return;  /* no-op, not an error */
3170
3171   if (ctx->Driver.CompressedTexSubImage2D) {
3172      success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3173                                       xoffset, yoffset, width, height, format,
3174                                       imageSize, data, texObj, texImage);
3175   }
3176   if (!success) {
3177      /* XXX what else can we do? */
3178      gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3179      return;
3180   }
3181}
3182
3183
3184void
3185_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3186                                 GLint yoffset, GLint zoffset, GLsizei width,
3187                                 GLsizei height, GLsizei depth, GLenum format,
3188                                 GLsizei imageSize, const GLvoid *data)
3189{
3190   GET_CURRENT_CONTEXT(ctx);
3191   struct gl_texture_unit *texUnit;
3192   struct gl_texture_object *texObj;
3193   struct gl_texture_image *texImage;
3194   GLboolean success = GL_FALSE;
3195
3196   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3197                              width, height, depth, format, GL_NONE)) {
3198      return;   /* error was detected */
3199   }
3200
3201   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3202   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3203   texImage = texObj->Image[level];
3204   assert(texImage);
3205
3206   if (width == 0 || height == 0 || depth == 0 || !data)
3207      return;  /* no-op, not an error */
3208
3209   if (ctx->Driver.CompressedTexSubImage3D) {
3210      success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3211                               xoffset, yoffset, zoffset, width, height, depth,
3212                               format, imageSize, data, texObj, texImage);
3213   }
3214   if (!success) {
3215      /* XXX what else can we do? */
3216      gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3217      return;
3218   }
3219}
3220
3221
3222void
3223_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3224{
3225   GET_CURRENT_CONTEXT(ctx);
3226   const struct gl_texture_object *texObj;
3227   struct gl_texture_image *texImage;
3228
3229   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3230
3231   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3232      gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3233      return;
3234   }
3235
3236   switch (target) {
3237      case GL_TEXTURE_1D:
3238         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3239         texImage = texObj->Image[level];
3240         break;
3241      case GL_TEXTURE_2D:
3242         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3243         texImage = texObj->Image[level];
3244         break;
3245      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3246         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3247         texImage = texObj->Image[level];
3248         break;
3249      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3250         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3251         texImage = texObj->NegX[level];
3252         break;
3253      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3254         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3255         texImage = texObj->PosY[level];
3256         break;
3257      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3258         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3259         texImage = texObj->NegY[level];
3260         break;
3261      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3262         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3263         texImage = texObj->PosZ[level];
3264         break;
3265      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3266         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3267         texImage = texObj->NegZ[level];
3268         break;
3269      case GL_TEXTURE_3D:
3270         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3271         texImage = texObj->Image[level];
3272         break;
3273      default:
3274         gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3275         return;
3276   }
3277
3278   if (!texImage) {
3279      /* invalid mipmap level */
3280      gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3281      return;
3282   }
3283
3284   if (!texImage->IsCompressed) {
3285      gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3286      return;
3287   }
3288
3289   if (!img)
3290      return;
3291
3292   if (ctx->Driver.GetCompressedTexImage) {
3293      (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3294                                           texImage);
3295   }
3296   else {
3297      gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3298   }
3299}
3300