teximage.c revision 1873b567b28a3e3f4d94d0eacb27ffd235ec9529
1/* $Id: teximage.c,v 1.52 2000/10/16 23:43:12 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
2117/*
2118 * Get all the mipmap images for a texture object from the device driver.
2119 * Actually, only get mipmap images if we're using a mipmap filter.
2120 */
2121GLboolean
2122_mesa_get_teximages_from_driver(GLcontext *ctx,
2123                                struct gl_texture_object *texObj)
2124{
2125   if (ctx->Driver.GetTexImage) {
2126      static const GLenum targets[] = {
2127         GL_TEXTURE_1D,
2128         GL_TEXTURE_2D,
2129         GL_TEXTURE_3D,
2130         GL_TEXTURE_CUBE_MAP_ARB,
2131         GL_TEXTURE_CUBE_MAP_ARB,
2132         GL_TEXTURE_CUBE_MAP_ARB
2133      };
2134      GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter);
2135      GLenum target = targets[texObj->Dimensions - 1];
2136      if (needLambda) {
2137         GLint level;
2138         /* Get images for all mipmap levels.  We might not need them
2139          * all but this is easier.  We're on a (slow) software path
2140          * anyway.
2141          */
2142         for (level = 0; level <= texObj->P; level++) {
2143            struct gl_texture_image *texImg = texObj->Image[level];
2144            if (texImg && !texImg->Data) {
2145               _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2146               if (!texImg->Data)
2147                  return GL_FALSE;  /* out of memory */
2148            }
2149         }
2150      }
2151      else {
2152         GLint level = texObj->BaseLevel;
2153         struct gl_texture_image *texImg = texObj->Image[level];
2154         if (texImg && !texImg->Data) {
2155            _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2156            if (!texImg->Data)
2157               return GL_FALSE;  /* out of memory */
2158         }
2159      }
2160      return GL_TRUE;
2161   }
2162   return GL_FALSE;
2163}
2164
2165
2166
2167void
2168_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2169                   GLenum type, GLvoid *pixels )
2170{
2171   GET_CURRENT_CONTEXT(ctx);
2172   const struct gl_texture_unit *texUnit;
2173   const struct gl_texture_object *texObj;
2174   struct gl_texture_image *texImage;
2175   GLboolean discardImage;
2176
2177   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2178
2179   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2180      gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2181      return;
2182   }
2183
2184   if (_mesa_sizeof_type(type) <= 0) {
2185      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2186      return;
2187   }
2188
2189   if (_mesa_components_in_format(format) <= 0) {
2190      gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2191      return;
2192   }
2193
2194   if (!pixels)
2195      return;
2196
2197   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2198   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2199   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2200   if (!texObj || !texImage ||
2201       target == GL_PROXY_TEXTURE_1D ||
2202       target == GL_PROXY_TEXTURE_2D ||
2203       target == GL_PROXY_TEXTURE_3D) {
2204      gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2205      return;
2206   }
2207
2208   if (!texImage) {
2209      /* invalid mipmap level */
2210      return;
2211   }
2212
2213   if (!texImage->Data) {
2214      /* try to get the texture image from the device driver */
2215      _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2216      discardImage = GL_TRUE;
2217   }
2218   else {
2219      discardImage = GL_FALSE;
2220   }
2221
2222   if (texImage->Data) {
2223      GLint width = texImage->Width;
2224      GLint height = texImage->Height;
2225      GLint depth = texImage->Depth;
2226      GLint img, row;
2227
2228      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2229         _mesa_update_image_transfer_state(ctx);
2230
2231      if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2232         /* convert texture image to GL_RGBA, GL_FLOAT */
2233         GLfloat *tmpImage, *convImage;
2234         const GLint comps = components_in_intformat(texImage->Format);
2235
2236         tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2237         if (!tmpImage) {
2238            gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2239            return;
2240         }
2241         convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2242         if (!convImage) {
2243            FREE(tmpImage);
2244            gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2245            return;
2246         }
2247
2248         for (img = 0; img < depth; img++) {
2249            GLint convWidth, convHeight;
2250
2251            /* convert to GL_RGBA */
2252            for (row = 0; row < height; row++) {
2253               const GLubyte *src = texImage->Data
2254                                  + (img * height + row ) * width * comps;
2255               GLfloat *dst = tmpImage + row * width * 4;
2256               _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2257                          texImage->Format, GL_UNSIGNED_BYTE,
2258                          src, &_mesa_native_packing,
2259                          ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
2260                          GL_FALSE);
2261            }
2262
2263            convWidth = width;
2264            convHeight = height;
2265
2266            /* convolve */
2267            if (target == GL_TEXTURE_1D) {
2268               if (ctx->Pixel.Convolution1DEnabled) {
2269                  _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2270               }
2271            }
2272            else {
2273               if (ctx->Pixel.Convolution2DEnabled) {
2274                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2275                                          tmpImage, convImage);
2276               }
2277               else if (ctx->Pixel.Separable2DEnabled) {
2278                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2279                                           tmpImage, convImage);
2280               }
2281            }
2282
2283            /* pack convolved image */
2284            for (row = 0; row < convHeight; row++) {
2285               const GLfloat *src = convImage + row * convWidth * 4;
2286               GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2287                                                  convWidth, convHeight,
2288                                                  format, type, img, row, 0);
2289               _mesa_pack_float_rgba_span(ctx, convWidth,
2290                        (const GLfloat(*)[4]) src,
2291                        format, type, dest, &ctx->Pack,
2292                        ctx->ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
2293            }
2294         }
2295
2296         FREE(tmpImage);
2297         FREE(convImage);
2298      }
2299      else {
2300         /* no convolution */
2301         for (img = 0; img < depth; img++) {
2302            for (row = 0; row < height; row++) {
2303               /* compute destination address in client memory */
2304               GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2305                                  width, height, format, type, img, row, 0);
2306               assert(dest);
2307               if (texImage->Format == GL_RGBA) {
2308                  /* simple case */
2309                  const GLubyte *src = texImage->Data
2310                                     + (img * height + row ) * width * 4;
2311                  _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
2312                                        format, type, dest, &ctx->Pack,
2313                                        ctx->ImageTransferState );
2314               }
2315               else {
2316                  /* general case:  convert row to RGBA format */
2317                  GLubyte rgba[MAX_WIDTH][4];
2318                  GLint i;
2319                  const GLubyte *src;
2320                  switch (texImage->Format) {
2321                     case GL_ALPHA:
2322                        src = texImage->Data + row * width * sizeof(GLubyte);
2323                        for (i = 0; i < width; i++) {
2324                           rgba[i][RCOMP] = 255;
2325                           rgba[i][GCOMP] = 255;
2326                           rgba[i][BCOMP] = 255;
2327                           rgba[i][ACOMP] = src[i];
2328                        }
2329                        break;
2330                     case GL_LUMINANCE:
2331                        src = texImage->Data + row * width * sizeof(GLubyte);
2332                        for (i = 0; i < width; i++) {
2333                           rgba[i][RCOMP] = src[i];
2334                           rgba[i][GCOMP] = src[i];
2335                           rgba[i][BCOMP] = src[i];
2336                           rgba[i][ACOMP] = 255;
2337                         }
2338                        break;
2339                     case GL_LUMINANCE_ALPHA:
2340                        src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2341                        for (i = 0; i < width; i++) {
2342                           rgba[i][RCOMP] = src[i*2+0];
2343                           rgba[i][GCOMP] = src[i*2+0];
2344                           rgba[i][BCOMP] = src[i*2+0];
2345                           rgba[i][ACOMP] = src[i*2+1];
2346                        }
2347                        break;
2348                     case GL_INTENSITY:
2349                        src = texImage->Data + row * width * sizeof(GLubyte);
2350                        for (i = 0; i < width; i++) {
2351                           rgba[i][RCOMP] = src[i];
2352                           rgba[i][GCOMP] = src[i];
2353                           rgba[i][BCOMP] = src[i];
2354                           rgba[i][ACOMP] = 255;
2355                        }
2356                        break;
2357                     case GL_RGB:
2358                        src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2359                        for (i = 0; i < width; i++) {
2360                           rgba[i][RCOMP] = src[i*3+0];
2361                           rgba[i][GCOMP] = src[i*3+1];
2362                           rgba[i][BCOMP] = src[i*3+2];
2363                           rgba[i][ACOMP] = 255;
2364                        }
2365                        break;
2366                     case GL_COLOR_INDEX:
2367                        gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2368                        break;
2369                     case GL_RGBA:
2370                     default:
2371                        gl_problem( ctx, "bad format in gl_GetTexImage" );
2372                  }
2373                  _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
2374                                        format, type, dest, &ctx->Pack,
2375                                        ctx->ImageTransferState );
2376               } /* format */
2377            } /* row */
2378         } /* img */
2379      } /* convolution */
2380
2381      /* if we got the teximage from the device driver we'll discard it now */
2382      if (discardImage) {
2383         FREE(texImage->Data);
2384         texImage->Data = NULL;
2385      }
2386   }
2387}
2388
2389
2390
2391void
2392_mesa_TexSubImage1D( GLenum target, GLint level,
2393                     GLint xoffset, GLsizei width,
2394                     GLenum format, GLenum type,
2395                     const GLvoid *pixels )
2396{
2397   GET_CURRENT_CONTEXT(ctx);
2398   struct gl_texture_unit *texUnit;
2399   struct gl_texture_object *texObj;
2400   struct gl_texture_image *texImage;
2401   GLboolean success = GL_FALSE;
2402   GLsizei postConvWidth;
2403
2404   postConvWidth = width;
2405   adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2406
2407   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2408                              postConvWidth, 1, 1, format, type)) {
2409      return;   /* error was detected */
2410   }
2411
2412   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2413   texObj = texUnit->CurrentD[1];
2414   texImage = texObj->Image[level];
2415   assert(texImage);
2416
2417   if (width == 0 || !pixels)
2418      return;  /* no-op, not an error */
2419
2420   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2421      _mesa_update_image_transfer_state(ctx);
2422
2423   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
2424      success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2425                                              width, format, type, pixels,
2426                                              &ctx->Unpack, texObj, texImage );
2427   }
2428   if (!success) {
2429      /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2430      GLboolean retain = GL_TRUE;
2431      if (!texImage->Data) {
2432         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2433         if (!texImage->Data) {
2434            make_null_texture(texImage);
2435         }
2436         if (!texImage->Data)
2437            return;  /* we're really out of luck! */
2438      }
2439
2440      fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2441                         width, 1, 1, xoffset, 0, 0, /* size and offsets */
2442                         0, 0, /* strides */
2443                         format, type, pixels, &ctx->Unpack);
2444
2445      if (ctx->Driver.TexImage1D) {
2446         (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2447                                    GL_UNSIGNED_BYTE, texImage->Data,
2448                                    &_mesa_native_packing, texObj, texImage,
2449                                    &retain );
2450      }
2451
2452      if (!retain && texImage->Data) {
2453         FREE(texImage->Data);
2454         texImage->Data = NULL;
2455      }
2456   }
2457}
2458
2459
2460void
2461_mesa_TexSubImage2D( GLenum target, GLint level,
2462                     GLint xoffset, GLint yoffset,
2463                     GLsizei width, GLsizei height,
2464                     GLenum format, GLenum type,
2465                     const GLvoid *pixels )
2466{
2467   GET_CURRENT_CONTEXT(ctx);
2468   struct gl_texture_unit *texUnit;
2469   struct gl_texture_object *texObj;
2470   struct gl_texture_image *texImage;
2471   GLboolean success = GL_FALSE;
2472   GLsizei postConvWidth, postConvHeight;
2473
2474   postConvWidth = width;
2475   postConvHeight = height;
2476   adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2477
2478   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2479                             postConvWidth, postConvHeight, 1, format, type)) {
2480      return;   /* error was detected */
2481   }
2482
2483   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2484   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2485   texImage = texObj->Image[level];
2486   assert(texImage);
2487
2488   if (width == 0 || height == 0 || !pixels)
2489      return;  /* no-op, not an error */
2490
2491   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2492      _mesa_update_image_transfer_state(ctx);
2493
2494   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
2495      success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2496                                     yoffset, width, height, format, type,
2497                                     pixels, &ctx->Unpack, texObj, texImage );
2498   }
2499   if (!success) {
2500      /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2501      const GLint texComps = components_in_intformat(texImage->Format);
2502      const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2503      GLboolean retain = GL_TRUE;
2504
2505      if (!texImage->Data) {
2506         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2507         if (!texImage->Data) {
2508            make_null_texture(texImage);
2509         }
2510         if (!texImage->Data)
2511            return;  /* we're really out of luck! */
2512      }
2513
2514      fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2515                         width, height, 1, xoffset, yoffset, 0,
2516                         texRowStride, 0,
2517                         format, type, pixels, &ctx->Unpack);
2518
2519      if (ctx->Driver.TexImage2D) {
2520         (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2521                                   GL_UNSIGNED_BYTE, texImage->Data,
2522                                   &_mesa_native_packing, texObj, texImage,
2523                                   &retain);
2524      }
2525
2526      if (!retain && texImage->Data) {
2527         FREE(texImage->Data);
2528         texImage->Data = NULL;
2529      }
2530
2531#ifdef OLD_DD_TEXTURE
2532      /* XXX this will be removed in the future */
2533      if (ctx->Driver.TexSubImage) {
2534         (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2535                                    xoffset, yoffset, width, height,
2536                                    texImage->IntFormat, texImage);
2537      }
2538      else if (ctx->Driver.TexImage) {
2539         (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2540                                 level, texImage->IntFormat, texImage );
2541      }
2542#endif
2543   }
2544}
2545
2546
2547
2548void
2549_mesa_TexSubImage3D( GLenum target, GLint level,
2550                     GLint xoffset, GLint yoffset, GLint zoffset,
2551                     GLsizei width, GLsizei height, GLsizei depth,
2552                     GLenum format, GLenum type,
2553                     const GLvoid *pixels )
2554{
2555   GET_CURRENT_CONTEXT(ctx);
2556   struct gl_texture_unit *texUnit;
2557   struct gl_texture_object *texObj;
2558   struct gl_texture_image *texImage;
2559   GLboolean success = GL_FALSE;
2560
2561   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2562                              width, height, depth, format, type)) {
2563      return;   /* error was detected */
2564   }
2565
2566   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2567   texObj = texUnit->CurrentD[3];
2568   texImage = texObj->Image[level];
2569   assert(texImage);
2570
2571   if (width == 0 || height == 0 || height == 0 || !pixels)
2572      return;  /* no-op, not an error */
2573
2574   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2575      _mesa_update_image_transfer_state(ctx);
2576
2577   if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
2578      success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2579                                yoffset, zoffset, width, height, depth, format,
2580                                type, pixels, &ctx->Unpack, texObj, texImage );
2581   }
2582   if (!success) {
2583      /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2584      const GLint texComps = components_in_intformat(texImage->Format);
2585      const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2586      const GLint texImgStride = texRowStride * texImage->Height;
2587      GLboolean retain = GL_TRUE;
2588
2589      if (!texImage->Data) {
2590         _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2591         if (!texImage->Data) {
2592            make_null_texture(texImage);
2593         }
2594         if (!texImage->Data)
2595            return;  /* we're really out of luck! */
2596      }
2597
2598      fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2599                         width, height, depth, xoffset, yoffset, zoffset,
2600                         texRowStride, texImgStride,
2601                         format, type, pixels, &ctx->Unpack);
2602
2603      if (ctx->Driver.TexImage3D) {
2604         (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2605                                   GL_UNSIGNED_BYTE, texImage->Data,
2606                                   &_mesa_native_packing, texObj, texImage,
2607                                   &retain);
2608      }
2609
2610      if (!retain && texImage->Data) {
2611         FREE(texImage->Data);
2612         texImage->Data = NULL;
2613      }
2614   }
2615}
2616
2617
2618
2619/*
2620 * Read an RGBA image from the frame buffer.
2621 * This is used by glCopyTex[Sub]Image[12]D().
2622 * Input:  ctx - the context
2623 *         x, y - lower left corner
2624 *         width, height - size of region to read
2625 * Return: pointer to block of GL_RGBA, GLubyte data.
2626 */
2627static GLubyte *
2628read_color_image( GLcontext *ctx, GLint x, GLint y,
2629                  GLsizei width, GLsizei height )
2630{
2631   GLint stride, i;
2632   GLubyte *image, *dst;
2633
2634   image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
2635   if (!image)
2636      return NULL;
2637
2638   /* Select buffer to read from */
2639   (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2640                                 ctx->Pixel.DriverReadBuffer );
2641
2642   dst = image;
2643   stride = width * 4 * sizeof(GLubyte);
2644   for (i = 0; i < height; i++) {
2645      gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2646                         (GLubyte (*)[4]) dst );
2647      dst += stride;
2648   }
2649
2650   /* Read from draw buffer (the default) */
2651   (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2652                                 ctx->Color.DriverDrawBuffer );
2653
2654   return image;
2655}
2656
2657
2658
2659void
2660_mesa_CopyTexImage1D( GLenum target, GLint level,
2661                      GLenum internalFormat,
2662                      GLint x, GLint y,
2663                      GLsizei width, GLint border )
2664{
2665   GET_CURRENT_CONTEXT(ctx);
2666   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2667
2668   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2669                               width, 1, border))
2670      return;
2671
2672   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2673      _mesa_update_image_transfer_state(ctx);
2674
2675   if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
2676       || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2677                         internalFormat, x, y, width, border)) {
2678      struct gl_pixelstore_attrib unpackSave;
2679
2680      /* get image from framebuffer */
2681      GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2682      if (!image) {
2683         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2684         return;
2685      }
2686
2687      /* call glTexImage1D to redefine the texture */
2688      unpackSave = ctx->Unpack;
2689      ctx->Unpack = _mesa_native_packing;
2690      (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2691                                border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2692      ctx->Unpack = unpackSave;
2693
2694      FREE(image);
2695   }
2696}
2697
2698
2699
2700void
2701_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2702                      GLint x, GLint y, GLsizei width, GLsizei height,
2703                      GLint border )
2704{
2705   GET_CURRENT_CONTEXT(ctx);
2706   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2707
2708   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2709                               width, height, border))
2710      return;
2711
2712   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2713      _mesa_update_image_transfer_state(ctx);
2714
2715   if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
2716       || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2717                         internalFormat, x, y, width, height, border)) {
2718      struct gl_pixelstore_attrib unpackSave;
2719
2720      /* get image from framebuffer */
2721      GLubyte *image = read_color_image( ctx, x, y, width, height );
2722      if (!image) {
2723         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2724         return;
2725      }
2726
2727      /* call glTexImage2D to redefine the texture */
2728      unpackSave = ctx->Unpack;
2729      ctx->Unpack = _mesa_native_packing;
2730      (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2731                      height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2732      ctx->Unpack = unpackSave;
2733
2734      FREE(image);
2735   }
2736}
2737
2738
2739
2740void
2741_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2742                         GLint xoffset, GLint x, GLint y, GLsizei width )
2743{
2744   GET_CURRENT_CONTEXT(ctx);
2745   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2746
2747   if (copytexsubimage_error_check(ctx, 1, target, level,
2748                                   xoffset, 0, 0, width, 1))
2749      return;
2750
2751   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2752      _mesa_update_image_transfer_state(ctx);
2753
2754   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2755       || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2756                                            xoffset, x, y, width)) {
2757      struct gl_texture_unit *texUnit;
2758      struct gl_texture_image *teximage;
2759      struct gl_pixelstore_attrib unpackSave;
2760      GLubyte *image;
2761
2762      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2763      teximage = texUnit->CurrentD[1]->Image[level];
2764      assert(teximage);
2765
2766      /* get image from frame buffer */
2767      image = read_color_image(ctx, x, y, width, 1);
2768      if (!image) {
2769         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2770         return;
2771      }
2772
2773      /* now call glTexSubImage1D to do the real work */
2774      unpackSave = ctx->Unpack;
2775      ctx->Unpack = _mesa_native_packing;
2776      _mesa_TexSubImage1D(target, level, xoffset, width,
2777                          GL_RGBA, GL_UNSIGNED_BYTE, image);
2778      ctx->Unpack = unpackSave;
2779
2780      FREE(image);
2781   }
2782}
2783
2784
2785
2786void
2787_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2788                         GLint xoffset, GLint yoffset,
2789                         GLint x, GLint y, GLsizei width, GLsizei height )
2790{
2791   GET_CURRENT_CONTEXT(ctx);
2792   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2793
2794   if (copytexsubimage_error_check(ctx, 2, target, level,
2795                                   xoffset, yoffset, 0, width, height))
2796      return;
2797
2798   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2799      _mesa_update_image_transfer_state(ctx);
2800
2801   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2802       || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2803                                xoffset, yoffset, x, y, width, height )) {
2804      struct gl_texture_unit *texUnit;
2805      struct gl_texture_image *teximage;
2806      struct gl_pixelstore_attrib unpackSave;
2807      GLubyte *image;
2808
2809      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2810      teximage = texUnit->CurrentD[2]->Image[level];
2811      assert(teximage);
2812
2813      /* get image from frame buffer */
2814      image = read_color_image(ctx, x, y, width, height);
2815      if (!image) {
2816         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2817         return;
2818      }
2819
2820      /* now call glTexSubImage2D to do the real work */
2821      unpackSave = ctx->Unpack;
2822      ctx->Unpack = _mesa_native_packing;
2823      _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2824                          GL_RGBA, GL_UNSIGNED_BYTE, image);
2825      ctx->Unpack = unpackSave;
2826
2827      FREE(image);
2828   }
2829}
2830
2831
2832
2833void
2834_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2835                         GLint xoffset, GLint yoffset, GLint zoffset,
2836                         GLint x, GLint y, GLsizei width, GLsizei height )
2837{
2838   GET_CURRENT_CONTEXT(ctx);
2839   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2840
2841   if (copytexsubimage_error_check(ctx, 3, target, level,
2842                    xoffset, yoffset, zoffset, width, height))
2843      return;
2844
2845   if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2846      _mesa_update_image_transfer_state(ctx);
2847
2848   if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2849       || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2850                     xoffset, yoffset, zoffset, x, y, width, height )) {
2851      struct gl_texture_unit *texUnit;
2852      struct gl_texture_image *teximage;
2853      struct gl_pixelstore_attrib unpackSave;
2854      GLubyte *image;
2855
2856      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2857      teximage = texUnit->CurrentD[3]->Image[level];
2858      assert(teximage);
2859
2860      /* get image from frame buffer */
2861      image = read_color_image(ctx, x, y, width, height);
2862      if (!image) {
2863         gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2864         return;
2865      }
2866
2867      /* now call glTexSubImage2D to do the real work */
2868      unpackSave = ctx->Unpack;
2869      ctx->Unpack = _mesa_native_packing;
2870      _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2871                          width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2872      ctx->Unpack = unpackSave;
2873
2874      FREE(image);
2875   }
2876}
2877
2878
2879
2880void
2881_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2882                              GLenum internalFormat, GLsizei width,
2883                              GLint border, GLsizei imageSize,
2884                              const GLvoid *data)
2885{
2886   GET_CURRENT_CONTEXT(ctx);
2887   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2888
2889   switch (internalFormat) {
2890      case GL_COMPRESSED_ALPHA_ARB:
2891      case GL_COMPRESSED_LUMINANCE_ARB:
2892      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2893      case GL_COMPRESSED_INTENSITY_ARB:
2894      case GL_COMPRESSED_RGB_ARB:
2895      case GL_COMPRESSED_RGBA_ARB:
2896         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2897         return;
2898      default:
2899         /* silence compiler warning */
2900         ;
2901   }
2902
2903   if (target == GL_TEXTURE_1D) {
2904      struct gl_texture_unit *texUnit;
2905      struct gl_texture_object *texObj;
2906      struct gl_texture_image *texImage;
2907      GLsizei computedImageSize;
2908
2909      if (texture_error_check(ctx, target, level, internalFormat,
2910                              GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2911         return;   /* error in texture image was detected */
2912      }
2913
2914      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2915      texObj = texUnit->CurrentD[1];
2916      texImage = texObj->Image[level];
2917
2918      if (!texImage) {
2919         texImage = _mesa_alloc_texture_image();
2920         texObj->Image[level] = texImage;
2921         if (!texImage) {
2922            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2923            return;
2924         }
2925      }
2926      else if (texImage->Data) {
2927         FREE(texImage->Data);
2928         texImage->Data = NULL;
2929      }
2930
2931      /* setup the teximage struct's fields */
2932      init_texture_image(ctx, texImage, width, 1, 1,
2933                         border, internalFormat);
2934
2935      /* process the texture image */
2936      if (data) {
2937         GLboolean retain = GL_TRUE;
2938         GLboolean success = GL_FALSE;
2939         if (ctx->Driver.CompressedTexImage1D) {
2940            success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2941                               imageSize, data, texObj, texImage, &retain);
2942         }
2943         if (retain || !success) {
2944            /* make internal copy of the texture image */
2945            computedImageSize = _mesa_compressed_image_size(ctx,
2946                                                        internalFormat,
2947                                                        1,    /* num dims */
2948                                                        width,
2949                                                        1,    /* height   */
2950                                                        1);   /* depth    */
2951            if (computedImageSize != imageSize) {
2952                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2953                return;
2954            }
2955            texImage->Data = MALLOC(computedImageSize);
2956            if (texImage->Data) {
2957               MEMCPY(texImage->Data, data, computedImageSize);
2958            }
2959         }
2960         if (!retain && texImage->Data) {
2961            FREE(texImage->Data);
2962            texImage->Data = NULL;
2963         }
2964      }
2965      else {
2966         make_null_texture(texImage);
2967         if (ctx->Driver.CompressedTexImage1D) {
2968            GLboolean retain;
2969            (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2970                                                texImage->Data, texObj,
2971                                                texImage, &retain);
2972         }
2973      }
2974
2975      /* state update */
2976      gl_put_texobj_on_dirty_list( ctx, texObj );
2977      ctx->NewState |= NEW_TEXTURING;
2978   }
2979   else if (target == GL_PROXY_TEXTURE_1D) {
2980      /* Proxy texture: check for errors and update proxy state */
2981      GLenum error = texture_error_check(ctx, target, level, internalFormat,
2982                                    GL_NONE, GL_NONE, 1, width, 1, 1, border);
2983      if (!error && ctx->Driver.TestProxyTexImage) {
2984         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2985                                             internalFormat, GL_NONE, GL_NONE,
2986                                             width, 1, 1, border);
2987      }
2988      if (error) {
2989         /* if error, clear all proxy texture image parameters */
2990         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2991            clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
2992         }
2993      }
2994      else {
2995         /* if no error, update proxy texture image parameters */
2996         init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
2997                            width, 1, 1, border, internalFormat);
2998      }
2999   }
3000   else {
3001      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
3002      return;
3003   }
3004}
3005
3006
3007void
3008_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3009                              GLenum internalFormat, GLsizei width,
3010                              GLsizei height, GLint border, GLsizei imageSize,
3011                              const GLvoid *data)
3012{
3013   GET_CURRENT_CONTEXT(ctx);
3014   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
3015
3016   switch (internalFormat) {
3017      case GL_COMPRESSED_ALPHA_ARB:
3018      case GL_COMPRESSED_LUMINANCE_ARB:
3019      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3020      case GL_COMPRESSED_INTENSITY_ARB:
3021      case GL_COMPRESSED_RGB_ARB:
3022      case GL_COMPRESSED_RGBA_ARB:
3023         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
3024         return;
3025      default:
3026         /* silence compiler warning */
3027         ;
3028   }
3029
3030   if (target==GL_TEXTURE_2D ||
3031       (ctx->Extensions.HaveTextureCubeMap &&
3032        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3033        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3034      struct gl_texture_unit *texUnit;
3035      struct gl_texture_object *texObj;
3036      struct gl_texture_image *texImage;
3037      GLsizei computedImageSize;
3038
3039      if (texture_error_check(ctx, target, level, internalFormat,
3040                              GL_NONE, GL_NONE, 1, width, height, 1, border)) {
3041         return;   /* error in texture image was detected */
3042      }
3043
3044      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3045      texObj = texUnit->CurrentD[2];
3046      texImage = texObj->Image[level];
3047
3048      if (!texImage) {
3049         texImage = _mesa_alloc_texture_image();
3050         texObj->Image[level] = texImage;
3051         if (!texImage) {
3052            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3053            return;
3054         }
3055      }
3056      else if (texImage->Data) {
3057         FREE(texImage->Data);
3058         texImage->Data = NULL;
3059      }
3060
3061      /* setup the teximage struct's fields */
3062      init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
3063
3064      /* process the texture image */
3065      if (data) {
3066         GLboolean retain = GL_TRUE;
3067         GLboolean success = GL_FALSE;
3068         if (ctx->Driver.CompressedTexImage2D) {
3069            success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3070                                                           target,
3071                                                           level,
3072                                                           imageSize,
3073                                                           data,
3074                                                           texObj,
3075                                                           texImage,
3076                                                           &retain);
3077         }
3078         if (retain || !success) {
3079            /* make internal copy of the texture image */
3080            computedImageSize = _mesa_compressed_image_size(ctx,
3081                                                           internalFormat,
3082                                                           2,    /* num dims */
3083                                                           width,
3084                                                           height,
3085                                                           1);   /* depth    */
3086            if (computedImageSize != imageSize) {
3087                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3088                return;
3089            }
3090            texImage->Data = MALLOC(computedImageSize);
3091            if (texImage->Data) {
3092               MEMCPY(texImage->Data, data, computedImageSize);
3093            }
3094         }
3095         if (!retain && texImage->Data) {
3096            FREE(texImage->Data);
3097            texImage->Data = NULL;
3098         }
3099      }
3100      else {
3101         make_null_texture(texImage);
3102         if (ctx->Driver.CompressedTexImage2D) {
3103            GLboolean retain;
3104            (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3105                                                 texImage->Data, texObj,
3106                                                 texImage, &retain);
3107         }
3108      }
3109
3110      /* state update */
3111      gl_put_texobj_on_dirty_list( ctx, texObj );
3112      ctx->NewState |= NEW_TEXTURING;
3113   }
3114   else if (target == GL_PROXY_TEXTURE_2D) {
3115      /* Proxy texture: check for errors and update proxy state */
3116      GLenum error = texture_error_check(ctx, target, level, internalFormat,
3117                                GL_NONE, GL_NONE, 2, width, height, 1, border);
3118      if (!error && ctx->Driver.TestProxyTexImage) {
3119         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3120                                              internalFormat, GL_NONE, GL_NONE,
3121                                              width, height, 1, border);
3122      }
3123      if (error) {
3124         /* if error, clear all proxy texture image parameters */
3125         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3126            clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
3127         }
3128      }
3129      else {
3130         /* if no error, update proxy texture image parameters */
3131         init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
3132                            width, 1, 1, border, internalFormat);
3133      }
3134   }
3135   else {
3136      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3137      return;
3138   }
3139}
3140
3141
3142void
3143_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3144                              GLenum internalFormat, GLsizei width,
3145                              GLsizei height, GLsizei depth, GLint border,
3146                              GLsizei imageSize, const GLvoid *data)
3147{
3148   GET_CURRENT_CONTEXT(ctx);
3149   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3150
3151   switch (internalFormat) {
3152      case GL_COMPRESSED_ALPHA_ARB:
3153      case GL_COMPRESSED_LUMINANCE_ARB:
3154      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3155      case GL_COMPRESSED_INTENSITY_ARB:
3156      case GL_COMPRESSED_RGB_ARB:
3157      case GL_COMPRESSED_RGBA_ARB:
3158         gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3159         return;
3160      default:
3161         /* silence compiler warning */
3162         ;
3163   }
3164
3165   if (target == GL_TEXTURE_3D) {
3166      struct gl_texture_unit *texUnit;
3167      struct gl_texture_object *texObj;
3168      struct gl_texture_image *texImage;
3169      GLsizei computedImageSize;
3170
3171      if (texture_error_check(ctx, target, level, internalFormat,
3172                          GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3173         return;   /* error in texture image was detected */
3174      }
3175
3176      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3177      texObj = texUnit->CurrentD[3];
3178      texImage = texObj->Image[level];
3179
3180      if (!texImage) {
3181         texImage = _mesa_alloc_texture_image();
3182         texObj->Image[level] = texImage;
3183         if (!texImage) {
3184            gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3185            return;
3186         }
3187      }
3188      else if (texImage->Data) {
3189         FREE(texImage->Data);
3190         texImage->Data = NULL;
3191      }
3192
3193      /* setup the teximage struct's fields */
3194      init_texture_image(ctx, texImage, width, height, depth,
3195                         border, internalFormat);
3196
3197      /* process the texture image */
3198      if (data) {
3199         GLboolean retain = GL_TRUE;
3200         GLboolean success = GL_FALSE;
3201         if (ctx->Driver.CompressedTexImage3D) {
3202            success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3203                                                          imageSize, data,
3204                                                          texObj, texImage,
3205                                                          &retain);
3206         }
3207         if (retain || !success) {
3208            /* make internal copy of the texture image */
3209            computedImageSize = _mesa_compressed_image_size(ctx,
3210                                                            internalFormat,
3211                                                            3,  /* num dims */
3212                                                            width,
3213                                                            height,
3214                                                            depth);
3215            if (computedImageSize != imageSize) {
3216                gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3217                return;
3218            }
3219            texImage->Data = MALLOC(computedImageSize);
3220            if (texImage->Data) {
3221               MEMCPY(texImage->Data, data, computedImageSize);
3222            }
3223         }
3224         if (!retain && texImage->Data) {
3225            FREE(texImage->Data);
3226            texImage->Data = NULL;
3227         }
3228      }
3229      else {
3230         make_null_texture(texImage);
3231         if (ctx->Driver.CompressedTexImage3D) {
3232            GLboolean retain;
3233            (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3234                                                 texImage->Data, texObj,
3235                                                 texImage, &retain);
3236         }
3237      }
3238
3239      /* state update */
3240      gl_put_texobj_on_dirty_list( ctx, texObj );
3241      ctx->NewState |= NEW_TEXTURING;
3242   }
3243   else if (target == GL_PROXY_TEXTURE_3D) {
3244      /* Proxy texture: check for errors and update proxy state */
3245      GLenum error = texture_error_check(ctx, target, level, internalFormat,
3246                            GL_NONE, GL_NONE, 1, width, height, depth, border);
3247      if (!error && ctx->Driver.TestProxyTexImage) {
3248         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3249                                             internalFormat, GL_NONE, GL_NONE,
3250                                             width, height, depth, border);
3251      }
3252      if (error) {
3253         /* if error, clear all proxy texture image parameters */
3254         if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3255            clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
3256         }
3257      }
3258      else {
3259         /* if no error, update proxy texture image parameters */
3260         init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3261                            width, 1, 1, border, internalFormat);
3262      }
3263   }
3264   else {
3265      gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3266      return;
3267   }
3268}
3269
3270
3271void
3272_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3273                                 GLsizei width, GLenum format,
3274                                 GLsizei imageSize, const GLvoid *data)
3275{
3276   GET_CURRENT_CONTEXT(ctx);
3277   struct gl_texture_unit *texUnit;
3278   struct gl_texture_object *texObj;
3279   struct gl_texture_image *texImage;
3280   GLboolean success = GL_FALSE;
3281
3282   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3283                              width, 1, 1, format, GL_NONE)) {
3284      return;   /* error was detected */
3285   }
3286
3287   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3288   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3289   texImage = texObj->Image[level];
3290   assert(texImage);
3291
3292   if (width == 0 || !data)
3293      return;  /* no-op, not an error */
3294
3295   if (ctx->Driver.CompressedTexSubImage1D) {
3296      success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3297                   xoffset, width, format, imageSize, data, texObj, texImage);
3298   }
3299   if (!success) {
3300      /* XXX what else can we do? */
3301      gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3302      return;
3303   }
3304}
3305
3306
3307void
3308_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3309                                 GLint yoffset, GLsizei width, GLsizei height,
3310                                 GLenum format, GLsizei imageSize,
3311                                 const GLvoid *data)
3312{
3313   GET_CURRENT_CONTEXT(ctx);
3314   struct gl_texture_unit *texUnit;
3315   struct gl_texture_object *texObj;
3316   struct gl_texture_image *texImage;
3317   GLboolean success = GL_FALSE;
3318
3319   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3320                              width, height, 1, format, GL_NONE)) {
3321      return;   /* error was detected */
3322   }
3323
3324   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3325   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3326   texImage = texObj->Image[level];
3327   assert(texImage);
3328
3329   if (width == 0 || height == 0 || !data)
3330      return;  /* no-op, not an error */
3331
3332   if (ctx->Driver.CompressedTexSubImage2D) {
3333      success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3334                                       xoffset, yoffset, width, height, format,
3335                                       imageSize, data, texObj, texImage);
3336   }
3337   if (!success) {
3338      /* XXX what else can we do? */
3339      gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3340      return;
3341   }
3342}
3343
3344
3345void
3346_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3347                                 GLint yoffset, GLint zoffset, GLsizei width,
3348                                 GLsizei height, GLsizei depth, GLenum format,
3349                                 GLsizei imageSize, const GLvoid *data)
3350{
3351   GET_CURRENT_CONTEXT(ctx);
3352   struct gl_texture_unit *texUnit;
3353   struct gl_texture_object *texObj;
3354   struct gl_texture_image *texImage;
3355   GLboolean success = GL_FALSE;
3356
3357   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3358                              width, height, depth, format, GL_NONE)) {
3359      return;   /* error was detected */
3360   }
3361
3362   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3363   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3364   texImage = texObj->Image[level];
3365   assert(texImage);
3366
3367   if (width == 0 || height == 0 || depth == 0 || !data)
3368      return;  /* no-op, not an error */
3369
3370   if (ctx->Driver.CompressedTexSubImage3D) {
3371      success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3372                               xoffset, yoffset, zoffset, width, height, depth,
3373                               format, imageSize, data, texObj, texImage);
3374   }
3375   if (!success) {
3376      /* XXX what else can we do? */
3377      gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3378      return;
3379   }
3380}
3381
3382
3383void
3384_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3385{
3386   GET_CURRENT_CONTEXT(ctx);
3387   const struct gl_texture_object *texObj;
3388   struct gl_texture_image *texImage;
3389
3390   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3391
3392   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3393      gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3394      return;
3395   }
3396
3397   switch (target) {
3398      case GL_TEXTURE_1D:
3399         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3400         texImage = texObj->Image[level];
3401         break;
3402      case GL_TEXTURE_2D:
3403         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3404         texImage = texObj->Image[level];
3405         break;
3406      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3407         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3408         texImage = texObj->Image[level];
3409         break;
3410      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3411         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3412         texImage = texObj->NegX[level];
3413         break;
3414      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3415         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3416         texImage = texObj->PosY[level];
3417         break;
3418      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3419         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3420         texImage = texObj->NegY[level];
3421         break;
3422      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3423         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3424         texImage = texObj->PosZ[level];
3425         break;
3426      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3427         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3428         texImage = texObj->NegZ[level];
3429         break;
3430      case GL_TEXTURE_3D:
3431         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3432         texImage = texObj->Image[level];
3433         break;
3434      default:
3435         gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3436         return;
3437   }
3438
3439   if (!texImage) {
3440      /* invalid mipmap level */
3441      gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3442      return;
3443   }
3444
3445   if (!texImage->IsCompressed) {
3446      gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3447      return;
3448   }
3449
3450   if (!img)
3451      return;
3452
3453   if (ctx->Driver.GetCompressedTexImage) {
3454      (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3455                                           texImage);
3456   }
3457   else {
3458      gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3459   }
3460}
3461