teximage.c 182 KB
Newer Older
jtg's avatar
jtg committed
1
/*
2
 * Mesa 3-D graphics library
Jouk Jansen's avatar
   
Jouk Jansen committed
3
 *
4
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
Jouk Jansen's avatar
   
Jouk Jansen committed
6
 *
jtg's avatar
jtg committed
7
8
9
10
11
12
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
Jouk Jansen's avatar
   
Jouk Jansen committed
13
 *
jtg's avatar
jtg committed
14
15
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
Jouk Jansen's avatar
   
Jouk Jansen committed
16
 *
jtg's avatar
jtg committed
17
18
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
21
22
23
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
jtg's avatar
jtg committed
24
25
 */

26

27
28
/**
 * \file teximage.c
29
 * Texture image-related functions.
30
31
 */

32
#include <stdbool.h>
33
#include "glheader.h"
34
#include "bufferobj.h"
jtg's avatar
jtg committed
35
#include "context.h"
36
#include "enums.h"
37
38
#include "fbobject.h"
#include "framebuffer.h"
39
#include "hash.h"
jtg's avatar
jtg committed
40
#include "image.h"
Brian Paul's avatar
Brian Paul committed
41
#include "imports.h"
42
#include "macros.h"
43
#include "multisample.h"
44
#include "pixelstore.h"
45
#include "state.h"
46
#include "texcompress.h"
47
#include "texcompress_cpal.h"
jtg's avatar
jtg committed
48
#include "teximage.h"
49
#include "texobj.h"
jtg's avatar
jtg committed
50
#include "texstate.h"
51
#include "texstorage.h"
52
#include "textureview.h"
Jouk Jansen's avatar
   
Jouk Jansen committed
53
#include "mtypes.h"
54
#include "glformats.h"
55
#include "texstore.h"
56
#include "pbo.h"
jtg's avatar
jtg committed
57
58


59
60
61
62
63
/**
 * State changes which we care about for glCopyTex[Sub]Image() calls.
 * In particular, we care about pixel transfer state and buffer state
 * (such as glReadBuffer to make sure we read from the right renderbuffer).
 */
64
#define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL)
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
 * Returns a corresponding internal floating point format for a given base
 * format as specifed by OES_texture_float. In case of GL_FLOAT, the internal
 * format needs to be a 32 bit component and in case of GL_HALF_FLOAT_OES it
 * needs to be a 16 bit component.
 *
 * For example, given base format GL_RGBA, type GL_Float return GL_RGBA32F_ARB.
 */
static GLenum
adjust_for_oes_float_texture(GLenum format, GLenum type)
{
   switch (type) {
   case GL_FLOAT:
      switch (format) {
      case GL_RGBA:
         return GL_RGBA32F;
      case GL_RGB:
         return GL_RGB32F;
      case GL_ALPHA:
         return GL_ALPHA32F_ARB;
      case GL_LUMINANCE:
         return GL_LUMINANCE32F_ARB;
      case GL_LUMINANCE_ALPHA:
         return GL_LUMINANCE_ALPHA32F_ARB;
      default:
         break;
      }
      break;

   case GL_HALF_FLOAT_OES:
      switch (format) {
      case GL_RGBA:
         return GL_RGBA16F;
      case GL_RGB:
         return GL_RGB16F;
      case GL_ALPHA:
         return GL_ALPHA16F_ARB;
      case GL_LUMINANCE:
         return GL_LUMINANCE16F_ARB;
      case GL_LUMINANCE_ALPHA:
         return GL_LUMINANCE_ALPHA16F_ARB;
      default:
         break;
      }
      break;
111

112
113
114
115
116
117
   default:
      break;
   }

   return format;
}
118

119

120
/**
121
122
 * Install gl_texture_image in a gl_texture_object according to the target
 * and level parameters.
123
124
125
126
127
 * 
 * \param tObj texture object.
 * \param target texture target.
 * \param level image level.
 * \param texImage texture image.
jtg's avatar
jtg committed
128
 */
129
130
131
132
static void
set_tex_image(struct gl_texture_object *tObj,
              GLenum target, GLint level,
              struct gl_texture_image *texImage)
133
{
134
135
   const GLuint face = _mesa_tex_target_to_face(target);

136
137
   assert(tObj);
   assert(texImage);
138
139
   if (target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_EXTERNAL_OES)
      assert(level == 0);
140
141
142

   tObj->Image[face][level] = texImage;

Brian Paul's avatar
Brian Paul committed
143
144
   /* Set the 'back' pointer */
   texImage->TexObject = tObj;
145
146
   texImage->Level = level;
   texImage->Face = face;
147
148
149
}


150
/**
151
 * Allocate a texture image structure.
152
 *
153
154
 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
 * driver.
155
156
157
 *
 * \return a pointer to gl_texture_image struct with all fields initialized to
 * zero.
Brian Paul's avatar
Brian Paul committed
158
159
 */
