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