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