• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
_mesa_lookup_texture(struct gl_context * ctx,GLuint id)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 *
_mesa_new_texture_object(struct gl_context * ctx,GLuint name,GLenum target)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
_mesa_initialize_texture_object(struct gl_texture_object * obj,GLuint name,GLenum target)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_EXTERNAL_OES ||
111           target == GL_TEXTURE_BUFFER);
112 
113    memset(obj, 0, sizeof(*obj));
114    /* init the non-zero fields */
115    _glthread_INIT_MUTEX(obj->Mutex);
116    obj->RefCount = 1;
117    obj->Name = name;
118    obj->Target = target;
119    obj->Priority = 1.0F;
120    obj->BaseLevel = 0;
121    obj->MaxLevel = 1000;
122 
123    /* must be one; no support for (YUV) planes in separate buffers */
124    obj->RequiredTextureImageUnits = 1;
125 
126    /* sampler state */
127    if (target == GL_TEXTURE_RECTANGLE_NV ||
128        target == GL_TEXTURE_EXTERNAL_OES) {
129       obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
130       obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
131       obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
132       obj->Sampler.MinFilter = GL_LINEAR;
133    }
134    else {
135       obj->Sampler.WrapS = GL_REPEAT;
136       obj->Sampler.WrapT = GL_REPEAT;
137       obj->Sampler.WrapR = GL_REPEAT;
138       obj->Sampler.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
139    }
140    obj->Sampler.MagFilter = GL_LINEAR;
141    obj->Sampler.MinLod = -1000.0;
142    obj->Sampler.MaxLod = 1000.0;
143    obj->Sampler.LodBias = 0.0;
144    obj->Sampler.MaxAnisotropy = 1.0;
145    obj->Sampler.CompareMode = GL_NONE;         /* ARB_shadow */
146    obj->Sampler.CompareFunc = GL_LEQUAL;       /* ARB_shadow */
147    obj->DepthMode = GL_LUMINANCE;
148    obj->Sampler.CubeMapSeamless = GL_FALSE;
149    obj->Swizzle[0] = GL_RED;
150    obj->Swizzle[1] = GL_GREEN;
151    obj->Swizzle[2] = GL_BLUE;
152    obj->Swizzle[3] = GL_ALPHA;
153    obj->_Swizzle = SWIZZLE_NOOP;
154    obj->Sampler.sRGBDecode = GL_DECODE_EXT;
155    obj->BufferObjectFormat = GL_LUMINANCE8;
156    obj->_BufferObjectFormat = MESA_FORMAT_L8;
157 }
158 
159 
160 /**
161  * Some texture initialization can't be finished until we know which
162  * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
163  */
164 static void
finish_texture_init(struct gl_context * ctx,GLenum target,struct gl_texture_object * obj)165 finish_texture_init(struct gl_context *ctx, GLenum target,
166                     struct gl_texture_object *obj)
167 {
168    assert(obj->Target == 0);
169 
170    if (target == GL_TEXTURE_RECTANGLE_NV ||
171        target == GL_TEXTURE_EXTERNAL_OES) {
172       /* have to init wrap and filter state here - kind of klunky */
173       obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
174       obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
175       obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
176       obj->Sampler.MinFilter = GL_LINEAR;
177       if (ctx->Driver.TexParameter) {
178          static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
179          static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
180          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
181          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
182          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
183          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter);
184       }
185    }
186 }
187 
188 
189 /**
190  * Deallocate a texture object struct.  It should have already been
191  * removed from the texture object pool.
192  * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
193  *
194  * \param shared the shared GL state to which the object belongs.
195  * \param texObj the texture object to delete.
196  */
197 void
_mesa_delete_texture_object(struct gl_context * ctx,struct gl_texture_object * texObj)198 _mesa_delete_texture_object(struct gl_context *ctx,
199                             struct gl_texture_object *texObj)
200 {
201    GLuint i, face;
202 
203    /* Set Target to an invalid value.  With some assertions elsewhere
204     * we can try to detect possible use of deleted textures.
205     */
206    texObj->Target = 0x99;
207 
208    /* free the texture images */
209    for (face = 0; face < 6; face++) {
210       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
211          if (texObj->Image[face][i]) {
212             ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]);
213          }
214       }
215    }
216 
217    _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
218 
219    /* destroy the mutex -- it may have allocated memory (eg on bsd) */
220    _glthread_DESTROY_MUTEX(texObj->Mutex);
221 
222    /* free this object */
223    free(texObj);
224 }
225 
226 
227 
228 /**
229  * Copy texture object state from one texture object to another.
230  * Use for glPush/PopAttrib.
231  *
232  * \param dest destination texture object.
233  * \param src source texture object.
234  */
235 void
_mesa_copy_texture_object(struct gl_texture_object * dest,const struct gl_texture_object * src)236 _mesa_copy_texture_object( struct gl_texture_object *dest,
237                            const struct gl_texture_object *src )
238 {
239    dest->Target = src->Target;
240    dest->Name = src->Name;
241    dest->Priority = src->Priority;
242    dest->Sampler.BorderColor.f[0] = src->Sampler.BorderColor.f[0];
243    dest->Sampler.BorderColor.f[1] = src->Sampler.BorderColor.f[1];
244    dest->Sampler.BorderColor.f[2] = src->Sampler.BorderColor.f[2];
245    dest->Sampler.BorderColor.f[3] = src->Sampler.BorderColor.f[3];
246    dest->Sampler.WrapS = src->Sampler.WrapS;
247    dest->Sampler.WrapT = src->Sampler.WrapT;
248    dest->Sampler.WrapR = src->Sampler.WrapR;
249    dest->Sampler.MinFilter = src->Sampler.MinFilter;
250    dest->Sampler.MagFilter = src->Sampler.MagFilter;
251    dest->Sampler.MinLod = src->Sampler.MinLod;
252    dest->Sampler.MaxLod = src->Sampler.MaxLod;
253    dest->Sampler.LodBias = src->Sampler.LodBias;
254    dest->BaseLevel = src->BaseLevel;
255    dest->MaxLevel = src->MaxLevel;
256    dest->Sampler.MaxAnisotropy = src->Sampler.MaxAnisotropy;
257    dest->Sampler.CompareMode = src->Sampler.CompareMode;
258    dest->Sampler.CompareFunc = src->Sampler.CompareFunc;
259    dest->Sampler.CubeMapSeamless = src->Sampler.CubeMapSeamless;
260    dest->DepthMode = src->DepthMode;
261    dest->Sampler.sRGBDecode = src->Sampler.sRGBDecode;
262    dest->_MaxLevel = src->_MaxLevel;
263    dest->_MaxLambda = src->_MaxLambda;
264    dest->GenerateMipmap = src->GenerateMipmap;
265    dest->_BaseComplete = src->_BaseComplete;
266    dest->_MipmapComplete = src->_MipmapComplete;
267    COPY_4V(dest->Swizzle, src->Swizzle);
268    dest->_Swizzle = src->_Swizzle;
269 
270    dest->RequiredTextureImageUnits = src->RequiredTextureImageUnits;
271 }
272 
273 
274 /**
275  * Free all texture images of the given texture object.
276  *
277  * \param ctx GL context.
278  * \param t texture object.
279  *
280  * \sa _mesa_clear_texture_image().
281  */
282 void
_mesa_clear_texture_object(struct gl_context * ctx,struct gl_texture_object * texObj)283 _mesa_clear_texture_object(struct gl_context *ctx,
284                            struct gl_texture_object *texObj)
285 {
286    GLuint i, j;
287 
288    if (texObj->Target == 0)
289       return;
290 
291    for (i = 0; i < MAX_FACES; i++) {
292       for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
293          struct gl_texture_image *texImage = texObj->Image[i][j];
294          if (texImage)
295             _mesa_clear_texture_image(ctx, texImage);
296       }
297    }
298 }
299 
300 
301 /**
302  * Check if the given texture object is valid by examining its Target field.
303  * For debugging only.
304  */
305 static GLboolean
valid_texture_object(const struct gl_texture_object * tex)306 valid_texture_object(const struct gl_texture_object *tex)
307 {
308    switch (tex->Target) {
309    case 0:
310    case GL_TEXTURE_1D:
311    case GL_TEXTURE_2D:
312    case GL_TEXTURE_3D:
313    case GL_TEXTURE_CUBE_MAP_ARB:
314    case GL_TEXTURE_RECTANGLE_NV:
315    case GL_TEXTURE_1D_ARRAY_EXT:
316    case GL_TEXTURE_2D_ARRAY_EXT:
317    case GL_TEXTURE_BUFFER:
318    case GL_TEXTURE_EXTERNAL_OES:
319       return GL_TRUE;
320    case 0x99:
321       _mesa_problem(NULL, "invalid reference to a deleted texture object");
322       return GL_FALSE;
323    default:
324       _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
325                     tex->Target, tex->Name);
326       return GL_FALSE;
327    }
328 }
329 
330 
331 /**
332  * Reference (or unreference) a texture object.
333  * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
334  * If 'tex' is non-null, increment its refcount.
335  * This is normally only called from the _mesa_reference_texobj() macro
336  * when there's a real pointer change.
337  */
338 void
_mesa_reference_texobj_(struct gl_texture_object ** ptr,struct gl_texture_object * tex)339 _mesa_reference_texobj_(struct gl_texture_object **ptr,
340                         struct gl_texture_object *tex)
341 {
342    assert(ptr);
343 
344    if (*ptr) {
345       /* Unreference the old texture */
346       GLboolean deleteFlag = GL_FALSE;
347       struct gl_texture_object *oldTex = *ptr;
348 
349       ASSERT(valid_texture_object(oldTex));
350       (void) valid_texture_object; /* silence warning in release builds */
351 
352       _glthread_LOCK_MUTEX(oldTex->Mutex);
353       ASSERT(oldTex->RefCount > 0);
354       oldTex->RefCount--;
355 
356       deleteFlag = (oldTex->RefCount == 0);
357       _glthread_UNLOCK_MUTEX(oldTex->Mutex);
358 
359       if (deleteFlag) {
360          GET_CURRENT_CONTEXT(ctx);
361          if (ctx)
362             ctx->Driver.DeleteTexture(ctx, oldTex);
363          else
364             _mesa_problem(NULL, "Unable to delete texture, no context");
365       }
366 
367       *ptr = NULL;
368    }
369    assert(!*ptr);
370 
371    if (tex) {
372       /* reference new texture */
373       ASSERT(valid_texture_object(tex));
374       _glthread_LOCK_MUTEX(tex->Mutex);
375       if (tex->RefCount == 0) {
376          /* this texture's being deleted (look just above) */
377          /* Not sure this can every really happen.  Warn if it does. */
378          _mesa_problem(NULL, "referencing deleted texture object");
379          *ptr = NULL;
380       }
381       else {
382          tex->RefCount++;
383          *ptr = tex;
384       }
385       _glthread_UNLOCK_MUTEX(tex->Mutex);
386    }
387 }
388 
389 
390 enum base_mipmap { BASE, MIPMAP };
391 
392 
393 /**
394  * Mark a texture object as incomplete.  There are actually three kinds of
395  * (in)completeness:
396  * 1. "base incomplete": the base level of the texture is invalid so no
397  *    texturing is possible.
398  * 2. "mipmap incomplete": a non-base level of the texture is invalid so
399  *    mipmap filtering isn't possible, but non-mipmap filtering is.
400  * 3. "texture incompleteness": some combination of texture state and
401  *    sampler state renders the texture incomplete.
402  *
403  * \param t  texture object
404  * \param bm  either BASE or MIPMAP to indicate what's incomplete
405  * \param fmt...  string describing why it's incomplete (for debugging).
406  */
407 static void
incomplete(struct gl_texture_object * t,enum base_mipmap bm,const char * fmt,...)408 incomplete(struct gl_texture_object *t, enum base_mipmap bm,
409            const char *fmt, ...)
410 {
411    if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) {
412       va_list args;
413       char s[100];
414 
415       va_start(args, fmt);
416       vsnprintf(s, sizeof(s), fmt, args);
417       va_end(args);
418 
419       _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s);
420    }
421 
422    if (bm == BASE)
423       t->_BaseComplete = GL_FALSE;
424    t->_MipmapComplete = GL_FALSE;
425 }
426 
427 
428 /**
429  * Examine a texture object to determine if it is complete.
430  *
431  * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
432  * accordingly.
433  *
434  * \param ctx GL context.
435  * \param t texture object.
436  *
437  * According to the texture target, verifies that each of the mipmaps is
438  * present and has the expected size.
439  */
440 void
_mesa_test_texobj_completeness(const struct gl_context * ctx,struct gl_texture_object * t)441 _mesa_test_texobj_completeness( const struct gl_context *ctx,
442                                 struct gl_texture_object *t )
443 {
444    const GLint baseLevel = t->BaseLevel;
445    const struct gl_texture_image *baseImage;
446    GLint maxLog2 = 0, maxLevels = 0;
447 
448    /* We'll set these to FALSE if tests fail below */
449    t->_BaseComplete = GL_TRUE;
450    t->_MipmapComplete = GL_TRUE;
451 
452    if (t->Target == GL_TEXTURE_BUFFER) {
453       /* Buffer textures are always considered complete.  The obvious case where
454        * they would be incomplete (no BO attached) is actually specced to be
455        * undefined rendering results.
456        */
457       return;
458    }
459 
460    /* Detect cases where the application set the base level to an invalid
461     * value.
462     */
463    if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
464       incomplete(t, BASE, "base level = %d is invalid", baseLevel);
465       return;
466    }
467 
468    if (t->MaxLevel < baseLevel) {
469       incomplete(t, BASE, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
470 		 t->MaxLevel, baseLevel);
471       return;
472    }
473 
474    baseImage = t->Image[0][baseLevel];
475 
476    /* Always need the base level image */
477    if (!baseImage) {
478       incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel);
479       return;
480    }
481 
482    /* Check width/height/depth for zero */
483    if (baseImage->Width == 0 ||
484        baseImage->Height == 0 ||
485        baseImage->Depth == 0) {
486       incomplete(t, BASE, "texture width or height or depth = 0");
487       return;
488    }
489 
490    /* Check if the texture values are integer */
491    {
492       GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat);
493       t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT;
494    }
495 
496    /* Compute _MaxLevel (the maximum mipmap level we'll sample from given the
497     * mipmap image sizes and GL_TEXTURE_MAX_LEVEL state).
498     */
499    switch (t->Target) {
500    case GL_TEXTURE_1D:
501    case GL_TEXTURE_1D_ARRAY_EXT:
502       maxLog2 = baseImage->WidthLog2;
503       maxLevels = ctx->Const.MaxTextureLevels;
504       break;
505    case GL_TEXTURE_2D:
506    case GL_TEXTURE_2D_ARRAY_EXT:
507       maxLog2 = MAX2(baseImage->WidthLog2,
508                      baseImage->HeightLog2);
509       maxLevels = ctx->Const.MaxTextureLevels;
510       break;
511    case GL_TEXTURE_3D:
512       maxLog2 = MAX3(baseImage->WidthLog2,
513                      baseImage->HeightLog2,
514                      baseImage->DepthLog2);
515       maxLevels = ctx->Const.Max3DTextureLevels;
516       break;
517    case GL_TEXTURE_CUBE_MAP_ARB:
518       maxLog2 = MAX2(baseImage->WidthLog2,
519                      baseImage->HeightLog2);
520       maxLevels = ctx->Const.MaxCubeTextureLevels;
521       break;
522    case GL_TEXTURE_RECTANGLE_NV:
523    case GL_TEXTURE_BUFFER:
524    case GL_TEXTURE_EXTERNAL_OES:
525       maxLog2 = 0;  /* not applicable */
526       maxLevels = 1;  /* no mipmapping */
527       break;
528    default:
529       _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
530       return;
531    }
532 
533    ASSERT(maxLevels > 0);
534 
535    t->_MaxLevel = baseLevel + maxLog2;  /* 'p' in the GL spec */
536    t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
537    t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); /* 'q' in the GL spec */
538 
539    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
540    t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);
541 
542    if (t->Immutable) {
543       /* This texture object was created with glTexStorage1/2/3D() so we
544        * know that all the mipmap levels are the right size and all cube
545        * map faces are the same size.
546        * We don't need to do any of the additional checks below.
547        */
548       return;
549    }
550 
551    if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
552       /* Make sure that all six cube map level 0 images are the same size.
553        * Note:  we know that the image's width==height (we enforce that
554        * at glTexImage time) so we only need to test the width here.
555        */
556       GLuint face;
557       assert(baseImage->Width2 == baseImage->Height);
558       for (face = 1; face < 6; face++) {
559          assert(t->Image[face][baseLevel] == NULL ||
560                 t->Image[face][baseLevel]->Width2 ==
561                 t->Image[face][baseLevel]->Height2);
562          if (t->Image[face][baseLevel] == NULL ||
563              t->Image[face][baseLevel]->Width2 != baseImage->Width2) {
564             incomplete(t, BASE, "Cube face missing or mismatched size");
565             return;
566          }
567       }
568    }
569 
570    /*
571     * Do mipmap consistency checking.
572     * Note: we don't care about the current texture sampler state here.
573     * To determine texture completeness we'll either look at _BaseComplete
574     * or _MipmapComplete depending on the current minification filter mode.
575     */
576    {
577       GLint i;
578       const GLint minLevel = baseLevel;
579       const GLint maxLevel = t->_MaxLevel;
580       const GLuint numFaces = _mesa_num_tex_faces(t->Target);
581       GLuint width, height, depth, face;
582 
583       if (minLevel > maxLevel) {
584          incomplete(t, BASE, "minLevel > maxLevel");
585          return;
586       }
587 
588       /* Get the base image's dimensions */
589       width = baseImage->Width2;
590       height = baseImage->Height2;
591       depth = baseImage->Depth2;
592 
593       /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL textures */
594       for (i = baseLevel + 1; i < maxLevels; i++) {
595          /* Compute the expected size of image at level[i] */
596          if (width > 1) {
597             width /= 2;
598          }
599          if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) {
600             height /= 2;
601          }
602          if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY) {
603             depth /= 2;
604          }
605 
606          /* loop over cube faces (or single face otherwise) */
607          for (face = 0; face < numFaces; face++) {
608             if (i >= minLevel && i <= maxLevel) {
609                const struct gl_texture_image *img = t->Image[face][i];
610 
611                if (!img) {
612                   incomplete(t, MIPMAP, "TexImage[%d] is missing", i);
613                   return;
614                }
615                if (img->TexFormat != baseImage->TexFormat) {
616                   incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]");
617                   return;
618                }
619                if (img->Border != baseImage->Border) {
620                   incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]");
621                   return;
622                }
623                if (img->Width2 != width) {
624                   incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i, img->Width2);
625                   return;
626                }
627                if (img->Height2 != height) {
628                   incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i, img->Height2);
629                   return;
630                }
631                if (img->Depth2 != depth) {
632                   incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i, img->Depth2);
633                   return;
634                }
635 
636                /* Extra checks for cube textures */
637                if (face > 0) {
638                   /* check that cube faces are the same size */
639                   if (img->Width2 != t->Image[0][i]->Width2 ||
640                       img->Height2 != t->Image[0][i]->Height2) {
641 		     incomplete(t, MIPMAP, "CubeMap Image[n][i] bad size");
642 		     return;
643 		  }
644                }
645             }
646          }
647 
648          if (width == 1 && height == 1 && depth == 1) {
649             return;  /* found smallest needed mipmap, all done! */
650          }
651       }
652    }
653 }
654 
655 
656 /**
657  * Check if the given cube map texture is "cube complete" as defined in
658  * the OpenGL specification.
659  */
660 GLboolean
_mesa_cube_complete(const struct gl_texture_object * texObj)661 _mesa_cube_complete(const struct gl_texture_object *texObj)
662 {
663    const GLint baseLevel = texObj->BaseLevel;
664    const struct gl_texture_image *img0, *img;
665    GLuint face;
666 
667    if (texObj->Target != GL_TEXTURE_CUBE_MAP)
668       return GL_FALSE;
669 
670    if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS))
671       return GL_FALSE;
672 
673    /* check first face */
674    img0 = texObj->Image[0][baseLevel];
675    if (!img0 ||
676        img0->Width < 1 ||
677        img0->Width != img0->Height)
678       return GL_FALSE;
679 
680    /* check remaining faces vs. first face */
681    for (face = 1; face < 6; face++) {
682       img = texObj->Image[face][baseLevel];
683       if (!img ||
684           img->Width != img0->Width ||
685           img->Height != img0->Height ||
686           img->TexFormat != img0->TexFormat)
687          return GL_FALSE;
688    }
689 
690    return GL_TRUE;
691 }
692 
693 
694 /**
695  * Mark a texture object dirty.  It forces the object to be incomplete
696  * and optionally forces the context to re-validate its state.
697  *
698  * \param ctx GL context.
699  * \param texObj texture object.
700  * \param invalidate_state also invalidate context state.
701  */
702 void
_mesa_dirty_texobj(struct gl_context * ctx,struct gl_texture_object * texObj,GLboolean invalidate_state)703 _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
704                    GLboolean invalidate_state)
705 {
706    texObj->_BaseComplete = GL_FALSE;
707    texObj->_MipmapComplete = GL_FALSE;
708    if (invalidate_state)
709       ctx->NewState |= _NEW_TEXTURE;
710 }
711 
712 
713 /**
714  * Return pointer to a default/fallback texture of the given type/target.
715  * The texture is an RGBA texture with all texels = (0,0,0,1).
716  * That's the value a GLSL sampler should get when sampling from an
717  * incomplete texture.
718  */
719 struct gl_texture_object *
_mesa_get_fallback_texture(struct gl_context * ctx,gl_texture_index tex)720 _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
721 {
722    if (!ctx->Shared->FallbackTex[tex]) {
723       /* create fallback texture now */
724       const GLsizei width = 1, height = 1, depth = 1;
725       GLubyte texel[4];
726       struct gl_texture_object *texObj;
727       struct gl_texture_image *texImage;
728       gl_format texFormat;
729       GLuint dims, face, numFaces = 1;
730       GLenum target;
731 
732       texel[0] =
733       texel[1] =
734       texel[2] = 0x0;
735       texel[3] = 0xff;
736 
737       switch (tex) {
738       case TEXTURE_2D_ARRAY_INDEX:
739          dims = 3;
740          target = GL_TEXTURE_2D_ARRAY;
741          break;
742       case TEXTURE_1D_ARRAY_INDEX:
743          dims = 2;
744          target = GL_TEXTURE_1D_ARRAY;
745          break;
746       case TEXTURE_CUBE_INDEX:
747          dims = 2;
748          target = GL_TEXTURE_CUBE_MAP;
749          numFaces = 6;
750          break;
751       case TEXTURE_3D_INDEX:
752          dims = 3;
753          target = GL_TEXTURE_3D;
754          break;
755       case TEXTURE_RECT_INDEX:
756          dims = 2;
757          target = GL_TEXTURE_RECTANGLE;
758          break;
759       case TEXTURE_2D_INDEX:
760          dims = 2;
761          target = GL_TEXTURE_2D;
762          break;
763       case TEXTURE_1D_INDEX:
764          dims = 1;
765          target = GL_TEXTURE_1D;
766          break;
767       case TEXTURE_BUFFER_INDEX:
768          dims = 0;
769          target = GL_TEXTURE_BUFFER;
770          break;
771       case TEXTURE_EXTERNAL_INDEX:
772          dims = 2;
773          target = GL_TEXTURE_EXTERNAL_OES;
774          break;
775       default:
776          /* no-op */
777          return NULL;
778       }
779 
780       /* create texture object */
781       texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
782       if (!texObj)
783          return NULL;
784 
785       assert(texObj->RefCount == 1);
786       texObj->Sampler.MinFilter = GL_NEAREST;
787       texObj->Sampler.MagFilter = GL_NEAREST;
788 
789       texFormat = ctx->Driver.ChooseTextureFormat(ctx, target,
790                                                   GL_RGBA, GL_RGBA,
791                                                   GL_UNSIGNED_BYTE);
792 
793       /* need a loop here just for cube maps */
794       for (face = 0; face < numFaces; face++) {
795          GLenum faceTarget;
796 
797          if (target == GL_TEXTURE_CUBE_MAP)
798             faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
799          else
800             faceTarget = target;
801 
802          /* initialize level[0] texture image */
803          texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
804 
805          _mesa_init_teximage_fields(ctx, texImage,
806                                     width,
807                                     (dims > 1) ? height : 1,
808                                     (dims > 2) ? depth : 1,
809                                     0, /* border */
810                                     GL_RGBA, texFormat);
811 
812          ctx->Driver.TexImage(ctx, dims, texImage,
813                               GL_RGBA, GL_UNSIGNED_BYTE, texel,
814                               &ctx->DefaultPacking);
815       }
816 
817       _mesa_test_texobj_completeness(ctx, texObj);
818       assert(texObj->_BaseComplete);
819       assert(texObj->_MipmapComplete);
820 
821       ctx->Shared->FallbackTex[tex] = texObj;
822    }
823    return ctx->Shared->FallbackTex[tex];
824 }
825 
826 
827 /**
828  * Compute the size of the given texture object, in bytes.
829  */
830 static GLuint
texture_size(const struct gl_texture_object * texObj)831 texture_size(const struct gl_texture_object *texObj)
832 {
833    const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
834    GLuint face, level, size = 0;
835 
836    for (face = 0; face < numFaces; face++) {
837       for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
838          const struct gl_texture_image *img = texObj->Image[face][level];
839          if (img) {
840             GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
841                                                 img->Height, img->Depth);
842             size += sz;
843          }
844       }
845    }
846 
847    return size;
848 }
849 
850 
851 /**
852  * Callback called from _mesa_HashWalk()
853  */
854 static void
count_tex_size(GLuint key,void * data,void * userData)855 count_tex_size(GLuint key, void *data, void *userData)
856 {
857    const struct gl_texture_object *texObj =
858       (const struct gl_texture_object *) data;
859    GLuint *total = (GLuint *) userData;
860 
861    *total = *total + texture_size(texObj);
862 }
863 
864 
865 /**
866  * Compute total size (in bytes) of all textures for the given context.
867  * For debugging purposes.
868  */
869 GLuint
_mesa_total_texture_memory(struct gl_context * ctx)870 _mesa_total_texture_memory(struct gl_context *ctx)
871 {
872    GLuint tgt, total = 0;
873 
874    _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total);
875 
876    /* plus, the default texture objects */
877    for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
878       total += texture_size(ctx->Shared->DefaultTex[tgt]);
879    }
880 
881    return total;
882 }
883 
884 static struct gl_texture_object *
invalidate_tex_image_error_check(struct gl_context * ctx,GLuint texture,GLint level,const char * name)885 invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture,
886                                  GLint level, const char *name)
887 {
888    /* The GL_ARB_invalidate_subdata spec says:
889     *
890     *     "If <texture> is zero or is not the name of a texture, the error
891     *     INVALID_VALUE is generated."
892     *
893     * This performs the error check in a different order than listed in the
894     * spec.  We have to get the texture object before we can validate the
895     * other parameters against values in the texture object.
896     */
897    struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture);
898    if (texture == 0 || t == NULL) {
899       _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name);
900       return NULL;
901    }
902 
903    /* The GL_ARB_invalidate_subdata spec says:
904     *
905     *     "If <level> is less than zero or greater than the base 2 logarithm
906     *     of the maximum texture width, height, or depth, the error
907     *     INVALID_VALUE is generated."
908     */
909    if (level < 0 || level > t->MaxLevel) {
910       _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
911       return NULL;
912    }
913 
914    /* The GL_ARB_invalidate_subdata spec says:
915     *
916     *     "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
917     *     TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
918     *     is not zero, the error INVALID_VALUE is generated."
919     */
920    if (level != 0) {
921       switch (t->Target) {
922       case GL_TEXTURE_RECTANGLE:
923       case GL_TEXTURE_BUFFER:
924       case GL_TEXTURE_2D_MULTISAMPLE:
925       case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
926          _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
927          return NULL;
928 
929       default:
930          break;
931       }
932    }
933 
934    return t;
935 }
936 
937 /*@}*/
938 
939 
940 /***********************************************************************/
941 /** \name API functions */
942 /*@{*/
943 
944 
945 /**
946  * Generate texture names.
947  *
948  * \param n number of texture names to be generated.
949  * \param textures an array in which will hold the generated texture names.
950  *
951  * \sa glGenTextures().
952  *
953  * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
954  * IDs which are stored in \p textures.  Corresponding empty texture
955  * objects are also generated.
956  */
957 void GLAPIENTRY
_mesa_GenTextures(GLsizei n,GLuint * textures)958 _mesa_GenTextures( GLsizei n, GLuint *textures )
959 {
960    GET_CURRENT_CONTEXT(ctx);
961    GLuint first;
962    GLint i;
963    ASSERT_OUTSIDE_BEGIN_END(ctx);
964 
965    if (n < 0) {
966       _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
967       return;
968    }
969 
970    if (!textures)
971       return;
972 
973    /*
974     * This must be atomic (generation and allocation of texture IDs)
975     */
976    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
977 
978    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
979 
980    /* Allocate new, empty texture objects */
981    for (i = 0; i < n; i++) {
982       struct gl_texture_object *texObj;
983       GLuint name = first + i;
984       GLenum target = 0;
985       texObj = ctx->Driver.NewTextureObject(ctx, name, target);
986       if (!texObj) {
987          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
988          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
989          return;
990       }
991 
992       /* insert into hash table */
993       _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
994 
995       textures[i] = name;
996    }
997 
998    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
999 }
1000 
1001 
1002 /**
1003  * Check if the given texture object is bound to the current draw or
1004  * read framebuffer.  If so, Unbind it.
1005  */
1006 static void
unbind_texobj_from_fbo(struct gl_context * ctx,struct gl_texture_object * texObj)1007 unbind_texobj_from_fbo(struct gl_context *ctx,
1008                        struct gl_texture_object *texObj)
1009 {
1010    const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2;
1011    GLuint i;
1012 
1013    for (i = 0; i < n; i++) {
1014       struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer;
1015       if (_mesa_is_user_fbo(fb)) {
1016          GLuint j;
1017          for (j = 0; j < BUFFER_COUNT; j++) {
1018             if (fb->Attachment[j].Type == GL_TEXTURE &&
1019                 fb->Attachment[j].Texture == texObj) {
1020 	       /* Vertices are already flushed by _mesa_DeleteTextures */
1021 	       ctx->NewState |= _NEW_BUFFERS;
1022                _mesa_remove_attachment(ctx, fb->Attachment + j);
1023             }
1024          }
1025       }
1026    }
1027 }
1028 
1029 
1030 /**
1031  * Check if the given texture object is bound to any texture image units and
1032  * unbind it if so (revert to default textures).
1033  */
1034 static void
unbind_texobj_from_texunits(struct gl_context * ctx,struct gl_texture_object * texObj)1035 unbind_texobj_from_texunits(struct gl_context *ctx,
1036                             struct gl_texture_object *texObj)
1037 {
1038    GLuint u, tex;
1039 
1040    for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
1041       struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
1042       for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
1043          if (texObj == unit->CurrentTex[tex]) {
1044             _mesa_reference_texobj(&unit->CurrentTex[tex],
1045                                    ctx->Shared->DefaultTex[tex]);
1046             ASSERT(unit->CurrentTex[tex]);
1047             break;
1048          }
1049       }
1050    }
1051 }
1052 
1053 
1054 /**
1055  * Delete named textures.
1056  *
1057  * \param n number of textures to be deleted.
1058  * \param textures array of texture IDs to be deleted.
1059  *
1060  * \sa glDeleteTextures().
1061  *
1062  * If we're about to delete a texture that's currently bound to any
1063  * texture unit, unbind the texture first.  Decrement the reference
1064  * count on the texture object and delete it if it's zero.
1065  * Recall that texture objects can be shared among several rendering
1066  * contexts.
1067  */
1068 void GLAPIENTRY
_mesa_DeleteTextures(GLsizei n,const GLuint * textures)1069 _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
1070 {
1071    GET_CURRENT_CONTEXT(ctx);
1072    GLint i;
1073    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
1074 
1075    if (!textures)
1076       return;
1077 
1078    for (i = 0; i < n; i++) {
1079       if (textures[i] > 0) {
1080          struct gl_texture_object *delObj
1081             = _mesa_lookup_texture(ctx, textures[i]);
1082 
1083          if (delObj) {
1084             _mesa_lock_texture(ctx, delObj);
1085 
1086             /* Check if texture is bound to any framebuffer objects.
1087              * If so, unbind.
1088              * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1089              */
1090             unbind_texobj_from_fbo(ctx, delObj);
1091 
1092             /* Check if this texture is currently bound to any texture units.
1093              * If so, unbind it.
1094              */
1095             unbind_texobj_from_texunits(ctx, delObj);
1096 
1097             _mesa_unlock_texture(ctx, delObj);
1098 
1099             ctx->NewState |= _NEW_TEXTURE;
1100 
1101             /* The texture _name_ is now free for re-use.
1102              * Remove it from the hash table now.
1103              */
1104             _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1105             _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
1106             _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1107 
1108             /* Unreference the texobj.  If refcount hits zero, the texture
1109              * will be deleted.
1110              */
1111             _mesa_reference_texobj(&delObj, NULL);
1112          }
1113       }
1114    }
1115 }
1116 
1117 
1118 /**
1119  * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
1120  * into the corresponding Mesa texture target index.
1121  * Note that proxy targets are not valid here.
1122  * \return TEXTURE_x_INDEX or -1 if target is invalid
1123  */
1124 static GLint
target_enum_to_index(struct gl_context * ctx,GLenum target)1125 target_enum_to_index(struct gl_context *ctx, GLenum target)
1126 {
1127    switch (target) {
1128    case GL_TEXTURE_1D:
1129       return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1;
1130    case GL_TEXTURE_2D:
1131       return TEXTURE_2D_INDEX;
1132    case GL_TEXTURE_3D:
1133       return TEXTURE_3D_INDEX;
1134    case GL_TEXTURE_CUBE_MAP_ARB:
1135       return ctx->Extensions.ARB_texture_cube_map
1136          ? TEXTURE_CUBE_INDEX : -1;
1137    case GL_TEXTURE_RECTANGLE_NV:
1138       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle
1139          ? TEXTURE_RECT_INDEX : -1;
1140    case GL_TEXTURE_1D_ARRAY_EXT:
1141       return _mesa_is_desktop_gl(ctx)
1142          && (ctx->Extensions.EXT_texture_array
1143              || ctx->Extensions.MESA_texture_array)
1144          ? TEXTURE_1D_ARRAY_INDEX : -1;
1145    case GL_TEXTURE_2D_ARRAY_EXT:
1146       return (_mesa_is_desktop_gl(ctx)
1147               && (ctx->Extensions.EXT_texture_array
1148                   || ctx->Extensions.MESA_texture_array))
1149          || _mesa_is_gles3(ctx)
1150          ? TEXTURE_2D_ARRAY_INDEX : -1;
1151    case GL_TEXTURE_BUFFER_ARB:
1152       return _mesa_is_desktop_gl(ctx)
1153          && ctx->Extensions.ARB_texture_buffer_object
1154          ? TEXTURE_BUFFER_INDEX : -1;
1155    case GL_TEXTURE_EXTERNAL_OES:
1156       return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
1157          ? TEXTURE_EXTERNAL_INDEX : -1;
1158    default:
1159       return -1;
1160    }
1161 }
1162 
1163 
1164 /**
1165  * Bind a named texture to a texturing target.
1166  *
1167  * \param target texture target.
1168  * \param texName texture name.
1169  *
1170  * \sa glBindTexture().
1171  *
1172  * Determines the old texture object bound and returns immediately if rebinding
1173  * the same texture.  Get the current texture which is either a default texture
1174  * if name is null, a named texture from the hash, or a new texture if the
1175  * given texture name is new. Increments its reference count, binds it, and
1176  * calls dd_function_table::BindTexture. Decrements the old texture reference
1177  * count and deletes it if it reaches zero.
1178  */
1179 void GLAPIENTRY
_mesa_BindTexture(GLenum target,GLuint texName)1180 _mesa_BindTexture( GLenum target, GLuint texName )
1181 {
1182    GET_CURRENT_CONTEXT(ctx);
1183    struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
1184    struct gl_texture_object *newTexObj = NULL;
1185    GLint targetIndex;
1186    ASSERT_OUTSIDE_BEGIN_END(ctx);
1187 
1188    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1189       _mesa_debug(ctx, "glBindTexture %s %d\n",
1190                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
1191 
1192    targetIndex = target_enum_to_index(ctx, target);
1193    if (targetIndex < 0) {
1194       _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
1195       return;
1196    }
1197    assert(targetIndex < NUM_TEXTURE_TARGETS);
1198 
1199    /*
1200     * Get pointer to new texture object (newTexObj)
1201     */
1202    if (texName == 0) {
1203       /* Use a default texture object */
1204       newTexObj = ctx->Shared->DefaultTex[targetIndex];
1205    }
1206    else {
1207       /* non-default texture object */
1208       newTexObj = _mesa_lookup_texture(ctx, texName);
1209       if (newTexObj) {
1210          /* error checking */
1211          if (newTexObj->Target != 0 && newTexObj->Target != target) {
1212             /* the named texture object's target doesn't match the given target */
1213             _mesa_error( ctx, GL_INVALID_OPERATION,
1214                          "glBindTexture(target mismatch)" );
1215             return;
1216          }
1217          if (newTexObj->Target == 0) {
1218             finish_texture_init(ctx, target, newTexObj);
1219          }
1220       }
1221       else {
1222          if (ctx->API == API_OPENGL_CORE) {
1223             _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTexture");
1224             return;
1225          }
1226 
1227          /* if this is a new texture id, allocate a texture object now */
1228          newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
1229          if (!newTexObj) {
1230             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
1231             return;
1232          }
1233 
1234          /* and insert it into hash table */
1235          _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1236          _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
1237          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1238       }
1239       newTexObj->Target = target;
1240    }
1241 
1242    assert(valid_texture_object(newTexObj));
1243 
1244    /* Check if this texture is only used by this context and is already bound.
1245     * If so, just return.
1246     */
1247    {
1248       GLboolean early_out;
1249       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1250       early_out = ((ctx->Shared->RefCount == 1)
1251                    && (newTexObj == texUnit->CurrentTex[targetIndex]));
1252       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1253       if (early_out) {
1254          return;
1255       }
1256    }
1257 
1258    /* flush before changing binding */
1259    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1260 
1261    /* Do the actual binding.  The refcount on the previously bound
1262     * texture object will be decremented.  It'll be deleted if the
1263     * count hits zero.
1264     */
1265    _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
1266    ASSERT(texUnit->CurrentTex[targetIndex]);
1267 
1268    /* Pass BindTexture call to device driver */
1269    if (ctx->Driver.BindTexture)
1270       ctx->Driver.BindTexture(ctx, target, newTexObj);
1271 }
1272 
1273 
1274 /**
1275  * Set texture priorities.
1276  *
1277  * \param n number of textures.
1278  * \param texName texture names.
1279  * \param priorities corresponding texture priorities.
1280  *
1281  * \sa glPrioritizeTextures().
1282  *
1283  * Looks up each texture in the hash, clamps the corresponding priority between
1284  * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
1285  */
1286 void GLAPIENTRY
_mesa_PrioritizeTextures(GLsizei n,const GLuint * texName,const GLclampf * priorities)1287 _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
1288                           const GLclampf *priorities )
1289 {
1290    GET_CURRENT_CONTEXT(ctx);
1291    GLint i;
1292    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1293 
1294    if (n < 0) {
1295       _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
1296       return;
1297    }
1298 
1299    if (!priorities)
1300       return;
1301 
1302    for (i = 0; i < n; i++) {
1303       if (texName[i] > 0) {
1304          struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
1305          if (t) {
1306             t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
1307          }
1308       }
1309    }
1310 
1311    ctx->NewState |= _NEW_TEXTURE;
1312 }
1313 
1314 
1315 
1316 /**
1317  * See if textures are loaded in texture memory.
1318  *
1319  * \param n number of textures to query.
1320  * \param texName array with the texture names.
1321  * \param residences array which will hold the residence status.
1322  *
1323  * \return GL_TRUE if all textures are resident and \p residences is left unchanged,
1324  *
1325  * Note: we assume all textures are always resident
1326  */
1327 GLboolean GLAPIENTRY
_mesa_AreTexturesResident(GLsizei n,const GLuint * texName,GLboolean * residences)1328 _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
1329                           GLboolean *residences)
1330 {
1331    GET_CURRENT_CONTEXT(ctx);
1332    GLboolean allResident = GL_TRUE;
1333    GLint i;
1334    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1335 
1336    if (n < 0) {
1337       _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
1338       return GL_FALSE;
1339    }
1340 
1341    if (!texName || !residences)
1342       return GL_FALSE;
1343 
1344    /* We only do error checking on the texture names */
1345    for (i = 0; i < n; i++) {
1346       struct gl_texture_object *t;
1347       if (texName[i] == 0) {
1348          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1349          return GL_FALSE;
1350       }
1351       t = _mesa_lookup_texture(ctx, texName[i]);
1352       if (!t) {
1353          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1354          return GL_FALSE;
1355       }
1356    }
1357 
1358    return allResident;
1359 }
1360 
1361 
1362 /**
1363  * See if a name corresponds to a texture.
1364  *
1365  * \param texture texture name.
1366  *
1367  * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
1368  * otherwise.
1369  *
1370  * \sa glIsTexture().
1371  *
1372  * Calls _mesa_HashLookup().
1373  */
1374 GLboolean GLAPIENTRY
_mesa_IsTexture(GLuint texture)1375 _mesa_IsTexture( GLuint texture )
1376 {
1377    struct gl_texture_object *t;
1378    GET_CURRENT_CONTEXT(ctx);
1379    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1380 
1381    if (!texture)
1382       return GL_FALSE;
1383 
1384    t = _mesa_lookup_texture(ctx, texture);
1385 
1386    /* IsTexture is true only after object has been bound once. */
1387    return t && t->Target;
1388 }
1389 
1390 
1391 /**
1392  * Simplest implementation of texture locking: grab the shared tex
1393  * mutex.  Examine the shared context state timestamp and if there has
1394  * been a change, set the appropriate bits in ctx->NewState.
1395  *
1396  * This is used to deal with synchronizing things when a texture object
1397  * is used/modified by different contexts (or threads) which are sharing
1398  * the texture.
1399  *
1400  * See also _mesa_lock/unlock_texture() in teximage.h
1401  */
1402 void
_mesa_lock_context_textures(struct gl_context * ctx)1403 _mesa_lock_context_textures( struct gl_context *ctx )
1404 {
1405    _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
1406 
1407    if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
1408       ctx->NewState |= _NEW_TEXTURE;
1409       ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
1410    }
1411 }
1412 
1413 
1414 void
_mesa_unlock_context_textures(struct gl_context * ctx)1415 _mesa_unlock_context_textures( struct gl_context *ctx )
1416 {
1417    assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
1418    _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
1419 }
1420 
1421 void GLAPIENTRY
_mesa_InvalidateTexSubImage(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth)1422 _mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
1423                             GLint yoffset, GLint zoffset, GLsizei width,
1424                             GLsizei height, GLsizei depth)
1425 {
1426    struct gl_texture_object *t;
1427    struct gl_texture_image *image;
1428    GET_CURRENT_CONTEXT(ctx);
1429 
1430    ASSERT_OUTSIDE_BEGIN_END(ctx);
1431 
1432    t = invalidate_tex_image_error_check(ctx, texture, level,
1433                                         "glInvalidateTexSubImage");
1434 
1435    /* The GL_ARB_invalidate_subdata spec says:
1436     *
1437     *     "...the specified subregion must be between -<b> and <dim>+<b> where
1438     *     <dim> is the size of the dimension of the texture image, and <b> is
1439     *     the size of the border of that texture image, otherwise
1440     *     INVALID_VALUE is generated (border is not applied to dimensions that
1441     *     don't exist in a given texture target)."
1442     */
1443    image = t->Image[0][level];
1444    if (image) {
1445       int xBorder;
1446       int yBorder;
1447       int zBorder;
1448       int imageWidth;
1449       int imageHeight;
1450       int imageDepth;
1451 
1452       /* The GL_ARB_invalidate_subdata spec says:
1453        *
1454        *     "For texture targets that don't have certain dimensions, this
1455        *     command treats those dimensions as having a size of 1. For
1456        *     example, to invalidate a portion of a two-dimensional texture,
1457        *     the application would use <zoffset> equal to zero and <depth>
1458        *     equal to one."
1459        */
1460       switch (t->Target) {
1461       case GL_TEXTURE_BUFFER:
1462          xBorder = 0;
1463          yBorder = 0;
1464          zBorder = 0;
1465          imageWidth = 1;
1466          imageHeight = 1;
1467          imageDepth = 1;
1468          break;
1469       case GL_TEXTURE_1D:
1470          xBorder = image->Border;
1471          yBorder = 0;
1472          zBorder = 0;
1473          imageWidth = image->Width;
1474          imageHeight = 1;
1475          imageDepth = 1;
1476          break;
1477       case GL_TEXTURE_1D_ARRAY:
1478          xBorder = image->Border;
1479          yBorder = 0;
1480          zBorder = 0;
1481          imageWidth = image->Width;
1482          imageHeight = image->Height;
1483          imageDepth = 1;
1484          break;
1485       case GL_TEXTURE_2D:
1486       case GL_TEXTURE_CUBE_MAP:
1487       case GL_TEXTURE_RECTANGLE:
1488       case GL_TEXTURE_2D_MULTISAMPLE:
1489          xBorder = image->Border;
1490          yBorder = image->Border;
1491          zBorder = 0;
1492          imageWidth = image->Width;
1493          imageHeight = image->Height;
1494          imageDepth = 1;
1495          break;
1496       case GL_TEXTURE_2D_ARRAY:
1497       case GL_TEXTURE_CUBE_MAP_ARRAY:
1498          xBorder = image->Border;
1499          yBorder = image->Border;
1500          zBorder = 0;
1501          imageWidth = image->Width;
1502          imageHeight = image->Height;
1503          imageDepth = image->Depth;
1504          break;
1505       case GL_TEXTURE_3D:
1506          xBorder = image->Border;
1507          yBorder = image->Border;
1508          zBorder = image->Border;
1509          imageWidth = image->Width;
1510          imageHeight = image->Height;
1511          imageDepth = image->Depth;
1512          break;
1513       default:
1514          assert(!"Should not get here.");
1515          xBorder = 0;
1516          yBorder = 0;
1517          zBorder = 0;
1518          imageWidth = 0;
1519          imageHeight = 0;
1520          imageDepth = 0;
1521          break;
1522       }
1523 
1524       if (xoffset < -xBorder) {
1525          _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)");
1526          return;
1527       }
1528 
1529       if (xoffset + width > imageWidth + xBorder) {
1530          _mesa_error(ctx, GL_INVALID_VALUE,
1531                      "glInvalidateSubTexImage(xoffset+width)");
1532          return;
1533       }
1534 
1535       if (yoffset < -yBorder) {
1536          _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)");
1537          return;
1538       }
1539 
1540       if (yoffset + height > imageHeight + yBorder) {
1541          _mesa_error(ctx, GL_INVALID_VALUE,
1542                      "glInvalidateSubTexImage(yoffset+height)");
1543          return;
1544       }
1545 
1546       if (zoffset < -zBorder) {
1547          _mesa_error(ctx, GL_INVALID_VALUE,
1548                      "glInvalidateSubTexImage(zoffset)");
1549          return;
1550       }
1551 
1552       if (zoffset + depth  > imageDepth + zBorder) {
1553          _mesa_error(ctx, GL_INVALID_VALUE,
1554                      "glInvalidateSubTexImage(zoffset+depth)");
1555          return;
1556       }
1557    }
1558 
1559    /* We don't actually do anything for this yet.  Just return after
1560     * validating the parameters and generating the required errors.
1561     */
1562    return;
1563 }
1564 
1565 void GLAPIENTRY
_mesa_InvalidateTexImage(GLuint texture,GLint level)1566 _mesa_InvalidateTexImage(GLuint texture, GLint level)
1567 {
1568    GET_CURRENT_CONTEXT(ctx);
1569 
1570    ASSERT_OUTSIDE_BEGIN_END(ctx);
1571 
1572    invalidate_tex_image_error_check(ctx, texture, level,
1573                                     "glInvalidateTexImage");
1574 
1575    /* We don't actually do anything for this yet.  Just return after
1576     * validating the parameters and generating the required errors.
1577     */
1578    return;
1579 }
1580 
1581 /*@}*/
1582