Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: teximage.c,v 1.1 2003-02-28 11:42:05 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  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
#include "glheader.h"
28
#include "context.h"
29
#include "convolve.h"
30
#include "image.h"
31
#include "imports.h"
32
#include "macros.h"
33
#include "mmath.h"
34
#include "state.h"
35
#include "texcompress.h"
36
#include "texformat.h"
37
#include "teximage.h"
38
#include "texstate.h"
39
#include "texstore.h"
40
#include "mtypes.h"
41
 
42
 
43
/*
44
 * NOTES:
45
 *
46
 * Mesa's native texture datatype is GLchan.  Native formats are
47
 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
48
 * and GL_COLOR_INDEX.
49
 * Device drivers are free to implement any internal format they want.
50
 */
51
 
52
 
53
#if 0
54
static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
55
{
56
#if CHAN_TYPE == GL_FLOAT
57
   _mesa_problem(NULL, "PrintTexture doesn't support float channels");
58
#else
59
   GLuint i, j, c;
60
   const GLchan *data = (const GLchan *) img->Data;
61
 
62
   if (!data) {
63
      _mesa_printf("No texture data\n");
64
      return;
65
   }
66
 
67
   switch (img->Format) {
68
      case GL_ALPHA:
69
      case GL_LUMINANCE:
70
      case GL_INTENSITY:
71
      case GL_COLOR_INDEX:
72
         c = 1;
73
         break;
74
      case GL_LUMINANCE_ALPHA:
75
         c = 2;
76
         break;
77
      case GL_RGB:
78
         c = 3;
79
         break;
80
      case GL_RGBA:
81
         c = 4;
82
         break;
83
      default:
84
         _mesa_problem(NULL, "error in PrintTexture\n");
85
         return;
86
   }
87
 
88
   for (i = 0; i < img->Height; i++) {
89
      for (j = 0; j < img->Width; j++) {
90
         if (c==1)
91
            _mesa_printf("%02x  ", data[0]);
92
         else if (c==2)
93
            _mesa_printf("%02x%02x  ", data[0], data[1]);
94
         else if (c==3)
95
            _mesa_printf("%02x%02x%02x  ", data[0], data[1], data[2]);
96
         else if (c==4)
97
            _mesa_printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
98
         data += (img->RowStride - img->Width) * c;
99
      }
100
      _mesa_printf("\n");
101
   }
102
#endif
103
}
104
#endif
105
 
106
 
107
 
108
/*
109
 * Compute log base 2 of n.
110
 * If n isn't an exact power of two return -1.
111
 * If n < 0 return -1.
112
 */
113
static int
114
logbase2( int n )
115
{
116
   GLint i = 1;
117
   GLint log2 = 0;
118
 
119
   if (n < 0) {
120
      return -1;
121
   }
122
 
123
   while ( n > i ) {
124
      i *= 2;
125
      log2++;
126
   }
127
   if (i != n) {
128
      return -1;
129
   }
130
   else {
131
      return log2;
132
   }
133
}
134
 
135
 
136
 
137
/*
138
 * Given an internal texture format enum or 1, 2, 3, 4 return the
139
 * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
140
 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
141
 *
142
 * This is the format which is used during texture application (i.e. the
143
 * texture format and env mode determine the arithmetic used.
144
 *
145
 * Return -1 if invalid enum.
146
 */
147
GLint
148
_mesa_base_tex_format( GLcontext *ctx, GLint format )
149
{
150
   /*
151
    * Ask the driver for the base format, if it doesn't
152
    * know, it will return -1;
153
    */
154
   switch (format) {
155
      case GL_ALPHA:
156
      case GL_ALPHA4:
157
      case GL_ALPHA8:
158
      case GL_ALPHA12:
159
      case GL_ALPHA16:
160
         return GL_ALPHA;
161
      case 1:
162
      case GL_LUMINANCE:
163
      case GL_LUMINANCE4:
164
      case GL_LUMINANCE8:
165
      case GL_LUMINANCE12:
166
      case GL_LUMINANCE16:
167
         return GL_LUMINANCE;
168
      case 2:
169
      case GL_LUMINANCE_ALPHA:
170
      case GL_LUMINANCE4_ALPHA4:
171
      case GL_LUMINANCE6_ALPHA2:
172
      case GL_LUMINANCE8_ALPHA8:
173
      case GL_LUMINANCE12_ALPHA4:
174
      case GL_LUMINANCE12_ALPHA12:
175
      case GL_LUMINANCE16_ALPHA16:
176
         return GL_LUMINANCE_ALPHA;
177
      case GL_INTENSITY:
178
      case GL_INTENSITY4:
179
      case GL_INTENSITY8:
180
      case GL_INTENSITY12:
181
      case GL_INTENSITY16:
182
         return GL_INTENSITY;
183
      case 3:
184
      case GL_RGB:
185
      case GL_R3_G3_B2:
186
      case GL_RGB4:
187
      case GL_RGB5:
188
      case GL_RGB8:
189
      case GL_RGB10:
190
      case GL_RGB12:
191
      case GL_RGB16:
192
         return GL_RGB;
193
      case 4:
194
      case GL_RGBA:
195
      case GL_RGBA2:
196
      case GL_RGBA4:
197
      case GL_RGB5_A1:
198
      case GL_RGBA8:
199
      case GL_RGB10_A2:
200
      case GL_RGBA12:
201
      case GL_RGBA16:
202
         return GL_RGBA;
203
      case GL_COLOR_INDEX:
204
      case GL_COLOR_INDEX1_EXT:
205
      case GL_COLOR_INDEX2_EXT:
206
      case GL_COLOR_INDEX4_EXT:
207
      case GL_COLOR_INDEX8_EXT:
208
      case GL_COLOR_INDEX12_EXT:
209
      case GL_COLOR_INDEX16_EXT:
210
         if (ctx->Extensions.EXT_paletted_texture)
211
            return GL_COLOR_INDEX;
212
         else
213
            return -1;
214
      case GL_DEPTH_COMPONENT:
215
      case GL_DEPTH_COMPONENT16_SGIX:
216
      case GL_DEPTH_COMPONENT24_SGIX:
217
      case GL_DEPTH_COMPONENT32_SGIX:
218
         if (ctx->Extensions.SGIX_depth_texture)
219
            return GL_DEPTH_COMPONENT;
220
         else
221
            return -1;
222
 
223
      /* GL_ARB_texture_compression */
224
      case GL_COMPRESSED_ALPHA:
225
         if (ctx->Extensions.ARB_texture_compression)
226
            return GL_ALPHA;
227
         else
228
            return -1;
229
      case GL_COMPRESSED_LUMINANCE:
230
         if (ctx->Extensions.ARB_texture_compression)
231
            return GL_LUMINANCE;
232
         else
233
            return -1;
234
      case GL_COMPRESSED_LUMINANCE_ALPHA:
235
         if (ctx->Extensions.ARB_texture_compression)
236
            return GL_LUMINANCE_ALPHA;
237
         else
238
            return -1;
239
      case GL_COMPRESSED_INTENSITY:
240
         if (ctx->Extensions.ARB_texture_compression)
241
            return GL_INTENSITY;
242
         else
243
            return -1;
244
      case GL_COMPRESSED_RGB:
245
         if (ctx->Extensions.ARB_texture_compression)
246
            return GL_RGB;
247
         else
248
            return -1;
249
      case GL_COMPRESSED_RGBA:
250
         if (ctx->Extensions.ARB_texture_compression)
251
            return GL_RGBA;
252
         else
253
            return -1;
254
      case GL_COMPRESSED_RGB_FXT1_3DFX:
255
         if (ctx->Extensions.TDFX_texture_compression_FXT1)
256
            return GL_RGB;
257
         else
258
            return -1;
259
      case GL_COMPRESSED_RGBA_FXT1_3DFX:
260
         if (ctx->Extensions.TDFX_texture_compression_FXT1)
261
            return GL_RGBA;
262
         else
263
            return -1;
264
 
265
      case GL_YCBCR_MESA:
266
         if (ctx->Extensions.MESA_ycbcr_texture)
267
            return GL_YCBCR_MESA;
268
         else
269
            return -1;
270
 
271
      default:
272
         return -1;  /* error */
273
   }
274
}
275
 
276
 
277
/*
278
 * Test if the given image format is a color/rgba format.  That is,
279
 * not color index, depth, stencil, etc.
280
 */
281
static GLboolean
282
is_color_format(GLenum format)
283
{
284
   switch (format) {
285
      case GL_ALPHA:
286
      case GL_ALPHA4:
287
      case GL_ALPHA8:
288
      case GL_ALPHA12:
289
      case GL_ALPHA16:
290
      case 1:
291
      case GL_LUMINANCE:
292
      case GL_LUMINANCE4:
293
      case GL_LUMINANCE8:
294
      case GL_LUMINANCE12:
295
      case GL_LUMINANCE16:
296
      case 2:
297
      case GL_LUMINANCE_ALPHA:
298
      case GL_LUMINANCE4_ALPHA4:
299
      case GL_LUMINANCE6_ALPHA2:
300
      case GL_LUMINANCE8_ALPHA8:
301
      case GL_LUMINANCE12_ALPHA4:
302
      case GL_LUMINANCE12_ALPHA12:
303
      case GL_LUMINANCE16_ALPHA16:
304
      case GL_INTENSITY:
305
      case GL_INTENSITY4:
306
      case GL_INTENSITY8:
307
      case GL_INTENSITY12:
308
      case GL_INTENSITY16:
309
      case 3:
310
      case GL_RGB:
311
      case GL_R3_G3_B2:
312
      case GL_RGB4:
313
      case GL_RGB5:
314
      case GL_RGB8:
315
      case GL_RGB10:
316
      case GL_RGB12:
317
      case GL_RGB16:
318
      case 4:
319
      case GL_RGBA:
320
      case GL_RGBA2:
321
      case GL_RGBA4:
322
      case GL_RGB5_A1:
323
      case GL_RGBA8:
324
      case GL_RGB10_A2:
325
      case GL_RGBA12:
326
      case GL_RGBA16:
327
         return GL_TRUE;
328
      case GL_YCBCR_MESA:  /* not considered to be RGB */
329
      default:
330
         return GL_FALSE;
331
   }
332
}
333
 
334
 
335
static GLboolean
336
is_index_format(GLenum format)
337
{
338
   switch (format) {
339
      case GL_COLOR_INDEX:
340
      case GL_COLOR_INDEX1_EXT:
341
      case GL_COLOR_INDEX2_EXT:
342
      case GL_COLOR_INDEX4_EXT:
343
      case GL_COLOR_INDEX8_EXT:
344
      case GL_COLOR_INDEX12_EXT:
345
      case GL_COLOR_INDEX16_EXT:
346
         return GL_TRUE;
347
      default:
348
         return GL_FALSE;
349
   }
350
}
351
 
352
 
353
/**
354
 * Return GL_TRUE if internalFormat is a supported compressed format,
355
 * return GL_FALSE otherwise.
356
 * \param - internalFormat - the internal format token provided by the user
357
 */
358
static GLboolean
359
is_compressed_format(GLenum internalFormat)
360
{
361
   switch (internalFormat) {
362
      case GL_COMPRESSED_RGB_FXT1_3DFX:
363
      case GL_COMPRESSED_RGBA_FXT1_3DFX:
364
         return GL_TRUE;
365
      default:
366
         return GL_FALSE;
367
   }
368
}
369
 
370
 
371
/*
372
 * Store a gl_texture_image pointer in a gl_texture_object structure
373
 * according to the target and level parameters.
374
 * This was basically prompted by the introduction of cube maps.
375
 */
376
void
377
_mesa_set_tex_image(struct gl_texture_object *tObj,
378
                    GLenum target, GLint level,
379
                    struct gl_texture_image *texImage)