struct gl_texture_image *
160
_mesa_new_texture_image( struct gl_context *ctx )
Brian Paul's avatar
Brian Paul committed
161
{
162
   (void) ctx;
Brian Paul's avatar
Brian Paul committed
163
164
165
166
   return CALLOC_STRUCT(gl_texture_image);
}


167
/**
168
169
 * Free a gl_texture_image and associated data.
 * This function is a fallback called via ctx->Driver.DeleteTextureImage().
170
 *
Vinson Lee's avatar
Vinson Lee committed
171
 * \param texImage texture image.
172
 *
173
 * Free the texture image structure and the associated image data.
174
 */
Brian Paul's avatar
Brian Paul committed
175
void
Brian Paul's avatar
Brian Paul committed
176
177
_mesa_delete_texture_image(struct gl_context *ctx,
                           struct gl_texture_image *texImage)
Brian Paul's avatar
Brian Paul committed
178
{
Keith Whitwell's avatar
Keith Whitwell committed
179
180
181
   /* Free texImage->Data and/or any other driver-specific texture
    * image storage.
    */
182
   assert(ctx->Driver.FreeTextureImageBuffer);
183
   ctx->Driver.FreeTextureImageBuffer( ctx, texImage );
184
   free(texImage);
Brian Paul's avatar
Brian Paul committed
185
186
187
}


188
189
190
191
192
193
/**
 * Test if a target is a proxy target.
 *
 * \param target texture target.
 *
 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
194
 */
195
196
GLboolean
_mesa_is_proxy_texture(GLenum target)
197
{
198
199
200
201
202
203
204
205
206
207
208
209
210
   unsigned i;
   static const GLenum targets[] = {
      GL_PROXY_TEXTURE_1D,
      GL_PROXY_TEXTURE_2D,
      GL_PROXY_TEXTURE_3D,
      GL_PROXY_TEXTURE_CUBE_MAP,
      GL_PROXY_TEXTURE_RECTANGLE,
      GL_PROXY_TEXTURE_1D_ARRAY,
      GL_PROXY_TEXTURE_2D_ARRAY,
      GL_PROXY_TEXTURE_CUBE_MAP_ARRAY,
      GL_PROXY_TEXTURE_2D_MULTISAMPLE,
      GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY
   };
211
   /*
212
    * NUM_TEXTURE_TARGETS should match number of terms above, except there's no
213
    * proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES.
214
    */
215
   STATIC_ASSERT(NUM_TEXTURE_TARGETS == ARRAY_SIZE(targets) + 2);
216

217
   for (i = 0; i < ARRAY_SIZE(targets); ++i)
218
219
220
      if (target == targets[i])
         return GL_TRUE;
   return GL_FALSE;
221
222
223
}


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/**
 * Test if a target is an array target.
 *
 * \param target texture target.
 *
 * \return true if the target is an array target, false otherwise.
 */
bool
_mesa_is_array_texture(GLenum target)
{
   switch (target) {
   case GL_TEXTURE_1D_ARRAY:
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
      return true;
   default:
      return false;
   };
}

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/**
 * Test if a target is a cube map.
 *
 * \param target texture target.
 *
 * \return true if the target is a cube map, false otherwise.
 */
bool
_mesa_is_cube_map_texture(GLenum target)
{
   switch(target) {
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
      return true;
   default:
      return false;
   }
}
263

264
265
266
/**
 * Return the proxy target which corresponds to the given texture target
 */
267
268
static GLenum
proxy_target(GLenum target)
269
270
271
272
273
274
275
276
277
278
279
{
   switch (target) {
   case GL_TEXTURE_1D:
   case GL_PROXY_TEXTURE_1D:
      return GL_PROXY_TEXTURE_1D;
   case GL_TEXTURE_2D:
   case GL_PROXY_TEXTURE_2D:
      return GL_PROXY_TEXTURE_2D;
   case GL_TEXTURE_3D:
   case GL_PROXY_TEXTURE_3D:
      return GL_PROXY_TEXTURE_3D;
280
281
282
283
284
285
286
287
288
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   case GL_TEXTURE_CUBE_MAP:
   case GL_PROXY_TEXTURE_CUBE_MAP:
      return GL_PROXY_TEXTURE_CUBE_MAP;
289
290
291
292
293
294
295
296
297
   case GL_TEXTURE_RECTANGLE_NV:
   case GL_PROXY_TEXTURE_RECTANGLE_NV:
      return GL_PROXY_TEXTURE_RECTANGLE_NV;
   case GL_TEXTURE_1D_ARRAY_EXT:
   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
      return GL_PROXY_TEXTURE_1D_ARRAY_EXT;
   case GL_TEXTURE_2D_ARRAY_EXT:
   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
      return GL_PROXY_TEXTURE_2D_ARRAY_EXT;
298
299
300
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
      return GL_PROXY_TEXTURE_CUBE_MAP_ARRAY;
301
302
303
304
305
306
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
      return GL_PROXY_TEXTURE_2D_MULTISAMPLE;
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
      return GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY;
307
   default:
308
      _mesa_problem(NULL, "unexpected target in proxy_target()");
309
310
311
312
313
      return 0;
   }
}


