Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / main / texobj.c
1 /**
2  * \file texobj.c
3  * Texture object management.
4  */
5
6 /*
7  * Mesa 3-D graphics library
8  * Version:  7.1
9  *
10  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28  */
29
30
31 #include "mfeatures.h"
32 #include "bufferobj.h"
33 #include "colortab.h"
34 #include "context.h"
35 #include "enums.h"
36 #include "fbobject.h"
37 #include "formats.h"
38 #include "hash.h"
39 #include "imports.h"
40 #include "macros.h"
41 #include "teximage.h"
42 #include "texobj.h"
43 #include "texstate.h"
44 #include "mtypes.h"
45 #include "program/prog_instruction.h"
46
47
48
49 /**********************************************************************/
50 /** \name Internal functions */
51 /*@{*/
52
53
54 /**
55  * Return the gl_texture_object for a given ID.
56  */
57 struct gl_texture_object *
58 _mesa_lookup_texture(struct gl_context *ctx, GLuint id)
59 {
60    return (struct gl_texture_object *)
61       _mesa_HashLookup(ctx->Shared->TexObjects, id);
62 }
63
64
65
66 /**
67  * Allocate and initialize a new texture object.  But don't put it into the
68  * texture object hash table.
69  *
70  * Called via ctx->Driver.NewTextureObject, unless overridden by a device
71  * driver.
72  * 
73  * \param shared the shared GL state structure to contain the texture object
74  * \param name integer name for the texture object
75  * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
76  * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV.  zero is ok for the sake
77  * of GenTextures()
78  *
79  * \return pointer to new texture object.
80  */
81 struct gl_texture_object *
82 _mesa_new_texture_object( struct gl_context *ctx, GLuint name, GLenum target )
83 {
84    struct gl_texture_object *obj;
85    (void) ctx;
86    obj = MALLOC_STRUCT(gl_texture_object);
87    _mesa_initialize_texture_object(obj, name, target);
88    return obj;
89 }
90
91
92 /**
93  * Initialize a new texture object to default values.
94  * \param obj  the texture object
95  * \param name  the texture name
96  * \param target  the texture target
97  */
98 void
99 _mesa_initialize_texture_object( struct gl_texture_object *obj,
100                                  GLuint name, GLenum target )
101 {
102    ASSERT(target == 0 ||
103           target == GL_TEXTURE_1D ||
104           target == GL_TEXTURE_2D ||
105           target == GL_TEXTURE_3D ||
106           target == GL_TEXTURE_CUBE_MAP_ARB ||
107           target == GL_TEXTURE_RECTANGLE_NV ||
108           target == GL_TEXTURE_1D_ARRAY_EXT ||
109           target == GL_TEXTURE_2D_ARRAY_EXT ||
110           target == GL_TEXTURE_BUFFER);
111
112    memset(obj, 0, sizeof(*obj));
113    /* init the non-zero fields */
114    _glthread_INIT_MUTEX(obj->Mutex);
115    obj->RefCount = 1;
116    obj->Name = name;
117    obj->Target = target;
118    obj->Priority = 1.0F;
119    obj->BaseLevel = 0;
120    obj->MaxLevel = 1000;
121
122    /* sampler state */
123    if (target == GL_TEXTURE_RECTANGLE_NV) {
124       obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
125       obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
126       obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
127       obj->Sampler.MinFilter = GL_LINEAR;
128    }
129    else {
130       obj->Sampler.WrapS = GL_REPEAT;
131       obj->Sampler.WrapT = GL_REPEAT;
132       obj->Sampler.WrapR = GL_REPEAT;
133       obj->Sampler.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
134    }
135    obj->Sampler.MagFilter = GL_LINEAR;
136    obj->Sampler.MinLod = -1000.0;
137    obj->Sampler.MaxLod = 1000.0;
138    obj->Sampler.LodBias = 0.0;
139    obj->Sampler.MaxAnisotropy = 1.0;
140    obj->Sampler.CompareMode = GL_NONE;         /* ARB_shadow */
141    obj->Sampler.CompareFunc = GL_LEQUAL;       /* ARB_shadow */
142    obj->Sampler.CompareFailValue = 0.0F;       /* ARB_shadow_ambient */
143    obj->Sampler.DepthMode = GL_LUMINANCE;      /* ARB_depth_texture */
144    obj->Sampler.CubeMapSeamless = GL_FALSE;
145    obj->Swizzle[0] = GL_RED;
146    obj->Swizzle[1] = GL_GREEN;
147    obj->Swizzle[2] = GL_BLUE;
148    obj->Swizzle[3] = GL_ALPHA;
149    obj->_Swizzle = SWIZZLE_NOOP;
150    obj->Sampler.sRGBDecode = GL_DECODE_EXT;
151 }
152
153
154 /**
155  * Some texture initialization can't be finished until we know which
156  * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
157  */
158 static void
159 finish_texture_init(struct gl_context *ctx, GLenum target,
160                     struct gl_texture_object *obj)
161 {
162    assert(obj->Target == 0);
163
164    if (target == GL_TEXTURE_RECTANGLE_NV) {
165       /* have to init wrap and filter state here - kind of klunky */
166       obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
167       obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
168       obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
169       obj->Sampler.MinFilter = GL_LINEAR;
170       if (ctx->Driver.TexParameter) {
171          static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
172          static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
173          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
174          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
175          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
176          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter);
177       }
178    }
179 }
180
181
182 /**
183  * Deallocate a texture object struct.  It should have already been
184  * removed from the texture object pool.
185  * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
186  *
187  * \param shared the shared GL state to which the object belongs.
188  * \param texObj the texture object to delete.
189  */
190 void
191 _mesa_delete_texture_object(struct gl_context *ctx,
192                             struct gl_texture_object *texObj)
193 {
194    GLuint i, face;
195
196    /* Set Target to an invalid value.  With some assertions elsewhere
197     * we can try to detect possible use of deleted textures.
198     */
199    texObj->Target = 0x99;
200
201    _mesa_free_colortable_data(&texObj->Palette);
202
203    /* free the texture images */
204    for (face = 0; face < 6; face++) {
205       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
206          if (texObj->Image[face][i]) {
207             _mesa_delete_texture_image( ctx, texObj->Image[face][i] );
208          }
209       }
210    }
211
212    _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
213
214    /* destroy the mutex -- it may have allocated memory (eg on bsd) */
215    _glthread_DESTROY_MUTEX(texObj->Mutex);
216
217    /* free this object */
218    free(texObj);
219 }
220
221
222
223 /**
224  * Copy texture object state from one texture object to another.
225  * Use for glPush/PopAttrib.
226  *
227  * \param dest destination texture object.
228  * \param src source texture object.
229  */
230 void
231 _mesa_copy_texture_object( struct gl_texture_object *dest,
232                            const struct gl_texture_object *src )
233 {
234    dest->Target = src->Target;
235    dest->Name = src->Name;
236    dest->Priority = src->Priority;
237    dest->Sampler.BorderColor.f[0] = src->Sampler.BorderColor.f[0];
238    dest->Sampler.BorderColor.f[1] = src->Sampler.BorderColor.f[1];
239    dest->Sampler.BorderColor.f[2] = src->Sampler.BorderColor.f[2];
240    dest->Sampler.BorderColor.f[3] = src->Sampler.BorderColor.f[3];
241    dest->Sampler.WrapS = src->Sampler.WrapS;
242    dest->Sampler.WrapT = src->Sampler.WrapT;
243    dest->Sampler.WrapR = src->Sampler.WrapR;
244    dest->Sampler.MinFilter = src->Sampler.MinFilter;
245    dest->Sampler.MagFilter = src->Sampler.MagFilter;
246    dest->Sampler.MinLod = src->Sampler.MinLod;
247    dest->Sampler.MaxLod = src->Sampler.MaxLod;
248    dest->Sampler.LodBias = src->Sampler.LodBias;
249    dest->BaseLevel = src->BaseLevel;
250    dest->MaxLevel = src->MaxLevel;
251    dest->Sampler.MaxAnisotropy = src->Sampler.MaxAnisotropy;
252    dest->Sampler.CompareMode = src->Sampler.CompareMode;
253    dest->Sampler.CompareFunc = src->Sampler.CompareFunc;
254    dest->Sampler.CompareFailValue = src->Sampler.CompareFailValue;
255    dest->Sampler.CubeMapSeamless = src->Sampler.CubeMapSeamless;
256    dest->Sampler.DepthMode = src->Sampler.DepthMode;
257    dest->Sampler.sRGBDecode = src->Sampler.sRGBDecode;
258    dest->_MaxLevel = src->_MaxLevel;
259    dest->_MaxLambda = src->_MaxLambda;
260    dest->GenerateMipmap = src->GenerateMipmap;
261    dest->Palette = src->Palette;
262    dest->_Complete = src->_Complete;
263    COPY_4V(dest->Swizzle, src->Swizzle);
264    dest->_Swizzle = src->_Swizzle;
265 }
266
267
268 /**
269  * Free all texture images of the given texture object.
270  *
271  * \param ctx GL context.
272  * \param t texture object.
273  *
274  * \sa _mesa_clear_texture_image().
275  */
276 void
277 _mesa_clear_texture_object(struct gl_context *ctx,
278                            struct gl_texture_object *texObj)
279 {
280    GLuint i, j;
281
282    if (texObj->Target == 0)
283       return;
284
285    for (i = 0; i < MAX_FACES; i++) {
286       for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
287          struct gl_texture_image *texImage = texObj->Image[i][j];
288          if (texImage)
289             _mesa_clear_texture_image(ctx, texImage);
290       }
291    }
292 }
293
294
295 /**
296  * Check if the given texture object is valid by examining its Target field.
297  * For debugging only.
298  */
299 static GLboolean
300 valid_texture_object(const struct gl_texture_object *tex)
301 {
302    switch (tex->Target) {
303    case 0:
304    case GL_TEXTURE_1D:
305    case GL_TEXTURE_2D:
306    case GL_TEXTURE_3D:
307    case GL_TEXTURE_CUBE_MAP_ARB:
308    case GL_TEXTURE_RECTANGLE_NV:
309    case GL_TEXTURE_1D_ARRAY_EXT:
310    case GL_TEXTURE_2D_ARRAY_EXT:
311    case GL_TEXTURE_BUFFER:
312       return GL_TRUE;
313    case 0x99:
314       _mesa_problem(NULL, "invalid reference to a deleted texture object");
315       return GL_FALSE;
316    default:
317       _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
318                     tex->Target, tex->Name);
319       return GL_FALSE;
320    }
321 }
322
323
324 /**
325  * Reference (or unreference) a texture object.
326  * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
327  * If 'tex' is non-null, increment its refcount.
328  */
329 void
330 _mesa_reference_texobj(struct gl_texture_object **ptr,
331                        struct gl_texture_object *tex)
332 {
333    assert(ptr);
334    if (*ptr == tex) {
335       /* no change */
336       return;
337    }
338
339    if (*ptr) {
340       /* Unreference the old texture */
341       GLboolean deleteFlag = GL_FALSE;
342       struct gl_texture_object *oldTex = *ptr;
343
344       ASSERT(valid_texture_object(oldTex));
345       (void) valid_texture_object; /* silence warning in release builds */
346
347       _glthread_LOCK_MUTEX(oldTex->Mutex);
348       ASSERT(oldTex->RefCount > 0);
349       oldTex->RefCount--;
350
351       deleteFlag = (oldTex->RefCount == 0);
352       _glthread_UNLOCK_MUTEX(oldTex->Mutex);
353
354       if (deleteFlag) {
355          GET_CURRENT_CONTEXT(ctx);
356          if (ctx)
357             ctx->Driver.DeleteTexture(ctx, oldTex);
358          else
359             _mesa_problem(NULL, "Unable to delete texture, no context");
360       }
361
362       *ptr = NULL;
363    }
364    assert(!*ptr);
365
366    if (tex) {
367       /* reference new texture */
368       ASSERT(valid_texture_object(tex));
369       _glthread_LOCK_MUTEX(tex->Mutex);
370       if (tex->RefCount == 0) {
371          /* this texture's being deleted (look just above) */
372          /* Not sure this can every really happen.  Warn if it does. */
373          _mesa_problem(NULL, "referencing deleted texture object");
374          *ptr = NULL;
375       }
376       else {
377          tex->RefCount++;
378          *ptr = tex;
379       }
380       _glthread_UNLOCK_MUTEX(tex->Mutex);
381    }
382 }
383
384
385
386 /**
387  * Mark a texture object as incomplete.
388  * \param t  texture object
389  * \param fmt...  string describing why it's incomplete (for debugging).
390  */
391 static void
392 incomplete(struct gl_texture_object *t, const char *fmt, ...)
393 {
394 #if 0
395    va_list args;
396    char s[100];
397
398    va_start(args, fmt);
399    vsnprintf(s, sizeof(s), fmt, args);
400    va_end(args);
401
402    printf("Texture Obj %d incomplete because: %s\n", t->Name, s);
403 #endif
404    t->_Complete = GL_FALSE;
405 }
406
407
408 /**
409  * Examine a texture object to determine if it is complete.
410  *
411  * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
412  * accordingly.
413  *
414  * \param ctx GL context.
415  * \param t texture object.
416  *
417  * According to the texture target, verifies that each of the mipmaps is
418  * present and has the expected size.
419  */
420 void
421 _mesa_test_texobj_completeness( const struct gl_context *ctx,
422                                 struct gl_texture_object *t )
423 {
424    const GLint baseLevel = t->BaseLevel;
425    GLint maxLog2 = 0, maxLevels = 0;
426
427    t->_Complete = GL_TRUE;  /* be optimistic */
428
429    /* Detect cases where the application set the base level to an invalid
430     * value.
431     */
432    if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
433       incomplete(t, "base level = %d is invalid", baseLevel);
434       return;
435    }
436
437    /* Always need the base level image */
438    if (!t->Image[0][baseLevel]) {
439       incomplete(t, "Image[baseLevel=%d] == NULL", baseLevel);
440       return;
441    }
442
443    /* Check width/height/depth for zero */
444    if (t->Image[0][baseLevel]->Width == 0 ||
445        t->Image[0][baseLevel]->Height == 0 ||
446        t->Image[0][baseLevel]->Depth == 0) {
447       incomplete(t, "texture width = 0");
448       return;
449    }
450
451    /* Compute _MaxLevel */
452    if ((t->Target == GL_TEXTURE_1D) ||
453        (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
454       maxLog2 = t->Image[0][baseLevel]->WidthLog2;
455       maxLevels = ctx->Const.MaxTextureLevels;
456    }
457    else if ((t->Target == GL_TEXTURE_2D) ||
458             (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
459       maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
460                      t->Image[0][baseLevel]->HeightLog2);
461       maxLevels = ctx->Const.MaxTextureLevels;
462    }
463    else if (t->Target == GL_TEXTURE_3D) {
464       GLint max = MAX2(t->Image[0][baseLevel]->WidthLog2,
465                        t->Image[0][baseLevel]->HeightLog2);
466       maxLog2 = MAX2(max, (GLint)(t->Image[0][baseLevel]->DepthLog2));
467       maxLevels = ctx->Const.Max3DTextureLevels;
468    }
469    else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
470       maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
471                      t->Image[0][baseLevel]->HeightLog2);
472       maxLevels = ctx->Const.MaxCubeTextureLevels;
473    }
474    else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
475       maxLog2 = 0;  /* not applicable */
476       maxLevels = 1;  /* no mipmapping */
477    }
478    else {
479       _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
480       return;
481    }
482
483    ASSERT(maxLevels > 0);
484
485    if (t->MaxLevel < t->BaseLevel) {
486       incomplete(t, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
487                  t->MaxLevel, t->BaseLevel);
488       return;
489    }
490
491    t->_MaxLevel = baseLevel + maxLog2;
492    t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
493    t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1);
494
495    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
496    t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
497
498    if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
499       /* make sure that all six cube map level 0 images are the same size */
500       const GLuint w = t->Image[0][baseLevel]->Width2;
501       const GLuint h = t->Image[0][baseLevel]->Height2;
502       GLuint face;
503       for (face = 1; face < 6; face++) {
504          if (t->Image[face][baseLevel] == NULL ||
505              t->Image[face][baseLevel]->Width2 != w ||
506              t->Image[face][baseLevel]->Height2 != h) {
507             incomplete(t, "Cube face missing or mismatched size");
508             return;
509          }
510       }
511    }
512
513    /* extra checking for mipmaps */
514    if (t->Sampler.MinFilter != GL_NEAREST && t->Sampler.MinFilter != GL_LINEAR) {
515       /*
516        * Mipmapping: determine if we have a complete set of mipmaps
517        */
518       GLint i;
519       GLint minLevel = baseLevel;
520       GLint maxLevel = t->_MaxLevel;
521
522       if (minLevel > maxLevel) {
523          incomplete(t, "minLevel > maxLevel");
524          return;
525       }
526
527       /* Test dimension-independent attributes */
528       for (i = minLevel; i <= maxLevel; i++) {
529          if (t->Image[0][i]) {
530             if (t->Image[0][i]->TexFormat != t->Image[0][baseLevel]->TexFormat) {
531                incomplete(t, "Format[i] != Format[baseLevel]");
532                return;
533             }
534             if (t->Image[0][i]->Border != t->Image[0][baseLevel]->Border) {
535                incomplete(t, "Border[i] != Border[baseLevel]");
536                return;
537             }
538          }
539       }
540
541       /* Test things which depend on number of texture image dimensions */
542       if ((t->Target == GL_TEXTURE_1D) ||
543           (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
544          /* Test 1-D mipmaps */
545          GLuint width = t->Image[0][baseLevel]->Width2;
546          for (i = baseLevel + 1; i < maxLevels; i++) {
547             if (width > 1) {
548                width /= 2;
549             }
550             if (i >= minLevel && i <= maxLevel) {
551                if (!t->Image[0][i]) {
552                   incomplete(t, "1D Image[0][i] == NULL");
553                   return;
554                }
555                if (t->Image[0][i]->Width2 != width ) {
556                   incomplete(t, "1D Image[0][i] bad width");
557                   return;
558                }
559             }
560             if (width == 1) {
561                return;  /* found smallest needed mipmap, all done! */
562             }
563          }
564       }
565       else if ((t->Target == GL_TEXTURE_2D) ||
566                (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
567          /* Test 2-D mipmaps */
568          GLuint width = t->Image[0][baseLevel]->Width2;
569          GLuint height = t->Image[0][baseLevel]->Height2;
570          for (i = baseLevel + 1; i < maxLevels; i++) {
571             if (width > 1) {
572                width /= 2;
573             }
574             if (height > 1) {
575                height /= 2;
576             }
577             if (i >= minLevel && i <= maxLevel) {
578                if (!t->Image[0][i]) {
579                   incomplete(t, "2D Image[0][i] == NULL");
580                   return;
581                }
582                if (t->Image[0][i]->Width2 != width) {
583                   incomplete(t, "2D Image[0][i] bad width");
584                   return;
585                }
586                if (t->Image[0][i]->Height2 != height) {
587                   incomplete(t, "2D Image[0][i] bad height");
588                   return;
589                }
590                if (width==1 && height==1) {
591                   return;  /* found smallest needed mipmap, all done! */
592                }
593             }
594          }
595       }
596       else if (t->Target == GL_TEXTURE_3D) {
597          /* Test 3-D mipmaps */
598          GLuint width = t->Image[0][baseLevel]->Width2;
599          GLuint height = t->Image[0][baseLevel]->Height2;
600          GLuint depth = t->Image[0][baseLevel]->Depth2;
601          for (i = baseLevel + 1; i < maxLevels; i++) {
602             if (width > 1) {
603                width /= 2;
604             }
605             if (height > 1) {
606                height /= 2;
607             }
608             if (depth > 1) {
609                depth /= 2;
610             }
611             if (i >= minLevel && i <= maxLevel) {
612                if (!t->Image[0][i]) {
613                   incomplete(t, "3D Image[0][i] == NULL");
614                   return;
615                }
616                if (t->Image[0][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
617                   incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
618                   return;
619                }
620                if (t->Image[0][i]->Width2 != width) {
621                   incomplete(t, "3D Image[0][i] bad width");
622                   return;
623                }
624                if (t->Image[0][i]->Height2 != height) {
625                   incomplete(t, "3D Image[0][i] bad height");
626                   return;
627                }
628                if (t->Image[0][i]->Depth2 != depth) {
629                   incomplete(t, "3D Image[0][i] bad depth");
630                   return;
631                }
632             }
633             if (width == 1 && height == 1 && depth == 1) {
634                return;  /* found smallest needed mipmap, all done! */
635             }
636          }
637       }
638       else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
639          /* make sure 6 cube faces are consistant */
640          GLuint width = t->Image[0][baseLevel]->Width2;
641          GLuint height = t->Image[0][baseLevel]->Height2;
642          for (i = baseLevel + 1; i < maxLevels; i++) {
643             if (width > 1) {
644                width /= 2;
645             }
646             if (height > 1) {
647                height /= 2;
648             }
649             if (i >= minLevel && i <= maxLevel) {
650                GLuint face;
651                for (face = 0; face < 6; face++) {
652                   /* check that we have images defined */
653                   if (!t->Image[face][i]) {
654                      incomplete(t, "CubeMap Image[n][i] == NULL");
655                      return;
656                   }
657                   /* Don't support GL_DEPTH_COMPONENT for cube maps */
658                   if (t->Image[face][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
659                      incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
660                      return;
661                   }
662                   /* check that all six images have same size */
663                   if (t->Image[face][i]->Width2 != width || 
664                       t->Image[face][i]->Height2 != height) {
665                      incomplete(t, "CubeMap Image[n][i] bad size");
666                      return;
667                   }
668                }
669             }
670             if (width == 1 && height == 1) {
671                return;  /* found smallest needed mipmap, all done! */
672             }
673          }
674       }
675       else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
676          /* XXX special checking? */
677       }
678       else {
679          /* Target = ??? */
680          _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
681       }
682    }
683 }
684
685
686 /**
687  * Check if the given cube map texture is "cube complete" as defined in
688  * the OpenGL specification.
689  */
690 GLboolean
691 _mesa_cube_complete(const struct gl_texture_object *texObj)
692 {
693    const GLint baseLevel = texObj->BaseLevel;
694    const struct gl_texture_image *img0, *img;
695    GLuint face;
696
697    if (texObj->Target != GL_TEXTURE_CUBE_MAP)
698       return GL_FALSE;
699
700    if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS))
701       return GL_FALSE;
702
703    /* check first face */
704    img0 = texObj->Image[0][baseLevel];
705    if (!img0 ||
706        img0->Width < 1 ||
707        img0->Width != img0->Height)
708       return GL_FALSE;
709
710    /* check remaining faces vs. first face */
711    for (face = 1; face < 6; face++) {
712       img = texObj->Image[face][baseLevel];
713       if (!img ||
714           img->Width != img0->Width ||
715           img->Height != img0->Height ||
716           img->TexFormat != img0->TexFormat)
717          return GL_FALSE;
718    }
719
720    return GL_TRUE;
721 }
722
723
724 /**
725  * Mark a texture object dirty.  It forces the object to be incomplete
726  * and optionally forces the context to re-validate its state.
727  *
728  * \param ctx GL context.
729  * \param texObj texture object.
730  * \param invalidate_state also invalidate context state.
731  */
732 void
733 _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
734                    GLboolean invalidate_state)
735 {
736    texObj->_Complete = GL_FALSE;
737    if (invalidate_state)
738       ctx->NewState |= _NEW_TEXTURE;
739 }
740
741
742 /**
743  * Return pointer to a default/fallback texture.
744  * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
745  * That's the value a sampler should get when sampling from an
746  * incomplete texture.
747  */
748 struct gl_texture_object *
749 _mesa_get_fallback_texture(struct gl_context *ctx)
750 {
751    if (!ctx->Shared->FallbackTex) {
752       /* create fallback texture now */
753       static GLubyte texels[8 * 8][4];
754       struct gl_texture_object *texObj;
755       struct gl_texture_image *texImage;
756       gl_format texFormat;
757       GLuint i;
758
759       for (i = 0; i < 8 * 8; i++) {
760          texels[i][0] =
761          texels[i][1] =
762          texels[i][2] = 0x0;
763          texels[i][3] = 0xff;
764       }
765
766       /* create texture object */
767       texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
768       assert(texObj->RefCount == 1);
769       texObj->Sampler.MinFilter = GL_NEAREST;
770       texObj->Sampler.MagFilter = GL_NEAREST;
771
772       /* create level[0] texture image */
773       texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
774
775       texFormat = ctx->Driver.ChooseTextureFormat(ctx, GL_RGBA, GL_RGBA,
776                                                   GL_UNSIGNED_BYTE);
777
778       /* init the image fields */
779       _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
780                                  8, 8, 1, 0, GL_RGBA, texFormat); 
781
782       ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
783
784       /* set image data */
785       ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
786                              8, 8, 0,
787                              GL_RGBA, GL_UNSIGNED_BYTE, texels,
788                              &ctx->DefaultPacking, texObj, texImage);
789
790       _mesa_test_texobj_completeness(ctx, texObj);
791       assert(texObj->_Complete);
792
793       ctx->Shared->FallbackTex = texObj;
794    }
795    return ctx->Shared->FallbackTex;
796 }
797
798
799 /*@}*/
800
801
802 /***********************************************************************/
803 /** \name API functions */
804 /*@{*/
805
806
807 /**
808  * Generate texture names.
809  *
810  * \param n number of texture names to be generated.
811  * \param textures an array in which will hold the generated texture names.
812  *
813  * \sa glGenTextures().
814  *
815  * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
816  * IDs which are stored in \p textures.  Corresponding empty texture
817  * objects are also generated.
818  */ 
819 void GLAPIENTRY
820 _mesa_GenTextures( GLsizei n, GLuint *textures )
821 {
822    GET_CURRENT_CONTEXT(ctx);
823    GLuint first;
824    GLint i;
825    ASSERT_OUTSIDE_BEGIN_END(ctx);
826
827    if (n < 0) {
828       _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
829       return;
830    }
831
832    if (!textures)
833       return;
834
835    /*
836     * This must be atomic (generation and allocation of texture IDs)
837     */
838    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
839
840    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
841
842    /* Allocate new, empty texture objects */
843    for (i = 0; i < n; i++) {
844       struct gl_texture_object *texObj;
845       GLuint name = first + i;
846       GLenum target = 0;
847       texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
848       if (!texObj) {
849          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
850          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
851          return;
852       }
853
854       /* insert into hash table */
855       _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
856
857       textures[i] = name;
858    }
859
860    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
861 }
862
863
864 /**
865  * Check if the given texture object is bound to the current draw or
866  * read framebuffer.  If so, Unbind it.
867  */
868 static void
869 unbind_texobj_from_fbo(struct gl_context *ctx,
870                        struct gl_texture_object *texObj)
871 {
872    const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2;
873    GLuint i;
874
875    for (i = 0; i < n; i++) {
876       struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer;
877       if (fb->Name) {
878          GLuint j;
879          for (j = 0; j < BUFFER_COUNT; j++) {
880             if (fb->Attachment[j].Type == GL_TEXTURE &&
881                 fb->Attachment[j].Texture == texObj) {
882                /* Vertices are already flushed by _mesa_DeleteTextures */
883                ctx->NewState |= _NEW_BUFFERS;
884                _mesa_remove_attachment(ctx, fb->Attachment + j);         
885             }
886          }
887       }
888    }
889 }
890
891
892 /**
893  * Check if the given texture object is bound to any texture image units and
894  * unbind it if so (revert to default textures).
895  */
896 static void
897 unbind_texobj_from_texunits(struct gl_context *ctx,
898                             struct gl_texture_object *texObj)
899 {
900    GLuint u, tex;
901
902    for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
903       struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
904       for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
905          if (texObj == unit->CurrentTex[tex]) {
906             _mesa_reference_texobj(&unit->CurrentTex[tex],
907                                    ctx->Shared->DefaultTex[tex]);
908             ASSERT(unit->CurrentTex[tex]);
909             break;
910          }
911       }
912    }
913 }
914
915
916 /**
917  * Delete named textures.
918  *
919  * \param n number of textures to be deleted.
920  * \param textures array of texture IDs to be deleted.
921  *
922  * \sa glDeleteTextures().
923  *
924  * If we're about to delete a texture that's currently bound to any
925  * texture unit, unbind the texture first.  Decrement the reference
926  * count on the texture object and delete it if it's zero.
927  * Recall that texture objects can be shared among several rendering
928  * contexts.
929  */
930 void GLAPIENTRY
931 _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
932 {
933    GET_CURRENT_CONTEXT(ctx);
934    GLint i;
935    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
936
937    if (!textures)
938       return;
939
940    for (i = 0; i < n; i++) {
941       if (textures[i] > 0) {
942          struct gl_texture_object *delObj
943             = _mesa_lookup_texture(ctx, textures[i]);
944
945          if (delObj) {
946             _mesa_lock_texture(ctx, delObj);
947
948             /* Check if texture is bound to any framebuffer objects.
949              * If so, unbind.
950              * See section 4.4.2.3 of GL_EXT_framebuffer_object.
951              */
952             unbind_texobj_from_fbo(ctx, delObj);
953
954             /* Check if this texture is currently bound to any texture units.
955              * If so, unbind it.
956              */
957             unbind_texobj_from_texunits(ctx, delObj);
958
959             _mesa_unlock_texture(ctx, delObj);
960
961             ctx->NewState |= _NEW_TEXTURE;
962
963             /* The texture _name_ is now free for re-use.
964              * Remove it from the hash table now.
965              */
966             _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
967             _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
968             _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
969
970             /* Unreference the texobj.  If refcount hits zero, the texture
971              * will be deleted.
972              */
973             _mesa_reference_texobj(&delObj, NULL);
974          }
975       }
976    }
977 }
978
979
980 /**
981  * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
982  * into the corresponding Mesa texture target index.
983  * Note that proxy targets are not valid here.
984  * \return TEXTURE_x_INDEX or -1 if target is invalid
985  */
986 static GLint
987 target_enum_to_index(GLenum target)
988 {
989    switch (target) {
990    case GL_TEXTURE_1D:
991       return TEXTURE_1D_INDEX;
992    case GL_TEXTURE_2D:
993       return TEXTURE_2D_INDEX;
994    case GL_TEXTURE_3D:
995       return TEXTURE_3D_INDEX;
996    case GL_TEXTURE_CUBE_MAP_ARB:
997       return TEXTURE_CUBE_INDEX;
998    case GL_TEXTURE_RECTANGLE_NV:
999       return TEXTURE_RECT_INDEX;
1000    case GL_TEXTURE_1D_ARRAY_EXT:
1001       return TEXTURE_1D_ARRAY_INDEX;
1002    case GL_TEXTURE_2D_ARRAY_EXT:
1003       return TEXTURE_2D_ARRAY_INDEX;
1004    case GL_TEXTURE_BUFFER_ARB:
1005       return TEXTURE_BUFFER_INDEX;
1006    default:
1007       return -1;
1008    }
1009 }
1010
1011
1012 /**
1013  * Bind a named texture to a texturing target.
1014  * 
1015  * \param target texture target.
1016  * \param texName texture name.
1017  * 
1018  * \sa glBindTexture().
1019  *
1020  * Determines the old texture object bound and returns immediately if rebinding
1021  * the same texture.  Get the current texture which is either a default texture
1022  * if name is null, a named texture from the hash, or a new texture if the
1023  * given texture name is new. Increments its reference count, binds it, and
1024  * calls dd_function_table::BindTexture. Decrements the old texture reference
1025  * count and deletes it if it reaches zero.
1026  */
1027 void GLAPIENTRY
1028 _mesa_BindTexture( GLenum target, GLuint texName )
1029 {
1030    GET_CURRENT_CONTEXT(ctx);
1031    struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
1032    struct gl_texture_object *newTexObj = NULL;
1033    GLint targetIndex;
1034    ASSERT_OUTSIDE_BEGIN_END(ctx);
1035
1036    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1037       _mesa_debug(ctx, "glBindTexture %s %d\n",
1038                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
1039
1040    targetIndex = target_enum_to_index(target);
1041    if (targetIndex < 0) {
1042       _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
1043       return;
1044    }
1045    assert(targetIndex < NUM_TEXTURE_TARGETS);
1046
1047    /*
1048     * Get pointer to new texture object (newTexObj)
1049     */
1050    if (texName == 0) {
1051       /* Use a default texture object */
1052       newTexObj = ctx->Shared->DefaultTex[targetIndex];
1053    }
1054    else {
1055       /* non-default texture object */
1056       newTexObj = _mesa_lookup_texture(ctx, texName);
1057       if (newTexObj) {
1058          /* error checking */
1059          if (newTexObj->Target != 0 && newTexObj->Target != target) {
1060             /* the named texture object's target doesn't match the given target */
1061             _mesa_error( ctx, GL_INVALID_OPERATION,
1062                          "glBindTexture(target mismatch)" );
1063             return;
1064          }
1065          if (newTexObj->Target == 0) {
1066             finish_texture_init(ctx, target, newTexObj);
1067          }
1068       }
1069       else {
1070          /* if this is a new texture id, allocate a texture object now */
1071          newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target);
1072          if (!newTexObj) {
1073             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
1074             return;
1075          }
1076
1077          /* and insert it into hash table */
1078          _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1079          _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
1080          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1081       }
1082       newTexObj->Target = target;
1083    }
1084
1085    assert(valid_texture_object(newTexObj));
1086
1087    /* Check if this texture is only used by this context and is already bound.
1088     * If so, just return.
1089     */
1090    {
1091       GLboolean early_out;
1092       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1093       early_out = ((ctx->Shared->RefCount == 1)
1094                    && (newTexObj == texUnit->CurrentTex[targetIndex]));
1095       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1096       if (early_out) {
1097          return;
1098       }
1099    }
1100
1101    /* flush before changing binding */
1102    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1103
1104    /* Do the actual binding.  The refcount on the previously bound
1105     * texture object will be decremented.  It'll be deleted if the
1106     * count hits zero.
1107     */
1108    _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
1109    ASSERT(texUnit->CurrentTex[targetIndex]);
1110
1111    /* Pass BindTexture call to device driver */
1112    if (ctx->Driver.BindTexture)
1113       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
1114 }
1115
1116
1117 /**
1118  * Set texture priorities.
1119  * 
1120  * \param n number of textures.
1121  * \param texName texture names.
1122  * \param priorities corresponding texture priorities.
1123  * 
1124  * \sa glPrioritizeTextures().
1125  * 
1126  * Looks up each texture in the hash, clamps the corresponding priority between
1127  * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
1128  */
1129 void GLAPIENTRY
1130 _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
1131                           const GLclampf *priorities )
1132 {
1133    GET_CURRENT_CONTEXT(ctx);
1134    GLint i;
1135    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1136
1137    if (n < 0) {
1138       _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
1139       return;
1140    }
1141
1142    if (!priorities)
1143       return;
1144
1145    for (i = 0; i < n; i++) {
1146       if (texName[i] > 0) {
1147          struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
1148          if (t) {
1149             t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
1150          }
1151       }
1152    }
1153
1154    ctx->NewState |= _NEW_TEXTURE;
1155 }
1156
1157
1158
1159 /**
1160  * See if textures are loaded in texture memory.
1161  * 
1162  * \param n number of textures to query.
1163  * \param texName array with the texture names.
1164  * \param residences array which will hold the residence status.
1165  *
1166  * \return GL_TRUE if all textures are resident and \p residences is left unchanged, 
1167  * 
1168  * \sa glAreTexturesResident().
1169  *
1170  * Looks up each texture in the hash and calls
1171  * dd_function_table::IsTextureResident.
1172  */
1173 GLboolean GLAPIENTRY
1174 _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
1175                           GLboolean *residences)
1176 {
1177    GET_CURRENT_CONTEXT(ctx);
1178    GLboolean allResident = GL_TRUE;
1179    GLint i, j;
1180    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1181
1182    if (n < 0) {
1183       _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
1184       return GL_FALSE;
1185    }
1186
1187    if (!texName || !residences)
1188       return GL_FALSE;
1189
1190    for (i = 0; i < n; i++) {
1191       struct gl_texture_object *t;
1192       if (texName[i] == 0) {
1193          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1194          return GL_FALSE;
1195       }
1196       t = _mesa_lookup_texture(ctx, texName[i]);
1197       if (!t) {
1198          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1199          return GL_FALSE;
1200       }
1201       if (!ctx->Driver.IsTextureResident ||
1202           ctx->Driver.IsTextureResident(ctx, t)) {
1203          /* The texture is resident */
1204          if (!allResident)
1205             residences[i] = GL_TRUE;
1206       }
1207       else {
1208          /* The texture is not resident */
1209          if (allResident) {
1210             allResident = GL_FALSE;
1211             for (j = 0; j < i; j++)
1212                residences[j] = GL_TRUE;
1213          }
1214          residences[i] = GL_FALSE;
1215       }
1216    }
1217    
1218    return allResident;
1219 }
1220
1221
1222 /**
1223  * See if a name corresponds to a texture.
1224  *
1225  * \param texture texture name.
1226  *
1227  * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
1228  * otherwise.
1229  * 
1230  * \sa glIsTexture().
1231  *
1232  * Calls _mesa_HashLookup().
1233  */
1234 GLboolean GLAPIENTRY
1235 _mesa_IsTexture( GLuint texture )
1236 {
1237    struct gl_texture_object *t;
1238    GET_CURRENT_CONTEXT(ctx);
1239    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1240
1241    if (!texture)
1242       return GL_FALSE;
1243
1244    t = _mesa_lookup_texture(ctx, texture);
1245
1246    /* IsTexture is true only after object has been bound once. */
1247    return t && t->Target;
1248 }
1249
1250
1251 /**
1252  * Simplest implementation of texture locking: grab the shared tex
1253  * mutex.  Examine the shared context state timestamp and if there has
1254  * been a change, set the appropriate bits in ctx->NewState.
1255  *
1256  * This is used to deal with synchronizing things when a texture object
1257  * is used/modified by different contexts (or threads) which are sharing
1258  * the texture.
1259  *
1260  * See also _mesa_lock/unlock_texture() in teximage.h
1261  */
1262 void
1263 _mesa_lock_context_textures( struct gl_context *ctx )
1264 {
1265    _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
1266
1267    if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
1268       ctx->NewState |= _NEW_TEXTURE;
1269       ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
1270    }
1271 }
1272
1273
1274 void
1275 _mesa_unlock_context_textures( struct gl_context *ctx )
1276 {
1277    assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
1278    _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
1279 }
1280
1281 /*@}*/