380
{
381
   ASSERT(tObj);
382
   ASSERT(texImage);
383
   switch (target) {
384
      case GL_TEXTURE_1D:
385
      case GL_TEXTURE_2D:
386
      case GL_TEXTURE_3D:
387
         tObj->Image[level] = texImage;
388
         return;
389
      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
390
         tObj->Image[level] = texImage;
391
         return;
392
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
393
         tObj->NegX[level] = texImage;
394
         return;
395
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
396
         tObj->PosY[level] = texImage;
397
         return;
398
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
399
         tObj->NegY[level] = texImage;
400
         return;
401
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
402
         tObj->PosZ[level] = texImage;
403
         return;
404
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
405
         tObj->NegZ[level] = texImage;
406
         return;
407
      case GL_TEXTURE_RECTANGLE_NV:
408
         ASSERT(level == 0);
409
         tObj->Image[level] = texImage;
410
         return;
411
      default:
412
         _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
413
         return;
414
   }
415
}
416
 
417
 
418
 
419
/*
420
 * Return new gl_texture_image struct with all fields initialized to zero.
421
 */
422
struct gl_texture_image *
423
_mesa_alloc_texture_image( void )
424
{
425
   return CALLOC_STRUCT(gl_texture_image);
426
}
427
 
428
 
429
 
430
void
431
_mesa_free_texture_image( struct gl_texture_image *teximage )
432
{
433
   if (teximage->Data && !teximage->IsClientData) {
434
      MESA_PBUFFER_FREE( teximage->Data );
435
      teximage->Data = NULL;
436
   }
437
   FREE( teximage );
438
}
439
 
440
 
441
/*
442
 * Return GL_TRUE if the target is a proxy target.
443
 */
444
static GLboolean
445
is_proxy_target(GLenum target)
446
{
447
   return (target == GL_PROXY_TEXTURE_1D ||
448
           target == GL_PROXY_TEXTURE_2D ||
449
           target == GL_PROXY_TEXTURE_3D ||
450
           target == GL_PROXY_TEXTURE_CUBE_MAP_ARB);
451
}
452
 
453
 
454
/*
455
 * Given a texture unit and a texture target, return the corresponding
456
 * texture object.
457
 */
458
struct gl_texture_object *
459
_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
460
                        GLenum target)
461
{
462
   switch (target) {
463
      case GL_TEXTURE_1D:
464
         return texUnit->Current1D;
465
      case GL_PROXY_TEXTURE_1D:
466
         return ctx->Texture.Proxy1D;
467
      case GL_TEXTURE_2D:
468
         return texUnit->Current2D;
469
      case GL_PROXY_TEXTURE_2D:
470
         return ctx->Texture.Proxy2D;
471
      case GL_TEXTURE_3D:
472
         return texUnit->Current3D;
473
      case GL_PROXY_TEXTURE_3D:
474
         return ctx->Texture.Proxy3D;
475
      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
476
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
477
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
478
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
479
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
480
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
481
      case GL_TEXTURE_CUBE_MAP_ARB:
482
         return ctx->Extensions.ARB_texture_cube_map
483
                ? texUnit->CurrentCubeMap : NULL;
484
      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
485
         return ctx->Extensions.ARB_texture_cube_map
486
                ? ctx->Texture.ProxyCubeMap : NULL;
487
      case GL_TEXTURE_RECTANGLE_NV:
488
         return ctx->Extensions.NV_texture_rectangle
489
                ? texUnit->CurrentRect : NULL;
490
      case GL_PROXY_TEXTURE_RECTANGLE_NV:
491
         return ctx->Extensions.NV_texture_rectangle
492
                ? ctx->Texture.ProxyRect : NULL;
493
      default:
494
         _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
495
         return NULL;
496
   }
497
}
498
 
499
 
500
/*
501
 * Return the texture image struct which corresponds to target and level
502
 * for the given texture unit.
503
 */
504
struct gl_texture_image *
505
_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
506
                       GLenum target, GLint level)
507
{
508
   ASSERT(texUnit);
509
   ASSERT(level < MAX_TEXTURE_LEVELS);
510
   switch (target) {
511
      case GL_TEXTURE_1D:
512
         return texUnit->Current1D->Image[level];
513
      case GL_PROXY_TEXTURE_1D:
514
         return ctx->Texture.Proxy1D->Image[level];
515
      case GL_TEXTURE_2D:
516
         return texUnit->Current2D->Image[level];
517
      case GL_PROXY_TEXTURE_2D:
518
         return ctx->Texture.Proxy2D->Image[level];
519
      case GL_TEXTURE_3D:
520
         return texUnit->Current3D->Image[level];
521
      case GL_PROXY_TEXTURE_3D:
522
         return ctx->Texture.Proxy3D->Image[level];
523
      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
524
         if (ctx->Extensions.ARB_texture_cube_map)
525
            return texUnit->CurrentCubeMap->Image[level];
526
         else
527
            return NULL;
528
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
529
         if (ctx->Extensions.ARB_texture_cube_map)
530
            return texUnit->CurrentCubeMap->NegX[level];
531
         else
532
            return NULL;
533
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
534
         if (ctx->Extensions.ARB_texture_cube_map)
535
            return texUnit->CurrentCubeMap->PosY[level];
536
         else
537
            return NULL;
538
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
539
         if (ctx->Extensions.ARB_texture_cube_map)
540
            return texUnit->CurrentCubeMap->NegY[level];
541
         else
542
            return NULL;
543
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
544
         if (ctx->Extensions.ARB_texture_cube_map)
545
            return texUnit->CurrentCubeMap->PosZ[level];
546
         else
547
            return NULL;
548
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
549
         if (ctx->Extensions.ARB_texture_cube_map)
550
            return texUnit->CurrentCubeMap->NegZ[level];
551
         else
552
            return NULL;
553
      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
554
         if (ctx->Extensions.ARB_texture_cube_map)
555
            return ctx->Texture.ProxyCubeMap->Image[level];
556
         else
557
            return NULL;
558
      case GL_TEXTURE_RECTANGLE_NV:
559
         if (ctx->Extensions.NV_texture_rectangle) {
560
            ASSERT(level == 0);
561
            return texUnit->CurrentRect->Image[level];
562
         }
563
         else {
564
            return NULL;
565
         }
566
      case GL_PROXY_TEXTURE_RECTANGLE_NV:
567
         if (ctx->Extensions.NV_texture_rectangle) {
568
            ASSERT(level == 0);
569
            return ctx->Texture.ProxyRect->Image[level];
570
         }
571
         else {
572
            return NULL;
573
         }
574
      default:
575
         _mesa_problem(ctx, "bad target in _mesa_select_tex_image()");
576
         return NULL;
577
   }
578
}
579
 
580
 
581
/*
582
 * Return the maximum number of allows mipmap levels for the given
583
 * texture target.
584
 */
585
GLint
586
_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
587
{
588
   switch (target) {
589
   case GL_TEXTURE_1D:
590
   case GL_PROXY_TEXTURE_1D:
591
   case GL_TEXTURE_2D:
592
   case GL_PROXY_TEXTURE_2D:
593
      return ctx->Const.MaxTextureLevels;
594
   case GL_TEXTURE_3D:
595
   case GL_PROXY_TEXTURE_3D:
596
      return ctx->Const.Max3DTextureLevels;
597
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
598
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
599
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
600
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
601
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
602
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
603
   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
604
      return ctx->Const.MaxCubeTextureLevels;
605
      break;
606
   case GL_TEXTURE_RECTANGLE_NV:
607
   case GL_PROXY_TEXTURE_RECTANGLE_NV:
608
      return 1;
609
      break;
610
   default:
611
      return 0; /* bad target */
612
   }
613
}
614
 
615
 
616
 
617
#if 000 /* not used anymore */
618
/*
619
 * glTexImage[123]D can accept a NULL image pointer.  In this case we
620
 * create a texture image with unspecified image contents per the OpenGL
621
 * spec.
622
 */
623
static GLubyte *
624
make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
625
{
626
   const GLint components = _mesa_components_in_format(format);
627
   const GLint numPixels = width * height * depth;
628
   GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
629
 
630
#ifdef DEBUG
631
   /*
632
    * Let's see if anyone finds this.  If glTexImage2D() is called with
633
    * a NULL image pointer then load the texture image with something
634
    * interesting instead of leaving it indeterminate.
635
    */
636
   if (data) {
637
      static const char message[8][32] = {
638
         "   X   X  XXXXX   XXX     X    ",
639
         "   XX XX  X      X   X   X X   ",
640
         "   X X X  X      X      X   X  ",
641
         "   X   X  XXXX    XXX   XXXXX  ",
642
         "   X   X  X          X  X   X  ",
643
         "   X   X  X      X   X  X   X  ",
644
         "   X   X  XXXXX   XXX   X   X  ",
645
         "                               "
646
      };
647
 
648
      GLubyte *imgPtr = data;
649
      GLint h, i, j, k;
650
      for (h = 0; h < depth; h++) {
651
         for (i = 0; i < height; i++) {
652
            GLint srcRow = 7 - (i % 8);
653
            for (j = 0; j < width; j++) {
654
               GLint srcCol = j % 32;
655
               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
656
               for (k = 0; k < components; k++) {
657
                  *imgPtr++ = texel;
658
               }
659
            }
660
         }
661
      }
662
   }
663
#endif
664
 
665
   return data;
666
}
667
#endif
668
 
669
 
670
 
671
/*
672
 * Reset the fields of a gl_texture_image struct to zero.
673
 * This is called when a proxy texture test fails, we set all the
674
 * image members (except DriverData) to zero.
675
 * It's also used in glTexImage[123]D as a safeguard to be sure all
676
 * required fields get initialized properly by the Driver.TexImage[123]D
677
 * functions.
678
 */
679
static void
680
clear_teximage_fields(struct gl_texture_image *img)
681
{
682
   ASSERT(img);
683
   img->Format = 0;
684
   img->IntFormat = 0;
685
   img->Border = 0;
686
   img->Width = 0;
687
   img->Height = 0;
688
   img->Depth = 0;
689
   img->RowStride = 0;
690
   img->Width2 = 0;
691
   img->Height2 = 0;
692
   img->Depth2 = 0;
693
   img->WidthLog2 = 0;
694
   img->HeightLog2 = 0;
695
   img->DepthLog2 = 0;
696
   img->Data = NULL;
697
   img->TexFormat = &_mesa_null_texformat;
698
   img->FetchTexel = NULL;
699
   img->IsCompressed = 0;
700
   img->CompressedSize = 0;
701
}
702
 
703
 
704
/*
705
 * Initialize basic fields of the gl_texture_image struct.
706
 */
707
void
708
_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
709
                           struct gl_texture_image *img,
710
                           GLsizei width, GLsizei height, GLsizei depth,
711
                           GLint border, GLenum internalFormat)
712
{
713
   ASSERT(img);
714
   img->Format = _mesa_base_tex_format( ctx, internalFormat );
715
   ASSERT(img->Format > 0);
716
   img->IntFormat = internalFormat;
717
   img->Border = border;
718
   img->Width = width;
719
   img->Height = height;
720
   img->Depth = depth;
721
   img->RowStride = width;
722
   img->WidthLog2 = logbase2(width - 2 * border);
723
   if (height == 1)  /* 1-D texture */
724
      img->HeightLog2 = 0;
725
   else
726
      img->HeightLog2 = logbase2(height - 2 * border);
727
   if (depth == 1)   /* 2-D texture */
728
      img->DepthLog2 = 0;
729
   else
730
      img->DepthLog2 = logbase2(depth - 2 * border);
731
   img->Width2 = 1 << img->WidthLog2;
732
   img->Height2 = 1 << img->HeightLog2;
733
   img->Depth2 = 1 << img->DepthLog2;
734
   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
735
   img->IsCompressed = is_compressed_format(internalFormat);
736
   if (img->IsCompressed)
737
      img->CompressedSize = _mesa_compressed_texture_size(ctx, width, height,
738
                                                       depth, internalFormat);
739
   else
740
      img->CompressedSize = 0;
741
 
742
   /* Compute Width/Height/DepthScale for mipmap lod computation */
743
   if (target == GL_TEXTURE_RECTANGLE_NV) {
744
      /* scale = 1.0 since texture coords directly map to texels */
745
      img->WidthScale = 1.0;
746
      img->HeightScale = 1.0;
747
      img->DepthScale = 1.0;
748
   }
749
   else {
750
      img->WidthScale = (GLfloat) img->Width;
751
      img->HeightScale = (GLfloat) img->Height;
752
      img->DepthScale = (GLfloat) img->Depth;
753
   }
754
}
755
 