314

315

316
/**
317
318
319
 * Get a texture image pointer from a texture object, given a texture
 * target and mipmap level.  The target and level parameters should
 * have already been error-checked.
320
 *
Vinson Lee's avatar
Vinson Lee committed
321
 * \param texObj texture unit.
322
323
324
 * \param target texture target.
 * \param level image level.
 *
325
 * \return pointer to the texture image structure, or NULL on failure.
326
327
 */
struct gl_texture_image *
328
_mesa_select_tex_image(const struct gl_texture_object *texObj,
329
		                 GLenum target, GLint level)
330
{
331
   const GLuint face = _mesa_tex_target_to_face(target);
Keith Whitwell's avatar
Keith Whitwell committed
332

333
334
335
   assert(texObj);
   assert(level >= 0);
   assert(level < MAX_TEXTURE_LEVELS);
336

337
   return texObj->Image[face][level];
338
339
340
}


341
342
343
344
345
346
/**
 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
 * it and install it.  Only return NULL if passed a bad parameter or run
 * out of memory.
 */
struct gl_texture_image *
347
_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj,
348
349
350
                    GLenum target, GLint level)
{
   struct gl_texture_image *texImage;
Keith Whitwell's avatar
Keith Whitwell committed
351
352
353

   if (!texObj)
      return NULL;
354

355
   texImage = _mesa_select_tex_image(texObj, target, level);
356
357
358
359
360
361
   if (!texImage) {
      texImage = ctx->Driver.NewTextureImage(ctx);
      if (!texImage) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
         return NULL;
      }
Keith Whitwell's avatar
Keith Whitwell committed
362

363
      set_tex_image(texObj, target, level, texImage);
364
   }
Keith Whitwell's avatar
Keith Whitwell committed
365

366
367
368
369
370
371
372
373
374
375
   return texImage;
}


/**
 * Return pointer to the specified proxy texture image.
 * Note that proxy textures are per-context, not per-texture unit.
 * \return pointer to texture image or NULL if invalid target, invalid
 *         level, or out of memory.
 */
376
377
static struct gl_texture_image *
get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
378
379
{
   struct gl_texture_image *texImage;
380
   GLuint texIndex;
381

382
   if (level < 0)
383
384
385
386
387
388
      return NULL;

   switch (target) {
   case GL_PROXY_TEXTURE_1D:
      if (level >= ctx->Const.MaxTextureLevels)
         return NULL;
389
390
      texIndex = TEXTURE_1D_INDEX;
      break;
391
392
393
   case GL_PROXY_TEXTURE_2D:
      if (level >= ctx->Const.MaxTextureLevels)
         return NULL;
394
395
      texIndex = TEXTURE_2D_INDEX;
      break;
396
397
398
   case GL_PROXY_TEXTURE_3D:
      if (level >= ctx->Const.Max3DTextureLevels)
         return NULL;
399
400
      texIndex = TEXTURE_3D_INDEX;
      break;
401
402
403
   case GL_PROXY_TEXTURE_CUBE_MAP:
      if (level >= ctx->Const.MaxCubeTextureLevels)
         return NULL;
404
405
      texIndex = TEXTURE_CUBE_INDEX;
      break;
406
407
408
   case GL_PROXY_TEXTURE_RECTANGLE_NV:
      if (level > 0)
         return NULL;
409
410
      texIndex = TEXTURE_RECT_INDEX;
      break;
411
412
413
   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
      if (level >= ctx->Const.MaxTextureLevels)
         return NULL;
414
415
      texIndex = TEXTURE_1D_ARRAY_INDEX;
      break;
416
417
418
   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
      if (level >= ctx->Const.MaxTextureLevels)
         return NULL;
419
420
      texIndex = TEXTURE_2D_ARRAY_INDEX;
      break;
421
422
423
424
425
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
      if (level >= ctx->Const.MaxCubeTextureLevels)
         return NULL;
      texIndex = TEXTURE_CUBE_ARRAY_INDEX;
      break;
426
427
428
429
430
431
432
433
434
435
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
      if (level > 0)
         return 0;
      texIndex = TEXTURE_2D_MULTISAMPLE_INDEX;
      break;
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
      if (level > 0)
         return 0;
      texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX;
      break;
436
437
438
   default:
      return NULL;
   }
439
440
441
442
443
444
445
446
447
448
449
450
451

   texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
   if (!texImage) {
      texImage = ctx->Driver.NewTextureImage(ctx);
      if (!texImage) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
         return NULL;
      }
      ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
      /* Set the 'back' pointer */
      texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
   }
   return texImage;
