teximage.c revision 37a6211795cfd0a4431bdb7c676acf54f29df994
1/* $Id: teximage.c,v 1.51 2000/09/28 18:30:39 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                                   GLint     *levelp,
1512                                   GLsizei   *widthp,
1513                                   GLsizei   *heightp,
1514                                   GLsizei   *depthp,
1515                                   GLint     *borderp,
1516                                   GLenum    *formatp,
1517                                   GLenum    *typep)
1518{
1519   char message[100];
1520   GLint internalFormat = ifmt;
1521
1522   if (ctx->Extensions.HaveTextureCompression
1523       && ctx->Driver.SpecificCompressedTexFormat) {
1524      /*
1525       * First, ask the driver for the specific format.
1526       * We do this for all formats, since we may want to
1527       * fake one compressed format for another.
1528       */
1529       internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1530                               (ctx, internalFormat, numDimensions,
1531                                levelp,
1532                                widthp, heightp, depthp,
1533                                borderp, formatp, typep);
1534   }
1535
1536   /*
1537    * Now, convert any generic format left to an uncompressed
1538    * specific format.  If the driver does not support compression
1539    * of the format, we must drop back to the uncompressed format.
1540    * See issue 15 of the GL_ARB_texture_compression specification.
1541    */
1542   switch (internalFormat) {
1543      case GL_COMPRESSED_ALPHA_ARB:
1544         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1545            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1546            gl_error(ctx, GL_INVALID_VALUE, message);
1547            return -1;
1548         }
1549         internalFormat = GL_ALPHA;
1550         break;
1551      case GL_COMPRESSED_LUMINANCE_ARB:
1552         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1553            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1554            gl_error(ctx, GL_INVALID_VALUE, message);
1555            return -1;
1556         }
1557         internalFormat = GL_LUMINANCE;
1558         break;
1559      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1560         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1561            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1562            gl_error(ctx, GL_INVALID_VALUE, message);
1563            return -1;
1564         }
1565         internalFormat = GL_LUMINANCE_ALPHA;
1566         break;
1567      case GL_COMPRESSED_INTENSITY_ARB:
1568         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1569            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1570            gl_error(ctx, GL_INVALID_VALUE, message);
1571            return -1;
1572         }
1573         internalFormat = GL_INTENSITY;
1574         break;
1575      case GL_COMPRESSED_RGB_ARB:
1576         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1577            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1578            gl_error(ctx, GL_INVALID_VALUE, message);
1579            return -1;
1580         }
1581         internalFormat = GL_RGB;
1582         break;
1583      case GL_COMPRESSED_RGBA_ARB:
1584         if (ctx && !ctx->Extensions.HaveTextureCompression) {
1585            sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1586            gl_error(ctx, GL_INVALID_VALUE, message);
1587            return -1;
1588         }
1589         internalFormat = GL_RGBA;
1590         break;
1591      default:
1592         /* silence compiler warning */
1593         ;
1594   }
1595   return internalFormat;
1596}
1597
1598
1599/*
1600 * Called from the API.  Note that width includes the border.
1601 */
1602void
1603_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1604                  GLsizei width, GLint border, GLenum format,
1605                  GLenum type, const GLvoid *pixels )
1606{
1607   GLsizei postConvWidth;
1608   GET_CURRENT_CONTEXT(ctx);
1609   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1610
1611   postConvWidth = width;
1612   adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1613
1614   if (target==GL_TEXTURE_1D) {
1615      struct gl_texture_unit *texUnit;
1616      struct gl_texture_object *texObj;
1617      struct gl_texture_image *texImage;
1618      GLint ifmt;
1619
1620      ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1621                                                &level,
1622                                                &width, 0, 0,
1623                                                &border, &format, &type);
1624      if (ifmt < 0) {
1625         /*
1626          * The error here is that we were sent a generic compressed
1627          * format, but the extension is not supported.
1628          */
1629         return;
1630      }
1631      else {
1632         internalFormat = ifmt;
1633      }
1634
1635      if (texture_error_check(ctx, target, level, internalFormat,
1636                              format, type, 1, postConvWidth, 1, 1, border)) {
1637         return;   /* error in texture image was detected */
1638      }
1639
1640      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1641      texObj = texUnit->CurrentD[1];
1642      texImage = texObj->Image[level];
1643
1644      if (!texImage) {
1645         texImage = _mesa_alloc_texture_image();
1646         texObj->Image[level] = texImage;
1647         if (!texImage) {
1648            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1649            return;
1650         }
1651      }
1652      else if (texImage->Data) {
1653         FREE(texImage->Data);
1654         texImage->Data = NULL;
1655      }
1656
1657      /* setup the teximage struct's fields */
1658      init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
1659
1660      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1661         _mesa_update_image_transfer_state(ctx);
1662
1663      /* process the texture image */
1664      if (pixels) {
1665         GLboolean retain = GL_TRUE;
1666         GLboolean success = GL_FALSE;
1667         if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
1668            /* let device driver try to use raw image */
1669            success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1670                                                 type, pixels, &ctx->Unpack,
1671                                                 texObj, texImage, &retain);
1672         }
1673         if (retain || !success) {
1674            /* make internal copy of the texture image */
1675            make_texture_image(ctx, 1, texImage, width, 1, 1,
1676                               format, type, pixels, &ctx->Unpack);
1677            if (!success && ctx->Driver.TexImage1D) {
1678               /* let device driver try to use unpacked image */
1679               (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1680                                          GL_UNSIGNED_BYTE, texImage->Data,
1681                                          &_mesa_native_packing,
1682                                          texObj, texImage, &retain);
1683            }
1684         }
1685         if (!retain && texImage->Data) {
1686            FREE(texImage->Data);
1687            texImage->Data = NULL;
1688         }
1689      }
1690      else {
1691         make_null_texture(texImage);
1692         if (ctx->Driver.TexImage1D) {
1693            GLboolean retain;
1694            (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1695                                       GL_UNSIGNED_BYTE, texImage->Data,
1696                                       &_mesa_native_packing,
1697                                       texObj, texImage, &retain);
1698         }
1699      }
1700
1701      /* state update */
1702      gl_put_texobj_on_dirty_list( ctx, texObj );
1703      ctx->NewState |= NEW_TEXTURING;
1704   }
1705   else if (target == GL_PROXY_TEXTURE_1D) {
1706      /* Proxy texture: check for errors and update proxy state */
1707      GLenum error = texture_error_check(ctx, target, level, internalFormat,
1708                                         format, type, 1, width, 1, 1, border);
1709      if (!error && ctx->Driver.TestProxyTexImage) {
1710         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1711                                                  internalFormat, format, type,
1712                                                  width, 1, 1, border);
1713      }
1714      if (error) {
1715         /* if error, clear all proxy texture image parameters */
1716         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1717            clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
1718         }
1719      }
1720      else {
1721         /* if no error, update proxy texture image parameters */
1722         init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
1723                            width, 1, 1, border, internalFormat);
1724      }
1725   }
1726   else {
1727      gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1728      return;
1729   }
1730}
1731
1732
1733void
1734_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1735                  GLsizei width, GLsizei height, GLint border,
1736                  GLenum format, GLenum type,
1737                  const GLvoid *pixels )
1738{
1739   GLsizei postConvWidth, postConvHeight;
1740   GET_CURRENT_CONTEXT(ctx);
1741   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1742
1743   postConvWidth = width;
1744   postConvHeight = height;
1745   adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1746
1747   if (target==GL_TEXTURE_2D ||
1748       (ctx->Extensions.HaveTextureCubeMap &&
1749        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1750        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1751      struct gl_texture_unit *texUnit;
1752      struct gl_texture_object *texObj;
1753      struct gl_texture_image *texImage;
1754      GLint ifmt;
1755
1756      ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1757                                                &level,
1758                                                &width, &height, 0,
1759                                                &border, &format, &type);
1760      if (ifmt < 0) {
1761         /*
1762          * The error here is that we were sent a generic compressed
1763          * format, but the extension is not supported.
1764          */
1765         return;
1766      }
1767      else {
1768         internalFormat = ifmt;
1769      }
1770
1771      if (texture_error_check(ctx, target, level, internalFormat,
1772                              format, type, 2, postConvWidth, postConvHeight,
1773                              1, border)) {
1774         return;   /* error in texture image was detected */
1775      }
1776
1777      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1778      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1779      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1780
1781      if (!texImage) {
1782         texImage = _mesa_alloc_texture_image();
1783         set_tex_image(texObj, target, level, texImage);
1784         /*texObj->Image[level] = texImage;*/
1785         if (!texImage) {
1786            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1787            return;
1788         }
1789      }
1790      else if (texImage->Data) {
1791         FREE(texImage->Data);
1792         texImage->Data = NULL;
1793      }
1794
1795      /* setup the teximage struct's fields */
1796      init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
1797                         1, border, internalFormat);
1798
1799      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1800         _mesa_update_image_transfer_state(ctx);
1801
1802      /* process the texture image */
1803      if (pixels) {
1804         GLboolean retain = GL_TRUE;
1805         GLboolean success = GL_FALSE;
1806         if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
1807            /* let device driver try to use raw image */
1808            success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1809                                                 type, pixels, &ctx->Unpack,
1810                                                 texObj, texImage, &retain);
1811         }
1812         if (retain || !success) {
1813            /* make internal copy of the texture image */
1814            make_texture_image(ctx, 2, texImage, width, height, 1,
1815                               format, type, pixels, &ctx->Unpack);
1816            if (!success && ctx->Driver.TexImage2D) {
1817               /* let device driver try to use unpacked image */
1818               (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1819                                          GL_UNSIGNED_BYTE, texImage->Data,
1820                                          &_mesa_native_packing,
1821                                          texObj, texImage, &retain);
1822            }
1823         }
1824         if (!retain && texImage->Data) {
1825            FREE(texImage->Data);
1826            texImage->Data = NULL;
1827         }
1828      }
1829      else {
1830         make_null_texture(texImage);
1831         if (ctx->Driver.TexImage2D) {
1832            GLboolean retain;
1833            (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1834                                       GL_UNSIGNED_BYTE, texImage->Data,
1835                                       &_mesa_native_packing,
1836                                       texObj, texImage, &retain);
1837         }
1838      }
1839
1840#define OLD_DD_TEXTURE
1841#ifdef OLD_DD_TEXTURE
1842      /* XXX this will be removed in the future */
1843      if (ctx->Driver.TexImage) {
1844         (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1845                                  texImage );
1846      }
1847#endif
1848
1849      /* state update */
1850      gl_put_texobj_on_dirty_list( ctx, texObj );
1851      ctx->NewState |= NEW_TEXTURING;
1852   }
1853   else if (target == GL_PROXY_TEXTURE_2D) {
1854      /* Proxy texture: check for errors and update proxy state */
1855      GLenum error = texture_error_check(ctx, target, level, internalFormat,
1856                                    format, type, 2, width, height, 1, border);
1857      if (!error && ctx->Driver.TestProxyTexImage) {
1858         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1859                                                  internalFormat, format, type,
1860                                                  width, height, 1, border);
1861      }
1862      if (error) {
1863         /* if error, clear all proxy texture image parameters */
1864         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1865            clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
1866         }
1867      }
1868      else {
1869         /* if no error, update proxy texture image parameters */
1870         init_texture_image(ctx,
1871                            ctx->Texture.Proxy2D->Image[level],
1872                            width, height, 1, border, internalFormat);
1873      }
1874   }
1875   else {
1876      gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1877      return;
1878   }
1879}
1880
1881
1882/*
1883 * Called by the API or display list executor.
1884 * Note that width and height include the border.
1885 */
1886void
1887_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1888                  GLsizei width, GLsizei height, GLsizei depth,
1889                  GLint border, GLenum format, GLenum type,
1890                  const GLvoid *pixels )
1891{
1892   GET_CURRENT_CONTEXT(ctx);
1893   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1894
1895   if (target==GL_TEXTURE_3D_EXT) {
1896      struct gl_texture_unit *texUnit;
1897      struct gl_texture_object *texObj;
1898      struct gl_texture_image *texImage;
1899      GLint ifmt;
1900
1901      ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1902                                                &level,
1903                                                &width, &height, &depth,
1904                                                &border, &format, &type);
1905      if (ifmt < 0) {
1906         /*
1907          * The error here is that we were sent a generic compressed
1908          * format, but the extension is not supported.
1909          */
1910         return;
1911      }
1912      else {
1913         internalFormat = ifmt;
1914      }
1915
1916      if (texture_error_check(ctx, target, level, internalFormat,
1917                              format, type, 3, width, height, depth, border)) {
1918         return;   /* error in texture image was detected */
1919      }
1920
1921      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1922      texObj = texUnit->CurrentD[3];
1923      texImage = texObj->Image[level];
1924
1925      if (!texImage) {
1926         texImage = _mesa_alloc_texture_image();
1927         texObj->Image[level] = texImage;
1928         if (!texImage) {
1929            gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1930            return;
1931         }
1932      }
1933      else if (texImage->Data) {
1934         FREE(texImage->Data);
1935         texImage->Data = NULL;
1936      }
1937
1938      /* setup the teximage struct's fields */
1939      init_texture_image(ctx, texImage, width, height, depth,
1940                         border, internalFormat);
1941
1942      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1943         _mesa_update_image_transfer_state(ctx);
1944
1945      /* process the texture image */
1946      if (pixels) {
1947         GLboolean retain = GL_TRUE;
1948         GLboolean success = GL_FALSE;
1949         if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
1950            /* let device driver try to use raw image */
1951            success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1952                                                 type, pixels, &ctx->Unpack,
1953                                                 texObj, texImage, &retain);
1954         }
1955         if (retain || !success) {
1956            /* make internal copy of the texture image */
1957            make_texture_image(ctx, 3, texImage, width, height, depth,
1958                               format, type, pixels, &ctx->Unpack);
1959            if (!success && ctx->Driver.TexImage3D) {
1960               /* let device driver try to use unpacked image */
1961               (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1962                                          GL_UNSIGNED_BYTE, texImage->Data,
1963                                          &_mesa_native_packing,
1964                                          texObj, texImage, &retain);
1965            }
1966         }
1967         if (!retain && texImage->Data) {
1968            FREE(texImage->Data);
1969            texImage->Data = NULL;
1970         }
1971      }
1972      else {
1973         make_null_texture(texImage);
1974         if (ctx->Driver.TexImage3D) {
1975            GLboolean retain;
1976            (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1977                                       GL_UNSIGNED_BYTE, texImage->Data,
1978                                       &_mesa_native_packing,
1979                                       texObj, texImage, &retain);
1980         }
1981      }
1982
1983      /* state update */
1984      gl_put_texobj_on_dirty_list( ctx, texObj );
1985      ctx->NewState |= NEW_TEXTURING;
1986   }
1987   else if (target == GL_PROXY_TEXTURE_3D) {
1988      /* Proxy texture: check for errors and update proxy state */
1989      GLenum error = texture_error_check(ctx, target, level, internalFormat,
1990                                format, type, 3, width, height, depth, border);
1991      if (!error && ctx->Driver.TestProxyTexImage) {
1992         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1993                                                 internalFormat, format, type,
1994                                                 width, height, depth, border);
1995      }
1996      if (error) {
1997         /* if error, clear all proxy texture image parameters */
1998         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1999            clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
2000         }
2001      }
2002      else {
2003         /* if no error, update proxy texture image parameters */
2004         init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
2005                            width, height, depth, border, internalFormat);
2006      }
2007   }
2008   else {
2009      gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2010      return;
2011   }
2012}
2013
2014
2015void
2016_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2017                     GLsizei width, GLsizei height, GLsizei depth,
2018                     GLint border, GLenum format, GLenum type,
2019                     const GLvoid *pixels )
2020{
2021   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2022                    depth, border, format, type, pixels);
2023}
2024
2025
2026/*
2027 * Fetch a texture image from the device driver.
2028 * Store the results in the given texture object at the given mipmap level.
2029 */
2030void
2031_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2032                                const struct gl_texture_object *texObj )
2033{
2034   GLvoid *image;
2035   GLenum imgFormat, imgType;
2036   GLboolean freeImage;
2037   struct gl_texture_image *texImage;
2038   GLint destComponents, numPixels, srcBytesPerTexel;
2039
2040   if (!ctx->Driver.GetTexImage)
2041      return;
2042
2043   image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
2044                                       &imgFormat, &imgType, &freeImage);
2045   if (!image)
2046      return;
2047
2048   texImage = texObj->Image[level];
2049   ASSERT(texImage);
2050   if (!texImage)
2051      return;
2052
2053   destComponents = components_in_intformat(texImage->Format);
2054   assert(destComponents > 0);
2055   numPixels = texImage->Width * texImage->Height * texImage->Depth;
2056   assert(numPixels > 0);
2057   srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
2058   assert(srcBytesPerTexel > 0);
2059
2060   if (!texImage->Data) {
2061      /* Allocate memory for the texture image data */
2062      texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
2063   }
2064
2065   if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2066      /* We got lucky!  The driver's format and type match Mesa's format. */
2067      if (texImage->Data) {
2068         MEMCPY(texImage->Data, image, numPixels * destComponents);
2069      }
2070   }
2071   else {
2072      /* Convert the texture image from the driver's format to Mesa's
2073       * internal format.
2074       */
2075      const GLint width = texImage->Width;
2076      const GLint height = texImage->Height;
2077      const GLint depth = texImage->Depth;
2078      const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2079      const GLint srcBytesPerRow = width * srcBytesPerTexel;
2080      const GLenum dstType = GL_UNSIGNED_BYTE;
2081      const GLenum dstFormat = texImage->Format;
2082      const GLubyte *srcPtr = (const GLubyte *) image;
2083      GLubyte *destPtr = texImage->Data;
2084
2085      if (texImage->Format == GL_COLOR_INDEX) {
2086         /* color index texture */
2087         GLint img, row;
2088         assert(imgFormat == GL_COLOR_INDEX);
2089         for (img = 0; img < depth; img++) {
2090            for (row = 0; row < height; row++) {
2091               _mesa_unpack_index_span(ctx, width, dstType, destPtr,
2092                             imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2093               destPtr += destBytesPerRow;
2094               srcPtr += srcBytesPerRow;
2095            }
2096         }
2097      }
2098      else {
2099         /* color texture */
2100         GLint img, row;
2101         for (img = 0; img < depth; img++) {
2102            for (row = 0; row < height; row++) {
2103               _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
2104                  imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2105               destPtr += destBytesPerRow;
2106               srcPtr += srcBytesPerRow;
2107            }
2108         }
2109      }
2110   }
2111
2112   if (freeImage)
2113      FREE(image);
2114}
2115
2116
2117void
2118_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2119                   GLenum type, GLvoid *pixels )
2120{
2121   GET_CURRENT_CONTEXT(ctx);
2122   const struct gl_texture_unit *texUnit;
2123   const struct gl_texture_object *texObj;
2124   struct gl_texture_image *texImage;
2125   GLboolean discardImage;
2126
2127   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2128
2129   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2130      gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2131      return;
2132   }
2133
2134   if (_mesa_sizeof_type(type) <= 0) {
2135      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2136      return;
2137   }
2138
2139   if (_mesa_components_in_format(format) <= 0) {
2140      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2141      return;
2142   }
2143
2144   if (!pixels)
2145      return;
2146
2147   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2148   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2149   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2150   if (!texObj || !texImage ||
2151       target == GL_PROXY_TEXTURE_1D ||
2152       target == GL_PROXY_TEXTURE_2D ||
2153       target == GL_PROXY_TEXTURE_3D) {
2154      gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2155      return;
2156   }
2157
2158   if (!texImage) {
2159      /* invalid mipmap level */
2160      return;
2161   }
2162
2163   if (!texImage->Data) {
2164      /* try to get the texture image from the device driver */
2165      _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2166      discardImage = GL_TRUE;
2167   }
2168   else {
2169      discardImage = GL_FALSE;
2170   }
2171
2172   if (texImage->Data) {
2173      GLint width = texImage->Width;
2174      GLint height = texImage->Height;
2175      GLint depth = texImage->Depth;
2176      GLint img, row;
2177
2178      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2179         _mesa_update_image_transfer_state(ctx);
2180
2181      if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2182         /* convert texture image to GL_RGBA, GL_FLOAT */
2183         GLfloat *tmpImage, *convImage;
2184         const GLint comps = components_in_intformat(texImage->Format);
2185
2186         tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2187         if (!tmpImage) {
2188            gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2189            return;
2190         }
2191         convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2192         if (!convImage) {
2193            FREE(tmpImage);
2194            gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2195            return;
2196         }
2197
2198         for (img = 0; img < depth; img++) {
2199            GLint convWidth, convHeight;
2200
2201            /* convert to GL_RGBA */
2202            for (row = 0; row < height; row++) {
2203               const GLubyte *src = texImage->Data
2204                                  + (img * height + row ) * width * comps;
2205               GLfloat *dst = tmpImage + row * width * 4;
2206               _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2207                          texImage->Format, GL_UNSIGNED_BYTE,
2208                          src, &_mesa_native_packing,
2209                          ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
2210                          GL_FALSE);
2211            }
2212
2213            convWidth = width;
2214            convHeight = height;
2215
2216            /* convolve */
2217            if (target == GL_TEXTURE_1D) {
2218               if (ctx->Pixel.Convolution1DEnabled) {
2219                  _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2220               }
2221            }
2222            else {
2223               if (ctx->Pixel.Convolution2DEnabled) {
2224                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2225                                          tmpImage, convImage);
2226               }
2227               else if (ctx->Pixel.Separable2DEnabled) {
2228                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2229                                           tmpImage, convImage);
2230               }
2231            }
2232
2233            /* pack convolved image */
2234            for (row = 0; row < convHeight; row++) {
2235               const GLfloat *src = convImage + row * convWidth * 4;
2236               GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2237                                                  convWidth, convHeight,
2238                                                  format, type, img, row, 0);
2239               _mesa_pack_float_rgba_span(ctx, convWidth,
2240                        (const GLfloat(*)[4]) src,
2241                        format, type, dest, &ctx->Pack,
2242                        ctx->ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
2243            }
2244         }
2245
2246         FREE(tmpImage);
2247         FREE(convImage);
2248      }
2249      else {
2250         /* no convolution */
2251         for (img = 0; img < depth; img++) {
2252            for (row = 0; row < height; row++) {
2253               /* compute destination address in client memory */
2254               GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2255                                  width, height, format, type, img, row, 0);
2256               assert(dest);
2257               if (texImage->Format == GL_RGBA) {
2258                  /* simple case */
2259                  const GLubyte *src = texImage->Data
2260                                     + (img * height + row ) * width * 4;
2261                  _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
2262                                        format, type, dest, &ctx->Pack,
2263                                        ctx->ImageTransferState );
2264               }
2265               else {
2266                  /* general case:  convert row to RGBA format */
2267                  GLubyte rgba[MAX_WIDTH][4];
2268                  GLint i;
2269                  const GLubyte *src;
2270                  switch (texImage->Format) {
2271                     case GL_ALPHA:
2272                        src = texImage->Data + row * width * sizeof(GLubyte);
2273                        for (i = 0; i < width; i++) {
2274                           rgba[i][RCOMP] = 255;
2275                           rgba[i][GCOMP] = 255;
2276                           rgba[i][BCOMP] = 255;
2277                           rgba[i][ACOMP] = src[i];
2278                        }
2279                        break;
2280                     case GL_LUMINANCE:
2281                        src = texImage->Data + row * width * sizeof(GLubyte);
2282                        for (i = 0; i < width; i++) {
2283                           rgba[i][RCOMP] = src[i];
2284                           rgba[i][GCOMP] = src[i];
2285                           rgba[i][BCOMP] = src[i];
2286                           rgba[i][ACOMP] = 255;
2287                         }
2288                        break;
2289                     case GL_LUMINANCE_ALPHA:
2290                        src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2291                        for (i = 0; i < width; i++) {
2292                           rgba[i][RCOMP] = src[i*2+0];
2293                           rgba[i][GCOMP] = src[i*2+0];
2294                           rgba[i][BCOMP] = src[i*2+0];
2295                           rgba[i][ACOMP] = src[i*2+1];
2296                        }
2297                        break;
2298                     case GL_INTENSITY:
2299                        src = texImage->Data + row * width * sizeof(GLubyte);
2300                        for (i = 0; i < width; i++) {
2301                           rgba[i][RCOMP] = src[i];
2302                           rgba[i][GCOMP] = src[i];
2303                           rgba[i][BCOMP] = src[i];
2304                           rgba[i][ACOMP] = 255;
2305                        }
2306                        break;
2307                     case GL_RGB:
2308                        src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2309                        for (i = 0; i < width; i++) {
2310                           rgba[i][RCOMP] = src[i*3+0];
2311                           rgba[i][GCOMP] = src[i*3+1];
2312                           rgba[i][BCOMP] = src[i*3+2];
2313                           rgba[i][ACOMP] = 255;
2314                        }
2315                        break;
2316                     case GL_COLOR_INDEX:
2317                        gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2318                        break;
2319                     case GL_RGBA:
2320                     default:
2321                        gl_problem( ctx, "bad format in gl_GetTexImage" );
2322                  }
2323                  _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
2324                                        format, type, dest, &ctx->Pack,
2325                                        ctx->ImageTransferState );
2326               } /* format */
2327            } /* row */
2328         } /* img */
2329      } /* convolution */
2330
2331      /* if we got the teximage from the device driver we'll discard it now */
2332      if (discardImage) {
2333         FREE(texImage->Data);
2334         texImage->Data = NULL;
2335      }
2336   }
2337}
2338
2339
2340
2341void
2342_mesa_TexSubImage1D( GLenum target, GLint level,
2343                     GLint xoffset, GLsizei width,
2344                     GLenum format, GLenum type,
2345                     const GLvoid *pixels )
2346{
2347   GET_CURRENT_CONTEXT(ctx);
2348   struct gl_texture_unit *texUnit;
2349   struct gl_texture_object *texObj;
2350   struct gl_texture_image *texImage;
2351   GLboolean success = GL_FALSE;
2352   GLsizei postConvWidth;
2353
2354   postConvWidth = width;
2355   adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2356
2357   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2358                              postConvWidth, 1, 1, format, type)) {
2359      return;   /* error was detected */
2360   }
2361
2362   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2363   texObj = texUnit->CurrentD[1];
2364   texImage = texObj->Image[level];
2365   assert(texImage);
2366
2367   if (width == 0 || !pixels)
2368      return;  /* no-op, not an error */
2369
2370   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2371      _mesa_update_image_transfer_state(ctx);
2372
2373   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
2374      success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2375                                              width, format, type, pixels,
2376                                              &ctx->Unpack, texObj, texImage );
2377   }
2378   if (!success) {
2379      /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2380      GLboolean retain = GL_TRUE;
2381      if (!texImage->Data) {
2382         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2383         if (!texImage->Data) {
2384            make_null_texture(texImage);
2385         }
2386         if (!texImage->Data)
2387            return;  /* we're really out of luck! */
2388      }
2389
2390      fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2391                         width, 1, 1, xoffset, 0, 0, /* size and offsets */
2392                         0, 0, /* strides */
2393                         format, type, pixels, &ctx->Unpack);
2394
2395      if (ctx->Driver.TexImage1D) {
2396         (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2397                                    GL_UNSIGNED_BYTE, texImage->Data,
2398                                    &_mesa_native_packing, texObj, texImage,
2399                                    &retain );
2400      }
2401
2402      if (!retain && texImage->Data) {
2403         FREE(texImage->Data);
2404         texImage->Data = NULL;
2405      }
2406   }
2407}
2408
2409
2410void
2411_mesa_TexSubImage2D( GLenum target, GLint level,
2412                     GLint xoffset, GLint yoffset,
2413                     GLsizei width, GLsizei height,
2414                     GLenum format, GLenum type,
2415                     const GLvoid *pixels )
2416{
2417   GET_CURRENT_CONTEXT(ctx);
2418   struct gl_texture_unit *texUnit;
2419   struct gl_texture_object *texObj;
2420   struct gl_texture_image *texImage;
2421   GLboolean success = GL_FALSE;
2422   GLsizei postConvWidth, postConvHeight;
2423
2424   postConvWidth = width;
2425   postConvHeight = height;
2426   adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2427
2428   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2429                             postConvWidth, postConvHeight, 1, format, type)) {
2430      return;   /* error was detected */
2431   }
2432
2433   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2434   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2435   texImage = texObj->Image[level];
2436   assert(texImage);
2437
2438   if (width == 0 || height == 0 || !pixels)
2439      return;  /* no-op, not an error */
2440
2441   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2442      _mesa_update_image_transfer_state(ctx);
2443
2444   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
2445      success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2446                                     yoffset, width, height, format, type,
2447                                     pixels, &ctx->Unpack, texObj, texImage );
2448   }
2449   if (!success) {
2450      /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2451      const GLint texComps = components_in_intformat(texImage->Format);
2452      const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2453      GLboolean retain = GL_TRUE;
2454
2455      if (!texImage->Data) {
2456         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2457         if (!texImage->Data) {
2458            make_null_texture(texImage);
2459         }
2460         if (!texImage->Data)
2461            return;  /* we're really out of luck! */
2462      }
2463
2464      fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2465                         width, height, 1, xoffset, yoffset, 0,
2466                         texRowStride, 0,
2467                         format, type, pixels, &ctx->Unpack);
2468
2469      if (ctx->Driver.TexImage2D) {
2470         (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2471                                   GL_UNSIGNED_BYTE, texImage->Data,
2472                                   &_mesa_native_packing, texObj, texImage,
2473                                   &retain);
2474      }
2475
2476      if (!retain && texImage->Data) {
2477         FREE(texImage->Data);
2478         texImage->Data = NULL;
2479      }
2480
2481#ifdef OLD_DD_TEXTURE
2482      /* XXX this will be removed in the future */
2483      if (ctx->Driver.TexSubImage) {
2484         (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2485                                    xoffset, yoffset, width, height,
2486                                    texImage->IntFormat, texImage);
2487      }
2488      else if (ctx->Driver.TexImage) {
2489         (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2490                                 level, texImage->IntFormat, texImage );
2491      }
2492#endif
2493   }
2494}
2495
2496
2497
2498void
2499_mesa_TexSubImage3D( GLenum target, GLint level,
2500                     GLint xoffset, GLint yoffset, GLint zoffset,
2501                     GLsizei width, GLsizei height, GLsizei depth,
2502                     GLenum format, GLenum type,
2503                     const GLvoid *pixels )
2504{
2505   GET_CURRENT_CONTEXT(ctx);
2506   struct gl_texture_unit *texUnit;
2507   struct gl_texture_object *texObj;
2508   struct gl_texture_image *texImage;
2509   GLboolean success = GL_FALSE;
2510
2511   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2512                              width, height, depth, format, type)) {
2513      return;   /* error was detected */
2514   }
2515
2516   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2517   texObj = texUnit->CurrentD[3];
2518   texImage = texObj->Image[level];
2519   assert(texImage);
2520
2521   if (width == 0 || height == 0 || height == 0 || !pixels)
2522      return;  /* no-op, not an error */
2523
2524   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2525      _mesa_update_image_transfer_state(ctx);
2526
2527   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
2528      success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2529                                yoffset, zoffset, width, height, depth, format,
2530                                type, pixels, &ctx->Unpack, texObj, texImage );
2531   }
2532   if (!success) {
2533      /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2534      const GLint texComps = components_in_intformat(texImage->Format);
2535      const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2536      const GLint texImgStride = texRowStride * texImage->Height;
2537      GLboolean retain = GL_TRUE;
2538
2539      if (!texImage->Data) {
2540         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2541         if (!texImage->Data) {
2542            make_null_texture(texImage);
2543         }
2544         if (!texImage->Data)
2545            return;  /* we're really out of luck! */
2546      }
2547
2548      fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2549                         width, height, depth, xoffset, yoffset, zoffset,
2550                         texRowStride, texImgStride,
2551                         format, type, pixels, &ctx->Unpack);
2552
2553      if (ctx->Driver.TexImage3D) {
2554         (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2555                                   GL_UNSIGNED_BYTE, texImage->Data,
2556                                   &_mesa_native_packing, texObj, texImage,
2557                                   &retain);
2558      }
2559
2560      if (!retain && texImage->Data) {
2561         FREE(texImage->Data);
2562         texImage->Data = NULL;
2563      }
2564   }
2565}
2566
2567
2568
2569/*
2570 * Read an RGBA image from the frame buffer.
2571 * This is used by glCopyTex[Sub]Image[12]D().
2572 * Input:  ctx - the context
2573 *         x, y - lower left corner
2574 *         width, height - size of region to read
2575 * Return: pointer to block of GL_RGBA, GLubyte data.
2576 */
2577static GLubyte *
2578read_color_image( GLcontext *ctx, GLint x, GLint y,
2579                  GLsizei width, GLsizei height )
2580{
2581   GLint stride, i;
2582   GLubyte *image, *dst;
2583
2584   image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
2585   if (!image)
2586      return NULL;
2587
2588   /* Select buffer to read from */
2589   (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2590                                 ctx->Pixel.DriverReadBuffer );
2591
2592   dst = image;
2593   stride = width * 4 * sizeof(GLubyte);
2594   for (i = 0; i < height; i++) {
2595      gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2596                         (GLubyte (*)[4]) dst );
2597      dst += stride;
2598   }
2599
2600   /* Read from draw buffer (the default) */
2601   (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2602                                 ctx->Color.DriverDrawBuffer );
2603
2604   return image;
2605}
2606
2607
2608
2609void
2610_mesa_CopyTexImage1D( GLenum target, GLint level,
2611                      GLenum internalFormat,
2612                      GLint x, GLint y,
2613                      GLsizei width, GLint border )
2614{
2615   GET_CURRENT_CONTEXT(ctx);
2616   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2617
2618   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2619                               width, 1, border))
2620      return;
2621
2622   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2623      _mesa_update_image_transfer_state(ctx);
2624
2625   if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
2626       || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2627                         internalFormat, x, y, width, border)) {
2628      struct gl_pixelstore_attrib unpackSave;
2629
2630      /* get image from framebuffer */
2631      GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2632      if (!image) {
2633         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2634         return;
2635      }
2636
2637      /* call glTexImage1D to redefine the texture */
2638      unpackSave = ctx->Unpack;
2639      ctx->Unpack = _mesa_native_packing;
2640      (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2641                                border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2642      ctx->Unpack = unpackSave;
2643
2644      FREE(image);
2645   }
2646}
2647
2648
2649
2650void
2651_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2652                      GLint x, GLint y, GLsizei width, GLsizei height,
2653                      GLint border )
2654{
2655   GET_CURRENT_CONTEXT(ctx);
2656   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2657
2658   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2659                               width, height, border))
2660      return;
2661
2662   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2663      _mesa_update_image_transfer_state(ctx);
2664
2665   if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
2666       || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2667                         internalFormat, x, y, width, height, border)) {
2668      struct gl_pixelstore_attrib unpackSave;
2669
2670      /* get image from framebuffer */
2671      GLubyte *image = read_color_image( ctx, x, y, width, height );
2672      if (!image) {
2673         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2674         return;
2675      }
2676
2677      /* call glTexImage2D to redefine the texture */
2678      unpackSave = ctx->Unpack;
2679      ctx->Unpack = _mesa_native_packing;
2680      (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2681                      height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2682      ctx->Unpack = unpackSave;
2683
2684      FREE(image);
2685   }
2686}
2687
2688
2689
2690void
2691_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2692                         GLint xoffset, GLint x, GLint y, GLsizei width )
2693{
2694   GET_CURRENT_CONTEXT(ctx);
2695   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2696
2697   if (copytexsubimage_error_check(ctx, 1, target, level,
2698                                   xoffset, 0, 0, width, 1))
2699      return;
2700
2701   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2702      _mesa_update_image_transfer_state(ctx);
2703
2704   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2705       || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2706                                            xoffset, x, y, width)) {
2707      struct gl_texture_unit *texUnit;
2708      struct gl_texture_image *teximage;
2709      struct gl_pixelstore_attrib unpackSave;
2710      GLubyte *image;
2711
2712      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2713      teximage = texUnit->CurrentD[1]->Image[level];
2714      assert(teximage);
2715
2716      /* get image from frame buffer */
2717      image = read_color_image(ctx, x, y, width, 1);
2718      if (!image) {
2719         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2720         return;
2721      }
2722
2723      /* now call glTexSubImage1D to do the real work */
2724      unpackSave = ctx->Unpack;
2725      ctx->Unpack = _mesa_native_packing;
2726      _mesa_TexSubImage1D(target, level, xoffset, width,
2727                          GL_RGBA, GL_UNSIGNED_BYTE, image);
2728      ctx->Unpack = unpackSave;
2729
2730      FREE(image);
2731   }
2732}
2733
2734
2735
2736void
2737_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2738                         GLint xoffset, GLint yoffset,
2739                         GLint x, GLint y, GLsizei width, GLsizei height )
2740{
2741   GET_CURRENT_CONTEXT(ctx);
2742   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2743
2744   if (copytexsubimage_error_check(ctx, 2, target, level,
2745                                   xoffset, yoffset, 0, width, height))
2746      return;
2747
2748   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2749      _mesa_update_image_transfer_state(ctx);
2750
2751   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2752       || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2753                                xoffset, yoffset, x, y, width, height )) {
2754      struct gl_texture_unit *texUnit;
2755      struct gl_texture_image *teximage;
2756      struct gl_pixelstore_attrib unpackSave;
2757      GLubyte *image;
2758
2759      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2760      teximage = texUnit->CurrentD[2]->Image[level];
2761      assert(teximage);
2762
2763      /* get image from frame buffer */
2764      image = read_color_image(ctx, x, y, width, height);
2765      if (!image) {
2766         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2767         return;
2768      }
2769
2770      /* now call glTexSubImage2D to do the real work */
2771      unpackSave = ctx->Unpack;
2772      ctx->Unpack = _mesa_native_packing;
2773      _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2774                          GL_RGBA, GL_UNSIGNED_BYTE, image);
2775      ctx->Unpack = unpackSave;
2776
2777      FREE(image);
2778   }
2779}
2780
2781
2782
2783void
2784_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2785                         GLint xoffset, GLint yoffset, GLint zoffset,
2786                         GLint x, GLint y, GLsizei width, GLsizei height )
2787{
2788   GET_CURRENT_CONTEXT(ctx);
2789   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2790
2791   if (copytexsubimage_error_check(ctx, 3, target, level,
2792                    xoffset, yoffset, zoffset, width, height))
2793      return;
2794
2795   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2796      _mesa_update_image_transfer_state(ctx);
2797
2798   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2799       || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2800                     xoffset, yoffset, zoffset, x, y, width, height )) {
2801      struct gl_texture_unit *texUnit;
2802      struct gl_texture_image *teximage;
2803      struct gl_pixelstore_attrib unpackSave;
2804      GLubyte *image;
2805
2806      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2807      teximage = texUnit->CurrentD[3]->Image[level];
2808      assert(teximage);
2809
2810      /* get image from frame buffer */
2811      image = read_color_image(ctx, x, y, width, height);
2812      if (!image) {
2813         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2814         return;
2815      }
2816
2817      /* now call glTexSubImage2D to do the real work */
2818      unpackSave = ctx->Unpack;
2819      ctx->Unpack = _mesa_native_packing;
2820      _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2821                          width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2822      ctx->Unpack = unpackSave;
2823
2824      FREE(image);
2825   }
2826}
2827
2828
2829
2830void
2831_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2832                              GLenum internalFormat, GLsizei width,
2833                              GLint border, GLsizei imageSize,
2834                              const GLvoid *data)
2835{
2836   GET_CURRENT_CONTEXT(ctx);
2837   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2838
2839   switch (internalFormat) {
2840      case GL_COMPRESSED_ALPHA_ARB:
2841      case GL_COMPRESSED_LUMINANCE_ARB:
2842      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2843      case GL_COMPRESSED_INTENSITY_ARB:
2844      case GL_COMPRESSED_RGB_ARB:
2845      case GL_COMPRESSED_RGBA_ARB:
2846         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2847         return;
2848      default:
2849         /* silence compiler warning */
2850         ;
2851   }
2852
2853   if (target == GL_TEXTURE_1D) {
2854      struct gl_texture_unit *texUnit;
2855      struct gl_texture_object *texObj;
2856      struct gl_texture_image *texImage;
2857      GLsizei computedImageSize;
2858
2859      if (texture_error_check(ctx, target, level, internalFormat,
2860                              GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2861         return;   /* error in texture image was detected */
2862      }
2863
2864      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2865      texObj = texUnit->CurrentD[1];
2866      texImage = texObj->Image[level];
2867
2868      if (!texImage) {
2869         texImage = _mesa_alloc_texture_image();
2870         texObj->Image[level] = texImage;
2871         if (!texImage) {
2872            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2873            return;
2874         }
2875      }
2876      else if (texImage->Data) {
2877         FREE(texImage->Data);
2878         texImage->Data = NULL;
2879      }
2880
2881      /* setup the teximage struct's fields */
2882      init_texture_image(ctx, texImage, width, 1, 1,
2883                         border, internalFormat);
2884
2885      /* process the texture image */
2886      if (data) {
2887         GLboolean retain = GL_TRUE;
2888         GLboolean success = GL_FALSE;
2889         if (ctx->Driver.CompressedTexImage1D) {
2890            success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2891                               imageSize, data, texObj, texImage, &retain);
2892         }
2893         if (retain || !success) {
2894            /* make internal copy of the texture image */
2895            computedImageSize = _mesa_compressed_image_size(ctx,
2896                                                        internalFormat,
2897                                                        1,    /* num dims */
2898                                                        width,
2899                                                        1,    /* height   */
2900                                                        1);   /* depth    */
2901            if (computedImageSize != imageSize) {
2902                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2903                return;
2904            }
2905            texImage->Data = MALLOC(computedImageSize);
2906            if (texImage->Data) {
2907               MEMCPY(texImage->Data, data, computedImageSize);
2908            }
2909         }
2910         if (!retain && texImage->Data) {
2911            FREE(texImage->Data);
2912            texImage->Data = NULL;
2913         }
2914      }
2915      else {
2916         make_null_texture(texImage);
2917         if (ctx->Driver.CompressedTexImage1D) {
2918            GLboolean retain;
2919            (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2920                                                texImage->Data, texObj,
2921                                                texImage, &retain);
2922         }
2923      }
2924
2925      /* state update */
2926      gl_put_texobj_on_dirty_list( ctx, texObj );
2927      ctx->NewState |= NEW_TEXTURING;
2928   }
2929   else if (target == GL_PROXY_TEXTURE_1D) {
2930      /* Proxy texture: check for errors and update proxy state */
2931      GLenum error = texture_error_check(ctx, target, level, internalFormat,
2932                                    GL_NONE, GL_NONE, 1, width, 1, 1, border);
2933      if (!error && ctx->Driver.TestProxyTexImage) {
2934         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2935                                             internalFormat, GL_NONE, GL_NONE,
2936                                             width, 1, 1, border);
2937      }
2938      if (error) {
2939         /* if error, clear all proxy texture image parameters */
2940         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2941            clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
2942         }
2943      }
2944      else {
2945         /* if no error, update proxy texture image parameters */
2946         init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
2947                            width, 1, 1, border, internalFormat);
2948      }
2949   }
2950   else {
2951      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2952      return;
2953   }
2954}
2955
2956
2957void
2958_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2959                              GLenum internalFormat, GLsizei width,
2960                              GLsizei height, GLint border, GLsizei imageSize,
2961                              const GLvoid *data)
2962{
2963   GET_CURRENT_CONTEXT(ctx);
2964   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2965
2966   switch (internalFormat) {
2967      case GL_COMPRESSED_ALPHA_ARB:
2968      case GL_COMPRESSED_LUMINANCE_ARB:
2969      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2970      case GL_COMPRESSED_INTENSITY_ARB:
2971      case GL_COMPRESSED_RGB_ARB:
2972      case GL_COMPRESSED_RGBA_ARB:
2973         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2974         return;
2975      default:
2976         /* silence compiler warning */
2977         ;
2978   }
2979
2980   if (target==GL_TEXTURE_2D ||
2981       (ctx->Extensions.HaveTextureCubeMap &&
2982        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2983        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2984      struct gl_texture_unit *texUnit;
2985      struct gl_texture_object *texObj;
2986      struct gl_texture_image *texImage;
2987      GLsizei computedImageSize;
2988
2989      if (texture_error_check(ctx, target, level, internalFormat,
2990                              GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2991         return;   /* error in texture image was detected */
2992      }
2993
2994      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2995      texObj = texUnit->CurrentD[2];
2996      texImage = texObj->Image[level];
2997
2998      if (!texImage) {
2999         texImage = _mesa_alloc_texture_image();
3000         texObj->Image[level] = texImage;
3001         if (!texImage) {
3002            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3003            return;
3004         }
3005      }
3006      else if (texImage->Data) {
3007         FREE(texImage->Data);
3008         texImage->Data = NULL;
3009      }
3010
3011      /* setup the teximage struct's fields */
3012      init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
3013
3014      /* process the texture image */
3015      if (data) {
3016         GLboolean retain = GL_TRUE;
3017         GLboolean success = GL_FALSE;
3018         if (ctx->Driver.CompressedTexImage2D) {
3019            success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3020                                                           target,
3021                                                           level,
3022                                                           imageSize,
3023                                                           data,
3024                                                           texObj,
3025                                                           texImage,
3026                                                           &retain);
3027         }
3028         if (retain || !success) {
3029            /* make internal copy of the texture image */
3030            computedImageSize = _mesa_compressed_image_size(ctx,
3031                                                           internalFormat,
3032                                                           2,    /* num dims */
3033                                                           width,
3034                                                           height,
3035                                                           1);   /* depth    */
3036            if (computedImageSize != imageSize) {
3037                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3038                return;
3039            }
3040            texImage->Data = MALLOC(computedImageSize);
3041            if (texImage->Data) {
3042               MEMCPY(texImage->Data, data, computedImageSize);
3043            }
3044         }
3045         if (!retain && texImage->Data) {
3046            FREE(texImage->Data);
3047            texImage->Data = NULL;
3048         }
3049      }
3050      else {
3051         make_null_texture(texImage);
3052         if (ctx->Driver.CompressedTexImage2D) {
3053            GLboolean retain;
3054            (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3055                                                 texImage->Data, texObj,
3056                                                 texImage, &retain);
3057         }
3058      }
3059
3060      /* state update */
3061      gl_put_texobj_on_dirty_list( ctx, texObj );
3062      ctx->NewState |= NEW_TEXTURING;
3063   }
3064   else if (target == GL_PROXY_TEXTURE_2D) {
3065      /* Proxy texture: check for errors and update proxy state */
3066      GLenum error = texture_error_check(ctx, target, level, internalFormat,
3067                                GL_NONE, GL_NONE, 2, width, height, 1, border);
3068      if (!error && ctx->Driver.TestProxyTexImage) {
3069         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3070                                              internalFormat, GL_NONE, GL_NONE,
3071                                              width, height, 1, border);
3072      }
3073      if (error) {
3074         /* if error, clear all proxy texture image parameters */
3075         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3076            clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
3077         }
3078      }
3079      else {
3080         /* if no error, update proxy texture image parameters */
3081         init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
3082                            width, 1, 1, border, internalFormat);
3083      }
3084   }
3085   else {
3086      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3087      return;
3088   }
3089}
3090
3091
3092void
3093_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3094                              GLenum internalFormat, GLsizei width,
3095                              GLsizei height, GLsizei depth, GLint border,
3096                              GLsizei imageSize, const GLvoid *data)
3097{
3098   GET_CURRENT_CONTEXT(ctx);
3099   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3100
3101   switch (internalFormat) {
3102      case GL_COMPRESSED_ALPHA_ARB:
3103      case GL_COMPRESSED_LUMINANCE_ARB:
3104      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3105      case GL_COMPRESSED_INTENSITY_ARB:
3106      case GL_COMPRESSED_RGB_ARB:
3107      case GL_COMPRESSED_RGBA_ARB:
3108         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3109         return;
3110      default:
3111         /* silence compiler warning */
3112         ;
3113   }
3114
3115   if (target == GL_TEXTURE_3D) {
3116      struct gl_texture_unit *texUnit;
3117      struct gl_texture_object *texObj;
3118      struct gl_texture_image *texImage;
3119      GLsizei computedImageSize;
3120
3121      if (texture_error_check(ctx, target, level, internalFormat,
3122                          GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3123         return;   /* error in texture image was detected */
3124      }
3125
3126      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3127      texObj = texUnit->CurrentD[3];
3128      texImage = texObj->Image[level];
3129
3130      if (!texImage) {
3131         texImage = _mesa_alloc_texture_image();
3132         texObj->Image[level] = texImage;
3133         if (!texImage) {
3134            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3135            return;
3136         }
3137      }
3138      else if (texImage->Data) {
3139         FREE(texImage->Data);
3140         texImage->Data = NULL;
3141      }
3142
3143      /* setup the teximage struct's fields */
3144      init_texture_image(ctx, texImage, width, height, depth,
3145                         border, internalFormat);
3146
3147      /* process the texture image */
3148      if (data) {
3149         GLboolean retain = GL_TRUE;
3150         GLboolean success = GL_FALSE;
3151         if (ctx->Driver.CompressedTexImage3D) {
3152            success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3153                                                          imageSize, data,
3154                                                          texObj, texImage,
3155                                                          &retain);
3156         }
3157         if (retain || !success) {
3158            /* make internal copy of the texture image */
3159            computedImageSize = _mesa_compressed_image_size(ctx,
3160                                                            internalFormat,
3161                                                            3,  /* num dims */
3162                                                            width,
3163                                                            height,
3164                                                            depth);
3165            if (computedImageSize != imageSize) {
3166                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3167                return;
3168            }
3169            texImage->Data = MALLOC(computedImageSize);
3170            if (texImage->Data) {
3171               MEMCPY(texImage->Data, data, computedImageSize);
3172            }
3173         }
3174         if (!retain && texImage->Data) {
3175            FREE(texImage->Data);
3176            texImage->Data = NULL;
3177         }
3178      }
3179      else {
3180         make_null_texture(texImage);
3181         if (ctx->Driver.CompressedTexImage3D) {
3182            GLboolean retain;
3183            (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3184                                                 texImage->Data, texObj,
3185                                                 texImage, &retain);
3186         }
3187      }
3188
3189      /* state update */
3190      gl_put_texobj_on_dirty_list( ctx, texObj );
3191      ctx->NewState |= NEW_TEXTURING;
3192   }
3193   else if (target == GL_PROXY_TEXTURE_3D) {
3194      /* Proxy texture: check for errors and update proxy state */
3195      GLenum error = texture_error_check(ctx, target, level, internalFormat,
3196                            GL_NONE, GL_NONE, 1, width, height, depth, border);
3197      if (!error && ctx->Driver.TestProxyTexImage) {
3198         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3199                                             internalFormat, GL_NONE, GL_NONE,
3200                                             width, height, depth, border);
3201      }
3202      if (error) {
3203         /* if error, clear all proxy texture image parameters */
3204         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3205            clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
3206         }
3207      }
3208      else {
3209         /* if no error, update proxy texture image parameters */
3210         init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3211                            width, 1, 1, border, internalFormat);
3212      }
3213   }
3214   else {
3215      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3216      return;
3217   }
3218}
3219
3220
3221void
3222_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3223                                 GLsizei width, GLenum format,
3224                                 GLsizei imageSize, const GLvoid *data)
3225{
3226   GET_CURRENT_CONTEXT(ctx);
3227   struct gl_texture_unit *texUnit;
3228   struct gl_texture_object *texObj;
3229   struct gl_texture_image *texImage;
3230   GLboolean success = GL_FALSE;
3231
3232   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3233                              width, 1, 1, format, GL_NONE)) {
3234      return;   /* error was detected */
3235   }
3236
3237   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3238   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3239   texImage = texObj->Image[level];
3240   assert(texImage);
3241
3242   if (width == 0 || !data)
3243      return;  /* no-op, not an error */
3244
3245   if (ctx->Driver.CompressedTexSubImage1D) {
3246      success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3247                   xoffset, width, format, imageSize, data, texObj, texImage);
3248   }
3249   if (!success) {
3250      /* XXX what else can we do? */
3251      gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3252      return;
3253   }
3254}
3255
3256
3257void
3258_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3259                                 GLint yoffset, GLsizei width, GLsizei height,
3260                                 GLenum format, GLsizei imageSize,
3261                                 const GLvoid *data)
3262{
3263   GET_CURRENT_CONTEXT(ctx);
3264   struct gl_texture_unit *texUnit;
3265   struct gl_texture_object *texObj;
3266   struct gl_texture_image *texImage;
3267   GLboolean success = GL_FALSE;
3268
3269   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3270                              width, height, 1, format, GL_NONE)) {
3271      return;   /* error was detected */
3272   }
3273
3274   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3275   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3276   texImage = texObj->Image[level];
3277   assert(texImage);
3278
3279   if (width == 0 || height == 0 || !data)
3280      return;  /* no-op, not an error */
3281
3282   if (ctx->Driver.CompressedTexSubImage2D) {
3283      success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3284                                       xoffset, yoffset, width, height, format,
3285                                       imageSize, data, texObj, texImage);
3286   }
3287   if (!success) {
3288      /* XXX what else can we do? */
3289      gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3290      return;
3291   }
3292}
3293
3294
3295void
3296_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3297                                 GLint yoffset, GLint zoffset, GLsizei width,
3298                                 GLsizei height, GLsizei depth, GLenum format,
3299                                 GLsizei imageSize, const GLvoid *data)
3300{
3301   GET_CURRENT_CONTEXT(ctx);
3302   struct gl_texture_unit *texUnit;
3303   struct gl_texture_object *texObj;
3304   struct gl_texture_image *texImage;
3305   GLboolean success = GL_FALSE;
3306
3307   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3308                              width, height, depth, format, GL_NONE)) {
3309      return;   /* error was detected */
3310   }
3311
3312   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3313   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3314   texImage = texObj->Image[level];
3315   assert(texImage);
3316
3317   if (width == 0 || height == 0 || depth == 0 || !data)
3318      return;  /* no-op, not an error */
3319
3320   if (ctx->Driver.CompressedTexSubImage3D) {
3321      success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3322                               xoffset, yoffset, zoffset, width, height, depth,
3323                               format, imageSize, data, texObj, texImage);
3324   }
3325   if (!success) {
3326      /* XXX what else can we do? */
3327      gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3328      return;
3329   }
3330}
3331
3332
3333void
3334_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3335{
3336   GET_CURRENT_CONTEXT(ctx);
3337   const struct gl_texture_object *texObj;
3338   struct gl_texture_image *texImage;
3339
3340   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3341
3342   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3343      gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3344      return;
3345   }
3346
3347   switch (target) {
3348      case GL_TEXTURE_1D:
3349         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3350         texImage = texObj->Image[level];
3351         break;
3352      case GL_TEXTURE_2D:
3353         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3354         texImage = texObj->Image[level];
3355         break;
3356      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3357         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3358         texImage = texObj->Image[level];
3359         break;
3360      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3361         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3362         texImage = texObj->NegX[level];
3363         break;
3364      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3365         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3366         texImage = texObj->PosY[level];
3367         break;
3368      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3369         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3370         texImage = texObj->NegY[level];
3371         break;
3372      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3373         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3374         texImage = texObj->PosZ[level];
3375         break;
3376      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3377         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3378         texImage = texObj->NegZ[level];
3379         break;
3380      case GL_TEXTURE_3D:
3381         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3382         texImage = texObj->Image[level];
3383         break;
3384      default:
3385         gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3386         return;
3387   }
3388
3389   if (!texImage) {
3390      /* invalid mipmap level */
3391      gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3392      return;
3393   }
3394
3395   if (!texImage->IsCompressed) {
3396      gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3397      return;
3398   }
3399
3400   if (!img)
3401      return;
3402
3403   if (ctx->Driver.GetCompressedTexImage) {
3404      (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3405                                           texImage);
3406   }
3407   else {
3408      gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3409   }
3410}
3411