756
 
757
 
758
/*
759
 * Test glTexImage[123]D() parameters for errors.
760
 * Input:
761
 *         dimensions - must be 1 or 2 or 3
762
 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
763
 */
764
static GLboolean
765
texture_error_check( GLcontext *ctx, GLenum target,
766
                     GLint level, GLint internalFormat,
767
                     GLenum format, GLenum type,
768
                     GLuint dimensions,
769
                     GLint width, GLint height,
770
                     GLint depth, GLint border )
771
{
772
   GLboolean isProxy;
773
   GLint maxLevels = 0, maxTextureSize;
774
 
775
   if (dimensions == 1) {
776
      if (target == GL_PROXY_TEXTURE_1D) {
777
         isProxy = GL_TRUE;
778
      }
779
      else if (target == GL_TEXTURE_1D) {
780
         isProxy = GL_FALSE;
781
      }
782
      else {
783
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
784
         return GL_TRUE;
785
      }
786
      maxLevels = ctx->Const.MaxTextureLevels;
787
   }
788
   else if (dimensions == 2) {
789
      if (target == GL_PROXY_TEXTURE_2D) {
790
         isProxy = GL_TRUE;
791
         maxLevels = ctx->Const.MaxTextureLevels;
792
      }
793
      else if (target == GL_TEXTURE_2D) {
794
         isProxy = GL_FALSE;
795
         maxLevels = ctx->Const.MaxTextureLevels;
796
      }
797
      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
798
         if (!ctx->Extensions.ARB_texture_cube_map) {
799
            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
800
            return GL_TRUE;
801
         }
802
         isProxy = GL_TRUE;
803
         maxLevels = ctx->Const.MaxCubeTextureLevels;
804
      }
805
      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
806
               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
807
         if (!ctx->Extensions.ARB_texture_cube_map) {
808
            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
809
            return GL_TRUE;
810
         }
811
         isProxy = GL_FALSE;
812
         maxLevels = ctx->Const.MaxCubeTextureLevels;
813
      }
814
      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
815
         if (!ctx->Extensions.NV_texture_rectangle) {
816
            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
817
            return GL_TRUE;
818
         }
819
         isProxy = GL_TRUE;
820
         maxLevels = 1;
821
      }
822
      else if (target == GL_TEXTURE_RECTANGLE_NV) {
823
         if (!ctx->Extensions.NV_texture_rectangle) {
824
            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
825
            return GL_TRUE;
826
         }
827
         isProxy = GL_FALSE;
828
         maxLevels = 1;
829
      }
830
      else {
831
         _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
832
         return GL_TRUE;
833
      }
834
   }
835
   else if (dimensions == 3) {
836
      if (target == GL_PROXY_TEXTURE_3D) {
837
         isProxy = GL_TRUE;
838
      }
839
      else if (target == GL_TEXTURE_3D) {
840
         isProxy = GL_FALSE;
841
      }
842
      else {
843
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
844
         return GL_TRUE;
845
      }
846
      maxLevels = ctx->Const.Max3DTextureLevels;
847
   }
848
   else {
849
      _mesa_problem( ctx, "bad dims in texture_error_check" );
850
      return GL_TRUE;
851
   }
852
 
853
   ASSERT(maxLevels > 0);
854
   maxTextureSize = 1 << (maxLevels - 1);
855
 
856
   /* Border */
857
   if (border != 0 && border != 1) {
858
      if (!isProxy) {
859
         _mesa_error(ctx, GL_INVALID_VALUE,
860
                     "glTexImage%dD(border=%d)", dimensions, border);
861
      }
862
      return GL_TRUE;
863
   }
864
   if ((target == GL_TEXTURE_RECTANGLE_NV ||
865
        target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0) {
866
      return GL_TRUE;
867
   }
868
 
869
   /* Width */
870
   if (target == GL_TEXTURE_RECTANGLE_NV ||
871
       target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
872
      if (width < 1 || width > ctx->Const.MaxTextureRectSize) {
873
         if (!isProxy) {
874
            _mesa_error(ctx, GL_INVALID_VALUE,
875
                        "glTexImage%dD(width=%d)", dimensions, width);
876
         }
877
         return GL_TRUE;
878
      }
879
   }
880
   else if (width < 2 * border || width > 2 + maxTextureSize
881
       || logbase2( width - 2 * border ) < 0) {
882
      if (!isProxy) {
883
         _mesa_error(ctx, GL_INVALID_VALUE,
884
                     "glTexImage%dD(width=%d)", dimensions, width);
885
      }
886
      return GL_TRUE;
887
   }
888
 
889
   /* Height */
890
   if (target == GL_TEXTURE_RECTANGLE_NV ||
891
       target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
892
      if (height < 1 || height > ctx->Const.MaxTextureRectSize) {
893
         if (!isProxy) {
894
            _mesa_error(ctx, GL_INVALID_VALUE,
895
                        "glTexImage%dD(height=%d)", dimensions, height);
896
         }
897
         return GL_TRUE;
898
      }
899
   }
900
   else if (dimensions >= 2) {
901
      if (height < 2 * border || height > 2 + maxTextureSize
902
          || logbase2( height - 2 * border ) < 0) {
903
         if (!isProxy) {
904
            _mesa_error(ctx, GL_INVALID_VALUE,
905
                        "glTexImage%dD(height=%d)", dimensions, height);
906
         }
907
         return GL_TRUE;
908
      }
909
   }
910
 
911
   /* For cube map, width must equal height */
912
   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
913
       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
914
      if (width != height) {
915
         if (!isProxy) {
916
            _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
917
         }
918
         return GL_TRUE;
919
      }
920
   }
921
 
922
   /* Depth */
923
   if (dimensions >= 3) {
924
      if (depth < 2 * border || depth > 2 + maxTextureSize
925
          || logbase2( depth - 2 * border ) < 0) {
926
         if (!isProxy) {
927
            _mesa_error( ctx, GL_INVALID_VALUE,
928
                         "glTexImage3D(depth=%d)", depth );
929
         }
930
         return GL_TRUE;
931
      }
932
   }
933
 
934
   /* Level */
935
   if (target == GL_TEXTURE_RECTANGLE_NV ||
936
       target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
937
      if (level != 0) {
938
         if (!isProxy) {
939
            _mesa_error(ctx, GL_INVALID_VALUE,
940
                        "glTexImage2D(level=%d)", level);
941
         }
942
         return GL_TRUE;
943
      }
944
   }
945
   else if (level < 0 || level >= maxLevels) {
946
      if (!isProxy) {
947
         _mesa_error(ctx, GL_INVALID_VALUE,
948
                     "glTexImage%dD(level=%d)", dimensions, level);
949
      }
950
      return GL_TRUE;
951
   }
952
 
953
   /* For cube map, width must equal height */
954
   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
955
       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
956
      if (width != height) {
957
         _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
958
         return GL_TRUE;
959
      }
960
   }
961
 
962
   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
963
      if (!isProxy) {
964
         _mesa_error(ctx, GL_INVALID_VALUE,
965
                     "glTexImage%dD(internalFormat=0x%x)",
966
                     dimensions, internalFormat);
967
      }
968
      return GL_TRUE;
969
   }
970
 
971
   if (!_mesa_is_legal_format_and_type(format, type)) {
972
      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
973
       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
974
       */
975
      if (!isProxy) {
976
         _mesa_error(ctx, GL_INVALID_OPERATION,
977
                     "glTexImage%dD(format or type)", dimensions);
978
      }
979
      return GL_TRUE;
980
   }
981
 
982
   if (format == GL_YCBCR_MESA || internalFormat == GL_YCBCR_MESA) {
983
      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
984
      if (format != GL_YCBCR_MESA ||
985
          internalFormat != GL_YCBCR_MESA ||
986
          (type != GL_UNSIGNED_SHORT_8_8_MESA &&
987
          type != GL_UNSIGNED_SHORT_8_8_REV_MESA)) {
988
         char message[100];
989
         _mesa_sprintf(message,
990
                 "glTexImage%d(format/type/internalFormat YCBCR mismatch",
991
                 dimensions);
992
         _mesa_error(ctx, GL_INVALID_ENUM, message);
993
         return GL_TRUE; /* error */
994
      }
995
      if (target != GL_TEXTURE_2D &&
996
          target != GL_PROXY_TEXTURE_2D &&
997
          target != GL_TEXTURE_RECTANGLE_NV &&
998
          target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
999
         if (!isProxy)
1000
            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1001
         return GL_TRUE;
1002
      }
1003
      if (border != 0) {
1004
         if (!isProxy) {
1005
            char message[100];
1006
            _mesa_sprintf(message,
1007
                    "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1008
                    dimensions, border);
1009
            _mesa_error(ctx, GL_INVALID_VALUE, message);
1010
         }
1011
         return GL_TRUE;
1012
      }
1013
   }
1014
 
1015
   if (is_compressed_format(internalFormat)) {
1016
      if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
1017
         /* OK */
1018
      }
1019
      else if (ctx->Extensions.ARB_texture_cube_map &&
1020
               (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1021
                (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1022
                 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
1023
         /* OK */
1024
      }
1025
      else {
1026
         if (!isProxy) {
1027
            _mesa_error(ctx, GL_INVALID_ENUM,
1028
                        "glTexImage%d(target)", dimensions);
1029
            return GL_TRUE;
1030
         }
1031
      }
1032
      if (border != 0) {
1033
         if (!isProxy) {
1034
            _mesa_error(ctx, GL_INVALID_OPERATION,
1035
                        "glTexImage%D(border!=0)", dimensions);
1036
         }
1037
         return GL_TRUE;
1038
      }
1039
   }
1040
 
1041
   /* if we get here, the parameters are OK */
1042
   return GL_FALSE;
1043
}
1044
 
1045
 
1046
 
1047
/*
1048
 * Test glTexSubImage[123]D() parameters for errors.
1049
 * Input:
1050
 *         dimensions - must be 1 or 2 or 3
1051
 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
1052
 */
1053
static GLboolean
1054
subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1055
                        GLenum target, GLint level,
1056
                        GLint xoffset, GLint yoffset, GLint zoffset,
1057
                        GLint width, GLint height, GLint depth,
1058
                        GLenum format, GLenum type )
1059
{
1060
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1061
   struct gl_texture_image *destTex;
1062
   GLint maxLevels = 0;
1063
 
1064
   if (dimensions == 1) {
1065
      if (target == GL_TEXTURE_1D) {
1066
         maxLevels = ctx->Const.MaxTextureLevels;
1067
      }
1068
      else {
1069
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1070
         return GL_TRUE;
1071
      }
1072
   }
1073
   else if (dimensions == 2) {
1074
      if (ctx->Extensions.ARB_texture_cube_map &&
1075
          target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1076
          target <=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1077
         maxLevels = ctx->Const.MaxCubeTextureLevels;
1078
      }
1079
      else if (ctx->Extensions.NV_texture_rectangle &&
1080
               target == GL_TEXTURE_RECTANGLE_NV) {
1081
         maxLevels = 1;
1082
      }
1083
      else if (target == GL_TEXTURE_2D) {
1084
         maxLevels = ctx->Const.MaxTextureLevels;
1085
      }
1086
      else {
1087
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1088
         return GL_TRUE;
1089
      }
1090
   }
1091
   else if (dimensions == 3) {
1092
      if (target == GL_TEXTURE_3D) {
1093
         maxLevels = ctx->Const.Max3DTextureLevels;
1094
      }
1095
      else {
1096
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1097
         return GL_TRUE;
1098
      }
1099
   }
1100
   else {
1101
      _mesa_problem( ctx, "bad dims in texture_error_check" );
1102
      return GL_TRUE;
1103
   }
1104
 
1105
   ASSERT(maxLevels > 0);
1106
 
1107
   if (level < 0 || level >= maxLevels) {
1108
      _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1109
      return GL_TRUE;
1110
   }
1111
 
1112
   if (width < 0) {
1113
      _mesa_error(ctx, GL_INVALID_VALUE,
1114
                  "glTexSubImage%dD(width=%d)", dimensions, width);
1115
      return GL_TRUE;
1116
   }
1117
   if (height < 0 && dimensions > 1) {
1118
      _mesa_error(ctx, GL_INVALID_VALUE,
1119
                  "glTexSubImage%dD(height=%d)", dimensions, height);
1120
      return GL_TRUE;
1121
   }
1122
   if (depth < 0 && dimensions > 2) {
1123
      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(depth=%d)", dimensions, depth);
1124
      return GL_TRUE;
1125
   }
1126
 
1127
   destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
1128
 
1129
   if (!destTex) {
1130
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1131
      return GL_TRUE;
1132
   }
1133
 
1134
   if (xoffset < -((GLint)destTex->Border)) {
1135
      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1136
      return GL_TRUE;
1137
   }
1138
   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1139
      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1140
      return GL_TRUE;
1141
   }