452
453
454
}


455
456
457
458
459
/**
 * Get the maximum number of allowed mipmap levels.
 *
 * \param ctx GL context.
 * \param target texture target.
460
 *
461
462
463
464
 * \return the maximum number of allowed mipmap levels for the given
 * texture target, or zero if passed a bad target.
 *
 * \sa gl_constants.
465
466
 */
GLint
467
_mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
468
469
470
471
472
473
474
475
476
477
{
   switch (target) {
   case GL_TEXTURE_1D:
   case GL_PROXY_TEXTURE_1D:
   case GL_TEXTURE_2D:
   case GL_PROXY_TEXTURE_2D:
      return ctx->Const.MaxTextureLevels;
   case GL_TEXTURE_3D:
   case GL_PROXY_TEXTURE_3D:
      return ctx->Const.Max3DTextureLevels;
478
   case GL_TEXTURE_CUBE_MAP:
479
480
481
482
483
484
485
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   case GL_PROXY_TEXTURE_CUBE_MAP:
486
487
      return ctx->Extensions.ARB_texture_cube_map
         ? ctx->Const.MaxCubeTextureLevels : 0;
488
489
   case GL_TEXTURE_RECTANGLE_NV:
   case GL_PROXY_TEXTURE_RECTANGLE_NV:
490
491
492
493
494
      return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
   case GL_TEXTURE_1D_ARRAY_EXT:
   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
   case GL_TEXTURE_2D_ARRAY_EXT:
   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
495
      return ctx->Extensions.EXT_texture_array
496
         ? ctx->Const.MaxTextureLevels : 0;
497
498
499
500
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
      return ctx->Extensions.ARB_texture_cube_map_array
         ? ctx->Const.MaxCubeTextureLevels : 0;
501
   case GL_TEXTURE_BUFFER:
502
503
      return (_mesa_has_ARB_texture_buffer_object(ctx) ||
              _mesa_has_OES_texture_buffer(ctx)) ? 1 : 0;
504
505
506
507
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
508
      return (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx))
509
510
         && ctx->Extensions.ARB_texture_multisample
         ? 1 : 0;
511
   case GL_TEXTURE_EXTERNAL_OES:
512
      /* fall-through */
513
514
515
516
517
518
   default:
      return 0; /* bad target */
   }
}


519
/**
520
 * Return number of dimensions per mipmap level for the given texture target.
521
 */
522
523
GLint
_mesa_get_texture_dimensions(GLenum target)
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
{
   switch (target) {
   case GL_TEXTURE_1D:
   case GL_PROXY_TEXTURE_1D:
      return 1;
   case GL_TEXTURE_2D:
   case GL_TEXTURE_RECTANGLE:
   case GL_TEXTURE_CUBE_MAP:
   case GL_PROXY_TEXTURE_2D:
   case GL_PROXY_TEXTURE_RECTANGLE:
   case GL_PROXY_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
541
542
   case GL_TEXTURE_1D_ARRAY:
   case GL_PROXY_TEXTURE_1D_ARRAY:
543
   case GL_TEXTURE_EXTERNAL_OES:
544
545
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
546
547
548
      return 2;
   case GL_TEXTURE_3D:
   case GL_PROXY_TEXTURE_3D:
549
550
   case GL_TEXTURE_2D_ARRAY:
   case GL_PROXY_TEXTURE_2D_ARRAY:
551
552
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
553
554
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
555
      return 3;
556
557
   case GL_TEXTURE_BUFFER:
      /* fall-through */
558
559
560
561
562
563
564
565
   default:
      _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()",
                    target);
      return 2;
   }
}


566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
/**
 * Check if a texture target can have more than one layer.
 */
GLboolean
_mesa_tex_target_is_layered(GLenum target)
{
   switch (target) {
   case GL_TEXTURE_1D:
   case GL_PROXY_TEXTURE_1D:
   case GL_TEXTURE_2D:
   case GL_PROXY_TEXTURE_2D:
   case GL_TEXTURE_RECTANGLE:
   case GL_PROXY_TEXTURE_RECTANGLE:
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_BUFFER:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   case GL_TEXTURE_EXTERNAL_OES:
      return GL_FALSE;

   case GL_TEXTURE_3D:
   case GL_PROXY_TEXTURE_3D:
   case GL_TEXTURE_CUBE_MAP:
   case GL_PROXY_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_1D_ARRAY:
   case GL_PROXY_TEXTURE_1D_ARRAY:
   case GL_TEXTURE_2D_ARRAY:
   case GL_PROXY_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
      return GL_TRUE;

   default:
      assert(!"Invalid texture target.");
      return GL_FALSE;
   }
}


