1848b8605Smrg/**
2848b8605Smrg * \file texobj.c
3848b8605Smrg * Texture object management.
4848b8605Smrg */
5848b8605Smrg
6848b8605Smrg/*
7848b8605Smrg * Mesa 3-D graphics library
8848b8605Smrg *
9848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
10848b8605Smrg *
11848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
12848b8605Smrg * copy of this software and associated documentation files (the "Software"),
13848b8605Smrg * to deal in the Software without restriction, including without limitation
14848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
16848b8605Smrg * Software is furnished to do so, subject to the following conditions:
17848b8605Smrg *
18848b8605Smrg * The above copyright notice and this permission notice shall be included
19848b8605Smrg * in all copies or substantial portions of the Software.
20848b8605Smrg *
21848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
28848b8605Smrg */
29848b8605Smrg
30848b8605Smrg
31b8e80941Smrg#include <stdio.h>
32848b8605Smrg#include "bufferobj.h"
33848b8605Smrg#include "context.h"
34848b8605Smrg#include "enums.h"
35848b8605Smrg#include "fbobject.h"
36848b8605Smrg#include "formats.h"
37848b8605Smrg#include "hash.h"
38848b8605Smrg#include "imports.h"
39848b8605Smrg#include "macros.h"
40b8e80941Smrg#include "shaderimage.h"
41848b8605Smrg#include "teximage.h"
42848b8605Smrg#include "texobj.h"
43848b8605Smrg#include "texstate.h"
44848b8605Smrg#include "mtypes.h"
45848b8605Smrg#include "program/prog_instruction.h"
46b8e80941Smrg#include "texturebindless.h"
47848b8605Smrg
48848b8605Smrg
49848b8605Smrg
50848b8605Smrg/**********************************************************************/
51848b8605Smrg/** \name Internal functions */
52848b8605Smrg/*@{*/
53848b8605Smrg
54b8e80941Smrg/**
55b8e80941Smrg * This function checks for all valid combinations of Min and Mag filters for
56b8e80941Smrg * Float types, when extensions like OES_texture_float and
57b8e80941Smrg * OES_texture_float_linear are supported. OES_texture_float mentions support
58b8e80941Smrg * for NEAREST, NEAREST_MIPMAP_NEAREST magnification and minification filters.
59b8e80941Smrg * Mag filters like LINEAR and min filters like NEAREST_MIPMAP_LINEAR,
60b8e80941Smrg * LINEAR_MIPMAP_NEAREST and LINEAR_MIPMAP_LINEAR are only valid in case
61b8e80941Smrg * OES_texture_float_linear is supported.
62b8e80941Smrg *
63b8e80941Smrg * Returns true in case the filter is valid for given Float type else false.
64b8e80941Smrg */
65b8e80941Smrgstatic bool
66b8e80941Smrgvalid_filter_for_float(const struct gl_context *ctx,
67b8e80941Smrg                       const struct gl_texture_object *obj)
68b8e80941Smrg{
69b8e80941Smrg   switch (obj->Sampler.MagFilter) {
70b8e80941Smrg   case GL_LINEAR:
71b8e80941Smrg      if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) {
72b8e80941Smrg         return false;
73b8e80941Smrg      } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) {
74b8e80941Smrg         return false;
75b8e80941Smrg      }
76b8e80941Smrg   case GL_NEAREST:
77b8e80941Smrg   case GL_NEAREST_MIPMAP_NEAREST:
78b8e80941Smrg      break;
79b8e80941Smrg   default:
80b8e80941Smrg      unreachable("Invalid mag filter");
81b8e80941Smrg   }
82b8e80941Smrg
83b8e80941Smrg   switch (obj->Sampler.MinFilter) {
84b8e80941Smrg   case GL_LINEAR:
85b8e80941Smrg   case GL_NEAREST_MIPMAP_LINEAR:
86b8e80941Smrg   case GL_LINEAR_MIPMAP_NEAREST:
87b8e80941Smrg   case GL_LINEAR_MIPMAP_LINEAR:
88b8e80941Smrg      if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) {
89b8e80941Smrg         return false;
90b8e80941Smrg      } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) {
91b8e80941Smrg         return false;
92b8e80941Smrg      }
93b8e80941Smrg   case GL_NEAREST:
94b8e80941Smrg   case GL_NEAREST_MIPMAP_NEAREST:
95b8e80941Smrg      break;
96b8e80941Smrg   default:
97b8e80941Smrg      unreachable("Invalid min filter");
98b8e80941Smrg   }
99b8e80941Smrg
100b8e80941Smrg   return true;
101b8e80941Smrg}
102848b8605Smrg
103848b8605Smrg/**
104848b8605Smrg * Return the gl_texture_object for a given ID.
105848b8605Smrg */
106848b8605Smrgstruct gl_texture_object *
107848b8605Smrg_mesa_lookup_texture(struct gl_context *ctx, GLuint id)
108848b8605Smrg{
109848b8605Smrg   return (struct gl_texture_object *)
110848b8605Smrg      _mesa_HashLookup(ctx->Shared->TexObjects, id);
111848b8605Smrg}
112848b8605Smrg
113b8e80941Smrg/**
114b8e80941Smrg * Wrapper around _mesa_lookup_texture that throws GL_INVALID_OPERATION if id
115b8e80941Smrg * is not in the hash table. After calling _mesa_error, it returns NULL.
116b8e80941Smrg */
117b8e80941Smrgstruct gl_texture_object *
118b8e80941Smrg_mesa_lookup_texture_err(struct gl_context *ctx, GLuint id, const char* func)
119848b8605Smrg{
120b8e80941Smrg   struct gl_texture_object *texObj = NULL;
121848b8605Smrg
122b8e80941Smrg   if (id > 0)
123b8e80941Smrg      texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */
124848b8605Smrg
125b8e80941Smrg   if (!texObj)
126b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture)", func);
127b8e80941Smrg
128b8e80941Smrg   return texObj;
129848b8605Smrg}
130848b8605Smrg
131848b8605Smrg
132848b8605Smrgstruct gl_texture_object *
133848b8605Smrg_mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id)
134848b8605Smrg{
135848b8605Smrg   return (struct gl_texture_object *)
136848b8605Smrg      _mesa_HashLookupLocked(ctx->Shared->TexObjects, id);
137848b8605Smrg}
138848b8605Smrg
139b8e80941Smrg/**
140b8e80941Smrg * Return a pointer to the current texture object for the given target
141b8e80941Smrg * on the current texture unit.
142b8e80941Smrg * Note: all <target> error checking should have been done by this point.
143b8e80941Smrg */
144b8e80941Smrgstruct gl_texture_object *
145b8e80941Smrg_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
146b8e80941Smrg{
147b8e80941Smrg   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
148b8e80941Smrg   const GLboolean arrayTex = ctx->Extensions.EXT_texture_array;
149b8e80941Smrg
150b8e80941Smrg   switch (target) {
151b8e80941Smrg      case GL_TEXTURE_1D:
152b8e80941Smrg         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
153b8e80941Smrg      case GL_PROXY_TEXTURE_1D:
154b8e80941Smrg         return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
155b8e80941Smrg      case GL_TEXTURE_2D:
156b8e80941Smrg         return texUnit->CurrentTex[TEXTURE_2D_INDEX];
157b8e80941Smrg      case GL_PROXY_TEXTURE_2D:
158b8e80941Smrg         return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
159b8e80941Smrg      case GL_TEXTURE_3D:
160b8e80941Smrg         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
161b8e80941Smrg      case GL_PROXY_TEXTURE_3D:
162b8e80941Smrg         return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
163b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
164b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
165b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
166b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
167b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
168b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
169b8e80941Smrg      case GL_TEXTURE_CUBE_MAP:
170b8e80941Smrg         return ctx->Extensions.ARB_texture_cube_map
171b8e80941Smrg                ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
172b8e80941Smrg      case GL_PROXY_TEXTURE_CUBE_MAP:
173b8e80941Smrg         return ctx->Extensions.ARB_texture_cube_map
174b8e80941Smrg                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
175b8e80941Smrg      case GL_TEXTURE_CUBE_MAP_ARRAY:
176b8e80941Smrg         return _mesa_has_texture_cube_map_array(ctx)
177b8e80941Smrg                ? texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
178b8e80941Smrg      case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
179b8e80941Smrg         return _mesa_has_texture_cube_map_array(ctx)
180b8e80941Smrg                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
181b8e80941Smrg      case GL_TEXTURE_RECTANGLE_NV:
182b8e80941Smrg         return ctx->Extensions.NV_texture_rectangle
183b8e80941Smrg                ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
184b8e80941Smrg      case GL_PROXY_TEXTURE_RECTANGLE_NV:
185b8e80941Smrg         return ctx->Extensions.NV_texture_rectangle
186b8e80941Smrg                ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
187b8e80941Smrg      case GL_TEXTURE_1D_ARRAY_EXT:
188b8e80941Smrg         return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
189b8e80941Smrg      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
190b8e80941Smrg         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
191b8e80941Smrg      case GL_TEXTURE_2D_ARRAY_EXT:
192b8e80941Smrg         return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
193b8e80941Smrg      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
194b8e80941Smrg         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
195b8e80941Smrg      case GL_TEXTURE_BUFFER:
196b8e80941Smrg         return (_mesa_has_ARB_texture_buffer_object(ctx) ||
197b8e80941Smrg                 _mesa_has_OES_texture_buffer(ctx)) ?
198b8e80941Smrg                texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
199b8e80941Smrg      case GL_TEXTURE_EXTERNAL_OES:
200b8e80941Smrg         return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
201b8e80941Smrg            ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
202b8e80941Smrg      case GL_TEXTURE_2D_MULTISAMPLE:
203b8e80941Smrg         return ctx->Extensions.ARB_texture_multisample
204b8e80941Smrg            ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
205b8e80941Smrg      case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
206b8e80941Smrg         return ctx->Extensions.ARB_texture_multisample
207b8e80941Smrg            ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
208b8e80941Smrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
209b8e80941Smrg         return ctx->Extensions.ARB_texture_multisample
210b8e80941Smrg            ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
211b8e80941Smrg      case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
212b8e80941Smrg         return ctx->Extensions.ARB_texture_multisample
213b8e80941Smrg            ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
214b8e80941Smrg      default:
215b8e80941Smrg         _mesa_problem(NULL, "bad target in _mesa_get_current_tex_object()");
216b8e80941Smrg         return NULL;
217b8e80941Smrg   }
218b8e80941Smrg}
219b8e80941Smrg
220848b8605Smrg
221848b8605Smrg/**
222848b8605Smrg * Allocate and initialize a new texture object.  But don't put it into the
223848b8605Smrg * texture object hash table.
224848b8605Smrg *
225848b8605Smrg * Called via ctx->Driver.NewTextureObject, unless overridden by a device
226848b8605Smrg * driver.
227b8e80941Smrg *
228848b8605Smrg * \param shared the shared GL state structure to contain the texture object
229848b8605Smrg * \param name integer name for the texture object
230848b8605Smrg * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
231b8e80941Smrg * GL_TEXTURE_CUBE_MAP or GL_TEXTURE_RECTANGLE_NV.  zero is ok for the sake
232848b8605Smrg * of GenTextures()
233848b8605Smrg *
234848b8605Smrg * \return pointer to new texture object.
235848b8605Smrg */
236848b8605Smrgstruct gl_texture_object *
237b8e80941Smrg_mesa_new_texture_object(struct gl_context *ctx, GLuint name, GLenum target)
238848b8605Smrg{
239848b8605Smrg   struct gl_texture_object *obj;
240b8e80941Smrg
241848b8605Smrg   obj = MALLOC_STRUCT(gl_texture_object);
242b8e80941Smrg   if (!obj)
243b8e80941Smrg      return NULL;
244b8e80941Smrg
245848b8605Smrg   _mesa_initialize_texture_object(ctx, obj, name, target);
246848b8605Smrg   return obj;
247848b8605Smrg}
248848b8605Smrg
249848b8605Smrg
250848b8605Smrg/**
251848b8605Smrg * Initialize a new texture object to default values.
252848b8605Smrg * \param obj  the texture object
253848b8605Smrg * \param name  the texture name
254848b8605Smrg * \param target  the texture target
255848b8605Smrg */
256848b8605Smrgvoid
257848b8605Smrg_mesa_initialize_texture_object( struct gl_context *ctx,
258848b8605Smrg                                 struct gl_texture_object *obj,
259848b8605Smrg                                 GLuint name, GLenum target )
260848b8605Smrg{
261b8e80941Smrg   assert(target == 0 ||
262848b8605Smrg          target == GL_TEXTURE_1D ||
263848b8605Smrg          target == GL_TEXTURE_2D ||
264848b8605Smrg          target == GL_TEXTURE_3D ||
265b8e80941Smrg          target == GL_TEXTURE_CUBE_MAP ||
266848b8605Smrg          target == GL_TEXTURE_RECTANGLE_NV ||
267848b8605Smrg          target == GL_TEXTURE_1D_ARRAY_EXT ||
268848b8605Smrg          target == GL_TEXTURE_2D_ARRAY_EXT ||
269848b8605Smrg          target == GL_TEXTURE_EXTERNAL_OES ||
270848b8605Smrg          target == GL_TEXTURE_CUBE_MAP_ARRAY ||
271848b8605Smrg          target == GL_TEXTURE_BUFFER ||
272848b8605Smrg          target == GL_TEXTURE_2D_MULTISAMPLE ||
273848b8605Smrg          target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
274848b8605Smrg
275b8e80941Smrg   GLenum filter = GL_LINEAR;
276b8e80941Smrg
277848b8605Smrg   memset(obj, 0, sizeof(*obj));
278848b8605Smrg   /* init the non-zero fields */
279b8e80941Smrg   simple_mtx_init(&obj->Mutex, mtx_plain);
280848b8605Smrg   obj->RefCount = 1;
281848b8605Smrg   obj->Name = name;
282848b8605Smrg   obj->Target = target;
283b8e80941Smrg   if (target != 0) {
284b8e80941Smrg      obj->TargetIndex = _mesa_tex_target_to_index(ctx, target);
285b8e80941Smrg   }
286b8e80941Smrg   else {
287b8e80941Smrg      obj->TargetIndex = NUM_TEXTURE_TARGETS; /* invalid/error value */
288b8e80941Smrg   }
289848b8605Smrg   obj->Priority = 1.0F;
290848b8605Smrg   obj->BaseLevel = 0;
291848b8605Smrg   obj->MaxLevel = 1000;
292848b8605Smrg
293848b8605Smrg   /* must be one; no support for (YUV) planes in separate buffers */
294848b8605Smrg   obj->RequiredTextureImageUnits = 1;
295848b8605Smrg
296848b8605Smrg   /* sampler state */
297b8e80941Smrg   switch (target) {
298b8e80941Smrg      case GL_TEXTURE_2D_MULTISAMPLE:
299b8e80941Smrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
300b8e80941Smrg         filter = GL_NEAREST;
301b8e80941Smrg         /* fallthrough */
302b8e80941Smrg
303b8e80941Smrg      case GL_TEXTURE_RECTANGLE_NV:
304b8e80941Smrg      case GL_TEXTURE_EXTERNAL_OES:
305b8e80941Smrg         obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
306b8e80941Smrg         obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
307b8e80941Smrg         obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
308b8e80941Smrg         obj->Sampler.MinFilter = filter;
309b8e80941Smrg         obj->Sampler.MagFilter = filter;
310b8e80941Smrg         break;
311b8e80941Smrg
312b8e80941Smrg      default:
313b8e80941Smrg         obj->Sampler.WrapS = GL_REPEAT;
314b8e80941Smrg         obj->Sampler.WrapT = GL_REPEAT;
315b8e80941Smrg         obj->Sampler.WrapR = GL_REPEAT;
316b8e80941Smrg         obj->Sampler.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
317b8e80941Smrg         obj->Sampler.MagFilter = GL_LINEAR;
318b8e80941Smrg         break;
319848b8605Smrg   }
320b8e80941Smrg
321848b8605Smrg   obj->Sampler.MinLod = -1000.0;
322848b8605Smrg   obj->Sampler.MaxLod = 1000.0;
323848b8605Smrg   obj->Sampler.LodBias = 0.0;
324848b8605Smrg   obj->Sampler.MaxAnisotropy = 1.0;
325848b8605Smrg   obj->Sampler.CompareMode = GL_NONE;         /* ARB_shadow */
326848b8605Smrg   obj->Sampler.CompareFunc = GL_LEQUAL;       /* ARB_shadow */
327848b8605Smrg   obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
328848b8605Smrg   obj->StencilSampling = false;
329848b8605Smrg   obj->Sampler.CubeMapSeamless = GL_FALSE;
330b8e80941Smrg   obj->Sampler.HandleAllocated = GL_FALSE;
331848b8605Smrg   obj->Swizzle[0] = GL_RED;
332848b8605Smrg   obj->Swizzle[1] = GL_GREEN;
333848b8605Smrg   obj->Swizzle[2] = GL_BLUE;
334848b8605Smrg   obj->Swizzle[3] = GL_ALPHA;
335848b8605Smrg   obj->_Swizzle = SWIZZLE_NOOP;
336848b8605Smrg   obj->Sampler.sRGBDecode = GL_DECODE_EXT;
337848b8605Smrg   obj->BufferObjectFormat = GL_R8;
338848b8605Smrg   obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
339848b8605Smrg   obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
340b8e80941Smrg
341b8e80941Smrg   /* GL_ARB_bindless_texture */
342b8e80941Smrg   _mesa_init_texture_handles(obj);
343848b8605Smrg}
344848b8605Smrg
345848b8605Smrg
346848b8605Smrg/**
347848b8605Smrg * Some texture initialization can't be finished until we know which
348848b8605Smrg * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
349848b8605Smrg */
350848b8605Smrgstatic void
351848b8605Smrgfinish_texture_init(struct gl_context *ctx, GLenum target,
352b8e80941Smrg                    struct gl_texture_object *obj, int targetIndex)
353848b8605Smrg{
354848b8605Smrg   GLenum filter = GL_LINEAR;
355848b8605Smrg   assert(obj->Target == 0);
356848b8605Smrg
357b8e80941Smrg   obj->Target = target;
358b8e80941Smrg   obj->TargetIndex = targetIndex;
359b8e80941Smrg   assert(obj->TargetIndex < NUM_TEXTURE_TARGETS);
360b8e80941Smrg
361848b8605Smrg   switch (target) {
362848b8605Smrg      case GL_TEXTURE_2D_MULTISAMPLE:
363848b8605Smrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
364848b8605Smrg         filter = GL_NEAREST;
365848b8605Smrg         /* fallthrough */
366848b8605Smrg
367848b8605Smrg      case GL_TEXTURE_RECTANGLE_NV:
368848b8605Smrg      case GL_TEXTURE_EXTERNAL_OES:
369848b8605Smrg         /* have to init wrap and filter state here - kind of klunky */
370848b8605Smrg         obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
371848b8605Smrg         obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
372848b8605Smrg         obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
373848b8605Smrg         obj->Sampler.MinFilter = filter;
374848b8605Smrg         obj->Sampler.MagFilter = filter;
375848b8605Smrg         if (ctx->Driver.TexParameter) {
376b8e80941Smrg            /* XXX we probably don't need to make all these calls */
377b8e80941Smrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_S);
378b8e80941Smrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_T);
379b8e80941Smrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_R);
380b8e80941Smrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_MIN_FILTER);
381b8e80941Smrg            ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_MAG_FILTER);
382848b8605Smrg         }
383848b8605Smrg         break;
384848b8605Smrg
385848b8605Smrg      default:
386848b8605Smrg         /* nothing needs done */
387848b8605Smrg         break;
388848b8605Smrg   }
389848b8605Smrg}
390848b8605Smrg
391848b8605Smrg
392848b8605Smrg/**
393848b8605Smrg * Deallocate a texture object struct.  It should have already been
394848b8605Smrg * removed from the texture object pool.
395848b8605Smrg * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
396848b8605Smrg *
397848b8605Smrg * \param shared the shared GL state to which the object belongs.
398848b8605Smrg * \param texObj the texture object to delete.
399848b8605Smrg */
400848b8605Smrgvoid
401848b8605Smrg_mesa_delete_texture_object(struct gl_context *ctx,
402848b8605Smrg                            struct gl_texture_object *texObj)
403848b8605Smrg{
404848b8605Smrg   GLuint i, face;
405848b8605Smrg
406848b8605Smrg   /* Set Target to an invalid value.  With some assertions elsewhere
407848b8605Smrg    * we can try to detect possible use of deleted textures.
408848b8605Smrg    */
409848b8605Smrg   texObj->Target = 0x99;
410848b8605Smrg
411848b8605Smrg   /* free the texture images */
412848b8605Smrg   for (face = 0; face < 6; face++) {
413848b8605Smrg      for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
414848b8605Smrg         if (texObj->Image[face][i]) {
415848b8605Smrg            ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]);
416848b8605Smrg         }
417848b8605Smrg      }
418848b8605Smrg   }
419848b8605Smrg
420b8e80941Smrg   /* Delete all texture/image handles. */
421b8e80941Smrg   _mesa_delete_texture_handles(ctx, texObj);
422b8e80941Smrg
423848b8605Smrg   _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
424848b8605Smrg
425848b8605Smrg   /* destroy the mutex -- it may have allocated memory (eg on bsd) */
426b8e80941Smrg   simple_mtx_destroy(&texObj->Mutex);
427848b8605Smrg
428848b8605Smrg   free(texObj->Label);
429848b8605Smrg
430848b8605Smrg   /* free this object */
431848b8605Smrg   free(texObj);
432848b8605Smrg}
433848b8605Smrg
434848b8605Smrg
435848b8605Smrg/**
436848b8605Smrg * Copy texture object state from one texture object to another.
437848b8605Smrg * Use for glPush/PopAttrib.
438848b8605Smrg *
439848b8605Smrg * \param dest destination texture object.
440848b8605Smrg * \param src source texture object.
441848b8605Smrg */
442848b8605Smrgvoid
443848b8605Smrg_mesa_copy_texture_object( struct gl_texture_object *dest,
444848b8605Smrg                           const struct gl_texture_object *src )
445848b8605Smrg{
446848b8605Smrg   dest->Target = src->Target;
447848b8605Smrg   dest->TargetIndex = src->TargetIndex;
448848b8605Smrg   dest->Name = src->Name;
449848b8605Smrg   dest->Priority = src->Priority;
450848b8605Smrg   dest->Sampler.BorderColor.f[0] = src->Sampler.BorderColor.f[0];
451848b8605Smrg   dest->Sampler.BorderColor.f[1] = src->Sampler.BorderColor.f[1];
452848b8605Smrg   dest->Sampler.BorderColor.f[2] = src->Sampler.BorderColor.f[2];
453848b8605Smrg   dest->Sampler.BorderColor.f[3] = src->Sampler.BorderColor.f[3];
454848b8605Smrg   dest->Sampler.WrapS = src->Sampler.WrapS;
455848b8605Smrg   dest->Sampler.WrapT = src->Sampler.WrapT;
456848b8605Smrg   dest->Sampler.WrapR = src->Sampler.WrapR;
457848b8605Smrg   dest->Sampler.MinFilter = src->Sampler.MinFilter;
458848b8605Smrg   dest->Sampler.MagFilter = src->Sampler.MagFilter;
459848b8605Smrg   dest->Sampler.MinLod = src->Sampler.MinLod;
460848b8605Smrg   dest->Sampler.MaxLod = src->Sampler.MaxLod;
461848b8605Smrg   dest->Sampler.LodBias = src->Sampler.LodBias;
462848b8605Smrg   dest->BaseLevel = src->BaseLevel;
463848b8605Smrg   dest->MaxLevel = src->MaxLevel;
464848b8605Smrg   dest->Sampler.MaxAnisotropy = src->Sampler.MaxAnisotropy;
465848b8605Smrg   dest->Sampler.CompareMode = src->Sampler.CompareMode;
466848b8605Smrg   dest->Sampler.CompareFunc = src->Sampler.CompareFunc;
467848b8605Smrg   dest->Sampler.CubeMapSeamless = src->Sampler.CubeMapSeamless;
468848b8605Smrg   dest->DepthMode = src->DepthMode;
469848b8605Smrg   dest->StencilSampling = src->StencilSampling;
470848b8605Smrg   dest->Sampler.sRGBDecode = src->Sampler.sRGBDecode;
471848b8605Smrg   dest->_MaxLevel = src->_MaxLevel;
472848b8605Smrg   dest->_MaxLambda = src->_MaxLambda;
473848b8605Smrg   dest->GenerateMipmap = src->GenerateMipmap;
474848b8605Smrg   dest->_BaseComplete = src->_BaseComplete;
475848b8605Smrg   dest->_MipmapComplete = src->_MipmapComplete;
476848b8605Smrg   COPY_4V(dest->Swizzle, src->Swizzle);
477848b8605Smrg   dest->_Swizzle = src->_Swizzle;
478b8e80941Smrg   dest->_IsHalfFloat = src->_IsHalfFloat;
479b8e80941Smrg   dest->_IsFloat = src->_IsFloat;
480848b8605Smrg
481848b8605Smrg   dest->RequiredTextureImageUnits = src->RequiredTextureImageUnits;
482848b8605Smrg}
483848b8605Smrg
484848b8605Smrg
485848b8605Smrg/**
486b8e80941Smrg * Free all texture images of the given texture objectm, except for
487b8e80941Smrg * \p retainTexImage.
488848b8605Smrg *
489848b8605Smrg * \param ctx GL context.
490b8e80941Smrg * \param texObj texture object.
491b8e80941Smrg * \param retainTexImage a texture image that will \em not be freed.
492848b8605Smrg *
493848b8605Smrg * \sa _mesa_clear_texture_image().
494848b8605Smrg */
495848b8605Smrgvoid
496848b8605Smrg_mesa_clear_texture_object(struct gl_context *ctx,
497b8e80941Smrg                           struct gl_texture_object *texObj,
498b8e80941Smrg                           struct gl_texture_image *retainTexImage)
499848b8605Smrg{
500848b8605Smrg   GLuint i, j;
501848b8605Smrg
502848b8605Smrg   if (texObj->Target == 0)
503848b8605Smrg      return;
504848b8605Smrg
505848b8605Smrg   for (i = 0; i < MAX_FACES; i++) {
506848b8605Smrg      for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
507848b8605Smrg         struct gl_texture_image *texImage = texObj->Image[i][j];
508b8e80941Smrg         if (texImage && texImage != retainTexImage)
509848b8605Smrg            _mesa_clear_texture_image(ctx, texImage);
510848b8605Smrg      }
511848b8605Smrg   }
512848b8605Smrg}
513848b8605Smrg
514848b8605Smrg
515848b8605Smrg/**
516848b8605Smrg * Check if the given texture object is valid by examining its Target field.
517848b8605Smrg * For debugging only.
518848b8605Smrg */
519848b8605Smrgstatic GLboolean
520848b8605Smrgvalid_texture_object(const struct gl_texture_object *tex)
521848b8605Smrg{
522848b8605Smrg   switch (tex->Target) {
523848b8605Smrg   case 0:
524848b8605Smrg   case GL_TEXTURE_1D:
525848b8605Smrg   case GL_TEXTURE_2D:
526848b8605Smrg   case GL_TEXTURE_3D:
527b8e80941Smrg   case GL_TEXTURE_CUBE_MAP:
528848b8605Smrg   case GL_TEXTURE_RECTANGLE_NV:
529848b8605Smrg   case GL_TEXTURE_1D_ARRAY_EXT:
530848b8605Smrg   case GL_TEXTURE_2D_ARRAY_EXT:
531848b8605Smrg   case GL_TEXTURE_BUFFER:
532848b8605Smrg   case GL_TEXTURE_EXTERNAL_OES:
533848b8605Smrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
534848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE:
535848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
536848b8605Smrg      return GL_TRUE;
537848b8605Smrg   case 0x99:
538848b8605Smrg      _mesa_problem(NULL, "invalid reference to a deleted texture object");
539848b8605Smrg      return GL_FALSE;
540848b8605Smrg   default:
541848b8605Smrg      _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
542848b8605Smrg                    tex->Target, tex->Name);
543848b8605Smrg      return GL_FALSE;
544848b8605Smrg   }
545848b8605Smrg}
546848b8605Smrg
547848b8605Smrg
548848b8605Smrg/**
549848b8605Smrg * Reference (or unreference) a texture object.
550848b8605Smrg * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
551848b8605Smrg * If 'tex' is non-null, increment its refcount.
552848b8605Smrg * This is normally only called from the _mesa_reference_texobj() macro
553848b8605Smrg * when there's a real pointer change.
554848b8605Smrg */
555848b8605Smrgvoid
556848b8605Smrg_mesa_reference_texobj_(struct gl_texture_object **ptr,
557848b8605Smrg                        struct gl_texture_object *tex)
558848b8605Smrg{
559848b8605Smrg   assert(ptr);
560848b8605Smrg
561848b8605Smrg   if (*ptr) {
562848b8605Smrg      /* Unreference the old texture */
563848b8605Smrg      GLboolean deleteFlag = GL_FALSE;
564848b8605Smrg      struct gl_texture_object *oldTex = *ptr;
565848b8605Smrg
566b8e80941Smrg      assert(valid_texture_object(oldTex));
567848b8605Smrg      (void) valid_texture_object; /* silence warning in release builds */
568848b8605Smrg
569b8e80941Smrg      simple_mtx_lock(&oldTex->Mutex);
570b8e80941Smrg      assert(oldTex->RefCount > 0);
571848b8605Smrg      oldTex->RefCount--;
572848b8605Smrg
573848b8605Smrg      deleteFlag = (oldTex->RefCount == 0);
574b8e80941Smrg      simple_mtx_unlock(&oldTex->Mutex);
575848b8605Smrg
576848b8605Smrg      if (deleteFlag) {
577b8e80941Smrg         /* Passing in the context drastically changes the driver code for
578b8e80941Smrg          * framebuffer deletion.
579b8e80941Smrg          */
580848b8605Smrg         GET_CURRENT_CONTEXT(ctx);
581848b8605Smrg         if (ctx)
582848b8605Smrg            ctx->Driver.DeleteTexture(ctx, oldTex);
583848b8605Smrg         else
584848b8605Smrg            _mesa_problem(NULL, "Unable to delete texture, no context");
585848b8605Smrg      }
586848b8605Smrg
587848b8605Smrg      *ptr = NULL;
588848b8605Smrg   }
589848b8605Smrg   assert(!*ptr);
590848b8605Smrg
591848b8605Smrg   if (tex) {
592848b8605Smrg      /* reference new texture */
593b8e80941Smrg      assert(valid_texture_object(tex));
594b8e80941Smrg      simple_mtx_lock(&tex->Mutex);
595b8e80941Smrg      assert(tex->RefCount > 0);
596b8e80941Smrg
597b8e80941Smrg      tex->RefCount++;
598b8e80941Smrg      *ptr = tex;
599b8e80941Smrg      simple_mtx_unlock(&tex->Mutex);
600848b8605Smrg   }
601848b8605Smrg}
602848b8605Smrg
603848b8605Smrg
604848b8605Smrgenum base_mipmap { BASE, MIPMAP };
605848b8605Smrg
606848b8605Smrg
607848b8605Smrg/**
608848b8605Smrg * Mark a texture object as incomplete.  There are actually three kinds of
609848b8605Smrg * (in)completeness:
610848b8605Smrg * 1. "base incomplete": the base level of the texture is invalid so no
611848b8605Smrg *    texturing is possible.
612848b8605Smrg * 2. "mipmap incomplete": a non-base level of the texture is invalid so
613848b8605Smrg *    mipmap filtering isn't possible, but non-mipmap filtering is.
614848b8605Smrg * 3. "texture incompleteness": some combination of texture state and
615848b8605Smrg *    sampler state renders the texture incomplete.
616848b8605Smrg *
617848b8605Smrg * \param t  texture object
618848b8605Smrg * \param bm  either BASE or MIPMAP to indicate what's incomplete
619848b8605Smrg * \param fmt...  string describing why it's incomplete (for debugging).
620848b8605Smrg */
621848b8605Smrgstatic void
622848b8605Smrgincomplete(struct gl_texture_object *t, enum base_mipmap bm,
623848b8605Smrg           const char *fmt, ...)
624848b8605Smrg{
625848b8605Smrg   if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) {
626848b8605Smrg      va_list args;
627848b8605Smrg      char s[100];
628848b8605Smrg
629848b8605Smrg      va_start(args, fmt);
630848b8605Smrg      vsnprintf(s, sizeof(s), fmt, args);
631848b8605Smrg      va_end(args);
632848b8605Smrg
633848b8605Smrg      _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s);
634848b8605Smrg   }
635848b8605Smrg
636848b8605Smrg   if (bm == BASE)
637848b8605Smrg      t->_BaseComplete = GL_FALSE;
638848b8605Smrg   t->_MipmapComplete = GL_FALSE;
639848b8605Smrg}
640848b8605Smrg
641848b8605Smrg
642848b8605Smrg/**
643848b8605Smrg * Examine a texture object to determine if it is complete.
644848b8605Smrg *
645848b8605Smrg * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
646848b8605Smrg * accordingly.
647848b8605Smrg *
648848b8605Smrg * \param ctx GL context.
649848b8605Smrg * \param t texture object.
650848b8605Smrg *
651848b8605Smrg * According to the texture target, verifies that each of the mipmaps is
652848b8605Smrg * present and has the expected size.
653848b8605Smrg */
654848b8605Smrgvoid
655848b8605Smrg_mesa_test_texobj_completeness( const struct gl_context *ctx,
656848b8605Smrg                                struct gl_texture_object *t )
657848b8605Smrg{
658848b8605Smrg   const GLint baseLevel = t->BaseLevel;
659848b8605Smrg   const struct gl_texture_image *baseImage;
660848b8605Smrg   GLint maxLevels = 0;
661848b8605Smrg
662848b8605Smrg   /* We'll set these to FALSE if tests fail below */
663848b8605Smrg   t->_BaseComplete = GL_TRUE;
664848b8605Smrg   t->_MipmapComplete = GL_TRUE;
665848b8605Smrg
666848b8605Smrg   if (t->Target == GL_TEXTURE_BUFFER) {
667848b8605Smrg      /* Buffer textures are always considered complete.  The obvious case where
668848b8605Smrg       * they would be incomplete (no BO attached) is actually specced to be
669848b8605Smrg       * undefined rendering results.
670848b8605Smrg       */
671848b8605Smrg      return;
672848b8605Smrg   }
673848b8605Smrg
674848b8605Smrg   /* Detect cases where the application set the base level to an invalid
675848b8605Smrg    * value.
676848b8605Smrg    */
677848b8605Smrg   if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
678848b8605Smrg      incomplete(t, BASE, "base level = %d is invalid", baseLevel);
679848b8605Smrg      return;
680848b8605Smrg   }
681848b8605Smrg
682848b8605Smrg   if (t->MaxLevel < baseLevel) {
683848b8605Smrg      incomplete(t, MIPMAP, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
684848b8605Smrg		 t->MaxLevel, baseLevel);
685848b8605Smrg      return;
686848b8605Smrg   }
687848b8605Smrg
688848b8605Smrg   baseImage = t->Image[0][baseLevel];
689848b8605Smrg
690848b8605Smrg   /* Always need the base level image */
691848b8605Smrg   if (!baseImage) {
692848b8605Smrg      incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel);
693848b8605Smrg      return;
694848b8605Smrg   }
695848b8605Smrg
696848b8605Smrg   /* Check width/height/depth for zero */
697848b8605Smrg   if (baseImage->Width == 0 ||
698848b8605Smrg       baseImage->Height == 0 ||
699848b8605Smrg       baseImage->Depth == 0) {
700848b8605Smrg      incomplete(t, BASE, "texture width or height or depth = 0");
701848b8605Smrg      return;
702848b8605Smrg   }
703848b8605Smrg
704848b8605Smrg   /* Check if the texture values are integer */
705848b8605Smrg   {
706848b8605Smrg      GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat);
707848b8605Smrg      t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT;
708848b8605Smrg   }
709848b8605Smrg
710b8e80941Smrg   /* Check if the texture type is Float or HalfFloatOES and ensure Min and Mag
711b8e80941Smrg    * filters are supported in this case.
712b8e80941Smrg    */
713b8e80941Smrg   if (_mesa_is_gles(ctx) && !valid_filter_for_float(ctx, t)) {
714b8e80941Smrg      incomplete(t, BASE, "Filter is not supported with Float types.");
715b8e80941Smrg      return;
716b8e80941Smrg   }
717b8e80941Smrg
718848b8605Smrg   /* Compute _MaxLevel (the maximum mipmap level we'll sample from given the
719848b8605Smrg    * mipmap image sizes and GL_TEXTURE_MAX_LEVEL state).
720848b8605Smrg    */
721848b8605Smrg   switch (t->Target) {
722848b8605Smrg   case GL_TEXTURE_1D:
723848b8605Smrg   case GL_TEXTURE_1D_ARRAY_EXT:
724848b8605Smrg      maxLevels = ctx->Const.MaxTextureLevels;
725848b8605Smrg      break;
726848b8605Smrg   case GL_TEXTURE_2D:
727848b8605Smrg   case GL_TEXTURE_2D_ARRAY_EXT:
728848b8605Smrg      maxLevels = ctx->Const.MaxTextureLevels;
729848b8605Smrg      break;
730848b8605Smrg   case GL_TEXTURE_3D:
731848b8605Smrg      maxLevels = ctx->Const.Max3DTextureLevels;
732848b8605Smrg      break;
733b8e80941Smrg   case GL_TEXTURE_CUBE_MAP:
734848b8605Smrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
735848b8605Smrg      maxLevels = ctx->Const.MaxCubeTextureLevels;
736848b8605Smrg      break;
737848b8605Smrg   case GL_TEXTURE_RECTANGLE_NV:
738848b8605Smrg   case GL_TEXTURE_BUFFER:
739848b8605Smrg   case GL_TEXTURE_EXTERNAL_OES:
740848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE:
741848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
742848b8605Smrg      maxLevels = 1;  /* no mipmapping */
743848b8605Smrg      break;
744848b8605Smrg   default:
745848b8605Smrg      _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
746848b8605Smrg      return;
747848b8605Smrg   }
748848b8605Smrg
749b8e80941Smrg   assert(maxLevels > 0);
750848b8605Smrg
751848b8605Smrg   t->_MaxLevel = MIN3(t->MaxLevel,
752848b8605Smrg                       /* 'p' in the GL spec */
753848b8605Smrg                       (int) (baseLevel + baseImage->MaxNumLevels - 1),
754848b8605Smrg                       /* 'q' in the GL spec */
755848b8605Smrg                       maxLevels - 1);
756848b8605Smrg
757848b8605Smrg   if (t->Immutable) {
758848b8605Smrg      /* Adjust max level for views: the data store may have more levels than
759848b8605Smrg       * the view exposes.
760848b8605Smrg       */
761848b8605Smrg      t->_MaxLevel = MIN2(t->_MaxLevel, t->NumLevels - 1);
762848b8605Smrg   }
763848b8605Smrg
764848b8605Smrg   /* Compute _MaxLambda = q - p in the spec used during mipmapping */
765848b8605Smrg   t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);
766848b8605Smrg
767848b8605Smrg   if (t->Immutable) {
768848b8605Smrg      /* This texture object was created with glTexStorage1/2/3D() so we
769848b8605Smrg       * know that all the mipmap levels are the right size and all cube
770848b8605Smrg       * map faces are the same size.
771848b8605Smrg       * We don't need to do any of the additional checks below.
772848b8605Smrg       */
773848b8605Smrg      return;
774848b8605Smrg   }
775848b8605Smrg
776b8e80941Smrg   if (t->Target == GL_TEXTURE_CUBE_MAP) {
777b8e80941Smrg      /* Make sure that all six cube map level 0 images are the same size and
778b8e80941Smrg       * format.
779848b8605Smrg       * Note:  we know that the image's width==height (we enforce that
780848b8605Smrg       * at glTexImage time) so we only need to test the width here.
781848b8605Smrg       */
782848b8605Smrg      GLuint face;
783848b8605Smrg      assert(baseImage->Width2 == baseImage->Height);
784848b8605Smrg      for (face = 1; face < 6; face++) {
785848b8605Smrg         assert(t->Image[face][baseLevel] == NULL ||
786848b8605Smrg                t->Image[face][baseLevel]->Width2 ==
787848b8605Smrg                t->Image[face][baseLevel]->Height2);
788848b8605Smrg         if (t->Image[face][baseLevel] == NULL ||
789848b8605Smrg             t->Image[face][baseLevel]->Width2 != baseImage->Width2) {
790848b8605Smrg            incomplete(t, BASE, "Cube face missing or mismatched size");
791848b8605Smrg            return;
792848b8605Smrg         }
793b8e80941Smrg         if (t->Image[face][baseLevel]->InternalFormat !=
794b8e80941Smrg             baseImage->InternalFormat) {
795b8e80941Smrg            incomplete(t, BASE, "Cube face format mismatch");
796b8e80941Smrg            return;
797b8e80941Smrg         }
798b8e80941Smrg         if (t->Image[face][baseLevel]->Border != baseImage->Border) {
799b8e80941Smrg            incomplete(t, BASE, "Cube face border size mismatch");
800b8e80941Smrg            return;
801b8e80941Smrg         }
802848b8605Smrg      }
803848b8605Smrg   }
804848b8605Smrg
805848b8605Smrg   /*
806848b8605Smrg    * Do mipmap consistency checking.
807848b8605Smrg    * Note: we don't care about the current texture sampler state here.
808848b8605Smrg    * To determine texture completeness we'll either look at _BaseComplete
809848b8605Smrg    * or _MipmapComplete depending on the current minification filter mode.
810848b8605Smrg    */
811848b8605Smrg   {
812848b8605Smrg      GLint i;
813848b8605Smrg      const GLint minLevel = baseLevel;
814848b8605Smrg      const GLint maxLevel = t->_MaxLevel;
815848b8605Smrg      const GLuint numFaces = _mesa_num_tex_faces(t->Target);
816848b8605Smrg      GLuint width, height, depth, face;
817848b8605Smrg
818848b8605Smrg      if (minLevel > maxLevel) {
819848b8605Smrg         incomplete(t, MIPMAP, "minLevel > maxLevel");
820848b8605Smrg         return;
821848b8605Smrg      }
822848b8605Smrg
823848b8605Smrg      /* Get the base image's dimensions */
824848b8605Smrg      width = baseImage->Width2;
825848b8605Smrg      height = baseImage->Height2;
826848b8605Smrg      depth = baseImage->Depth2;
827848b8605Smrg
828848b8605Smrg      /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL,
829848b8605Smrg       * MULTISAMPLE and MULTISAMPLE_ARRAY textures
830848b8605Smrg       */
831848b8605Smrg      for (i = baseLevel + 1; i < maxLevels; i++) {
832848b8605Smrg         /* Compute the expected size of image at level[i] */
833848b8605Smrg         if (width > 1) {
834848b8605Smrg            width /= 2;
835848b8605Smrg         }
836848b8605Smrg         if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) {
837848b8605Smrg            height /= 2;
838848b8605Smrg         }
839b8e80941Smrg         if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY
840b8e80941Smrg             && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) {
841848b8605Smrg            depth /= 2;
842848b8605Smrg         }
843848b8605Smrg
844848b8605Smrg         /* loop over cube faces (or single face otherwise) */
845848b8605Smrg         for (face = 0; face < numFaces; face++) {
846848b8605Smrg            if (i >= minLevel && i <= maxLevel) {
847848b8605Smrg               const struct gl_texture_image *img = t->Image[face][i];
848848b8605Smrg
849848b8605Smrg               if (!img) {
850848b8605Smrg                  incomplete(t, MIPMAP, "TexImage[%d] is missing", i);
851848b8605Smrg                  return;
852848b8605Smrg               }
853b8e80941Smrg               if (img->InternalFormat != baseImage->InternalFormat) {
854848b8605Smrg                  incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]");
855848b8605Smrg                  return;
856848b8605Smrg               }
857848b8605Smrg               if (img->Border != baseImage->Border) {
858848b8605Smrg                  incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]");
859848b8605Smrg                  return;
860848b8605Smrg               }
861848b8605Smrg               if (img->Width2 != width) {
862b8e80941Smrg                  incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i,
863b8e80941Smrg                             img->Width2);
864848b8605Smrg                  return;
865848b8605Smrg               }
866848b8605Smrg               if (img->Height2 != height) {
867b8e80941Smrg                  incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i,
868b8e80941Smrg                             img->Height2);
869848b8605Smrg                  return;
870848b8605Smrg               }
871848b8605Smrg               if (img->Depth2 != depth) {
872b8e80941Smrg                  incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i,
873b8e80941Smrg                             img->Depth2);
874848b8605Smrg                  return;
875848b8605Smrg               }
876848b8605Smrg            }
877848b8605Smrg         }
878b8e80941Smrg
879848b8605Smrg         if (width == 1 && height == 1 && depth == 1) {
880848b8605Smrg            return;  /* found smallest needed mipmap, all done! */
881848b8605Smrg         }
882848b8605Smrg      }
883848b8605Smrg   }
884848b8605Smrg}
885848b8605Smrg
886848b8605Smrg
887848b8605SmrgGLboolean
888b8e80941Smrg_mesa_cube_level_complete(const struct gl_texture_object *texObj,
889b8e80941Smrg                          const GLint level)
890848b8605Smrg{
891848b8605Smrg   const struct gl_texture_image *img0, *img;
892848b8605Smrg   GLuint face;
893848b8605Smrg
894848b8605Smrg   if (texObj->Target != GL_TEXTURE_CUBE_MAP)
895848b8605Smrg      return GL_FALSE;
896848b8605Smrg
897b8e80941Smrg   if ((level < 0) || (level >= MAX_TEXTURE_LEVELS))
898848b8605Smrg      return GL_FALSE;
899848b8605Smrg
900848b8605Smrg   /* check first face */
901b8e80941Smrg   img0 = texObj->Image[0][level];
902848b8605Smrg   if (!img0 ||
903848b8605Smrg       img0->Width < 1 ||
904848b8605Smrg       img0->Width != img0->Height)
905848b8605Smrg      return GL_FALSE;
906848b8605Smrg
907848b8605Smrg   /* check remaining faces vs. first face */
908848b8605Smrg   for (face = 1; face < 6; face++) {
909b8e80941Smrg      img = texObj->Image[face][level];
910848b8605Smrg      if (!img ||
911848b8605Smrg          img->Width != img0->Width ||
912848b8605Smrg          img->Height != img0->Height ||
913848b8605Smrg          img->TexFormat != img0->TexFormat)
914848b8605Smrg         return GL_FALSE;
915848b8605Smrg   }
916848b8605Smrg
917848b8605Smrg   return GL_TRUE;
918848b8605Smrg}
919848b8605Smrg
920b8e80941Smrg/**
921b8e80941Smrg * Check if the given cube map texture is "cube complete" as defined in
922b8e80941Smrg * the OpenGL specification.
923b8e80941Smrg */
924b8e80941SmrgGLboolean
925b8e80941Smrg_mesa_cube_complete(const struct gl_texture_object *texObj)
926b8e80941Smrg{
927b8e80941Smrg   return _mesa_cube_level_complete(texObj, texObj->BaseLevel);
928b8e80941Smrg}
929848b8605Smrg
930848b8605Smrg/**
931848b8605Smrg * Mark a texture object dirty.  It forces the object to be incomplete
932848b8605Smrg * and forces the context to re-validate its state.
933848b8605Smrg *
934848b8605Smrg * \param ctx GL context.
935848b8605Smrg * \param texObj texture object.
936848b8605Smrg */
937848b8605Smrgvoid
938848b8605Smrg_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj)
939848b8605Smrg{
940848b8605Smrg   texObj->_BaseComplete = GL_FALSE;
941848b8605Smrg   texObj->_MipmapComplete = GL_FALSE;
942b8e80941Smrg   ctx->NewState |= _NEW_TEXTURE_OBJECT;
943848b8605Smrg}
944848b8605Smrg
945848b8605Smrg
946848b8605Smrg/**
947848b8605Smrg * Return pointer to a default/fallback texture of the given type/target.
948848b8605Smrg * The texture is an RGBA texture with all texels = (0,0,0,1).
949848b8605Smrg * That's the value a GLSL sampler should get when sampling from an
950848b8605Smrg * incomplete texture.
951848b8605Smrg */
952848b8605Smrgstruct gl_texture_object *
953848b8605Smrg_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
954848b8605Smrg{
955848b8605Smrg   if (!ctx->Shared->FallbackTex[tex]) {
956848b8605Smrg      /* create fallback texture now */
957b8e80941Smrg      const GLsizei width = 1, height = 1;
958b8e80941Smrg      GLsizei depth = 1;
959b8e80941Smrg      GLubyte texel[24];
960848b8605Smrg      struct gl_texture_object *texObj;
961848b8605Smrg      struct gl_texture_image *texImage;
962848b8605Smrg      mesa_format texFormat;
963848b8605Smrg      GLuint dims, face, numFaces = 1;
964848b8605Smrg      GLenum target;
965848b8605Smrg
966b8e80941Smrg      for (face = 0; face < 6; face++) {
967b8e80941Smrg         texel[4*face + 0] =
968b8e80941Smrg         texel[4*face + 1] =
969b8e80941Smrg         texel[4*face + 2] = 0x0;
970b8e80941Smrg         texel[4*face + 3] = 0xff;
971b8e80941Smrg      }
972848b8605Smrg
973848b8605Smrg      switch (tex) {
974848b8605Smrg      case TEXTURE_2D_ARRAY_INDEX:
975848b8605Smrg         dims = 3;
976848b8605Smrg         target = GL_TEXTURE_2D_ARRAY;
977848b8605Smrg         break;
978848b8605Smrg      case TEXTURE_1D_ARRAY_INDEX:
979848b8605Smrg         dims = 2;
980848b8605Smrg         target = GL_TEXTURE_1D_ARRAY;
981848b8605Smrg         break;
982848b8605Smrg      case TEXTURE_CUBE_INDEX:
983848b8605Smrg         dims = 2;
984848b8605Smrg         target = GL_TEXTURE_CUBE_MAP;
985848b8605Smrg         numFaces = 6;
986848b8605Smrg         break;
987848b8605Smrg      case TEXTURE_3D_INDEX:
988848b8605Smrg         dims = 3;
989848b8605Smrg         target = GL_TEXTURE_3D;
990848b8605Smrg         break;
991848b8605Smrg      case TEXTURE_RECT_INDEX:
992848b8605Smrg         dims = 2;
993848b8605Smrg         target = GL_TEXTURE_RECTANGLE;
994848b8605Smrg         break;
995848b8605Smrg      case TEXTURE_2D_INDEX:
996848b8605Smrg         dims = 2;
997848b8605Smrg         target = GL_TEXTURE_2D;
998848b8605Smrg         break;
999848b8605Smrg      case TEXTURE_1D_INDEX:
1000848b8605Smrg         dims = 1;
1001848b8605Smrg         target = GL_TEXTURE_1D;
1002848b8605Smrg         break;
1003848b8605Smrg      case TEXTURE_BUFFER_INDEX:
1004848b8605Smrg         dims = 0;
1005848b8605Smrg         target = GL_TEXTURE_BUFFER;
1006848b8605Smrg         break;
1007848b8605Smrg      case TEXTURE_CUBE_ARRAY_INDEX:
1008848b8605Smrg         dims = 3;
1009848b8605Smrg         target = GL_TEXTURE_CUBE_MAP_ARRAY;
1010b8e80941Smrg         depth = 6;
1011848b8605Smrg         break;
1012848b8605Smrg      case TEXTURE_EXTERNAL_INDEX:
1013848b8605Smrg         dims = 2;
1014848b8605Smrg         target = GL_TEXTURE_EXTERNAL_OES;
1015848b8605Smrg         break;
1016848b8605Smrg      case TEXTURE_2D_MULTISAMPLE_INDEX:
1017848b8605Smrg         dims = 2;
1018848b8605Smrg         target = GL_TEXTURE_2D_MULTISAMPLE;
1019848b8605Smrg         break;
1020848b8605Smrg      case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX:
1021848b8605Smrg         dims = 3;
1022848b8605Smrg         target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
1023848b8605Smrg         break;
1024848b8605Smrg      default:
1025848b8605Smrg         /* no-op */
1026848b8605Smrg         return NULL;
1027848b8605Smrg      }
1028848b8605Smrg
1029848b8605Smrg      /* create texture object */
1030848b8605Smrg      texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
1031848b8605Smrg      if (!texObj)
1032848b8605Smrg         return NULL;
1033848b8605Smrg
1034848b8605Smrg      assert(texObj->RefCount == 1);
1035848b8605Smrg      texObj->Sampler.MinFilter = GL_NEAREST;
1036848b8605Smrg      texObj->Sampler.MagFilter = GL_NEAREST;
1037848b8605Smrg
1038848b8605Smrg      texFormat = ctx->Driver.ChooseTextureFormat(ctx, target,
1039848b8605Smrg                                                  GL_RGBA, GL_RGBA,
1040848b8605Smrg                                                  GL_UNSIGNED_BYTE);
1041848b8605Smrg
1042848b8605Smrg      /* need a loop here just for cube maps */
1043848b8605Smrg      for (face = 0; face < numFaces; face++) {
1044b8e80941Smrg         const GLenum faceTarget = _mesa_cube_face_target(target, face);
1045848b8605Smrg
1046848b8605Smrg         /* initialize level[0] texture image */
1047848b8605Smrg         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
1048848b8605Smrg
1049848b8605Smrg         _mesa_init_teximage_fields(ctx, texImage,
1050848b8605Smrg                                    width,
1051848b8605Smrg                                    (dims > 1) ? height : 1,
1052848b8605Smrg                                    (dims > 2) ? depth : 1,
1053848b8605Smrg                                    0, /* border */
1054848b8605Smrg                                    GL_RGBA, texFormat);
1055848b8605Smrg
1056848b8605Smrg         ctx->Driver.TexImage(ctx, dims, texImage,
1057848b8605Smrg                              GL_RGBA, GL_UNSIGNED_BYTE, texel,
1058848b8605Smrg                              &ctx->DefaultPacking);
1059848b8605Smrg      }
1060848b8605Smrg
1061848b8605Smrg      _mesa_test_texobj_completeness(ctx, texObj);
1062848b8605Smrg      assert(texObj->_BaseComplete);
1063848b8605Smrg      assert(texObj->_MipmapComplete);
1064848b8605Smrg
1065848b8605Smrg      ctx->Shared->FallbackTex[tex] = texObj;
1066b8e80941Smrg
1067b8e80941Smrg      /* Complete the driver's operation in case another context will also
1068b8e80941Smrg       * use the same fallback texture. */
1069b8e80941Smrg      if (ctx->Driver.Finish)
1070b8e80941Smrg         ctx->Driver.Finish(ctx);
1071848b8605Smrg   }
1072848b8605Smrg   return ctx->Shared->FallbackTex[tex];
1073848b8605Smrg}
1074848b8605Smrg
1075848b8605Smrg
1076848b8605Smrg/**
1077848b8605Smrg * Compute the size of the given texture object, in bytes.
1078848b8605Smrg */
1079848b8605Smrgstatic GLuint
1080848b8605Smrgtexture_size(const struct gl_texture_object *texObj)
1081848b8605Smrg{
1082848b8605Smrg   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1083848b8605Smrg   GLuint face, level, size = 0;
1084848b8605Smrg
1085848b8605Smrg   for (face = 0; face < numFaces; face++) {
1086848b8605Smrg      for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
1087848b8605Smrg         const struct gl_texture_image *img = texObj->Image[face][level];
1088848b8605Smrg         if (img) {
1089848b8605Smrg            GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
1090848b8605Smrg                                                img->Height, img->Depth);
1091848b8605Smrg            size += sz;
1092848b8605Smrg         }
1093848b8605Smrg      }
1094848b8605Smrg   }
1095848b8605Smrg
1096848b8605Smrg   return size;
1097848b8605Smrg}
1098848b8605Smrg
1099848b8605Smrg
1100848b8605Smrg/**
1101848b8605Smrg * Callback called from _mesa_HashWalk()
1102848b8605Smrg */
1103848b8605Smrgstatic void
1104848b8605Smrgcount_tex_size(GLuint key, void *data, void *userData)
1105848b8605Smrg{
1106848b8605Smrg   const struct gl_texture_object *texObj =
1107848b8605Smrg      (const struct gl_texture_object *) data;
1108848b8605Smrg   GLuint *total = (GLuint *) userData;
1109848b8605Smrg
1110848b8605Smrg   (void) key;
1111848b8605Smrg
1112848b8605Smrg   *total = *total + texture_size(texObj);
1113848b8605Smrg}
1114848b8605Smrg
1115848b8605Smrg
1116848b8605Smrg/**
1117848b8605Smrg * Compute total size (in bytes) of all textures for the given context.
1118848b8605Smrg * For debugging purposes.
1119848b8605Smrg */
1120848b8605SmrgGLuint
1121848b8605Smrg_mesa_total_texture_memory(struct gl_context *ctx)
1122848b8605Smrg{
1123848b8605Smrg   GLuint tgt, total = 0;
1124848b8605Smrg
1125848b8605Smrg   _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total);
1126848b8605Smrg
1127848b8605Smrg   /* plus, the default texture objects */
1128848b8605Smrg   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
1129848b8605Smrg      total += texture_size(ctx->Shared->DefaultTex[tgt]);
1130848b8605Smrg   }
1131848b8605Smrg
1132848b8605Smrg   return total;
1133848b8605Smrg}
1134848b8605Smrg
1135b8e80941Smrg
1136b8e80941Smrg/**
1137b8e80941Smrg * Return the base format for the given texture object by looking
1138b8e80941Smrg * at the base texture image.
1139b8e80941Smrg * \return base format (such as GL_RGBA) or GL_NONE if it can't be determined
1140b8e80941Smrg */
1141b8e80941SmrgGLenum
1142b8e80941Smrg_mesa_texture_base_format(const struct gl_texture_object *texObj)
1143b8e80941Smrg{
1144b8e80941Smrg   const struct gl_texture_image *texImage = _mesa_base_tex_image(texObj);
1145b8e80941Smrg
1146b8e80941Smrg   return texImage ? texImage->_BaseFormat : GL_NONE;
1147b8e80941Smrg}
1148b8e80941Smrg
1149b8e80941Smrg
1150848b8605Smrgstatic struct gl_texture_object *
1151848b8605Smrginvalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture,
1152848b8605Smrg                                 GLint level, const char *name)
1153848b8605Smrg{
1154848b8605Smrg   /* The GL_ARB_invalidate_subdata spec says:
1155848b8605Smrg    *
1156848b8605Smrg    *     "If <texture> is zero or is not the name of a texture, the error
1157848b8605Smrg    *     INVALID_VALUE is generated."
1158848b8605Smrg    *
1159848b8605Smrg    * This performs the error check in a different order than listed in the
1160848b8605Smrg    * spec.  We have to get the texture object before we can validate the
1161848b8605Smrg    * other parameters against values in the texture object.
1162848b8605Smrg    */
1163848b8605Smrg   struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture);
1164848b8605Smrg   if (texture == 0 || t == NULL) {
1165848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name);
1166848b8605Smrg      return NULL;
1167848b8605Smrg   }
1168848b8605Smrg
1169848b8605Smrg   /* The GL_ARB_invalidate_subdata spec says:
1170848b8605Smrg    *
1171848b8605Smrg    *     "If <level> is less than zero or greater than the base 2 logarithm
1172848b8605Smrg    *     of the maximum texture width, height, or depth, the error
1173848b8605Smrg    *     INVALID_VALUE is generated."
1174848b8605Smrg    */
1175848b8605Smrg   if (level < 0 || level > t->MaxLevel) {
1176848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1177848b8605Smrg      return NULL;
1178848b8605Smrg   }
1179848b8605Smrg
1180848b8605Smrg   /* The GL_ARB_invalidate_subdata spec says:
1181848b8605Smrg    *
1182848b8605Smrg    *     "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
1183848b8605Smrg    *     TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
1184848b8605Smrg    *     is not zero, the error INVALID_VALUE is generated."
1185848b8605Smrg    */
1186848b8605Smrg   if (level != 0) {
1187848b8605Smrg      switch (t->Target) {
1188848b8605Smrg      case GL_TEXTURE_RECTANGLE:
1189848b8605Smrg      case GL_TEXTURE_BUFFER:
1190848b8605Smrg      case GL_TEXTURE_2D_MULTISAMPLE:
1191848b8605Smrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1192848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1193848b8605Smrg         return NULL;
1194848b8605Smrg
1195848b8605Smrg      default:
1196848b8605Smrg         break;
1197848b8605Smrg      }
1198848b8605Smrg   }
1199848b8605Smrg
1200848b8605Smrg   return t;
1201848b8605Smrg}
1202848b8605Smrg
1203848b8605Smrg
1204848b8605Smrg/**
1205b8e80941Smrg * Helper function for glCreateTextures and glGenTextures. Need this because
1206b8e80941Smrg * glCreateTextures should throw errors if target = 0. This is not exposed to
1207b8e80941Smrg * the rest of Mesa to encourage Mesa internals to use nameless textures,
1208b8e80941Smrg * which do not require expensive hash lookups.
1209b8e80941Smrg * \param target  either 0 or a valid / error-checked texture target enum
1210b8e80941Smrg */
1211b8e80941Smrgstatic void
1212b8e80941Smrgcreate_textures(struct gl_context *ctx, GLenum target,
1213b8e80941Smrg                GLsizei n, GLuint *textures, const char *caller)
1214848b8605Smrg{
1215848b8605Smrg   GLuint first;
1216848b8605Smrg   GLint i;
1217848b8605Smrg
1218848b8605Smrg   if (!textures)
1219848b8605Smrg      return;
1220848b8605Smrg
1221848b8605Smrg   /*
1222848b8605Smrg    * This must be atomic (generation and allocation of texture IDs)
1223848b8605Smrg    */
1224b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->TexObjects);
1225848b8605Smrg
1226848b8605Smrg   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
1227848b8605Smrg
1228848b8605Smrg   /* Allocate new, empty texture objects */
1229848b8605Smrg   for (i = 0; i < n; i++) {
1230848b8605Smrg      struct gl_texture_object *texObj;
1231848b8605Smrg      GLuint name = first + i;
1232848b8605Smrg      texObj = ctx->Driver.NewTextureObject(ctx, name, target);
1233848b8605Smrg      if (!texObj) {
1234b8e80941Smrg         _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1235b8e80941Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
1236848b8605Smrg         return;
1237848b8605Smrg      }
1238848b8605Smrg
1239848b8605Smrg      /* insert into hash table */
1240b8e80941Smrg      _mesa_HashInsertLocked(ctx->Shared->TexObjects, texObj->Name, texObj);
1241848b8605Smrg
1242848b8605Smrg      textures[i] = name;
1243848b8605Smrg   }
1244848b8605Smrg
1245b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1246b8e80941Smrg}
1247b8e80941Smrg
1248b8e80941Smrg
1249b8e80941Smrgstatic void
1250b8e80941Smrgcreate_textures_err(struct gl_context *ctx, GLenum target,
1251b8e80941Smrg                    GLsizei n, GLuint *textures, const char *caller)
1252b8e80941Smrg{
1253b8e80941Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1254b8e80941Smrg      _mesa_debug(ctx, "%s %d\n", caller, n);
1255b8e80941Smrg
1256b8e80941Smrg   if (n < 0) {
1257b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
1258b8e80941Smrg      return;
1259b8e80941Smrg   }
1260b8e80941Smrg
1261b8e80941Smrg   create_textures(ctx, target, n, textures, caller);
1262b8e80941Smrg}
1263b8e80941Smrg
1264b8e80941Smrg/*@}*/
1265b8e80941Smrg
1266b8e80941Smrg
1267b8e80941Smrg/***********************************************************************/
1268b8e80941Smrg/** \name API functions */
1269b8e80941Smrg/*@{*/
1270b8e80941Smrg
1271b8e80941Smrg
1272b8e80941Smrg/**
1273b8e80941Smrg * Generate texture names.
1274b8e80941Smrg *
1275b8e80941Smrg * \param n number of texture names to be generated.
1276b8e80941Smrg * \param textures an array in which will hold the generated texture names.
1277b8e80941Smrg *
1278b8e80941Smrg * \sa glGenTextures(), glCreateTextures().
1279b8e80941Smrg *
1280b8e80941Smrg * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
1281b8e80941Smrg * IDs which are stored in \p textures.  Corresponding empty texture
1282b8e80941Smrg * objects are also generated.
1283b8e80941Smrg */
1284b8e80941Smrgvoid GLAPIENTRY
1285b8e80941Smrg_mesa_GenTextures_no_error(GLsizei n, GLuint *textures)
1286b8e80941Smrg{
1287b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1288b8e80941Smrg   create_textures(ctx, 0, n, textures, "glGenTextures");
1289848b8605Smrg}
1290848b8605Smrg
1291848b8605Smrg
1292b8e80941Smrgvoid GLAPIENTRY
1293b8e80941Smrg_mesa_GenTextures(GLsizei n, GLuint *textures)
1294b8e80941Smrg{
1295b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1296b8e80941Smrg   create_textures_err(ctx, 0, n, textures, "glGenTextures");
1297b8e80941Smrg}
1298b8e80941Smrg
1299b8e80941Smrg/**
1300b8e80941Smrg * Create texture objects.
1301b8e80941Smrg *
1302b8e80941Smrg * \param target the texture target for each name to be generated.
1303b8e80941Smrg * \param n number of texture names to be generated.
1304b8e80941Smrg * \param textures an array in which will hold the generated texture names.
1305b8e80941Smrg *
1306b8e80941Smrg * \sa glCreateTextures(), glGenTextures().
1307b8e80941Smrg *
1308b8e80941Smrg * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
1309b8e80941Smrg * IDs which are stored in \p textures.  Corresponding empty texture
1310b8e80941Smrg * objects are also generated.
1311b8e80941Smrg */
1312b8e80941Smrgvoid GLAPIENTRY
1313b8e80941Smrg_mesa_CreateTextures_no_error(GLenum target, GLsizei n, GLuint *textures)
1314b8e80941Smrg{
1315b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1316b8e80941Smrg   create_textures(ctx, target, n, textures, "glCreateTextures");
1317b8e80941Smrg}
1318b8e80941Smrg
1319b8e80941Smrg
1320b8e80941Smrgvoid GLAPIENTRY
1321b8e80941Smrg_mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
1322b8e80941Smrg{
1323b8e80941Smrg   GLint targetIndex;
1324b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1325b8e80941Smrg
1326b8e80941Smrg   /*
1327b8e80941Smrg    * The 4.5 core profile spec (30.10.2014) doesn't specify what
1328b8e80941Smrg    * glCreateTextures should do with invalid targets, which was probably an
1329b8e80941Smrg    * oversight.  This conforms to the spec for glBindTexture.
1330b8e80941Smrg    */
1331b8e80941Smrg   targetIndex = _mesa_tex_target_to_index(ctx, target);
1332b8e80941Smrg   if (targetIndex < 0) {
1333b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glCreateTextures(target)");
1334b8e80941Smrg      return;
1335b8e80941Smrg   }
1336b8e80941Smrg
1337b8e80941Smrg   create_textures_err(ctx, target, n, textures, "glCreateTextures");
1338b8e80941Smrg}
1339b8e80941Smrg
1340848b8605Smrg/**
1341848b8605Smrg * Check if the given texture object is bound to the current draw or
1342848b8605Smrg * read framebuffer.  If so, Unbind it.
1343848b8605Smrg */
1344848b8605Smrgstatic void
1345848b8605Smrgunbind_texobj_from_fbo(struct gl_context *ctx,
1346848b8605Smrg                       struct gl_texture_object *texObj)
1347848b8605Smrg{
1348848b8605Smrg   bool progress = false;
1349848b8605Smrg
1350848b8605Smrg   /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection
1351848b8605Smrg    * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec
1352848b8605Smrg    * says:
1353848b8605Smrg    *
1354848b8605Smrg    *     "If a texture object is deleted while its image is attached to one
1355848b8605Smrg    *     or more attachment points in the currently bound framebuffer, then
1356848b8605Smrg    *     it is as if FramebufferTexture* had been called, with a texture of
1357848b8605Smrg    *     zero, for each attachment point to which this image was attached in
1358848b8605Smrg    *     the currently bound framebuffer. In other words, this texture image
1359848b8605Smrg    *     is first detached from all attachment points in the currently bound
1360848b8605Smrg    *     framebuffer. Note that the texture image is specifically not
1361848b8605Smrg    *     detached from any other framebuffer objects. Detaching the texture
1362848b8605Smrg    *     image from any other framebuffer objects is the responsibility of
1363848b8605Smrg    *     the application."
1364848b8605Smrg    */
1365848b8605Smrg   if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1366848b8605Smrg      progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj);
1367848b8605Smrg   }
1368848b8605Smrg   if (_mesa_is_user_fbo(ctx->ReadBuffer)
1369848b8605Smrg       && ctx->ReadBuffer != ctx->DrawBuffer) {
1370848b8605Smrg      progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj)
1371848b8605Smrg         || progress;
1372848b8605Smrg   }
1373848b8605Smrg
1374848b8605Smrg   if (progress)
1375848b8605Smrg      /* Vertices are already flushed by _mesa_DeleteTextures */
1376848b8605Smrg      ctx->NewState |= _NEW_BUFFERS;
1377848b8605Smrg}
1378848b8605Smrg
1379848b8605Smrg
1380848b8605Smrg/**
1381848b8605Smrg * Check if the given texture object is bound to any texture image units and
1382848b8605Smrg * unbind it if so (revert to default textures).
1383848b8605Smrg */
1384848b8605Smrgstatic void
1385848b8605Smrgunbind_texobj_from_texunits(struct gl_context *ctx,
1386848b8605Smrg                            struct gl_texture_object *texObj)
1387848b8605Smrg{
1388848b8605Smrg   const gl_texture_index index = texObj->TargetIndex;
1389848b8605Smrg   GLuint u;
1390848b8605Smrg
1391b8e80941Smrg   if (texObj->Target == 0) {
1392b8e80941Smrg      /* texture was never bound */
1393848b8605Smrg      return;
1394b8e80941Smrg   }
1395b8e80941Smrg
1396b8e80941Smrg   assert(index < NUM_TEXTURE_TARGETS);
1397848b8605Smrg
1398848b8605Smrg   for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) {
1399848b8605Smrg      struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
1400848b8605Smrg
1401848b8605Smrg      if (texObj == unit->CurrentTex[index]) {
1402848b8605Smrg         /* Bind the default texture for this unit/target */
1403848b8605Smrg         _mesa_reference_texobj(&unit->CurrentTex[index],
1404848b8605Smrg                                ctx->Shared->DefaultTex[index]);
1405848b8605Smrg         unit->_BoundTextures &= ~(1 << index);
1406848b8605Smrg      }
1407848b8605Smrg   }
1408848b8605Smrg}
1409848b8605Smrg
1410848b8605Smrg
1411848b8605Smrg/**
1412848b8605Smrg * Check if the given texture object is bound to any shader image unit
1413848b8605Smrg * and unbind it if that's the case.
1414848b8605Smrg */
1415848b8605Smrgstatic void
1416848b8605Smrgunbind_texobj_from_image_units(struct gl_context *ctx,
1417848b8605Smrg                               struct gl_texture_object *texObj)
1418848b8605Smrg{
1419848b8605Smrg   GLuint i;
1420848b8605Smrg
1421848b8605Smrg   for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
1422848b8605Smrg      struct gl_image_unit *unit = &ctx->ImageUnits[i];
1423848b8605Smrg
1424b8e80941Smrg      if (texObj == unit->TexObj) {
1425848b8605Smrg         _mesa_reference_texobj(&unit->TexObj, NULL);
1426b8e80941Smrg         *unit = _mesa_default_image_unit(ctx);
1427b8e80941Smrg      }
1428848b8605Smrg   }
1429848b8605Smrg}
1430848b8605Smrg
1431b8e80941Smrg
1432848b8605Smrg/**
1433848b8605Smrg * Unbinds all textures bound to the given texture image unit.
1434848b8605Smrg */
1435848b8605Smrgstatic void
1436848b8605Smrgunbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
1437848b8605Smrg{
1438848b8605Smrg   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1439848b8605Smrg
1440848b8605Smrg   while (texUnit->_BoundTextures) {
1441848b8605Smrg      const GLuint index = ffs(texUnit->_BoundTextures) - 1;
1442848b8605Smrg      struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
1443848b8605Smrg
1444848b8605Smrg      _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
1445848b8605Smrg
1446848b8605Smrg      /* Pass BindTexture call to device driver */
1447848b8605Smrg      if (ctx->Driver.BindTexture)
1448848b8605Smrg         ctx->Driver.BindTexture(ctx, unit, 0, texObj);
1449848b8605Smrg
1450848b8605Smrg      texUnit->_BoundTextures &= ~(1 << index);
1451b8e80941Smrg      ctx->NewState |= _NEW_TEXTURE_OBJECT;
1452848b8605Smrg   }
1453848b8605Smrg}
1454848b8605Smrg
1455b8e80941Smrg
1456848b8605Smrg/**
1457848b8605Smrg * Delete named textures.
1458848b8605Smrg *
1459848b8605Smrg * \param n number of textures to be deleted.
1460848b8605Smrg * \param textures array of texture IDs to be deleted.
1461848b8605Smrg *
1462848b8605Smrg * \sa glDeleteTextures().
1463848b8605Smrg *
1464848b8605Smrg * If we're about to delete a texture that's currently bound to any
1465848b8605Smrg * texture unit, unbind the texture first.  Decrement the reference
1466848b8605Smrg * count on the texture object and delete it if it's zero.
1467848b8605Smrg * Recall that texture objects can be shared among several rendering
1468848b8605Smrg * contexts.
1469848b8605Smrg */
1470b8e80941Smrgstatic void
1471b8e80941Smrgdelete_textures(struct gl_context *ctx, GLsizei n, const GLuint *textures)
1472848b8605Smrg{
1473848b8605Smrg   FLUSH_VERTICES(ctx, 0); /* too complex */
1474848b8605Smrg
1475848b8605Smrg   if (!textures)
1476848b8605Smrg      return;
1477848b8605Smrg
1478b8e80941Smrg   for (GLsizei i = 0; i < n; i++) {
1479848b8605Smrg      if (textures[i] > 0) {
1480848b8605Smrg         struct gl_texture_object *delObj
1481848b8605Smrg            = _mesa_lookup_texture(ctx, textures[i]);
1482848b8605Smrg
1483848b8605Smrg         if (delObj) {
1484848b8605Smrg            _mesa_lock_texture(ctx, delObj);
1485848b8605Smrg
1486848b8605Smrg            /* Check if texture is bound to any framebuffer objects.
1487848b8605Smrg             * If so, unbind.
1488848b8605Smrg             * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1489848b8605Smrg             */
1490848b8605Smrg            unbind_texobj_from_fbo(ctx, delObj);
1491848b8605Smrg
1492848b8605Smrg            /* Check if this texture is currently bound to any texture units.
1493848b8605Smrg             * If so, unbind it.
1494848b8605Smrg             */
1495848b8605Smrg            unbind_texobj_from_texunits(ctx, delObj);
1496848b8605Smrg
1497848b8605Smrg            /* Check if this texture is currently bound to any shader
1498848b8605Smrg             * image unit.  If so, unbind it.
1499848b8605Smrg             * See section 3.9.X of GL_ARB_shader_image_load_store.
1500848b8605Smrg             */
1501848b8605Smrg            unbind_texobj_from_image_units(ctx, delObj);
1502848b8605Smrg
1503b8e80941Smrg            /* Make all handles that reference this texture object non-resident
1504b8e80941Smrg             * in the current context.
1505b8e80941Smrg             */
1506b8e80941Smrg            _mesa_make_texture_handles_non_resident(ctx, delObj);
1507b8e80941Smrg
1508848b8605Smrg            _mesa_unlock_texture(ctx, delObj);
1509848b8605Smrg
1510b8e80941Smrg            ctx->NewState |= _NEW_TEXTURE_OBJECT;
1511848b8605Smrg
1512848b8605Smrg            /* The texture _name_ is now free for re-use.
1513848b8605Smrg             * Remove it from the hash table now.
1514848b8605Smrg             */
1515848b8605Smrg            _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
1516848b8605Smrg
1517848b8605Smrg            /* Unreference the texobj.  If refcount hits zero, the texture
1518848b8605Smrg             * will be deleted.
1519848b8605Smrg             */
1520848b8605Smrg            _mesa_reference_texobj(&delObj, NULL);
1521848b8605Smrg         }
1522848b8605Smrg      }
1523848b8605Smrg   }
1524848b8605Smrg}
1525848b8605Smrg
1526b8e80941Smrg/**
1527b8e80941Smrg * This deletes a texObj without altering the hash table.
1528b8e80941Smrg */
1529b8e80941Smrgvoid
1530b8e80941Smrg_mesa_delete_nameless_texture(struct gl_context *ctx,
1531b8e80941Smrg                              struct gl_texture_object *texObj)
1532b8e80941Smrg{
1533b8e80941Smrg   if (!texObj)
1534b8e80941Smrg      return;
1535b8e80941Smrg
1536b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
1537b8e80941Smrg
1538b8e80941Smrg   _mesa_lock_texture(ctx, texObj);
1539b8e80941Smrg   {
1540b8e80941Smrg      /* Check if texture is bound to any framebuffer objects.
1541b8e80941Smrg       * If so, unbind.
1542b8e80941Smrg       * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1543b8e80941Smrg       */
1544b8e80941Smrg      unbind_texobj_from_fbo(ctx, texObj);
1545b8e80941Smrg
1546b8e80941Smrg      /* Check if this texture is currently bound to any texture units.
1547b8e80941Smrg       * If so, unbind it.
1548b8e80941Smrg       */
1549b8e80941Smrg      unbind_texobj_from_texunits(ctx, texObj);
1550b8e80941Smrg
1551b8e80941Smrg      /* Check if this texture is currently bound to any shader
1552b8e80941Smrg       * image unit.  If so, unbind it.
1553b8e80941Smrg       * See section 3.9.X of GL_ARB_shader_image_load_store.
1554b8e80941Smrg       */
1555b8e80941Smrg      unbind_texobj_from_image_units(ctx, texObj);
1556b8e80941Smrg   }
1557b8e80941Smrg   _mesa_unlock_texture(ctx, texObj);
1558b8e80941Smrg
1559b8e80941Smrg   ctx->NewState |= _NEW_TEXTURE_OBJECT;
1560b8e80941Smrg
1561b8e80941Smrg   /* Unreference the texobj.  If refcount hits zero, the texture
1562b8e80941Smrg    * will be deleted.
1563b8e80941Smrg    */
1564b8e80941Smrg   _mesa_reference_texobj(&texObj, NULL);
1565b8e80941Smrg}
1566b8e80941Smrg
1567b8e80941Smrg
1568b8e80941Smrgvoid GLAPIENTRY
1569b8e80941Smrg_mesa_DeleteTextures_no_error(GLsizei n, const GLuint *textures)
1570b8e80941Smrg{
1571b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1572b8e80941Smrg   delete_textures(ctx, n, textures);
1573b8e80941Smrg}
1574b8e80941Smrg
1575b8e80941Smrg
1576b8e80941Smrgvoid GLAPIENTRY
1577b8e80941Smrg_mesa_DeleteTextures(GLsizei n, const GLuint *textures)
1578b8e80941Smrg{
1579b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1580b8e80941Smrg
1581b8e80941Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1582b8e80941Smrg      _mesa_debug(ctx, "glDeleteTextures %d\n", n);
1583b8e80941Smrg
1584b8e80941Smrg   if (n < 0) {
1585b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTextures(n < 0)");
1586b8e80941Smrg      return;
1587b8e80941Smrg   }
1588b8e80941Smrg
1589b8e80941Smrg   delete_textures(ctx, n, textures);
1590b8e80941Smrg}
1591b8e80941Smrg
1592848b8605Smrg
1593848b8605Smrg/**
1594848b8605Smrg * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
1595848b8605Smrg * into the corresponding Mesa texture target index.
1596848b8605Smrg * Note that proxy targets are not valid here.
1597848b8605Smrg * \return TEXTURE_x_INDEX or -1 if target is invalid
1598848b8605Smrg */
1599848b8605Smrgint
1600848b8605Smrg_mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target)
1601848b8605Smrg{
1602848b8605Smrg   switch (target) {
1603848b8605Smrg   case GL_TEXTURE_1D:
1604848b8605Smrg      return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1;
1605848b8605Smrg   case GL_TEXTURE_2D:
1606848b8605Smrg      return TEXTURE_2D_INDEX;
1607848b8605Smrg   case GL_TEXTURE_3D:
1608848b8605Smrg      return ctx->API != API_OPENGLES ? TEXTURE_3D_INDEX : -1;
1609848b8605Smrg   case GL_TEXTURE_CUBE_MAP:
1610848b8605Smrg      return ctx->Extensions.ARB_texture_cube_map
1611848b8605Smrg         ? TEXTURE_CUBE_INDEX : -1;
1612848b8605Smrg   case GL_TEXTURE_RECTANGLE:
1613848b8605Smrg      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle
1614848b8605Smrg         ? TEXTURE_RECT_INDEX : -1;
1615848b8605Smrg   case GL_TEXTURE_1D_ARRAY:
1616848b8605Smrg      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array
1617848b8605Smrg         ? TEXTURE_1D_ARRAY_INDEX : -1;
1618848b8605Smrg   case GL_TEXTURE_2D_ARRAY:
1619848b8605Smrg      return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1620848b8605Smrg         || _mesa_is_gles3(ctx)
1621848b8605Smrg         ? TEXTURE_2D_ARRAY_INDEX : -1;
1622848b8605Smrg   case GL_TEXTURE_BUFFER:
1623b8e80941Smrg      return (_mesa_has_ARB_texture_buffer_object(ctx) ||
1624b8e80941Smrg              _mesa_has_OES_texture_buffer(ctx)) ?
1625848b8605Smrg             TEXTURE_BUFFER_INDEX : -1;
1626848b8605Smrg   case GL_TEXTURE_EXTERNAL_OES:
1627848b8605Smrg      return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
1628848b8605Smrg         ? TEXTURE_EXTERNAL_INDEX : -1;
1629848b8605Smrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
1630b8e80941Smrg      return _mesa_has_texture_cube_map_array(ctx)
1631848b8605Smrg         ? TEXTURE_CUBE_ARRAY_INDEX : -1;
1632848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE:
1633b8e80941Smrg      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) ||
1634b8e80941Smrg              _mesa_is_gles31(ctx)) ? TEXTURE_2D_MULTISAMPLE_INDEX: -1;
1635848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1636b8e80941Smrg      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) ||
1637b8e80941Smrg              _mesa_is_gles31(ctx))
1638848b8605Smrg         ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1;
1639848b8605Smrg   default:
1640848b8605Smrg      return -1;
1641848b8605Smrg   }
1642848b8605Smrg}
1643848b8605Smrg
1644848b8605Smrg
1645848b8605Smrg/**
1646b8e80941Smrg * Do actual texture binding.  All error checking should have been done prior
1647b8e80941Smrg * to calling this function.  Note that the texture target (1D, 2D, etc) is
1648b8e80941Smrg * always specified by the texObj->TargetIndex.
1649b8e80941Smrg *
1650b8e80941Smrg * \param unit  index of texture unit to update
1651b8e80941Smrg * \param texObj  the new texture object (cannot be NULL)
1652b8e80941Smrg */
1653b8e80941Smrgstatic void
1654b8e80941Smrgbind_texture_object(struct gl_context *ctx, unsigned unit,
1655b8e80941Smrg                    struct gl_texture_object *texObj)
1656b8e80941Smrg{
1657b8e80941Smrg   struct gl_texture_unit *texUnit;
1658b8e80941Smrg   int targetIndex;
1659b8e80941Smrg
1660b8e80941Smrg   assert(unit < ARRAY_SIZE(ctx->Texture.Unit));
1661b8e80941Smrg   texUnit = &ctx->Texture.Unit[unit];
1662b8e80941Smrg
1663b8e80941Smrg   assert(texObj);
1664b8e80941Smrg   assert(valid_texture_object(texObj));
1665b8e80941Smrg
1666b8e80941Smrg   targetIndex = texObj->TargetIndex;
1667b8e80941Smrg   assert(targetIndex >= 0);
1668b8e80941Smrg   assert(targetIndex < NUM_TEXTURE_TARGETS);
1669b8e80941Smrg
1670b8e80941Smrg   /* Check if this texture is only used by this context and is already bound.
1671b8e80941Smrg    * If so, just return. For GL_OES_image_external, rebinding the texture
1672b8e80941Smrg    * always must invalidate cached resources.
1673b8e80941Smrg    */
1674b8e80941Smrg   if (targetIndex != TEXTURE_EXTERNAL_INDEX) {
1675b8e80941Smrg      bool early_out;
1676b8e80941Smrg      simple_mtx_lock(&ctx->Shared->Mutex);
1677b8e80941Smrg      early_out = ((ctx->Shared->RefCount == 1)
1678b8e80941Smrg                   && (texObj == texUnit->CurrentTex[targetIndex]));
1679b8e80941Smrg      simple_mtx_unlock(&ctx->Shared->Mutex);
1680b8e80941Smrg      if (early_out) {
1681b8e80941Smrg         return;
1682b8e80941Smrg      }
1683b8e80941Smrg   }
1684b8e80941Smrg
1685b8e80941Smrg   /* flush before changing binding */
1686b8e80941Smrg   FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
1687b8e80941Smrg
1688b8e80941Smrg   /* If the refcount on the previously bound texture is decremented to
1689b8e80941Smrg    * zero, it'll be deleted here.
1690b8e80941Smrg    */
1691b8e80941Smrg   _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], texObj);
1692b8e80941Smrg
1693b8e80941Smrg   ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1694b8e80941Smrg                                         unit + 1);
1695b8e80941Smrg
1696b8e80941Smrg   if (texObj->Name != 0)
1697b8e80941Smrg      texUnit->_BoundTextures |= (1 << targetIndex);
1698b8e80941Smrg   else
1699b8e80941Smrg      texUnit->_BoundTextures &= ~(1 << targetIndex);
1700b8e80941Smrg
1701b8e80941Smrg   /* Pass BindTexture call to device driver */
1702b8e80941Smrg   if (ctx->Driver.BindTexture) {
1703b8e80941Smrg      ctx->Driver.BindTexture(ctx, unit, texObj->Target, texObj);
1704b8e80941Smrg   }
1705b8e80941Smrg}
1706b8e80941Smrg
1707b8e80941Smrg/**
1708b8e80941Smrg * Light-weight bind texture for internal users
1709b8e80941Smrg *
1710b8e80941Smrg * This is really just \c finish_texture_init plus \c bind_texture_object.
1711b8e80941Smrg * This is intended to be used by internal Mesa functions that use
1712b8e80941Smrg * \c _mesa_CreateTexture and need to bind textures (e.g., meta).
1713b8e80941Smrg */
1714b8e80941Smrgvoid
1715b8e80941Smrg_mesa_bind_texture(struct gl_context *ctx, GLenum target,
1716b8e80941Smrg                   struct gl_texture_object *tex_obj)
1717b8e80941Smrg{
1718b8e80941Smrg   const GLint targetIndex = _mesa_tex_target_to_index(ctx, target);
1719b8e80941Smrg
1720b8e80941Smrg   assert(targetIndex >= 0 && targetIndex < NUM_TEXTURE_TARGETS);
1721b8e80941Smrg
1722b8e80941Smrg   if (tex_obj->Target == 0)
1723b8e80941Smrg      finish_texture_init(ctx, target, tex_obj, targetIndex);
1724b8e80941Smrg
1725b8e80941Smrg   assert(tex_obj->Target == target);
1726b8e80941Smrg   assert(tex_obj->TargetIndex == targetIndex);
1727b8e80941Smrg
1728b8e80941Smrg   bind_texture_object(ctx, ctx->Texture.CurrentUnit, tex_obj);
1729b8e80941Smrg}
1730b8e80941Smrg
1731b8e80941Smrg/**
1732b8e80941Smrg * Implement glBindTexture().  Do error checking, look-up or create a new
1733b8e80941Smrg * texture object, then bind it in the current texture unit.
1734b8e80941Smrg *
1735848b8605Smrg * \param target texture target.
1736848b8605Smrg * \param texName texture name.
1737848b8605Smrg */
1738b8e80941Smrgstatic ALWAYS_INLINE void
1739b8e80941Smrgbind_texture(struct gl_context *ctx, GLenum target, GLuint texName,
1740b8e80941Smrg             bool no_error)
1741848b8605Smrg{
1742848b8605Smrg   struct gl_texture_object *newTexObj = NULL;
1743b8e80941Smrg   int targetIndex;
1744848b8605Smrg
1745848b8605Smrg   targetIndex = _mesa_tex_target_to_index(ctx, target);
1746b8e80941Smrg   if (!no_error && targetIndex < 0) {
1747b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target = %s)",
1748b8e80941Smrg                  _mesa_enum_to_string(target));
1749848b8605Smrg      return;
1750848b8605Smrg   }
1751848b8605Smrg   assert(targetIndex < NUM_TEXTURE_TARGETS);
1752848b8605Smrg
1753848b8605Smrg   /*
1754848b8605Smrg    * Get pointer to new texture object (newTexObj)
1755848b8605Smrg    */
1756848b8605Smrg   if (texName == 0) {
1757848b8605Smrg      /* Use a default texture object */
1758848b8605Smrg      newTexObj = ctx->Shared->DefaultTex[targetIndex];
1759b8e80941Smrg   } else {
1760848b8605Smrg      /* non-default texture object */
1761848b8605Smrg      newTexObj = _mesa_lookup_texture(ctx, texName);
1762848b8605Smrg      if (newTexObj) {
1763848b8605Smrg         /* error checking */
1764b8e80941Smrg         if (!no_error &&
1765b8e80941Smrg             newTexObj->Target != 0 && newTexObj->Target != target) {
1766b8e80941Smrg            /* The named texture object's target doesn't match the
1767b8e80941Smrg             * given target
1768b8e80941Smrg             */
1769848b8605Smrg            _mesa_error( ctx, GL_INVALID_OPERATION,
1770848b8605Smrg                         "glBindTexture(target mismatch)" );
1771848b8605Smrg            return;
1772848b8605Smrg         }
1773848b8605Smrg         if (newTexObj->Target == 0) {
1774b8e80941Smrg            finish_texture_init(ctx, target, newTexObj, targetIndex);
1775848b8605Smrg         }
1776848b8605Smrg      }
1777848b8605Smrg      else {
1778b8e80941Smrg         if (!no_error && ctx->API == API_OPENGL_CORE) {
1779b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
1780b8e80941Smrg                        "glBindTexture(non-gen name)");
1781848b8605Smrg            return;
1782848b8605Smrg         }
1783848b8605Smrg
1784848b8605Smrg         /* if this is a new texture id, allocate a texture object now */
1785848b8605Smrg         newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
1786848b8605Smrg         if (!newTexObj) {
1787848b8605Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
1788848b8605Smrg            return;
1789848b8605Smrg         }
1790848b8605Smrg
1791848b8605Smrg         /* and insert it into hash table */
1792848b8605Smrg         _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
1793848b8605Smrg      }
1794848b8605Smrg   }
1795848b8605Smrg
1796b8e80941Smrg   assert(newTexObj->Target == target);
1797b8e80941Smrg   assert(newTexObj->TargetIndex == targetIndex);
1798848b8605Smrg
1799b8e80941Smrg   bind_texture_object(ctx, ctx->Texture.CurrentUnit, newTexObj);
1800b8e80941Smrg}
1801b8e80941Smrg
1802b8e80941Smrgvoid GLAPIENTRY
1803b8e80941Smrg_mesa_BindTexture_no_error(GLenum target, GLuint texName)
1804b8e80941Smrg{
1805b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1806b8e80941Smrg   bind_texture(ctx, target, texName, true);
1807b8e80941Smrg}
1808b8e80941Smrg
1809b8e80941Smrg
1810b8e80941Smrgvoid GLAPIENTRY
1811b8e80941Smrg_mesa_BindTexture(GLenum target, GLuint texName)
1812b8e80941Smrg{
1813b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1814b8e80941Smrg
1815b8e80941Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1816b8e80941Smrg      _mesa_debug(ctx, "glBindTexture %s %d\n",
1817b8e80941Smrg                  _mesa_enum_to_string(target), (GLint) texName);
1818b8e80941Smrg
1819b8e80941Smrg   bind_texture(ctx, target, texName, false);
1820b8e80941Smrg}
1821b8e80941Smrg
1822b8e80941Smrg
1823b8e80941Smrg/**
1824b8e80941Smrg * OpenGL 4.5 / GL_ARB_direct_state_access glBindTextureUnit().
1825b8e80941Smrg *
1826b8e80941Smrg * \param unit texture unit.
1827b8e80941Smrg * \param texture texture name.
1828b8e80941Smrg *
1829b8e80941Smrg * \sa glBindTexture().
1830b8e80941Smrg *
1831b8e80941Smrg * If the named texture is 0, this will reset each target for the specified
1832b8e80941Smrg * texture unit to its default texture.
1833b8e80941Smrg * If the named texture is not 0 or a recognized texture name, this throws
1834b8e80941Smrg * GL_INVALID_OPERATION.
1835b8e80941Smrg */
1836b8e80941Smrgstatic ALWAYS_INLINE void
1837b8e80941Smrgbind_texture_unit(struct gl_context *ctx, GLuint unit, GLuint texture,
1838b8e80941Smrg                  bool no_error)
1839b8e80941Smrg{
1840b8e80941Smrg   struct gl_texture_object *texObj;
1841b8e80941Smrg
1842b8e80941Smrg   /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
1843b8e80941Smrg    * (20141030) says:
1844b8e80941Smrg    *    "When texture is zero, each of the targets enumerated at the
1845b8e80941Smrg    *    beginning of this section is reset to its default texture for the
1846b8e80941Smrg    *    corresponding texture image unit."
1847848b8605Smrg    */
1848b8e80941Smrg   if (texture == 0) {
1849b8e80941Smrg      unbind_textures_from_unit(ctx, unit);
1850b8e80941Smrg      return;
1851b8e80941Smrg   }
1852b8e80941Smrg
1853b8e80941Smrg   /* Get the non-default texture object */
1854b8e80941Smrg   texObj = _mesa_lookup_texture(ctx, texture);
1855b8e80941Smrg   if (!no_error) {
1856b8e80941Smrg      /* Error checking */
1857b8e80941Smrg      if (!texObj) {
1858b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1859b8e80941Smrg                     "glBindTextureUnit(non-gen name)");
1860b8e80941Smrg         return;
1861b8e80941Smrg      }
1862b8e80941Smrg
1863b8e80941Smrg      if (texObj->Target == 0) {
1864b8e80941Smrg         /* Texture object was gen'd but never bound so the target is not set */
1865b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTextureUnit(target)");
1866848b8605Smrg         return;
1867848b8605Smrg      }
1868848b8605Smrg   }
1869848b8605Smrg
1870b8e80941Smrg   assert(valid_texture_object(texObj));
1871848b8605Smrg
1872b8e80941Smrg   bind_texture_object(ctx, unit, texObj);
1873b8e80941Smrg}
1874848b8605Smrg
1875848b8605Smrg
1876b8e80941Smrgvoid GLAPIENTRY
1877b8e80941Smrg_mesa_BindTextureUnit_no_error(GLuint unit, GLuint texture)
1878b8e80941Smrg{
1879b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1880b8e80941Smrg   bind_texture_unit(ctx, unit, texture, true);
1881848b8605Smrg}
1882848b8605Smrg
1883848b8605Smrg
1884848b8605Smrgvoid GLAPIENTRY
1885b8e80941Smrg_mesa_BindTextureUnit(GLuint unit, GLuint texture)
1886848b8605Smrg{
1887848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1888848b8605Smrg
1889b8e80941Smrg   if (unit >= _mesa_max_tex_unit(ctx)) {
1890b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindTextureUnit(unit=%u)", unit);
1891848b8605Smrg      return;
1892848b8605Smrg   }
1893848b8605Smrg
1894b8e80941Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1895b8e80941Smrg      _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
1896b8e80941Smrg                  _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture);
1897848b8605Smrg
1898b8e80941Smrg   bind_texture_unit(ctx, unit, texture, false);
1899b8e80941Smrg}
1900b8e80941Smrg
1901b8e80941Smrg
1902b8e80941Smrg/**
1903b8e80941Smrg * OpenGL 4.4 / GL_ARB_multi_bind glBindTextures().
1904b8e80941Smrg */
1905b8e80941Smrgstatic ALWAYS_INLINE void
1906b8e80941Smrgbind_textures(struct gl_context *ctx, GLuint first, GLsizei count,
1907b8e80941Smrg              const GLuint *textures, bool no_error)
1908b8e80941Smrg{
1909b8e80941Smrg   GLsizei i;
1910848b8605Smrg
1911848b8605Smrg   if (textures) {
1912848b8605Smrg      /* Note that the error semantics for multi-bind commands differ from
1913848b8605Smrg       * those of other GL commands.
1914848b8605Smrg       *
1915848b8605Smrg       * The issues section in the ARB_multi_bind spec says:
1916848b8605Smrg       *
1917848b8605Smrg       *    "(11) Typically, OpenGL specifies that if an error is generated by
1918848b8605Smrg       *          a command, that command has no effect.  This is somewhat
1919848b8605Smrg       *          unfortunate for multi-bind commands, because it would require
1920848b8605Smrg       *          a first pass to scan the entire list of bound objects for
1921848b8605Smrg       *          errors and then a second pass to actually perform the
1922848b8605Smrg       *          bindings.  Should we have different error semantics?
1923848b8605Smrg       *
1924848b8605Smrg       *       RESOLVED:  Yes.  In this specification, when the parameters for
1925848b8605Smrg       *       one of the <count> binding points are invalid, that binding
1926848b8605Smrg       *       point is not updated and an error will be generated.  However,
1927848b8605Smrg       *       other binding points in the same command will be updated if
1928848b8605Smrg       *       their parameters are valid and no other error occurs."
1929848b8605Smrg       */
1930848b8605Smrg
1931b8e80941Smrg      _mesa_HashLockMutex(ctx->Shared->TexObjects);
1932848b8605Smrg
1933848b8605Smrg      for (i = 0; i < count; i++) {
1934848b8605Smrg         if (textures[i] != 0) {
1935848b8605Smrg            struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
1936848b8605Smrg            struct gl_texture_object *current = texUnit->_Current;
1937848b8605Smrg            struct gl_texture_object *texObj;
1938848b8605Smrg
1939848b8605Smrg            if (current && current->Name == textures[i])
1940848b8605Smrg               texObj = current;
1941848b8605Smrg            else
1942848b8605Smrg               texObj = _mesa_lookup_texture_locked(ctx, textures[i]);
1943848b8605Smrg
1944848b8605Smrg            if (texObj && texObj->Target != 0) {
1945b8e80941Smrg               bind_texture_object(ctx, first + i, texObj);
1946b8e80941Smrg            } else if (!no_error) {
1947848b8605Smrg               /* The ARB_multi_bind spec says:
1948848b8605Smrg                *
1949848b8605Smrg                *     "An INVALID_OPERATION error is generated if any value
1950848b8605Smrg                *      in <textures> is not zero or the name of an existing
1951848b8605Smrg                *      texture object (per binding)."
1952848b8605Smrg                */
1953848b8605Smrg               _mesa_error(ctx, GL_INVALID_OPERATION,
1954848b8605Smrg                           "glBindTextures(textures[%d]=%u is not zero "
1955848b8605Smrg                           "or the name of an existing texture object)",
1956848b8605Smrg                           i, textures[i]);
1957848b8605Smrg            }
1958848b8605Smrg         } else {
1959848b8605Smrg            unbind_textures_from_unit(ctx, first + i);
1960848b8605Smrg         }
1961848b8605Smrg      }
1962848b8605Smrg
1963b8e80941Smrg      _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1964848b8605Smrg   } else {
1965848b8605Smrg      /* Unbind all textures in the range <first> through <first>+<count>-1 */
1966848b8605Smrg      for (i = 0; i < count; i++)
1967848b8605Smrg         unbind_textures_from_unit(ctx, first + i);
1968848b8605Smrg   }
1969848b8605Smrg}
1970848b8605Smrg
1971848b8605Smrg
1972b8e80941Smrgvoid GLAPIENTRY
1973b8e80941Smrg_mesa_BindTextures_no_error(GLuint first, GLsizei count, const GLuint *textures)
1974b8e80941Smrg{
1975b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1976b8e80941Smrg   bind_textures(ctx, first, count, textures, true);
1977b8e80941Smrg}
1978b8e80941Smrg
1979b8e80941Smrg
1980b8e80941Smrgvoid GLAPIENTRY
1981b8e80941Smrg_mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
1982b8e80941Smrg{
1983b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1984b8e80941Smrg
1985b8e80941Smrg   /* The ARB_multi_bind spec says:
1986b8e80941Smrg    *
1987b8e80941Smrg    *     "An INVALID_OPERATION error is generated if <first> + <count>
1988b8e80941Smrg    *      is greater than the number of texture image units supported
1989b8e80941Smrg    *      by the implementation."
1990b8e80941Smrg    */
1991b8e80941Smrg   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
1992b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1993b8e80941Smrg                  "glBindTextures(first=%u + count=%d > the value of "
1994b8e80941Smrg                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
1995b8e80941Smrg                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
1996b8e80941Smrg      return;
1997b8e80941Smrg   }
1998b8e80941Smrg
1999b8e80941Smrg   bind_textures(ctx, first, count, textures, false);
2000b8e80941Smrg}
2001b8e80941Smrg
2002b8e80941Smrg
2003848b8605Smrg/**
2004848b8605Smrg * Set texture priorities.
2005b8e80941Smrg *
2006848b8605Smrg * \param n number of textures.
2007848b8605Smrg * \param texName texture names.
2008848b8605Smrg * \param priorities corresponding texture priorities.
2009b8e80941Smrg *
2010848b8605Smrg * \sa glPrioritizeTextures().
2011b8e80941Smrg *
2012848b8605Smrg * Looks up each texture in the hash, clamps the corresponding priority between
2013848b8605Smrg * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
2014848b8605Smrg */
2015848b8605Smrgvoid GLAPIENTRY
2016848b8605Smrg_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
2017848b8605Smrg                          const GLclampf *priorities )
2018848b8605Smrg{
2019848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2020848b8605Smrg   GLint i;
2021848b8605Smrg
2022848b8605Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2023848b8605Smrg      _mesa_debug(ctx, "glPrioritizeTextures %d\n", n);
2024848b8605Smrg
2025848b8605Smrg   FLUSH_VERTICES(ctx, 0);
2026848b8605Smrg
2027848b8605Smrg   if (n < 0) {
2028848b8605Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
2029848b8605Smrg      return;
2030848b8605Smrg   }
2031848b8605Smrg
2032848b8605Smrg   if (!priorities)
2033848b8605Smrg      return;
2034848b8605Smrg
2035848b8605Smrg   for (i = 0; i < n; i++) {
2036848b8605Smrg      if (texName[i] > 0) {
2037848b8605Smrg         struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
2038848b8605Smrg         if (t) {
2039848b8605Smrg            t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
2040848b8605Smrg         }
2041848b8605Smrg      }
2042848b8605Smrg   }
2043848b8605Smrg
2044b8e80941Smrg   ctx->NewState |= _NEW_TEXTURE_OBJECT;
2045848b8605Smrg}
2046848b8605Smrg
2047848b8605Smrg
2048848b8605Smrg
2049848b8605Smrg/**
2050848b8605Smrg * See if textures are loaded in texture memory.
2051b8e80941Smrg *
2052848b8605Smrg * \param n number of textures to query.
2053848b8605Smrg * \param texName array with the texture names.
2054848b8605Smrg * \param residences array which will hold the residence status.
2055848b8605Smrg *
2056b8e80941Smrg * \return GL_TRUE if all textures are resident and
2057b8e80941Smrg *                 residences is left unchanged,
2058b8e80941Smrg *
2059848b8605Smrg * Note: we assume all textures are always resident
2060848b8605Smrg */
2061848b8605SmrgGLboolean GLAPIENTRY
2062848b8605Smrg_mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
2063848b8605Smrg                          GLboolean *residences)
2064848b8605Smrg{
2065848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2066848b8605Smrg   GLboolean allResident = GL_TRUE;
2067848b8605Smrg   GLint i;
2068848b8605Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2069848b8605Smrg
2070848b8605Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2071848b8605Smrg      _mesa_debug(ctx, "glAreTexturesResident %d\n", n);
2072848b8605Smrg
2073848b8605Smrg   if (n < 0) {
2074848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
2075848b8605Smrg      return GL_FALSE;
2076848b8605Smrg   }
2077848b8605Smrg
2078848b8605Smrg   if (!texName || !residences)
2079848b8605Smrg      return GL_FALSE;
2080848b8605Smrg
2081848b8605Smrg   /* We only do error checking on the texture names */
2082848b8605Smrg   for (i = 0; i < n; i++) {
2083848b8605Smrg      struct gl_texture_object *t;
2084848b8605Smrg      if (texName[i] == 0) {
2085848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
2086848b8605Smrg         return GL_FALSE;
2087848b8605Smrg      }
2088848b8605Smrg      t = _mesa_lookup_texture(ctx, texName[i]);
2089848b8605Smrg      if (!t) {
2090848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
2091848b8605Smrg         return GL_FALSE;
2092848b8605Smrg      }
2093848b8605Smrg   }
2094b8e80941Smrg
2095848b8605Smrg   return allResident;
2096848b8605Smrg}
2097848b8605Smrg
2098848b8605Smrg
2099848b8605Smrg/**
2100848b8605Smrg * See if a name corresponds to a texture.
2101848b8605Smrg *
2102848b8605Smrg * \param texture texture name.
2103848b8605Smrg *
2104848b8605Smrg * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
2105848b8605Smrg * otherwise.
2106b8e80941Smrg *
2107848b8605Smrg * \sa glIsTexture().
2108848b8605Smrg *
2109848b8605Smrg * Calls _mesa_HashLookup().
2110848b8605Smrg */
2111848b8605SmrgGLboolean GLAPIENTRY
2112848b8605Smrg_mesa_IsTexture( GLuint texture )
2113848b8605Smrg{
2114848b8605Smrg   struct gl_texture_object *t;
2115848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2116848b8605Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2117848b8605Smrg
2118848b8605Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2119848b8605Smrg      _mesa_debug(ctx, "glIsTexture %d\n", texture);
2120848b8605Smrg
2121848b8605Smrg   if (!texture)
2122848b8605Smrg      return GL_FALSE;
2123848b8605Smrg
2124848b8605Smrg   t = _mesa_lookup_texture(ctx, texture);
2125848b8605Smrg
2126848b8605Smrg   /* IsTexture is true only after object has been bound once. */
2127848b8605Smrg   return t && t->Target;
2128848b8605Smrg}
2129848b8605Smrg
2130848b8605Smrg
2131848b8605Smrg/**
2132848b8605Smrg * Simplest implementation of texture locking: grab the shared tex
2133848b8605Smrg * mutex.  Examine the shared context state timestamp and if there has
2134848b8605Smrg * been a change, set the appropriate bits in ctx->NewState.
2135848b8605Smrg *
2136848b8605Smrg * This is used to deal with synchronizing things when a texture object
2137848b8605Smrg * is used/modified by different contexts (or threads) which are sharing
2138848b8605Smrg * the texture.
2139848b8605Smrg *
2140848b8605Smrg * See also _mesa_lock/unlock_texture() in teximage.h
2141848b8605Smrg */
2142848b8605Smrgvoid
2143848b8605Smrg_mesa_lock_context_textures( struct gl_context *ctx )
2144848b8605Smrg{
2145848b8605Smrg   mtx_lock(&ctx->Shared->TexMutex);
2146848b8605Smrg
2147848b8605Smrg   if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
2148b8e80941Smrg      ctx->NewState |= _NEW_TEXTURE_OBJECT;
2149848b8605Smrg      ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
2150848b8605Smrg   }
2151848b8605Smrg}
2152848b8605Smrg
2153848b8605Smrg
2154848b8605Smrgvoid
2155848b8605Smrg_mesa_unlock_context_textures( struct gl_context *ctx )
2156848b8605Smrg{
2157848b8605Smrg   assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
2158848b8605Smrg   mtx_unlock(&ctx->Shared->TexMutex);
2159848b8605Smrg}
2160848b8605Smrg
2161b8e80941Smrg
2162b8e80941Smrgvoid GLAPIENTRY
2163b8e80941Smrg_mesa_InvalidateTexSubImage_no_error(GLuint texture, GLint level, GLint xoffset,
2164b8e80941Smrg                                     GLint yoffset, GLint zoffset,
2165b8e80941Smrg                                     GLsizei width, GLsizei height,
2166b8e80941Smrg                                     GLsizei depth)
2167b8e80941Smrg{
2168b8e80941Smrg   /* no-op */
2169b8e80941Smrg}
2170b8e80941Smrg
2171b8e80941Smrg
2172848b8605Smrgvoid GLAPIENTRY
2173848b8605Smrg_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
2174848b8605Smrg                            GLint yoffset, GLint zoffset, GLsizei width,
2175848b8605Smrg                            GLsizei height, GLsizei depth)
2176848b8605Smrg{
2177848b8605Smrg   struct gl_texture_object *t;
2178848b8605Smrg   struct gl_texture_image *image;
2179848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2180848b8605Smrg
2181848b8605Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2182848b8605Smrg      _mesa_debug(ctx, "glInvalidateTexSubImage %d\n", texture);
2183848b8605Smrg
2184848b8605Smrg   t = invalidate_tex_image_error_check(ctx, texture, level,
2185848b8605Smrg                                        "glInvalidateTexSubImage");
2186848b8605Smrg
2187848b8605Smrg   /* The GL_ARB_invalidate_subdata spec says:
2188848b8605Smrg    *
2189848b8605Smrg    *     "...the specified subregion must be between -<b> and <dim>+<b> where
2190848b8605Smrg    *     <dim> is the size of the dimension of the texture image, and <b> is
2191848b8605Smrg    *     the size of the border of that texture image, otherwise
2192848b8605Smrg    *     INVALID_VALUE is generated (border is not applied to dimensions that
2193848b8605Smrg    *     don't exist in a given texture target)."
2194848b8605Smrg    */
2195848b8605Smrg   image = t->Image[0][level];
2196848b8605Smrg   if (image) {
2197848b8605Smrg      int xBorder;
2198848b8605Smrg      int yBorder;
2199848b8605Smrg      int zBorder;
2200848b8605Smrg      int imageWidth;
2201848b8605Smrg      int imageHeight;
2202848b8605Smrg      int imageDepth;
2203848b8605Smrg
2204848b8605Smrg      /* The GL_ARB_invalidate_subdata spec says:
2205848b8605Smrg       *
2206848b8605Smrg       *     "For texture targets that don't have certain dimensions, this
2207848b8605Smrg       *     command treats those dimensions as having a size of 1. For
2208848b8605Smrg       *     example, to invalidate a portion of a two-dimensional texture,
2209848b8605Smrg       *     the application would use <zoffset> equal to zero and <depth>
2210848b8605Smrg       *     equal to one."
2211848b8605Smrg       */
2212848b8605Smrg      switch (t->Target) {
2213848b8605Smrg      case GL_TEXTURE_BUFFER:
2214848b8605Smrg         xBorder = 0;
2215848b8605Smrg         yBorder = 0;
2216848b8605Smrg         zBorder = 0;
2217848b8605Smrg         imageWidth = 1;
2218848b8605Smrg         imageHeight = 1;
2219848b8605Smrg         imageDepth = 1;
2220848b8605Smrg         break;
2221848b8605Smrg      case GL_TEXTURE_1D:
2222848b8605Smrg         xBorder = image->Border;
2223848b8605Smrg         yBorder = 0;
2224848b8605Smrg         zBorder = 0;
2225848b8605Smrg         imageWidth = image->Width;
2226848b8605Smrg         imageHeight = 1;
2227848b8605Smrg         imageDepth = 1;
2228848b8605Smrg         break;
2229848b8605Smrg      case GL_TEXTURE_1D_ARRAY:
2230848b8605Smrg         xBorder = image->Border;
2231848b8605Smrg         yBorder = 0;
2232848b8605Smrg         zBorder = 0;
2233848b8605Smrg         imageWidth = image->Width;
2234848b8605Smrg         imageHeight = image->Height;
2235848b8605Smrg         imageDepth = 1;
2236848b8605Smrg         break;
2237848b8605Smrg      case GL_TEXTURE_2D:
2238848b8605Smrg      case GL_TEXTURE_CUBE_MAP:
2239848b8605Smrg      case GL_TEXTURE_RECTANGLE:
2240848b8605Smrg      case GL_TEXTURE_2D_MULTISAMPLE:
2241848b8605Smrg         xBorder = image->Border;
2242848b8605Smrg         yBorder = image->Border;
2243848b8605Smrg         zBorder = 0;
2244848b8605Smrg         imageWidth = image->Width;
2245848b8605Smrg         imageHeight = image->Height;
2246848b8605Smrg         imageDepth = 1;
2247848b8605Smrg         break;
2248848b8605Smrg      case GL_TEXTURE_2D_ARRAY:
2249848b8605Smrg      case GL_TEXTURE_CUBE_MAP_ARRAY:
2250848b8605Smrg      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2251848b8605Smrg         xBorder = image->Border;
2252848b8605Smrg         yBorder = image->Border;
2253848b8605Smrg         zBorder = 0;
2254848b8605Smrg         imageWidth = image->Width;
2255848b8605Smrg         imageHeight = image->Height;
2256848b8605Smrg         imageDepth = image->Depth;
2257848b8605Smrg         break;
2258848b8605Smrg      case GL_TEXTURE_3D:
2259848b8605Smrg         xBorder = image->Border;
2260848b8605Smrg         yBorder = image->Border;
2261848b8605Smrg         zBorder = image->Border;
2262848b8605Smrg         imageWidth = image->Width;
2263848b8605Smrg         imageHeight = image->Height;
2264848b8605Smrg         imageDepth = image->Depth;
2265848b8605Smrg         break;
2266848b8605Smrg      default:
2267848b8605Smrg         assert(!"Should not get here.");
2268848b8605Smrg         xBorder = 0;
2269848b8605Smrg         yBorder = 0;
2270848b8605Smrg         zBorder = 0;
2271848b8605Smrg         imageWidth = 0;
2272848b8605Smrg         imageHeight = 0;
2273848b8605Smrg         imageDepth = 0;
2274848b8605Smrg         break;
2275848b8605Smrg      }
2276848b8605Smrg
2277848b8605Smrg      if (xoffset < -xBorder) {
2278848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)");
2279848b8605Smrg         return;
2280848b8605Smrg      }
2281848b8605Smrg
2282848b8605Smrg      if (xoffset + width > imageWidth + xBorder) {
2283848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
2284848b8605Smrg                     "glInvalidateSubTexImage(xoffset+width)");
2285848b8605Smrg         return;
2286848b8605Smrg      }
2287848b8605Smrg
2288848b8605Smrg      if (yoffset < -yBorder) {
2289848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)");
2290848b8605Smrg         return;
2291848b8605Smrg      }
2292848b8605Smrg
2293848b8605Smrg      if (yoffset + height > imageHeight + yBorder) {
2294848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
2295848b8605Smrg                     "glInvalidateSubTexImage(yoffset+height)");
2296848b8605Smrg         return;
2297848b8605Smrg      }
2298848b8605Smrg
2299848b8605Smrg      if (zoffset < -zBorder) {
2300848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
2301848b8605Smrg                     "glInvalidateSubTexImage(zoffset)");
2302848b8605Smrg         return;
2303848b8605Smrg      }
2304848b8605Smrg
2305848b8605Smrg      if (zoffset + depth  > imageDepth + zBorder) {
2306848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
2307848b8605Smrg                     "glInvalidateSubTexImage(zoffset+depth)");
2308848b8605Smrg         return;
2309848b8605Smrg      }
2310848b8605Smrg   }
2311848b8605Smrg
2312848b8605Smrg   /* We don't actually do anything for this yet.  Just return after
2313848b8605Smrg    * validating the parameters and generating the required errors.
2314848b8605Smrg    */
2315848b8605Smrg   return;
2316848b8605Smrg}
2317848b8605Smrg
2318b8e80941Smrg
2319b8e80941Smrgvoid GLAPIENTRY
2320b8e80941Smrg_mesa_InvalidateTexImage_no_error(GLuint texture, GLint level)
2321b8e80941Smrg{
2322b8e80941Smrg   /* no-op */
2323b8e80941Smrg}
2324b8e80941Smrg
2325b8e80941Smrg
2326848b8605Smrgvoid GLAPIENTRY
2327848b8605Smrg_mesa_InvalidateTexImage(GLuint texture, GLint level)
2328848b8605Smrg{
2329848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2330848b8605Smrg
2331848b8605Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2332848b8605Smrg      _mesa_debug(ctx, "glInvalidateTexImage(%d, %d)\n", texture, level);
2333848b8605Smrg
2334848b8605Smrg   invalidate_tex_image_error_check(ctx, texture, level,
2335848b8605Smrg                                    "glInvalidateTexImage");
2336848b8605Smrg
2337848b8605Smrg   /* We don't actually do anything for this yet.  Just return after
2338848b8605Smrg    * validating the parameters and generating the required errors.
2339848b8605Smrg    */
2340848b8605Smrg   return;
2341848b8605Smrg}
2342848b8605Smrg
2343848b8605Smrg/*@}*/
2344