1142
   if (dimensions > 1) {
1143
      if (yoffset < -((GLint)destTex->Border)) {
1144
         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1145
         return GL_TRUE;
1146
      }
1147
      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1148
         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1149
         return GL_TRUE;
1150
      }
1151
   }
1152
   if (dimensions > 2) {
1153
      if (zoffset < -((GLint)destTex->Border)) {
1154
         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1155
         return GL_TRUE;
1156
      }
1157
      if (zoffset + depth  > (GLint) (destTex->Depth + destTex->Border)) {
1158
         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1159
         return GL_TRUE;
1160
      }
1161
   }
1162
 
1163
   if (!_mesa_is_legal_format_and_type(format, type)) {
1164
      _mesa_error(ctx, GL_INVALID_ENUM,
1165
                  "glTexSubImage%dD(format or type)", dimensions);
1166
      return GL_TRUE;
1167
   }
1168
 
1169
   if (destTex->IsCompressed) {
1170
      const struct gl_texture_unit *texUnit;
1171
      const struct gl_texture_object *texObj;
1172
      const struct gl_texture_image *texImage;
1173
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1174
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1175
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1176
 
1177
      if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
1178
         /* OK */
1179
      }
1180
      else if (ctx->Extensions.ARB_texture_cube_map &&
1181
               (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1182
                (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1183
                 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
1184
         /* OK */
1185
      }
1186
      else {
1187
         _mesa_error(ctx, GL_INVALID_ENUM,
1188
                     "glTexSubImage%D(target)", dimensions);
1189
         return GL_TRUE;
1190
      }
1191
      /* offset must be multiple of 4 */
1192
      if ((xoffset & 3) || (yoffset & 3)) {
1193
         _mesa_error(ctx, GL_INVALID_OPERATION,
1194
                     "glTexSubImage%D(xoffset or yoffset)", dimensions);
1195
         return GL_TRUE;
1196
      }
1197
      /* size must be multiple of 4 or equal to whole texture size */
1198
      if ((width & 3) && (GLuint) width != texImage->Width) {
1199
         _mesa_error(ctx, GL_INVALID_OPERATION,
1200
                     "glTexSubImage%D(width)", dimensions);
1201
         return GL_TRUE;
1202
      }        
1203
      if ((height & 3) && (GLuint) height != texImage->Height) {
1204
         _mesa_error(ctx, GL_INVALID_OPERATION,
1205
                     "glTexSubImage%D(width)", dimensions);
1206
         return GL_TRUE;
1207
      }        
1208
   }
1209
 
1210
   return GL_FALSE;
1211
}
1212
 
1213
 
1214
/*
1215
 * Test glCopyTexImage[12]D() parameters for errors.
1216
 * Input:  dimensions - must be 1 or 2 or 3
1217
 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
1218
 */
1219
static GLboolean
1220
copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1221
                         GLenum target, GLint level, GLint internalFormat,
1222
                         GLint width, GLint height, GLint border )
1223
{
1224
   GLint maxLevels = 0, maxTextureSize;
1225
 
1226
   if (dimensions == 1) {
1227
      if (target != GL_TEXTURE_1D) {
1228
         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1229
         return GL_TRUE;
1230
      }
1231
      maxLevels = ctx->Const.MaxTextureLevels;
1232
   }
1233
   else if (dimensions == 2) {
1234
      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1235
          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1236
         if (!ctx->Extensions.ARB_texture_cube_map) {
1237
            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1238
            return GL_TRUE;
1239
         }
1240
      }
1241
      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1242
         if (!ctx->Extensions.NV_texture_rectangle) {
1243
            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1244
            return GL_TRUE;
1245
         }
1246
      }
1247
      else if (target != GL_TEXTURE_2D) {
1248
         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1249
         return GL_TRUE;
1250
      }
1251
      if (target == GL_TEXTURE_2D)
1252
         maxLevels = ctx->Const.MaxTextureLevels;
1253
      else if (target == GL_TEXTURE_RECTANGLE_NV)
1254
         maxLevels = 1;
1255
      else
1256
         maxLevels = ctx->Const.MaxCubeTextureLevels;
1257
   }
1258
 
1259
   ASSERT(maxLevels > 0);
1260
   maxTextureSize = 1 << (maxLevels - 1);
1261
 
1262
   /* Border */
1263
   if (border != 0 && border != 1) {
1264
      _mesa_error(ctx, GL_INVALID_VALUE,
1265
                  "glCopyTexImage%dD(border)", dimensions);
1266
      return GL_TRUE;
1267
   }
1268
 
1269
   /* Width */
1270
   if (width < 2 * border || width > 2 + maxTextureSize
1271
       || logbase2( width - 2 * border ) < 0) {
1272
      _mesa_error(ctx, GL_INVALID_VALUE,
1273
                  "glCopyTexImage%dD(width=%d)", dimensions, width);
1274
      return GL_TRUE;
1275
   }
1276
 
1277
   /* Height */
1278
   if (dimensions >= 2) {
1279
      if (height < 2 * border || height > 2 + maxTextureSize
1280
          || logbase2( height - 2 * border ) < 0) {
1281
         _mesa_error(ctx, GL_INVALID_VALUE,
1282
                     "glCopyTexImage%dD(height=%d)", dimensions, height);
1283
         return GL_TRUE;
1284
      }
1285
   }
1286
 
1287
   /* For cube map, width must equal height */
1288
   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1289
       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1290
      if (width != height) {
1291
         _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1292
         return GL_TRUE;
1293
      }
1294
   }
1295
 
1296
   /* Level */
1297
   if (level < 0 || level >= maxLevels) {
1298
      _mesa_error(ctx, GL_INVALID_VALUE,
1299
                  "glCopyTexImage%dD(level=%d)", dimensions, level);
1300
      return GL_TRUE;
1301
   }
1302
 
1303
   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1304
      _mesa_error(ctx, GL_INVALID_VALUE,
1305
                  "glCopyTexImage%dD(internalFormat)", dimensions);
1306
      return GL_TRUE;
1307
   }
1308
 
1309
   if (is_compressed_format(internalFormat)) {
1310
      if (target != GL_TEXTURE_2D) {
1311
         _mesa_error(ctx, GL_INVALID_ENUM,
1312
                     "glCopyTexImage%d(target)", dimensions);
1313
         return GL_TRUE;
1314
      }
1315
      if (border != 0) {
1316
         _mesa_error(ctx, GL_INVALID_OPERATION,
1317
                     "glCopyTexImage%D(border!=0)", dimensions);
1318
         return GL_TRUE;
1319
      }
1320
   }
1321
 
1322
   /* if we get here, the parameters are OK */
1323
   return GL_FALSE;
1324
}
1325
 
1326
 
1327
static GLboolean
1328
copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1329
                             GLenum target, GLint level,
1330
                             GLint xoffset, GLint yoffset, GLint zoffset,
1331
                             GLsizei width, GLsizei height )
1332
{
1333
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1334
   struct gl_texture_image *teximage;
1335
   GLint maxLevels = 0;
1336
 
1337
   if (dimensions == 1) {
1338
      if (target != GL_TEXTURE_1D) {
1339
         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1340
         return GL_TRUE;
1341
      }
1342
      maxLevels = ctx->Const.MaxTextureLevels;
1343
   }
1344
   else if (dimensions == 2) {
1345
      if (ctx->Extensions.ARB_texture_cube_map) {
1346
         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1347
              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1348
             target != GL_TEXTURE_2D) {
1349
            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1350
            return GL_TRUE;
1351
         }
1352
      }
1353
      else if (target != GL_TEXTURE_2D) {
1354
         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1355
         return GL_TRUE;
1356
      }
1357
      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
1358
         maxLevels = ctx->Const.MaxTextureLevels;
1359
      else
1360
         maxLevels = ctx->Const.MaxCubeTextureLevels;
1361
   }
1362
   else if (dimensions == 3) {
1363
      if (target != GL_TEXTURE_3D) {
1364
         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1365
         return GL_TRUE;
1366
      }
1367
      maxLevels = ctx->Const.Max3DTextureLevels;
1368
   }
1369
 
1370
   ASSERT(maxLevels > 0);
1371
 