/**
 * Return the number of layers present in the given level of an array,
 * cubemap or 3D texture.  If the texture is not layered return zero.
 */
GLuint
_mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level)
{
   assert(level >= 0 && level < MAX_TEXTURE_LEVELS);

   switch (texObj->Target) {
   case GL_TEXTURE_1D:
   case GL_TEXTURE_2D:
   case GL_TEXTURE_RECTANGLE:
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_BUFFER:
   case GL_TEXTURE_EXTERNAL_OES:
      return 0;

   case GL_TEXTURE_CUBE_MAP:
      return 6;

   case GL_TEXTURE_1D_ARRAY: {
      struct gl_texture_image *img = texObj->Image[0][level];
      return img ? img->Height : 0;
   }

   case GL_TEXTURE_3D:
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
      struct gl_texture_image *img = texObj->Image[0][level];
      return img ? img->Depth : 0;
   }

   default:
      assert(!"Invalid texture target.");
      return 0;
   }
}


653
654
655
656
657
658
659
660
661
662
663
664
665
666
/**
 * Return the maximum number of mipmap levels for the given target
 * and the dimensions.
 * The dimensions are expected not to include the border.
 */
GLsizei
_mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height,
                             GLsizei depth)
{
   GLsizei size;

   switch (target) {
   case GL_TEXTURE_1D:
   case GL_TEXTURE_1D_ARRAY:
667
668
   case GL_PROXY_TEXTURE_1D:
   case GL_PROXY_TEXTURE_1D_ARRAY:
669
670
671
672
      size = width;
      break;
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
673
674
   case GL_PROXY_TEXTURE_CUBE_MAP:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
675
676
677
678
      size = width;
      break;
   case GL_TEXTURE_2D:
   case GL_TEXTURE_2D_ARRAY:
679
680
   case GL_PROXY_TEXTURE_2D:
   case GL_PROXY_TEXTURE_2D_ARRAY:
681
682
683
      size = MAX2(width, height);
      break;
   case GL_TEXTURE_3D:
684
   case GL_PROXY_TEXTURE_3D:
685
686
687
      size = MAX3(width, height, depth);
      break;
   case GL_TEXTURE_RECTANGLE:
688
   case GL_TEXTURE_EXTERNAL_OES:
689
690
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
691
692
693
   case GL_PROXY_TEXTURE_RECTANGLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
694
695
696
697
698
699
700
701
      return 1;
   default:
      assert(0);
      return 1;
   }

   return _mesa_logbase2(size) + 1;
}
702

703

704
#if 000 /* not used anymore */
jtg's avatar
jtg committed
705
706
707
/*
 * glTexImage[123]D can accept a NULL image pointer.  In this case we
 * create a texture image with unspecified image contents per the OpenGL
708
 * spec.
jtg's avatar
jtg committed
709
 */
710
711
static GLubyte *
make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
jtg's avatar
jtg committed
712
{
713
714
   const GLint components = _mesa_components_in_format(format);
   const GLint numPixels = width * height * depth;
Brian Paul's avatar
Brian Paul committed
715
   GLubyte *data = (GLubyte *) malloc(numPixels * components * sizeof(GLubyte));
jtg's avatar
jtg committed
716

717
#ifdef DEBUG
jtg's avatar
jtg committed
718
719
720
721
722
   /*
    * Let's see if anyone finds this.  If glTexImage2D() is called with
    * a NULL image pointer then load the texture image with something
    * interesting instead of leaving it indeterminate.
    */
723
   if (data) {
724
      static const char message[8][32] = {
jtg's avatar
jtg committed
725
726
727
728
729
730
731
732
733
734
         "   X   X  XXXXX   XXX     X    ",
         "   XX XX  X      X   X   X X   ",
         "   X X X  X      X      X   X  ",
         "   X   X  XXXX    XXX   XXXXX  ",
         "   X   X  X          X  X   X  ",
         "   X   X  X      X   X  X   X  ",
         "   X   X  XXXXX   XXX   X   X  ",
         "                               "
      };

735
736
737
738
739
740
741
742
743
744
745
      GLubyte *imgPtr = data;
      GLint h, i, j, k;
      for (h = 0; h < depth; h++) {
         for (i = 0; i < height; i++) {
            GLint srcRow = 7 - (i % 8);
            for (j = 0; j < width; j++) {
               GLint srcCol = j % 32;
               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
               for (k = 0; k < components; k++) {
                  *imgPtr++ = texel;
               }
jtg's avatar
jtg committed
746
747
748
749
            }
         }
      }
   }
750
#endif
751
752

   return data;
jtg's avatar
jtg committed
753
}
754
#endif
jtg's avatar
jtg committed
755
756
757



