texobj.c revision 01e04c3f
17117f1b4Smrg/**
27117f1b4Smrg * \file texobj.c
37117f1b4Smrg * Texture object management.
47117f1b4Smrg */
57117f1b4Smrg
67117f1b4Smrg/*
77117f1b4Smrg * Mesa 3-D graphics library
87117f1b4Smrg *
9c1f859d4Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
107117f1b4Smrg *
117117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
127117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
137117f1b4Smrg * to deal in the Software without restriction, including without limitation
147117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
157117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
167117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
177117f1b4Smrg *
187117f1b4Smrg * The above copyright notice and this permission notice shall be included
197117f1b4Smrg * in all copies or substantial portions of the Software.
207117f1b4Smrg *
217117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
227117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
237117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
287117f1b4Smrg */
297117f1b4Smrg
307117f1b4Smrg
3101e04c3fSmrg#include <stdio.h>
323464ebd5Sriastradh#include "bufferobj.h"
337117f1b4Smrg#include "context.h"
347117f1b4Smrg#include "enums.h"
357117f1b4Smrg#include "fbobject.h"
364a49301eSmrg#include "formats.h"
377117f1b4Smrg#include "hash.h"
387117f1b4Smrg#include "imports.h"
397117f1b4Smrg#include "macros.h"
4001e04c3fSmrg#include "shaderimage.h"
417117f1b4Smrg#include "teximage.h"
427117f1b4Smrg#include "texobj.h"
433464ebd5Sriastradh#include "texstate.h"
447117f1b4Smrg#include "mtypes.h"
453464ebd5Sriastradh#include "program/prog_instruction.h"
4601e04c3fSmrg#include "texturebindless.h"
474a49301eSmrg
487117f1b4Smrg
497117f1b4Smrg
507117f1b4Smrg/**********************************************************************/
517117f1b4Smrg/** \name Internal functions */
527117f1b4Smrg/*@{*/
537117f1b4Smrg
5401e04c3fSmrg/**
5501e04c3fSmrg * This function checks for all valid combinations of Min and Mag filters for
5601e04c3fSmrg * Float types, when extensions like OES_texture_float and
5701e04c3fSmrg * OES_texture_float_linear are supported. OES_texture_float mentions support
5801e04c3fSmrg * for NEAREST, NEAREST_MIPMAP_NEAREST magnification and minification filters.
5901e04c3fSmrg * Mag filters like LINEAR and min filters like NEAREST_MIPMAP_LINEAR,
6001e04c3fSmrg * LINEAR_MIPMAP_NEAREST and LINEAR_MIPMAP_LINEAR are only valid in case
6101e04c3fSmrg * OES_texture_float_linear is supported.
6201e04c3fSmrg *
6301e04c3fSmrg * Returns true in case the filter is valid for given Float type else false.
6401e04c3fSmrg */
6501e04c3fSmrgstatic bool
6601e04c3fSmrgvalid_filter_for_float(const struct gl_context *ctx,
6701e04c3fSmrg                       const struct gl_texture_object *obj)
6801e04c3fSmrg{
6901e04c3fSmrg   switch (obj->Sampler.MagFilter) {
7001e04c3fSmrg   case GL_LINEAR:
7101e04c3fSmrg      if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) {
7201e04c3fSmrg         return false;
7301e04c3fSmrg      } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) {
7401e04c3fSmrg         return false;
7501e04c3fSmrg      }
7601e04c3fSmrg   case GL_NEAREST:
7701e04c3fSmrg   case GL_NEAREST_MIPMAP_NEAREST:
7801e04c3fSmrg      break;
7901e04c3fSmrg   default:
8001e04c3fSmrg      unreachable("Invalid mag filter");
8101e04c3fSmrg   }
8201e04c3fSmrg
8301e04c3fSmrg   switch (obj->Sampler.MinFilter) {
8401e04c3fSmrg   case GL_LINEAR:
8501e04c3fSmrg   case GL_NEAREST_MIPMAP_LINEAR:
8601e04c3fSmrg   case GL_LINEAR_MIPMAP_NEAREST:
8701e04c3fSmrg   case GL_LINEAR_MIPMAP_LINEAR:
8801e04c3fSmrg      if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) {
8901e04c3fSmrg         return false;
9001e04c3fSmrg      } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) {
9101e04c3fSmrg         return false;
9201e04c3fSmrg      }
9301e04c3fSmrg   case GL_NEAREST:
9401e04c3fSmrg   case GL_NEAREST_MIPMAP_NEAREST:
9501e04c3fSmrg      break;
9601e04c3fSmrg   default:
9701e04c3fSmrg      unreachable("Invalid min filter");
9801e04c3fSmrg   }
9901e04c3fSmrg
10001e04c3fSmrg   return true;
10101e04c3fSmrg}
1027117f1b4Smrg
1037117f1b4Smrg/**
1047117f1b4Smrg * Return the gl_texture_object for a given ID.
1057117f1b4Smrg */
1067117f1b4Smrgstruct gl_texture_object *
1073464ebd5Sriastradh_mesa_lookup_texture(struct gl_context *ctx, GLuint id)
1087117f1b4Smrg{
1097117f1b4Smrg   return (struct gl_texture_object *)
1107117f1b4Smrg      _mesa_HashLookup(ctx->Shared->TexObjects, id);
1117117f1b4Smrg}
1127117f1b4Smrg
11301e04c3fSmrg/**
11401e04c3fSmrg * Wrapper around _mesa_lookup_texture that throws GL_INVALID_OPERATION if id
11501e04c3fSmrg * is not in the hash table. After calling _mesa_error, it returns NULL.
11601e04c3fSmrg */
11701e04c3fSmrgstruct gl_texture_object *
11801e04c3fSmrg_mesa_lookup_texture_err(struct gl_context *ctx, GLuint id, const char* func)
119af69d88dSmrg{
12001e04c3fSmrg   struct gl_texture_object *texObj = NULL;
121af69d88dSmrg
12201e04c3fSmrg   if (id > 0)
12301e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */
124af69d88dSmrg
12501e04c3fSmrg   if (!texObj)
12601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture)", func);
12701e04c3fSmrg
12801e04c3fSmrg   return texObj;
129af69d88dSmrg}
130af69d88dSmrg
131af69d88dSmrg
132af69d88dSmrgstruct gl_texture_object *
133af69d88dSmrg_mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id)
134af69d88dSmrg{
135af69d88dSmrg   return (struct gl_texture_object *)
136af69d88dSmrg      _mesa_HashLookupLocked(ctx->Shared->TexObjects, id);
137af69d88dSmrg}
138af69d88dSmrg
13901e04c3fSmrg/**
14001e04c3fSmrg * Return a pointer to the current texture object for the given target
14101e04c3fSmrg * on the current texture unit.
14201e04c3fSmrg * Note: all <target> error checking should have been done by this point.
14301e04c3fSmrg */
14401e04c3fSmrgstruct gl_texture_object *
14501e04c3fSmrg_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
14601e04c3fSmrg{
14701e04c3fSmrg   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
14801e04c3fSmrg   const GLboolean arrayTex = ctx->Extensions.EXT_texture_array;
14901e04c3fSmrg
15001e04c3fSmrg   switch (target) {
15101e04c3fSmrg      case GL_TEXTURE_1D:
15201e04c3fSmrg         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
15301e04c3fSmrg      case GL_PROXY_TEXTURE_1D:
15401e04c3fSmrg         return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
15501e04c3fSmrg      case GL_TEXTURE_2D:
15601e04c3fSmrg         return texUnit->CurrentTex[TEXTURE_2D_INDEX];
15701e04c3fSmrg      case GL_PROXY_TEXTURE_2D:
15801e04c3fSmrg         return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
15901e04c3fSmrg      case GL_TEXTURE_3D:
16001e04c3fSmrg         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
16101e04c3fSmrg      case GL_PROXY_TEXTURE_3D:
16201e04c3fSmrg         return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
16301e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
16401e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
16501e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
16601e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
16701e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
16801e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
16901e04c3fSmrg      case GL_TEXTURE_CUBE_MAP:
17001e04c3fSmrg         return ctx->Extensions.ARB_texture_cube_map
17101e04c3fSmrg                ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
17201e04c3fSmrg      case GL_PROXY_TEXTURE_CUBE_MAP:
17301e04c3fSmrg         return ctx->Extensions.ARB_texture_cube_map
17401e04c3fSmrg                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
17501e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_ARRAY:
17601e04c3fSmrg         return _mesa_has_texture_cube_map_array(ctx)
17701e04c3fSmrg                ? texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
17801e04c3fSmrg      case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
17901e04c3fSmrg         return _mesa_has_texture_cube_map_array(ctx)
18001e04c3fSmrg                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
18101e04c3fSmrg      case GL_TEXTURE_RECTANGLE_NV:
18201e04c3fSmrg         return ctx->Extensions.NV_texture_rectangle
18301e04c3fSmrg                ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
18401e04c3fSmrg      case GL_PROXY_TEXTURE_RECTANGLE_NV:
18501e04c3fSmrg         return ctx->Extensions.NV_texture_rectangle
18601e04c3fSmrg                ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
18701e04c3fSmrg      case GL_TEXTURE_1D_ARRAY_EXT:
18801e04c3fSmrg         return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
18901e04c3fSmrg      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
19001e04c3fSmrg         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
19101e04c3fSmrg      case GL_TEXTURE_2D_ARRAY_EXT:
19201e04c3fSmrg         return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
19301e04c3fSmrg      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
19401e04c3fSmrg         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
19501e04c3fSmrg      case GL_TEXTURE_BUFFER:
19601e04c3fSmrg         return (_mesa_has_ARB_texture_buffer_object(ctx) ||
19701e04c3fSmrg                 _mesa_has_OES_texture_buffer(ctx)) ?
19801e04c3fSmrg                texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
19901e04c3fSmrg      case GL_TEXTURE_EXTERNAL_OES:
20001e04c3fSmrg         return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
20101e04c3fSmrg            ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
20201e04c3fSmrg      case GL_TEXTURE_2D_MULTISAMPLE:
20301e04c3fSmrg         return ctx->Extensions.ARB_texture_multisample
20401e04c3fSmrg            ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
20501e04c3fSmrg      case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
20601e04c3fSmrg         return ctx->Extensions.ARB_texture_multisample
20701e04c3fSmrg            ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
20801e04c3fSmrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
20901e04c3fSmrg         return ctx->Extensions.ARB_texture_multisample
21001e04c3fSmrg            ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
21101e04c3fSmrg      case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
21201e04c3fSmrg         return ctx->Extensions.ARB_texture_multisample
21301e04c3fSmrg            ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
21401e04c3fSmrg      default:
21501e04c3fSmrg         _mesa_problem(NULL, "bad target in _mesa_get_current_tex_object()");
21601e04c3fSmrg         return NULL;
21701e04c3fSmrg   }
21801e04c3fSmrg}
21901e04c3fSmrg
2207117f1b4Smrg
2217117f1b4Smrg/**
2227117f1b4Smrg * Allocate and initialize a new texture object.  But don't put it into the
2237117f1b4Smrg * texture object hash table.
2247117f1b4Smrg *
2257117f1b4Smrg * Called via ctx->Driver.NewTextureObject, unless overridden by a device
2267117f1b4Smrg * driver.
22701e04c3fSmrg *
2287117f1b4Smrg * \param shared the shared GL state structure to contain the texture object
2297117f1b4Smrg * \param name integer name for the texture object
2307117f1b4Smrg * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
23101e04c3fSmrg * GL_TEXTURE_CUBE_MAP or GL_TEXTURE_RECTANGLE_NV.  zero is ok for the sake
2327117f1b4Smrg * of GenTextures()
2337117f1b4Smrg *
2347117f1b4Smrg * \return pointer to new texture object.
2357117f1b4Smrg */
2367117f1b4Smrgstruct gl_texture_object *
23701e04c3fSmrg_mesa_new_texture_object(struct gl_context *ctx, GLuint name, GLenum target)
2387117f1b4Smrg{
2397117f1b4Smrg   struct gl_texture_object *obj;
24001e04c3fSmrg
2417117f1b4Smrg   obj = MALLOC_STRUCT(gl_texture_object);
24201e04c3fSmrg   if (!obj)
24301e04c3fSmrg      return NULL;
24401e04c3fSmrg
245af69d88dSmrg   _mesa_initialize_texture_object(ctx, obj, name, target);
2467117f1b4Smrg   return obj;
2477117f1b4Smrg}
2487117f1b4Smrg
2497117f1b4Smrg
2507117f1b4Smrg/**
2517117f1b4Smrg * Initialize a new texture object to default values.
2527117f1b4Smrg * \param obj  the texture object
2537117f1b4Smrg * \param name  the texture name
2547117f1b4Smrg * \param target  the texture target
2557117f1b4Smrg */
2567117f1b4Smrgvoid
257af69d88dSmrg_mesa_initialize_texture_object( struct gl_context *ctx,
258af69d88dSmrg                                 struct gl_texture_object *obj,
2597117f1b4Smrg                                 GLuint name, GLenum target )
2607117f1b4Smrg{
26101e04c3fSmrg   assert(target == 0 ||
2627117f1b4Smrg          target == GL_TEXTURE_1D ||
2637117f1b4Smrg          target == GL_TEXTURE_2D ||
2647117f1b4Smrg          target == GL_TEXTURE_3D ||
26501e04c3fSmrg          target == GL_TEXTURE_CUBE_MAP ||
266c1f859d4Smrg          target == GL_TEXTURE_RECTANGLE_NV ||
267c1f859d4Smrg          target == GL_TEXTURE_1D_ARRAY_EXT ||
2683464ebd5Sriastradh          target == GL_TEXTURE_2D_ARRAY_EXT ||
269af69d88dSmrg          target == GL_TEXTURE_EXTERNAL_OES ||
270af69d88dSmrg          target == GL_TEXTURE_CUBE_MAP_ARRAY ||
271af69d88dSmrg          target == GL_TEXTURE_BUFFER ||
272af69d88dSmrg          target == GL_TEXTURE_2D_MULTISAMPLE ||
273af69d88dSmrg          target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2747117f1b4Smrg
275cdc920a0Smrg   memset(obj, 0, sizeof(*obj));
2767117f1b4Smrg   /* init the non-zero fields */
27701e04c3fSmrg   simple_mtx_init(&obj->Mutex, mtx_plain);
2787117f1b4Smrg   obj->RefCount = 1;
2797117f1b4Smrg   obj->Name = name;
2807117f1b4Smrg   obj->Target = target;
28101e04c3fSmrg   if (target != 0) {
28201e04c3fSmrg      obj->TargetIndex = _mesa_tex_target_to_index(ctx, target);
28301e04c3fSmrg   }
28401e04c3fSmrg   else {
28501e04c3fSmrg      obj->TargetIndex = NUM_TEXTURE_TARGETS; /* invalid/error value */
28601e04c3fSmrg   }
2877117f1b4Smrg   obj->Priority = 1.0F;
2883464ebd5Sriastradh   obj->BaseLevel = 0;
2893464ebd5Sriastradh   obj->MaxLevel = 1000;
2903464ebd5Sriastradh
291af69d88dSmrg   /* must be one; no support for (YUV) planes in separate buffers */
292af69d88dSmrg   obj->RequiredTextureImageUnits = 1;
293af69d88dSmrg
2943464ebd5Sriastradh   /* sampler state */
295af69d88dSmrg   if (target == GL_TEXTURE_RECTANGLE_NV ||
296af69d88dSmrg       target == GL_TEXTURE_EXTERNAL_OES) {
2973464ebd5Sriastradh      obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
2983464ebd5Sriastradh      obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
2993464ebd5Sriastradh      obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
3003464ebd5Sriastradh      obj->Sampler.MinFilter = GL_LINEAR;
3017117f1b4Smrg   }
3027117f1b4Smrg   else {
3033464ebd5Sriastradh      obj->Sampler.WrapS = GL_REPEAT;
3043464ebd5Sriastradh      obj->Sampler.WrapT = GL_REPEAT;
3053464ebd5Sriastradh      obj->Sampler.WrapR = GL_REPEAT;
3063464ebd5Sriastradh      obj->Sampler.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
3077117f1b4Smrg   }
3083464ebd5Sriastradh   obj->Sampler.MagFilter = GL_LINEAR;
3093464ebd5Sriastradh   obj->Sampler.MinLod = -1000.0;
3103464ebd5Sriastradh   obj->Sampler.MaxLod = 1000.0;
3113464ebd5Sriastradh   obj->Sampler.LodBias = 0.0;
3123464ebd5Sriastradh   obj->Sampler.MaxAnisotropy = 1.0;
3133464ebd5Sriastradh   obj->Sampler.CompareMode = GL_NONE;         /* ARB_shadow */
3143464ebd5Sriastradh   obj->Sampler.CompareFunc = GL_LEQUAL;       /* ARB_shadow */
315af69d88dSmrg   obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
316af69d88dSmrg   obj->StencilSampling = false;
3173464ebd5Sriastradh   obj->Sampler.CubeMapSeamless = GL_FALSE;
31801e04c3fSmrg   obj->Sampler.HandleAllocated = GL_FALSE;
3194a49301eSmrg   obj->Swizzle[0] = GL_RED;
3204a49301eSmrg   obj->Swizzle[1] = GL_GREEN;
3214a49301eSmrg   obj->Swizzle[2] = GL_BLUE;
3224a49301eSmrg   obj->Swizzle[3] = GL_ALPHA;
3234a49301eSmrg   obj->_Swizzle = SWIZZLE_NOOP;
3243464ebd5Sriastradh   obj->Sampler.sRGBDecode = GL_DECODE_EXT;
325af69d88dSmrg   obj->BufferObjectFormat = GL_R8;
326af69d88dSmrg   obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
327af69d88dSmrg   obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
32801e04c3fSmrg
32901e04c3fSmrg   /* GL_ARB_bindless_texture */
33001e04c3fSmrg   _mesa_init_texture_handles(obj);
331c1f859d4Smrg}
332c1f859d4Smrg
333c1f859d4Smrg
334c1f859d4Smrg/**
335c1f859d4Smrg * Some texture initialization can't be finished until we know which
336c1f859d4Smrg * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
337c1f859d4Smrg */
338c1f859d4Smrgstatic void
3393464ebd5Sriastradhfinish_texture_init(struct gl_context *ctx, GLenum target,
34001e04c3fSmrg                    struct gl_texture_object *obj, int targetIndex)
341c1f859d4Smrg{
342af69d88dSmrg   GLenum filter = GL_LINEAR;
343c1f859d4Smrg   assert(obj->Target == 0);
344c1f859d4Smrg
34501e04c3fSmrg   obj->Target = target;
34601e04c3fSmrg   obj->TargetIndex = targetIndex;
34701e04c3fSmrg   assert(obj->TargetIndex < NUM_TEXTURE_TARGETS);
34801e04c3fSmrg
349af69d88dSmrg   switch (target) {
350af69d88dSmrg      case GL_TEXTURE_2D_MULTISAMPLE:
351af69d88dSmrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
352af69d88dSmrg         filter = GL_NEAREST;
353af69d88dSmrg         /* fallthrough */
354af69d88dSmrg
355af69d88dSmrg      case GL_TEXTURE_RECTANGLE_NV:
356af69d88dSmrg      case GL_TEXTURE_EXTERNAL_OES:
357af69d88dSmrg         /* have to init wrap and filter state here - kind of klunky */
358af69d88dSmrg         obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
359af69d88dSmrg         obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
360af69d88dSmrg         obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
361af69d88dSmrg         obj->Sampler.MinFilter = filter;
362af69d88dSmrg         obj->Sampler.MagFilter = filter;
363af69d88dSmrg         if (ctx->Driver.TexParameter) {
36401e04c3fSmrg            /* XXX we probably don't need to make all these calls */
36501e04c3fSmrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_S);
36601e04c3fSmrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_T);
36701e04c3fSmrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_R);
36801e04c3fSmrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_MIN_FILTER);
36901e04c3fSmrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_MAG_FILTER);
370af69d88dSmrg         }
371af69d88dSmrg         break;
372af69d88dSmrg
373af69d88dSmrg      default:
374af69d88dSmrg         /* nothing needs done */
375af69d88dSmrg         break;
376c1f859d4Smrg   }
3777117f1b4Smrg}
3787117f1b4Smrg
3797117f1b4Smrg
3807117f1b4Smrg/**
3817117f1b4Smrg * Deallocate a texture object struct.  It should have already been
3827117f1b4Smrg * removed from the texture object pool.
383c1f859d4Smrg * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
3847117f1b4Smrg *
3857117f1b4Smrg * \param shared the shared GL state to which the object belongs.
3864a49301eSmrg * \param texObj the texture object to delete.
3877117f1b4Smrg */
3887117f1b4Smrgvoid
3893464ebd5Sriastradh_mesa_delete_texture_object(struct gl_context *ctx,
3903464ebd5Sriastradh                            struct gl_texture_object *texObj)
3917117f1b4Smrg{
3927117f1b4Smrg   GLuint i, face;
3937117f1b4Smrg
3947117f1b4Smrg   /* Set Target to an invalid value.  With some assertions elsewhere
3957117f1b4Smrg    * we can try to detect possible use of deleted textures.
3967117f1b4Smrg    */
3977117f1b4Smrg   texObj->Target = 0x99;
3987117f1b4Smrg
3997117f1b4Smrg   /* free the texture images */
4007117f1b4Smrg   for (face = 0; face < 6; face++) {
4017117f1b4Smrg      for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
4023464ebd5Sriastradh         if (texObj->Image[face][i]) {
403af69d88dSmrg            ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]);
4043464ebd5Sriastradh         }
4057117f1b4Smrg      }
4067117f1b4Smrg   }
4077117f1b4Smrg
40801e04c3fSmrg   /* Delete all texture/image handles. */
40901e04c3fSmrg   _mesa_delete_texture_handles(ctx, texObj);
41001e04c3fSmrg
4113464ebd5Sriastradh   _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
4123464ebd5Sriastradh
4137117f1b4Smrg   /* destroy the mutex -- it may have allocated memory (eg on bsd) */
41401e04c3fSmrg   simple_mtx_destroy(&texObj->Mutex);
415af69d88dSmrg
416af69d88dSmrg   free(texObj->Label);
4177117f1b4Smrg
4187117f1b4Smrg   /* free this object */
419cdc920a0Smrg   free(texObj);
4207117f1b4Smrg}
4217117f1b4Smrg
4227117f1b4Smrg
4237117f1b4Smrg/**
4247117f1b4Smrg * Copy texture object state from one texture object to another.
4257117f1b4Smrg * Use for glPush/PopAttrib.
4267117f1b4Smrg *
4277117f1b4Smrg * \param dest destination texture object.
4287117f1b4Smrg * \param src source texture object.
4297117f1b4Smrg */
4307117f1b4Smrgvoid
4317117f1b4Smrg_mesa_copy_texture_object( struct gl_texture_object *dest,
4327117f1b4Smrg                           const struct gl_texture_object *src )
4337117f1b4Smrg{
4347117f1b4Smrg   dest->Target = src->Target;
435af69d88dSmrg   dest->TargetIndex = src->TargetIndex;
4367117f1b4Smrg   dest->Name = src->Name;
4377117f1b4Smrg   dest->Priority = src->Priority;
4383464ebd5Sriastradh   dest->Sampler.BorderColor.f[0] = src->Sampler.BorderColor.f[0];
4393464ebd5Sriastradh   dest->Sampler.BorderColor.f[1] = src->Sampler.BorderColor.f[1];
4403464ebd5Sriastradh   dest->Sampler.BorderColor.f[2] = src->Sampler.BorderColor.f[2];
4413464ebd5Sriastradh   dest->Sampler.BorderColor.f[3] = src->Sampler.BorderColor.f[3];
4423464ebd5Sriastradh   dest->Sampler.WrapS = src->Sampler.WrapS;
4433464ebd5Sriastradh   dest->Sampler.WrapT = src->Sampler.WrapT;
4443464ebd5Sriastradh   dest->Sampler.WrapR = src->Sampler.WrapR;
4453464ebd5Sriastradh   dest->Sampler.MinFilter = src->Sampler.MinFilter;
4463464ebd5Sriastradh   dest->Sampler.MagFilter = src->Sampler.MagFilter;
4473464ebd5Sriastradh   dest->Sampler.MinLod = src->Sampler.MinLod;
4483464ebd5Sriastradh   dest->Sampler.MaxLod = src->Sampler.MaxLod;
4493464ebd5Sriastradh   dest->Sampler.LodBias = src->Sampler.LodBias;
4507117f1b4Smrg   dest->BaseLevel = src->BaseLevel;
4517117f1b4Smrg   dest->MaxLevel = src->MaxLevel;
4523464ebd5Sriastradh   dest->Sampler.MaxAnisotropy = src->Sampler.MaxAnisotropy;
4533464ebd5Sriastradh   dest->Sampler.CompareMode = src->Sampler.CompareMode;
4543464ebd5Sriastradh   dest->Sampler.CompareFunc = src->Sampler.CompareFunc;
4553464ebd5Sriastradh   dest->Sampler.CubeMapSeamless = src->Sampler.CubeMapSeamless;
456af69d88dSmrg   dest->DepthMode = src->DepthMode;
457af69d88dSmrg   dest->StencilSampling = src->StencilSampling;
4583464ebd5Sriastradh   dest->Sampler.sRGBDecode = src->Sampler.sRGBDecode;
4597117f1b4Smrg   dest->_MaxLevel = src->_MaxLevel;
4607117f1b4Smrg   dest->_MaxLambda = src->_MaxLambda;
4617117f1b4Smrg   dest->GenerateMipmap = src->GenerateMipmap;
462af69d88dSmrg   dest->_BaseComplete = src->_BaseComplete;
463af69d88dSmrg   dest->_MipmapComplete = src->_MipmapComplete;
4644a49301eSmrg   COPY_4V(dest->Swizzle, src->Swizzle);
4654a49301eSmrg   dest->_Swizzle = src->_Swizzle;
46601e04c3fSmrg   dest->_IsHalfFloat = src->_IsHalfFloat;
46701e04c3fSmrg   dest->_IsFloat = src->_IsFloat;
468af69d88dSmrg
469af69d88dSmrg   dest->RequiredTextureImageUnits = src->RequiredTextureImageUnits;
4704a49301eSmrg}
4714a49301eSmrg
4724a49301eSmrg
4734a49301eSmrg/**
47401e04c3fSmrg * Free all texture images of the given texture objectm, except for
47501e04c3fSmrg * \p retainTexImage.
4764a49301eSmrg *
4774a49301eSmrg * \param ctx GL context.
47801e04c3fSmrg * \param texObj texture object.
47901e04c3fSmrg * \param retainTexImage a texture image that will \em not be freed.
4804a49301eSmrg *
4814a49301eSmrg * \sa _mesa_clear_texture_image().
4824a49301eSmrg */
4834a49301eSmrgvoid
4843464ebd5Sriastradh_mesa_clear_texture_object(struct gl_context *ctx,
48501e04c3fSmrg                           struct gl_texture_object *texObj,
48601e04c3fSmrg                           struct gl_texture_image *retainTexImage)
4874a49301eSmrg{
4884a49301eSmrg   GLuint i, j;
4894a49301eSmrg
4904a49301eSmrg   if (texObj->Target == 0)
4914a49301eSmrg      return;
4924a49301eSmrg
4934a49301eSmrg   for (i = 0; i < MAX_FACES; i++) {
4944a49301eSmrg      for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
4954a49301eSmrg         struct gl_texture_image *texImage = texObj->Image[i][j];
49601e04c3fSmrg         if (texImage && texImage != retainTexImage)
4974a49301eSmrg            _mesa_clear_texture_image(ctx, texImage);
4984a49301eSmrg      }
4994a49301eSmrg   }
5007117f1b4Smrg}
5017117f1b4Smrg
5027117f1b4Smrg
5037117f1b4Smrg/**
5047117f1b4Smrg * Check if the given texture object is valid by examining its Target field.
5057117f1b4Smrg * For debugging only.
5067117f1b4Smrg */
5077117f1b4Smrgstatic GLboolean
5087117f1b4Smrgvalid_texture_object(const struct gl_texture_object *tex)
5097117f1b4Smrg{
5107117f1b4Smrg   switch (tex->Target) {
5117117f1b4Smrg   case 0:
5127117f1b4Smrg   case GL_TEXTURE_1D:
5137117f1b4Smrg   case GL_TEXTURE_2D:
5147117f1b4Smrg   case GL_TEXTURE_3D:
51501e04c3fSmrg   case GL_TEXTURE_CUBE_MAP:
5167117f1b4Smrg   case GL_TEXTURE_RECTANGLE_NV:
517c1f859d4Smrg   case GL_TEXTURE_1D_ARRAY_EXT:
518c1f859d4Smrg   case GL_TEXTURE_2D_ARRAY_EXT:
5193464ebd5Sriastradh   case GL_TEXTURE_BUFFER:
520af69d88dSmrg   case GL_TEXTURE_EXTERNAL_OES:
521af69d88dSmrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
522af69d88dSmrg   case GL_TEXTURE_2D_MULTISAMPLE:
523af69d88dSmrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
5247117f1b4Smrg      return GL_TRUE;
5257117f1b4Smrg   case 0x99:
5267117f1b4Smrg      _mesa_problem(NULL, "invalid reference to a deleted texture object");
5277117f1b4Smrg      return GL_FALSE;
5287117f1b4Smrg   default:
5294a49301eSmrg      _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
5304a49301eSmrg                    tex->Target, tex->Name);
5317117f1b4Smrg      return GL_FALSE;
5327117f1b4Smrg   }
5337117f1b4Smrg}
5347117f1b4Smrg
5357117f1b4Smrg
5367117f1b4Smrg/**
5377117f1b4Smrg * Reference (or unreference) a texture object.
5387117f1b4Smrg * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
5397117f1b4Smrg * If 'tex' is non-null, increment its refcount.
540af69d88dSmrg * This is normally only called from the _mesa_reference_texobj() macro
541af69d88dSmrg * when there's a real pointer change.
5427117f1b4Smrg */
5437117f1b4Smrgvoid
544af69d88dSmrg_mesa_reference_texobj_(struct gl_texture_object **ptr,
545af69d88dSmrg                        struct gl_texture_object *tex)
5467117f1b4Smrg{
5477117f1b4Smrg   assert(ptr);
5487117f1b4Smrg
5497117f1b4Smrg   if (*ptr) {
5507117f1b4Smrg      /* Unreference the old texture */
5517117f1b4Smrg      GLboolean deleteFlag = GL_FALSE;
5527117f1b4Smrg      struct gl_texture_object *oldTex = *ptr;
5537117f1b4Smrg
55401e04c3fSmrg      assert(valid_texture_object(oldTex));
5553464ebd5Sriastradh      (void) valid_texture_object; /* silence warning in release builds */
5567117f1b4Smrg
55701e04c3fSmrg      simple_mtx_lock(&oldTex->Mutex);
55801e04c3fSmrg      assert(oldTex->RefCount > 0);
5597117f1b4Smrg      oldTex->RefCount--;
5607117f1b4Smrg
5617117f1b4Smrg      deleteFlag = (oldTex->RefCount == 0);
56201e04c3fSmrg      simple_mtx_unlock(&oldTex->Mutex);
5637117f1b4Smrg
5647117f1b4Smrg      if (deleteFlag) {
56501e04c3fSmrg         /* Passing in the context drastically changes the driver code for
56601e04c3fSmrg          * framebuffer deletion.
56701e04c3fSmrg          */
5687117f1b4Smrg         GET_CURRENT_CONTEXT(ctx);
5697117f1b4Smrg         if (ctx)
5707117f1b4Smrg            ctx->Driver.DeleteTexture(ctx, oldTex);
5717117f1b4Smrg         else
5727117f1b4Smrg            _mesa_problem(NULL, "Unable to delete texture, no context");
5737117f1b4Smrg      }
5747117f1b4Smrg
5757117f1b4Smrg      *ptr = NULL;
5767117f1b4Smrg   }
5777117f1b4Smrg   assert(!*ptr);
5787117f1b4Smrg
5797117f1b4Smrg   if (tex) {
5807117f1b4Smrg      /* reference new texture */
58101e04c3fSmrg      assert(valid_texture_object(tex));
58201e04c3fSmrg      simple_mtx_lock(&tex->Mutex);
58301e04c3fSmrg      assert(tex->RefCount > 0);
58401e04c3fSmrg
58501e04c3fSmrg      tex->RefCount++;
58601e04c3fSmrg      *ptr = tex;
58701e04c3fSmrg      simple_mtx_unlock(&tex->Mutex);
5887117f1b4Smrg   }
5897117f1b4Smrg}
5907117f1b4Smrg
5917117f1b4Smrg
592af69d88dSmrgenum base_mipmap { BASE, MIPMAP };
593af69d88dSmrg
5947117f1b4Smrg
5957117f1b4Smrg/**
596af69d88dSmrg * Mark a texture object as incomplete.  There are actually three kinds of
597af69d88dSmrg * (in)completeness:
598af69d88dSmrg * 1. "base incomplete": the base level of the texture is invalid so no
599af69d88dSmrg *    texturing is possible.
600af69d88dSmrg * 2. "mipmap incomplete": a non-base level of the texture is invalid so
601af69d88dSmrg *    mipmap filtering isn't possible, but non-mipmap filtering is.
602af69d88dSmrg * 3. "texture incompleteness": some combination of texture state and
603af69d88dSmrg *    sampler state renders the texture incomplete.
604af69d88dSmrg *
6053464ebd5Sriastradh * \param t  texture object
606af69d88dSmrg * \param bm  either BASE or MIPMAP to indicate what's incomplete
6073464ebd5Sriastradh * \param fmt...  string describing why it's incomplete (for debugging).
6087117f1b4Smrg */
6097117f1b4Smrgstatic void
610af69d88dSmrgincomplete(struct gl_texture_object *t, enum base_mipmap bm,
611af69d88dSmrg           const char *fmt, ...)
6127117f1b4Smrg{
613af69d88dSmrg   if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) {
614af69d88dSmrg      va_list args;
615af69d88dSmrg      char s[100];
6163464ebd5Sriastradh
617af69d88dSmrg      va_start(args, fmt);
618af69d88dSmrg      vsnprintf(s, sizeof(s), fmt, args);
619af69d88dSmrg      va_end(args);
620af69d88dSmrg
621af69d88dSmrg      _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s);
622af69d88dSmrg   }
6233464ebd5Sriastradh
624af69d88dSmrg   if (bm == BASE)
625af69d88dSmrg      t->_BaseComplete = GL_FALSE;
626af69d88dSmrg   t->_MipmapComplete = GL_FALSE;
6273464ebd5Sriastradh}
6287117f1b4Smrg
6297117f1b4Smrg
6307117f1b4Smrg/**
6317117f1b4Smrg * Examine a texture object to determine if it is complete.
6327117f1b4Smrg *
6337117f1b4Smrg * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
6347117f1b4Smrg * accordingly.
6357117f1b4Smrg *
6367117f1b4Smrg * \param ctx GL context.
6377117f1b4Smrg * \param t texture object.
6387117f1b4Smrg *
6397117f1b4Smrg * According to the texture target, verifies that each of the mipmaps is
6407117f1b4Smrg * present and has the expected size.
6417117f1b4Smrg */
6427117f1b4Smrgvoid
6433464ebd5Sriastradh_mesa_test_texobj_completeness( const struct gl_context *ctx,
6447117f1b4Smrg                                struct gl_texture_object *t )
6457117f1b4Smrg{
6467117f1b4Smrg   const GLint baseLevel = t->BaseLevel;
647af69d88dSmrg   const struct gl_texture_image *baseImage;
648af69d88dSmrg   GLint maxLevels = 0;
6497117f1b4Smrg
650af69d88dSmrg   /* We'll set these to FALSE if tests fail below */
651af69d88dSmrg   t->_BaseComplete = GL_TRUE;
652af69d88dSmrg   t->_MipmapComplete = GL_TRUE;
653af69d88dSmrg
654af69d88dSmrg   if (t->Target == GL_TEXTURE_BUFFER) {
655af69d88dSmrg      /* Buffer textures are always considered complete.  The obvious case where
656af69d88dSmrg       * they would be incomplete (no BO attached) is actually specced to be
657af69d88dSmrg       * undefined rendering results.
658af69d88dSmrg       */
659af69d88dSmrg      return;
660af69d88dSmrg   }
661c1f859d4Smrg
662c1f859d4Smrg   /* Detect cases where the application set the base level to an invalid
663c1f859d4Smrg    * value.
664c1f859d4Smrg    */
6654a49301eSmrg   if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
666af69d88dSmrg      incomplete(t, BASE, "base level = %d is invalid", baseLevel);
667c1f859d4Smrg      return;
668c1f859d4Smrg   }
6697117f1b4Smrg
670af69d88dSmrg   if (t->MaxLevel < baseLevel) {
671af69d88dSmrg      incomplete(t, MIPMAP, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
672af69d88dSmrg		 t->MaxLevel, baseLevel);
673af69d88dSmrg      return;
674af69d88dSmrg   }
675af69d88dSmrg
676af69d88dSmrg   baseImage = t->Image[0][baseLevel];
677af69d88dSmrg
6787117f1b4Smrg   /* Always need the base level image */
679af69d88dSmrg   if (!baseImage) {
680af69d88dSmrg      incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel);
6817117f1b4Smrg      return;
6827117f1b4Smrg   }
6837117f1b4Smrg
6847117f1b4Smrg   /* Check width/height/depth for zero */
685af69d88dSmrg   if (baseImage->Width == 0 ||
686af69d88dSmrg       baseImage->Height == 0 ||
687af69d88dSmrg       baseImage->Depth == 0) {
688af69d88dSmrg      incomplete(t, BASE, "texture width or height or depth = 0");
6897117f1b4Smrg      return;
6907117f1b4Smrg   }
6917117f1b4Smrg
692af69d88dSmrg   /* Check if the texture values are integer */
693af69d88dSmrg   {
694af69d88dSmrg      GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat);
695af69d88dSmrg      t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT;
6967117f1b4Smrg   }
697af69d88dSmrg
69801e04c3fSmrg   /* Check if the texture type is Float or HalfFloatOES and ensure Min and Mag
69901e04c3fSmrg    * filters are supported in this case.
70001e04c3fSmrg    */
70101e04c3fSmrg   if (_mesa_is_gles(ctx) && !valid_filter_for_float(ctx, t)) {
70201e04c3fSmrg      incomplete(t, BASE, "Filter is not supported with Float types.");
70301e04c3fSmrg      return;
70401e04c3fSmrg   }
70501e04c3fSmrg
706af69d88dSmrg   /* Compute _MaxLevel (the maximum mipmap level we'll sample from given the
707af69d88dSmrg    * mipmap image sizes and GL_TEXTURE_MAX_LEVEL state).
708af69d88dSmrg    */
709af69d88dSmrg   switch (t->Target) {
710af69d88dSmrg   case GL_TEXTURE_1D:
711af69d88dSmrg   case GL_TEXTURE_1D_ARRAY_EXT:
7127117f1b4Smrg      maxLevels = ctx->Const.MaxTextureLevels;
713af69d88dSmrg      break;
714af69d88dSmrg   case GL_TEXTURE_2D:
715af69d88dSmrg   case GL_TEXTURE_2D_ARRAY_EXT:
716af69d88dSmrg      maxLevels = ctx->Const.MaxTextureLevels;
717af69d88dSmrg      break;
718af69d88dSmrg   case GL_TEXTURE_3D:
7197117f1b4Smrg      maxLevels = ctx->Const.Max3DTextureLevels;
720af69d88dSmrg      break;
72101e04c3fSmrg   case GL_TEXTURE_CUBE_MAP:
722af69d88dSmrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
7237117f1b4Smrg      maxLevels = ctx->Const.MaxCubeTextureLevels;
724af69d88dSmrg      break;
725af69d88dSmrg   case GL_TEXTURE_RECTANGLE_NV:
726af69d88dSmrg   case GL_TEXTURE_BUFFER:
727af69d88dSmrg   case GL_TEXTURE_EXTERNAL_OES:
728af69d88dSmrg   case GL_TEXTURE_2D_MULTISAMPLE:
729af69d88dSmrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
7307117f1b4Smrg      maxLevels = 1;  /* no mipmapping */
731af69d88dSmrg      break;
732af69d88dSmrg   default:
7337117f1b4Smrg      _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
7347117f1b4Smrg      return;
7357117f1b4Smrg   }
7367117f1b4Smrg
73701e04c3fSmrg   assert(maxLevels > 0);
7387117f1b4Smrg
739af69d88dSmrg   t->_MaxLevel = MIN3(t->MaxLevel,
740af69d88dSmrg                       /* 'p' in the GL spec */
741af69d88dSmrg                       (int) (baseLevel + baseImage->MaxNumLevels - 1),
742af69d88dSmrg                       /* 'q' in the GL spec */
743af69d88dSmrg                       maxLevels - 1);
744af69d88dSmrg
745af69d88dSmrg   if (t->Immutable) {
746af69d88dSmrg      /* Adjust max level for views: the data store may have more levels than
747af69d88dSmrg       * the view exposes.
748af69d88dSmrg       */
749af69d88dSmrg      t->_MaxLevel = MIN2(t->_MaxLevel, t->NumLevels - 1);
7503464ebd5Sriastradh   }
7513464ebd5Sriastradh
752af69d88dSmrg   /* Compute _MaxLambda = q - p in the spec used during mipmapping */
753af69d88dSmrg   t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);
7547117f1b4Smrg
755af69d88dSmrg   if (t->Immutable) {
756af69d88dSmrg      /* This texture object was created with glTexStorage1/2/3D() so we
757af69d88dSmrg       * know that all the mipmap levels are the right size and all cube
758af69d88dSmrg       * map faces are the same size.
759af69d88dSmrg       * We don't need to do any of the additional checks below.
760af69d88dSmrg       */
761af69d88dSmrg      return;
762af69d88dSmrg   }
7637117f1b4Smrg
76401e04c3fSmrg   if (t->Target == GL_TEXTURE_CUBE_MAP) {
76501e04c3fSmrg      /* Make sure that all six cube map level 0 images are the same size and
76601e04c3fSmrg       * format.
767af69d88dSmrg       * Note:  we know that the image's width==height (we enforce that
768af69d88dSmrg       * at glTexImage time) so we only need to test the width here.
769af69d88dSmrg       */
7707117f1b4Smrg      GLuint face;
771af69d88dSmrg      assert(baseImage->Width2 == baseImage->Height);
7727117f1b4Smrg      for (face = 1; face < 6; face++) {
773af69d88dSmrg         assert(t->Image[face][baseLevel] == NULL ||
774af69d88dSmrg                t->Image[face][baseLevel]->Width2 ==
775af69d88dSmrg                t->Image[face][baseLevel]->Height2);
7763464ebd5Sriastradh         if (t->Image[face][baseLevel] == NULL ||
777af69d88dSmrg             t->Image[face][baseLevel]->Width2 != baseImage->Width2) {
778af69d88dSmrg            incomplete(t, BASE, "Cube face missing or mismatched size");
7793464ebd5Sriastradh            return;
7803464ebd5Sriastradh         }
78101e04c3fSmrg         if (t->Image[face][baseLevel]->InternalFormat !=
78201e04c3fSmrg             baseImage->InternalFormat) {
78301e04c3fSmrg            incomplete(t, BASE, "Cube face format mismatch");
78401e04c3fSmrg            return;
78501e04c3fSmrg         }
78601e04c3fSmrg         if (t->Image[face][baseLevel]->Border != baseImage->Border) {
78701e04c3fSmrg            incomplete(t, BASE, "Cube face border size mismatch");
78801e04c3fSmrg            return;
78901e04c3fSmrg         }
7907117f1b4Smrg      }
7917117f1b4Smrg   }
7927117f1b4Smrg
793af69d88dSmrg   /*
794af69d88dSmrg    * Do mipmap consistency checking.
795af69d88dSmrg    * Note: we don't care about the current texture sampler state here.
796af69d88dSmrg    * To determine texture completeness we'll either look at _BaseComplete
797af69d88dSmrg    * or _MipmapComplete depending on the current minification filter mode.
798af69d88dSmrg    */
799af69d88dSmrg   {
8007117f1b4Smrg      GLint i;
801af69d88dSmrg      const GLint minLevel = baseLevel;
802af69d88dSmrg      const GLint maxLevel = t->_MaxLevel;
803af69d88dSmrg      const GLuint numFaces = _mesa_num_tex_faces(t->Target);
804af69d88dSmrg      GLuint width, height, depth, face;
8057117f1b4Smrg
8067117f1b4Smrg      if (minLevel > maxLevel) {
807af69d88dSmrg         incomplete(t, MIPMAP, "minLevel > maxLevel");
8087117f1b4Smrg         return;
8097117f1b4Smrg      }
8107117f1b4Smrg
811af69d88dSmrg      /* Get the base image's dimensions */
812af69d88dSmrg      width = baseImage->Width2;
813af69d88dSmrg      height = baseImage->Height2;
814af69d88dSmrg      depth = baseImage->Depth2;
8157117f1b4Smrg
816af69d88dSmrg      /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL,
817af69d88dSmrg       * MULTISAMPLE and MULTISAMPLE_ARRAY textures
818af69d88dSmrg       */
819af69d88dSmrg      for (i = baseLevel + 1; i < maxLevels; i++) {
820af69d88dSmrg         /* Compute the expected size of image at level[i] */
821af69d88dSmrg         if (width > 1) {
822af69d88dSmrg            width /= 2;
8237117f1b4Smrg         }
824af69d88dSmrg         if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) {
825af69d88dSmrg            height /= 2;
826af69d88dSmrg         }
82701e04c3fSmrg         if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY
82801e04c3fSmrg             && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) {
829af69d88dSmrg            depth /= 2;
830af69d88dSmrg         }
831af69d88dSmrg
832af69d88dSmrg         /* loop over cube faces (or single face otherwise) */
833af69d88dSmrg         for (face = 0; face < numFaces; face++) {
8347117f1b4Smrg            if (i >= minLevel && i <= maxLevel) {
835af69d88dSmrg               const struct gl_texture_image *img = t->Image[face][i];
836af69d88dSmrg
837af69d88dSmrg               if (!img) {
838af69d88dSmrg                  incomplete(t, MIPMAP, "TexImage[%d] is missing", i);
8397117f1b4Smrg                  return;
8407117f1b4Smrg               }
84101e04c3fSmrg               if (img->InternalFormat != baseImage->InternalFormat) {
842af69d88dSmrg                  incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]");
8437117f1b4Smrg                  return;
8447117f1b4Smrg               }
845af69d88dSmrg               if (img->Border != baseImage->Border) {
846af69d88dSmrg                  incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]");
8477117f1b4Smrg                  return;
8487117f1b4Smrg               }
849af69d88dSmrg               if (img->Width2 != width) {
85001e04c3fSmrg                  incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i,
85101e04c3fSmrg                             img->Width2);
8527117f1b4Smrg                  return;
8537117f1b4Smrg               }
854af69d88dSmrg               if (img->Height2 != height) {
85501e04c3fSmrg                  incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i,
85601e04c3fSmrg                             img->Height2);
8577117f1b4Smrg                  return;
8587117f1b4Smrg               }
859af69d88dSmrg               if (img->Depth2 != depth) {
86001e04c3fSmrg                  incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i,
86101e04c3fSmrg                             img->Depth2);
8627117f1b4Smrg                  return;
8637117f1b4Smrg               }
8647117f1b4Smrg            }
8657117f1b4Smrg         }
86601e04c3fSmrg
867af69d88dSmrg         if (width == 1 && height == 1 && depth == 1) {
868af69d88dSmrg            return;  /* found smallest needed mipmap, all done! */
869af69d88dSmrg         }
8707117f1b4Smrg      }
8717117f1b4Smrg   }
8727117f1b4Smrg}
8737117f1b4Smrg
8744a49301eSmrg
8753464ebd5SriastradhGLboolean
87601e04c3fSmrg_mesa_cube_level_complete(const struct gl_texture_object *texObj,
87701e04c3fSmrg                          const GLint level)
8783464ebd5Sriastradh{
8793464ebd5Sriastradh   const struct gl_texture_image *img0, *img;
8803464ebd5Sriastradh   GLuint face;
8813464ebd5Sriastradh
8823464ebd5Sriastradh   if (texObj->Target != GL_TEXTURE_CUBE_MAP)
8833464ebd5Sriastradh      return GL_FALSE;
8843464ebd5Sriastradh
88501e04c3fSmrg   if ((level < 0) || (level >= MAX_TEXTURE_LEVELS))
8863464ebd5Sriastradh      return GL_FALSE;
8873464ebd5Sriastradh
8883464ebd5Sriastradh   /* check first face */
88901e04c3fSmrg   img0 = texObj->Image[0][level];
8903464ebd5Sriastradh   if (!img0 ||
8913464ebd5Sriastradh       img0->Width < 1 ||
8923464ebd5Sriastradh       img0->Width != img0->Height)
8933464ebd5Sriastradh      return GL_FALSE;
8943464ebd5Sriastradh
8953464ebd5Sriastradh   /* check remaining faces vs. first face */
8963464ebd5Sriastradh   for (face = 1; face < 6; face++) {
89701e04c3fSmrg      img = texObj->Image[face][level];
8983464ebd5Sriastradh      if (!img ||
8993464ebd5Sriastradh          img->Width != img0->Width ||
9003464ebd5Sriastradh          img->Height != img0->Height ||
9013464ebd5Sriastradh          img->TexFormat != img0->TexFormat)
9023464ebd5Sriastradh         return GL_FALSE;
9033464ebd5Sriastradh   }
9043464ebd5Sriastradh
9053464ebd5Sriastradh   return GL_TRUE;
9063464ebd5Sriastradh}
9073464ebd5Sriastradh
90801e04c3fSmrg/**
90901e04c3fSmrg * Check if the given cube map texture is "cube complete" as defined in
91001e04c3fSmrg * the OpenGL specification.
91101e04c3fSmrg */
91201e04c3fSmrgGLboolean
91301e04c3fSmrg_mesa_cube_complete(const struct gl_texture_object *texObj)
91401e04c3fSmrg{
91501e04c3fSmrg   return _mesa_cube_level_complete(texObj, texObj->BaseLevel);
91601e04c3fSmrg}
9173464ebd5Sriastradh
9184a49301eSmrg/**
9194a49301eSmrg * Mark a texture object dirty.  It forces the object to be incomplete
920af69d88dSmrg * and forces the context to re-validate its state.
9214a49301eSmrg *
9224a49301eSmrg * \param ctx GL context.
9234a49301eSmrg * \param texObj texture object.
9244a49301eSmrg */
9254a49301eSmrgvoid
926af69d88dSmrg_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj)
9274a49301eSmrg{
928af69d88dSmrg   texObj->_BaseComplete = GL_FALSE;
929af69d88dSmrg   texObj->_MipmapComplete = GL_FALSE;
93001e04c3fSmrg   ctx->NewState |= _NEW_TEXTURE_OBJECT;
9314a49301eSmrg}
9324a49301eSmrg
9334a49301eSmrg
9344a49301eSmrg/**
935af69d88dSmrg * Return pointer to a default/fallback texture of the given type/target.
936af69d88dSmrg * The texture is an RGBA texture with all texels = (0,0,0,1).
937af69d88dSmrg * That's the value a GLSL sampler should get when sampling from an
9384a49301eSmrg * incomplete texture.
9394a49301eSmrg */
9404a49301eSmrgstruct gl_texture_object *
941af69d88dSmrg_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
9424a49301eSmrg{
943af69d88dSmrg   if (!ctx->Shared->FallbackTex[tex]) {
9444a49301eSmrg      /* create fallback texture now */
94501e04c3fSmrg      const GLsizei width = 1, height = 1;
94601e04c3fSmrg      GLsizei depth = 1;
94701e04c3fSmrg      GLubyte texel[24];
9484a49301eSmrg      struct gl_texture_object *texObj;
9494a49301eSmrg      struct gl_texture_image *texImage;
950af69d88dSmrg      mesa_format texFormat;
951af69d88dSmrg      GLuint dims, face, numFaces = 1;
952af69d88dSmrg      GLenum target;
953af69d88dSmrg
95401e04c3fSmrg      for (face = 0; face < 6; face++) {
95501e04c3fSmrg         texel[4*face + 0] =
95601e04c3fSmrg         texel[4*face + 1] =
95701e04c3fSmrg         texel[4*face + 2] = 0x0;
95801e04c3fSmrg         texel[4*face + 3] = 0xff;
95901e04c3fSmrg      }
960af69d88dSmrg
961af69d88dSmrg      switch (tex) {
962af69d88dSmrg      case TEXTURE_2D_ARRAY_INDEX:
963af69d88dSmrg         dims = 3;
964af69d88dSmrg         target = GL_TEXTURE_2D_ARRAY;
965af69d88dSmrg         break;
966af69d88dSmrg      case TEXTURE_1D_ARRAY_INDEX:
967af69d88dSmrg         dims = 2;
968af69d88dSmrg         target = GL_TEXTURE_1D_ARRAY;
969af69d88dSmrg         break;
970af69d88dSmrg      case TEXTURE_CUBE_INDEX:
971af69d88dSmrg         dims = 2;
972af69d88dSmrg         target = GL_TEXTURE_CUBE_MAP;
973af69d88dSmrg         numFaces = 6;
974af69d88dSmrg         break;
975af69d88dSmrg      case TEXTURE_3D_INDEX:
976af69d88dSmrg         dims = 3;
977af69d88dSmrg         target = GL_TEXTURE_3D;
978af69d88dSmrg         break;
979af69d88dSmrg      case TEXTURE_RECT_INDEX:
980af69d88dSmrg         dims = 2;
981af69d88dSmrg         target = GL_TEXTURE_RECTANGLE;
982af69d88dSmrg         break;
983af69d88dSmrg      case TEXTURE_2D_INDEX:
984af69d88dSmrg         dims = 2;
985af69d88dSmrg         target = GL_TEXTURE_2D;
986af69d88dSmrg         break;
987af69d88dSmrg      case TEXTURE_1D_INDEX:
988af69d88dSmrg         dims = 1;
989af69d88dSmrg         target = GL_TEXTURE_1D;
990af69d88dSmrg         break;
991af69d88dSmrg      case TEXTURE_BUFFER_INDEX:
992af69d88dSmrg         dims = 0;
993af69d88dSmrg         target = GL_TEXTURE_BUFFER;
994af69d88dSmrg         break;
995af69d88dSmrg      case TEXTURE_CUBE_ARRAY_INDEX:
996af69d88dSmrg         dims = 3;
997af69d88dSmrg         target = GL_TEXTURE_CUBE_MAP_ARRAY;
99801e04c3fSmrg         depth = 6;
999af69d88dSmrg         break;
1000af69d88dSmrg      case TEXTURE_EXTERNAL_INDEX:
1001af69d88dSmrg         dims = 2;
1002af69d88dSmrg         target = GL_TEXTURE_EXTERNAL_OES;
1003af69d88dSmrg         break;
1004af69d88dSmrg      case TEXTURE_2D_MULTISAMPLE_INDEX:
1005af69d88dSmrg         dims = 2;
1006af69d88dSmrg         target = GL_TEXTURE_2D_MULTISAMPLE;
1007af69d88dSmrg         break;
1008af69d88dSmrg      case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX:
1009af69d88dSmrg         dims = 3;
1010af69d88dSmrg         target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
1011af69d88dSmrg         break;
1012af69d88dSmrg      default:
1013af69d88dSmrg         /* no-op */
1014af69d88dSmrg         return NULL;
10154a49301eSmrg      }
10164a49301eSmrg
10174a49301eSmrg      /* create texture object */
1018af69d88dSmrg      texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
1019af69d88dSmrg      if (!texObj)
1020af69d88dSmrg         return NULL;
1021af69d88dSmrg
10224a49301eSmrg      assert(texObj->RefCount == 1);
10233464ebd5Sriastradh      texObj->Sampler.MinFilter = GL_NEAREST;
10243464ebd5Sriastradh      texObj->Sampler.MagFilter = GL_NEAREST;
10254a49301eSmrg
1026af69d88dSmrg      texFormat = ctx->Driver.ChooseTextureFormat(ctx, target,
1027af69d88dSmrg                                                  GL_RGBA, GL_RGBA,
10283464ebd5Sriastradh                                                  GL_UNSIGNED_BYTE);
10293464ebd5Sriastradh
1030af69d88dSmrg      /* need a loop here just for cube maps */
1031af69d88dSmrg      for (face = 0; face < numFaces; face++) {
103201e04c3fSmrg         const GLenum faceTarget = _mesa_cube_face_target(target, face);
10334a49301eSmrg
1034af69d88dSmrg         /* initialize level[0] texture image */
1035af69d88dSmrg         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
10364a49301eSmrg
1037af69d88dSmrg         _mesa_init_teximage_fields(ctx, texImage,
1038af69d88dSmrg                                    width,
1039af69d88dSmrg                                    (dims > 1) ? height : 1,
1040af69d88dSmrg                                    (dims > 2) ? depth : 1,
1041af69d88dSmrg                                    0, /* border */
1042af69d88dSmrg                                    GL_RGBA, texFormat);
1043af69d88dSmrg
1044af69d88dSmrg         ctx->Driver.TexImage(ctx, dims, texImage,
1045af69d88dSmrg                              GL_RGBA, GL_UNSIGNED_BYTE, texel,
1046af69d88dSmrg                              &ctx->DefaultPacking);
1047af69d88dSmrg      }
10484a49301eSmrg
10494a49301eSmrg      _mesa_test_texobj_completeness(ctx, texObj);
1050af69d88dSmrg      assert(texObj->_BaseComplete);
1051af69d88dSmrg      assert(texObj->_MipmapComplete);
1052af69d88dSmrg
1053af69d88dSmrg      ctx->Shared->FallbackTex[tex] = texObj;
105401e04c3fSmrg
105501e04c3fSmrg      /* Complete the driver's operation in case another context will also
105601e04c3fSmrg       * use the same fallback texture. */
105701e04c3fSmrg      if (ctx->Driver.Finish)
105801e04c3fSmrg         ctx->Driver.Finish(ctx);
1059af69d88dSmrg   }
1060af69d88dSmrg   return ctx->Shared->FallbackTex[tex];
1061af69d88dSmrg}
1062af69d88dSmrg
1063af69d88dSmrg
1064af69d88dSmrg/**
1065af69d88dSmrg * Compute the size of the given texture object, in bytes.
1066af69d88dSmrg */
1067af69d88dSmrgstatic GLuint
1068af69d88dSmrgtexture_size(const struct gl_texture_object *texObj)
1069af69d88dSmrg{
1070af69d88dSmrg   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1071af69d88dSmrg   GLuint face, level, size = 0;
1072af69d88dSmrg
1073af69d88dSmrg   for (face = 0; face < numFaces; face++) {
1074af69d88dSmrg      for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
1075af69d88dSmrg         const struct gl_texture_image *img = texObj->Image[face][level];
1076af69d88dSmrg         if (img) {
1077af69d88dSmrg            GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
1078af69d88dSmrg                                                img->Height, img->Depth);
1079af69d88dSmrg            size += sz;
1080af69d88dSmrg         }
1081af69d88dSmrg      }
1082af69d88dSmrg   }
1083af69d88dSmrg
1084af69d88dSmrg   return size;
1085af69d88dSmrg}
1086af69d88dSmrg
1087af69d88dSmrg
1088af69d88dSmrg/**
1089af69d88dSmrg * Callback called from _mesa_HashWalk()
1090af69d88dSmrg */
1091af69d88dSmrgstatic void
1092af69d88dSmrgcount_tex_size(GLuint key, void *data, void *userData)
1093af69d88dSmrg{
1094af69d88dSmrg   const struct gl_texture_object *texObj =
1095af69d88dSmrg      (const struct gl_texture_object *) data;
1096af69d88dSmrg   GLuint *total = (GLuint *) userData;
1097af69d88dSmrg
1098af69d88dSmrg   (void) key;
10994a49301eSmrg
1100af69d88dSmrg   *total = *total + texture_size(texObj);
1101af69d88dSmrg}
1102af69d88dSmrg
1103af69d88dSmrg
1104af69d88dSmrg/**
1105af69d88dSmrg * Compute total size (in bytes) of all textures for the given context.
1106af69d88dSmrg * For debugging purposes.
1107af69d88dSmrg */
1108af69d88dSmrgGLuint
1109af69d88dSmrg_mesa_total_texture_memory(struct gl_context *ctx)
1110af69d88dSmrg{
1111af69d88dSmrg   GLuint tgt, total = 0;
1112af69d88dSmrg
1113af69d88dSmrg   _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total);
1114af69d88dSmrg
1115af69d88dSmrg   /* plus, the default texture objects */
1116af69d88dSmrg   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
1117af69d88dSmrg      total += texture_size(ctx->Shared->DefaultTex[tgt]);
11184a49301eSmrg   }
1119af69d88dSmrg
1120af69d88dSmrg   return total;
11214a49301eSmrg}
11224a49301eSmrg
112301e04c3fSmrg
112401e04c3fSmrg/**
112501e04c3fSmrg * Return the base format for the given texture object by looking
112601e04c3fSmrg * at the base texture image.
112701e04c3fSmrg * \return base format (such as GL_RGBA) or GL_NONE if it can't be determined
112801e04c3fSmrg */
112901e04c3fSmrgGLenum
113001e04c3fSmrg_mesa_texture_base_format(const struct gl_texture_object *texObj)
113101e04c3fSmrg{
113201e04c3fSmrg   const struct gl_texture_image *texImage = _mesa_base_tex_image(texObj);
113301e04c3fSmrg
113401e04c3fSmrg   return texImage ? texImage->_BaseFormat : GL_NONE;
113501e04c3fSmrg}
113601e04c3fSmrg
113701e04c3fSmrg
1138af69d88dSmrgstatic struct gl_texture_object *
1139af69d88dSmrginvalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture,
1140af69d88dSmrg                                 GLint level, const char *name)
1141af69d88dSmrg{
1142af69d88dSmrg   /* The GL_ARB_invalidate_subdata spec says:
1143af69d88dSmrg    *
1144af69d88dSmrg    *     "If <texture> is zero or is not the name of a texture, the error
1145af69d88dSmrg    *     INVALID_VALUE is generated."
1146af69d88dSmrg    *
1147af69d88dSmrg    * This performs the error check in a different order than listed in the
1148af69d88dSmrg    * spec.  We have to get the texture object before we can validate the
1149af69d88dSmrg    * other parameters against values in the texture object.
1150af69d88dSmrg    */
1151af69d88dSmrg   struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture);
1152af69d88dSmrg   if (texture == 0 || t == NULL) {
1153af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name);
1154af69d88dSmrg      return NULL;
1155af69d88dSmrg   }
1156af69d88dSmrg
1157af69d88dSmrg   /* The GL_ARB_invalidate_subdata spec says:
1158af69d88dSmrg    *
1159af69d88dSmrg    *     "If <level> is less than zero or greater than the base 2 logarithm
1160af69d88dSmrg    *     of the maximum texture width, height, or depth, the error
1161af69d88dSmrg    *     INVALID_VALUE is generated."
1162af69d88dSmrg    */
1163af69d88dSmrg   if (level < 0 || level > t->MaxLevel) {
1164af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1165af69d88dSmrg      return NULL;
1166af69d88dSmrg   }
1167af69d88dSmrg
1168af69d88dSmrg   /* The GL_ARB_invalidate_subdata spec says:
1169af69d88dSmrg    *
1170af69d88dSmrg    *     "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
1171af69d88dSmrg    *     TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
1172af69d88dSmrg    *     is not zero, the error INVALID_VALUE is generated."
1173af69d88dSmrg    */
1174af69d88dSmrg   if (level != 0) {
1175af69d88dSmrg      switch (t->Target) {
1176af69d88dSmrg      case GL_TEXTURE_RECTANGLE:
1177af69d88dSmrg      case GL_TEXTURE_BUFFER:
1178af69d88dSmrg      case GL_TEXTURE_2D_MULTISAMPLE:
1179af69d88dSmrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1180af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1181af69d88dSmrg         return NULL;
1182af69d88dSmrg
1183af69d88dSmrg      default:
1184af69d88dSmrg         break;
1185af69d88dSmrg      }
1186af69d88dSmrg   }
1187af69d88dSmrg
1188af69d88dSmrg   return t;
1189af69d88dSmrg}
11904a49301eSmrg
11917117f1b4Smrg
11927117f1b4Smrg/**
119301e04c3fSmrg * Helper function for glCreateTextures and glGenTextures. Need this because
119401e04c3fSmrg * glCreateTextures should throw errors if target = 0. This is not exposed to
119501e04c3fSmrg * the rest of Mesa to encourage Mesa internals to use nameless textures,
119601e04c3fSmrg * which do not require expensive hash lookups.
119701e04c3fSmrg * \param target  either 0 or a valid / error-checked texture target enum
119801e04c3fSmrg */
119901e04c3fSmrgstatic void
120001e04c3fSmrgcreate_textures(struct gl_context *ctx, GLenum target,
120101e04c3fSmrg                GLsizei n, GLuint *textures, const char *caller)
12027117f1b4Smrg{
12037117f1b4Smrg   GLuint first;
12047117f1b4Smrg   GLint i;
1205af69d88dSmrg
12067117f1b4Smrg   if (!textures)
12077117f1b4Smrg      return;
12087117f1b4Smrg
12097117f1b4Smrg   /*
12107117f1b4Smrg    * This must be atomic (generation and allocation of texture IDs)
12117117f1b4Smrg    */
121201e04c3fSmrg   _mesa_HashLockMutex(ctx->Shared->TexObjects);
12137117f1b4Smrg
12147117f1b4Smrg   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
12157117f1b4Smrg
12167117f1b4Smrg   /* Allocate new, empty texture objects */
12177117f1b4Smrg   for (i = 0; i < n; i++) {
12187117f1b4Smrg      struct gl_texture_object *texObj;
12197117f1b4Smrg      GLuint name = first + i;
1220af69d88dSmrg      texObj = ctx->Driver.NewTextureObject(ctx, name, target);
12217117f1b4Smrg      if (!texObj) {
122201e04c3fSmrg         _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
122301e04c3fSmrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
12247117f1b4Smrg         return;
12257117f1b4Smrg      }
12267117f1b4Smrg
12277117f1b4Smrg      /* insert into hash table */
122801e04c3fSmrg      _mesa_HashInsertLocked(ctx->Shared->TexObjects, texObj->Name, texObj);
12297117f1b4Smrg
12307117f1b4Smrg      textures[i] = name;
12317117f1b4Smrg   }
12327117f1b4Smrg
123301e04c3fSmrg   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
12347117f1b4Smrg}
12357117f1b4Smrg
12367117f1b4Smrg
123701e04c3fSmrgstatic void
123801e04c3fSmrgcreate_textures_err(struct gl_context *ctx, GLenum target,
123901e04c3fSmrg                    GLsizei n, GLuint *textures, const char *caller)
124001e04c3fSmrg{
124101e04c3fSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
124201e04c3fSmrg      _mesa_debug(ctx, "%s %d\n", caller, n);
124301e04c3fSmrg
124401e04c3fSmrg   if (n < 0) {
124501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
124601e04c3fSmrg      return;
124701e04c3fSmrg   }
124801e04c3fSmrg
124901e04c3fSmrg   create_textures(ctx, target, n, textures, caller);
125001e04c3fSmrg}
125101e04c3fSmrg
125201e04c3fSmrg/*@}*/
125301e04c3fSmrg
125401e04c3fSmrg
125501e04c3fSmrg/***********************************************************************/
125601e04c3fSmrg/** \name API functions */
125701e04c3fSmrg/*@{*/
125801e04c3fSmrg
125901e04c3fSmrg
126001e04c3fSmrg/**
126101e04c3fSmrg * Generate texture names.
126201e04c3fSmrg *
126301e04c3fSmrg * \param n number of texture names to be generated.
126401e04c3fSmrg * \param textures an array in which will hold the generated texture names.
126501e04c3fSmrg *
126601e04c3fSmrg * \sa glGenTextures(), glCreateTextures().
126701e04c3fSmrg *
126801e04c3fSmrg * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
126901e04c3fSmrg * IDs which are stored in \p textures.  Corresponding empty texture
127001e04c3fSmrg * objects are also generated.
127101e04c3fSmrg */
127201e04c3fSmrgvoid GLAPIENTRY
127301e04c3fSmrg_mesa_GenTextures_no_error(GLsizei n, GLuint *textures)
127401e04c3fSmrg{
127501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
127601e04c3fSmrg   create_textures(ctx, 0, n, textures, "glGenTextures");
127701e04c3fSmrg}
127801e04c3fSmrg
127901e04c3fSmrg
128001e04c3fSmrgvoid GLAPIENTRY
128101e04c3fSmrg_mesa_GenTextures(GLsizei n, GLuint *textures)
128201e04c3fSmrg{
128301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
128401e04c3fSmrg   create_textures_err(ctx, 0, n, textures, "glGenTextures");
128501e04c3fSmrg}
128601e04c3fSmrg
128701e04c3fSmrg/**
128801e04c3fSmrg * Create texture objects.
128901e04c3fSmrg *
129001e04c3fSmrg * \param target the texture target for each name to be generated.
129101e04c3fSmrg * \param n number of texture names to be generated.
129201e04c3fSmrg * \param textures an array in which will hold the generated texture names.
129301e04c3fSmrg *
129401e04c3fSmrg * \sa glCreateTextures(), glGenTextures().
129501e04c3fSmrg *
129601e04c3fSmrg * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
129701e04c3fSmrg * IDs which are stored in \p textures.  Corresponding empty texture
129801e04c3fSmrg * objects are also generated.
129901e04c3fSmrg */
130001e04c3fSmrgvoid GLAPIENTRY
130101e04c3fSmrg_mesa_CreateTextures_no_error(GLenum target, GLsizei n, GLuint *textures)
130201e04c3fSmrg{
130301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
130401e04c3fSmrg   create_textures(ctx, target, n, textures, "glCreateTextures");
130501e04c3fSmrg}
130601e04c3fSmrg
130701e04c3fSmrg
130801e04c3fSmrgvoid GLAPIENTRY
130901e04c3fSmrg_mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
131001e04c3fSmrg{
131101e04c3fSmrg   GLint targetIndex;
131201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
131301e04c3fSmrg
131401e04c3fSmrg   /*
131501e04c3fSmrg    * The 4.5 core profile spec (30.10.2014) doesn't specify what
131601e04c3fSmrg    * glCreateTextures should do with invalid targets, which was probably an
131701e04c3fSmrg    * oversight.  This conforms to the spec for glBindTexture.
131801e04c3fSmrg    */
131901e04c3fSmrg   targetIndex = _mesa_tex_target_to_index(ctx, target);
132001e04c3fSmrg   if (targetIndex < 0) {
132101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glCreateTextures(target)");
132201e04c3fSmrg      return;
132301e04c3fSmrg   }
132401e04c3fSmrg
132501e04c3fSmrg   create_textures_err(ctx, target, n, textures, "glCreateTextures");
132601e04c3fSmrg}
132701e04c3fSmrg
13287117f1b4Smrg/**
13297117f1b4Smrg * Check if the given texture object is bound to the current draw or
13307117f1b4Smrg * read framebuffer.  If so, Unbind it.
13317117f1b4Smrg */
13327117f1b4Smrgstatic void
13333464ebd5Sriastradhunbind_texobj_from_fbo(struct gl_context *ctx,
13343464ebd5Sriastradh                       struct gl_texture_object *texObj)
13357117f1b4Smrg{
1336af69d88dSmrg   bool progress = false;
1337af69d88dSmrg
1338af69d88dSmrg   /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection
1339af69d88dSmrg    * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec
1340af69d88dSmrg    * says:
1341af69d88dSmrg    *
1342af69d88dSmrg    *     "If a texture object is deleted while its image is attached to one
1343af69d88dSmrg    *     or more attachment points in the currently bound framebuffer, then
1344af69d88dSmrg    *     it is as if FramebufferTexture* had been called, with a texture of
1345af69d88dSmrg    *     zero, for each attachment point to which this image was attached in
1346af69d88dSmrg    *     the currently bound framebuffer. In other words, this texture image
1347af69d88dSmrg    *     is first detached from all attachment points in the currently bound
1348af69d88dSmrg    *     framebuffer. Note that the texture image is specifically not
1349af69d88dSmrg    *     detached from any other framebuffer objects. Detaching the texture
1350af69d88dSmrg    *     image from any other framebuffer objects is the responsibility of
1351af69d88dSmrg    *     the application."
1352af69d88dSmrg    */
1353af69d88dSmrg   if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1354af69d88dSmrg      progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj);
1355af69d88dSmrg   }
1356af69d88dSmrg   if (_mesa_is_user_fbo(ctx->ReadBuffer)
1357af69d88dSmrg       && ctx->ReadBuffer != ctx->DrawBuffer) {
1358af69d88dSmrg      progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj)
1359af69d88dSmrg         || progress;
13607117f1b4Smrg   }
1361af69d88dSmrg
1362af69d88dSmrg   if (progress)
1363af69d88dSmrg      /* Vertices are already flushed by _mesa_DeleteTextures */
1364af69d88dSmrg      ctx->NewState |= _NEW_BUFFERS;
13657117f1b4Smrg}
13667117f1b4Smrg
13677117f1b4Smrg
13687117f1b4Smrg/**
13697117f1b4Smrg * Check if the given texture object is bound to any texture image units and
13707117f1b4Smrg * unbind it if so (revert to default textures).
13717117f1b4Smrg */
13727117f1b4Smrgstatic void
13733464ebd5Sriastradhunbind_texobj_from_texunits(struct gl_context *ctx,
13743464ebd5Sriastradh                            struct gl_texture_object *texObj)
13757117f1b4Smrg{
1376af69d88dSmrg   const gl_texture_index index = texObj->TargetIndex;
1377af69d88dSmrg   GLuint u;
13787117f1b4Smrg
137901e04c3fSmrg   if (texObj->Target == 0) {
138001e04c3fSmrg      /* texture was never bound */
1381af69d88dSmrg      return;
138201e04c3fSmrg   }
138301e04c3fSmrg
138401e04c3fSmrg   assert(index < NUM_TEXTURE_TARGETS);
1385af69d88dSmrg
1386af69d88dSmrg   for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) {
13877117f1b4Smrg      struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
1388af69d88dSmrg
1389af69d88dSmrg      if (texObj == unit->CurrentTex[index]) {
1390af69d88dSmrg         /* Bind the default texture for this unit/target */
1391af69d88dSmrg         _mesa_reference_texobj(&unit->CurrentTex[index],
1392af69d88dSmrg                                ctx->Shared->DefaultTex[index]);
1393af69d88dSmrg         unit->_BoundTextures &= ~(1 << index);
13947117f1b4Smrg      }
13957117f1b4Smrg   }
13967117f1b4Smrg}
13977117f1b4Smrg
13987117f1b4Smrg
1399af69d88dSmrg/**
1400af69d88dSmrg * Check if the given texture object is bound to any shader image unit
1401af69d88dSmrg * and unbind it if that's the case.
1402af69d88dSmrg */
1403af69d88dSmrgstatic void
1404af69d88dSmrgunbind_texobj_from_image_units(struct gl_context *ctx,
1405af69d88dSmrg                               struct gl_texture_object *texObj)
1406af69d88dSmrg{
1407af69d88dSmrg   GLuint i;
1408af69d88dSmrg
1409af69d88dSmrg   for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
1410af69d88dSmrg      struct gl_image_unit *unit = &ctx->ImageUnits[i];
1411af69d88dSmrg
141201e04c3fSmrg      if (texObj == unit->TexObj) {
1413af69d88dSmrg         _mesa_reference_texobj(&unit->TexObj, NULL);
141401e04c3fSmrg         *unit = _mesa_default_image_unit(ctx);
141501e04c3fSmrg      }
1416af69d88dSmrg   }
1417af69d88dSmrg}
1418af69d88dSmrg
141901e04c3fSmrg
1420af69d88dSmrg/**
1421af69d88dSmrg * Unbinds all textures bound to the given texture image unit.
1422af69d88dSmrg */
1423af69d88dSmrgstatic void
1424af69d88dSmrgunbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
1425af69d88dSmrg{
1426af69d88dSmrg   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1427af69d88dSmrg
1428af69d88dSmrg   while (texUnit->_BoundTextures) {
1429af69d88dSmrg      const GLuint index = ffs(texUnit->_BoundTextures) - 1;
1430af69d88dSmrg      struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
1431af69d88dSmrg
1432af69d88dSmrg      _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
1433af69d88dSmrg
1434af69d88dSmrg      /* Pass BindTexture call to device driver */
1435af69d88dSmrg      if (ctx->Driver.BindTexture)
1436af69d88dSmrg         ctx->Driver.BindTexture(ctx, unit, 0, texObj);
1437af69d88dSmrg
1438af69d88dSmrg      texUnit->_BoundTextures &= ~(1 << index);
143901e04c3fSmrg      ctx->NewState |= _NEW_TEXTURE_OBJECT;
1440af69d88dSmrg   }
1441af69d88dSmrg}
1442af69d88dSmrg
144301e04c3fSmrg
14447117f1b4Smrg/**
14457117f1b4Smrg * Delete named textures.
14467117f1b4Smrg *
14477117f1b4Smrg * \param n number of textures to be deleted.
14487117f1b4Smrg * \param textures array of texture IDs to be deleted.
14497117f1b4Smrg *
14507117f1b4Smrg * \sa glDeleteTextures().
14517117f1b4Smrg *
14527117f1b4Smrg * If we're about to delete a texture that's currently bound to any
14537117f1b4Smrg * texture unit, unbind the texture first.  Decrement the reference
14547117f1b4Smrg * count on the texture object and delete it if it's zero.
14557117f1b4Smrg * Recall that texture objects can be shared among several rendering
14567117f1b4Smrg * contexts.
14577117f1b4Smrg */
145801e04c3fSmrgstatic void
145901e04c3fSmrgdelete_textures(struct gl_context *ctx, GLsizei n, const GLuint *textures)
14607117f1b4Smrg{
1461af69d88dSmrg   FLUSH_VERTICES(ctx, 0); /* too complex */
14627117f1b4Smrg
14637117f1b4Smrg   if (!textures)
14647117f1b4Smrg      return;
14657117f1b4Smrg
146601e04c3fSmrg   for (GLsizei i = 0; i < n; i++) {
14677117f1b4Smrg      if (textures[i] > 0) {
14687117f1b4Smrg         struct gl_texture_object *delObj
14697117f1b4Smrg            = _mesa_lookup_texture(ctx, textures[i]);
14707117f1b4Smrg
14717117f1b4Smrg         if (delObj) {
14723464ebd5Sriastradh            _mesa_lock_texture(ctx, delObj);
14737117f1b4Smrg
14747117f1b4Smrg            /* Check if texture is bound to any framebuffer objects.
14757117f1b4Smrg             * If so, unbind.
14767117f1b4Smrg             * See section 4.4.2.3 of GL_EXT_framebuffer_object.
14777117f1b4Smrg             */
14787117f1b4Smrg            unbind_texobj_from_fbo(ctx, delObj);
14797117f1b4Smrg
14807117f1b4Smrg            /* Check if this texture is currently bound to any texture units.
14817117f1b4Smrg             * If so, unbind it.
14827117f1b4Smrg             */
14837117f1b4Smrg            unbind_texobj_from_texunits(ctx, delObj);
14847117f1b4Smrg
1485af69d88dSmrg            /* Check if this texture is currently bound to any shader
1486af69d88dSmrg             * image unit.  If so, unbind it.
1487af69d88dSmrg             * See section 3.9.X of GL_ARB_shader_image_load_store.
1488af69d88dSmrg             */
1489af69d88dSmrg            unbind_texobj_from_image_units(ctx, delObj);
1490af69d88dSmrg
149101e04c3fSmrg            /* Make all handles that reference this texture object non-resident
149201e04c3fSmrg             * in the current context.
149301e04c3fSmrg             */
149401e04c3fSmrg            _mesa_make_texture_handles_non_resident(ctx, delObj);
149501e04c3fSmrg
14963464ebd5Sriastradh            _mesa_unlock_texture(ctx, delObj);
14977117f1b4Smrg
149801e04c3fSmrg            ctx->NewState |= _NEW_TEXTURE_OBJECT;
14997117f1b4Smrg
15007117f1b4Smrg            /* The texture _name_ is now free for re-use.
15017117f1b4Smrg             * Remove it from the hash table now.
15027117f1b4Smrg             */
15037117f1b4Smrg            _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
15047117f1b4Smrg
15057117f1b4Smrg            /* Unreference the texobj.  If refcount hits zero, the texture
15067117f1b4Smrg             * will be deleted.
15077117f1b4Smrg             */
15087117f1b4Smrg            _mesa_reference_texobj(&delObj, NULL);
15097117f1b4Smrg         }
15107117f1b4Smrg      }
15117117f1b4Smrg   }
15127117f1b4Smrg}
15137117f1b4Smrg
151401e04c3fSmrg/**
151501e04c3fSmrg * This deletes a texObj without altering the hash table.
151601e04c3fSmrg */
151701e04c3fSmrgvoid
151801e04c3fSmrg_mesa_delete_nameless_texture(struct gl_context *ctx,
151901e04c3fSmrg                              struct gl_texture_object *texObj)
152001e04c3fSmrg{
152101e04c3fSmrg   if (!texObj)
152201e04c3fSmrg      return;
152301e04c3fSmrg
152401e04c3fSmrg   FLUSH_VERTICES(ctx, 0);
152501e04c3fSmrg
152601e04c3fSmrg   _mesa_lock_texture(ctx, texObj);
152701e04c3fSmrg   {
152801e04c3fSmrg      /* Check if texture is bound to any framebuffer objects.
152901e04c3fSmrg       * If so, unbind.
153001e04c3fSmrg       * See section 4.4.2.3 of GL_EXT_framebuffer_object.
153101e04c3fSmrg       */
153201e04c3fSmrg      unbind_texobj_from_fbo(ctx, texObj);
153301e04c3fSmrg
153401e04c3fSmrg      /* Check if this texture is currently bound to any texture units.
153501e04c3fSmrg       * If so, unbind it.
153601e04c3fSmrg       */
153701e04c3fSmrg      unbind_texobj_from_texunits(ctx, texObj);
153801e04c3fSmrg
153901e04c3fSmrg      /* Check if this texture is currently bound to any shader
154001e04c3fSmrg       * image unit.  If so, unbind it.
154101e04c3fSmrg       * See section 3.9.X of GL_ARB_shader_image_load_store.
154201e04c3fSmrg       */
154301e04c3fSmrg      unbind_texobj_from_image_units(ctx, texObj);
154401e04c3fSmrg   }
154501e04c3fSmrg   _mesa_unlock_texture(ctx, texObj);
154601e04c3fSmrg
154701e04c3fSmrg   ctx->NewState |= _NEW_TEXTURE_OBJECT;
154801e04c3fSmrg
154901e04c3fSmrg   /* Unreference the texobj.  If refcount hits zero, the texture
155001e04c3fSmrg    * will be deleted.
155101e04c3fSmrg    */
155201e04c3fSmrg   _mesa_reference_texobj(&texObj, NULL);
155301e04c3fSmrg}
155401e04c3fSmrg
155501e04c3fSmrg
155601e04c3fSmrgvoid GLAPIENTRY
155701e04c3fSmrg_mesa_DeleteTextures_no_error(GLsizei n, const GLuint *textures)
155801e04c3fSmrg{
155901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
156001e04c3fSmrg   delete_textures(ctx, n, textures);
156101e04c3fSmrg}
156201e04c3fSmrg
156301e04c3fSmrg
156401e04c3fSmrgvoid GLAPIENTRY
156501e04c3fSmrg_mesa_DeleteTextures(GLsizei n, const GLuint *textures)
156601e04c3fSmrg{
156701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
156801e04c3fSmrg
156901e04c3fSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
157001e04c3fSmrg      _mesa_debug(ctx, "glDeleteTextures %d\n", n);
157101e04c3fSmrg
157201e04c3fSmrg   if (n < 0) {
157301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTextures(n < 0)");
157401e04c3fSmrg      return;
157501e04c3fSmrg   }
157601e04c3fSmrg
157701e04c3fSmrg   delete_textures(ctx, n, textures);
157801e04c3fSmrg}
157901e04c3fSmrg
15807117f1b4Smrg
1581c1f859d4Smrg/**
1582c1f859d4Smrg * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
1583c1f859d4Smrg * into the corresponding Mesa texture target index.
1584cdc920a0Smrg * Note that proxy targets are not valid here.
1585cdc920a0Smrg * \return TEXTURE_x_INDEX or -1 if target is invalid
1586c1f859d4Smrg */
1587af69d88dSmrgint
1588af69d88dSmrg_mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target)
1589c1f859d4Smrg{
1590c1f859d4Smrg   switch (target) {
1591c1f859d4Smrg   case GL_TEXTURE_1D:
1592af69d88dSmrg      return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1;
1593c1f859d4Smrg   case GL_TEXTURE_2D:
1594c1f859d4Smrg      return TEXTURE_2D_INDEX;
1595c1f859d4Smrg   case GL_TEXTURE_3D:
1596af69d88dSmrg      return ctx->API != API_OPENGLES ? TEXTURE_3D_INDEX : -1;
1597af69d88dSmrg   case GL_TEXTURE_CUBE_MAP:
1598af69d88dSmrg      return ctx->Extensions.ARB_texture_cube_map
1599af69d88dSmrg         ? TEXTURE_CUBE_INDEX : -1;
1600af69d88dSmrg   case GL_TEXTURE_RECTANGLE:
1601af69d88dSmrg      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle
1602af69d88dSmrg         ? TEXTURE_RECT_INDEX : -1;
1603af69d88dSmrg   case GL_TEXTURE_1D_ARRAY:
1604af69d88dSmrg      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array
1605af69d88dSmrg         ? TEXTURE_1D_ARRAY_INDEX : -1;
1606af69d88dSmrg   case GL_TEXTURE_2D_ARRAY:
1607af69d88dSmrg      return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1608af69d88dSmrg         || _mesa_is_gles3(ctx)
1609af69d88dSmrg         ? TEXTURE_2D_ARRAY_INDEX : -1;
1610af69d88dSmrg   case GL_TEXTURE_BUFFER:
161101e04c3fSmrg      return (_mesa_has_ARB_texture_buffer_object(ctx) ||
161201e04c3fSmrg              _mesa_has_OES_texture_buffer(ctx)) ?
1613af69d88dSmrg             TEXTURE_BUFFER_INDEX : -1;
1614af69d88dSmrg   case GL_TEXTURE_EXTERNAL_OES:
1615af69d88dSmrg      return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
1616af69d88dSmrg         ? TEXTURE_EXTERNAL_INDEX : -1;
1617af69d88dSmrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
161801e04c3fSmrg      return _mesa_has_texture_cube_map_array(ctx)
1619af69d88dSmrg         ? TEXTURE_CUBE_ARRAY_INDEX : -1;
1620af69d88dSmrg   case GL_TEXTURE_2D_MULTISAMPLE:
162101e04c3fSmrg      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) ||
162201e04c3fSmrg              _mesa_is_gles31(ctx)) ? TEXTURE_2D_MULTISAMPLE_INDEX: -1;
1623af69d88dSmrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
162401e04c3fSmrg      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) ||
162501e04c3fSmrg              _mesa_is_gles31(ctx))
1626af69d88dSmrg         ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1;
1627c1f859d4Smrg   default:
1628c1f859d4Smrg      return -1;
1629c1f859d4Smrg   }
1630c1f859d4Smrg}
1631c1f859d4Smrg
1632c1f859d4Smrg
16337117f1b4Smrg/**
163401e04c3fSmrg * Do actual texture binding.  All error checking should have been done prior
163501e04c3fSmrg * to calling this function.  Note that the texture target (1D, 2D, etc) is
163601e04c3fSmrg * always specified by the texObj->TargetIndex.
163701e04c3fSmrg *
163801e04c3fSmrg * \param unit  index of texture unit to update
163901e04c3fSmrg * \param texObj  the new texture object (cannot be NULL)
164001e04c3fSmrg */
164101e04c3fSmrgstatic void
164201e04c3fSmrgbind_texture_object(struct gl_context *ctx, unsigned unit,
164301e04c3fSmrg                    struct gl_texture_object *texObj)
164401e04c3fSmrg{
164501e04c3fSmrg   struct gl_texture_unit *texUnit;
164601e04c3fSmrg   int targetIndex;
164701e04c3fSmrg
164801e04c3fSmrg   assert(unit < ARRAY_SIZE(ctx->Texture.Unit));
164901e04c3fSmrg   texUnit = &ctx->Texture.Unit[unit];
165001e04c3fSmrg
165101e04c3fSmrg   assert(texObj);
165201e04c3fSmrg   assert(valid_texture_object(texObj));
165301e04c3fSmrg
165401e04c3fSmrg   targetIndex = texObj->TargetIndex;
165501e04c3fSmrg   assert(targetIndex >= 0);
165601e04c3fSmrg   assert(targetIndex < NUM_TEXTURE_TARGETS);
165701e04c3fSmrg
165801e04c3fSmrg   /* Check if this texture is only used by this context and is already bound.
165901e04c3fSmrg    * If so, just return. For GL_OES_image_external, rebinding the texture
166001e04c3fSmrg    * always must invalidate cached resources.
166101e04c3fSmrg    */
166201e04c3fSmrg   if (targetIndex != TEXTURE_EXTERNAL_INDEX) {
166301e04c3fSmrg      bool early_out;
166401e04c3fSmrg      simple_mtx_lock(&ctx->Shared->Mutex);
166501e04c3fSmrg      early_out = ((ctx->Shared->RefCount == 1)
166601e04c3fSmrg                   && (texObj == texUnit->CurrentTex[targetIndex]));
166701e04c3fSmrg      simple_mtx_unlock(&ctx->Shared->Mutex);
166801e04c3fSmrg      if (early_out) {
166901e04c3fSmrg         return;
167001e04c3fSmrg      }
167101e04c3fSmrg   }
167201e04c3fSmrg
167301e04c3fSmrg   /* flush before changing binding */
167401e04c3fSmrg   FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
167501e04c3fSmrg
167601e04c3fSmrg   /* If the refcount on the previously bound texture is decremented to
167701e04c3fSmrg    * zero, it'll be deleted here.
167801e04c3fSmrg    */
167901e04c3fSmrg   _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], texObj);
168001e04c3fSmrg
168101e04c3fSmrg   ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
168201e04c3fSmrg                                         unit + 1);
168301e04c3fSmrg
168401e04c3fSmrg   if (texObj->Name != 0)
168501e04c3fSmrg      texUnit->_BoundTextures |= (1 << targetIndex);
168601e04c3fSmrg   else
168701e04c3fSmrg      texUnit->_BoundTextures &= ~(1 << targetIndex);
168801e04c3fSmrg
168901e04c3fSmrg   /* Pass BindTexture call to device driver */
169001e04c3fSmrg   if (ctx->Driver.BindTexture) {
169101e04c3fSmrg      ctx->Driver.BindTexture(ctx, unit, texObj->Target, texObj);
169201e04c3fSmrg   }
169301e04c3fSmrg}
169401e04c3fSmrg
169501e04c3fSmrg/**
169601e04c3fSmrg * Light-weight bind texture for internal users
169701e04c3fSmrg *
169801e04c3fSmrg * This is really just \c finish_texture_init plus \c bind_texture_object.
169901e04c3fSmrg * This is intended to be used by internal Mesa functions that use
170001e04c3fSmrg * \c _mesa_CreateTexture and need to bind textures (e.g., meta).
170101e04c3fSmrg */
170201e04c3fSmrgvoid
170301e04c3fSmrg_mesa_bind_texture(struct gl_context *ctx, GLenum target,
170401e04c3fSmrg                   struct gl_texture_object *tex_obj)
170501e04c3fSmrg{
170601e04c3fSmrg   const GLint targetIndex = _mesa_tex_target_to_index(ctx, target);
170701e04c3fSmrg
170801e04c3fSmrg   assert(targetIndex >= 0 && targetIndex < NUM_TEXTURE_TARGETS);
170901e04c3fSmrg
171001e04c3fSmrg   if (tex_obj->Target == 0)
171101e04c3fSmrg      finish_texture_init(ctx, target, tex_obj, targetIndex);
171201e04c3fSmrg
171301e04c3fSmrg   assert(tex_obj->Target == target);
171401e04c3fSmrg   assert(tex_obj->TargetIndex == targetIndex);
171501e04c3fSmrg
171601e04c3fSmrg   bind_texture_object(ctx, ctx->Texture.CurrentUnit, tex_obj);
171701e04c3fSmrg}
171801e04c3fSmrg
171901e04c3fSmrg/**
172001e04c3fSmrg * Implement glBindTexture().  Do error checking, look-up or create a new
172101e04c3fSmrg * texture object, then bind it in the current texture unit.
172201e04c3fSmrg *
17237117f1b4Smrg * \param target texture target.
17247117f1b4Smrg * \param texName texture name.
17257117f1b4Smrg */
172601e04c3fSmrgstatic ALWAYS_INLINE void
172701e04c3fSmrgbind_texture(struct gl_context *ctx, GLenum target, GLuint texName,
172801e04c3fSmrg             bool no_error)
17297117f1b4Smrg{
17303464ebd5Sriastradh   struct gl_texture_object *newTexObj = NULL;
173101e04c3fSmrg   int targetIndex;
17327117f1b4Smrg
1733af69d88dSmrg   targetIndex = _mesa_tex_target_to_index(ctx, target);
173401e04c3fSmrg   if (!no_error && targetIndex < 0) {
173501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target = %s)",
173601e04c3fSmrg                  _mesa_enum_to_string(target));
1737c1f859d4Smrg      return;
1738c1f859d4Smrg   }
1739c1f859d4Smrg   assert(targetIndex < NUM_TEXTURE_TARGETS);
1740c1f859d4Smrg
17417117f1b4Smrg   /*
17427117f1b4Smrg    * Get pointer to new texture object (newTexObj)
17437117f1b4Smrg    */
17447117f1b4Smrg   if (texName == 0) {
17453464ebd5Sriastradh      /* Use a default texture object */
17463464ebd5Sriastradh      newTexObj = ctx->Shared->DefaultTex[targetIndex];
174701e04c3fSmrg   } else {
17487117f1b4Smrg      /* non-default texture object */
17497117f1b4Smrg      newTexObj = _mesa_lookup_texture(ctx, texName);
17507117f1b4Smrg      if (newTexObj) {
17517117f1b4Smrg         /* error checking */
175201e04c3fSmrg         if (!no_error &&
175301e04c3fSmrg             newTexObj->Target != 0 && newTexObj->Target != target) {
175401e04c3fSmrg            /* The named texture object's target doesn't match the
175501e04c3fSmrg             * given target
175601e04c3fSmrg             */
17577117f1b4Smrg            _mesa_error( ctx, GL_INVALID_OPERATION,
1758c1f859d4Smrg                         "glBindTexture(target mismatch)" );
17597117f1b4Smrg            return;
17607117f1b4Smrg         }
1761c1f859d4Smrg         if (newTexObj->Target == 0) {
176201e04c3fSmrg            finish_texture_init(ctx, target, newTexObj, targetIndex);
17637117f1b4Smrg         }
17647117f1b4Smrg      }
17657117f1b4Smrg      else {
176601e04c3fSmrg         if (!no_error && ctx->API == API_OPENGL_CORE) {
176701e04c3fSmrg            _mesa_error(ctx, GL_INVALID_OPERATION,
176801e04c3fSmrg                        "glBindTexture(non-gen name)");
1769af69d88dSmrg            return;
1770af69d88dSmrg         }
1771af69d88dSmrg
17727117f1b4Smrg         /* if this is a new texture id, allocate a texture object now */
1773af69d88dSmrg         newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
17747117f1b4Smrg         if (!newTexObj) {
17757117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
17767117f1b4Smrg            return;
17777117f1b4Smrg         }
17787117f1b4Smrg
17797117f1b4Smrg         /* and insert it into hash table */
17807117f1b4Smrg         _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
17817117f1b4Smrg      }
17827117f1b4Smrg   }
17837117f1b4Smrg
178401e04c3fSmrg   assert(newTexObj->Target == target);
178501e04c3fSmrg   assert(newTexObj->TargetIndex == targetIndex);
17867117f1b4Smrg
178701e04c3fSmrg   bind_texture_object(ctx, ctx->Texture.CurrentUnit, newTexObj);
178801e04c3fSmrg}
178901e04c3fSmrg
179001e04c3fSmrgvoid GLAPIENTRY
179101e04c3fSmrg_mesa_BindTexture_no_error(GLenum target, GLuint texName)
179201e04c3fSmrg{
179301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
179401e04c3fSmrg   bind_texture(ctx, target, texName, true);
179501e04c3fSmrg}
179601e04c3fSmrg
179701e04c3fSmrg
179801e04c3fSmrgvoid GLAPIENTRY
179901e04c3fSmrg_mesa_BindTexture(GLenum target, GLuint texName)
180001e04c3fSmrg{
180101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
180201e04c3fSmrg
180301e04c3fSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
180401e04c3fSmrg      _mesa_debug(ctx, "glBindTexture %s %d\n",
180501e04c3fSmrg                  _mesa_enum_to_string(target), (GLint) texName);
180601e04c3fSmrg
180701e04c3fSmrg   bind_texture(ctx, target, texName, false);
180801e04c3fSmrg}
180901e04c3fSmrg
181001e04c3fSmrg
181101e04c3fSmrg/**
181201e04c3fSmrg * OpenGL 4.5 / GL_ARB_direct_state_access glBindTextureUnit().
181301e04c3fSmrg *
181401e04c3fSmrg * \param unit texture unit.
181501e04c3fSmrg * \param texture texture name.
181601e04c3fSmrg *
181701e04c3fSmrg * \sa glBindTexture().
181801e04c3fSmrg *
181901e04c3fSmrg * If the named texture is 0, this will reset each target for the specified
182001e04c3fSmrg * texture unit to its default texture.
182101e04c3fSmrg * If the named texture is not 0 or a recognized texture name, this throws
182201e04c3fSmrg * GL_INVALID_OPERATION.
182301e04c3fSmrg */
182401e04c3fSmrgstatic ALWAYS_INLINE void
182501e04c3fSmrgbind_texture_unit(struct gl_context *ctx, GLuint unit, GLuint texture,
182601e04c3fSmrg                  bool no_error)
182701e04c3fSmrg{
182801e04c3fSmrg   struct gl_texture_object *texObj;
182901e04c3fSmrg
183001e04c3fSmrg   /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
183101e04c3fSmrg    * (20141030) says:
183201e04c3fSmrg    *    "When texture is zero, each of the targets enumerated at the
183301e04c3fSmrg    *    beginning of this section is reset to its default texture for the
183401e04c3fSmrg    *    corresponding texture image unit."
18353464ebd5Sriastradh    */
183601e04c3fSmrg   if (texture == 0) {
183701e04c3fSmrg      unbind_textures_from_unit(ctx, unit);
183801e04c3fSmrg      return;
183901e04c3fSmrg   }
184001e04c3fSmrg
184101e04c3fSmrg   /* Get the non-default texture object */
184201e04c3fSmrg   texObj = _mesa_lookup_texture(ctx, texture);
184301e04c3fSmrg   if (!no_error) {
184401e04c3fSmrg      /* Error checking */
184501e04c3fSmrg      if (!texObj) {
184601e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
184701e04c3fSmrg                     "glBindTextureUnit(non-gen name)");
184801e04c3fSmrg         return;
184901e04c3fSmrg      }
185001e04c3fSmrg
185101e04c3fSmrg      if (texObj->Target == 0) {
185201e04c3fSmrg         /* Texture object was gen'd but never bound so the target is not set */
185301e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTextureUnit(target)");
18543464ebd5Sriastradh         return;
18553464ebd5Sriastradh      }
18564a49301eSmrg   }
18574a49301eSmrg
185801e04c3fSmrg   assert(valid_texture_object(texObj));
18597117f1b4Smrg
186001e04c3fSmrg   bind_texture_object(ctx, unit, texObj);
186101e04c3fSmrg}
18627117f1b4Smrg
1863af69d88dSmrg
186401e04c3fSmrgvoid GLAPIENTRY
186501e04c3fSmrg_mesa_BindTextureUnit_no_error(GLuint unit, GLuint texture)
186601e04c3fSmrg{
186701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
186801e04c3fSmrg   bind_texture_unit(ctx, unit, texture, true);
1869af69d88dSmrg}
1870af69d88dSmrg
1871af69d88dSmrg
1872af69d88dSmrgvoid GLAPIENTRY
187301e04c3fSmrg_mesa_BindTextureUnit(GLuint unit, GLuint texture)
1874af69d88dSmrg{
1875af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1876af69d88dSmrg
187701e04c3fSmrg   if (unit >= _mesa_max_tex_unit(ctx)) {
187801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindTextureUnit(unit=%u)", unit);
1879af69d88dSmrg      return;
1880af69d88dSmrg   }
1881af69d88dSmrg
188201e04c3fSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
188301e04c3fSmrg      _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
188401e04c3fSmrg                  _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture);
188501e04c3fSmrg
188601e04c3fSmrg   bind_texture_unit(ctx, unit, texture, false);
188701e04c3fSmrg}
1888af69d88dSmrg
188901e04c3fSmrg
189001e04c3fSmrg/**
189101e04c3fSmrg * OpenGL 4.4 / GL_ARB_multi_bind glBindTextures().
189201e04c3fSmrg */
189301e04c3fSmrgstatic ALWAYS_INLINE void
189401e04c3fSmrgbind_textures(struct gl_context *ctx, GLuint first, GLsizei count,
189501e04c3fSmrg              const GLuint *textures, bool no_error)
189601e04c3fSmrg{
189701e04c3fSmrg   GLsizei i;
1898af69d88dSmrg
1899af69d88dSmrg   if (textures) {
1900af69d88dSmrg      /* Note that the error semantics for multi-bind commands differ from
1901af69d88dSmrg       * those of other GL commands.
1902af69d88dSmrg       *
1903af69d88dSmrg       * The issues section in the ARB_multi_bind spec says:
1904af69d88dSmrg       *
1905af69d88dSmrg       *    "(11) Typically, OpenGL specifies that if an error is generated by
1906af69d88dSmrg       *          a command, that command has no effect.  This is somewhat
1907af69d88dSmrg       *          unfortunate for multi-bind commands, because it would require
1908af69d88dSmrg       *          a first pass to scan the entire list of bound objects for
1909af69d88dSmrg       *          errors and then a second pass to actually perform the
1910af69d88dSmrg       *          bindings.  Should we have different error semantics?
1911af69d88dSmrg       *
1912af69d88dSmrg       *       RESOLVED:  Yes.  In this specification, when the parameters for
1913af69d88dSmrg       *       one of the <count> binding points are invalid, that binding
1914af69d88dSmrg       *       point is not updated and an error will be generated.  However,
1915af69d88dSmrg       *       other binding points in the same command will be updated if
1916af69d88dSmrg       *       their parameters are valid and no other error occurs."
1917af69d88dSmrg       */
1918af69d88dSmrg
191901e04c3fSmrg      _mesa_HashLockMutex(ctx->Shared->TexObjects);
1920af69d88dSmrg
1921af69d88dSmrg      for (i = 0; i < count; i++) {
1922af69d88dSmrg         if (textures[i] != 0) {
1923af69d88dSmrg            struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
1924af69d88dSmrg            struct gl_texture_object *current = texUnit->_Current;
1925af69d88dSmrg            struct gl_texture_object *texObj;
1926af69d88dSmrg
1927af69d88dSmrg            if (current && current->Name == textures[i])
1928af69d88dSmrg               texObj = current;
1929af69d88dSmrg            else
1930af69d88dSmrg               texObj = _mesa_lookup_texture_locked(ctx, textures[i]);
1931af69d88dSmrg
1932af69d88dSmrg            if (texObj && texObj->Target != 0) {
193301e04c3fSmrg               bind_texture_object(ctx, first + i, texObj);
193401e04c3fSmrg            } else if (!no_error) {
1935af69d88dSmrg               /* The ARB_multi_bind spec says:
1936af69d88dSmrg                *
1937af69d88dSmrg                *     "An INVALID_OPERATION error is generated if any value
1938af69d88dSmrg                *      in <textures> is not zero or the name of an existing
1939af69d88dSmrg                *      texture object (per binding)."
1940af69d88dSmrg                */
1941af69d88dSmrg               _mesa_error(ctx, GL_INVALID_OPERATION,
1942af69d88dSmrg                           "glBindTextures(textures[%d]=%u is not zero "
1943af69d88dSmrg                           "or the name of an existing texture object)",
1944af69d88dSmrg                           i, textures[i]);
1945af69d88dSmrg            }
1946af69d88dSmrg         } else {
1947af69d88dSmrg            unbind_textures_from_unit(ctx, first + i);
1948af69d88dSmrg         }
1949af69d88dSmrg      }
1950af69d88dSmrg
195101e04c3fSmrg      _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1952af69d88dSmrg   } else {
1953af69d88dSmrg      /* Unbind all textures in the range <first> through <first>+<count>-1 */
1954af69d88dSmrg      for (i = 0; i < count; i++)
1955af69d88dSmrg         unbind_textures_from_unit(ctx, first + i);
1956af69d88dSmrg   }
19577117f1b4Smrg}
19587117f1b4Smrg
19597117f1b4Smrg
196001e04c3fSmrgvoid GLAPIENTRY
196101e04c3fSmrg_mesa_BindTextures_no_error(GLuint first, GLsizei count, const GLuint *textures)
196201e04c3fSmrg{
196301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
196401e04c3fSmrg   bind_textures(ctx, first, count, textures, true);
196501e04c3fSmrg}
196601e04c3fSmrg
196701e04c3fSmrg
196801e04c3fSmrgvoid GLAPIENTRY
196901e04c3fSmrg_mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
197001e04c3fSmrg{
197101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
197201e04c3fSmrg
197301e04c3fSmrg   /* The ARB_multi_bind spec says:
197401e04c3fSmrg    *
197501e04c3fSmrg    *     "An INVALID_OPERATION error is generated if <first> + <count>
197601e04c3fSmrg    *      is greater than the number of texture image units supported
197701e04c3fSmrg    *      by the implementation."
197801e04c3fSmrg    */
197901e04c3fSmrg   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
198001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
198101e04c3fSmrg                  "glBindTextures(first=%u + count=%d > the value of "
198201e04c3fSmrg                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
198301e04c3fSmrg                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
198401e04c3fSmrg      return;
198501e04c3fSmrg   }
198601e04c3fSmrg
198701e04c3fSmrg   bind_textures(ctx, first, count, textures, false);
198801e04c3fSmrg}
198901e04c3fSmrg
199001e04c3fSmrg
19917117f1b4Smrg/**
19927117f1b4Smrg * Set texture priorities.
199301e04c3fSmrg *
19947117f1b4Smrg * \param n number of textures.
19957117f1b4Smrg * \param texName texture names.
19967117f1b4Smrg * \param priorities corresponding texture priorities.
199701e04c3fSmrg *
19987117f1b4Smrg * \sa glPrioritizeTextures().
199901e04c3fSmrg *
20007117f1b4Smrg * Looks up each texture in the hash, clamps the corresponding priority between
20017117f1b4Smrg * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
20027117f1b4Smrg */
20037117f1b4Smrgvoid GLAPIENTRY
20047117f1b4Smrg_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
20057117f1b4Smrg                          const GLclampf *priorities )
20067117f1b4Smrg{
20077117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
20087117f1b4Smrg   GLint i;
2009af69d88dSmrg
2010af69d88dSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2011af69d88dSmrg      _mesa_debug(ctx, "glPrioritizeTextures %d\n", n);
2012af69d88dSmrg
2013af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
20147117f1b4Smrg
20157117f1b4Smrg   if (n < 0) {
20167117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
20177117f1b4Smrg      return;
20187117f1b4Smrg   }
20197117f1b4Smrg
20207117f1b4Smrg   if (!priorities)
20217117f1b4Smrg      return;
20227117f1b4Smrg
20237117f1b4Smrg   for (i = 0; i < n; i++) {
20247117f1b4Smrg      if (texName[i] > 0) {
20257117f1b4Smrg         struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
20267117f1b4Smrg         if (t) {
20277117f1b4Smrg            t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
20287117f1b4Smrg         }
20297117f1b4Smrg      }
20307117f1b4Smrg   }
20317117f1b4Smrg
203201e04c3fSmrg   ctx->NewState |= _NEW_TEXTURE_OBJECT;
20337117f1b4Smrg}
20347117f1b4Smrg
20353464ebd5Sriastradh
20363464ebd5Sriastradh
20377117f1b4Smrg/**
20387117f1b4Smrg * See if textures are loaded in texture memory.
203901e04c3fSmrg *
20407117f1b4Smrg * \param n number of textures to query.
20417117f1b4Smrg * \param texName array with the texture names.
20427117f1b4Smrg * \param residences array which will hold the residence status.
20437117f1b4Smrg *
204401e04c3fSmrg * \return GL_TRUE if all textures are resident and
204501e04c3fSmrg *                 residences is left unchanged,
204601e04c3fSmrg *
2047af69d88dSmrg * Note: we assume all textures are always resident
20487117f1b4Smrg */
20497117f1b4SmrgGLboolean GLAPIENTRY
20507117f1b4Smrg_mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
20517117f1b4Smrg                          GLboolean *residences)
20527117f1b4Smrg{
20537117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
20547117f1b4Smrg   GLboolean allResident = GL_TRUE;
2055af69d88dSmrg   GLint i;
20567117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
20577117f1b4Smrg
2058af69d88dSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2059af69d88dSmrg      _mesa_debug(ctx, "glAreTexturesResident %d\n", n);
2060af69d88dSmrg
20617117f1b4Smrg   if (n < 0) {
20627117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
20637117f1b4Smrg      return GL_FALSE;
20647117f1b4Smrg   }
20657117f1b4Smrg
20667117f1b4Smrg   if (!texName || !residences)
20677117f1b4Smrg      return GL_FALSE;
20687117f1b4Smrg
2069af69d88dSmrg   /* We only do error checking on the texture names */
20707117f1b4Smrg   for (i = 0; i < n; i++) {
20717117f1b4Smrg      struct gl_texture_object *t;
20727117f1b4Smrg      if (texName[i] == 0) {
20737117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
20747117f1b4Smrg         return GL_FALSE;
20757117f1b4Smrg      }
20767117f1b4Smrg      t = _mesa_lookup_texture(ctx, texName[i]);
20777117f1b4Smrg      if (!t) {
20787117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
20797117f1b4Smrg         return GL_FALSE;
20807117f1b4Smrg      }
20817117f1b4Smrg   }
208201e04c3fSmrg
20837117f1b4Smrg   return allResident;
20847117f1b4Smrg}
20857117f1b4Smrg
20863464ebd5Sriastradh
20877117f1b4Smrg/**
20887117f1b4Smrg * See if a name corresponds to a texture.
20897117f1b4Smrg *
20907117f1b4Smrg * \param texture texture name.
20917117f1b4Smrg *
20927117f1b4Smrg * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
20937117f1b4Smrg * otherwise.
209401e04c3fSmrg *
20957117f1b4Smrg * \sa glIsTexture().
20967117f1b4Smrg *
20977117f1b4Smrg * Calls _mesa_HashLookup().
20987117f1b4Smrg */
20997117f1b4SmrgGLboolean GLAPIENTRY
21007117f1b4Smrg_mesa_IsTexture( GLuint texture )
21017117f1b4Smrg{
21027117f1b4Smrg   struct gl_texture_object *t;
21037117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
21047117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
21057117f1b4Smrg
2106af69d88dSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2107af69d88dSmrg      _mesa_debug(ctx, "glIsTexture %d\n", texture);
2108af69d88dSmrg
21097117f1b4Smrg   if (!texture)
21107117f1b4Smrg      return GL_FALSE;
21117117f1b4Smrg
21127117f1b4Smrg   t = _mesa_lookup_texture(ctx, texture);
21137117f1b4Smrg
21147117f1b4Smrg   /* IsTexture is true only after object has been bound once. */
21157117f1b4Smrg   return t && t->Target;
21167117f1b4Smrg}
21177117f1b4Smrg
2118c1f859d4Smrg
2119c1f859d4Smrg/**
21204a49301eSmrg * Simplest implementation of texture locking: grab the shared tex
21214a49301eSmrg * mutex.  Examine the shared context state timestamp and if there has
21224a49301eSmrg * been a change, set the appropriate bits in ctx->NewState.
21237117f1b4Smrg *
2124c1f859d4Smrg * This is used to deal with synchronizing things when a texture object
2125c1f859d4Smrg * is used/modified by different contexts (or threads) which are sharing
2126c1f859d4Smrg * the texture.
2127c1f859d4Smrg *
2128c1f859d4Smrg * See also _mesa_lock/unlock_texture() in teximage.h
21297117f1b4Smrg */
2130c1f859d4Smrgvoid
21313464ebd5Sriastradh_mesa_lock_context_textures( struct gl_context *ctx )
21327117f1b4Smrg{
2133af69d88dSmrg   mtx_lock(&ctx->Shared->TexMutex);
21347117f1b4Smrg
21357117f1b4Smrg   if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
213601e04c3fSmrg      ctx->NewState |= _NEW_TEXTURE_OBJECT;
21377117f1b4Smrg      ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
21387117f1b4Smrg   }
21397117f1b4Smrg}
21407117f1b4Smrg
21417117f1b4Smrg
2142c1f859d4Smrgvoid
21433464ebd5Sriastradh_mesa_unlock_context_textures( struct gl_context *ctx )
21447117f1b4Smrg{
21457117f1b4Smrg   assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
2146af69d88dSmrg   mtx_unlock(&ctx->Shared->TexMutex);
2147af69d88dSmrg}
2148af69d88dSmrg
214901e04c3fSmrg
215001e04c3fSmrgvoid GLAPIENTRY
215101e04c3fSmrg_mesa_InvalidateTexSubImage_no_error(GLuint texture, GLint level, GLint xoffset,
215201e04c3fSmrg                                     GLint yoffset, GLint zoffset,
215301e04c3fSmrg                                     GLsizei width, GLsizei height,
215401e04c3fSmrg                                     GLsizei depth)
215501e04c3fSmrg{
215601e04c3fSmrg   /* no-op */
215701e04c3fSmrg}
215801e04c3fSmrg
215901e04c3fSmrg
2160af69d88dSmrgvoid GLAPIENTRY
2161af69d88dSmrg_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
2162af69d88dSmrg                            GLint yoffset, GLint zoffset, GLsizei width,
2163af69d88dSmrg                            GLsizei height, GLsizei depth)
2164af69d88dSmrg{
2165af69d88dSmrg   struct gl_texture_object *t;
2166af69d88dSmrg   struct gl_texture_image *image;
2167af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
2168af69d88dSmrg
2169af69d88dSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2170af69d88dSmrg      _mesa_debug(ctx, "glInvalidateTexSubImage %d\n", texture);
2171af69d88dSmrg
2172af69d88dSmrg   t = invalidate_tex_image_error_check(ctx, texture, level,
2173af69d88dSmrg                                        "glInvalidateTexSubImage");
2174af69d88dSmrg
2175af69d88dSmrg   /* The GL_ARB_invalidate_subdata spec says:
2176af69d88dSmrg    *
2177af69d88dSmrg    *     "...the specified subregion must be between -<b> and <dim>+<b> where
2178af69d88dSmrg    *     <dim> is the size of the dimension of the texture image, and <b> is
2179af69d88dSmrg    *     the size of the border of that texture image, otherwise
2180af69d88dSmrg    *     INVALID_VALUE is generated (border is not applied to dimensions that
2181af69d88dSmrg    *     don't exist in a given texture target)."
2182af69d88dSmrg    */
2183af69d88dSmrg   image = t->Image[0][level];
2184af69d88dSmrg   if (image) {
2185af69d88dSmrg      int xBorder;
2186af69d88dSmrg      int yBorder;
2187af69d88dSmrg      int zBorder;
2188af69d88dSmrg      int imageWidth;
2189af69d88dSmrg      int imageHeight;
2190af69d88dSmrg      int imageDepth;
2191af69d88dSmrg
2192af69d88dSmrg      /* The GL_ARB_invalidate_subdata spec says:
2193af69d88dSmrg       *
2194af69d88dSmrg       *     "For texture targets that don't have certain dimensions, this
2195af69d88dSmrg       *     command treats those dimensions as having a size of 1. For
2196af69d88dSmrg       *     example, to invalidate a portion of a two-dimensional texture,
2197af69d88dSmrg       *     the application would use <zoffset> equal to zero and <depth>
2198af69d88dSmrg       *     equal to one."
2199af69d88dSmrg       */
2200af69d88dSmrg      switch (t->Target) {
2201af69d88dSmrg      case GL_TEXTURE_BUFFER:
2202af69d88dSmrg         xBorder = 0;
2203af69d88dSmrg         yBorder = 0;
2204af69d88dSmrg         zBorder = 0;
2205af69d88dSmrg         imageWidth = 1;
2206af69d88dSmrg         imageHeight = 1;
2207af69d88dSmrg         imageDepth = 1;
2208af69d88dSmrg         break;
2209af69d88dSmrg      case GL_TEXTURE_1D:
2210af69d88dSmrg         xBorder = image->Border;
2211af69d88dSmrg         yBorder = 0;
2212af69d88dSmrg         zBorder = 0;
2213af69d88dSmrg         imageWidth = image->Width;
2214af69d88dSmrg         imageHeight = 1;
2215af69d88dSmrg         imageDepth = 1;
2216af69d88dSmrg         break;
2217af69d88dSmrg      case GL_TEXTURE_1D_ARRAY:
2218af69d88dSmrg         xBorder = image->Border;
2219af69d88dSmrg         yBorder = 0;
2220af69d88dSmrg         zBorder = 0;
2221af69d88dSmrg         imageWidth = image->Width;
2222af69d88dSmrg         imageHeight = image->Height;
2223af69d88dSmrg         imageDepth = 1;
2224af69d88dSmrg         break;
2225af69d88dSmrg      case GL_TEXTURE_2D:
2226af69d88dSmrg      case GL_TEXTURE_CUBE_MAP:
2227af69d88dSmrg      case GL_TEXTURE_RECTANGLE:
2228af69d88dSmrg      case GL_TEXTURE_2D_MULTISAMPLE:
2229af69d88dSmrg         xBorder = image->Border;
2230af69d88dSmrg         yBorder = image->Border;
2231af69d88dSmrg         zBorder = 0;
2232af69d88dSmrg         imageWidth = image->Width;
2233af69d88dSmrg         imageHeight = image->Height;
2234af69d88dSmrg         imageDepth = 1;
2235af69d88dSmrg         break;
2236af69d88dSmrg      case GL_TEXTURE_2D_ARRAY:
2237af69d88dSmrg      case GL_TEXTURE_CUBE_MAP_ARRAY:
2238af69d88dSmrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2239af69d88dSmrg         xBorder = image->Border;
2240af69d88dSmrg         yBorder = image->Border;
2241af69d88dSmrg         zBorder = 0;
2242af69d88dSmrg         imageWidth = image->Width;
2243af69d88dSmrg         imageHeight = image->Height;
2244af69d88dSmrg         imageDepth = image->Depth;
2245af69d88dSmrg         break;
2246af69d88dSmrg      case GL_TEXTURE_3D:
2247af69d88dSmrg         xBorder = image->Border;
2248af69d88dSmrg         yBorder = image->Border;
2249af69d88dSmrg         zBorder = image->Border;
2250af69d88dSmrg         imageWidth = image->Width;
2251af69d88dSmrg         imageHeight = image->Height;
2252af69d88dSmrg         imageDepth = image->Depth;
2253af69d88dSmrg         break;
2254af69d88dSmrg      default:
2255af69d88dSmrg         assert(!"Should not get here.");
2256af69d88dSmrg         xBorder = 0;
2257af69d88dSmrg         yBorder = 0;
2258af69d88dSmrg         zBorder = 0;
2259af69d88dSmrg         imageWidth = 0;
2260af69d88dSmrg         imageHeight = 0;
2261af69d88dSmrg         imageDepth = 0;
2262af69d88dSmrg         break;
2263af69d88dSmrg      }
2264af69d88dSmrg
2265af69d88dSmrg      if (xoffset < -xBorder) {
2266af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)");
2267af69d88dSmrg         return;
2268af69d88dSmrg      }
2269af69d88dSmrg
2270af69d88dSmrg      if (xoffset + width > imageWidth + xBorder) {
2271af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
2272af69d88dSmrg                     "glInvalidateSubTexImage(xoffset+width)");
2273af69d88dSmrg         return;
2274af69d88dSmrg      }
2275af69d88dSmrg
2276af69d88dSmrg      if (yoffset < -yBorder) {
2277af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)");
2278af69d88dSmrg         return;
2279af69d88dSmrg      }
2280af69d88dSmrg
2281af69d88dSmrg      if (yoffset + height > imageHeight + yBorder) {
2282af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
2283af69d88dSmrg                     "glInvalidateSubTexImage(yoffset+height)");
2284af69d88dSmrg         return;
2285af69d88dSmrg      }
2286af69d88dSmrg
2287af69d88dSmrg      if (zoffset < -zBorder) {
2288af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
2289af69d88dSmrg                     "glInvalidateSubTexImage(zoffset)");
2290af69d88dSmrg         return;
2291af69d88dSmrg      }
2292af69d88dSmrg
2293af69d88dSmrg      if (zoffset + depth  > imageDepth + zBorder) {
2294af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
2295af69d88dSmrg                     "glInvalidateSubTexImage(zoffset+depth)");
2296af69d88dSmrg         return;
2297af69d88dSmrg      }
2298af69d88dSmrg   }
2299af69d88dSmrg
2300af69d88dSmrg   /* We don't actually do anything for this yet.  Just return after
2301af69d88dSmrg    * validating the parameters and generating the required errors.
2302af69d88dSmrg    */
2303af69d88dSmrg   return;
2304af69d88dSmrg}
2305af69d88dSmrg
230601e04c3fSmrg
230701e04c3fSmrgvoid GLAPIENTRY
230801e04c3fSmrg_mesa_InvalidateTexImage_no_error(GLuint texture, GLint level)
230901e04c3fSmrg{
231001e04c3fSmrg   /* no-op */
231101e04c3fSmrg}
231201e04c3fSmrg
231301e04c3fSmrg
2314af69d88dSmrgvoid GLAPIENTRY
2315af69d88dSmrg_mesa_InvalidateTexImage(GLuint texture, GLint level)
2316af69d88dSmrg{
2317af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
2318af69d88dSmrg
2319af69d88dSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2320af69d88dSmrg      _mesa_debug(ctx, "glInvalidateTexImage(%d, %d)\n", texture, level);
2321af69d88dSmrg
2322af69d88dSmrg   invalidate_tex_image_error_check(ctx, texture, level,
2323af69d88dSmrg                                    "glInvalidateTexImage");
2324af69d88dSmrg
2325af69d88dSmrg   /* We don't actually do anything for this yet.  Just return after
2326af69d88dSmrg    * validating the parameters and generating the required errors.
2327af69d88dSmrg    */
2328af69d88dSmrg   return;
23297117f1b4Smrg}
23307117f1b4Smrg
23317117f1b4Smrg/*@}*/
2332