1372
   if (level < 0 || level >= maxLevels) {
1373
      _mesa_error(ctx, GL_INVALID_VALUE,
1374
                  "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1375
      return GL_TRUE;
1376
   }
1377
 
1378
   if (width < 0) {
1379
      _mesa_error(ctx, GL_INVALID_VALUE,
1380
                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1381
      return GL_TRUE;
1382
   }
1383
   if (dimensions > 1 && height < 0) {
1384
      _mesa_error(ctx, GL_INVALID_VALUE,
1385
                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1386
      return GL_TRUE;
1387
   }
1388
 
1389
   teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
1390
   if (!teximage) {
1391
      _mesa_error(ctx, GL_INVALID_OPERATION,
1392
                  "glCopyTexSubImage%dD(undefined texture level: %d)",
1393
                  dimensions, level);
1394
      return GL_TRUE;
1395
   }
1396
 
1397
   if (xoffset < -((GLint)teximage->Border)) {
1398
      _mesa_error(ctx, GL_INVALID_VALUE,
1399
                  "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1400
      return GL_TRUE;
1401
   }
1402
   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1403
      _mesa_error(ctx, GL_INVALID_VALUE,
1404
                  "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1405
      return GL_TRUE;
1406
   }
1407
   if (dimensions > 1) {
1408
      if (yoffset < -((GLint)teximage->Border)) {
1409
         _mesa_error(ctx, GL_INVALID_VALUE,
1410
                     "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1411
         return GL_TRUE;
1412
      }
1413
      /* NOTE: we're adding the border here, not subtracting! */
1414
      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1415
         _mesa_error(ctx, GL_INVALID_VALUE,
1416
                     "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1417
         return GL_TRUE;
1418
      }
1419
   }
1420
 
1421
   if (dimensions > 2) {
1422
      if (zoffset < -((GLint)teximage->Border)) {
1423
         _mesa_error(ctx, GL_INVALID_VALUE,
1424
                     "glCopyTexSubImage%dD(zoffset)", dimensions);
1425
         return GL_TRUE;
1426
      }
1427
      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1428
         _mesa_error(ctx, GL_INVALID_VALUE,
1429
                     "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1430
         return GL_TRUE;
1431
      }
1432
   }
1433
 
1434
   if (teximage->IsCompressed) {
1435
      if (target != GL_TEXTURE_2D) {
1436
         _mesa_error(ctx, GL_INVALID_ENUM,
1437
                     "glCopyTexSubImage%d(target)", dimensions);
1438
         return GL_TRUE;
1439
      }
1440
      /* offset must be multiple of 4 */
1441
      if ((xoffset & 3) || (yoffset & 3)) {
1442
         _mesa_error(ctx, GL_INVALID_VALUE,
1443
                     "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
1444
         return GL_TRUE;
1445
      }
1446
      /* size must be multiple of 4 */
1447
      if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
1448
         _mesa_error(ctx, GL_INVALID_VALUE,
1449
                     "glCopyTexSubImage%D(width)", dimensions);
1450
         return GL_TRUE;
1451
      }        
1452
      if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
1453
         _mesa_error(ctx, GL_INVALID_VALUE,
1454
                     "glCopyTexSubImage%D(height)", dimensions);
1455
         return GL_TRUE;
1456
      }        
1457
   }
1458
 
1459
   if (teximage->IntFormat == GL_YCBCR_MESA) {
1460
      _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
1461
      return GL_TRUE;
1462
   }
1463
 
1464
   /* if we get here, the parameters are OK */
1465
   return GL_FALSE;
1466
}
1467
 
1468
 
1469
 
1470
void
1471
_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1472
                   GLenum type, GLvoid *pixels )
1473
{
1474
   const struct gl_texture_unit *texUnit;
1475
   const struct gl_texture_object *texObj;
1476
   const struct gl_texture_image *texImage;
1477
   GLint maxLevels = 0;
1478
   GET_CURRENT_CONTEXT(ctx);
1479
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1480
 
1481
   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
1482
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1483
   if (!texObj || is_proxy_target(target)) {
1484
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
1485
      return;
1486
   }
1487
 
1488
   maxLevels = _mesa_max_texture_levels(ctx, target);
1489
   ASSERT(maxLevels > 0);  /* 0 indicates bad target, caught above */
1490
 
1491
   if (level < 0 || level >= maxLevels) {
1492
      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1493
      return;
1494
   }
1495
 
1496
   if (_mesa_sizeof_packed_type(type) <= 0) {
1497
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1498
      return;
1499
   }
1500
 
1501
   if (_mesa_components_in_format(format) <= 0 ||
1502
       format == GL_STENCIL_INDEX) {
1503
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1504
      return;
1505
   }
1506
 
1507
   if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
1508
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1509
   }
1510
 
1511
   if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) {
1512
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1513
   }
1514
 
1515
   if (!ctx->Extensions.MESA_ycbcr_texture && format == GL_YCBCR_MESA) {
1516
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1517
   }
1518
 
1519
   /* XXX what if format/type doesn't match texture format/type? */
1520
 
1521
   if (!pixels)
1522
      return;
1523
 
1524
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1525
   if (!texImage) {
1526
      /* invalid mipmap level, not an error */
1527
      return;
1528
   }
1529
 
1530
   if (!texImage->Data) {
1531
      /* no image data, not an error */
1532
      return;
1533
   }
1534
 
1535
   {
1536
      const GLint width = texImage->Width;
1537
      const GLint height = texImage->Height;
1538
      const GLint depth = texImage->Depth;
1539
      GLint img, row;
1540
      for (img = 0; img < depth; img++) {
1541
         for (row = 0; row < height; row++) {
1542
            /* compute destination address in client memory */
1543
            GLvoid *dest = _mesa_image_address( &ctx->Pack, pixels,
1544
                                                width, height, format, type,
1545
                                                img, row, 0);
1546
            assert(dest);
1547
 
1548
            if (format == GL_COLOR_INDEX) {
1549
               GLuint indexRow[MAX_WIDTH];
1550
               GLint col;
1551
               for (col = 0; col < width; col++) {
1552
                  (*texImage->FetchTexel)(texImage, col, row, img,
1553
                                          (GLvoid *) &indexRow[col]);
1554
               }
1555
               _mesa_pack_index_span(ctx, width, type, dest,
1556
                                     indexRow, &ctx->Pack,
1557
 
1558
            }
1559
            else if (format == GL_DEPTH_COMPONENT) {
1560
               GLfloat depthRow[MAX_WIDTH];
1561
               GLint col;
1562
               for (col = 0; col < width; col++) {
1563
                  (*texImage->FetchTexel)(texImage, col, row, img,
1564
                                          (GLvoid *) &depthRow[col]);
1565
               }
1566
               _mesa_pack_depth_span(ctx, width, dest, type,
1567
                                     depthRow, &ctx->Pack);
1568
            }
1569
            else if (format == GL_YCBCR_MESA) {
1570
               /* No pixel transfer */
1571
               const GLint rowstride = texImage->RowStride;
1572
               MEMCPY(dest,
1573
                      (const GLushort *) texImage->Data + row * rowstride,
1574
                      width * sizeof(GLushort));
1575
               /* check for byte swapping */
1576
               if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
1577
                    && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
1578
                   (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
1579
                    && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
1580
                  if (!ctx->Pack.SwapBytes)
1581
                     _mesa_swap2((GLushort *) dest, width);
1582
               }
1583
               else if (ctx->Pack.SwapBytes) {
1584
                  _mesa_swap2((GLushort *) dest, width);
1585
               }
1586
            }
1587
            else {
1588
               /* general case:  convert row to RGBA format */
1589
               GLchan rgba[MAX_WIDTH][4];
1590
               GLint col;
1591
               for (col = 0; col < width; col++) {
1592
                  (*texImage->FetchTexel)(texImage, col, row, img,
1593
                                          (GLvoid *) rgba[col]);
1594
               }
1595
               _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba,
1596
                                    format, type, dest, &ctx->Pack,
1597
 
1598
            } /* format */
1599
         } /* row */
1600
      } /* img */
1601
   }
1602
}
1603
 
1604
 
1605
 
1606
/*
1607
 * Called from the API.  Note that width includes the border.
1608
 */
1609
void
1610
_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1611
                  GLsizei width, GLint border, GLenum format,
1612
                  GLenum type, const GLvoid *pixels )
1613
{
1614
   GLsizei postConvWidth = width;
1615
   GET_CURRENT_CONTEXT(ctx);
1616
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1617
 
1618
   if (is_color_format(internalFormat)) {
1619
      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1620
   }
1621
 
1622
   if (target == GL_TEXTURE_1D) {
1623
      struct gl_texture_unit *texUnit;
1624
      struct gl_texture_object *texObj;
1625
      struct gl_texture_image *texImage;
1626
 
1627
      if (texture_error_check(ctx, target, level, internalFormat,
1628
                              format, type, 1, postConvWidth, 1, 1, border)) {
1629
         return;   /* error was recorded */
1630
      }
1631
 
1632
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1633
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1634
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1635
 
1636
      if (!texImage) {
1637
         texImage = _mesa_alloc_texture_image();
1638
         texObj->Image[level] = texImage;
1639
         if (!texImage) {
1640
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1641
            return;
1642
         }
1643
      }
1644
      else if (texImage->Data && !texImage->IsClientData) {
1645
         /* free the old texture data */
1646
         MESA_PBUFFER_FREE(texImage->Data);
1647
      }
1648
      texImage->Data = NULL;
1649
      clear_teximage_fields(texImage); /* not really needed, but helpful */
1650
      _mesa_init_teximage_fields(ctx, target, texImage,
1651
                                 postConvWidth, 1, 1,
1652
                                 border, internalFormat);
1653
 
1654
      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1655
         _mesa_update_state(ctx);
1656
 
1657
      ASSERT(ctx->Driver.TexImage1D);
1658
 
1659
      /* Give the texture to the driver!  <pixels> may be null! */
1660
      (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1661
                                width, border, format, type, pixels,
1662
                                &ctx->Unpack, texObj, texImage);
1663
 
1664
      ASSERT(texImage->TexFormat);
1665
      if (!texImage->FetchTexel) {
1666
         /* If driver didn't explicitly set this, use the default */
1667
         texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1668
      }
1669
      ASSERT(texImage->FetchTexel);
1670
 
1671
      /* state update */
1672
      texObj->Complete = GL_FALSE;
1673
      ctx->NewState |= _NEW_TEXTURE;
1674
   }
1675
   else if (target == GL_PROXY_TEXTURE_1D) {
1676
      /* Proxy texture: check for errors and update proxy state */
1677
      GLboolean error = texture_error_check(ctx, target, level, internalFormat,
1678
                                 format, type, 1, postConvWidth, 1, 1, border);
1679
      if (!error) {
1680
         ASSERT(ctx->Driver.TestProxyTexImage);
1681
         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1682
                                                  internalFormat, format, type,
1683
                                                  postConvWidth, 1, 1, border);
1684
      }
1685
      if (error) {
1686
         /* if error, clear all proxy texture image parameters */
1687
         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
1688
            clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
1689
         }
1690
      }
1691
      else {
1692
         /* no error, set the tex image parameters */
1693
         struct gl_texture_unit *texUnit;
1694
         struct gl_texture_image *texImage;
1695
         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1696
         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1697
         _mesa_init_teximage_fields(ctx, target, texImage,
1698
                                    postConvWidth, 1, 1,
1699
                                    border, internalFormat);
1700
      }
1701
   }
1702
   else {
1703
      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1704
      return;
1705
   }
1706
}
1707
 
1708
 
1709
void
1710
_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1711
                  GLsizei width, GLsizei height, GLint border,
1712
                  GLenum format, GLenum type,
1713
                  const GLvoid *pixels )
1714
{
1715
   GLsizei postConvWidth = width, postConvHeight = height;
1716
   GET_CURRENT_CONTEXT(ctx);
1717
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1718
 
1719
   if (is_color_format(internalFormat)) {
1720
      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1721
                                         &postConvHeight);
1722
   }
1723
 
1724
   if (target == GL_TEXTURE_2D ||
1725
       (ctx->Extensions.ARB_texture_cube_map &&
1726
        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1727
        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
1728
       (ctx->Extensions.NV_texture_rectangle &&
1729
        target == GL_TEXTURE_RECTANGLE_NV)) {
1730
      /* non-proxy target */
1731
      struct gl_texture_unit *texUnit;
1732
      struct gl_texture_object *texObj;
1733
      struct gl_texture_image *texImage;
1734
 
1735
      if (texture_error_check(ctx, target, level, internalFormat,
1736
                              format, type, 2, postConvWidth, postConvHeight,
1737
                              1, border)) {
1738
         return;   /* error was recorded */
1739
      }
1740
 
1741
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1742
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1743
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1744
 
1745
      if (!texImage) {
1746
         texImage = _mesa_alloc_texture_image();
1747
         _mesa_set_tex_image(texObj, target, level, texImage);
1748
         if (!texImage) {
1749
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1750
            return;
1751
         }
1752
      }
1753
      else if (texImage->Data && !texImage->IsClientData) {
1754
         /* free the old texture data */
1755
         MESA_PBUFFER_FREE(texImage->Data);
1756
      }
1757
      texImage->Data = NULL;
1758
      clear_teximage_fields(texImage); /* not really needed, but helpful */
1759
      _mesa_init_teximage_fields(ctx, target, texImage,
1760
                                 postConvWidth, postConvHeight, 1,
1761
                                 border, internalFormat);
1762
 
1763
      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1764
         _mesa_update_state(ctx);
1765
 
1766
      ASSERT(ctx->Driver.TexImage2D);
1767
 
1768
      /* Give the texture to the driver!  <pixels> may be null! */
1769
      (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1770
                                width, height, border, format, type, pixels,
1771
                                &ctx->Unpack, texObj, texImage);
1772
 
1773
      ASSERT(texImage->TexFormat);
1774
      if (!texImage->FetchTexel) {
1775
         /* If driver didn't explicitly set this, use the default */
1776
         texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1777
      }
1778
      ASSERT(texImage->FetchTexel);
1779
 
1780
      /* state update */
1781
      texObj->Complete = GL_FALSE;
1782
      ctx->NewState |= _NEW_TEXTURE;
1783
   }
1784
   else if (target == GL_PROXY_TEXTURE_2D ||
1785
            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
1786
             ctx->Extensions.ARB_texture_cube_map) ||
1787
            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
1788
             ctx->Extensions.NV_texture_rectangle)) {
1789
      /* Proxy texture: check for errors and update proxy state */
1790
      GLboolean error = texture_error_check(ctx, target, level, internalFormat,
1791
                    format, type, 2, postConvWidth, postConvHeight, 1, border);
1792
      if (!error) {
1793
         ASSERT(ctx->Driver.TestProxyTexImage);
1794
         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1795
                                    internalFormat, format, type,
1796
                                    postConvWidth, postConvHeight, 1, border);
1797
      }
1798
      if (error) {
1799
         /* if error, clear all proxy texture image parameters */
1800
         const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
1801
            ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
1802
         if (level >= 0 && level < maxLevels) {
1803
            clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
1804
         }
1805
      }