758
/**
759
760
 * Set the size and format-related fields of a gl_texture_image struct
 * to zero.  This is used when a proxy texture test fails.
761
762
 */
static void
763
clear_teximage_fields(struct gl_texture_image *img)
764
{
765
   assert(img);
766
767
   img->_BaseFormat = 0;
   img->InternalFormat = 0;
768
769
770
771
772
773
774
775
776
777
   img->Border = 0;
   img->Width = 0;
   img->Height = 0;
   img->Depth = 0;
   img->Width2 = 0;
   img->Height2 = 0;
   img->Depth2 = 0;
   img->WidthLog2 = 0;
   img->HeightLog2 = 0;
   img->DepthLog2 = 0;
778
   img->TexFormat = MESA_FORMAT_NONE;
779
780
   img->NumSamples = 0;
   img->FixedSampleLocations = GL_TRUE;
781
782
783
}


784
/**
785
 * Initialize basic fields of the gl_texture_image struct.
786
787
788
789
790
791
792
793
 *
 * \param ctx GL context.
 * \param img texture image structure to be initialized.
 * \param width image width.
 * \param height image height.
 * \param depth image depth.
 * \param border image border.
 * \param internalFormat internal format.
794
 * \param format  the actual hardware format (one of MESA_FORMAT_*)
795
796
 * \param numSamples  number of samples per texel, or zero for non-MS.
 * \param fixedSampleLocations  are sample locations fixed?
797
798
 *
 * Fills in the fields of \p img with the given information.
799
 * Note: width, height and depth include the border.
800
 */
801
802
803
804
805
806
807
static void
init_teximage_fields_ms(struct gl_context *ctx,
                        struct gl_texture_image *img,
                        GLsizei width, GLsizei height, GLsizei depth,
                        GLint border, GLenum internalFormat,
                        mesa_format format,
                        GLuint numSamples, GLboolean fixedSampleLocations)
808
{
809
   GLenum target;
810
811
812
813
   assert(img);
   assert(width >= 0);
   assert(height >= 0);
   assert(depth >= 0);
814

815
   target = img->TexObject->Target;
816
   img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
817
   assert(img->_BaseFormat != -1);
818
   img->InternalFormat = internalFormat;
819
820
821
822
   img->Border = border;
   img->Width = width;
   img->Height = height;
   img->Depth = depth;
823

824
   img->Width2 = width - 2 * border;   /* == 1 << img->WidthLog2; */
825
   img->WidthLog2 = _mesa_logbase2(img->Width2);
826

827
828
829
   img->NumSamples = 0;
   img->FixedSampleLocations = GL_TRUE;

830
831
832
833
834
835
836
837
   switch(target) {
   case GL_TEXTURE_1D:
   case GL_TEXTURE_BUFFER:
   case GL_PROXY_TEXTURE_1D:
      if (height == 0)
         img->Height2 = 0;
      else
         img->Height2 = 1;
838
      img->HeightLog2 = 0;
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
      if (depth == 0)
         img->Depth2 = 0;
      else
         img->Depth2 = 1;
      img->DepthLog2 = 0;
      break;
   case GL_TEXTURE_1D_ARRAY:
   case GL_PROXY_TEXTURE_1D_ARRAY:
      img->Height2 = height; /* no border */
      img->HeightLog2 = 0; /* not used */
      if (depth == 0)
         img->Depth2 = 0;
      else
         img->Depth2 = 1;
      img->DepthLog2 = 0;
      break;
   case GL_TEXTURE_2D:
   case GL_TEXTURE_RECTANGLE:
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   case GL_TEXTURE_EXTERNAL_OES:
   case GL_PROXY_TEXTURE_2D:
   case GL_PROXY_TEXTURE_RECTANGLE:
   case GL_PROXY_TEXTURE_CUBE_MAP:
868
869
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
870
      img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
871
      img->HeightLog2 = _mesa_logbase2(img->Height2);
872
873
874
875
      if (depth == 0)
         img->Depth2 = 0;
      else
         img->Depth2 = 1;
876
      img->DepthLog2 = 0;
877
878
879
      break;
   case GL_TEXTURE_2D_ARRAY:
   case GL_PROXY_TEXTURE_2D_ARRAY:
880
881
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
882
883
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
884
885
886
887
888
889
890
891
892
      img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
      img->HeightLog2 = _mesa_logbase2(img->Height2);
      img->Depth2 = depth; /* no border */
      img->DepthLog2 = 0; /* not used */
      break;
   case GL_TEXTURE_3D:
   case GL_PROXY_TEXTURE_3D:
      img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
      img->HeightLog2 = _mesa_logbase2(img->Height2);
893
      img->Depth2 = depth - 2 * border;   /* == 1 << img->DepthLog2; */
894
      img->DepthLog2 = _mesa_logbase2(img->Depth2);
895
896
897
898
      break;
   default:
      _mesa_problem(NULL, "invalid target 0x%x in _mesa_init_teximage_fields()",
                    target);
899
900
   }

901
902
903
   img->MaxNumLevels =
      _mesa_get_tex_max_num_levels(target,
                                   img->Width2, img->Height2, img->Depth2);
904
   img->TexFormat = format;
905
906
907
908
909
910
911
912
913
914
915
916
917
918
   img->NumSamples = numSamples;
   img->FixedSampleLocations = fixedSampleLocations;
}


