1bf215546Sopenharmony_ci/**
2bf215546Sopenharmony_ci * \file texobj.c
3bf215546Sopenharmony_ci * Texture object management.
4bf215546Sopenharmony_ci */
5bf215546Sopenharmony_ci
6bf215546Sopenharmony_ci/*
7bf215546Sopenharmony_ci * Mesa 3-D graphics library
8bf215546Sopenharmony_ci *
9bf215546Sopenharmony_ci * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
12bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
13bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
14bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
16bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
19bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
20bf215546Sopenharmony_ci *
21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
28bf215546Sopenharmony_ci */
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include <stdio.h>
32bf215546Sopenharmony_ci#include "bufferobj.h"
33bf215546Sopenharmony_ci#include "context.h"
34bf215546Sopenharmony_ci#include "enums.h"
35bf215546Sopenharmony_ci#include "fbobject.h"
36bf215546Sopenharmony_ci#include "formats.h"
37bf215546Sopenharmony_ci#include "hash.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "macros.h"
40bf215546Sopenharmony_ci#include "shaderimage.h"
41bf215546Sopenharmony_ci#include "teximage.h"
42bf215546Sopenharmony_ci#include "texobj.h"
43bf215546Sopenharmony_ci#include "texstate.h"
44bf215546Sopenharmony_ci#include "mtypes.h"
45bf215546Sopenharmony_ci#include "program/prog_instruction.h"
46bf215546Sopenharmony_ci#include "texturebindless.h"
47bf215546Sopenharmony_ci#include "util/u_memory.h"
48bf215546Sopenharmony_ci#include "util/u_inlines.h"
49bf215546Sopenharmony_ci#include "api_exec_decl.h"
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#include "state_tracker/st_cb_texture.h"
52bf215546Sopenharmony_ci#include "state_tracker/st_context.h"
53bf215546Sopenharmony_ci#include "state_tracker/st_format.h"
54bf215546Sopenharmony_ci#include "state_tracker/st_cb_flush.h"
55bf215546Sopenharmony_ci#include "state_tracker/st_texture.h"
56bf215546Sopenharmony_ci#include "state_tracker/st_sampler_view.h"
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci/**********************************************************************/
59bf215546Sopenharmony_ci/** \name Internal functions */
60bf215546Sopenharmony_ci/*@{*/
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci/**
63bf215546Sopenharmony_ci * This function checks for all valid combinations of Min and Mag filters for
64bf215546Sopenharmony_ci * Float types, when extensions like OES_texture_float and
65bf215546Sopenharmony_ci * OES_texture_float_linear are supported. OES_texture_float mentions support
66bf215546Sopenharmony_ci * for NEAREST, NEAREST_MIPMAP_NEAREST magnification and minification filters.
67bf215546Sopenharmony_ci * Mag filters like LINEAR and min filters like NEAREST_MIPMAP_LINEAR,
68bf215546Sopenharmony_ci * LINEAR_MIPMAP_NEAREST and LINEAR_MIPMAP_LINEAR are only valid in case
69bf215546Sopenharmony_ci * OES_texture_float_linear is supported.
70bf215546Sopenharmony_ci *
71bf215546Sopenharmony_ci * Returns true in case the filter is valid for given Float type else false.
72bf215546Sopenharmony_ci */
73bf215546Sopenharmony_cistatic bool
74bf215546Sopenharmony_civalid_filter_for_float(const struct gl_context *ctx,
75bf215546Sopenharmony_ci                       const struct gl_texture_object *obj)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   switch (obj->Sampler.Attrib.MagFilter) {
78bf215546Sopenharmony_ci   case GL_LINEAR:
79bf215546Sopenharmony_ci      if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) {
80bf215546Sopenharmony_ci         return false;
81bf215546Sopenharmony_ci      } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) {
82bf215546Sopenharmony_ci         return false;
83bf215546Sopenharmony_ci      }
84bf215546Sopenharmony_ci      FALLTHROUGH;
85bf215546Sopenharmony_ci   case GL_NEAREST:
86bf215546Sopenharmony_ci   case GL_NEAREST_MIPMAP_NEAREST:
87bf215546Sopenharmony_ci      break;
88bf215546Sopenharmony_ci   default:
89bf215546Sopenharmony_ci      unreachable("Invalid mag filter");
90bf215546Sopenharmony_ci   }
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   switch (obj->Sampler.Attrib.MinFilter) {
93bf215546Sopenharmony_ci   case GL_LINEAR:
94bf215546Sopenharmony_ci   case GL_NEAREST_MIPMAP_LINEAR:
95bf215546Sopenharmony_ci   case GL_LINEAR_MIPMAP_NEAREST:
96bf215546Sopenharmony_ci   case GL_LINEAR_MIPMAP_LINEAR:
97bf215546Sopenharmony_ci      if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) {
98bf215546Sopenharmony_ci         return false;
99bf215546Sopenharmony_ci      } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) {
100bf215546Sopenharmony_ci         return false;
101bf215546Sopenharmony_ci      }
102bf215546Sopenharmony_ci      FALLTHROUGH;
103bf215546Sopenharmony_ci   case GL_NEAREST:
104bf215546Sopenharmony_ci   case GL_NEAREST_MIPMAP_NEAREST:
105bf215546Sopenharmony_ci      break;
106bf215546Sopenharmony_ci   default:
107bf215546Sopenharmony_ci      unreachable("Invalid min filter");
108bf215546Sopenharmony_ci   }
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   return true;
111bf215546Sopenharmony_ci}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci/**
114bf215546Sopenharmony_ci * Return the gl_texture_object for a given ID.
115bf215546Sopenharmony_ci */
116bf215546Sopenharmony_cistruct gl_texture_object *
117bf215546Sopenharmony_ci_mesa_lookup_texture(struct gl_context *ctx, GLuint id)
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   return (struct gl_texture_object *)
120bf215546Sopenharmony_ci      _mesa_HashLookup(ctx->Shared->TexObjects, id);
121bf215546Sopenharmony_ci}
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci/**
124bf215546Sopenharmony_ci * Wrapper around _mesa_lookup_texture that throws GL_INVALID_OPERATION if id
125bf215546Sopenharmony_ci * is not in the hash table. After calling _mesa_error, it returns NULL.
126bf215546Sopenharmony_ci */
127bf215546Sopenharmony_cistruct gl_texture_object *
128bf215546Sopenharmony_ci_mesa_lookup_texture_err(struct gl_context *ctx, GLuint id, const char* func)
129bf215546Sopenharmony_ci{
130bf215546Sopenharmony_ci   struct gl_texture_object *texObj = NULL;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   if (id > 0)
133bf215546Sopenharmony_ci      texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   if (!texObj)
136bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture)", func);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   return texObj;
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_cistruct gl_texture_object *
143bf215546Sopenharmony_ci_mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id)
144bf215546Sopenharmony_ci{
145bf215546Sopenharmony_ci   return (struct gl_texture_object *)
146bf215546Sopenharmony_ci      _mesa_HashLookupLocked(ctx->Shared->TexObjects, id);
147bf215546Sopenharmony_ci}
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci/**
150bf215546Sopenharmony_ci * Return a pointer to the current texture object for the given target
151bf215546Sopenharmony_ci * on the current texture unit.
152bf215546Sopenharmony_ci * Note: all <target> error checking should have been done by this point.
153bf215546Sopenharmony_ci */
154bf215546Sopenharmony_cistruct gl_texture_object *
155bf215546Sopenharmony_ci_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
156bf215546Sopenharmony_ci{
157bf215546Sopenharmony_ci   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
158bf215546Sopenharmony_ci   const GLboolean arrayTex = ctx->Extensions.EXT_texture_array;
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   switch (target) {
161bf215546Sopenharmony_ci      case GL_TEXTURE_1D:
162bf215546Sopenharmony_ci         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
163bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_1D:
164bf215546Sopenharmony_ci         return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
165bf215546Sopenharmony_ci      case GL_TEXTURE_2D:
166bf215546Sopenharmony_ci         return texUnit->CurrentTex[TEXTURE_2D_INDEX];
167bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_2D:
168bf215546Sopenharmony_ci         return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
169bf215546Sopenharmony_ci      case GL_TEXTURE_3D:
170bf215546Sopenharmony_ci         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
171bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_3D:
172bf215546Sopenharmony_ci         return !(ctx->API == API_OPENGLES2 && !ctx->Extensions.OES_texture_3D)
173bf215546Sopenharmony_ci             ? ctx->Texture.ProxyTex[TEXTURE_3D_INDEX] : NULL;
174bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
175bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
176bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
177bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
178bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
179bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
180bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP:
181bf215546Sopenharmony_ci         return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
182bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_CUBE_MAP:
183bf215546Sopenharmony_ci         return ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX];
184bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_ARRAY:
185bf215546Sopenharmony_ci         return _mesa_has_texture_cube_map_array(ctx)
186bf215546Sopenharmony_ci                ? texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
187bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
188bf215546Sopenharmony_ci         return _mesa_has_texture_cube_map_array(ctx)
189bf215546Sopenharmony_ci                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
190bf215546Sopenharmony_ci      case GL_TEXTURE_RECTANGLE_NV:
191bf215546Sopenharmony_ci         return ctx->Extensions.NV_texture_rectangle
192bf215546Sopenharmony_ci                ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
193bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_RECTANGLE_NV:
194bf215546Sopenharmony_ci         return ctx->Extensions.NV_texture_rectangle
195bf215546Sopenharmony_ci                ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
196bf215546Sopenharmony_ci      case GL_TEXTURE_1D_ARRAY_EXT:
197bf215546Sopenharmony_ci         return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
198bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
199bf215546Sopenharmony_ci         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
200bf215546Sopenharmony_ci      case GL_TEXTURE_2D_ARRAY_EXT:
201bf215546Sopenharmony_ci         return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
202bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
203bf215546Sopenharmony_ci         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
204bf215546Sopenharmony_ci      case GL_TEXTURE_BUFFER:
205bf215546Sopenharmony_ci         return (_mesa_has_ARB_texture_buffer_object(ctx) ||
206bf215546Sopenharmony_ci                 _mesa_has_OES_texture_buffer(ctx)) ?
207bf215546Sopenharmony_ci                texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
208bf215546Sopenharmony_ci      case GL_TEXTURE_EXTERNAL_OES:
209bf215546Sopenharmony_ci         return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
210bf215546Sopenharmony_ci            ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
211bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE:
212bf215546Sopenharmony_ci         return ctx->Extensions.ARB_texture_multisample
213bf215546Sopenharmony_ci            ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
214bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
215bf215546Sopenharmony_ci         return ctx->Extensions.ARB_texture_multisample
216bf215546Sopenharmony_ci            ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
217bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
218bf215546Sopenharmony_ci         return ctx->Extensions.ARB_texture_multisample
219bf215546Sopenharmony_ci            ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
220bf215546Sopenharmony_ci      case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
221bf215546Sopenharmony_ci         return ctx->Extensions.ARB_texture_multisample
222bf215546Sopenharmony_ci            ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
223bf215546Sopenharmony_ci      default:
224bf215546Sopenharmony_ci         _mesa_problem(NULL, "bad target in _mesa_get_current_tex_object(): 0x%04x", target);
225bf215546Sopenharmony_ci         return NULL;
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci}
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci/**
231bf215546Sopenharmony_ci * Get the texture object for given target and texunit
232bf215546Sopenharmony_ci * Proxy targets are accepted only allowProxyTarget is true.
233bf215546Sopenharmony_ci * Return NULL if any error (and record the error).
234bf215546Sopenharmony_ci */
235bf215546Sopenharmony_cistruct gl_texture_object *
236bf215546Sopenharmony_ci_mesa_get_texobj_by_target_and_texunit(struct gl_context *ctx, GLenum target,
237bf215546Sopenharmony_ci                                       GLuint texunit, bool allowProxyTarget,
238bf215546Sopenharmony_ci                                       const char* caller)
239bf215546Sopenharmony_ci{
240bf215546Sopenharmony_ci   struct gl_texture_unit *texUnit;
241bf215546Sopenharmony_ci   int targetIndex;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   if (_mesa_is_proxy_texture(target) && allowProxyTarget) {
244bf215546Sopenharmony_ci      return _mesa_get_current_tex_object(ctx, target);
245bf215546Sopenharmony_ci   }
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   if (texunit >= ctx->Const.MaxCombinedTextureImageUnits) {
248bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
249bf215546Sopenharmony_ci                  "%s(texunit=%d)", caller, texunit);
250bf215546Sopenharmony_ci      return NULL;
251bf215546Sopenharmony_ci   }
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   texUnit = _mesa_get_tex_unit(ctx, texunit);
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   targetIndex = _mesa_tex_target_to_index(ctx, target);
256bf215546Sopenharmony_ci   if (targetIndex < 0 || targetIndex == TEXTURE_BUFFER_INDEX) {
257bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
258bf215546Sopenharmony_ci      return NULL;
259bf215546Sopenharmony_ci   }
260bf215546Sopenharmony_ci   assert(targetIndex < NUM_TEXTURE_TARGETS);
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci   return texUnit->CurrentTex[targetIndex];
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci/**
267bf215546Sopenharmony_ci * Initialize a new texture object to default values.
268bf215546Sopenharmony_ci * \param obj  the texture object
269bf215546Sopenharmony_ci * \param name  the texture name
270bf215546Sopenharmony_ci * \param target  the texture target
271bf215546Sopenharmony_ci */
272bf215546Sopenharmony_cistatic bool
273bf215546Sopenharmony_ci_mesa_initialize_texture_object( struct gl_context *ctx,
274bf215546Sopenharmony_ci                                 struct gl_texture_object *obj,
275bf215546Sopenharmony_ci                                 GLuint name, GLenum target )
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   assert(target == 0 ||
278bf215546Sopenharmony_ci          target == GL_TEXTURE_1D ||
279bf215546Sopenharmony_ci          target == GL_TEXTURE_2D ||
280bf215546Sopenharmony_ci          target == GL_TEXTURE_3D ||
281bf215546Sopenharmony_ci          target == GL_TEXTURE_CUBE_MAP ||
282bf215546Sopenharmony_ci          target == GL_TEXTURE_RECTANGLE_NV ||
283bf215546Sopenharmony_ci          target == GL_TEXTURE_1D_ARRAY_EXT ||
284bf215546Sopenharmony_ci          target == GL_TEXTURE_2D_ARRAY_EXT ||
285bf215546Sopenharmony_ci          target == GL_TEXTURE_EXTERNAL_OES ||
286bf215546Sopenharmony_ci          target == GL_TEXTURE_CUBE_MAP_ARRAY ||
287bf215546Sopenharmony_ci          target == GL_TEXTURE_BUFFER ||
288bf215546Sopenharmony_ci          target == GL_TEXTURE_2D_MULTISAMPLE ||
289bf215546Sopenharmony_ci          target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   memset(obj, 0, sizeof(*obj));
292bf215546Sopenharmony_ci   /* init the non-zero fields */
293bf215546Sopenharmony_ci   obj->RefCount = 1;
294bf215546Sopenharmony_ci   obj->Name = name;
295bf215546Sopenharmony_ci   obj->Target = target;
296bf215546Sopenharmony_ci   if (target != 0) {
297bf215546Sopenharmony_ci      obj->TargetIndex = _mesa_tex_target_to_index(ctx, target);
298bf215546Sopenharmony_ci   }
299bf215546Sopenharmony_ci   else {
300bf215546Sopenharmony_ci      obj->TargetIndex = NUM_TEXTURE_TARGETS; /* invalid/error value */
301bf215546Sopenharmony_ci   }
302bf215546Sopenharmony_ci   obj->Attrib.Priority = 1.0F;
303bf215546Sopenharmony_ci   obj->Attrib.BaseLevel = 0;
304bf215546Sopenharmony_ci   obj->Attrib.MaxLevel = 1000;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   /* must be one; no support for (YUV) planes in separate buffers */
307bf215546Sopenharmony_ci   obj->RequiredTextureImageUnits = 1;
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   /* sampler state */
310bf215546Sopenharmony_ci   if (target == GL_TEXTURE_RECTANGLE_NV ||
311bf215546Sopenharmony_ci       target == GL_TEXTURE_EXTERNAL_OES) {
312bf215546Sopenharmony_ci      obj->Sampler.Attrib.WrapS = GL_CLAMP_TO_EDGE;
313bf215546Sopenharmony_ci      obj->Sampler.Attrib.WrapT = GL_CLAMP_TO_EDGE;
314bf215546Sopenharmony_ci      obj->Sampler.Attrib.WrapR = GL_CLAMP_TO_EDGE;
315bf215546Sopenharmony_ci      obj->Sampler.Attrib.MinFilter = GL_LINEAR;
316bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
317bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
318bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
319bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.min_img_filter = PIPE_TEX_FILTER_LINEAR;
320bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
321bf215546Sopenharmony_ci   }
322bf215546Sopenharmony_ci   else {
323bf215546Sopenharmony_ci      obj->Sampler.Attrib.WrapS = GL_REPEAT;
324bf215546Sopenharmony_ci      obj->Sampler.Attrib.WrapT = GL_REPEAT;
325bf215546Sopenharmony_ci      obj->Sampler.Attrib.WrapR = GL_REPEAT;
326bf215546Sopenharmony_ci      obj->Sampler.Attrib.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
327bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.wrap_s = PIPE_TEX_WRAP_REPEAT;
328bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.wrap_t = PIPE_TEX_WRAP_REPEAT;
329bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.wrap_r = PIPE_TEX_WRAP_REPEAT;
330bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.min_img_filter = PIPE_TEX_FILTER_NEAREST;
331bf215546Sopenharmony_ci      obj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
332bf215546Sopenharmony_ci   }
333bf215546Sopenharmony_ci   obj->Sampler.Attrib.MagFilter = GL_LINEAR;
334bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
335bf215546Sopenharmony_ci   obj->Sampler.Attrib.MinLod = -1000.0;
336bf215546Sopenharmony_ci   obj->Sampler.Attrib.MaxLod = 1000.0;
337bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.min_lod = 0; /* no negative numbers */
338bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.max_lod = 1000;
339bf215546Sopenharmony_ci   obj->Sampler.Attrib.LodBias = 0.0;
340bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.lod_bias = 0;
341bf215546Sopenharmony_ci   obj->Sampler.Attrib.MaxAnisotropy = 1.0;
342bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.max_anisotropy = 0; /* gallium sets 0 instead of 1 */
343bf215546Sopenharmony_ci   obj->Sampler.Attrib.CompareMode = GL_NONE;         /* ARB_shadow */
344bf215546Sopenharmony_ci   obj->Sampler.Attrib.CompareFunc = GL_LEQUAL;       /* ARB_shadow */
345bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.compare_mode = PIPE_TEX_COMPARE_NONE;
346bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.compare_func = PIPE_FUNC_LEQUAL;
347bf215546Sopenharmony_ci   obj->Attrib.DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
348bf215546Sopenharmony_ci   obj->StencilSampling = false;
349bf215546Sopenharmony_ci   obj->Sampler.Attrib.CubeMapSeamless = GL_FALSE;
350bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.seamless_cube_map = false;
351bf215546Sopenharmony_ci   obj->Sampler.HandleAllocated = GL_FALSE;
352bf215546Sopenharmony_ci   obj->Attrib.Swizzle[0] = GL_RED;
353bf215546Sopenharmony_ci   obj->Attrib.Swizzle[1] = GL_GREEN;
354bf215546Sopenharmony_ci   obj->Attrib.Swizzle[2] = GL_BLUE;
355bf215546Sopenharmony_ci   obj->Attrib.Swizzle[3] = GL_ALPHA;
356bf215546Sopenharmony_ci   obj->Attrib._Swizzle = SWIZZLE_NOOP;
357bf215546Sopenharmony_ci   obj->Sampler.Attrib.sRGBDecode = GL_DECODE_EXT;
358bf215546Sopenharmony_ci   obj->Sampler.Attrib.ReductionMode = GL_WEIGHTED_AVERAGE_EXT;
359bf215546Sopenharmony_ci   obj->Sampler.Attrib.state.reduction_mode = PIPE_TEX_REDUCTION_WEIGHTED_AVERAGE;
360bf215546Sopenharmony_ci   obj->BufferObjectFormat = ctx->API == API_OPENGL_COMPAT ? GL_LUMINANCE8 : GL_R8;
361bf215546Sopenharmony_ci   obj->_BufferObjectFormat = ctx->API == API_OPENGL_COMPAT
362bf215546Sopenharmony_ci      ? MESA_FORMAT_L_UNORM8 : MESA_FORMAT_R_UNORM8;
363bf215546Sopenharmony_ci   obj->Attrib.ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   /* GL_ARB_bindless_texture */
366bf215546Sopenharmony_ci   _mesa_init_texture_handles(obj);
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   obj->level_override = -1;
369bf215546Sopenharmony_ci   obj->layer_override = -1;
370bf215546Sopenharmony_ci   simple_mtx_init(&obj->validate_mutex, mtx_plain);
371bf215546Sopenharmony_ci   obj->needs_validation = true;
372bf215546Sopenharmony_ci   /* Pre-allocate a sampler views container to save a branch in the
373bf215546Sopenharmony_ci    * fast path.
374bf215546Sopenharmony_ci    */
375bf215546Sopenharmony_ci   obj->sampler_views = calloc(1, sizeof(struct st_sampler_views)
376bf215546Sopenharmony_ci                               + sizeof(struct st_sampler_view));
377bf215546Sopenharmony_ci   if (!obj->sampler_views) {
378bf215546Sopenharmony_ci      return false;
379bf215546Sopenharmony_ci   }
380bf215546Sopenharmony_ci   obj->sampler_views->max = 1;
381bf215546Sopenharmony_ci   return true;
382bf215546Sopenharmony_ci}
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci/**
385bf215546Sopenharmony_ci * Allocate and initialize a new texture object.  But don't put it into the
386bf215546Sopenharmony_ci * texture object hash table.
387bf215546Sopenharmony_ci *
388bf215546Sopenharmony_ci * \param shared the shared GL state structure to contain the texture object
389bf215546Sopenharmony_ci * \param name integer name for the texture object
390bf215546Sopenharmony_ci * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
391bf215546Sopenharmony_ci * GL_TEXTURE_CUBE_MAP or GL_TEXTURE_RECTANGLE_NV.  zero is ok for the sake
392bf215546Sopenharmony_ci * of GenTextures()
393bf215546Sopenharmony_ci *
394bf215546Sopenharmony_ci * \return pointer to new texture object.
395bf215546Sopenharmony_ci */
396bf215546Sopenharmony_cistruct gl_texture_object *
397bf215546Sopenharmony_ci_mesa_new_texture_object(struct gl_context *ctx, GLuint name, GLenum target)
398bf215546Sopenharmony_ci{
399bf215546Sopenharmony_ci   struct gl_texture_object *obj;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   obj = MALLOC_STRUCT(gl_texture_object);
402bf215546Sopenharmony_ci   if (!obj)
403bf215546Sopenharmony_ci      return NULL;
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   if (!_mesa_initialize_texture_object(ctx, obj, name, target)) {
406bf215546Sopenharmony_ci      free(obj);
407bf215546Sopenharmony_ci      return NULL;
408bf215546Sopenharmony_ci   }
409bf215546Sopenharmony_ci   return obj;
410bf215546Sopenharmony_ci}
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci/**
413bf215546Sopenharmony_ci * Some texture initialization can't be finished until we know which
414bf215546Sopenharmony_ci * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
415bf215546Sopenharmony_ci */
416bf215546Sopenharmony_cistatic void
417bf215546Sopenharmony_cifinish_texture_init(struct gl_context *ctx, GLenum target,
418bf215546Sopenharmony_ci                    struct gl_texture_object *obj, int targetIndex)
419bf215546Sopenharmony_ci{
420bf215546Sopenharmony_ci   GLenum filter = GL_LINEAR;
421bf215546Sopenharmony_ci   assert(obj->Target == 0);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci   obj->Target = target;
424bf215546Sopenharmony_ci   obj->TargetIndex = targetIndex;
425bf215546Sopenharmony_ci   assert(obj->TargetIndex < NUM_TEXTURE_TARGETS);
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci   switch (target) {
428bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE:
429bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
430bf215546Sopenharmony_ci         filter = GL_NEAREST;
431bf215546Sopenharmony_ci         FALLTHROUGH;
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci      case GL_TEXTURE_RECTANGLE_NV:
434bf215546Sopenharmony_ci      case GL_TEXTURE_EXTERNAL_OES:
435bf215546Sopenharmony_ci         /* have to init wrap and filter state here - kind of klunky */
436bf215546Sopenharmony_ci         obj->Sampler.Attrib.WrapS = GL_CLAMP_TO_EDGE;
437bf215546Sopenharmony_ci         obj->Sampler.Attrib.WrapT = GL_CLAMP_TO_EDGE;
438bf215546Sopenharmony_ci         obj->Sampler.Attrib.WrapR = GL_CLAMP_TO_EDGE;
439bf215546Sopenharmony_ci         obj->Sampler.Attrib.state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
440bf215546Sopenharmony_ci         obj->Sampler.Attrib.state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
441bf215546Sopenharmony_ci         obj->Sampler.Attrib.state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
442bf215546Sopenharmony_ci         obj->Sampler.Attrib.MinFilter = filter;
443bf215546Sopenharmony_ci         obj->Sampler.Attrib.MagFilter = filter;
444bf215546Sopenharmony_ci         obj->Sampler.Attrib.state.min_img_filter = filter_to_gallium(filter);
445bf215546Sopenharmony_ci         obj->Sampler.Attrib.state.min_mip_filter = mipfilter_to_gallium(filter);
446bf215546Sopenharmony_ci         obj->Sampler.Attrib.state.mag_img_filter = filter_to_gallium(filter);
447bf215546Sopenharmony_ci         break;
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci      default:
450bf215546Sopenharmony_ci         /* nothing needs done */
451bf215546Sopenharmony_ci         break;
452bf215546Sopenharmony_ci   }
453bf215546Sopenharmony_ci}
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci/**
457bf215546Sopenharmony_ci * Deallocate a texture object struct.  It should have already been
458bf215546Sopenharmony_ci * removed from the texture object pool.
459bf215546Sopenharmony_ci *
460bf215546Sopenharmony_ci * \param shared the shared GL state to which the object belongs.
461bf215546Sopenharmony_ci * \param texObj the texture object to delete.
462bf215546Sopenharmony_ci */
463bf215546Sopenharmony_civoid
464bf215546Sopenharmony_ci_mesa_delete_texture_object(struct gl_context *ctx,
465bf215546Sopenharmony_ci                            struct gl_texture_object *texObj)
466bf215546Sopenharmony_ci{
467bf215546Sopenharmony_ci   GLuint i, face;
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci   /* Set Target to an invalid value.  With some assertions elsewhere
470bf215546Sopenharmony_ci    * we can try to detect possible use of deleted textures.
471bf215546Sopenharmony_ci    */
472bf215546Sopenharmony_ci   texObj->Target = 0x99;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   pipe_resource_reference(&texObj->pt, NULL);
475bf215546Sopenharmony_ci   st_delete_texture_sampler_views(ctx->st, texObj);
476bf215546Sopenharmony_ci   simple_mtx_destroy(&texObj->validate_mutex);
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci   /* free the texture images */
479bf215546Sopenharmony_ci   for (face = 0; face < 6; face++) {
480bf215546Sopenharmony_ci      for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
481bf215546Sopenharmony_ci         if (texObj->Image[face][i]) {
482bf215546Sopenharmony_ci            _mesa_delete_texture_image(ctx, texObj->Image[face][i]);
483bf215546Sopenharmony_ci         }
484bf215546Sopenharmony_ci      }
485bf215546Sopenharmony_ci   }
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   /* Delete all texture/image handles. */
488bf215546Sopenharmony_ci   _mesa_delete_texture_handles(ctx, texObj);
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci   _mesa_reference_buffer_object_shared(ctx, &texObj->BufferObject, NULL);
491bf215546Sopenharmony_ci   free(texObj->Label);
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   /* free this object */
494bf215546Sopenharmony_ci   FREE(texObj);
495bf215546Sopenharmony_ci}
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci/**
499bf215546Sopenharmony_ci * Free all texture images of the given texture objectm, except for
500bf215546Sopenharmony_ci * \p retainTexImage.
501bf215546Sopenharmony_ci *
502bf215546Sopenharmony_ci * \param ctx GL context.
503bf215546Sopenharmony_ci * \param texObj texture object.
504bf215546Sopenharmony_ci * \param retainTexImage a texture image that will \em not be freed.
505bf215546Sopenharmony_ci *
506bf215546Sopenharmony_ci * \sa _mesa_clear_texture_image().
507bf215546Sopenharmony_ci */
508bf215546Sopenharmony_civoid
509bf215546Sopenharmony_ci_mesa_clear_texture_object(struct gl_context *ctx,
510bf215546Sopenharmony_ci                           struct gl_texture_object *texObj,
511bf215546Sopenharmony_ci                           struct gl_texture_image *retainTexImage)
512bf215546Sopenharmony_ci{
513bf215546Sopenharmony_ci   GLuint i, j;
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   if (texObj->Target == 0)
516bf215546Sopenharmony_ci      return;
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci   for (i = 0; i < MAX_FACES; i++) {
519bf215546Sopenharmony_ci      for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
520bf215546Sopenharmony_ci         struct gl_texture_image *texImage = texObj->Image[i][j];
521bf215546Sopenharmony_ci         if (texImage && texImage != retainTexImage)
522bf215546Sopenharmony_ci            _mesa_clear_texture_image(ctx, texImage);
523bf215546Sopenharmony_ci      }
524bf215546Sopenharmony_ci   }
525bf215546Sopenharmony_ci}
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci/**
529bf215546Sopenharmony_ci * Check if the given texture object is valid by examining its Target field.
530bf215546Sopenharmony_ci * For debugging only.
531bf215546Sopenharmony_ci */
532bf215546Sopenharmony_cistatic GLboolean
533bf215546Sopenharmony_civalid_texture_object(const struct gl_texture_object *tex)
534bf215546Sopenharmony_ci{
535bf215546Sopenharmony_ci   switch (tex->Target) {
536bf215546Sopenharmony_ci   case 0:
537bf215546Sopenharmony_ci   case GL_TEXTURE_1D:
538bf215546Sopenharmony_ci   case GL_TEXTURE_2D:
539bf215546Sopenharmony_ci   case GL_TEXTURE_3D:
540bf215546Sopenharmony_ci   case GL_TEXTURE_CUBE_MAP:
541bf215546Sopenharmony_ci   case GL_TEXTURE_RECTANGLE_NV:
542bf215546Sopenharmony_ci   case GL_TEXTURE_1D_ARRAY_EXT:
543bf215546Sopenharmony_ci   case GL_TEXTURE_2D_ARRAY_EXT:
544bf215546Sopenharmony_ci   case GL_TEXTURE_BUFFER:
545bf215546Sopenharmony_ci   case GL_TEXTURE_EXTERNAL_OES:
546bf215546Sopenharmony_ci   case GL_TEXTURE_CUBE_MAP_ARRAY:
547bf215546Sopenharmony_ci   case GL_TEXTURE_2D_MULTISAMPLE:
548bf215546Sopenharmony_ci   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
549bf215546Sopenharmony_ci      return GL_TRUE;
550bf215546Sopenharmony_ci   case 0x99:
551bf215546Sopenharmony_ci      _mesa_problem(NULL, "invalid reference to a deleted texture object");
552bf215546Sopenharmony_ci      return GL_FALSE;
553bf215546Sopenharmony_ci   default:
554bf215546Sopenharmony_ci      _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
555bf215546Sopenharmony_ci                    tex->Target, tex->Name);
556bf215546Sopenharmony_ci      return GL_FALSE;
557bf215546Sopenharmony_ci   }
558bf215546Sopenharmony_ci}
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci/**
562bf215546Sopenharmony_ci * Reference (or unreference) a texture object.
563bf215546Sopenharmony_ci * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
564bf215546Sopenharmony_ci * If 'tex' is non-null, increment its refcount.
565bf215546Sopenharmony_ci * This is normally only called from the _mesa_reference_texobj() macro
566bf215546Sopenharmony_ci * when there's a real pointer change.
567bf215546Sopenharmony_ci */
568bf215546Sopenharmony_civoid
569bf215546Sopenharmony_ci_mesa_reference_texobj_(struct gl_texture_object **ptr,
570bf215546Sopenharmony_ci                        struct gl_texture_object *tex)
571bf215546Sopenharmony_ci{
572bf215546Sopenharmony_ci   assert(ptr);
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   if (*ptr) {
575bf215546Sopenharmony_ci      /* Unreference the old texture */
576bf215546Sopenharmony_ci      struct gl_texture_object *oldTex = *ptr;
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci      assert(valid_texture_object(oldTex));
579bf215546Sopenharmony_ci      (void) valid_texture_object; /* silence warning in release builds */
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci      assert(oldTex->RefCount > 0);
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci      if (p_atomic_dec_zero(&oldTex->RefCount)) {
584bf215546Sopenharmony_ci         /* Passing in the context drastically changes the driver code for
585bf215546Sopenharmony_ci          * framebuffer deletion.
586bf215546Sopenharmony_ci          */
587bf215546Sopenharmony_ci         GET_CURRENT_CONTEXT(ctx);
588bf215546Sopenharmony_ci         if (ctx)
589bf215546Sopenharmony_ci            _mesa_delete_texture_object(ctx, oldTex);
590bf215546Sopenharmony_ci         else
591bf215546Sopenharmony_ci            _mesa_problem(NULL, "Unable to delete texture, no context");
592bf215546Sopenharmony_ci      }
593bf215546Sopenharmony_ci   }
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci   if (tex) {
596bf215546Sopenharmony_ci      /* reference new texture */
597bf215546Sopenharmony_ci      assert(valid_texture_object(tex));
598bf215546Sopenharmony_ci      assert(tex->RefCount > 0);
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci      p_atomic_inc(&tex->RefCount);
601bf215546Sopenharmony_ci   }
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   *ptr = tex;
604bf215546Sopenharmony_ci}
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_cienum base_mipmap { BASE, MIPMAP };
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci/**
611bf215546Sopenharmony_ci * Mark a texture object as incomplete.  There are actually three kinds of
612bf215546Sopenharmony_ci * (in)completeness:
613bf215546Sopenharmony_ci * 1. "base incomplete": the base level of the texture is invalid so no
614bf215546Sopenharmony_ci *    texturing is possible.
615bf215546Sopenharmony_ci * 2. "mipmap incomplete": a non-base level of the texture is invalid so
616bf215546Sopenharmony_ci *    mipmap filtering isn't possible, but non-mipmap filtering is.
617bf215546Sopenharmony_ci * 3. "texture incompleteness": some combination of texture state and
618bf215546Sopenharmony_ci *    sampler state renders the texture incomplete.
619bf215546Sopenharmony_ci *
620bf215546Sopenharmony_ci * \param t  texture object
621bf215546Sopenharmony_ci * \param bm  either BASE or MIPMAP to indicate what's incomplete
622bf215546Sopenharmony_ci * \param fmt...  string describing why it's incomplete (for debugging).
623bf215546Sopenharmony_ci */
624bf215546Sopenharmony_cistatic void
625bf215546Sopenharmony_ciincomplete(struct gl_texture_object *t, enum base_mipmap bm,
626bf215546Sopenharmony_ci           const char *fmt, ...)
627bf215546Sopenharmony_ci{
628bf215546Sopenharmony_ci   if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) {
629bf215546Sopenharmony_ci      va_list args;
630bf215546Sopenharmony_ci      char s[100];
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci      va_start(args, fmt);
633bf215546Sopenharmony_ci      vsnprintf(s, sizeof(s), fmt, args);
634bf215546Sopenharmony_ci      va_end(args);
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_ci      _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s);
637bf215546Sopenharmony_ci   }
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci   if (bm == BASE)
640bf215546Sopenharmony_ci      t->_BaseComplete = GL_FALSE;
641bf215546Sopenharmony_ci   t->_MipmapComplete = GL_FALSE;
642bf215546Sopenharmony_ci}
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci/**
646bf215546Sopenharmony_ci * Examine a texture object to determine if it is complete.
647bf215546Sopenharmony_ci *
648bf215546Sopenharmony_ci * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
649bf215546Sopenharmony_ci * accordingly.
650bf215546Sopenharmony_ci *
651bf215546Sopenharmony_ci * \param ctx GL context.
652bf215546Sopenharmony_ci * \param t texture object.
653bf215546Sopenharmony_ci *
654bf215546Sopenharmony_ci * According to the texture target, verifies that each of the mipmaps is
655bf215546Sopenharmony_ci * present and has the expected size.
656bf215546Sopenharmony_ci */
657bf215546Sopenharmony_civoid
658bf215546Sopenharmony_ci_mesa_test_texobj_completeness( const struct gl_context *ctx,
659bf215546Sopenharmony_ci                                struct gl_texture_object *t )
660bf215546Sopenharmony_ci{
661bf215546Sopenharmony_ci   const GLint baseLevel = t->Attrib.BaseLevel;
662bf215546Sopenharmony_ci   const struct gl_texture_image *baseImage;
663bf215546Sopenharmony_ci   GLint maxLevels = 0;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   /* We'll set these to FALSE if tests fail below */
666bf215546Sopenharmony_ci   t->_BaseComplete = GL_TRUE;
667bf215546Sopenharmony_ci   t->_MipmapComplete = GL_TRUE;
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci   if (t->Target == GL_TEXTURE_BUFFER) {
670bf215546Sopenharmony_ci      /* Buffer textures are always considered complete.  The obvious case where
671bf215546Sopenharmony_ci       * they would be incomplete (no BO attached) is actually specced to be
672bf215546Sopenharmony_ci       * undefined rendering results.
673bf215546Sopenharmony_ci       */
674bf215546Sopenharmony_ci      return;
675bf215546Sopenharmony_ci   }
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci   /* Detect cases where the application set the base level to an invalid
678bf215546Sopenharmony_ci    * value.
679bf215546Sopenharmony_ci    */
680bf215546Sopenharmony_ci   if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
681bf215546Sopenharmony_ci      incomplete(t, BASE, "base level = %d is invalid", baseLevel);
682bf215546Sopenharmony_ci      return;
683bf215546Sopenharmony_ci   }
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_ci   if (t->Attrib.MaxLevel < baseLevel) {
686bf215546Sopenharmony_ci      incomplete(t, MIPMAP, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
687bf215546Sopenharmony_ci		 t->Attrib.MaxLevel, baseLevel);
688bf215546Sopenharmony_ci      return;
689bf215546Sopenharmony_ci   }
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci   baseImage = t->Image[0][baseLevel];
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci   /* Always need the base level image */
694bf215546Sopenharmony_ci   if (!baseImage) {
695bf215546Sopenharmony_ci      incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel);
696bf215546Sopenharmony_ci      return;
697bf215546Sopenharmony_ci   }
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci   /* Check width/height/depth for zero */
700bf215546Sopenharmony_ci   if (baseImage->Width == 0 ||
701bf215546Sopenharmony_ci       baseImage->Height == 0 ||
702bf215546Sopenharmony_ci       baseImage->Depth == 0) {
703bf215546Sopenharmony_ci      incomplete(t, BASE, "texture width or height or depth = 0");
704bf215546Sopenharmony_ci      return;
705bf215546Sopenharmony_ci   }
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci   /* Check if the texture values are integer */
708bf215546Sopenharmony_ci   {
709bf215546Sopenharmony_ci      GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat);
710bf215546Sopenharmony_ci      t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT;
711bf215546Sopenharmony_ci   }
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci   /* Check if the texture type is Float or HalfFloatOES and ensure Min and Mag
714bf215546Sopenharmony_ci    * filters are supported in this case.
715bf215546Sopenharmony_ci    */
716bf215546Sopenharmony_ci   if (_mesa_is_gles(ctx) && !valid_filter_for_float(ctx, t)) {
717bf215546Sopenharmony_ci      incomplete(t, BASE, "Filter is not supported with Float types.");
718bf215546Sopenharmony_ci      return;
719bf215546Sopenharmony_ci   }
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   maxLevels = _mesa_max_texture_levels(ctx, t->Target);
722bf215546Sopenharmony_ci   if (maxLevels == 0) {
723bf215546Sopenharmony_ci      _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
724bf215546Sopenharmony_ci      return;
725bf215546Sopenharmony_ci   }
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   assert(maxLevels > 0);
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   t->_MaxLevel = MIN3(t->Attrib.MaxLevel,
730bf215546Sopenharmony_ci                       /* 'p' in the GL spec */
731bf215546Sopenharmony_ci                       (int) (baseLevel + baseImage->MaxNumLevels - 1),
732bf215546Sopenharmony_ci                       /* 'q' in the GL spec */
733bf215546Sopenharmony_ci                       maxLevels - 1);
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   if (t->Immutable) {
736bf215546Sopenharmony_ci      /* Adjust max level for views: the data store may have more levels than
737bf215546Sopenharmony_ci       * the view exposes.
738bf215546Sopenharmony_ci       */
739bf215546Sopenharmony_ci      t->_MaxLevel = MAX2(MIN2(t->_MaxLevel, t->Attrib.NumLevels - 1), 0);
740bf215546Sopenharmony_ci   }
741bf215546Sopenharmony_ci
742bf215546Sopenharmony_ci   /* Compute _MaxLambda = q - p in the spec used during mipmapping */
743bf215546Sopenharmony_ci   t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_ci   if (t->Immutable) {
746bf215546Sopenharmony_ci      /* This texture object was created with glTexStorage1/2/3D() so we
747bf215546Sopenharmony_ci       * know that all the mipmap levels are the right size and all cube
748bf215546Sopenharmony_ci       * map faces are the same size.
749bf215546Sopenharmony_ci       * We don't need to do any of the additional checks below.
750bf215546Sopenharmony_ci       */
751bf215546Sopenharmony_ci      return;
752bf215546Sopenharmony_ci   }
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci   if (t->Target == GL_TEXTURE_CUBE_MAP) {
755bf215546Sopenharmony_ci      /* Make sure that all six cube map level 0 images are the same size and
756bf215546Sopenharmony_ci       * format.
757bf215546Sopenharmony_ci       * Note:  we know that the image's width==height (we enforce that
758bf215546Sopenharmony_ci       * at glTexImage time) so we only need to test the width here.
759bf215546Sopenharmony_ci       */
760bf215546Sopenharmony_ci      GLuint face;
761bf215546Sopenharmony_ci      assert(baseImage->Width2 == baseImage->Height);
762bf215546Sopenharmony_ci      for (face = 1; face < 6; face++) {
763bf215546Sopenharmony_ci         assert(t->Image[face][baseLevel] == NULL ||
764bf215546Sopenharmony_ci                t->Image[face][baseLevel]->Width2 ==
765bf215546Sopenharmony_ci                t->Image[face][baseLevel]->Height2);
766bf215546Sopenharmony_ci         if (t->Image[face][baseLevel] == NULL ||
767bf215546Sopenharmony_ci             t->Image[face][baseLevel]->Width2 != baseImage->Width2) {
768bf215546Sopenharmony_ci            incomplete(t, BASE, "Cube face missing or mismatched size");
769bf215546Sopenharmony_ci            return;
770bf215546Sopenharmony_ci         }
771bf215546Sopenharmony_ci         if (t->Image[face][baseLevel]->InternalFormat !=
772bf215546Sopenharmony_ci             baseImage->InternalFormat) {
773bf215546Sopenharmony_ci            incomplete(t, BASE, "Cube face format mismatch");
774bf215546Sopenharmony_ci            return;
775bf215546Sopenharmony_ci         }
776bf215546Sopenharmony_ci         if (t->Image[face][baseLevel]->Border != baseImage->Border) {
777bf215546Sopenharmony_ci            incomplete(t, BASE, "Cube face border size mismatch");
778bf215546Sopenharmony_ci            return;
779bf215546Sopenharmony_ci         }
780bf215546Sopenharmony_ci      }
781bf215546Sopenharmony_ci   }
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci   /*
784bf215546Sopenharmony_ci    * Do mipmap consistency checking.
785bf215546Sopenharmony_ci    * Note: we don't care about the current texture sampler state here.
786bf215546Sopenharmony_ci    * To determine texture completeness we'll either look at _BaseComplete
787bf215546Sopenharmony_ci    * or _MipmapComplete depending on the current minification filter mode.
788bf215546Sopenharmony_ci    */
789bf215546Sopenharmony_ci   {
790bf215546Sopenharmony_ci      GLint i;
791bf215546Sopenharmony_ci      const GLint minLevel = baseLevel;
792bf215546Sopenharmony_ci      const GLint maxLevel = t->_MaxLevel;
793bf215546Sopenharmony_ci      const GLuint numFaces = _mesa_num_tex_faces(t->Target);
794bf215546Sopenharmony_ci      GLuint width, height, depth, face;
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci      if (minLevel > maxLevel) {
797bf215546Sopenharmony_ci         incomplete(t, MIPMAP, "minLevel > maxLevel");
798bf215546Sopenharmony_ci         return;
799bf215546Sopenharmony_ci      }
800bf215546Sopenharmony_ci
801bf215546Sopenharmony_ci      /* Get the base image's dimensions */
802bf215546Sopenharmony_ci      width = baseImage->Width2;
803bf215546Sopenharmony_ci      height = baseImage->Height2;
804bf215546Sopenharmony_ci      depth = baseImage->Depth2;
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_ci      /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL,
807bf215546Sopenharmony_ci       * MULTISAMPLE and MULTISAMPLE_ARRAY textures
808bf215546Sopenharmony_ci       */
809bf215546Sopenharmony_ci      for (i = baseLevel + 1; i < maxLevels; i++) {
810bf215546Sopenharmony_ci         /* Compute the expected size of image at level[i] */
811bf215546Sopenharmony_ci         if (width > 1) {
812bf215546Sopenharmony_ci            width /= 2;
813bf215546Sopenharmony_ci         }
814bf215546Sopenharmony_ci         if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) {
815bf215546Sopenharmony_ci            height /= 2;
816bf215546Sopenharmony_ci         }
817bf215546Sopenharmony_ci         if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY
818bf215546Sopenharmony_ci             && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) {
819bf215546Sopenharmony_ci            depth /= 2;
820bf215546Sopenharmony_ci         }
821bf215546Sopenharmony_ci
822bf215546Sopenharmony_ci         /* loop over cube faces (or single face otherwise) */
823bf215546Sopenharmony_ci         for (face = 0; face < numFaces; face++) {
824bf215546Sopenharmony_ci            if (i >= minLevel && i <= maxLevel) {
825bf215546Sopenharmony_ci               const struct gl_texture_image *img = t->Image[face][i];
826bf215546Sopenharmony_ci
827bf215546Sopenharmony_ci               if (!img) {
828bf215546Sopenharmony_ci                  incomplete(t, MIPMAP, "TexImage[%d] is missing", i);
829bf215546Sopenharmony_ci                  return;
830bf215546Sopenharmony_ci               }
831bf215546Sopenharmony_ci               if (img->InternalFormat != baseImage->InternalFormat) {
832bf215546Sopenharmony_ci                  incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]");
833bf215546Sopenharmony_ci                  return;
834bf215546Sopenharmony_ci               }
835bf215546Sopenharmony_ci               if (img->Border != baseImage->Border) {
836bf215546Sopenharmony_ci                  incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]");
837bf215546Sopenharmony_ci                  return;
838bf215546Sopenharmony_ci               }
839bf215546Sopenharmony_ci               if (img->Width2 != width) {
840bf215546Sopenharmony_ci                  incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i,
841bf215546Sopenharmony_ci                             img->Width2);
842bf215546Sopenharmony_ci                  return;
843bf215546Sopenharmony_ci               }
844bf215546Sopenharmony_ci               if (img->Height2 != height) {
845bf215546Sopenharmony_ci                  incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i,
846bf215546Sopenharmony_ci                             img->Height2);
847bf215546Sopenharmony_ci                  return;
848bf215546Sopenharmony_ci               }
849bf215546Sopenharmony_ci               if (img->Depth2 != depth) {
850bf215546Sopenharmony_ci                  incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i,
851bf215546Sopenharmony_ci                             img->Depth2);
852bf215546Sopenharmony_ci                  return;
853bf215546Sopenharmony_ci               }
854bf215546Sopenharmony_ci            }
855bf215546Sopenharmony_ci         }
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci         if (width == 1 && height == 1 && depth == 1) {
858bf215546Sopenharmony_ci            return;  /* found smallest needed mipmap, all done! */
859bf215546Sopenharmony_ci         }
860bf215546Sopenharmony_ci      }
861bf215546Sopenharmony_ci   }
862bf215546Sopenharmony_ci}
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_ci
865bf215546Sopenharmony_ciGLboolean
866bf215546Sopenharmony_ci_mesa_cube_level_complete(const struct gl_texture_object *texObj,
867bf215546Sopenharmony_ci                          const GLint level)
868bf215546Sopenharmony_ci{
869bf215546Sopenharmony_ci   const struct gl_texture_image *img0, *img;
870bf215546Sopenharmony_ci   GLuint face;
871bf215546Sopenharmony_ci
872bf215546Sopenharmony_ci   if (texObj->Target != GL_TEXTURE_CUBE_MAP)
873bf215546Sopenharmony_ci      return GL_FALSE;
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_ci   if ((level < 0) || (level >= MAX_TEXTURE_LEVELS))
876bf215546Sopenharmony_ci      return GL_FALSE;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   /* check first face */
879bf215546Sopenharmony_ci   img0 = texObj->Image[0][level];
880bf215546Sopenharmony_ci   if (!img0 ||
881bf215546Sopenharmony_ci       img0->Width < 1 ||
882bf215546Sopenharmony_ci       img0->Width != img0->Height)
883bf215546Sopenharmony_ci      return GL_FALSE;
884bf215546Sopenharmony_ci
885bf215546Sopenharmony_ci   /* check remaining faces vs. first face */
886bf215546Sopenharmony_ci   for (face = 1; face < 6; face++) {
887bf215546Sopenharmony_ci      img = texObj->Image[face][level];
888bf215546Sopenharmony_ci      if (!img ||
889bf215546Sopenharmony_ci          img->Width != img0->Width ||
890bf215546Sopenharmony_ci          img->Height != img0->Height ||
891bf215546Sopenharmony_ci          img->TexFormat != img0->TexFormat)
892bf215546Sopenharmony_ci         return GL_FALSE;
893bf215546Sopenharmony_ci   }
894bf215546Sopenharmony_ci
895bf215546Sopenharmony_ci   return GL_TRUE;
896bf215546Sopenharmony_ci}
897bf215546Sopenharmony_ci
898bf215546Sopenharmony_ci/**
899bf215546Sopenharmony_ci * Check if the given cube map texture is "cube complete" as defined in
900bf215546Sopenharmony_ci * the OpenGL specification.
901bf215546Sopenharmony_ci */
902bf215546Sopenharmony_ciGLboolean
903bf215546Sopenharmony_ci_mesa_cube_complete(const struct gl_texture_object *texObj)
904bf215546Sopenharmony_ci{
905bf215546Sopenharmony_ci   return _mesa_cube_level_complete(texObj, texObj->Attrib.BaseLevel);
906bf215546Sopenharmony_ci}
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci/**
909bf215546Sopenharmony_ci * Mark a texture object dirty.  It forces the object to be incomplete
910bf215546Sopenharmony_ci * and forces the context to re-validate its state.
911bf215546Sopenharmony_ci *
912bf215546Sopenharmony_ci * \param ctx GL context.
913bf215546Sopenharmony_ci * \param texObj texture object.
914bf215546Sopenharmony_ci */
915bf215546Sopenharmony_civoid
916bf215546Sopenharmony_ci_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj)
917bf215546Sopenharmony_ci{
918bf215546Sopenharmony_ci   texObj->_BaseComplete = GL_FALSE;
919bf215546Sopenharmony_ci   texObj->_MipmapComplete = GL_FALSE;
920bf215546Sopenharmony_ci   ctx->NewState |= _NEW_TEXTURE_OBJECT;
921bf215546Sopenharmony_ci   ctx->PopAttribState |= GL_TEXTURE_BIT;
922bf215546Sopenharmony_ci}
923bf215546Sopenharmony_ci
924bf215546Sopenharmony_ci
925bf215546Sopenharmony_ci/**
926bf215546Sopenharmony_ci * Return pointer to a default/fallback texture of the given type/target.
927bf215546Sopenharmony_ci * The texture is an RGBA texture with all texels = (0,0,0,1).
928bf215546Sopenharmony_ci * That's the value a GLSL sampler should get when sampling from an
929bf215546Sopenharmony_ci * incomplete texture.
930bf215546Sopenharmony_ci */
931bf215546Sopenharmony_cistruct gl_texture_object *
932bf215546Sopenharmony_ci_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
933bf215546Sopenharmony_ci{
934bf215546Sopenharmony_ci   if (!ctx->Shared->FallbackTex[tex]) {
935bf215546Sopenharmony_ci      /* create fallback texture now */
936bf215546Sopenharmony_ci      const GLsizei width = 1, height = 1;
937bf215546Sopenharmony_ci      GLsizei depth = 1;
938bf215546Sopenharmony_ci      GLubyte texel[24];
939bf215546Sopenharmony_ci      struct gl_texture_object *texObj;
940bf215546Sopenharmony_ci      struct gl_texture_image *texImage;
941bf215546Sopenharmony_ci      mesa_format texFormat;
942bf215546Sopenharmony_ci      GLuint dims, face, numFaces = 1;
943bf215546Sopenharmony_ci      GLenum target;
944bf215546Sopenharmony_ci
945bf215546Sopenharmony_ci      for (face = 0; face < 6; face++) {
946bf215546Sopenharmony_ci         texel[4*face + 0] =
947bf215546Sopenharmony_ci         texel[4*face + 1] =
948bf215546Sopenharmony_ci         texel[4*face + 2] = 0x0;
949bf215546Sopenharmony_ci         texel[4*face + 3] = 0xff;
950bf215546Sopenharmony_ci      }
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci      switch (tex) {
953bf215546Sopenharmony_ci      case TEXTURE_2D_ARRAY_INDEX:
954bf215546Sopenharmony_ci         dims = 3;
955bf215546Sopenharmony_ci         target = GL_TEXTURE_2D_ARRAY;
956bf215546Sopenharmony_ci         break;
957bf215546Sopenharmony_ci      case TEXTURE_1D_ARRAY_INDEX:
958bf215546Sopenharmony_ci         dims = 2;
959bf215546Sopenharmony_ci         target = GL_TEXTURE_1D_ARRAY;
960bf215546Sopenharmony_ci         break;
961bf215546Sopenharmony_ci      case TEXTURE_CUBE_INDEX:
962bf215546Sopenharmony_ci         dims = 2;
963bf215546Sopenharmony_ci         target = GL_TEXTURE_CUBE_MAP;
964bf215546Sopenharmony_ci         numFaces = 6;
965bf215546Sopenharmony_ci         break;
966bf215546Sopenharmony_ci      case TEXTURE_3D_INDEX:
967bf215546Sopenharmony_ci         dims = 3;
968bf215546Sopenharmony_ci         target = GL_TEXTURE_3D;
969bf215546Sopenharmony_ci         break;
970bf215546Sopenharmony_ci      case TEXTURE_RECT_INDEX:
971bf215546Sopenharmony_ci         dims = 2;
972bf215546Sopenharmony_ci         target = GL_TEXTURE_RECTANGLE;
973bf215546Sopenharmony_ci         break;
974bf215546Sopenharmony_ci      case TEXTURE_2D_INDEX:
975bf215546Sopenharmony_ci         dims = 2;
976bf215546Sopenharmony_ci         target = GL_TEXTURE_2D;
977bf215546Sopenharmony_ci         break;
978bf215546Sopenharmony_ci      case TEXTURE_1D_INDEX:
979bf215546Sopenharmony_ci         dims = 1;
980bf215546Sopenharmony_ci         target = GL_TEXTURE_1D;
981bf215546Sopenharmony_ci         break;
982bf215546Sopenharmony_ci      case TEXTURE_BUFFER_INDEX:
983bf215546Sopenharmony_ci         dims = 0;
984bf215546Sopenharmony_ci         target = GL_TEXTURE_BUFFER;
985bf215546Sopenharmony_ci         break;
986bf215546Sopenharmony_ci      case TEXTURE_CUBE_ARRAY_INDEX:
987bf215546Sopenharmony_ci         dims = 3;
988bf215546Sopenharmony_ci         target = GL_TEXTURE_CUBE_MAP_ARRAY;
989bf215546Sopenharmony_ci         depth = 6;
990bf215546Sopenharmony_ci         break;
991bf215546Sopenharmony_ci      case TEXTURE_EXTERNAL_INDEX:
992bf215546Sopenharmony_ci         dims = 2;
993bf215546Sopenharmony_ci         target = GL_TEXTURE_EXTERNAL_OES;
994bf215546Sopenharmony_ci         break;
995bf215546Sopenharmony_ci      case TEXTURE_2D_MULTISAMPLE_INDEX:
996bf215546Sopenharmony_ci         dims = 2;
997bf215546Sopenharmony_ci         target = GL_TEXTURE_2D_MULTISAMPLE;
998bf215546Sopenharmony_ci         break;
999bf215546Sopenharmony_ci      case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX:
1000bf215546Sopenharmony_ci         dims = 3;
1001bf215546Sopenharmony_ci         target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
1002bf215546Sopenharmony_ci         break;
1003bf215546Sopenharmony_ci      default:
1004bf215546Sopenharmony_ci         /* no-op */
1005bf215546Sopenharmony_ci         return NULL;
1006bf215546Sopenharmony_ci      }
1007bf215546Sopenharmony_ci
1008bf215546Sopenharmony_ci      /* create texture object */
1009bf215546Sopenharmony_ci      texObj = _mesa_new_texture_object(ctx, 0, target);
1010bf215546Sopenharmony_ci      if (!texObj)
1011bf215546Sopenharmony_ci         return NULL;
1012bf215546Sopenharmony_ci
1013bf215546Sopenharmony_ci      assert(texObj->RefCount == 1);
1014bf215546Sopenharmony_ci      texObj->Sampler.Attrib.MinFilter = GL_NEAREST;
1015bf215546Sopenharmony_ci      texObj->Sampler.Attrib.MagFilter = GL_NEAREST;
1016bf215546Sopenharmony_ci      texObj->Sampler.Attrib.state.min_img_filter = PIPE_TEX_FILTER_NEAREST;
1017bf215546Sopenharmony_ci      texObj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
1018bf215546Sopenharmony_ci      texObj->Sampler.Attrib.state.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci      texFormat = st_ChooseTextureFormat(ctx, target,
1021bf215546Sopenharmony_ci                                         GL_RGBA, GL_RGBA,
1022bf215546Sopenharmony_ci                                         GL_UNSIGNED_BYTE);
1023bf215546Sopenharmony_ci
1024bf215546Sopenharmony_ci      /* need a loop here just for cube maps */
1025bf215546Sopenharmony_ci      for (face = 0; face < numFaces; face++) {
1026bf215546Sopenharmony_ci         const GLenum faceTarget = _mesa_cube_face_target(target, face);
1027bf215546Sopenharmony_ci
1028bf215546Sopenharmony_ci         /* initialize level[0] texture image */
1029bf215546Sopenharmony_ci         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
1030bf215546Sopenharmony_ci
1031bf215546Sopenharmony_ci         _mesa_init_teximage_fields(ctx, texImage,
1032bf215546Sopenharmony_ci                                    width,
1033bf215546Sopenharmony_ci                                    (dims > 1) ? height : 1,
1034bf215546Sopenharmony_ci                                    (dims > 2) ? depth : 1,
1035bf215546Sopenharmony_ci                                    0, /* border */
1036bf215546Sopenharmony_ci                                    GL_RGBA, texFormat);
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci         st_TexImage(ctx, dims, texImage,
1039bf215546Sopenharmony_ci                     GL_RGBA, GL_UNSIGNED_BYTE, texel,
1040bf215546Sopenharmony_ci                     &ctx->DefaultPacking);
1041bf215546Sopenharmony_ci      }
1042bf215546Sopenharmony_ci
1043bf215546Sopenharmony_ci      _mesa_test_texobj_completeness(ctx, texObj);
1044bf215546Sopenharmony_ci      assert(texObj->_BaseComplete);
1045bf215546Sopenharmony_ci      assert(texObj->_MipmapComplete);
1046bf215546Sopenharmony_ci
1047bf215546Sopenharmony_ci      ctx->Shared->FallbackTex[tex] = texObj;
1048bf215546Sopenharmony_ci
1049bf215546Sopenharmony_ci      /* Complete the driver's operation in case another context will also
1050bf215546Sopenharmony_ci       * use the same fallback texture. */
1051bf215546Sopenharmony_ci      st_glFinish(ctx);
1052bf215546Sopenharmony_ci   }
1053bf215546Sopenharmony_ci   return ctx->Shared->FallbackTex[tex];
1054bf215546Sopenharmony_ci}
1055bf215546Sopenharmony_ci
1056bf215546Sopenharmony_ci
1057bf215546Sopenharmony_ci/**
1058bf215546Sopenharmony_ci * Compute the size of the given texture object, in bytes.
1059bf215546Sopenharmony_ci */
1060bf215546Sopenharmony_cistatic GLuint
1061bf215546Sopenharmony_citexture_size(const struct gl_texture_object *texObj)
1062bf215546Sopenharmony_ci{
1063bf215546Sopenharmony_ci   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1064bf215546Sopenharmony_ci   GLuint face, level, size = 0;
1065bf215546Sopenharmony_ci
1066bf215546Sopenharmony_ci   for (face = 0; face < numFaces; face++) {
1067bf215546Sopenharmony_ci      for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
1068bf215546Sopenharmony_ci         const struct gl_texture_image *img = texObj->Image[face][level];
1069bf215546Sopenharmony_ci         if (img) {
1070bf215546Sopenharmony_ci            GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
1071bf215546Sopenharmony_ci                                                img->Height, img->Depth);
1072bf215546Sopenharmony_ci            size += sz;
1073bf215546Sopenharmony_ci         }
1074bf215546Sopenharmony_ci      }
1075bf215546Sopenharmony_ci   }
1076bf215546Sopenharmony_ci
1077bf215546Sopenharmony_ci   return size;
1078bf215546Sopenharmony_ci}
1079bf215546Sopenharmony_ci
1080bf215546Sopenharmony_ci
1081bf215546Sopenharmony_ci/**
1082bf215546Sopenharmony_ci * Callback called from _mesa_HashWalk()
1083bf215546Sopenharmony_ci */
1084bf215546Sopenharmony_cistatic void
1085bf215546Sopenharmony_cicount_tex_size(void *data, void *userData)
1086bf215546Sopenharmony_ci{
1087bf215546Sopenharmony_ci   const struct gl_texture_object *texObj =
1088bf215546Sopenharmony_ci      (const struct gl_texture_object *) data;
1089bf215546Sopenharmony_ci   GLuint *total = (GLuint *) userData;
1090bf215546Sopenharmony_ci
1091bf215546Sopenharmony_ci   *total = *total + texture_size(texObj);
1092bf215546Sopenharmony_ci}
1093bf215546Sopenharmony_ci
1094bf215546Sopenharmony_ci
1095bf215546Sopenharmony_ci/**
1096bf215546Sopenharmony_ci * Compute total size (in bytes) of all textures for the given context.
1097bf215546Sopenharmony_ci * For debugging purposes.
1098bf215546Sopenharmony_ci */
1099bf215546Sopenharmony_ciGLuint
1100bf215546Sopenharmony_ci_mesa_total_texture_memory(struct gl_context *ctx)
1101bf215546Sopenharmony_ci{
1102bf215546Sopenharmony_ci   GLuint tgt, total = 0;
1103bf215546Sopenharmony_ci
1104bf215546Sopenharmony_ci   _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total);
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_ci   /* plus, the default texture objects */
1107bf215546Sopenharmony_ci   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
1108bf215546Sopenharmony_ci      total += texture_size(ctx->Shared->DefaultTex[tgt]);
1109bf215546Sopenharmony_ci   }
1110bf215546Sopenharmony_ci
1111bf215546Sopenharmony_ci   return total;
1112bf215546Sopenharmony_ci}
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci
1115bf215546Sopenharmony_ci/**
1116bf215546Sopenharmony_ci * Return the base format for the given texture object by looking
1117bf215546Sopenharmony_ci * at the base texture image.
1118bf215546Sopenharmony_ci * \return base format (such as GL_RGBA) or GL_NONE if it can't be determined
1119bf215546Sopenharmony_ci */
1120bf215546Sopenharmony_ciGLenum
1121bf215546Sopenharmony_ci_mesa_texture_base_format(const struct gl_texture_object *texObj)
1122bf215546Sopenharmony_ci{
1123bf215546Sopenharmony_ci   const struct gl_texture_image *texImage = _mesa_base_tex_image(texObj);
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci   return texImage ? texImage->_BaseFormat : GL_NONE;
1126bf215546Sopenharmony_ci}
1127bf215546Sopenharmony_ci
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_cistatic struct gl_texture_object *
1130bf215546Sopenharmony_ciinvalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture,
1131bf215546Sopenharmony_ci                                 GLint level, const char *name)
1132bf215546Sopenharmony_ci{
1133bf215546Sopenharmony_ci   /* The GL_ARB_invalidate_subdata spec says:
1134bf215546Sopenharmony_ci    *
1135bf215546Sopenharmony_ci    *     "If <texture> is zero or is not the name of a texture, the error
1136bf215546Sopenharmony_ci    *     INVALID_VALUE is generated."
1137bf215546Sopenharmony_ci    *
1138bf215546Sopenharmony_ci    * This performs the error check in a different order than listed in the
1139bf215546Sopenharmony_ci    * spec.  We have to get the texture object before we can validate the
1140bf215546Sopenharmony_ci    * other parameters against values in the texture object.
1141bf215546Sopenharmony_ci    */
1142bf215546Sopenharmony_ci   struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture);
1143bf215546Sopenharmony_ci   if (texture == 0 || t == NULL) {
1144bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name);
1145bf215546Sopenharmony_ci      return NULL;
1146bf215546Sopenharmony_ci   }
1147bf215546Sopenharmony_ci
1148bf215546Sopenharmony_ci   /* The GL_ARB_invalidate_subdata spec says:
1149bf215546Sopenharmony_ci    *
1150bf215546Sopenharmony_ci    *     "If <level> is less than zero or greater than the base 2 logarithm
1151bf215546Sopenharmony_ci    *     of the maximum texture width, height, or depth, the error
1152bf215546Sopenharmony_ci    *     INVALID_VALUE is generated."
1153bf215546Sopenharmony_ci    */
1154bf215546Sopenharmony_ci   if (level < 0 || level > t->Attrib.MaxLevel) {
1155bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1156bf215546Sopenharmony_ci      return NULL;
1157bf215546Sopenharmony_ci   }
1158bf215546Sopenharmony_ci
1159bf215546Sopenharmony_ci   /* The GL_ARB_invalidate_subdata spec says:
1160bf215546Sopenharmony_ci    *
1161bf215546Sopenharmony_ci    *     "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
1162bf215546Sopenharmony_ci    *     TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
1163bf215546Sopenharmony_ci    *     is not zero, the error INVALID_VALUE is generated."
1164bf215546Sopenharmony_ci    */
1165bf215546Sopenharmony_ci   if (level != 0) {
1166bf215546Sopenharmony_ci      switch (t->Target) {
1167bf215546Sopenharmony_ci      case GL_TEXTURE_RECTANGLE:
1168bf215546Sopenharmony_ci      case GL_TEXTURE_BUFFER:
1169bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE:
1170bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1171bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1172bf215546Sopenharmony_ci         return NULL;
1173bf215546Sopenharmony_ci
1174bf215546Sopenharmony_ci      default:
1175bf215546Sopenharmony_ci         break;
1176bf215546Sopenharmony_ci      }
1177bf215546Sopenharmony_ci   }
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci   return t;
1180bf215546Sopenharmony_ci}
1181bf215546Sopenharmony_ci
1182bf215546Sopenharmony_ci
1183bf215546Sopenharmony_ci/**
1184bf215546Sopenharmony_ci * Helper function for glCreateTextures and glGenTextures. Need this because
1185bf215546Sopenharmony_ci * glCreateTextures should throw errors if target = 0. This is not exposed to
1186bf215546Sopenharmony_ci * the rest of Mesa to encourage Mesa internals to use nameless textures,
1187bf215546Sopenharmony_ci * which do not require expensive hash lookups.
1188bf215546Sopenharmony_ci * \param target  either 0 or a valid / error-checked texture target enum
1189bf215546Sopenharmony_ci */
1190bf215546Sopenharmony_cistatic void
1191bf215546Sopenharmony_cicreate_textures(struct gl_context *ctx, GLenum target,
1192bf215546Sopenharmony_ci                GLsizei n, GLuint *textures, const char *caller)
1193bf215546Sopenharmony_ci{
1194bf215546Sopenharmony_ci   GLint i;
1195bf215546Sopenharmony_ci
1196bf215546Sopenharmony_ci   if (!textures)
1197bf215546Sopenharmony_ci      return;
1198bf215546Sopenharmony_ci
1199bf215546Sopenharmony_ci   /*
1200bf215546Sopenharmony_ci    * This must be atomic (generation and allocation of texture IDs)
1201bf215546Sopenharmony_ci    */
1202bf215546Sopenharmony_ci   _mesa_HashLockMutex(ctx->Shared->TexObjects);
1203bf215546Sopenharmony_ci
1204bf215546Sopenharmony_ci   _mesa_HashFindFreeKeys(ctx->Shared->TexObjects, textures, n);
1205bf215546Sopenharmony_ci
1206bf215546Sopenharmony_ci   /* Allocate new, empty texture objects */
1207bf215546Sopenharmony_ci   for (i = 0; i < n; i++) {
1208bf215546Sopenharmony_ci      struct gl_texture_object *texObj;
1209bf215546Sopenharmony_ci      texObj = _mesa_new_texture_object(ctx, textures[i], target);
1210bf215546Sopenharmony_ci      if (!texObj) {
1211bf215546Sopenharmony_ci         _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1212bf215546Sopenharmony_ci         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
1213bf215546Sopenharmony_ci         return;
1214bf215546Sopenharmony_ci      }
1215bf215546Sopenharmony_ci
1216bf215546Sopenharmony_ci      /* insert into hash table */
1217bf215546Sopenharmony_ci      _mesa_HashInsertLocked(ctx->Shared->TexObjects, texObj->Name, texObj, true);
1218bf215546Sopenharmony_ci   }
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1221bf215546Sopenharmony_ci}
1222bf215546Sopenharmony_ci
1223bf215546Sopenharmony_ci
1224bf215546Sopenharmony_cistatic void
1225bf215546Sopenharmony_cicreate_textures_err(struct gl_context *ctx, GLenum target,
1226bf215546Sopenharmony_ci                    GLsizei n, GLuint *textures, const char *caller)
1227bf215546Sopenharmony_ci{
1228bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1229bf215546Sopenharmony_ci      _mesa_debug(ctx, "%s %d\n", caller, n);
1230bf215546Sopenharmony_ci
1231bf215546Sopenharmony_ci   if (n < 0) {
1232bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
1233bf215546Sopenharmony_ci      return;
1234bf215546Sopenharmony_ci   }
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci   create_textures(ctx, target, n, textures, caller);
1237bf215546Sopenharmony_ci}
1238bf215546Sopenharmony_ci
1239bf215546Sopenharmony_ci/*@}*/
1240bf215546Sopenharmony_ci
1241bf215546Sopenharmony_ci
1242bf215546Sopenharmony_ci/***********************************************************************/
1243bf215546Sopenharmony_ci/** \name API functions */
1244bf215546Sopenharmony_ci/*@{*/
1245bf215546Sopenharmony_ci
1246bf215546Sopenharmony_ci
1247bf215546Sopenharmony_ci/**
1248bf215546Sopenharmony_ci * Generate texture names.
1249bf215546Sopenharmony_ci *
1250bf215546Sopenharmony_ci * \param n number of texture names to be generated.
1251bf215546Sopenharmony_ci * \param textures an array in which will hold the generated texture names.
1252bf215546Sopenharmony_ci *
1253bf215546Sopenharmony_ci * \sa glGenTextures(), glCreateTextures().
1254bf215546Sopenharmony_ci *
1255bf215546Sopenharmony_ci * Calls _mesa_HashFindFreeKeys() to find a block of free texture
1256bf215546Sopenharmony_ci * IDs which are stored in \p textures.  Corresponding empty texture
1257bf215546Sopenharmony_ci * objects are also generated.
1258bf215546Sopenharmony_ci */
1259bf215546Sopenharmony_civoid GLAPIENTRY
1260bf215546Sopenharmony_ci_mesa_GenTextures_no_error(GLsizei n, GLuint *textures)
1261bf215546Sopenharmony_ci{
1262bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1263bf215546Sopenharmony_ci   create_textures(ctx, 0, n, textures, "glGenTextures");
1264bf215546Sopenharmony_ci}
1265bf215546Sopenharmony_ci
1266bf215546Sopenharmony_ci
1267bf215546Sopenharmony_civoid GLAPIENTRY
1268bf215546Sopenharmony_ci_mesa_GenTextures(GLsizei n, GLuint *textures)
1269bf215546Sopenharmony_ci{
1270bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1271bf215546Sopenharmony_ci   create_textures_err(ctx, 0, n, textures, "glGenTextures");
1272bf215546Sopenharmony_ci}
1273bf215546Sopenharmony_ci
1274bf215546Sopenharmony_ci/**
1275bf215546Sopenharmony_ci * Create texture objects.
1276bf215546Sopenharmony_ci *
1277bf215546Sopenharmony_ci * \param target the texture target for each name to be generated.
1278bf215546Sopenharmony_ci * \param n number of texture names to be generated.
1279bf215546Sopenharmony_ci * \param textures an array in which will hold the generated texture names.
1280bf215546Sopenharmony_ci *
1281bf215546Sopenharmony_ci * \sa glCreateTextures(), glGenTextures().
1282bf215546Sopenharmony_ci *
1283bf215546Sopenharmony_ci * Calls _mesa_HashFindFreeKeys() to find a block of free texture
1284bf215546Sopenharmony_ci * IDs which are stored in \p textures.  Corresponding empty texture
1285bf215546Sopenharmony_ci * objects are also generated.
1286bf215546Sopenharmony_ci */
1287bf215546Sopenharmony_civoid GLAPIENTRY
1288bf215546Sopenharmony_ci_mesa_CreateTextures_no_error(GLenum target, GLsizei n, GLuint *textures)
1289bf215546Sopenharmony_ci{
1290bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1291bf215546Sopenharmony_ci   create_textures(ctx, target, n, textures, "glCreateTextures");
1292bf215546Sopenharmony_ci}
1293bf215546Sopenharmony_ci
1294bf215546Sopenharmony_ci
1295bf215546Sopenharmony_civoid GLAPIENTRY
1296bf215546Sopenharmony_ci_mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
1297bf215546Sopenharmony_ci{
1298bf215546Sopenharmony_ci   GLint targetIndex;
1299bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1300bf215546Sopenharmony_ci
1301bf215546Sopenharmony_ci   /*
1302bf215546Sopenharmony_ci    * The 4.5 core profile spec (30.10.2014) doesn't specify what
1303bf215546Sopenharmony_ci    * glCreateTextures should do with invalid targets, which was probably an
1304bf215546Sopenharmony_ci    * oversight.  This conforms to the spec for glBindTexture.
1305bf215546Sopenharmony_ci    */
1306bf215546Sopenharmony_ci   targetIndex = _mesa_tex_target_to_index(ctx, target);
1307bf215546Sopenharmony_ci   if (targetIndex < 0) {
1308bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glCreateTextures(target)");
1309bf215546Sopenharmony_ci      return;
1310bf215546Sopenharmony_ci   }
1311bf215546Sopenharmony_ci
1312bf215546Sopenharmony_ci   create_textures_err(ctx, target, n, textures, "glCreateTextures");
1313bf215546Sopenharmony_ci}
1314bf215546Sopenharmony_ci
1315bf215546Sopenharmony_ci/**
1316bf215546Sopenharmony_ci * Check if the given texture object is bound to the current draw or
1317bf215546Sopenharmony_ci * read framebuffer.  If so, Unbind it.
1318bf215546Sopenharmony_ci */
1319bf215546Sopenharmony_cistatic void
1320bf215546Sopenharmony_ciunbind_texobj_from_fbo(struct gl_context *ctx,
1321bf215546Sopenharmony_ci                       struct gl_texture_object *texObj)
1322bf215546Sopenharmony_ci{
1323bf215546Sopenharmony_ci   bool progress = false;
1324bf215546Sopenharmony_ci
1325bf215546Sopenharmony_ci   /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection
1326bf215546Sopenharmony_ci    * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec
1327bf215546Sopenharmony_ci    * says:
1328bf215546Sopenharmony_ci    *
1329bf215546Sopenharmony_ci    *     "If a texture object is deleted while its image is attached to one
1330bf215546Sopenharmony_ci    *     or more attachment points in the currently bound framebuffer, then
1331bf215546Sopenharmony_ci    *     it is as if FramebufferTexture* had been called, with a texture of
1332bf215546Sopenharmony_ci    *     zero, for each attachment point to which this image was attached in
1333bf215546Sopenharmony_ci    *     the currently bound framebuffer. In other words, this texture image
1334bf215546Sopenharmony_ci    *     is first detached from all attachment points in the currently bound
1335bf215546Sopenharmony_ci    *     framebuffer. Note that the texture image is specifically not
1336bf215546Sopenharmony_ci    *     detached from any other framebuffer objects. Detaching the texture
1337bf215546Sopenharmony_ci    *     image from any other framebuffer objects is the responsibility of
1338bf215546Sopenharmony_ci    *     the application."
1339bf215546Sopenharmony_ci    */
1340bf215546Sopenharmony_ci   if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1341bf215546Sopenharmony_ci      progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj);
1342bf215546Sopenharmony_ci   }
1343bf215546Sopenharmony_ci   if (_mesa_is_user_fbo(ctx->ReadBuffer)
1344bf215546Sopenharmony_ci       && ctx->ReadBuffer != ctx->DrawBuffer) {
1345bf215546Sopenharmony_ci      progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj)
1346bf215546Sopenharmony_ci         || progress;
1347bf215546Sopenharmony_ci   }
1348bf215546Sopenharmony_ci
1349bf215546Sopenharmony_ci   if (progress)
1350bf215546Sopenharmony_ci      /* Vertices are already flushed by _mesa_DeleteTextures */
1351bf215546Sopenharmony_ci      ctx->NewState |= _NEW_BUFFERS;
1352bf215546Sopenharmony_ci}
1353bf215546Sopenharmony_ci
1354bf215546Sopenharmony_ci
1355bf215546Sopenharmony_ci/**
1356bf215546Sopenharmony_ci * Check if the given texture object is bound to any texture image units and
1357bf215546Sopenharmony_ci * unbind it if so (revert to default textures).
1358bf215546Sopenharmony_ci */
1359bf215546Sopenharmony_cistatic void
1360bf215546Sopenharmony_ciunbind_texobj_from_texunits(struct gl_context *ctx,
1361bf215546Sopenharmony_ci                            struct gl_texture_object *texObj)
1362bf215546Sopenharmony_ci{
1363bf215546Sopenharmony_ci   const gl_texture_index index = texObj->TargetIndex;
1364bf215546Sopenharmony_ci   GLuint u;
1365bf215546Sopenharmony_ci
1366bf215546Sopenharmony_ci   if (texObj->Target == 0) {
1367bf215546Sopenharmony_ci      /* texture was never bound */
1368bf215546Sopenharmony_ci      return;
1369bf215546Sopenharmony_ci   }
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci   assert(index < NUM_TEXTURE_TARGETS);
1372bf215546Sopenharmony_ci
1373bf215546Sopenharmony_ci   for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) {
1374bf215546Sopenharmony_ci      struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
1375bf215546Sopenharmony_ci
1376bf215546Sopenharmony_ci      if (texObj == unit->CurrentTex[index]) {
1377bf215546Sopenharmony_ci         /* Bind the default texture for this unit/target */
1378bf215546Sopenharmony_ci         _mesa_reference_texobj(&unit->CurrentTex[index],
1379bf215546Sopenharmony_ci                                ctx->Shared->DefaultTex[index]);
1380bf215546Sopenharmony_ci         unit->_BoundTextures &= ~(1 << index);
1381bf215546Sopenharmony_ci      }
1382bf215546Sopenharmony_ci   }
1383bf215546Sopenharmony_ci}
1384bf215546Sopenharmony_ci
1385bf215546Sopenharmony_ci
1386bf215546Sopenharmony_ci/**
1387bf215546Sopenharmony_ci * Check if the given texture object is bound to any shader image unit
1388bf215546Sopenharmony_ci * and unbind it if that's the case.
1389bf215546Sopenharmony_ci */
1390bf215546Sopenharmony_cistatic void
1391bf215546Sopenharmony_ciunbind_texobj_from_image_units(struct gl_context *ctx,
1392bf215546Sopenharmony_ci                               struct gl_texture_object *texObj)
1393bf215546Sopenharmony_ci{
1394bf215546Sopenharmony_ci   GLuint i;
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci   for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
1397bf215546Sopenharmony_ci      struct gl_image_unit *unit = &ctx->ImageUnits[i];
1398bf215546Sopenharmony_ci
1399bf215546Sopenharmony_ci      if (texObj == unit->TexObj) {
1400bf215546Sopenharmony_ci         _mesa_reference_texobj(&unit->TexObj, NULL);
1401bf215546Sopenharmony_ci         *unit = _mesa_default_image_unit(ctx);
1402bf215546Sopenharmony_ci      }
1403bf215546Sopenharmony_ci   }
1404bf215546Sopenharmony_ci}
1405bf215546Sopenharmony_ci
1406bf215546Sopenharmony_ci
1407bf215546Sopenharmony_ci/**
1408bf215546Sopenharmony_ci * Unbinds all textures bound to the given texture image unit.
1409bf215546Sopenharmony_ci */
1410bf215546Sopenharmony_cistatic void
1411bf215546Sopenharmony_ciunbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
1412bf215546Sopenharmony_ci{
1413bf215546Sopenharmony_ci   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1414bf215546Sopenharmony_ci
1415bf215546Sopenharmony_ci   while (texUnit->_BoundTextures) {
1416bf215546Sopenharmony_ci      const GLuint index = ffs(texUnit->_BoundTextures) - 1;
1417bf215546Sopenharmony_ci      struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci      _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
1420bf215546Sopenharmony_ci
1421bf215546Sopenharmony_ci      texUnit->_BoundTextures &= ~(1 << index);
1422bf215546Sopenharmony_ci      ctx->NewState |= _NEW_TEXTURE_OBJECT;
1423bf215546Sopenharmony_ci      ctx->PopAttribState |= GL_TEXTURE_BIT;
1424bf215546Sopenharmony_ci   }
1425bf215546Sopenharmony_ci}
1426bf215546Sopenharmony_ci
1427bf215546Sopenharmony_ci
1428bf215546Sopenharmony_ci/**
1429bf215546Sopenharmony_ci * Delete named textures.
1430bf215546Sopenharmony_ci *
1431bf215546Sopenharmony_ci * \param n number of textures to be deleted.
1432bf215546Sopenharmony_ci * \param textures array of texture IDs to be deleted.
1433bf215546Sopenharmony_ci *
1434bf215546Sopenharmony_ci * \sa glDeleteTextures().
1435bf215546Sopenharmony_ci *
1436bf215546Sopenharmony_ci * If we're about to delete a texture that's currently bound to any
1437bf215546Sopenharmony_ci * texture unit, unbind the texture first.  Decrement the reference
1438bf215546Sopenharmony_ci * count on the texture object and delete it if it's zero.
1439bf215546Sopenharmony_ci * Recall that texture objects can be shared among several rendering
1440bf215546Sopenharmony_ci * contexts.
1441bf215546Sopenharmony_ci */
1442bf215546Sopenharmony_cistatic void
1443bf215546Sopenharmony_cidelete_textures(struct gl_context *ctx, GLsizei n, const GLuint *textures)
1444bf215546Sopenharmony_ci{
1445bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, 0, 0); /* too complex */
1446bf215546Sopenharmony_ci
1447bf215546Sopenharmony_ci   if (!textures)
1448bf215546Sopenharmony_ci      return;
1449bf215546Sopenharmony_ci
1450bf215546Sopenharmony_ci   for (GLsizei i = 0; i < n; i++) {
1451bf215546Sopenharmony_ci      if (textures[i] > 0) {
1452bf215546Sopenharmony_ci         struct gl_texture_object *delObj
1453bf215546Sopenharmony_ci            = _mesa_lookup_texture(ctx, textures[i]);
1454bf215546Sopenharmony_ci
1455bf215546Sopenharmony_ci         if (delObj) {
1456bf215546Sopenharmony_ci            _mesa_lock_texture(ctx, delObj);
1457bf215546Sopenharmony_ci
1458bf215546Sopenharmony_ci            /* Check if texture is bound to any framebuffer objects.
1459bf215546Sopenharmony_ci             * If so, unbind.
1460bf215546Sopenharmony_ci             * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1461bf215546Sopenharmony_ci             */
1462bf215546Sopenharmony_ci            unbind_texobj_from_fbo(ctx, delObj);
1463bf215546Sopenharmony_ci
1464bf215546Sopenharmony_ci            /* Check if this texture is currently bound to any texture units.
1465bf215546Sopenharmony_ci             * If so, unbind it.
1466bf215546Sopenharmony_ci             */
1467bf215546Sopenharmony_ci            unbind_texobj_from_texunits(ctx, delObj);
1468bf215546Sopenharmony_ci
1469bf215546Sopenharmony_ci            /* Check if this texture is currently bound to any shader
1470bf215546Sopenharmony_ci             * image unit.  If so, unbind it.
1471bf215546Sopenharmony_ci             * See section 3.9.X of GL_ARB_shader_image_load_store.
1472bf215546Sopenharmony_ci             */
1473bf215546Sopenharmony_ci            unbind_texobj_from_image_units(ctx, delObj);
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci            /* Make all handles that reference this texture object non-resident
1476bf215546Sopenharmony_ci             * in the current context.
1477bf215546Sopenharmony_ci             */
1478bf215546Sopenharmony_ci            _mesa_make_texture_handles_non_resident(ctx, delObj);
1479bf215546Sopenharmony_ci
1480bf215546Sopenharmony_ci            _mesa_unlock_texture(ctx, delObj);
1481bf215546Sopenharmony_ci
1482bf215546Sopenharmony_ci            ctx->NewState |= _NEW_TEXTURE_OBJECT;
1483bf215546Sopenharmony_ci            ctx->PopAttribState |= GL_TEXTURE_BIT;
1484bf215546Sopenharmony_ci
1485bf215546Sopenharmony_ci            /* The texture _name_ is now free for re-use.
1486bf215546Sopenharmony_ci             * Remove it from the hash table now.
1487bf215546Sopenharmony_ci             */
1488bf215546Sopenharmony_ci            _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
1489bf215546Sopenharmony_ci
1490bf215546Sopenharmony_ci            st_texture_release_all_sampler_views(st_context(ctx), delObj);
1491bf215546Sopenharmony_ci
1492bf215546Sopenharmony_ci            /* Unreference the texobj.  If refcount hits zero, the texture
1493bf215546Sopenharmony_ci             * will be deleted.
1494bf215546Sopenharmony_ci             */
1495bf215546Sopenharmony_ci            _mesa_reference_texobj(&delObj, NULL);
1496bf215546Sopenharmony_ci         }
1497bf215546Sopenharmony_ci      }
1498bf215546Sopenharmony_ci   }
1499bf215546Sopenharmony_ci}
1500bf215546Sopenharmony_ci
1501bf215546Sopenharmony_civoid GLAPIENTRY
1502bf215546Sopenharmony_ci_mesa_DeleteTextures_no_error(GLsizei n, const GLuint *textures)
1503bf215546Sopenharmony_ci{
1504bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1505bf215546Sopenharmony_ci   delete_textures(ctx, n, textures);
1506bf215546Sopenharmony_ci}
1507bf215546Sopenharmony_ci
1508bf215546Sopenharmony_ci
1509bf215546Sopenharmony_civoid GLAPIENTRY
1510bf215546Sopenharmony_ci_mesa_DeleteTextures(GLsizei n, const GLuint *textures)
1511bf215546Sopenharmony_ci{
1512bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1513bf215546Sopenharmony_ci
1514bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1515bf215546Sopenharmony_ci      _mesa_debug(ctx, "glDeleteTextures %d\n", n);
1516bf215546Sopenharmony_ci
1517bf215546Sopenharmony_ci   if (n < 0) {
1518bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTextures(n < 0)");
1519bf215546Sopenharmony_ci      return;
1520bf215546Sopenharmony_ci   }
1521bf215546Sopenharmony_ci
1522bf215546Sopenharmony_ci   delete_textures(ctx, n, textures);
1523bf215546Sopenharmony_ci}
1524bf215546Sopenharmony_ci
1525bf215546Sopenharmony_ci
1526bf215546Sopenharmony_ci/**
1527bf215546Sopenharmony_ci * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
1528bf215546Sopenharmony_ci * into the corresponding Mesa texture target index.
1529bf215546Sopenharmony_ci * Note that proxy targets are not valid here.
1530bf215546Sopenharmony_ci * \return TEXTURE_x_INDEX or -1 if target is invalid
1531bf215546Sopenharmony_ci */
1532bf215546Sopenharmony_ciint
1533bf215546Sopenharmony_ci_mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target)
1534bf215546Sopenharmony_ci{
1535bf215546Sopenharmony_ci   switch (target) {
1536bf215546Sopenharmony_ci   case GL_TEXTURE_1D:
1537bf215546Sopenharmony_ci      return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1;
1538bf215546Sopenharmony_ci   case GL_TEXTURE_2D:
1539bf215546Sopenharmony_ci      return TEXTURE_2D_INDEX;
1540bf215546Sopenharmony_ci   case GL_TEXTURE_3D:
1541bf215546Sopenharmony_ci      return (ctx->API != API_OPENGLES &&
1542bf215546Sopenharmony_ci              !(ctx->API == API_OPENGLES2 && !ctx->Extensions.OES_texture_3D))
1543bf215546Sopenharmony_ci         ? TEXTURE_3D_INDEX : -1;
1544bf215546Sopenharmony_ci   case GL_TEXTURE_CUBE_MAP:
1545bf215546Sopenharmony_ci      return TEXTURE_CUBE_INDEX;
1546bf215546Sopenharmony_ci   case GL_TEXTURE_RECTANGLE:
1547bf215546Sopenharmony_ci      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle
1548bf215546Sopenharmony_ci         ? TEXTURE_RECT_INDEX : -1;
1549bf215546Sopenharmony_ci   case GL_TEXTURE_1D_ARRAY:
1550bf215546Sopenharmony_ci      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array
1551bf215546Sopenharmony_ci         ? TEXTURE_1D_ARRAY_INDEX : -1;
1552bf215546Sopenharmony_ci   case GL_TEXTURE_2D_ARRAY:
1553bf215546Sopenharmony_ci      return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1554bf215546Sopenharmony_ci         || _mesa_is_gles3(ctx)
1555bf215546Sopenharmony_ci         ? TEXTURE_2D_ARRAY_INDEX : -1;
1556bf215546Sopenharmony_ci   case GL_TEXTURE_BUFFER:
1557bf215546Sopenharmony_ci      return (_mesa_has_ARB_texture_buffer_object(ctx) ||
1558bf215546Sopenharmony_ci              _mesa_has_OES_texture_buffer(ctx)) ?
1559bf215546Sopenharmony_ci             TEXTURE_BUFFER_INDEX : -1;
1560bf215546Sopenharmony_ci   case GL_TEXTURE_EXTERNAL_OES:
1561bf215546Sopenharmony_ci      return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
1562bf215546Sopenharmony_ci         ? TEXTURE_EXTERNAL_INDEX : -1;
1563bf215546Sopenharmony_ci   case GL_TEXTURE_CUBE_MAP_ARRAY:
1564bf215546Sopenharmony_ci      return _mesa_has_texture_cube_map_array(ctx)
1565bf215546Sopenharmony_ci         ? TEXTURE_CUBE_ARRAY_INDEX : -1;
1566bf215546Sopenharmony_ci   case GL_TEXTURE_2D_MULTISAMPLE:
1567bf215546Sopenharmony_ci      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) ||
1568bf215546Sopenharmony_ci              _mesa_is_gles31(ctx)) ? TEXTURE_2D_MULTISAMPLE_INDEX: -1;
1569bf215546Sopenharmony_ci   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1570bf215546Sopenharmony_ci      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) ||
1571bf215546Sopenharmony_ci              _mesa_is_gles31(ctx))
1572bf215546Sopenharmony_ci         ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1;
1573bf215546Sopenharmony_ci   default:
1574bf215546Sopenharmony_ci      return -1;
1575bf215546Sopenharmony_ci   }
1576bf215546Sopenharmony_ci}
1577bf215546Sopenharmony_ci
1578bf215546Sopenharmony_ci
1579bf215546Sopenharmony_ci/**
1580bf215546Sopenharmony_ci * Do actual texture binding.  All error checking should have been done prior
1581bf215546Sopenharmony_ci * to calling this function.  Note that the texture target (1D, 2D, etc) is
1582bf215546Sopenharmony_ci * always specified by the texObj->TargetIndex.
1583bf215546Sopenharmony_ci *
1584bf215546Sopenharmony_ci * \param unit  index of texture unit to update
1585bf215546Sopenharmony_ci * \param texObj  the new texture object (cannot be NULL)
1586bf215546Sopenharmony_ci */
1587bf215546Sopenharmony_cistatic void
1588bf215546Sopenharmony_cibind_texture_object(struct gl_context *ctx, unsigned unit,
1589bf215546Sopenharmony_ci                    struct gl_texture_object *texObj)
1590bf215546Sopenharmony_ci{
1591bf215546Sopenharmony_ci   struct gl_texture_unit *texUnit;
1592bf215546Sopenharmony_ci   int targetIndex;
1593bf215546Sopenharmony_ci
1594bf215546Sopenharmony_ci   assert(unit < ARRAY_SIZE(ctx->Texture.Unit));
1595bf215546Sopenharmony_ci   texUnit = &ctx->Texture.Unit[unit];
1596bf215546Sopenharmony_ci
1597bf215546Sopenharmony_ci   assert(texObj);
1598bf215546Sopenharmony_ci   assert(valid_texture_object(texObj));
1599bf215546Sopenharmony_ci
1600bf215546Sopenharmony_ci   targetIndex = texObj->TargetIndex;
1601bf215546Sopenharmony_ci   assert(targetIndex >= 0);
1602bf215546Sopenharmony_ci   assert(targetIndex < NUM_TEXTURE_TARGETS);
1603bf215546Sopenharmony_ci
1604bf215546Sopenharmony_ci   /* Check if this texture is only used by this context and is already bound.
1605bf215546Sopenharmony_ci    * If so, just return. For GL_OES_image_external, rebinding the texture
1606bf215546Sopenharmony_ci    * always must invalidate cached resources.
1607bf215546Sopenharmony_ci    */
1608bf215546Sopenharmony_ci   if (targetIndex != TEXTURE_EXTERNAL_INDEX &&
1609bf215546Sopenharmony_ci       ctx->Shared->RefCount == 1 &&
1610bf215546Sopenharmony_ci       texObj == texUnit->CurrentTex[targetIndex])
1611bf215546Sopenharmony_ci      return;
1612bf215546Sopenharmony_ci
1613bf215546Sopenharmony_ci   /* Flush before changing binding.
1614bf215546Sopenharmony_ci    *
1615bf215546Sopenharmony_ci    * Note: Multisample textures don't need to flag GL_TEXTURE_BIT because
1616bf215546Sopenharmony_ci    *       they are not restored by glPopAttrib according to the GL 4.6
1617bf215546Sopenharmony_ci    *       Compatibility Profile specification. We set GL_TEXTURE_BIT anyway
1618bf215546Sopenharmony_ci    *       to simplify the code. This has no effect on behavior.
1619bf215546Sopenharmony_ci    */
1620bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT);
1621bf215546Sopenharmony_ci
1622bf215546Sopenharmony_ci   /* if the previously bound texture uses GL_CLAMP, flag the driver here
1623bf215546Sopenharmony_ci    * to ensure any emulation is disabled
1624bf215546Sopenharmony_ci    */
1625bf215546Sopenharmony_ci   if (texUnit->CurrentTex[targetIndex] &&
1626bf215546Sopenharmony_ci       texUnit->CurrentTex[targetIndex]->Sampler.glclamp_mask !=
1627bf215546Sopenharmony_ci       texObj->Sampler.glclamp_mask)
1628bf215546Sopenharmony_ci      ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
1629bf215546Sopenharmony_ci
1630bf215546Sopenharmony_ci   /* If the refcount on the previously bound texture is decremented to
1631bf215546Sopenharmony_ci    * zero, it'll be deleted here.
1632bf215546Sopenharmony_ci    */
1633bf215546Sopenharmony_ci   _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], texObj);
1634bf215546Sopenharmony_ci
1635bf215546Sopenharmony_ci   ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1636bf215546Sopenharmony_ci                                         unit + 1);
1637bf215546Sopenharmony_ci
1638bf215546Sopenharmony_ci   if (texObj->Name != 0)
1639bf215546Sopenharmony_ci      texUnit->_BoundTextures |= (1 << targetIndex);
1640bf215546Sopenharmony_ci   else
1641bf215546Sopenharmony_ci      texUnit->_BoundTextures &= ~(1 << targetIndex);
1642bf215546Sopenharmony_ci}
1643bf215546Sopenharmony_ci
1644bf215546Sopenharmony_cistruct gl_texture_object *
1645bf215546Sopenharmony_ci_mesa_lookup_or_create_texture(struct gl_context *ctx, GLenum target,
1646bf215546Sopenharmony_ci                               GLuint texName, bool no_error, bool is_ext_dsa,
1647bf215546Sopenharmony_ci                               const char *caller)
1648bf215546Sopenharmony_ci{
1649bf215546Sopenharmony_ci   struct gl_texture_object *newTexObj = NULL;
1650bf215546Sopenharmony_ci   int targetIndex;
1651bf215546Sopenharmony_ci
1652bf215546Sopenharmony_ci   if (is_ext_dsa) {
1653bf215546Sopenharmony_ci      if (_mesa_is_proxy_texture(target)) {
1654bf215546Sopenharmony_ci         /* EXT_dsa allows proxy targets only when texName is 0 */
1655bf215546Sopenharmony_ci         if (texName != 0) {
1656bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_OPERATION, "%s(target = %s)", caller,
1657bf215546Sopenharmony_ci                        _mesa_enum_to_string(target));
1658bf215546Sopenharmony_ci            return NULL;
1659bf215546Sopenharmony_ci         }
1660bf215546Sopenharmony_ci         return _mesa_get_current_tex_object(ctx, target);
1661bf215546Sopenharmony_ci      }
1662bf215546Sopenharmony_ci      if (GL_TEXTURE_CUBE_MAP_POSITIVE_X <= target &&
1663bf215546Sopenharmony_ci          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
1664bf215546Sopenharmony_ci         target = GL_TEXTURE_CUBE_MAP;
1665bf215546Sopenharmony_ci      }
1666bf215546Sopenharmony_ci   }
1667bf215546Sopenharmony_ci
1668bf215546Sopenharmony_ci   targetIndex = _mesa_tex_target_to_index(ctx, target);
1669bf215546Sopenharmony_ci   if (!no_error && targetIndex < 0) {
1670bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target = %s)", caller,
1671bf215546Sopenharmony_ci                  _mesa_enum_to_string(target));
1672bf215546Sopenharmony_ci      return NULL;
1673bf215546Sopenharmony_ci   }
1674bf215546Sopenharmony_ci   assert(targetIndex < NUM_TEXTURE_TARGETS);
1675bf215546Sopenharmony_ci
1676bf215546Sopenharmony_ci   /*
1677bf215546Sopenharmony_ci    * Get pointer to new texture object (newTexObj)
1678bf215546Sopenharmony_ci    */
1679bf215546Sopenharmony_ci   if (texName == 0) {
1680bf215546Sopenharmony_ci      /* Use a default texture object */
1681bf215546Sopenharmony_ci      newTexObj = ctx->Shared->DefaultTex[targetIndex];
1682bf215546Sopenharmony_ci   } else {
1683bf215546Sopenharmony_ci      /* non-default texture object */
1684bf215546Sopenharmony_ci      newTexObj = _mesa_lookup_texture(ctx, texName);
1685bf215546Sopenharmony_ci      if (newTexObj) {
1686bf215546Sopenharmony_ci         /* error checking */
1687bf215546Sopenharmony_ci         if (!no_error &&
1688bf215546Sopenharmony_ci             newTexObj->Target != 0 && newTexObj->Target != target) {
1689bf215546Sopenharmony_ci            /* The named texture object's target doesn't match the
1690bf215546Sopenharmony_ci             * given target
1691bf215546Sopenharmony_ci             */
1692bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_OPERATION,
1693bf215546Sopenharmony_ci                        "%s(target mismatch)", caller);
1694bf215546Sopenharmony_ci            return NULL;
1695bf215546Sopenharmony_ci         }
1696bf215546Sopenharmony_ci         if (newTexObj->Target == 0) {
1697bf215546Sopenharmony_ci            finish_texture_init(ctx, target, newTexObj, targetIndex);
1698bf215546Sopenharmony_ci         }
1699bf215546Sopenharmony_ci      } else {
1700bf215546Sopenharmony_ci         if (!no_error && ctx->API == API_OPENGL_CORE) {
1701bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_OPERATION,
1702bf215546Sopenharmony_ci                        "%s(non-gen name)", caller);
1703bf215546Sopenharmony_ci            return NULL;
1704bf215546Sopenharmony_ci         }
1705bf215546Sopenharmony_ci
1706bf215546Sopenharmony_ci         /* if this is a new texture id, allocate a texture object now */
1707bf215546Sopenharmony_ci         newTexObj = _mesa_new_texture_object(ctx, texName, target);
1708bf215546Sopenharmony_ci         if (!newTexObj) {
1709bf215546Sopenharmony_ci            _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
1710bf215546Sopenharmony_ci            return NULL;
1711bf215546Sopenharmony_ci         }
1712bf215546Sopenharmony_ci
1713bf215546Sopenharmony_ci         /* and insert it into hash table */
1714bf215546Sopenharmony_ci         _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj, false);
1715bf215546Sopenharmony_ci      }
1716bf215546Sopenharmony_ci   }
1717bf215546Sopenharmony_ci
1718bf215546Sopenharmony_ci   assert(newTexObj->Target == target);
1719bf215546Sopenharmony_ci   assert(newTexObj->TargetIndex == targetIndex);
1720bf215546Sopenharmony_ci
1721bf215546Sopenharmony_ci   return newTexObj;
1722bf215546Sopenharmony_ci}
1723bf215546Sopenharmony_ci
1724bf215546Sopenharmony_ci/**
1725bf215546Sopenharmony_ci * Implement glBindTexture().  Do error checking, look-up or create a new
1726bf215546Sopenharmony_ci * texture object, then bind it in the current texture unit.
1727bf215546Sopenharmony_ci *
1728bf215546Sopenharmony_ci * \param target texture target.
1729bf215546Sopenharmony_ci * \param texName texture name.
1730bf215546Sopenharmony_ci * \param texunit texture unit.
1731bf215546Sopenharmony_ci */
1732bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1733bf215546Sopenharmony_cibind_texture(struct gl_context *ctx, GLenum target, GLuint texName,
1734bf215546Sopenharmony_ci             GLenum texunit, bool no_error, const char *caller)
1735bf215546Sopenharmony_ci{
1736bf215546Sopenharmony_ci   struct gl_texture_object *newTexObj =
1737bf215546Sopenharmony_ci      _mesa_lookup_or_create_texture(ctx, target, texName, no_error, false,
1738bf215546Sopenharmony_ci                                     caller);
1739bf215546Sopenharmony_ci   if (!newTexObj)
1740bf215546Sopenharmony_ci      return;
1741bf215546Sopenharmony_ci
1742bf215546Sopenharmony_ci   bind_texture_object(ctx, texunit, newTexObj);
1743bf215546Sopenharmony_ci}
1744bf215546Sopenharmony_ci
1745bf215546Sopenharmony_civoid GLAPIENTRY
1746bf215546Sopenharmony_ci_mesa_BindTexture_no_error(GLenum target, GLuint texName)
1747bf215546Sopenharmony_ci{
1748bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1749bf215546Sopenharmony_ci   bind_texture(ctx, target, texName, ctx->Texture.CurrentUnit, true,
1750bf215546Sopenharmony_ci                "glBindTexture");
1751bf215546Sopenharmony_ci}
1752bf215546Sopenharmony_ci
1753bf215546Sopenharmony_ci
1754bf215546Sopenharmony_civoid GLAPIENTRY
1755bf215546Sopenharmony_ci_mesa_BindTexture(GLenum target, GLuint texName)
1756bf215546Sopenharmony_ci{
1757bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1758bf215546Sopenharmony_ci
1759bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1760bf215546Sopenharmony_ci      _mesa_debug(ctx, "glBindTexture %s %d\n",
1761bf215546Sopenharmony_ci                  _mesa_enum_to_string(target), (GLint) texName);
1762bf215546Sopenharmony_ci
1763bf215546Sopenharmony_ci   bind_texture(ctx, target, texName, ctx->Texture.CurrentUnit, false,
1764bf215546Sopenharmony_ci                "glBindTexture");
1765bf215546Sopenharmony_ci}
1766bf215546Sopenharmony_ci
1767bf215546Sopenharmony_ci
1768bf215546Sopenharmony_civoid GLAPIENTRY
1769bf215546Sopenharmony_ci_mesa_BindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture)
1770bf215546Sopenharmony_ci{
1771bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1772bf215546Sopenharmony_ci
1773bf215546Sopenharmony_ci   unsigned unit = texunit - GL_TEXTURE0;
1774bf215546Sopenharmony_ci
1775bf215546Sopenharmony_ci   if (texunit < GL_TEXTURE0 || unit >= _mesa_max_tex_unit(ctx)) {
1776bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glBindMultiTextureEXT(texunit=%s)",
1777bf215546Sopenharmony_ci                  _mesa_enum_to_string(texunit));
1778bf215546Sopenharmony_ci      return;
1779bf215546Sopenharmony_ci   }
1780bf215546Sopenharmony_ci
1781bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1782bf215546Sopenharmony_ci      _mesa_debug(ctx, "glBindMultiTextureEXT %s %d\n",
1783bf215546Sopenharmony_ci                  _mesa_enum_to_string(texunit), (GLint) texture);
1784bf215546Sopenharmony_ci
1785bf215546Sopenharmony_ci   bind_texture(ctx, target, texture, unit, false, "glBindMultiTextureEXT");
1786bf215546Sopenharmony_ci}
1787bf215546Sopenharmony_ci
1788bf215546Sopenharmony_ci
1789bf215546Sopenharmony_ci/**
1790bf215546Sopenharmony_ci * OpenGL 4.5 / GL_ARB_direct_state_access glBindTextureUnit().
1791bf215546Sopenharmony_ci *
1792bf215546Sopenharmony_ci * \param unit texture unit.
1793bf215546Sopenharmony_ci * \param texture texture name.
1794bf215546Sopenharmony_ci *
1795bf215546Sopenharmony_ci * \sa glBindTexture().
1796bf215546Sopenharmony_ci *
1797bf215546Sopenharmony_ci * If the named texture is 0, this will reset each target for the specified
1798bf215546Sopenharmony_ci * texture unit to its default texture.
1799bf215546Sopenharmony_ci * If the named texture is not 0 or a recognized texture name, this throws
1800bf215546Sopenharmony_ci * GL_INVALID_OPERATION.
1801bf215546Sopenharmony_ci */
1802bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1803bf215546Sopenharmony_cibind_texture_unit(struct gl_context *ctx, GLuint unit, GLuint texture,
1804bf215546Sopenharmony_ci                  bool no_error)
1805bf215546Sopenharmony_ci{
1806bf215546Sopenharmony_ci   struct gl_texture_object *texObj;
1807bf215546Sopenharmony_ci
1808bf215546Sopenharmony_ci   /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
1809bf215546Sopenharmony_ci    * (20141030) says:
1810bf215546Sopenharmony_ci    *    "When texture is zero, each of the targets enumerated at the
1811bf215546Sopenharmony_ci    *    beginning of this section is reset to its default texture for the
1812bf215546Sopenharmony_ci    *    corresponding texture image unit."
1813bf215546Sopenharmony_ci    */
1814bf215546Sopenharmony_ci   if (texture == 0) {
1815bf215546Sopenharmony_ci      unbind_textures_from_unit(ctx, unit);
1816bf215546Sopenharmony_ci      return;
1817bf215546Sopenharmony_ci   }
1818bf215546Sopenharmony_ci
1819bf215546Sopenharmony_ci   /* Get the non-default texture object */
1820bf215546Sopenharmony_ci   texObj = _mesa_lookup_texture(ctx, texture);
1821bf215546Sopenharmony_ci   if (!no_error) {
1822bf215546Sopenharmony_ci      /* Error checking */
1823bf215546Sopenharmony_ci      if (!texObj) {
1824bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION,
1825bf215546Sopenharmony_ci                     "glBindTextureUnit(non-gen name)");
1826bf215546Sopenharmony_ci         return;
1827bf215546Sopenharmony_ci      }
1828bf215546Sopenharmony_ci
1829bf215546Sopenharmony_ci      if (texObj->Target == 0) {
1830bf215546Sopenharmony_ci         /* Texture object was gen'd but never bound so the target is not set */
1831bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTextureUnit(target)");
1832bf215546Sopenharmony_ci         return;
1833bf215546Sopenharmony_ci      }
1834bf215546Sopenharmony_ci   }
1835bf215546Sopenharmony_ci
1836bf215546Sopenharmony_ci   assert(valid_texture_object(texObj));
1837bf215546Sopenharmony_ci
1838bf215546Sopenharmony_ci   bind_texture_object(ctx, unit, texObj);
1839bf215546Sopenharmony_ci}
1840bf215546Sopenharmony_ci
1841bf215546Sopenharmony_ci
1842bf215546Sopenharmony_civoid GLAPIENTRY
1843bf215546Sopenharmony_ci_mesa_BindTextureUnit_no_error(GLuint unit, GLuint texture)
1844bf215546Sopenharmony_ci{
1845bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1846bf215546Sopenharmony_ci   bind_texture_unit(ctx, unit, texture, true);
1847bf215546Sopenharmony_ci}
1848bf215546Sopenharmony_ci
1849bf215546Sopenharmony_ci
1850bf215546Sopenharmony_civoid GLAPIENTRY
1851bf215546Sopenharmony_ci_mesa_BindTextureUnit(GLuint unit, GLuint texture)
1852bf215546Sopenharmony_ci{
1853bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1854bf215546Sopenharmony_ci
1855bf215546Sopenharmony_ci   if (unit >= _mesa_max_tex_unit(ctx)) {
1856bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glBindTextureUnit(unit=%u)", unit);
1857bf215546Sopenharmony_ci      return;
1858bf215546Sopenharmony_ci   }
1859bf215546Sopenharmony_ci
1860bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1861bf215546Sopenharmony_ci      _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
1862bf215546Sopenharmony_ci                  _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture);
1863bf215546Sopenharmony_ci
1864bf215546Sopenharmony_ci   bind_texture_unit(ctx, unit, texture, false);
1865bf215546Sopenharmony_ci}
1866bf215546Sopenharmony_ci
1867bf215546Sopenharmony_ci
1868bf215546Sopenharmony_ci/**
1869bf215546Sopenharmony_ci * OpenGL 4.4 / GL_ARB_multi_bind glBindTextures().
1870bf215546Sopenharmony_ci */
1871bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1872bf215546Sopenharmony_cibind_textures(struct gl_context *ctx, GLuint first, GLsizei count,
1873bf215546Sopenharmony_ci              const GLuint *textures, bool no_error)
1874bf215546Sopenharmony_ci{
1875bf215546Sopenharmony_ci   GLsizei i;
1876bf215546Sopenharmony_ci
1877bf215546Sopenharmony_ci   if (textures) {
1878bf215546Sopenharmony_ci      /* Note that the error semantics for multi-bind commands differ from
1879bf215546Sopenharmony_ci       * those of other GL commands.
1880bf215546Sopenharmony_ci       *
1881bf215546Sopenharmony_ci       * The issues section in the ARB_multi_bind spec says:
1882bf215546Sopenharmony_ci       *
1883bf215546Sopenharmony_ci       *    "(11) Typically, OpenGL specifies that if an error is generated by
1884bf215546Sopenharmony_ci       *          a command, that command has no effect.  This is somewhat
1885bf215546Sopenharmony_ci       *          unfortunate for multi-bind commands, because it would require
1886bf215546Sopenharmony_ci       *          a first pass to scan the entire list of bound objects for
1887bf215546Sopenharmony_ci       *          errors and then a second pass to actually perform the
1888bf215546Sopenharmony_ci       *          bindings.  Should we have different error semantics?
1889bf215546Sopenharmony_ci       *
1890bf215546Sopenharmony_ci       *       RESOLVED:  Yes.  In this specification, when the parameters for
1891bf215546Sopenharmony_ci       *       one of the <count> binding points are invalid, that binding
1892bf215546Sopenharmony_ci       *       point is not updated and an error will be generated.  However,
1893bf215546Sopenharmony_ci       *       other binding points in the same command will be updated if
1894bf215546Sopenharmony_ci       *       their parameters are valid and no other error occurs."
1895bf215546Sopenharmony_ci       */
1896bf215546Sopenharmony_ci
1897bf215546Sopenharmony_ci      _mesa_HashLockMutex(ctx->Shared->TexObjects);
1898bf215546Sopenharmony_ci
1899bf215546Sopenharmony_ci      for (i = 0; i < count; i++) {
1900bf215546Sopenharmony_ci         if (textures[i] != 0) {
1901bf215546Sopenharmony_ci            struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
1902bf215546Sopenharmony_ci            struct gl_texture_object *current = texUnit->_Current;
1903bf215546Sopenharmony_ci            struct gl_texture_object *texObj;
1904bf215546Sopenharmony_ci
1905bf215546Sopenharmony_ci            if (current && current->Name == textures[i])
1906bf215546Sopenharmony_ci               texObj = current;
1907bf215546Sopenharmony_ci            else
1908bf215546Sopenharmony_ci               texObj = _mesa_lookup_texture_locked(ctx, textures[i]);
1909bf215546Sopenharmony_ci
1910bf215546Sopenharmony_ci            if (texObj && texObj->Target != 0) {
1911bf215546Sopenharmony_ci               bind_texture_object(ctx, first + i, texObj);
1912bf215546Sopenharmony_ci            } else if (!no_error) {
1913bf215546Sopenharmony_ci               /* The ARB_multi_bind spec says:
1914bf215546Sopenharmony_ci                *
1915bf215546Sopenharmony_ci                *     "An INVALID_OPERATION error is generated if any value
1916bf215546Sopenharmony_ci                *      in <textures> is not zero or the name of an existing
1917bf215546Sopenharmony_ci                *      texture object (per binding)."
1918bf215546Sopenharmony_ci                */
1919bf215546Sopenharmony_ci               _mesa_error(ctx, GL_INVALID_OPERATION,
1920bf215546Sopenharmony_ci                           "glBindTextures(textures[%d]=%u is not zero "
1921bf215546Sopenharmony_ci                           "or the name of an existing texture object)",
1922bf215546Sopenharmony_ci                           i, textures[i]);
1923bf215546Sopenharmony_ci            }
1924bf215546Sopenharmony_ci         } else {
1925bf215546Sopenharmony_ci            unbind_textures_from_unit(ctx, first + i);
1926bf215546Sopenharmony_ci         }
1927bf215546Sopenharmony_ci      }
1928bf215546Sopenharmony_ci
1929bf215546Sopenharmony_ci      _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
1930bf215546Sopenharmony_ci   } else {
1931bf215546Sopenharmony_ci      /* Unbind all textures in the range <first> through <first>+<count>-1 */
1932bf215546Sopenharmony_ci      for (i = 0; i < count; i++)
1933bf215546Sopenharmony_ci         unbind_textures_from_unit(ctx, first + i);
1934bf215546Sopenharmony_ci   }
1935bf215546Sopenharmony_ci}
1936bf215546Sopenharmony_ci
1937bf215546Sopenharmony_ci
1938bf215546Sopenharmony_civoid GLAPIENTRY
1939bf215546Sopenharmony_ci_mesa_BindTextures_no_error(GLuint first, GLsizei count, const GLuint *textures)
1940bf215546Sopenharmony_ci{
1941bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1942bf215546Sopenharmony_ci   bind_textures(ctx, first, count, textures, true);
1943bf215546Sopenharmony_ci}
1944bf215546Sopenharmony_ci
1945bf215546Sopenharmony_ci
1946bf215546Sopenharmony_civoid GLAPIENTRY
1947bf215546Sopenharmony_ci_mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
1948bf215546Sopenharmony_ci{
1949bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1950bf215546Sopenharmony_ci
1951bf215546Sopenharmony_ci   /* The ARB_multi_bind spec says:
1952bf215546Sopenharmony_ci    *
1953bf215546Sopenharmony_ci    *     "An INVALID_OPERATION error is generated if <first> + <count>
1954bf215546Sopenharmony_ci    *      is greater than the number of texture image units supported
1955bf215546Sopenharmony_ci    *      by the implementation."
1956bf215546Sopenharmony_ci    */
1957bf215546Sopenharmony_ci   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
1958bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
1959bf215546Sopenharmony_ci                  "glBindTextures(first=%u + count=%d > the value of "
1960bf215546Sopenharmony_ci                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
1961bf215546Sopenharmony_ci                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
1962bf215546Sopenharmony_ci      return;
1963bf215546Sopenharmony_ci   }
1964bf215546Sopenharmony_ci
1965bf215546Sopenharmony_ci   bind_textures(ctx, first, count, textures, false);
1966bf215546Sopenharmony_ci}
1967bf215546Sopenharmony_ci
1968bf215546Sopenharmony_ci
1969bf215546Sopenharmony_ci/**
1970bf215546Sopenharmony_ci * Set texture priorities.
1971bf215546Sopenharmony_ci *
1972bf215546Sopenharmony_ci * \param n number of textures.
1973bf215546Sopenharmony_ci * \param texName texture names.
1974bf215546Sopenharmony_ci * \param priorities corresponding texture priorities.
1975bf215546Sopenharmony_ci *
1976bf215546Sopenharmony_ci * \sa glPrioritizeTextures().
1977bf215546Sopenharmony_ci *
1978bf215546Sopenharmony_ci * Looks up each texture in the hash, clamps the corresponding priority between
1979bf215546Sopenharmony_ci * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
1980bf215546Sopenharmony_ci */
1981bf215546Sopenharmony_civoid GLAPIENTRY
1982bf215546Sopenharmony_ci_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
1983bf215546Sopenharmony_ci                          const GLclampf *priorities )
1984bf215546Sopenharmony_ci{
1985bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1986bf215546Sopenharmony_ci   GLint i;
1987bf215546Sopenharmony_ci
1988bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1989bf215546Sopenharmony_ci      _mesa_debug(ctx, "glPrioritizeTextures %d\n", n);
1990bf215546Sopenharmony_ci
1991bf215546Sopenharmony_ci
1992bf215546Sopenharmony_ci   if (n < 0) {
1993bf215546Sopenharmony_ci      _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
1994bf215546Sopenharmony_ci      return;
1995bf215546Sopenharmony_ci   }
1996bf215546Sopenharmony_ci
1997bf215546Sopenharmony_ci   if (!priorities)
1998bf215546Sopenharmony_ci      return;
1999bf215546Sopenharmony_ci
2000bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT);
2001bf215546Sopenharmony_ci
2002bf215546Sopenharmony_ci   for (i = 0; i < n; i++) {
2003bf215546Sopenharmony_ci      if (texName[i] > 0) {
2004bf215546Sopenharmony_ci         struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
2005bf215546Sopenharmony_ci         if (t) {
2006bf215546Sopenharmony_ci            t->Attrib.Priority = CLAMP( priorities[i], 0.0F, 1.0F );
2007bf215546Sopenharmony_ci         }
2008bf215546Sopenharmony_ci      }
2009bf215546Sopenharmony_ci   }
2010bf215546Sopenharmony_ci}
2011bf215546Sopenharmony_ci
2012bf215546Sopenharmony_ci
2013bf215546Sopenharmony_ci
2014bf215546Sopenharmony_ci/**
2015bf215546Sopenharmony_ci * See if textures are loaded in texture memory.
2016bf215546Sopenharmony_ci *
2017bf215546Sopenharmony_ci * \param n number of textures to query.
2018bf215546Sopenharmony_ci * \param texName array with the texture names.
2019bf215546Sopenharmony_ci * \param residences array which will hold the residence status.
2020bf215546Sopenharmony_ci *
2021bf215546Sopenharmony_ci * \return GL_TRUE if all textures are resident and
2022bf215546Sopenharmony_ci *                 residences is left unchanged,
2023bf215546Sopenharmony_ci *
2024bf215546Sopenharmony_ci * Note: we assume all textures are always resident
2025bf215546Sopenharmony_ci */
2026bf215546Sopenharmony_ciGLboolean GLAPIENTRY
2027bf215546Sopenharmony_ci_mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
2028bf215546Sopenharmony_ci                          GLboolean *residences)
2029bf215546Sopenharmony_ci{
2030bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2031bf215546Sopenharmony_ci   GLboolean allResident = GL_TRUE;
2032bf215546Sopenharmony_ci   GLint i;
2033bf215546Sopenharmony_ci   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2034bf215546Sopenharmony_ci
2035bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2036bf215546Sopenharmony_ci      _mesa_debug(ctx, "glAreTexturesResident %d\n", n);
2037bf215546Sopenharmony_ci
2038bf215546Sopenharmony_ci   if (n < 0) {
2039bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
2040bf215546Sopenharmony_ci      return GL_FALSE;
2041bf215546Sopenharmony_ci   }
2042bf215546Sopenharmony_ci
2043bf215546Sopenharmony_ci   if (!texName || !residences)
2044bf215546Sopenharmony_ci      return GL_FALSE;
2045bf215546Sopenharmony_ci
2046bf215546Sopenharmony_ci   /* We only do error checking on the texture names */
2047bf215546Sopenharmony_ci   for (i = 0; i < n; i++) {
2048bf215546Sopenharmony_ci      struct gl_texture_object *t;
2049bf215546Sopenharmony_ci      if (texName[i] == 0) {
2050bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
2051bf215546Sopenharmony_ci         return GL_FALSE;
2052bf215546Sopenharmony_ci      }
2053bf215546Sopenharmony_ci      t = _mesa_lookup_texture(ctx, texName[i]);
2054bf215546Sopenharmony_ci      if (!t) {
2055bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
2056bf215546Sopenharmony_ci         return GL_FALSE;
2057bf215546Sopenharmony_ci      }
2058bf215546Sopenharmony_ci   }
2059bf215546Sopenharmony_ci
2060bf215546Sopenharmony_ci   return allResident;
2061bf215546Sopenharmony_ci}
2062bf215546Sopenharmony_ci
2063bf215546Sopenharmony_ci
2064bf215546Sopenharmony_ci/**
2065bf215546Sopenharmony_ci * See if a name corresponds to a texture.
2066bf215546Sopenharmony_ci *
2067bf215546Sopenharmony_ci * \param texture texture name.
2068bf215546Sopenharmony_ci *
2069bf215546Sopenharmony_ci * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
2070bf215546Sopenharmony_ci * otherwise.
2071bf215546Sopenharmony_ci *
2072bf215546Sopenharmony_ci * \sa glIsTexture().
2073bf215546Sopenharmony_ci *
2074bf215546Sopenharmony_ci * Calls _mesa_HashLookup().
2075bf215546Sopenharmony_ci */
2076bf215546Sopenharmony_ciGLboolean GLAPIENTRY
2077bf215546Sopenharmony_ci_mesa_IsTexture( GLuint texture )
2078bf215546Sopenharmony_ci{
2079bf215546Sopenharmony_ci   struct gl_texture_object *t;
2080bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2081bf215546Sopenharmony_ci   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2082bf215546Sopenharmony_ci
2083bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2084bf215546Sopenharmony_ci      _mesa_debug(ctx, "glIsTexture %d\n", texture);
2085bf215546Sopenharmony_ci
2086bf215546Sopenharmony_ci   if (!texture)
2087bf215546Sopenharmony_ci      return GL_FALSE;
2088bf215546Sopenharmony_ci
2089bf215546Sopenharmony_ci   t = _mesa_lookup_texture(ctx, texture);
2090bf215546Sopenharmony_ci
2091bf215546Sopenharmony_ci   /* IsTexture is true only after object has been bound once. */
2092bf215546Sopenharmony_ci   return t && t->Target;
2093bf215546Sopenharmony_ci}
2094bf215546Sopenharmony_ci
2095bf215546Sopenharmony_ci
2096bf215546Sopenharmony_ci/**
2097bf215546Sopenharmony_ci * Simplest implementation of texture locking: grab the shared tex
2098bf215546Sopenharmony_ci * mutex.  Examine the shared context state timestamp and if there has
2099bf215546Sopenharmony_ci * been a change, set the appropriate bits in ctx->NewState.
2100bf215546Sopenharmony_ci *
2101bf215546Sopenharmony_ci * This is used to deal with synchronizing things when a texture object
2102bf215546Sopenharmony_ci * is used/modified by different contexts (or threads) which are sharing
2103bf215546Sopenharmony_ci * the texture.
2104bf215546Sopenharmony_ci *
2105bf215546Sopenharmony_ci * See also _mesa_lock/unlock_texture() in teximage.h
2106bf215546Sopenharmony_ci */
2107bf215546Sopenharmony_civoid
2108bf215546Sopenharmony_ci_mesa_lock_context_textures( struct gl_context *ctx )
2109bf215546Sopenharmony_ci{
2110bf215546Sopenharmony_ci   if (!ctx->TexturesLocked)
2111bf215546Sopenharmony_ci      simple_mtx_lock(&ctx->Shared->TexMutex);
2112bf215546Sopenharmony_ci
2113bf215546Sopenharmony_ci   if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
2114bf215546Sopenharmony_ci      ctx->NewState |= _NEW_TEXTURE_OBJECT;
2115bf215546Sopenharmony_ci      ctx->PopAttribState |= GL_TEXTURE_BIT;
2116bf215546Sopenharmony_ci      ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
2117bf215546Sopenharmony_ci   }
2118bf215546Sopenharmony_ci}
2119bf215546Sopenharmony_ci
2120bf215546Sopenharmony_ci
2121bf215546Sopenharmony_civoid
2122bf215546Sopenharmony_ci_mesa_unlock_context_textures( struct gl_context *ctx )
2123bf215546Sopenharmony_ci{
2124bf215546Sopenharmony_ci   assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
2125bf215546Sopenharmony_ci   if (!ctx->TexturesLocked)
2126bf215546Sopenharmony_ci      simple_mtx_unlock(&ctx->Shared->TexMutex);
2127bf215546Sopenharmony_ci}
2128bf215546Sopenharmony_ci
2129bf215546Sopenharmony_ci
2130bf215546Sopenharmony_civoid GLAPIENTRY
2131bf215546Sopenharmony_ci_mesa_InvalidateTexSubImage_no_error(GLuint texture, GLint level, GLint xoffset,
2132bf215546Sopenharmony_ci                                     GLint yoffset, GLint zoffset,
2133bf215546Sopenharmony_ci                                     GLsizei width, GLsizei height,
2134bf215546Sopenharmony_ci                                     GLsizei depth)
2135bf215546Sopenharmony_ci{
2136bf215546Sopenharmony_ci   /* no-op */
2137bf215546Sopenharmony_ci}
2138bf215546Sopenharmony_ci
2139bf215546Sopenharmony_ci
2140bf215546Sopenharmony_civoid GLAPIENTRY
2141bf215546Sopenharmony_ci_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
2142bf215546Sopenharmony_ci                            GLint yoffset, GLint zoffset, GLsizei width,
2143bf215546Sopenharmony_ci                            GLsizei height, GLsizei depth)
2144bf215546Sopenharmony_ci{
2145bf215546Sopenharmony_ci   struct gl_texture_object *t;
2146bf215546Sopenharmony_ci   struct gl_texture_image *image;
2147bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2148bf215546Sopenharmony_ci
2149bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2150bf215546Sopenharmony_ci      _mesa_debug(ctx, "glInvalidateTexSubImage %d\n", texture);
2151bf215546Sopenharmony_ci
2152bf215546Sopenharmony_ci   t = invalidate_tex_image_error_check(ctx, texture, level,
2153bf215546Sopenharmony_ci                                        "glInvalidateTexSubImage");
2154bf215546Sopenharmony_ci
2155bf215546Sopenharmony_ci   /* The GL_ARB_invalidate_subdata spec says:
2156bf215546Sopenharmony_ci    *
2157bf215546Sopenharmony_ci    *     "...the specified subregion must be between -<b> and <dim>+<b> where
2158bf215546Sopenharmony_ci    *     <dim> is the size of the dimension of the texture image, and <b> is
2159bf215546Sopenharmony_ci    *     the size of the border of that texture image, otherwise
2160bf215546Sopenharmony_ci    *     INVALID_VALUE is generated (border is not applied to dimensions that
2161bf215546Sopenharmony_ci    *     don't exist in a given texture target)."
2162bf215546Sopenharmony_ci    */
2163bf215546Sopenharmony_ci   image = t->Image[0][level];
2164bf215546Sopenharmony_ci   if (image) {
2165bf215546Sopenharmony_ci      int xBorder;
2166bf215546Sopenharmony_ci      int yBorder;
2167bf215546Sopenharmony_ci      int zBorder;
2168bf215546Sopenharmony_ci      int imageWidth;
2169bf215546Sopenharmony_ci      int imageHeight;
2170bf215546Sopenharmony_ci      int imageDepth;
2171bf215546Sopenharmony_ci
2172bf215546Sopenharmony_ci      /* The GL_ARB_invalidate_subdata spec says:
2173bf215546Sopenharmony_ci       *
2174bf215546Sopenharmony_ci       *     "For texture targets that don't have certain dimensions, this
2175bf215546Sopenharmony_ci       *     command treats those dimensions as having a size of 1. For
2176bf215546Sopenharmony_ci       *     example, to invalidate a portion of a two-dimensional texture,
2177bf215546Sopenharmony_ci       *     the application would use <zoffset> equal to zero and <depth>
2178bf215546Sopenharmony_ci       *     equal to one."
2179bf215546Sopenharmony_ci       */
2180bf215546Sopenharmony_ci      switch (t->Target) {
2181bf215546Sopenharmony_ci      case GL_TEXTURE_BUFFER:
2182bf215546Sopenharmony_ci         xBorder = 0;
2183bf215546Sopenharmony_ci         yBorder = 0;
2184bf215546Sopenharmony_ci         zBorder = 0;
2185bf215546Sopenharmony_ci         imageWidth = 1;
2186bf215546Sopenharmony_ci         imageHeight = 1;
2187bf215546Sopenharmony_ci         imageDepth = 1;
2188bf215546Sopenharmony_ci         break;
2189bf215546Sopenharmony_ci      case GL_TEXTURE_1D:
2190bf215546Sopenharmony_ci         xBorder = image->Border;
2191bf215546Sopenharmony_ci         yBorder = 0;
2192bf215546Sopenharmony_ci         zBorder = 0;
2193bf215546Sopenharmony_ci         imageWidth = image->Width;
2194bf215546Sopenharmony_ci         imageHeight = 1;
2195bf215546Sopenharmony_ci         imageDepth = 1;
2196bf215546Sopenharmony_ci         break;
2197bf215546Sopenharmony_ci      case GL_TEXTURE_1D_ARRAY:
2198bf215546Sopenharmony_ci         xBorder = image->Border;
2199bf215546Sopenharmony_ci         yBorder = 0;
2200bf215546Sopenharmony_ci         zBorder = 0;
2201bf215546Sopenharmony_ci         imageWidth = image->Width;
2202bf215546Sopenharmony_ci         imageHeight = image->Height;
2203bf215546Sopenharmony_ci         imageDepth = 1;
2204bf215546Sopenharmony_ci         break;
2205bf215546Sopenharmony_ci      case GL_TEXTURE_2D:
2206bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP:
2207bf215546Sopenharmony_ci      case GL_TEXTURE_RECTANGLE:
2208bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE:
2209bf215546Sopenharmony_ci         xBorder = image->Border;
2210bf215546Sopenharmony_ci         yBorder = image->Border;
2211bf215546Sopenharmony_ci         zBorder = 0;
2212bf215546Sopenharmony_ci         imageWidth = image->Width;
2213bf215546Sopenharmony_ci         imageHeight = image->Height;
2214bf215546Sopenharmony_ci         imageDepth = 1;
2215bf215546Sopenharmony_ci         break;
2216bf215546Sopenharmony_ci      case GL_TEXTURE_2D_ARRAY:
2217bf215546Sopenharmony_ci      case GL_TEXTURE_CUBE_MAP_ARRAY:
2218bf215546Sopenharmony_ci      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2219bf215546Sopenharmony_ci         xBorder = image->Border;
2220bf215546Sopenharmony_ci         yBorder = image->Border;
2221bf215546Sopenharmony_ci         zBorder = 0;
2222bf215546Sopenharmony_ci         imageWidth = image->Width;
2223bf215546Sopenharmony_ci         imageHeight = image->Height;
2224bf215546Sopenharmony_ci         imageDepth = image->Depth;
2225bf215546Sopenharmony_ci         break;
2226bf215546Sopenharmony_ci      case GL_TEXTURE_3D:
2227bf215546Sopenharmony_ci         xBorder = image->Border;
2228bf215546Sopenharmony_ci         yBorder = image->Border;
2229bf215546Sopenharmony_ci         zBorder = image->Border;
2230bf215546Sopenharmony_ci         imageWidth = image->Width;
2231bf215546Sopenharmony_ci         imageHeight = image->Height;
2232bf215546Sopenharmony_ci         imageDepth = image->Depth;
2233bf215546Sopenharmony_ci         break;
2234bf215546Sopenharmony_ci      default:
2235bf215546Sopenharmony_ci         assert(!"Should not get here.");
2236bf215546Sopenharmony_ci         xBorder = 0;
2237bf215546Sopenharmony_ci         yBorder = 0;
2238bf215546Sopenharmony_ci         zBorder = 0;
2239bf215546Sopenharmony_ci         imageWidth = 0;
2240bf215546Sopenharmony_ci         imageHeight = 0;
2241bf215546Sopenharmony_ci         imageDepth = 0;
2242bf215546Sopenharmony_ci         break;
2243bf215546Sopenharmony_ci      }
2244bf215546Sopenharmony_ci
2245bf215546Sopenharmony_ci      if (xoffset < -xBorder) {
2246bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)");
2247bf215546Sopenharmony_ci         return;
2248bf215546Sopenharmony_ci      }
2249bf215546Sopenharmony_ci
2250bf215546Sopenharmony_ci      if (xoffset + width > imageWidth + xBorder) {
2251bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
2252bf215546Sopenharmony_ci                     "glInvalidateSubTexImage(xoffset+width)");
2253bf215546Sopenharmony_ci         return;
2254bf215546Sopenharmony_ci      }
2255bf215546Sopenharmony_ci
2256bf215546Sopenharmony_ci      if (yoffset < -yBorder) {
2257bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)");
2258bf215546Sopenharmony_ci         return;
2259bf215546Sopenharmony_ci      }
2260bf215546Sopenharmony_ci
2261bf215546Sopenharmony_ci      if (yoffset + height > imageHeight + yBorder) {
2262bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
2263bf215546Sopenharmony_ci                     "glInvalidateSubTexImage(yoffset+height)");
2264bf215546Sopenharmony_ci         return;
2265bf215546Sopenharmony_ci      }
2266bf215546Sopenharmony_ci
2267bf215546Sopenharmony_ci      if (zoffset < -zBorder) {
2268bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
2269bf215546Sopenharmony_ci                     "glInvalidateSubTexImage(zoffset)");
2270bf215546Sopenharmony_ci         return;
2271bf215546Sopenharmony_ci      }
2272bf215546Sopenharmony_ci
2273bf215546Sopenharmony_ci      if (zoffset + depth  > imageDepth + zBorder) {
2274bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
2275bf215546Sopenharmony_ci                     "glInvalidateSubTexImage(zoffset+depth)");
2276bf215546Sopenharmony_ci         return;
2277bf215546Sopenharmony_ci      }
2278bf215546Sopenharmony_ci   }
2279bf215546Sopenharmony_ci
2280bf215546Sopenharmony_ci   /* We don't actually do anything for this yet.  Just return after
2281bf215546Sopenharmony_ci    * validating the parameters and generating the required errors.
2282bf215546Sopenharmony_ci    */
2283bf215546Sopenharmony_ci   return;
2284bf215546Sopenharmony_ci}
2285bf215546Sopenharmony_ci
2286bf215546Sopenharmony_ci
2287bf215546Sopenharmony_civoid GLAPIENTRY
2288bf215546Sopenharmony_ci_mesa_InvalidateTexImage_no_error(GLuint texture, GLint level)
2289bf215546Sopenharmony_ci{
2290bf215546Sopenharmony_ci   /* no-op */
2291bf215546Sopenharmony_ci}
2292bf215546Sopenharmony_ci
2293bf215546Sopenharmony_ci
2294bf215546Sopenharmony_civoid GLAPIENTRY
2295bf215546Sopenharmony_ci_mesa_InvalidateTexImage(GLuint texture, GLint level)
2296bf215546Sopenharmony_ci{
2297bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2298bf215546Sopenharmony_ci
2299bf215546Sopenharmony_ci   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2300bf215546Sopenharmony_ci      _mesa_debug(ctx, "glInvalidateTexImage(%d, %d)\n", texture, level);
2301bf215546Sopenharmony_ci
2302bf215546Sopenharmony_ci   invalidate_tex_image_error_check(ctx, texture, level,
2303bf215546Sopenharmony_ci                                    "glInvalidateTexImage");
2304bf215546Sopenharmony_ci
2305bf215546Sopenharmony_ci   /* We don't actually do anything for this yet.  Just return after
2306bf215546Sopenharmony_ci    * validating the parameters and generating the required errors.
2307bf215546Sopenharmony_ci    */
2308bf215546Sopenharmony_ci   return;
2309bf215546Sopenharmony_ci}
2310bf215546Sopenharmony_ci
2311bf215546Sopenharmony_cistatic void
2312bf215546Sopenharmony_citexture_page_commitment(struct gl_context *ctx, GLenum target,
2313bf215546Sopenharmony_ci                        struct gl_texture_object *tex_obj,
2314bf215546Sopenharmony_ci                        GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
2315bf215546Sopenharmony_ci                        GLsizei width, GLsizei height, GLsizei depth,
2316bf215546Sopenharmony_ci                        GLboolean commit, const char *func)
2317bf215546Sopenharmony_ci{
2318bf215546Sopenharmony_ci   if (!tex_obj->Immutable || !tex_obj->IsSparse) {
2319bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sparse texture)", func);
2320bf215546Sopenharmony_ci      return;
2321bf215546Sopenharmony_ci   }
2322bf215546Sopenharmony_ci
2323bf215546Sopenharmony_ci   if (level < 0 || level > tex_obj->_MaxLevel) {
2324bf215546Sopenharmony_ci      /* Not in error list of ARB_sparse_texture. */
2325bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level %d)", func, level);
2326bf215546Sopenharmony_ci      return;
2327bf215546Sopenharmony_ci   }
2328bf215546Sopenharmony_ci
2329bf215546Sopenharmony_ci   struct gl_texture_image *image = tex_obj->Image[0][level];
2330bf215546Sopenharmony_ci
2331bf215546Sopenharmony_ci   int max_depth = image->Depth;
2332bf215546Sopenharmony_ci   if (target == GL_TEXTURE_CUBE_MAP)
2333bf215546Sopenharmony_ci      max_depth *= 6;
2334bf215546Sopenharmony_ci
2335bf215546Sopenharmony_ci   if (xoffset + width > image->Width ||
2336bf215546Sopenharmony_ci       yoffset + height > image->Height ||
2337bf215546Sopenharmony_ci       zoffset + depth > max_depth) {
2338bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(exceed max size)", func);
2339bf215546Sopenharmony_ci      return;
2340bf215546Sopenharmony_ci   }
2341bf215546Sopenharmony_ci
2342bf215546Sopenharmony_ci   int px, py, pz;
2343bf215546Sopenharmony_ci   bool ret = st_GetSparseTextureVirtualPageSize(
2344bf215546Sopenharmony_ci      ctx, target, image->TexFormat, tex_obj->VirtualPageSizeIndex, &px, &py, &pz);
2345bf215546Sopenharmony_ci   assert(ret);
2346bf215546Sopenharmony_ci
2347bf215546Sopenharmony_ci   if (xoffset % px || yoffset % py || zoffset % pz) {
2348bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset multiple of page size)", func);
2349bf215546Sopenharmony_ci      return;
2350bf215546Sopenharmony_ci   }
2351bf215546Sopenharmony_ci
2352bf215546Sopenharmony_ci   if ((width % px && xoffset + width != image->Width) ||
2353bf215546Sopenharmony_ci       (height % py && yoffset + height != image->Height) ||
2354bf215546Sopenharmony_ci       (depth % pz && zoffset + depth != max_depth)) {
2355bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(alignment)", func);
2356bf215546Sopenharmony_ci      return;
2357bf215546Sopenharmony_ci   }
2358bf215546Sopenharmony_ci
2359bf215546Sopenharmony_ci   st_TexturePageCommitment(ctx, tex_obj, level, xoffset, yoffset, zoffset,
2360bf215546Sopenharmony_ci                            width, height, depth, commit);
2361bf215546Sopenharmony_ci}
2362bf215546Sopenharmony_ci
2363bf215546Sopenharmony_civoid GLAPIENTRY
2364bf215546Sopenharmony_ci_mesa_TexPageCommitmentARB(GLenum target, GLint level, GLint xoffset,
2365bf215546Sopenharmony_ci                           GLint yoffset, GLint zoffset, GLsizei width,
2366bf215546Sopenharmony_ci                           GLsizei height, GLsizei depth, GLboolean commit)
2367bf215546Sopenharmony_ci{
2368bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2369bf215546Sopenharmony_ci   struct gl_texture_object *texObj;
2370bf215546Sopenharmony_ci
2371bf215546Sopenharmony_ci   texObj = _mesa_get_current_tex_object(ctx, target);
2372bf215546Sopenharmony_ci   if (!texObj) {
2373bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glTexPageCommitmentARB(target)");
2374bf215546Sopenharmony_ci      return;
2375bf215546Sopenharmony_ci   }
2376bf215546Sopenharmony_ci
2377bf215546Sopenharmony_ci   texture_page_commitment(ctx, target, texObj, level, xoffset, yoffset, zoffset,
2378bf215546Sopenharmony_ci                           width, height, depth, commit,
2379bf215546Sopenharmony_ci                           "glTexPageCommitmentARB");
2380bf215546Sopenharmony_ci}
2381bf215546Sopenharmony_ci
2382bf215546Sopenharmony_civoid GLAPIENTRY
2383bf215546Sopenharmony_ci_mesa_TexturePageCommitmentEXT(GLuint texture, GLint level, GLint xoffset,
2384bf215546Sopenharmony_ci                               GLint yoffset, GLint zoffset, GLsizei width,
2385bf215546Sopenharmony_ci                               GLsizei height, GLsizei depth, GLboolean commit)
2386bf215546Sopenharmony_ci{
2387bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2388bf215546Sopenharmony_ci   struct gl_texture_object *texObj;
2389bf215546Sopenharmony_ci
2390bf215546Sopenharmony_ci   texObj = _mesa_lookup_texture(ctx, texture);
2391bf215546Sopenharmony_ci   if (texture == 0 || texObj == NULL) {
2392bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexturePageCommitmentEXT(texture)");
2393bf215546Sopenharmony_ci      return;
2394bf215546Sopenharmony_ci   }
2395bf215546Sopenharmony_ci
2396bf215546Sopenharmony_ci   texture_page_commitment(ctx, texObj->Target, texObj, level, xoffset, yoffset,
2397bf215546Sopenharmony_ci                           zoffset, width, height, depth, commit,
2398bf215546Sopenharmony_ci                           "glTexturePageCommitmentEXT");
2399bf215546Sopenharmony_ci}
2400bf215546Sopenharmony_ci
2401bf215546Sopenharmony_ci/*@}*/
2402