1806
      else {
1807
         /* no error, set the tex image parameters */
1808
         struct gl_texture_unit *texUnit;
1809
         struct gl_texture_image *texImage;
1810
         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1811
         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1812
         _mesa_init_teximage_fields(ctx, target, texImage,
1813
                                    postConvWidth, postConvHeight, 1,
1814
                                    border, internalFormat);
1815
      }
1816
   }
1817
   else {
1818
      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1819
      return;
1820
   }
1821
}
1822
 
1823
 
1824
/*
1825
 * Called by the API or display list executor.
1826
 * Note that width and height include the border.
1827
 */
1828
void
1829
_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1830
                  GLsizei width, GLsizei height, GLsizei depth,
1831
                  GLint border, GLenum format, GLenum type,
1832
                  const GLvoid *pixels )
1833
{
1834
   GET_CURRENT_CONTEXT(ctx);
1835
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1836
 
1837
   if (target == GL_TEXTURE_3D) {
1838
      struct gl_texture_unit *texUnit;
1839
      struct gl_texture_object *texObj;
1840
      struct gl_texture_image *texImage;
1841
 
1842
      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
1843
                              format, type, 3, width, height, depth, border)) {
1844
         return;   /* error was recorded */
1845
      }
1846
 
1847
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1848
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1849
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1850
 
1851
      if (!texImage) {
1852
         texImage = _mesa_alloc_texture_image();
1853
         texObj->Image[level] = texImage;
1854
         if (!texImage) {
1855
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1856
            return;
1857
         }
1858
      }
1859
      else if (texImage->Data && !texImage->IsClientData) {
1860
         MESA_PBUFFER_FREE(texImage->Data);
1861
      }
1862
      texImage->Data = NULL;
1863
      clear_teximage_fields(texImage); /* not really needed, but helpful */
1864
      _mesa_init_teximage_fields(ctx, target, texImage,
1865
                                 width, height, depth,
1866
                                 border, internalFormat);
1867
 
1868
      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1869
         _mesa_update_state(ctx);
1870
 
1871
      ASSERT(ctx->Driver.TexImage3D);
1872
 
1873
      /* Give the texture to the driver!  <pixels> may be null! */
1874
      (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
1875
                                width, height, depth, border, format, type,
1876
                                pixels, &ctx->Unpack, texObj, texImage);
1877
 
1878
      ASSERT(texImage->TexFormat);
1879
      if (!texImage->FetchTexel) {
1880
         /* If driver didn't explicitly set this, use the default */
1881
         texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
1882
      }
1883
      ASSERT(texImage->FetchTexel);
1884
 
1885
      /* state update */
1886
      texObj->Complete = GL_FALSE;
1887
      ctx->NewState |= _NEW_TEXTURE;
1888
   }
1889
   else if (target == GL_PROXY_TEXTURE_3D) {
1890
      /* Proxy texture: check for errors and update proxy state */
1891
      GLboolean error = texture_error_check(ctx, target, level, internalFormat,
1892
                                format, type, 3, width, height, depth, border);
1893
      if (!error) {
1894
         ASSERT(ctx->Driver.TestProxyTexImage);
1895
         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1896
                                                 internalFormat, format, type,
1897
                                                 width, height, depth, border);
1898
      }
1899
      if (error) {
1900
         /* if error, clear all proxy texture image parameters */
1901
         if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
1902
            clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
1903
         }
1904
      }
1905
      else {
1906
         /* no error, set the tex image parameters */
1907
         struct gl_texture_unit *texUnit;
1908
         struct gl_texture_image *texImage;
1909
         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1910
         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1911
         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
1912
                                    border, internalFormat);
1913
      }
1914
   }
1915
   else {
1916
      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1917
      return;
1918
   }
1919
}
1920
 
1921
 
1922
void
1923
_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1924
                     GLsizei width, GLsizei height, GLsizei depth,
1925
                     GLint border, GLenum format, GLenum type,
1926
                     const GLvoid *pixels )
1927
{
1928
   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1929
                    depth, border, format, type, pixels);
1930
}
1931
 
1932
 
1933
 
1934
void
1935
_mesa_TexSubImage1D( GLenum target, GLint level,
1936
                     GLint xoffset, GLsizei width,
1937
                     GLenum format, GLenum type,
1938
                     const GLvoid *pixels )
1939
{
1940
   GLsizei postConvWidth = width;
1941
   struct gl_texture_unit *texUnit;
1942
   struct gl_texture_object *texObj;
1943
   struct gl_texture_image *texImage;
1944
   GET_CURRENT_CONTEXT(ctx);
1945
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1946
 
1947
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1948
      _mesa_update_state(ctx);
1949
 
1950
   /* XXX should test internal format */
1951
   if (is_color_format(format)) {
1952
      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1953
   }
1954
 
1955
   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1956
                              postConvWidth, 1, 1, format, type)) {
1957
      return;   /* error was detected */
1958
   }
1959
 
1960
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1961
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1962
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1963
   assert(texImage);
1964
 
1965
   if (width == 0 || !pixels)
1966
      return;  /* no-op, not an error */
1967
 
1968
   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
1969
   xoffset += texImage->Border;
1970
 
1971
   ASSERT(ctx->Driver.TexSubImage1D);
1972
   (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
1973
                                format, type, pixels, &ctx->Unpack,
1974
                                texObj, texImage);
1975
   ctx->NewState |= _NEW_TEXTURE;
1976
}
1977
 
1978
 
1979
void
1980
_mesa_TexSubImage2D( GLenum target, GLint level,
1981
                     GLint xoffset, GLint yoffset,
1982
                     GLsizei width, GLsizei height,
1983
                     GLenum format, GLenum type,
1984
                     const GLvoid *pixels )
1985
{
1986
   GLsizei postConvWidth = width, postConvHeight = height;
1987
   struct gl_texture_unit *texUnit;
1988
   struct gl_texture_object *texObj;
1989
   struct gl_texture_image *texImage;
1990
   GET_CURRENT_CONTEXT(ctx);
1991
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1992
 
1993
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1994
      _mesa_update_state(ctx);
1995
 
1996
   /* XXX should test internal format */
1997
   if (is_color_format(format)) {
1998
      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1999
                                         &postConvHeight);
2000
   }
2001
 
2002
   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2003
                             postConvWidth, postConvHeight, 1, format, type)) {
2004
      return;   /* error was detected */
2005
   }
2006
 
2007
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2008
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2009
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2010
   assert(texImage);
2011
 
2012
   if (width == 0 || height == 0 || !pixels)
2013
      return;  /* no-op, not an error */
2014
 
2015
   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2016
   xoffset += texImage->Border;
2017
   yoffset += texImage->Border;
2018
 
2019
   ASSERT(ctx->Driver.TexSubImage2D);
2020
   (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2021
                                width, height, format, type, pixels,
2022
                                &ctx->Unpack, texObj, texImage);
2023
   ctx->NewState |= _NEW_TEXTURE;
2024
}
2025
 
2026
 
2027
 
2028
void
2029
_mesa_TexSubImage3D( GLenum target, GLint level,
2030
                     GLint xoffset, GLint yoffset, GLint zoffset,
2031
                     GLsizei width, GLsizei height, GLsizei depth,
2032
                     GLenum format, GLenum type,
2033
                     const GLvoid *pixels )
2034
{
2035
   struct gl_texture_unit *texUnit;
2036
   struct gl_texture_object *texObj;
2037
   struct gl_texture_image *texImage;
2038
   GET_CURRENT_CONTEXT(ctx);
2039
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2040
 
2041
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2042
      _mesa_update_state(ctx);
2043
 
2044
   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2045
                              width, height, depth, format, type)) {
2046
      return;   /* error was detected */
2047
   }
2048
 
2049
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2050
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2051
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2052
   assert(texImage);
2053
 
2054
   if (width == 0 || height == 0 || height == 0 || !pixels)
2055
      return;  /* no-op, not an error */
2056
 
2057
   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2058
   xoffset += texImage->Border;
2059
   yoffset += texImage->Border;
2060
   zoffset += texImage->Border;
2061
 
2062
   ASSERT(ctx->Driver.TexSubImage3D);
2063
   (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2064
                                xoffset, yoffset, zoffset,
2065
                                width, height, depth,
2066
                                format, type, pixels,
2067
                                &ctx->Unpack, texObj, texImage );
2068
   ctx->NewState |= _NEW_TEXTURE;
2069
}
2070
 
2071
 
2072
 
2073
void
2074
_mesa_CopyTexImage1D( GLenum target, GLint level,
2075
                      GLenum internalFormat,
2076
                      GLint x, GLint y,
2077
                      GLsizei width, GLint border )
2078
{
2079
   struct gl_texture_unit *texUnit;
2080
   struct gl_texture_object *texObj;
2081
   struct gl_texture_image *texImage;
2082
   GLsizei postConvWidth = width;
2083
   GET_CURRENT_CONTEXT(ctx);
2084
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2085
 
2086
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2087
      _mesa_update_state(ctx);
2088
 
2089
   if (is_color_format(internalFormat)) {
2090
      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2091
   }
2092
 
2093
   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2094
                               postConvWidth, 1, border))
2095
      return;
2096
 
2097
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2098
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2099
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2100
   if (!texImage) {
2101
      texImage = _mesa_alloc_texture_image();
2102
      _mesa_set_tex_image(texObj, target, level, texImage);
2103
      if (!texImage) {
2104
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2105
         return;
2106
      }
2107
   }
2108
   else if (texImage->Data && !texImage->IsClientData) {
2109
      /* free the old texture data */
2110
      MESA_PBUFFER_FREE(texImage->Data);
2111
   }
2112
   texImage->Data = NULL;
2113
 
2114
   clear_teximage_fields(texImage); /* not really needed, but helpful */
2115
   _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2116
                              border, internalFormat);
2117
 
2118
 
2119
   ASSERT(ctx->Driver.CopyTexImage1D);
2120
   (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
2121
                                 x, y, width, border);
2122
 
2123
   ASSERT(texImage->TexFormat);
2124
   if (!texImage->FetchTexel) {
2125
      /* If driver didn't explicitly set this, use the default */
2126
      texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
2127
   }
2128
   ASSERT(texImage->FetchTexel);
2129
 
2130
   /* state update */
2131
   texObj->Complete = GL_FALSE;
2132
   ctx->NewState |= _NEW_TEXTURE;
2133
}
2134
 
2135
 
2136
 
2137
void
2138
_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2139
                      GLint x, GLint y, GLsizei width, GLsizei height,
2140
                      GLint border )
2141
{
2142
   struct gl_texture_unit *texUnit;
2143
   struct gl_texture_object *texObj;
2144
   struct gl_texture_image *texImage;
2145
   GLsizei postConvWidth = width, postConvHeight = height;
2146
   GET_CURRENT_CONTEXT(ctx);
2147
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2148
 
2149
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2150
      _mesa_update_state(ctx);
2151
 
2152
   if (is_color_format(internalFormat)) {
2153
      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2154
                                         &postConvHeight);
2155
   }
2156
 
2157
   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2158
                               postConvWidth, postConvHeight, border))
2159
      return;
2160
 
2161
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2162
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2163
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2164
   if (!texImage) {
2165
      texImage = _mesa_alloc_texture_image();
2166
      _mesa_set_tex_image(texObj, target, level, texImage);
2167
      if (!texImage) {
2168
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2169
         return;
2170
      }
2171
   }
2172
   else if (texImage->Data && !texImage->IsClientData) {
2173
      /* free the old texture data */
2174
      MESA_PBUFFER_FREE(texImage->Data);
2175
   }
2176
   texImage->Data = NULL;
2177
 
2178
   clear_teximage_fields(texImage); /* not really needed, but helpful */
2179
   _mesa_init_teximage_fields(ctx, target, texImage,
2180
                              postConvWidth, postConvHeight, 1,
2181
                              border, internalFormat);
2182
 
2183
   ASSERT(ctx->Driver.CopyTexImage2D);
2184
   (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
2185
                                 x, y, width, height, border);
2186
 