void
_mesa_init_teximage_fields(struct gl_context *ctx,
                           struct gl_texture_image *img,
                           GLsizei width, GLsizei height, GLsizei depth,
                           GLint border, GLenum internalFormat,
                           mesa_format format)
{
   init_teximage_fields_ms(ctx, img, width, height, depth, border,
                           internalFormat, format, 0, GL_TRUE);
919
920
921
}


922
923
924
925
926
927
928
929
930
931
/**
 * Free and clear fields of the gl_texture_image struct.
 *
 * \param ctx GL context.
 * \param texImage texture image structure to be cleared.
 *
 * After the call, \p texImage will have no data associated with it.  Its
 * fields are cleared so that its parent object will test incomplete.
 */
void
Brian Paul's avatar
Brian Paul committed
932
933
_mesa_clear_texture_image(struct gl_context *ctx,
                          struct gl_texture_image *texImage)
934
{
935
   ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
936
937
938
939
   clear_teximage_fields(texImage);
}


940
/**
941
942
943
 * Check the width, height, depth and border of a texture image are legal.
 * Used by all the glTexImage, glCompressedTexImage and glCopyTexImage
 * functions.
944
945
 * The target and level parameters will have already been validated.
 * \return GL_TRUE if size is OK, GL_FALSE otherwise.
946
947
 */
GLboolean
948
949
950
_mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
                               GLint level, GLint width, GLint height,
                               GLint depth, GLint border)
951
952
{
   GLint maxSize;
953

954
   switch (target) {
955
   case GL_TEXTURE_1D:
956
   case GL_PROXY_TEXTURE_1D:
957
958
959
960
      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); /* level zero size */
      maxSize >>= level;  /* level size */
      if (width < 2 * border || width > 2 * border + maxSize)
         return GL_FALSE;
961
962
963
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
964
965
      }
      return GL_TRUE;
966

967
   case GL_TEXTURE_2D:
968
   case GL_PROXY_TEXTURE_2D:
969
970
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
971
      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
972
      maxSize >>= level;
973
      if (width < 2 * border || width > 2 * border + maxSize)
974
         return GL_FALSE;
975
      if (height < 2 * border || height > 2 * border + maxSize)
976
         return GL_FALSE;
977
978
979
980
981
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
         if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
            return GL_FALSE;
982
983
      }
      return GL_TRUE;
984

985
   case GL_TEXTURE_3D:
986
987
   case GL_PROXY_TEXTURE_3D:
      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
988
      maxSize >>= level;
989
      if (width < 2 * border || width > 2 * border + maxSize)
990
         return GL_FALSE;
991
      if (height < 2 * border || height > 2 * border + maxSize)
992
         return GL_FALSE;
993
      if (depth < 2 * border || depth > 2 * border + maxSize)
994
995
996
997
998
999
1000
1001
         return GL_FALSE;
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
         if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
            return GL_FALSE;
         if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border))
            return GL_FALSE;
1002
1003
      }
      return GL_TRUE;
1004

1005
   case GL_TEXTURE_RECTANGLE_NV:
1006
   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1007
1008
      if (level != 0)
         return GL_FALSE;
1009
1010
1011
1012
1013
      maxSize = ctx->Const.MaxTextureRectSize;
      if (width < 0 || width > maxSize)
         return GL_FALSE;
      if (height < 0 || height > maxSize)
         return GL_FALSE;
1014
      return GL_TRUE;
1015

1016
   case GL_TEXTURE_CUBE_MAP:
1017
1018
1019
1020
1021
1022
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1023
   case GL_PROXY_TEXTURE_CUBE_MAP:
1024
      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1025
      maxSize >>= level;
1026
1027
      if (width != height)
         return GL_FALSE;
1028
      if (width < 2 * border || width > 2 * border + maxSize)
1029
         return GL_FALSE;
1030
      if (height < 2 * border || height > 2 * border + maxSize)
1031
1032
1033
1034
1035
1036
         return GL_FALSE;
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
         if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
            return GL_FALSE;
1037
1038
      }
      return GL_TRUE;
1039

1040
   case GL_TEXTURE_1D_ARRAY_EXT:
