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