2187
   ASSERT(texImage->TexFormat);
2188
   if (!texImage->FetchTexel) {
2189
      /* If driver didn't explicitly set this, use the default */
2190
      texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
2191
   }
2192
   ASSERT(texImage->FetchTexel);
2193
 
2194
   /* state update */
2195
   texObj->Complete = GL_FALSE;
2196
   ctx->NewState |= _NEW_TEXTURE;
2197
}
2198
 
2199
 
2200
 
2201
void
2202
_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2203
                         GLint xoffset, GLint x, GLint y, GLsizei width )
2204
{
2205
   struct gl_texture_unit *texUnit;
2206
   struct gl_texture_object *texObj;
2207
   struct gl_texture_image *texImage;
2208
   GLsizei postConvWidth = width;
2209
   GET_CURRENT_CONTEXT(ctx);
2210
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2211
 
2212
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2213
      _mesa_update_state(ctx);
2214
 
2215
   /* XXX should test internal format */
2216
   _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2217
 
2218
   if (copytexsubimage_error_check(ctx, 1, target, level,
2219
                                   xoffset, 0, 0, postConvWidth, 1))
2220
      return;
2221
 
2222
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2223
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2224
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2225
 
2226
   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2227
   xoffset += texImage->Border;
2228
 
2229
   ASSERT(ctx->Driver.CopyTexSubImage1D);
2230
   (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
2231
   ctx->NewState |= _NEW_TEXTURE;
2232
}
2233
 
2234
 
2235
 
2236
void
2237
_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2238
                         GLint xoffset, GLint yoffset,
2239
                         GLint x, GLint y, GLsizei width, GLsizei height )
2240
{
2241
   struct gl_texture_unit *texUnit;
2242
   struct gl_texture_object *texObj;
2243
   struct gl_texture_image *texImage;
2244
   GLsizei postConvWidth = width, postConvHeight = height;
2245
   GET_CURRENT_CONTEXT(ctx);
2246
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2247
 
2248
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2249
      _mesa_update_state(ctx);
2250
 
2251
   /* XXX should test internal format */
2252
   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2253
 
2254
   if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2255
                                   postConvWidth, postConvHeight))
2256
      return;
2257
 
2258
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2259
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2260
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2261
 
2262
   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2263
   xoffset += texImage->Border;
2264
   yoffset += texImage->Border;
2265
 
2266
   ASSERT(ctx->Driver.CopyTexSubImage2D);
2267
   (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2268
                                    xoffset, yoffset, x, y, width, height);
2269
   ctx->NewState |= _NEW_TEXTURE;
2270
}
2271
 
2272
 
2273
 
2274
void
2275
_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2276
                         GLint xoffset, GLint yoffset, GLint zoffset,
2277
                         GLint x, GLint y, GLsizei width, GLsizei height )
2278
{
2279
   struct gl_texture_unit *texUnit;
2280
   struct gl_texture_object *texObj;
2281
   struct gl_texture_image *texImage;
2282
   GLsizei postConvWidth = width, postConvHeight = height;
2283
   GET_CURRENT_CONTEXT(ctx);
2284
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2285
 
2286
   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2287
      _mesa_update_state(ctx);
2288
 
2289
   /* XXX should test internal format */
2290
   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2291
 
2292
   if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2293
                                   zoffset, postConvWidth, postConvHeight))
2294
      return;
2295
 
2296
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2297
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2298
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2299
 
2300
   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2301
   xoffset += texImage->Border;
2302
   yoffset += texImage->Border;
2303
   zoffset += texImage->Border;
2304
 
2305
   ASSERT(ctx->Driver.CopyTexSubImage3D);
2306
   (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2307
                                    xoffset, yoffset, zoffset,
2308
                                    x, y, width, height);
2309
   ctx->NewState |= _NEW_TEXTURE;
2310
}
2311
 
2312
 
2313
 
2314
 
2315
/**********************************************************************/
2316
/******                   Compressed Textures                    ******/
2317
/**********************************************************************/
2318
 
2319
 
2320
/**
2321
 * Error checking for glCompressedTexImage[123]D().
2322
 * \return error code or GL_NO_ERROR.
2323
 */
2324
static GLenum
2325
compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
2326
                               GLenum target, GLint level,
2327
                               GLenum internalFormat, GLsizei width,
2328
                               GLsizei height, GLsizei depth, GLint border,
2329
                               GLsizei imageSize)
2330
{
2331
   GLboolean isProxy = GL_FALSE;
2332
   GLint expectedSize, maxLevels = 0, maxTextureSize;
2333
 
2334
   if (dimensions == 1) {
2335
      /* 1D compressed textures not allowed */
2336
      return GL_INVALID_ENUM;
2337
   }
2338
   else if (dimensions == 2) {
2339
      if (target == GL_PROXY_TEXTURE_2D) {
2340
         maxLevels = ctx->Const.MaxTextureLevels;
2341
         isProxy = GL_TRUE;
2342
      }
2343
      else if (target == GL_TEXTURE_2D) {
2344
         maxLevels = ctx->Const.MaxTextureLevels;
2345
      }
2346
      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
2347
         if (!ctx->Extensions.ARB_texture_cube_map)
2348
            return GL_INVALID_ENUM; /*target*/
2349
         maxLevels = ctx->Const.MaxCubeTextureLevels;
2350
         isProxy = GL_TRUE;
2351
      }
2352
      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2353
               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2354
         if (!ctx->Extensions.ARB_texture_cube_map)
2355
            return GL_INVALID_ENUM; /*target*/
2356
         maxLevels = ctx->Const.MaxCubeTextureLevels;
2357
      }
2358
      else {
2359
         return GL_INVALID_ENUM; /*target*/
2360
      }
2361
   }
2362
   else if (dimensions == 3) {
2363
      /* 3D compressed textures not allowed */
2364
      return GL_INVALID_ENUM;
2365
   }
2366
 
2367
   maxTextureSize = 1 << (maxLevels - 1);
2368
 
2369
   if (!is_compressed_format(internalFormat))
2370
      return GL_INVALID_ENUM;
2371
 
2372
   if (border != 0)
2373
      return GL_INVALID_VALUE;
2374
 
2375
   if (width < 1 || width > maxTextureSize || logbase2(width) < 0)
2376
      return GL_INVALID_VALUE;
2377
 
2378
   if ((height < 1 || height > maxTextureSize || logbase2(height) < 0)
2379
       && dimensions > 1)
2380
      return GL_INVALID_VALUE;
2381
 
2382
   if ((depth < 1 || depth > maxTextureSize || logbase2(depth) < 0)
2383
       && dimensions > 2)
2384
      return GL_INVALID_VALUE;
2385
 
2386
   /* For cube map, width must equal height */
2387
   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2388
       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
2389
      return GL_INVALID_VALUE;
2390
 
2391
   if (level < 0 || level >= maxLevels)
2392
      return GL_INVALID_VALUE;
2393
 
2394
   expectedSize = _mesa_compressed_texture_size(ctx, width, height, depth,
2395
                                                internalFormat);
2396
   if (expectedSize != imageSize)
2397
      return GL_INVALID_VALUE;
2398
 
2399
   return GL_NO_ERROR;
2400
}
2401
 
2402
 
2403
/**
2404
 * Error checking for glCompressedTexSubImage[123]D().
2405
 * \return error code or GL_NO_ERROR.
2406
 */
2407
static GLenum
2408
compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
2409
                                  GLenum target, GLint level,
2410
                                  GLint xoffset, GLint yoffset, GLint zoffset,
2411
                                  GLsizei width, GLsizei height, GLsizei depth,
2412
                                  GLenum format, GLsizei imageSize)
2413
{
2414
   GLboolean isProxy = GL_FALSE;
2415
   GLint expectedSize, maxLevels = 0, maxTextureSize;
2416
 
2417
   if (dimensions == 1) {
2418
      /* 1D compressed textures not allowed */
2419
      return GL_INVALID_ENUM;
2420
   }
2421
   else if (dimensions == 2) {
2422
      if (target == GL_PROXY_TEXTURE_2D) {
2423
         maxLevels = ctx->Const.MaxTextureLevels;
2424
         isProxy = GL_TRUE;
2425
      }
2426
      else if (target == GL_TEXTURE_2D) {
2427
         maxLevels = ctx->Const.MaxTextureLevels;
2428
      }
2429
      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
2430
         if (!ctx->Extensions.ARB_texture_cube_map)
2431
            return GL_INVALID_ENUM; /*target*/
2432
         maxLevels = ctx->Const.MaxCubeTextureLevels;
2433
         isProxy = GL_TRUE;
2434
      }
2435
      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2436
               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2437
         if (!ctx->Extensions.ARB_texture_cube_map)
2438
            return GL_INVALID_ENUM; /*target*/
2439
         maxLevels = ctx->Const.MaxCubeTextureLevels;
2440
      }
2441
      else {
2442
         return GL_INVALID_ENUM; /*target*/
2443
      }
2444
   }
2445
   else if (dimensions == 3) {
2446
      /* 3D compressed textures not allowed */
2447
      return GL_INVALID_ENUM;
2448
   }
2449
 
2450
   maxTextureSize = 1 << (maxLevels - 1);
2451
 
2452
   if (!is_compressed_format(format))
2453
      return GL_INVALID_ENUM;
2454
 
2455
   if (width < 1 || width > maxTextureSize || logbase2(width) < 0)
2456
      return GL_INVALID_VALUE;
2457
 
2458
   if ((height < 1 || height > maxTextureSize || logbase2(height) < 0)
2459
       && dimensions > 1)
2460
      return GL_INVALID_VALUE;
2461
 
2462
   if (level < 0 || level >= maxLevels)
2463
      return GL_INVALID_VALUE;
2464
 
2465
   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
2466
      return GL_INVALID_VALUE;
2467
 
2468
   if ((width & 3) != 0 && width != 2 && width != 1)
2469
      return GL_INVALID_VALUE;
2470
 
2471
   if ((height & 3) != 0 && height != 2 && height != 1)
2472
      return GL_INVALID_VALUE;
2473
 
2474
   expectedSize = _mesa_compressed_texture_size(ctx, width, height, depth,
2475
                                                format);
2476
   if (expectedSize != imageSize)
2477
      return GL_INVALID_VALUE;
2478
 
2479
   return GL_NO_ERROR;
2480
}
2481
 
2482
 
2483
 
2484
void
2485
_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2486
                              GLenum internalFormat, GLsizei width,
2487
                              GLint border, GLsizei imageSize,
2488
                              const GLvoid *data)
2489
{
2490
   GET_CURRENT_CONTEXT(ctx);
2491
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2492
 
2493
   if (target == GL_TEXTURE_1D) {
2494
      struct gl_texture_unit *texUnit;
2495
      struct gl_texture_object *texObj;
2496
      struct gl_texture_image *texImage;
2497
      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
2498
                               internalFormat, width, 1, 1, border, imageSize);
2499
      if (error) {
2500
         _mesa_error(ctx, error, "glCompressedTexImage1D");
2501
         return;
2502
      }
2503
 
2504
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2505
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2506
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2507
 
2508
      if (!texImage) {
2509
         texImage = _mesa_alloc_texture_image();
2510
         texObj->Image[level] = texImage;
2511
         if (!texImage) {
2512
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
2513
            return;
2514
         }
2515
      }
2516
      else if (texImage->Data && !texImage->IsClientData) {
2517
         MESA_PBUFFER_FREE(texImage->Data);
2518
      }
2519
      texImage->Data = NULL;
2520
 
2521
      _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
2522
                                 border, internalFormat);
2523
 
2524
      ASSERT(ctx->Driver.CompressedTexImage1D);
2525
      (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2526
                                          internalFormat, width, border,
2527
                                          imageSize, data,
2528
                                          texObj, texImage);
2529
 
2530
      /* state update */
2531
      texObj->Complete = GL_FALSE;
2532
      ctx->NewState |= _NEW_TEXTURE;
2533
   }
2534
   else if (target == GL_PROXY_TEXTURE_1D) {
2535
      /* Proxy texture: check for errors and update proxy state */
2536
      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
2537
                               internalFormat, width, 1, 1, border, imageSize);