1041
1042
   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1043
      maxSize >>= level;
1044
      if (width < 2 * border || width > 2 * border + maxSize)
1045
         return GL_FALSE;
1046
      if (height < 0 || height > ctx->Const.MaxArrayTextureLayers)
1047
         return GL_FALSE;
1048
1049
1050
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
1051
1052
      }
      return GL_TRUE;
1053

1054
   case GL_TEXTURE_2D_ARRAY_EXT:
1055
   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1056
1057
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
1058
      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1059
      maxSize >>= level;
1060
      if (width < 2 * border || width > 2 * border + maxSize)
1061
         return GL_FALSE;
1062
      if (height < 2 * border || height > 2 * border + maxSize)
1063
         return GL_FALSE;
1064
      if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers)
1065
         return GL_FALSE;
1066
1067
1068
1069
1070
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
         if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
            return GL_FALSE;
1071
1072
      }
      return GL_TRUE;
1073

1074
1075
1076
1077
1078
1079
1080
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
      if (width < 2 * border || width > 2 * border + maxSize)
         return GL_FALSE;
      if (height < 2 * border || height > 2 * border + maxSize)
         return GL_FALSE;
1081
      if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers || depth % 6)
1082
1083
         return GL_FALSE;
      if (width != height)
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
         return GL_FALSE;
      if (level >= ctx->Const.MaxCubeTextureLevels)
         return GL_FALSE;
      if (!ctx->Extensions.ARB_texture_non_power_of_two) {
         if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
            return GL_FALSE;
         if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
            return GL_FALSE;
      }
      return GL_TRUE;
1094
   default:
1095
      _mesa_problem(ctx, "Invalid target in _mesa_legal_texture_dimensions()");
1096
1097
1098
1099
1100
      return GL_FALSE;
   }
}


1101
/**
1102
1103
1104
 * Do error checking of xoffset, yoffset, zoffset, width, height and depth
 * for glTexSubImage, glCopyTexSubImage and glCompressedTexSubImage.
 * \param destImage  the destination texture image.
1105
1106
1107
 * \return GL_TRUE if error found, GL_FALSE otherwise.
 */
static GLboolean
1108
error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
1109
1110
                                  const struct gl_texture_image *destImage,
                                  GLint xoffset, GLint yoffset, GLint zoffset,
1111
                                  GLsizei subWidth, GLsizei subHeight,
1112
                                  GLsizei subDepth, const char *func)
1113
{
1114
   const GLenum target = destImage->TexObject->Target;
1115
   GLuint bw, bh, bd;
1116

1117
1118
1119
   /* Check size */
   if (subWidth < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE,
1120
                  "%s(width=%d)", func, subWidth);
1121
1122
1123
1124
1125
      return GL_TRUE;
   }

   if (dims > 1 && subHeight < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE,
1126
                  "%s(height=%d)", func, subHeight);
1127
1128
1129
1130
1131
      return GL_TRUE;
   }

   if (dims > 2 && subDepth < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE,
1132
                  "%s(depth=%d)", func, subDepth);
1133
1134
1135
1136
      return GL_TRUE;
   }

   /* check xoffset and width */
1137
   if (xoffset < - (GLint) destImage->Border) {
1138
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset)", func);
1139
1140
1141
      return GL_TRUE;
   }

1142
   if (xoffset + subWidth > (GLint) destImage->Width) {
1143
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset+width)", func);
1144
1145
1146
1147
1148
1149
1150
      return GL_TRUE;
   }

   /* check yoffset and height */
   if (dims > 1) {
      GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border;
      if (yoffset < -yBorder) {
1151
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset)", func);
1152
1153
         return GL_TRUE;
      }
1154
      if (yoffset + subHeight > (GLint) destImage->Height) {
1155
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset+height)", func);
1156
1157
1158
1159
1160
1161
         return GL_TRUE;
      }
   }

   /* check zoffset and depth */
   if (dims > 2) {
1162
      GLint depth;
1163
1164
1165
1166
      GLint zBorder = (target == GL_TEXTURE_2D_ARRAY ||
                       target == GL_TEXTURE_CUBE_MAP_ARRAY) ?
                         0 : destImage->Border;

1167
      if (zoffset < -zBorder) {
1168
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset)", func);
1169
1170
         return GL_TRUE;
      }
1171
1172
1173
1174
1175

      depth = (GLint) destImage->Depth;
      if (target == GL_TEXTURE_CUBE_MAP)
         depth = 6;
      if (zoffset + subDepth  > depth) {
1176
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset+depth)", func);
1177
1178
1179
1180
         return GL_TRUE;
      }
   }

1181
1182
1183
1184
1185
1186
1187
   /*
    * The OpenGL spec (and GL_ARB_texture_compression) says only whole