2538
      if (!error) {
2539
         ASSERT(ctx->Driver.TestProxyTexImage);
2540
         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2541
                                             internalFormat, GL_NONE, GL_NONE,
2542
                                             width, 1, 1, border);
2543
      }
2544
      if (error) {
2545
         /* if error, clear all proxy texture image parameters */
2546
         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2547
            clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
2548
         }
2549
      }
2550
      else {
2551
         /* store the teximage parameters */
2552
         struct gl_texture_unit *texUnit;
2553
         struct gl_texture_image *texImage;
2554
         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2555
         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2556
         _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
2557
                                    border, internalFormat);
2558
      }
2559
   }
2560
   else {
2561
      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
2562
      return;
2563
   }
2564
}
2565
 
2566
 
2567
void
2568
_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2569
                              GLenum internalFormat, GLsizei width,
2570
                              GLsizei height, GLint border, GLsizei imageSize,
2571
                              const GLvoid *data)
2572
{
2573
   GET_CURRENT_CONTEXT(ctx);
2574
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2575
 
2576
   if (target == GL_TEXTURE_2D ||
2577
       (ctx->Extensions.ARB_texture_cube_map &&
2578
        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2579
        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2580
      struct gl_texture_unit *texUnit;
2581
      struct gl_texture_object *texObj;
2582
      struct gl_texture_image *texImage;
2583
      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
2584
                          internalFormat, width, height, 1, border, imageSize);
2585
      if (error) {
2586
         _mesa_error(ctx, error, "glCompressedTexImage2D");
2587
         return;
2588
      }
2589
 
2590
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2591
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2592
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2593
 
2594
      if (!texImage) {
2595
         texImage = _mesa_alloc_texture_image();
2596
         texObj->Image[level] = texImage;
2597
         if (!texImage) {
2598
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
2599
            return;
2600
         }
2601
      }
2602
      else if (texImage->Data && !texImage->IsClientData) {
2603
         MESA_PBUFFER_FREE(texImage->Data);
2604
      }
2605
      texImage->Data = NULL;
2606
 
2607
      _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
2608
                                 border, internalFormat);
2609
 
2610
      ASSERT(ctx->Driver.CompressedTexImage2D);
2611
      (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
2612
                                          internalFormat, width, height,
2613
                                          border, imageSize, data,
2614
                                          texObj, texImage);
2615
 
2616
      /* state update */
2617
      texObj->Complete = GL_FALSE;
2618
      ctx->NewState |= _NEW_TEXTURE;
2619
   }
2620
   else if (target == GL_PROXY_TEXTURE_2D ||
2621
            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2622
             ctx->Extensions.ARB_texture_cube_map)) {
2623
      /* Proxy texture: check for errors and update proxy state */
2624
      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
2625
                          internalFormat, width, height, 1, border, imageSize);
2626
      if (!error) {
2627
         ASSERT(ctx->Driver.TestProxyTexImage);
2628
         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2629
                                              internalFormat, GL_NONE, GL_NONE,
2630
                                              width, height, 1, border);
2631
      }
2632
      if (error) {
2633
         /* if error, clear all proxy texture image parameters */
2634
         const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
2635
            ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
2636
         if (level >= 0 && level < maxLevels) {
2637
            clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
2638
         }
2639
      }
2640
      else {
2641
         /* store the teximage parameters */
2642
         struct gl_texture_unit *texUnit;
2643
         struct gl_texture_image *texImage;
2644
         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2645
         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2646
         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
2647
                                    border, internalFormat);
2648
      }
2649
   }
2650
   else {
2651
      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
2652
      return;
2653
   }
2654
}
2655
 
2656
 
2657
void
2658
_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2659
                              GLenum internalFormat, GLsizei width,
2660
                              GLsizei height, GLsizei depth, GLint border,
2661
                              GLsizei imageSize, const GLvoid *data)
2662
{
2663
   GET_CURRENT_CONTEXT(ctx);
2664
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2665
 
2666
   if (target == GL_TEXTURE_3D) {
2667
      struct gl_texture_unit *texUnit;
2668
      struct gl_texture_object *texObj;
2669
      struct gl_texture_image *texImage;
2670
      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
2671
                      internalFormat, width, height, depth, border, imageSize);
2672
      if (error) {
2673
         _mesa_error(ctx, error, "glCompressedTexImage3D");
2674
         return;
2675
      }
2676
 
2677
      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2678
      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2679
      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2680
 
2681
      if (!texImage) {
2682
         texImage = _mesa_alloc_texture_image();
2683
         texObj->Image[level] = texImage;
2684
         if (!texImage) {
2685
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
2686
            return;
2687
         }
2688
      }
2689
      else if (texImage->Data && !texImage->IsClientData) {
2690
         MESA_PBUFFER_FREE(texImage->Data);
2691
      }
2692
      texImage->Data = NULL;
2693
 
2694
      _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
2695
                                 border, internalFormat);
2696
 
2697
      ASSERT(ctx->Driver.CompressedTexImage3D);
2698
      (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
2699
                                          internalFormat,
2700
                                          width, height, depth,
2701
                                          border, imageSize, data,
2702
                                          texObj, texImage);
2703
 
2704
      /* state update */
2705
      texObj->Complete = GL_FALSE;
2706
      ctx->NewState |= _NEW_TEXTURE;
2707
   }
2708
   else if (target == GL_PROXY_TEXTURE_3D) {
2709
      /* Proxy texture: check for errors and update proxy state */
2710
      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
2711
                      internalFormat, width, height, depth, border, imageSize);
2712
      if (!error) {
2713
         ASSERT(ctx->Driver.TestProxyTexImage);
2714
         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2715
                                             internalFormat, GL_NONE, GL_NONE,
2716
                                             width, height, depth, border);
2717
      }
2718
      if (error) {
2719
         /* if error, clear all proxy texture image parameters */
2720
         if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
2721
            clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
2722
         }
2723
      }
2724
      else {
2725
         /* store the teximage parameters */
2726
         struct gl_texture_unit *texUnit;
2727
         struct gl_texture_image *texImage;
2728
         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2729
         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2730
         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2731
                                    depth, border, internalFormat);
2732
      }
2733
   }
2734
   else {
2735
      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
2736
      return;
2737
   }
2738
}
2739
 
2740
 
2741
void
2742
_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2743
                                 GLsizei width, GLenum format,
2744
                                 GLsizei imageSize, const GLvoid *data)
2745
{
2746
   struct gl_texture_unit *texUnit;
2747
   struct gl_texture_object *texObj;
2748
   struct gl_texture_image *texImage;
2749
   GLenum error;
2750
   GET_CURRENT_CONTEXT(ctx);
2751
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2752
 
2753
   error = compressed_subtexture_error_check(ctx, 1, target, level,
2754
                                xoffset, 0, 0, width, 1, 1, format, imageSize);
2755
   if (error) {
2756
      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
2757
      return;
2758
   }
2759
 
2760
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2761
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2762
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2763
   assert(texImage);
2764
 
2765
   if ((GLint) format != texImage->IntFormat) {
2766
      _mesa_error(ctx, GL_INVALID_OPERATION,
2767
                  "glCompressedTexSubImage1D(format)");
2768
      return;
2769
   }
2770
 
2771
   if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
2772
      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
2773
      return;
2774
   }
2775
 
2776
   if (width == 0 || !data)
2777
      return;  /* no-op, not an error */
2778
 
2779
   if (ctx->Driver.CompressedTexSubImage1D) {
2780
      (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
2781
                                             xoffset, width,
2782
                                             format, imageSize, data,
2783
                                             texObj, texImage);
2784
   }
2785
   ctx->NewState |= _NEW_TEXTURE;
2786
}
2787
 
2788
 
2789
void
2790
_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2791
                                 GLint yoffset, GLsizei width, GLsizei height,
2792
                                 GLenum format, GLsizei imageSize,
2793
                                 const GLvoid *data)
2794
{
2795
   struct gl_texture_unit *texUnit;
2796
   struct gl_texture_object *texObj;
2797
   struct gl_texture_image *texImage;
2798
   GLenum error;
2799
   GET_CURRENT_CONTEXT(ctx);
2800
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2801
 
2802
   error = compressed_subtexture_error_check(ctx, 2, target, level,
2803
                     xoffset, yoffset, 0, width, height, 1, format, imageSize);
2804
   if (error) {
2805
      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
2806
      return;
2807
   }
2808
 
2809
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2810
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2811
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2812
   assert(texImage);
2813
 
2814
   if ((GLint) format != texImage->IntFormat) {
2815
      _mesa_error(ctx, GL_INVALID_OPERATION,
2816
                  "glCompressedTexSubImage2D(format)");
2817
      return;
2818
   }
2819
 
2820
   if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
2821
       ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
2822
      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
2823
      return;
2824
   }
2825
 
2826
   if (width == 0 || height == 0 || !data)
2827
      return;  /* no-op, not an error */
2828
 
2829
   if (ctx->Driver.CompressedTexSubImage2D) {
2830
      (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
2831
                                             xoffset, yoffset, width, height,
2832
                                             format, imageSize, data,
2833
                                             texObj, texImage);
2834
   }
2835
   ctx->NewState |= _NEW_TEXTURE;
2836
}
2837
 
2838
 
2839
void
2840
_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2841
                                 GLint yoffset, GLint zoffset, GLsizei width,
2842
                                 GLsizei height, GLsizei depth, GLenum format,
2843
                                 GLsizei imageSize, const GLvoid *data)
2844
{
2845
   struct gl_texture_unit *texUnit;
2846
   struct gl_texture_object *texObj;
2847
   struct gl_texture_image *texImage;
2848
   GLenum error;
2849
   GET_CURRENT_CONTEXT(ctx);
2850
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2851
 
2852
   error = compressed_subtexture_error_check(ctx, 3, target, level,
2853
           xoffset, yoffset, zoffset, width, height, depth, format, imageSize);
2854
   if (error) {
2855
      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
2856
      return;
2857
   }
2858
 
2859
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2860
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2861
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2862
   assert(texImage);
2863
 
2864
   if ((GLint) format != texImage->IntFormat) {
2865
      _mesa_error(ctx, GL_INVALID_OPERATION,
2866
                  "glCompressedTexSubImage3D(format)");
2867
      return;
2868
   }
2869
 
2870
   if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
2871
       ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
2872
       ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
2873
      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
2874
      return;
2875
   }
2876
 
2877
   if (width == 0 || height == 0 || depth == 0 || !data)
2878
      return;  /* no-op, not an error */
2879
 
2880
   if (ctx->Driver.CompressedTexSubImage3D) {
2881
      (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
2882
                                             xoffset, yoffset, zoffset,
2883
                                             width, height, depth,
2884
                                             format, imageSize, data,
2885
                                             texObj, texImage);
2886
   }
2887
   ctx->NewState |= _NEW_TEXTURE;
2888
}
2889
 
2890
 
2891
void
2892
_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
2893
{
2894
   const struct gl_texture_unit *texUnit;
2895
   const struct gl_texture_object *texObj;
2896
   struct gl_texture_image *texImage;
2897
   GLint maxLevels;
2898
   GET_CURRENT_CONTEXT(ctx);
2899
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2900
 
2901
   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2902
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2903
   if (!texObj) {
2904
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
2905
      return;
2906
   }
2907
 
2908
   maxLevels = _mesa_max_texture_levels(ctx, target);
2909
   ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
2910
 
2911
   if (level < 0 || level >= maxLevels) {
2912
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2913
      return;
2914
   }
2915
 
2916
   if (is_proxy_target(target)) {
2917
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
2918
      return;
2919
   }
2920
 
2921
   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2922
   if (!texImage) {
2923
      /* probably invalid mipmap level */
2924
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2925
      return;
2926
   }
2927
 
2928
   if (!texImage->IsCompressed) {
2929
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
2930
      return;
2931
   }
2932
 
2933
   if (!img)
2934
      return;
2935
 
2936
   /* just memcpy, no pixelstore or pixel transfer */
2937
   MEMCPY(img, texImage->Data, texImage->CompressedSize);
2938
}