17117f1b4Smrg/** 27117f1b4Smrg * \file texobj.c 37117f1b4Smrg * Texture object management. 47117f1b4Smrg */ 57117f1b4Smrg 67117f1b4Smrg/* 77117f1b4Smrg * Mesa 3-D graphics library 87117f1b4Smrg * 9c1f859d4Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 107117f1b4Smrg * 117117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 127117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 137117f1b4Smrg * to deal in the Software without restriction, including without limitation 147117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 157117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 167117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 177117f1b4Smrg * 187117f1b4Smrg * The above copyright notice and this permission notice shall be included 197117f1b4Smrg * in all copies or substantial portions of the Software. 207117f1b4Smrg * 217117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 227117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 237117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 287117f1b4Smrg */ 297117f1b4Smrg 307117f1b4Smrg 3101e04c3fSmrg#include <stdio.h> 323464ebd5Sriastradh#include "bufferobj.h" 337117f1b4Smrg#include "context.h" 347117f1b4Smrg#include "enums.h" 357117f1b4Smrg#include "fbobject.h" 364a49301eSmrg#include "formats.h" 377117f1b4Smrg#include "hash.h" 387ec681f3Smrg 397117f1b4Smrg#include "macros.h" 4001e04c3fSmrg#include "shaderimage.h" 417117f1b4Smrg#include "teximage.h" 427117f1b4Smrg#include "texobj.h" 433464ebd5Sriastradh#include "texstate.h" 447117f1b4Smrg#include "mtypes.h" 453464ebd5Sriastradh#include "program/prog_instruction.h" 4601e04c3fSmrg#include "texturebindless.h" 477ec681f3Smrg#include "util/u_memory.h" 484a49301eSmrg 497117f1b4Smrg 507117f1b4Smrg 517117f1b4Smrg/**********************************************************************/ 527117f1b4Smrg/** \name Internal functions */ 537117f1b4Smrg/*@{*/ 547117f1b4Smrg 5501e04c3fSmrg/** 5601e04c3fSmrg * This function checks for all valid combinations of Min and Mag filters for 5701e04c3fSmrg * Float types, when extensions like OES_texture_float and 5801e04c3fSmrg * OES_texture_float_linear are supported. OES_texture_float mentions support 5901e04c3fSmrg * for NEAREST, NEAREST_MIPMAP_NEAREST magnification and minification filters. 6001e04c3fSmrg * Mag filters like LINEAR and min filters like NEAREST_MIPMAP_LINEAR, 6101e04c3fSmrg * LINEAR_MIPMAP_NEAREST and LINEAR_MIPMAP_LINEAR are only valid in case 6201e04c3fSmrg * OES_texture_float_linear is supported. 6301e04c3fSmrg * 6401e04c3fSmrg * Returns true in case the filter is valid for given Float type else false. 6501e04c3fSmrg */ 6601e04c3fSmrgstatic bool 6701e04c3fSmrgvalid_filter_for_float(const struct gl_context *ctx, 6801e04c3fSmrg const struct gl_texture_object *obj) 6901e04c3fSmrg{ 707ec681f3Smrg switch (obj->Sampler.Attrib.MagFilter) { 7101e04c3fSmrg case GL_LINEAR: 7201e04c3fSmrg if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) { 7301e04c3fSmrg return false; 7401e04c3fSmrg } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) { 7501e04c3fSmrg return false; 7601e04c3fSmrg } 777ec681f3Smrg FALLTHROUGH; 7801e04c3fSmrg case GL_NEAREST: 7901e04c3fSmrg case GL_NEAREST_MIPMAP_NEAREST: 8001e04c3fSmrg break; 8101e04c3fSmrg default: 8201e04c3fSmrg unreachable("Invalid mag filter"); 8301e04c3fSmrg } 8401e04c3fSmrg 857ec681f3Smrg switch (obj->Sampler.Attrib.MinFilter) { 8601e04c3fSmrg case GL_LINEAR: 8701e04c3fSmrg case GL_NEAREST_MIPMAP_LINEAR: 8801e04c3fSmrg case GL_LINEAR_MIPMAP_NEAREST: 8901e04c3fSmrg case GL_LINEAR_MIPMAP_LINEAR: 9001e04c3fSmrg if (obj->_IsHalfFloat && !ctx->Extensions.OES_texture_half_float_linear) { 9101e04c3fSmrg return false; 9201e04c3fSmrg } else if (obj->_IsFloat && !ctx->Extensions.OES_texture_float_linear) { 9301e04c3fSmrg return false; 9401e04c3fSmrg } 957ec681f3Smrg FALLTHROUGH; 9601e04c3fSmrg case GL_NEAREST: 9701e04c3fSmrg case GL_NEAREST_MIPMAP_NEAREST: 9801e04c3fSmrg break; 9901e04c3fSmrg default: 10001e04c3fSmrg unreachable("Invalid min filter"); 10101e04c3fSmrg } 10201e04c3fSmrg 10301e04c3fSmrg return true; 10401e04c3fSmrg} 1057117f1b4Smrg 1067117f1b4Smrg/** 1077117f1b4Smrg * Return the gl_texture_object for a given ID. 1087117f1b4Smrg */ 1097117f1b4Smrgstruct gl_texture_object * 1103464ebd5Sriastradh_mesa_lookup_texture(struct gl_context *ctx, GLuint id) 1117117f1b4Smrg{ 1127117f1b4Smrg return (struct gl_texture_object *) 1137117f1b4Smrg _mesa_HashLookup(ctx->Shared->TexObjects, id); 1147117f1b4Smrg} 1157117f1b4Smrg 11601e04c3fSmrg/** 11701e04c3fSmrg * Wrapper around _mesa_lookup_texture that throws GL_INVALID_OPERATION if id 11801e04c3fSmrg * is not in the hash table. After calling _mesa_error, it returns NULL. 11901e04c3fSmrg */ 12001e04c3fSmrgstruct gl_texture_object * 12101e04c3fSmrg_mesa_lookup_texture_err(struct gl_context *ctx, GLuint id, const char* func) 122af69d88dSmrg{ 12301e04c3fSmrg struct gl_texture_object *texObj = NULL; 124af69d88dSmrg 12501e04c3fSmrg if (id > 0) 12601e04c3fSmrg texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */ 127af69d88dSmrg 12801e04c3fSmrg if (!texObj) 12901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture)", func); 13001e04c3fSmrg 13101e04c3fSmrg return texObj; 132af69d88dSmrg} 133af69d88dSmrg 134af69d88dSmrg 135af69d88dSmrgstruct gl_texture_object * 136af69d88dSmrg_mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id) 137af69d88dSmrg{ 138af69d88dSmrg return (struct gl_texture_object *) 139af69d88dSmrg _mesa_HashLookupLocked(ctx->Shared->TexObjects, id); 140af69d88dSmrg} 141af69d88dSmrg 14201e04c3fSmrg/** 14301e04c3fSmrg * Return a pointer to the current texture object for the given target 14401e04c3fSmrg * on the current texture unit. 14501e04c3fSmrg * Note: all <target> error checking should have been done by this point. 14601e04c3fSmrg */ 14701e04c3fSmrgstruct gl_texture_object * 14801e04c3fSmrg_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target) 14901e04c3fSmrg{ 15001e04c3fSmrg struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 15101e04c3fSmrg const GLboolean arrayTex = ctx->Extensions.EXT_texture_array; 15201e04c3fSmrg 15301e04c3fSmrg switch (target) { 15401e04c3fSmrg case GL_TEXTURE_1D: 15501e04c3fSmrg return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 15601e04c3fSmrg case GL_PROXY_TEXTURE_1D: 15701e04c3fSmrg return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 15801e04c3fSmrg case GL_TEXTURE_2D: 15901e04c3fSmrg return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 16001e04c3fSmrg case GL_PROXY_TEXTURE_2D: 16101e04c3fSmrg return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 16201e04c3fSmrg case GL_TEXTURE_3D: 16301e04c3fSmrg return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 16401e04c3fSmrg case GL_PROXY_TEXTURE_3D: 16501e04c3fSmrg return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 16601e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 16701e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 16801e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 16901e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 17001e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 17101e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 17201e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 17301e04c3fSmrg return ctx->Extensions.ARB_texture_cube_map 17401e04c3fSmrg ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 17501e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 17601e04c3fSmrg return ctx->Extensions.ARB_texture_cube_map 17701e04c3fSmrg ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 17801e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 17901e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx) 18001e04c3fSmrg ? texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL; 18101e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 18201e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx) 18301e04c3fSmrg ? ctx->Texture.ProxyTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL; 18401e04c3fSmrg case GL_TEXTURE_RECTANGLE_NV: 18501e04c3fSmrg return ctx->Extensions.NV_texture_rectangle 18601e04c3fSmrg ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 18701e04c3fSmrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 18801e04c3fSmrg return ctx->Extensions.NV_texture_rectangle 18901e04c3fSmrg ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 19001e04c3fSmrg case GL_TEXTURE_1D_ARRAY_EXT: 19101e04c3fSmrg return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 19201e04c3fSmrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 19301e04c3fSmrg return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 19401e04c3fSmrg case GL_TEXTURE_2D_ARRAY_EXT: 19501e04c3fSmrg return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 19601e04c3fSmrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 19701e04c3fSmrg return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 19801e04c3fSmrg case GL_TEXTURE_BUFFER: 19901e04c3fSmrg return (_mesa_has_ARB_texture_buffer_object(ctx) || 20001e04c3fSmrg _mesa_has_OES_texture_buffer(ctx)) ? 20101e04c3fSmrg texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL; 20201e04c3fSmrg case GL_TEXTURE_EXTERNAL_OES: 20301e04c3fSmrg return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external 20401e04c3fSmrg ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL; 20501e04c3fSmrg case GL_TEXTURE_2D_MULTISAMPLE: 20601e04c3fSmrg return ctx->Extensions.ARB_texture_multisample 20701e04c3fSmrg ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL; 20801e04c3fSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 20901e04c3fSmrg return ctx->Extensions.ARB_texture_multisample 21001e04c3fSmrg ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL; 21101e04c3fSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 21201e04c3fSmrg return ctx->Extensions.ARB_texture_multisample 21301e04c3fSmrg ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL; 21401e04c3fSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 21501e04c3fSmrg return ctx->Extensions.ARB_texture_multisample 21601e04c3fSmrg ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL; 21701e04c3fSmrg default: 21801e04c3fSmrg _mesa_problem(NULL, "bad target in _mesa_get_current_tex_object()"); 21901e04c3fSmrg return NULL; 22001e04c3fSmrg } 22101e04c3fSmrg} 22201e04c3fSmrg 2237117f1b4Smrg 2247ec681f3Smrg/** 2257ec681f3Smrg * Get the texture object for given target and texunit 2267ec681f3Smrg * Proxy targets are accepted only allowProxyTarget is true. 2277ec681f3Smrg * Return NULL if any error (and record the error). 2287ec681f3Smrg */ 2297ec681f3Smrgstruct gl_texture_object * 2307ec681f3Smrg_mesa_get_texobj_by_target_and_texunit(struct gl_context *ctx, GLenum target, 2317ec681f3Smrg GLuint texunit, bool allowProxyTarget, 2327ec681f3Smrg const char* caller) 2337ec681f3Smrg{ 2347ec681f3Smrg struct gl_texture_unit *texUnit; 2357ec681f3Smrg int targetIndex; 2367ec681f3Smrg 2377ec681f3Smrg if (_mesa_is_proxy_texture(target) && allowProxyTarget) { 2387ec681f3Smrg return _mesa_get_current_tex_object(ctx, target); 2397ec681f3Smrg } 2407ec681f3Smrg 2417ec681f3Smrg if (texunit >= ctx->Const.MaxCombinedTextureImageUnits) { 2427ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2437ec681f3Smrg "%s(texunit=%d)", caller, texunit); 2447ec681f3Smrg return NULL; 2457ec681f3Smrg } 2467ec681f3Smrg 2477ec681f3Smrg texUnit = _mesa_get_tex_unit(ctx, texunit); 2487ec681f3Smrg 2497ec681f3Smrg targetIndex = _mesa_tex_target_to_index(ctx, target); 2507ec681f3Smrg if (targetIndex < 0 || targetIndex == TEXTURE_BUFFER_INDEX) { 2517ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller); 2527ec681f3Smrg return NULL; 2537ec681f3Smrg } 2547ec681f3Smrg assert(targetIndex < NUM_TEXTURE_TARGETS); 2557ec681f3Smrg 2567ec681f3Smrg return texUnit->CurrentTex[targetIndex]; 2577ec681f3Smrg} 2587ec681f3Smrg 2597ec681f3Smrg 2607117f1b4Smrg/** 2617117f1b4Smrg * Allocate and initialize a new texture object. But don't put it into the 2627117f1b4Smrg * texture object hash table. 2637117f1b4Smrg * 2647117f1b4Smrg * Called via ctx->Driver.NewTextureObject, unless overridden by a device 2657117f1b4Smrg * driver. 26601e04c3fSmrg * 2677117f1b4Smrg * \param shared the shared GL state structure to contain the texture object 2687117f1b4Smrg * \param name integer name for the texture object 2697117f1b4Smrg * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, 27001e04c3fSmrg * GL_TEXTURE_CUBE_MAP or GL_TEXTURE_RECTANGLE_NV. zero is ok for the sake 2717117f1b4Smrg * of GenTextures() 2727117f1b4Smrg * 2737117f1b4Smrg * \return pointer to new texture object. 2747117f1b4Smrg */ 2757117f1b4Smrgstruct gl_texture_object * 27601e04c3fSmrg_mesa_new_texture_object(struct gl_context *ctx, GLuint name, GLenum target) 2777117f1b4Smrg{ 2787117f1b4Smrg struct gl_texture_object *obj; 27901e04c3fSmrg 2807117f1b4Smrg obj = MALLOC_STRUCT(gl_texture_object); 28101e04c3fSmrg if (!obj) 28201e04c3fSmrg return NULL; 28301e04c3fSmrg 284af69d88dSmrg _mesa_initialize_texture_object(ctx, obj, name, target); 2857117f1b4Smrg return obj; 2867117f1b4Smrg} 2877117f1b4Smrg 2887117f1b4Smrg 2897117f1b4Smrg/** 2907117f1b4Smrg * Initialize a new texture object to default values. 2917117f1b4Smrg * \param obj the texture object 2927117f1b4Smrg * \param name the texture name 2937117f1b4Smrg * \param target the texture target 2947117f1b4Smrg */ 2957117f1b4Smrgvoid 296af69d88dSmrg_mesa_initialize_texture_object( struct gl_context *ctx, 297af69d88dSmrg struct gl_texture_object *obj, 2987117f1b4Smrg GLuint name, GLenum target ) 2997117f1b4Smrg{ 30001e04c3fSmrg assert(target == 0 || 3017117f1b4Smrg target == GL_TEXTURE_1D || 3027117f1b4Smrg target == GL_TEXTURE_2D || 3037117f1b4Smrg target == GL_TEXTURE_3D || 30401e04c3fSmrg target == GL_TEXTURE_CUBE_MAP || 305c1f859d4Smrg target == GL_TEXTURE_RECTANGLE_NV || 306c1f859d4Smrg target == GL_TEXTURE_1D_ARRAY_EXT || 3073464ebd5Sriastradh target == GL_TEXTURE_2D_ARRAY_EXT || 308af69d88dSmrg target == GL_TEXTURE_EXTERNAL_OES || 309af69d88dSmrg target == GL_TEXTURE_CUBE_MAP_ARRAY || 310af69d88dSmrg target == GL_TEXTURE_BUFFER || 311af69d88dSmrg target == GL_TEXTURE_2D_MULTISAMPLE || 312af69d88dSmrg target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY); 3137117f1b4Smrg 314cdc920a0Smrg memset(obj, 0, sizeof(*obj)); 3157117f1b4Smrg /* init the non-zero fields */ 3167117f1b4Smrg obj->RefCount = 1; 3177117f1b4Smrg obj->Name = name; 3187117f1b4Smrg obj->Target = target; 31901e04c3fSmrg if (target != 0) { 32001e04c3fSmrg obj->TargetIndex = _mesa_tex_target_to_index(ctx, target); 32101e04c3fSmrg } 32201e04c3fSmrg else { 32301e04c3fSmrg obj->TargetIndex = NUM_TEXTURE_TARGETS; /* invalid/error value */ 32401e04c3fSmrg } 3257ec681f3Smrg obj->Attrib.Priority = 1.0F; 3267ec681f3Smrg obj->Attrib.BaseLevel = 0; 3277ec681f3Smrg obj->Attrib.MaxLevel = 1000; 3283464ebd5Sriastradh 329af69d88dSmrg /* must be one; no support for (YUV) planes in separate buffers */ 330af69d88dSmrg obj->RequiredTextureImageUnits = 1; 331af69d88dSmrg 3323464ebd5Sriastradh /* sampler state */ 3337ec681f3Smrg if (target == GL_TEXTURE_RECTANGLE_NV || 3347ec681f3Smrg target == GL_TEXTURE_EXTERNAL_OES) { 3357ec681f3Smrg obj->Sampler.Attrib.WrapS = GL_CLAMP_TO_EDGE; 3367ec681f3Smrg obj->Sampler.Attrib.WrapT = GL_CLAMP_TO_EDGE; 3377ec681f3Smrg obj->Sampler.Attrib.WrapR = GL_CLAMP_TO_EDGE; 3387ec681f3Smrg obj->Sampler.Attrib.MinFilter = GL_LINEAR; 3397ec681f3Smrg obj->Sampler.Attrib.state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 3407ec681f3Smrg obj->Sampler.Attrib.state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 3417ec681f3Smrg obj->Sampler.Attrib.state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 3427ec681f3Smrg obj->Sampler.Attrib.state.min_img_filter = PIPE_TEX_FILTER_LINEAR; 3437ec681f3Smrg obj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 3447117f1b4Smrg } 3457ec681f3Smrg else { 3467ec681f3Smrg obj->Sampler.Attrib.WrapS = GL_REPEAT; 3477ec681f3Smrg obj->Sampler.Attrib.WrapT = GL_REPEAT; 3487ec681f3Smrg obj->Sampler.Attrib.WrapR = GL_REPEAT; 3497ec681f3Smrg obj->Sampler.Attrib.MinFilter = GL_NEAREST_MIPMAP_LINEAR; 3507ec681f3Smrg obj->Sampler.Attrib.state.wrap_s = PIPE_TEX_WRAP_REPEAT; 3517ec681f3Smrg obj->Sampler.Attrib.state.wrap_t = PIPE_TEX_WRAP_REPEAT; 3527ec681f3Smrg obj->Sampler.Attrib.state.wrap_r = PIPE_TEX_WRAP_REPEAT; 3537ec681f3Smrg obj->Sampler.Attrib.state.min_img_filter = PIPE_TEX_FILTER_NEAREST; 3547ec681f3Smrg obj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR; 3557ec681f3Smrg } 3567ec681f3Smrg obj->Sampler.Attrib.MagFilter = GL_LINEAR; 3577ec681f3Smrg obj->Sampler.Attrib.state.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 3587ec681f3Smrg obj->Sampler.Attrib.MinLod = -1000.0; 3597ec681f3Smrg obj->Sampler.Attrib.MaxLod = 1000.0; 3607ec681f3Smrg obj->Sampler.Attrib.state.min_lod = 0; /* no negative numbers */ 3617ec681f3Smrg obj->Sampler.Attrib.state.max_lod = 1000; 3627ec681f3Smrg obj->Sampler.Attrib.LodBias = 0.0; 3637ec681f3Smrg obj->Sampler.Attrib.state.lod_bias = 0; 3647ec681f3Smrg obj->Sampler.Attrib.MaxAnisotropy = 1.0; 3657ec681f3Smrg obj->Sampler.Attrib.state.max_anisotropy = 0; /* gallium sets 0 instead of 1 */ 3667ec681f3Smrg obj->Sampler.Attrib.CompareMode = GL_NONE; /* ARB_shadow */ 3677ec681f3Smrg obj->Sampler.Attrib.CompareFunc = GL_LEQUAL; /* ARB_shadow */ 3687ec681f3Smrg obj->Sampler.Attrib.state.compare_mode = PIPE_TEX_COMPARE_NONE; 3697ec681f3Smrg obj->Sampler.Attrib.state.compare_func = PIPE_FUNC_LEQUAL; 3707ec681f3Smrg obj->Attrib.DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE; 371af69d88dSmrg obj->StencilSampling = false; 3727ec681f3Smrg obj->Sampler.Attrib.CubeMapSeamless = GL_FALSE; 3737ec681f3Smrg obj->Sampler.Attrib.state.seamless_cube_map = false; 37401e04c3fSmrg obj->Sampler.HandleAllocated = GL_FALSE; 3757ec681f3Smrg obj->Attrib.Swizzle[0] = GL_RED; 3767ec681f3Smrg obj->Attrib.Swizzle[1] = GL_GREEN; 3777ec681f3Smrg obj->Attrib.Swizzle[2] = GL_BLUE; 3787ec681f3Smrg obj->Attrib.Swizzle[3] = GL_ALPHA; 3797ec681f3Smrg obj->Attrib._Swizzle = SWIZZLE_NOOP; 3807ec681f3Smrg obj->Sampler.Attrib.sRGBDecode = GL_DECODE_EXT; 3817ec681f3Smrg obj->Sampler.Attrib.ReductionMode = GL_WEIGHTED_AVERAGE_EXT; 3827ec681f3Smrg obj->Sampler.Attrib.state.reduction_mode = PIPE_TEX_REDUCTION_WEIGHTED_AVERAGE; 3837ec681f3Smrg obj->BufferObjectFormat = ctx->API == API_OPENGL_COMPAT ? GL_LUMINANCE8 : GL_R8; 3847ec681f3Smrg obj->_BufferObjectFormat = ctx->API == API_OPENGL_COMPAT 3857ec681f3Smrg ? MESA_FORMAT_L_UNORM8 : MESA_FORMAT_R_UNORM8; 3867ec681f3Smrg obj->Attrib.ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE; 38701e04c3fSmrg 38801e04c3fSmrg /* GL_ARB_bindless_texture */ 38901e04c3fSmrg _mesa_init_texture_handles(obj); 390c1f859d4Smrg} 391c1f859d4Smrg 392c1f859d4Smrg 393c1f859d4Smrg/** 394c1f859d4Smrg * Some texture initialization can't be finished until we know which 395c1f859d4Smrg * target it's getting bound to (GL_TEXTURE_1D/2D/etc). 396c1f859d4Smrg */ 397c1f859d4Smrgstatic void 3983464ebd5Sriastradhfinish_texture_init(struct gl_context *ctx, GLenum target, 39901e04c3fSmrg struct gl_texture_object *obj, int targetIndex) 400c1f859d4Smrg{ 401af69d88dSmrg GLenum filter = GL_LINEAR; 402c1f859d4Smrg assert(obj->Target == 0); 403c1f859d4Smrg 40401e04c3fSmrg obj->Target = target; 40501e04c3fSmrg obj->TargetIndex = targetIndex; 40601e04c3fSmrg assert(obj->TargetIndex < NUM_TEXTURE_TARGETS); 40701e04c3fSmrg 408af69d88dSmrg switch (target) { 409af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 410af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 411af69d88dSmrg filter = GL_NEAREST; 4127ec681f3Smrg FALLTHROUGH; 413af69d88dSmrg 414af69d88dSmrg case GL_TEXTURE_RECTANGLE_NV: 415af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 416af69d88dSmrg /* have to init wrap and filter state here - kind of klunky */ 4177ec681f3Smrg obj->Sampler.Attrib.WrapS = GL_CLAMP_TO_EDGE; 4187ec681f3Smrg obj->Sampler.Attrib.WrapT = GL_CLAMP_TO_EDGE; 4197ec681f3Smrg obj->Sampler.Attrib.WrapR = GL_CLAMP_TO_EDGE; 4207ec681f3Smrg obj->Sampler.Attrib.state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 4217ec681f3Smrg obj->Sampler.Attrib.state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 4227ec681f3Smrg obj->Sampler.Attrib.state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 4237ec681f3Smrg obj->Sampler.Attrib.MinFilter = filter; 4247ec681f3Smrg obj->Sampler.Attrib.MagFilter = filter; 4257ec681f3Smrg obj->Sampler.Attrib.state.min_img_filter = filter_to_gallium(filter); 4267ec681f3Smrg obj->Sampler.Attrib.state.min_mip_filter = mipfilter_to_gallium(filter); 4277ec681f3Smrg obj->Sampler.Attrib.state.mag_img_filter = filter_to_gallium(filter); 428af69d88dSmrg if (ctx->Driver.TexParameter) { 42901e04c3fSmrg /* XXX we probably don't need to make all these calls */ 43001e04c3fSmrg ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_S); 43101e04c3fSmrg ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_T); 43201e04c3fSmrg ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_R); 43301e04c3fSmrg ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_MIN_FILTER); 43401e04c3fSmrg ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_MAG_FILTER); 435af69d88dSmrg } 436af69d88dSmrg break; 437af69d88dSmrg 438af69d88dSmrg default: 439af69d88dSmrg /* nothing needs done */ 440af69d88dSmrg break; 441c1f859d4Smrg } 4427117f1b4Smrg} 4437117f1b4Smrg 4447117f1b4Smrg 4457117f1b4Smrg/** 4467117f1b4Smrg * Deallocate a texture object struct. It should have already been 4477117f1b4Smrg * removed from the texture object pool. 448c1f859d4Smrg * Called via ctx->Driver.DeleteTexture() if not overriden by a driver. 4497117f1b4Smrg * 4507117f1b4Smrg * \param shared the shared GL state to which the object belongs. 4514a49301eSmrg * \param texObj the texture object to delete. 4527117f1b4Smrg */ 4537117f1b4Smrgvoid 4543464ebd5Sriastradh_mesa_delete_texture_object(struct gl_context *ctx, 4553464ebd5Sriastradh struct gl_texture_object *texObj) 4567117f1b4Smrg{ 4577117f1b4Smrg GLuint i, face; 4587117f1b4Smrg 4597117f1b4Smrg /* Set Target to an invalid value. With some assertions elsewhere 4607117f1b4Smrg * we can try to detect possible use of deleted textures. 4617117f1b4Smrg */ 4627117f1b4Smrg texObj->Target = 0x99; 4637117f1b4Smrg 4647117f1b4Smrg /* free the texture images */ 4657117f1b4Smrg for (face = 0; face < 6; face++) { 4667117f1b4Smrg for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { 4673464ebd5Sriastradh if (texObj->Image[face][i]) { 468af69d88dSmrg ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]); 4693464ebd5Sriastradh } 4707117f1b4Smrg } 4717117f1b4Smrg } 4727117f1b4Smrg 47301e04c3fSmrg /* Delete all texture/image handles. */ 47401e04c3fSmrg _mesa_delete_texture_handles(ctx, texObj); 47501e04c3fSmrg 4767ec681f3Smrg _mesa_reference_buffer_object_shared(ctx, &texObj->BufferObject, NULL); 477af69d88dSmrg free(texObj->Label); 4787117f1b4Smrg 4797117f1b4Smrg /* free this object */ 480cdc920a0Smrg free(texObj); 4817117f1b4Smrg} 4827117f1b4Smrg 4837117f1b4Smrg 4844a49301eSmrg/** 48501e04c3fSmrg * Free all texture images of the given texture objectm, except for 48601e04c3fSmrg * \p retainTexImage. 4874a49301eSmrg * 4884a49301eSmrg * \param ctx GL context. 48901e04c3fSmrg * \param texObj texture object. 49001e04c3fSmrg * \param retainTexImage a texture image that will \em not be freed. 4914a49301eSmrg * 4924a49301eSmrg * \sa _mesa_clear_texture_image(). 4934a49301eSmrg */ 4944a49301eSmrgvoid 4953464ebd5Sriastradh_mesa_clear_texture_object(struct gl_context *ctx, 49601e04c3fSmrg struct gl_texture_object *texObj, 49701e04c3fSmrg struct gl_texture_image *retainTexImage) 4984a49301eSmrg{ 4994a49301eSmrg GLuint i, j; 5004a49301eSmrg 5014a49301eSmrg if (texObj->Target == 0) 5024a49301eSmrg return; 5034a49301eSmrg 5044a49301eSmrg for (i = 0; i < MAX_FACES; i++) { 5054a49301eSmrg for (j = 0; j < MAX_TEXTURE_LEVELS; j++) { 5064a49301eSmrg struct gl_texture_image *texImage = texObj->Image[i][j]; 50701e04c3fSmrg if (texImage && texImage != retainTexImage) 5084a49301eSmrg _mesa_clear_texture_image(ctx, texImage); 5094a49301eSmrg } 5104a49301eSmrg } 5117117f1b4Smrg} 5127117f1b4Smrg 5137117f1b4Smrg 5147117f1b4Smrg/** 5157117f1b4Smrg * Check if the given texture object is valid by examining its Target field. 5167117f1b4Smrg * For debugging only. 5177117f1b4Smrg */ 5187117f1b4Smrgstatic GLboolean 5197117f1b4Smrgvalid_texture_object(const struct gl_texture_object *tex) 5207117f1b4Smrg{ 5217117f1b4Smrg switch (tex->Target) { 5227117f1b4Smrg case 0: 5237117f1b4Smrg case GL_TEXTURE_1D: 5247117f1b4Smrg case GL_TEXTURE_2D: 5257117f1b4Smrg case GL_TEXTURE_3D: 52601e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 5277117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 528c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 529c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 5303464ebd5Sriastradh case GL_TEXTURE_BUFFER: 531af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 532af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 533af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 534af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 5357117f1b4Smrg return GL_TRUE; 5367117f1b4Smrg case 0x99: 5377117f1b4Smrg _mesa_problem(NULL, "invalid reference to a deleted texture object"); 5387117f1b4Smrg return GL_FALSE; 5397117f1b4Smrg default: 5404a49301eSmrg _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u", 5414a49301eSmrg tex->Target, tex->Name); 5427117f1b4Smrg return GL_FALSE; 5437117f1b4Smrg } 5447117f1b4Smrg} 5457117f1b4Smrg 5467117f1b4Smrg 5477117f1b4Smrg/** 5487117f1b4Smrg * Reference (or unreference) a texture object. 5497117f1b4Smrg * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero). 5507117f1b4Smrg * If 'tex' is non-null, increment its refcount. 551af69d88dSmrg * This is normally only called from the _mesa_reference_texobj() macro 552af69d88dSmrg * when there's a real pointer change. 5537117f1b4Smrg */ 5547117f1b4Smrgvoid 555af69d88dSmrg_mesa_reference_texobj_(struct gl_texture_object **ptr, 556af69d88dSmrg struct gl_texture_object *tex) 5577117f1b4Smrg{ 5587117f1b4Smrg assert(ptr); 5597117f1b4Smrg 5607117f1b4Smrg if (*ptr) { 5617117f1b4Smrg /* Unreference the old texture */ 5627117f1b4Smrg struct gl_texture_object *oldTex = *ptr; 5637117f1b4Smrg 56401e04c3fSmrg assert(valid_texture_object(oldTex)); 5653464ebd5Sriastradh (void) valid_texture_object; /* silence warning in release builds */ 5667117f1b4Smrg 56701e04c3fSmrg assert(oldTex->RefCount > 0); 5687117f1b4Smrg 5697ec681f3Smrg if (p_atomic_dec_zero(&oldTex->RefCount)) { 57001e04c3fSmrg /* Passing in the context drastically changes the driver code for 57101e04c3fSmrg * framebuffer deletion. 57201e04c3fSmrg */ 5737117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5747117f1b4Smrg if (ctx) 5757117f1b4Smrg ctx->Driver.DeleteTexture(ctx, oldTex); 5767117f1b4Smrg else 5777117f1b4Smrg _mesa_problem(NULL, "Unable to delete texture, no context"); 5787117f1b4Smrg } 5797117f1b4Smrg } 5807117f1b4Smrg 5817117f1b4Smrg if (tex) { 5827117f1b4Smrg /* reference new texture */ 58301e04c3fSmrg assert(valid_texture_object(tex)); 58401e04c3fSmrg assert(tex->RefCount > 0); 58501e04c3fSmrg 5867ec681f3Smrg p_atomic_inc(&tex->RefCount); 5877117f1b4Smrg } 5887ec681f3Smrg 5897ec681f3Smrg *ptr = tex; 5907117f1b4Smrg} 5917117f1b4Smrg 5927117f1b4Smrg 593af69d88dSmrgenum base_mipmap { BASE, MIPMAP }; 594af69d88dSmrg 5957117f1b4Smrg 5967117f1b4Smrg/** 597af69d88dSmrg * Mark a texture object as incomplete. There are actually three kinds of 598af69d88dSmrg * (in)completeness: 599af69d88dSmrg * 1. "base incomplete": the base level of the texture is invalid so no 600af69d88dSmrg * texturing is possible. 601af69d88dSmrg * 2. "mipmap incomplete": a non-base level of the texture is invalid so 602af69d88dSmrg * mipmap filtering isn't possible, but non-mipmap filtering is. 603af69d88dSmrg * 3. "texture incompleteness": some combination of texture state and 604af69d88dSmrg * sampler state renders the texture incomplete. 605af69d88dSmrg * 6063464ebd5Sriastradh * \param t texture object 607af69d88dSmrg * \param bm either BASE or MIPMAP to indicate what's incomplete 6083464ebd5Sriastradh * \param fmt... string describing why it's incomplete (for debugging). 6097117f1b4Smrg */ 6107117f1b4Smrgstatic void 611af69d88dSmrgincomplete(struct gl_texture_object *t, enum base_mipmap bm, 612af69d88dSmrg const char *fmt, ...) 6137117f1b4Smrg{ 614af69d88dSmrg if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) { 615af69d88dSmrg va_list args; 616af69d88dSmrg char s[100]; 6173464ebd5Sriastradh 618af69d88dSmrg va_start(args, fmt); 619af69d88dSmrg vsnprintf(s, sizeof(s), fmt, args); 620af69d88dSmrg va_end(args); 621af69d88dSmrg 622af69d88dSmrg _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s); 623af69d88dSmrg } 6243464ebd5Sriastradh 625af69d88dSmrg if (bm == BASE) 626af69d88dSmrg t->_BaseComplete = GL_FALSE; 627af69d88dSmrg t->_MipmapComplete = GL_FALSE; 6283464ebd5Sriastradh} 6297117f1b4Smrg 6307117f1b4Smrg 6317117f1b4Smrg/** 6327117f1b4Smrg * Examine a texture object to determine if it is complete. 6337117f1b4Smrg * 6347117f1b4Smrg * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE 6357117f1b4Smrg * accordingly. 6367117f1b4Smrg * 6377117f1b4Smrg * \param ctx GL context. 6387117f1b4Smrg * \param t texture object. 6397117f1b4Smrg * 6407117f1b4Smrg * According to the texture target, verifies that each of the mipmaps is 6417117f1b4Smrg * present and has the expected size. 6427117f1b4Smrg */ 6437117f1b4Smrgvoid 6443464ebd5Sriastradh_mesa_test_texobj_completeness( const struct gl_context *ctx, 6457117f1b4Smrg struct gl_texture_object *t ) 6467117f1b4Smrg{ 6477ec681f3Smrg const GLint baseLevel = t->Attrib.BaseLevel; 648af69d88dSmrg const struct gl_texture_image *baseImage; 649af69d88dSmrg GLint maxLevels = 0; 6507117f1b4Smrg 651af69d88dSmrg /* We'll set these to FALSE if tests fail below */ 652af69d88dSmrg t->_BaseComplete = GL_TRUE; 653af69d88dSmrg t->_MipmapComplete = GL_TRUE; 654af69d88dSmrg 655af69d88dSmrg if (t->Target == GL_TEXTURE_BUFFER) { 656af69d88dSmrg /* Buffer textures are always considered complete. The obvious case where 657af69d88dSmrg * they would be incomplete (no BO attached) is actually specced to be 658af69d88dSmrg * undefined rendering results. 659af69d88dSmrg */ 660af69d88dSmrg return; 661af69d88dSmrg } 662c1f859d4Smrg 663c1f859d4Smrg /* Detect cases where the application set the base level to an invalid 664c1f859d4Smrg * value. 665c1f859d4Smrg */ 6664a49301eSmrg if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) { 667af69d88dSmrg incomplete(t, BASE, "base level = %d is invalid", baseLevel); 668c1f859d4Smrg return; 669c1f859d4Smrg } 6707117f1b4Smrg 6717ec681f3Smrg if (t->Attrib.MaxLevel < baseLevel) { 672af69d88dSmrg incomplete(t, MIPMAP, "MAX_LEVEL (%d) < BASE_LEVEL (%d)", 6737ec681f3Smrg t->Attrib.MaxLevel, baseLevel); 674af69d88dSmrg return; 675af69d88dSmrg } 676af69d88dSmrg 677af69d88dSmrg baseImage = t->Image[0][baseLevel]; 678af69d88dSmrg 6797117f1b4Smrg /* Always need the base level image */ 680af69d88dSmrg if (!baseImage) { 681af69d88dSmrg incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel); 6827117f1b4Smrg return; 6837117f1b4Smrg } 6847117f1b4Smrg 6857117f1b4Smrg /* Check width/height/depth for zero */ 686af69d88dSmrg if (baseImage->Width == 0 || 687af69d88dSmrg baseImage->Height == 0 || 688af69d88dSmrg baseImage->Depth == 0) { 689af69d88dSmrg incomplete(t, BASE, "texture width or height or depth = 0"); 6907117f1b4Smrg return; 6917117f1b4Smrg } 6927117f1b4Smrg 693af69d88dSmrg /* Check if the texture values are integer */ 694af69d88dSmrg { 695af69d88dSmrg GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat); 696af69d88dSmrg t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT; 6977117f1b4Smrg } 698af69d88dSmrg 69901e04c3fSmrg /* Check if the texture type is Float or HalfFloatOES and ensure Min and Mag 70001e04c3fSmrg * filters are supported in this case. 70101e04c3fSmrg */ 70201e04c3fSmrg if (_mesa_is_gles(ctx) && !valid_filter_for_float(ctx, t)) { 70301e04c3fSmrg incomplete(t, BASE, "Filter is not supported with Float types."); 70401e04c3fSmrg return; 70501e04c3fSmrg } 70601e04c3fSmrg 7077ec681f3Smrg maxLevels = _mesa_max_texture_levels(ctx, t->Target); 7087ec681f3Smrg if (maxLevels == 0) { 7097117f1b4Smrg _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness"); 7107117f1b4Smrg return; 7117117f1b4Smrg } 7127117f1b4Smrg 71301e04c3fSmrg assert(maxLevels > 0); 7147117f1b4Smrg 7157ec681f3Smrg t->_MaxLevel = MIN3(t->Attrib.MaxLevel, 716af69d88dSmrg /* 'p' in the GL spec */ 717af69d88dSmrg (int) (baseLevel + baseImage->MaxNumLevels - 1), 718af69d88dSmrg /* 'q' in the GL spec */ 719af69d88dSmrg maxLevels - 1); 720af69d88dSmrg 721af69d88dSmrg if (t->Immutable) { 722af69d88dSmrg /* Adjust max level for views: the data store may have more levels than 723af69d88dSmrg * the view exposes. 724af69d88dSmrg */ 7257ec681f3Smrg t->_MaxLevel = MAX2(MIN2(t->_MaxLevel, t->Attrib.NumLevels - 1), 0); 7263464ebd5Sriastradh } 7273464ebd5Sriastradh 728af69d88dSmrg /* Compute _MaxLambda = q - p in the spec used during mipmapping */ 729af69d88dSmrg t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel); 7307117f1b4Smrg 731af69d88dSmrg if (t->Immutable) { 732af69d88dSmrg /* This texture object was created with glTexStorage1/2/3D() so we 733af69d88dSmrg * know that all the mipmap levels are the right size and all cube 734af69d88dSmrg * map faces are the same size. 735af69d88dSmrg * We don't need to do any of the additional checks below. 736af69d88dSmrg */ 737af69d88dSmrg return; 738af69d88dSmrg } 7397117f1b4Smrg 74001e04c3fSmrg if (t->Target == GL_TEXTURE_CUBE_MAP) { 74101e04c3fSmrg /* Make sure that all six cube map level 0 images are the same size and 74201e04c3fSmrg * format. 743af69d88dSmrg * Note: we know that the image's width==height (we enforce that 744af69d88dSmrg * at glTexImage time) so we only need to test the width here. 745af69d88dSmrg */ 7467117f1b4Smrg GLuint face; 747af69d88dSmrg assert(baseImage->Width2 == baseImage->Height); 7487117f1b4Smrg for (face = 1; face < 6; face++) { 749af69d88dSmrg assert(t->Image[face][baseLevel] == NULL || 750af69d88dSmrg t->Image[face][baseLevel]->Width2 == 751af69d88dSmrg t->Image[face][baseLevel]->Height2); 7523464ebd5Sriastradh if (t->Image[face][baseLevel] == NULL || 753af69d88dSmrg t->Image[face][baseLevel]->Width2 != baseImage->Width2) { 754af69d88dSmrg incomplete(t, BASE, "Cube face missing or mismatched size"); 7553464ebd5Sriastradh return; 7563464ebd5Sriastradh } 75701e04c3fSmrg if (t->Image[face][baseLevel]->InternalFormat != 75801e04c3fSmrg baseImage->InternalFormat) { 75901e04c3fSmrg incomplete(t, BASE, "Cube face format mismatch"); 76001e04c3fSmrg return; 76101e04c3fSmrg } 76201e04c3fSmrg if (t->Image[face][baseLevel]->Border != baseImage->Border) { 76301e04c3fSmrg incomplete(t, BASE, "Cube face border size mismatch"); 76401e04c3fSmrg return; 76501e04c3fSmrg } 7667117f1b4Smrg } 7677117f1b4Smrg } 7687117f1b4Smrg 769af69d88dSmrg /* 770af69d88dSmrg * Do mipmap consistency checking. 771af69d88dSmrg * Note: we don't care about the current texture sampler state here. 772af69d88dSmrg * To determine texture completeness we'll either look at _BaseComplete 773af69d88dSmrg * or _MipmapComplete depending on the current minification filter mode. 774af69d88dSmrg */ 775af69d88dSmrg { 7767117f1b4Smrg GLint i; 777af69d88dSmrg const GLint minLevel = baseLevel; 778af69d88dSmrg const GLint maxLevel = t->_MaxLevel; 779af69d88dSmrg const GLuint numFaces = _mesa_num_tex_faces(t->Target); 780af69d88dSmrg GLuint width, height, depth, face; 7817117f1b4Smrg 7827117f1b4Smrg if (minLevel > maxLevel) { 783af69d88dSmrg incomplete(t, MIPMAP, "minLevel > maxLevel"); 7847117f1b4Smrg return; 7857117f1b4Smrg } 7867117f1b4Smrg 787af69d88dSmrg /* Get the base image's dimensions */ 788af69d88dSmrg width = baseImage->Width2; 789af69d88dSmrg height = baseImage->Height2; 790af69d88dSmrg depth = baseImage->Depth2; 7917117f1b4Smrg 792af69d88dSmrg /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL, 793af69d88dSmrg * MULTISAMPLE and MULTISAMPLE_ARRAY textures 794af69d88dSmrg */ 795af69d88dSmrg for (i = baseLevel + 1; i < maxLevels; i++) { 796af69d88dSmrg /* Compute the expected size of image at level[i] */ 797af69d88dSmrg if (width > 1) { 798af69d88dSmrg width /= 2; 7997117f1b4Smrg } 800af69d88dSmrg if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) { 801af69d88dSmrg height /= 2; 802af69d88dSmrg } 80301e04c3fSmrg if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY 80401e04c3fSmrg && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) { 805af69d88dSmrg depth /= 2; 806af69d88dSmrg } 807af69d88dSmrg 808af69d88dSmrg /* loop over cube faces (or single face otherwise) */ 809af69d88dSmrg for (face = 0; face < numFaces; face++) { 8107117f1b4Smrg if (i >= minLevel && i <= maxLevel) { 811af69d88dSmrg const struct gl_texture_image *img = t->Image[face][i]; 812af69d88dSmrg 813af69d88dSmrg if (!img) { 814af69d88dSmrg incomplete(t, MIPMAP, "TexImage[%d] is missing", i); 8157117f1b4Smrg return; 8167117f1b4Smrg } 81701e04c3fSmrg if (img->InternalFormat != baseImage->InternalFormat) { 818af69d88dSmrg incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]"); 8197117f1b4Smrg return; 8207117f1b4Smrg } 821af69d88dSmrg if (img->Border != baseImage->Border) { 822af69d88dSmrg incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]"); 8237117f1b4Smrg return; 8247117f1b4Smrg } 825af69d88dSmrg if (img->Width2 != width) { 82601e04c3fSmrg incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i, 82701e04c3fSmrg img->Width2); 8287117f1b4Smrg return; 8297117f1b4Smrg } 830af69d88dSmrg if (img->Height2 != height) { 83101e04c3fSmrg incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i, 83201e04c3fSmrg img->Height2); 8337117f1b4Smrg return; 8347117f1b4Smrg } 835af69d88dSmrg if (img->Depth2 != depth) { 83601e04c3fSmrg incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i, 83701e04c3fSmrg img->Depth2); 8387117f1b4Smrg return; 8397117f1b4Smrg } 8407117f1b4Smrg } 8417117f1b4Smrg } 84201e04c3fSmrg 843af69d88dSmrg if (width == 1 && height == 1 && depth == 1) { 844af69d88dSmrg return; /* found smallest needed mipmap, all done! */ 845af69d88dSmrg } 8467117f1b4Smrg } 8477117f1b4Smrg } 8487117f1b4Smrg} 8497117f1b4Smrg 8504a49301eSmrg 8513464ebd5SriastradhGLboolean 85201e04c3fSmrg_mesa_cube_level_complete(const struct gl_texture_object *texObj, 85301e04c3fSmrg const GLint level) 8543464ebd5Sriastradh{ 8553464ebd5Sriastradh const struct gl_texture_image *img0, *img; 8563464ebd5Sriastradh GLuint face; 8573464ebd5Sriastradh 8583464ebd5Sriastradh if (texObj->Target != GL_TEXTURE_CUBE_MAP) 8593464ebd5Sriastradh return GL_FALSE; 8603464ebd5Sriastradh 86101e04c3fSmrg if ((level < 0) || (level >= MAX_TEXTURE_LEVELS)) 8623464ebd5Sriastradh return GL_FALSE; 8633464ebd5Sriastradh 8643464ebd5Sriastradh /* check first face */ 86501e04c3fSmrg img0 = texObj->Image[0][level]; 8663464ebd5Sriastradh if (!img0 || 8673464ebd5Sriastradh img0->Width < 1 || 8683464ebd5Sriastradh img0->Width != img0->Height) 8693464ebd5Sriastradh return GL_FALSE; 8703464ebd5Sriastradh 8713464ebd5Sriastradh /* check remaining faces vs. first face */ 8723464ebd5Sriastradh for (face = 1; face < 6; face++) { 87301e04c3fSmrg img = texObj->Image[face][level]; 8743464ebd5Sriastradh if (!img || 8753464ebd5Sriastradh img->Width != img0->Width || 8763464ebd5Sriastradh img->Height != img0->Height || 8773464ebd5Sriastradh img->TexFormat != img0->TexFormat) 8783464ebd5Sriastradh return GL_FALSE; 8793464ebd5Sriastradh } 8803464ebd5Sriastradh 8813464ebd5Sriastradh return GL_TRUE; 8823464ebd5Sriastradh} 8833464ebd5Sriastradh 88401e04c3fSmrg/** 88501e04c3fSmrg * Check if the given cube map texture is "cube complete" as defined in 88601e04c3fSmrg * the OpenGL specification. 88701e04c3fSmrg */ 88801e04c3fSmrgGLboolean 88901e04c3fSmrg_mesa_cube_complete(const struct gl_texture_object *texObj) 89001e04c3fSmrg{ 8917ec681f3Smrg return _mesa_cube_level_complete(texObj, texObj->Attrib.BaseLevel); 89201e04c3fSmrg} 8933464ebd5Sriastradh 8944a49301eSmrg/** 8954a49301eSmrg * Mark a texture object dirty. It forces the object to be incomplete 896af69d88dSmrg * and forces the context to re-validate its state. 8974a49301eSmrg * 8984a49301eSmrg * \param ctx GL context. 8994a49301eSmrg * \param texObj texture object. 9004a49301eSmrg */ 9014a49301eSmrgvoid 902af69d88dSmrg_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj) 9034a49301eSmrg{ 904af69d88dSmrg texObj->_BaseComplete = GL_FALSE; 905af69d88dSmrg texObj->_MipmapComplete = GL_FALSE; 90601e04c3fSmrg ctx->NewState |= _NEW_TEXTURE_OBJECT; 9077ec681f3Smrg ctx->PopAttribState |= GL_TEXTURE_BIT; 9084a49301eSmrg} 9094a49301eSmrg 9104a49301eSmrg 9114a49301eSmrg/** 912af69d88dSmrg * Return pointer to a default/fallback texture of the given type/target. 913af69d88dSmrg * The texture is an RGBA texture with all texels = (0,0,0,1). 914af69d88dSmrg * That's the value a GLSL sampler should get when sampling from an 9154a49301eSmrg * incomplete texture. 9164a49301eSmrg */ 9174a49301eSmrgstruct gl_texture_object * 918af69d88dSmrg_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) 9194a49301eSmrg{ 920af69d88dSmrg if (!ctx->Shared->FallbackTex[tex]) { 9214a49301eSmrg /* create fallback texture now */ 92201e04c3fSmrg const GLsizei width = 1, height = 1; 92301e04c3fSmrg GLsizei depth = 1; 92401e04c3fSmrg GLubyte texel[24]; 9254a49301eSmrg struct gl_texture_object *texObj; 9264a49301eSmrg struct gl_texture_image *texImage; 927af69d88dSmrg mesa_format texFormat; 928af69d88dSmrg GLuint dims, face, numFaces = 1; 929af69d88dSmrg GLenum target; 930af69d88dSmrg 93101e04c3fSmrg for (face = 0; face < 6; face++) { 93201e04c3fSmrg texel[4*face + 0] = 93301e04c3fSmrg texel[4*face + 1] = 93401e04c3fSmrg texel[4*face + 2] = 0x0; 93501e04c3fSmrg texel[4*face + 3] = 0xff; 93601e04c3fSmrg } 937af69d88dSmrg 938af69d88dSmrg switch (tex) { 939af69d88dSmrg case TEXTURE_2D_ARRAY_INDEX: 940af69d88dSmrg dims = 3; 941af69d88dSmrg target = GL_TEXTURE_2D_ARRAY; 942af69d88dSmrg break; 943af69d88dSmrg case TEXTURE_1D_ARRAY_INDEX: 944af69d88dSmrg dims = 2; 945af69d88dSmrg target = GL_TEXTURE_1D_ARRAY; 946af69d88dSmrg break; 947af69d88dSmrg case TEXTURE_CUBE_INDEX: 948af69d88dSmrg dims = 2; 949af69d88dSmrg target = GL_TEXTURE_CUBE_MAP; 950af69d88dSmrg numFaces = 6; 951af69d88dSmrg break; 952af69d88dSmrg case TEXTURE_3D_INDEX: 953af69d88dSmrg dims = 3; 954af69d88dSmrg target = GL_TEXTURE_3D; 955af69d88dSmrg break; 956af69d88dSmrg case TEXTURE_RECT_INDEX: 957af69d88dSmrg dims = 2; 958af69d88dSmrg target = GL_TEXTURE_RECTANGLE; 959af69d88dSmrg break; 960af69d88dSmrg case TEXTURE_2D_INDEX: 961af69d88dSmrg dims = 2; 962af69d88dSmrg target = GL_TEXTURE_2D; 963af69d88dSmrg break; 964af69d88dSmrg case TEXTURE_1D_INDEX: 965af69d88dSmrg dims = 1; 966af69d88dSmrg target = GL_TEXTURE_1D; 967af69d88dSmrg break; 968af69d88dSmrg case TEXTURE_BUFFER_INDEX: 969af69d88dSmrg dims = 0; 970af69d88dSmrg target = GL_TEXTURE_BUFFER; 971af69d88dSmrg break; 972af69d88dSmrg case TEXTURE_CUBE_ARRAY_INDEX: 973af69d88dSmrg dims = 3; 974af69d88dSmrg target = GL_TEXTURE_CUBE_MAP_ARRAY; 97501e04c3fSmrg depth = 6; 976af69d88dSmrg break; 977af69d88dSmrg case TEXTURE_EXTERNAL_INDEX: 978af69d88dSmrg dims = 2; 979af69d88dSmrg target = GL_TEXTURE_EXTERNAL_OES; 980af69d88dSmrg break; 981af69d88dSmrg case TEXTURE_2D_MULTISAMPLE_INDEX: 982af69d88dSmrg dims = 2; 983af69d88dSmrg target = GL_TEXTURE_2D_MULTISAMPLE; 984af69d88dSmrg break; 985af69d88dSmrg case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: 986af69d88dSmrg dims = 3; 987af69d88dSmrg target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; 988af69d88dSmrg break; 989af69d88dSmrg default: 990af69d88dSmrg /* no-op */ 991af69d88dSmrg return NULL; 9924a49301eSmrg } 9934a49301eSmrg 9944a49301eSmrg /* create texture object */ 995af69d88dSmrg texObj = ctx->Driver.NewTextureObject(ctx, 0, target); 996af69d88dSmrg if (!texObj) 997af69d88dSmrg return NULL; 998af69d88dSmrg 9994a49301eSmrg assert(texObj->RefCount == 1); 10007ec681f3Smrg texObj->Sampler.Attrib.MinFilter = GL_NEAREST; 10017ec681f3Smrg texObj->Sampler.Attrib.MagFilter = GL_NEAREST; 10027ec681f3Smrg texObj->Sampler.Attrib.state.min_img_filter = PIPE_TEX_FILTER_NEAREST; 10037ec681f3Smrg texObj->Sampler.Attrib.state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 10047ec681f3Smrg texObj->Sampler.Attrib.state.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 10054a49301eSmrg 1006af69d88dSmrg texFormat = ctx->Driver.ChooseTextureFormat(ctx, target, 1007af69d88dSmrg GL_RGBA, GL_RGBA, 10083464ebd5Sriastradh GL_UNSIGNED_BYTE); 10093464ebd5Sriastradh 1010af69d88dSmrg /* need a loop here just for cube maps */ 1011af69d88dSmrg for (face = 0; face < numFaces; face++) { 101201e04c3fSmrg const GLenum faceTarget = _mesa_cube_face_target(target, face); 10134a49301eSmrg 1014af69d88dSmrg /* initialize level[0] texture image */ 1015af69d88dSmrg texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0); 10164a49301eSmrg 1017af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, 1018af69d88dSmrg width, 1019af69d88dSmrg (dims > 1) ? height : 1, 1020af69d88dSmrg (dims > 2) ? depth : 1, 1021af69d88dSmrg 0, /* border */ 1022af69d88dSmrg GL_RGBA, texFormat); 1023af69d88dSmrg 1024af69d88dSmrg ctx->Driver.TexImage(ctx, dims, texImage, 1025af69d88dSmrg GL_RGBA, GL_UNSIGNED_BYTE, texel, 1026af69d88dSmrg &ctx->DefaultPacking); 1027af69d88dSmrg } 10284a49301eSmrg 10294a49301eSmrg _mesa_test_texobj_completeness(ctx, texObj); 1030af69d88dSmrg assert(texObj->_BaseComplete); 1031af69d88dSmrg assert(texObj->_MipmapComplete); 1032af69d88dSmrg 1033af69d88dSmrg ctx->Shared->FallbackTex[tex] = texObj; 103401e04c3fSmrg 103501e04c3fSmrg /* Complete the driver's operation in case another context will also 103601e04c3fSmrg * use the same fallback texture. */ 103701e04c3fSmrg if (ctx->Driver.Finish) 103801e04c3fSmrg ctx->Driver.Finish(ctx); 1039af69d88dSmrg } 1040af69d88dSmrg return ctx->Shared->FallbackTex[tex]; 1041af69d88dSmrg} 1042af69d88dSmrg 1043af69d88dSmrg 1044af69d88dSmrg/** 1045af69d88dSmrg * Compute the size of the given texture object, in bytes. 1046af69d88dSmrg */ 1047af69d88dSmrgstatic GLuint 1048af69d88dSmrgtexture_size(const struct gl_texture_object *texObj) 1049af69d88dSmrg{ 1050af69d88dSmrg const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); 1051af69d88dSmrg GLuint face, level, size = 0; 1052af69d88dSmrg 1053af69d88dSmrg for (face = 0; face < numFaces; face++) { 1054af69d88dSmrg for (level = 0; level < MAX_TEXTURE_LEVELS; level++) { 1055af69d88dSmrg const struct gl_texture_image *img = texObj->Image[face][level]; 1056af69d88dSmrg if (img) { 1057af69d88dSmrg GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width, 1058af69d88dSmrg img->Height, img->Depth); 1059af69d88dSmrg size += sz; 1060af69d88dSmrg } 1061af69d88dSmrg } 1062af69d88dSmrg } 1063af69d88dSmrg 1064af69d88dSmrg return size; 1065af69d88dSmrg} 1066af69d88dSmrg 1067af69d88dSmrg 1068af69d88dSmrg/** 1069af69d88dSmrg * Callback called from _mesa_HashWalk() 1070af69d88dSmrg */ 1071af69d88dSmrgstatic void 10727ec681f3Smrgcount_tex_size(void *data, void *userData) 1073af69d88dSmrg{ 1074af69d88dSmrg const struct gl_texture_object *texObj = 1075af69d88dSmrg (const struct gl_texture_object *) data; 1076af69d88dSmrg GLuint *total = (GLuint *) userData; 1077af69d88dSmrg 1078af69d88dSmrg *total = *total + texture_size(texObj); 1079af69d88dSmrg} 1080af69d88dSmrg 1081af69d88dSmrg 1082af69d88dSmrg/** 1083af69d88dSmrg * Compute total size (in bytes) of all textures for the given context. 1084af69d88dSmrg * For debugging purposes. 1085af69d88dSmrg */ 1086af69d88dSmrgGLuint 1087af69d88dSmrg_mesa_total_texture_memory(struct gl_context *ctx) 1088af69d88dSmrg{ 1089af69d88dSmrg GLuint tgt, total = 0; 1090af69d88dSmrg 1091af69d88dSmrg _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total); 1092af69d88dSmrg 1093af69d88dSmrg /* plus, the default texture objects */ 1094af69d88dSmrg for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 1095af69d88dSmrg total += texture_size(ctx->Shared->DefaultTex[tgt]); 10964a49301eSmrg } 1097af69d88dSmrg 1098af69d88dSmrg return total; 10994a49301eSmrg} 11004a49301eSmrg 110101e04c3fSmrg 110201e04c3fSmrg/** 110301e04c3fSmrg * Return the base format for the given texture object by looking 110401e04c3fSmrg * at the base texture image. 110501e04c3fSmrg * \return base format (such as GL_RGBA) or GL_NONE if it can't be determined 110601e04c3fSmrg */ 110701e04c3fSmrgGLenum 110801e04c3fSmrg_mesa_texture_base_format(const struct gl_texture_object *texObj) 110901e04c3fSmrg{ 111001e04c3fSmrg const struct gl_texture_image *texImage = _mesa_base_tex_image(texObj); 111101e04c3fSmrg 111201e04c3fSmrg return texImage ? texImage->_BaseFormat : GL_NONE; 111301e04c3fSmrg} 111401e04c3fSmrg 111501e04c3fSmrg 1116af69d88dSmrgstatic struct gl_texture_object * 1117af69d88dSmrginvalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture, 1118af69d88dSmrg GLint level, const char *name) 1119af69d88dSmrg{ 1120af69d88dSmrg /* The GL_ARB_invalidate_subdata spec says: 1121af69d88dSmrg * 1122af69d88dSmrg * "If <texture> is zero or is not the name of a texture, the error 1123af69d88dSmrg * INVALID_VALUE is generated." 1124af69d88dSmrg * 1125af69d88dSmrg * This performs the error check in a different order than listed in the 1126af69d88dSmrg * spec. We have to get the texture object before we can validate the 1127af69d88dSmrg * other parameters against values in the texture object. 1128af69d88dSmrg */ 1129af69d88dSmrg struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture); 1130af69d88dSmrg if (texture == 0 || t == NULL) { 1131af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name); 1132af69d88dSmrg return NULL; 1133af69d88dSmrg } 1134af69d88dSmrg 1135af69d88dSmrg /* The GL_ARB_invalidate_subdata spec says: 1136af69d88dSmrg * 1137af69d88dSmrg * "If <level> is less than zero or greater than the base 2 logarithm 1138af69d88dSmrg * of the maximum texture width, height, or depth, the error 1139af69d88dSmrg * INVALID_VALUE is generated." 1140af69d88dSmrg */ 11417ec681f3Smrg if (level < 0 || level > t->Attrib.MaxLevel) { 1142af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); 1143af69d88dSmrg return NULL; 1144af69d88dSmrg } 1145af69d88dSmrg 1146af69d88dSmrg /* The GL_ARB_invalidate_subdata spec says: 1147af69d88dSmrg * 1148af69d88dSmrg * "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER, 1149af69d88dSmrg * TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level> 1150af69d88dSmrg * is not zero, the error INVALID_VALUE is generated." 1151af69d88dSmrg */ 1152af69d88dSmrg if (level != 0) { 1153af69d88dSmrg switch (t->Target) { 1154af69d88dSmrg case GL_TEXTURE_RECTANGLE: 1155af69d88dSmrg case GL_TEXTURE_BUFFER: 1156af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 1157af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1158af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); 1159af69d88dSmrg return NULL; 1160af69d88dSmrg 1161af69d88dSmrg default: 1162af69d88dSmrg break; 1163af69d88dSmrg } 1164af69d88dSmrg } 1165af69d88dSmrg 1166af69d88dSmrg return t; 1167af69d88dSmrg} 11684a49301eSmrg 11697117f1b4Smrg 11707117f1b4Smrg/** 117101e04c3fSmrg * Helper function for glCreateTextures and glGenTextures. Need this because 117201e04c3fSmrg * glCreateTextures should throw errors if target = 0. This is not exposed to 117301e04c3fSmrg * the rest of Mesa to encourage Mesa internals to use nameless textures, 117401e04c3fSmrg * which do not require expensive hash lookups. 117501e04c3fSmrg * \param target either 0 or a valid / error-checked texture target enum 117601e04c3fSmrg */ 117701e04c3fSmrgstatic void 117801e04c3fSmrgcreate_textures(struct gl_context *ctx, GLenum target, 117901e04c3fSmrg GLsizei n, GLuint *textures, const char *caller) 11807117f1b4Smrg{ 11817117f1b4Smrg GLint i; 1182af69d88dSmrg 11837117f1b4Smrg if (!textures) 11847117f1b4Smrg return; 11857117f1b4Smrg 11867117f1b4Smrg /* 11877117f1b4Smrg * This must be atomic (generation and allocation of texture IDs) 11887117f1b4Smrg */ 118901e04c3fSmrg _mesa_HashLockMutex(ctx->Shared->TexObjects); 11907117f1b4Smrg 11917ec681f3Smrg _mesa_HashFindFreeKeys(ctx->Shared->TexObjects, textures, n); 11927117f1b4Smrg 11937117f1b4Smrg /* Allocate new, empty texture objects */ 11947117f1b4Smrg for (i = 0; i < n; i++) { 11957117f1b4Smrg struct gl_texture_object *texObj; 11967ec681f3Smrg texObj = ctx->Driver.NewTextureObject(ctx, textures[i], target); 11977117f1b4Smrg if (!texObj) { 119801e04c3fSmrg _mesa_HashUnlockMutex(ctx->Shared->TexObjects); 119901e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 12007117f1b4Smrg return; 12017117f1b4Smrg } 12027117f1b4Smrg 12037117f1b4Smrg /* insert into hash table */ 12047ec681f3Smrg _mesa_HashInsertLocked(ctx->Shared->TexObjects, texObj->Name, texObj, true); 12057117f1b4Smrg } 12067117f1b4Smrg 120701e04c3fSmrg _mesa_HashUnlockMutex(ctx->Shared->TexObjects); 12087117f1b4Smrg} 12097117f1b4Smrg 12107117f1b4Smrg 121101e04c3fSmrgstatic void 121201e04c3fSmrgcreate_textures_err(struct gl_context *ctx, GLenum target, 121301e04c3fSmrg GLsizei n, GLuint *textures, const char *caller) 121401e04c3fSmrg{ 121501e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 121601e04c3fSmrg _mesa_debug(ctx, "%s %d\n", caller, n); 121701e04c3fSmrg 121801e04c3fSmrg if (n < 0) { 121901e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller); 122001e04c3fSmrg return; 122101e04c3fSmrg } 122201e04c3fSmrg 122301e04c3fSmrg create_textures(ctx, target, n, textures, caller); 122401e04c3fSmrg} 122501e04c3fSmrg 122601e04c3fSmrg/*@}*/ 122701e04c3fSmrg 122801e04c3fSmrg 122901e04c3fSmrg/***********************************************************************/ 123001e04c3fSmrg/** \name API functions */ 123101e04c3fSmrg/*@{*/ 123201e04c3fSmrg 123301e04c3fSmrg 123401e04c3fSmrg/** 123501e04c3fSmrg * Generate texture names. 123601e04c3fSmrg * 123701e04c3fSmrg * \param n number of texture names to be generated. 123801e04c3fSmrg * \param textures an array in which will hold the generated texture names. 123901e04c3fSmrg * 124001e04c3fSmrg * \sa glGenTextures(), glCreateTextures(). 124101e04c3fSmrg * 12427ec681f3Smrg * Calls _mesa_HashFindFreeKeys() to find a block of free texture 124301e04c3fSmrg * IDs which are stored in \p textures. Corresponding empty texture 124401e04c3fSmrg * objects are also generated. 124501e04c3fSmrg */ 124601e04c3fSmrgvoid GLAPIENTRY 124701e04c3fSmrg_mesa_GenTextures_no_error(GLsizei n, GLuint *textures) 124801e04c3fSmrg{ 124901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 125001e04c3fSmrg create_textures(ctx, 0, n, textures, "glGenTextures"); 125101e04c3fSmrg} 125201e04c3fSmrg 125301e04c3fSmrg 125401e04c3fSmrgvoid GLAPIENTRY 125501e04c3fSmrg_mesa_GenTextures(GLsizei n, GLuint *textures) 125601e04c3fSmrg{ 125701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 125801e04c3fSmrg create_textures_err(ctx, 0, n, textures, "glGenTextures"); 125901e04c3fSmrg} 126001e04c3fSmrg 126101e04c3fSmrg/** 126201e04c3fSmrg * Create texture objects. 126301e04c3fSmrg * 126401e04c3fSmrg * \param target the texture target for each name to be generated. 126501e04c3fSmrg * \param n number of texture names to be generated. 126601e04c3fSmrg * \param textures an array in which will hold the generated texture names. 126701e04c3fSmrg * 126801e04c3fSmrg * \sa glCreateTextures(), glGenTextures(). 126901e04c3fSmrg * 12707ec681f3Smrg * Calls _mesa_HashFindFreeKeys() to find a block of free texture 127101e04c3fSmrg * IDs which are stored in \p textures. Corresponding empty texture 127201e04c3fSmrg * objects are also generated. 127301e04c3fSmrg */ 127401e04c3fSmrgvoid GLAPIENTRY 127501e04c3fSmrg_mesa_CreateTextures_no_error(GLenum target, GLsizei n, GLuint *textures) 127601e04c3fSmrg{ 127701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 127801e04c3fSmrg create_textures(ctx, target, n, textures, "glCreateTextures"); 127901e04c3fSmrg} 128001e04c3fSmrg 128101e04c3fSmrg 128201e04c3fSmrgvoid GLAPIENTRY 128301e04c3fSmrg_mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures) 128401e04c3fSmrg{ 128501e04c3fSmrg GLint targetIndex; 128601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 128701e04c3fSmrg 128801e04c3fSmrg /* 128901e04c3fSmrg * The 4.5 core profile spec (30.10.2014) doesn't specify what 129001e04c3fSmrg * glCreateTextures should do with invalid targets, which was probably an 129101e04c3fSmrg * oversight. This conforms to the spec for glBindTexture. 129201e04c3fSmrg */ 129301e04c3fSmrg targetIndex = _mesa_tex_target_to_index(ctx, target); 129401e04c3fSmrg if (targetIndex < 0) { 129501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glCreateTextures(target)"); 129601e04c3fSmrg return; 129701e04c3fSmrg } 129801e04c3fSmrg 129901e04c3fSmrg create_textures_err(ctx, target, n, textures, "glCreateTextures"); 130001e04c3fSmrg} 130101e04c3fSmrg 13027117f1b4Smrg/** 13037117f1b4Smrg * Check if the given texture object is bound to the current draw or 13047117f1b4Smrg * read framebuffer. If so, Unbind it. 13057117f1b4Smrg */ 13067117f1b4Smrgstatic void 13073464ebd5Sriastradhunbind_texobj_from_fbo(struct gl_context *ctx, 13083464ebd5Sriastradh struct gl_texture_object *texObj) 13097117f1b4Smrg{ 1310af69d88dSmrg bool progress = false; 1311af69d88dSmrg 1312af69d88dSmrg /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection 1313af69d88dSmrg * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec 1314af69d88dSmrg * says: 1315af69d88dSmrg * 1316af69d88dSmrg * "If a texture object is deleted while its image is attached to one 1317af69d88dSmrg * or more attachment points in the currently bound framebuffer, then 1318af69d88dSmrg * it is as if FramebufferTexture* had been called, with a texture of 1319af69d88dSmrg * zero, for each attachment point to which this image was attached in 1320af69d88dSmrg * the currently bound framebuffer. In other words, this texture image 1321af69d88dSmrg * is first detached from all attachment points in the currently bound 1322af69d88dSmrg * framebuffer. Note that the texture image is specifically not 1323af69d88dSmrg * detached from any other framebuffer objects. Detaching the texture 1324af69d88dSmrg * image from any other framebuffer objects is the responsibility of 1325af69d88dSmrg * the application." 1326af69d88dSmrg */ 1327af69d88dSmrg if (_mesa_is_user_fbo(ctx->DrawBuffer)) { 1328af69d88dSmrg progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj); 1329af69d88dSmrg } 1330af69d88dSmrg if (_mesa_is_user_fbo(ctx->ReadBuffer) 1331af69d88dSmrg && ctx->ReadBuffer != ctx->DrawBuffer) { 1332af69d88dSmrg progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj) 1333af69d88dSmrg || progress; 13347117f1b4Smrg } 1335af69d88dSmrg 1336af69d88dSmrg if (progress) 1337af69d88dSmrg /* Vertices are already flushed by _mesa_DeleteTextures */ 1338af69d88dSmrg ctx->NewState |= _NEW_BUFFERS; 13397117f1b4Smrg} 13407117f1b4Smrg 13417117f1b4Smrg 13427117f1b4Smrg/** 13437117f1b4Smrg * Check if the given texture object is bound to any texture image units and 13447117f1b4Smrg * unbind it if so (revert to default textures). 13457117f1b4Smrg */ 13467117f1b4Smrgstatic void 13473464ebd5Sriastradhunbind_texobj_from_texunits(struct gl_context *ctx, 13483464ebd5Sriastradh struct gl_texture_object *texObj) 13497117f1b4Smrg{ 1350af69d88dSmrg const gl_texture_index index = texObj->TargetIndex; 1351af69d88dSmrg GLuint u; 13527117f1b4Smrg 135301e04c3fSmrg if (texObj->Target == 0) { 135401e04c3fSmrg /* texture was never bound */ 1355af69d88dSmrg return; 135601e04c3fSmrg } 135701e04c3fSmrg 135801e04c3fSmrg assert(index < NUM_TEXTURE_TARGETS); 1359af69d88dSmrg 1360af69d88dSmrg for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) { 13617117f1b4Smrg struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; 1362af69d88dSmrg 1363af69d88dSmrg if (texObj == unit->CurrentTex[index]) { 1364af69d88dSmrg /* Bind the default texture for this unit/target */ 1365af69d88dSmrg _mesa_reference_texobj(&unit->CurrentTex[index], 1366af69d88dSmrg ctx->Shared->DefaultTex[index]); 1367af69d88dSmrg unit->_BoundTextures &= ~(1 << index); 13687117f1b4Smrg } 13697117f1b4Smrg } 13707117f1b4Smrg} 13717117f1b4Smrg 13727117f1b4Smrg 1373af69d88dSmrg/** 1374af69d88dSmrg * Check if the given texture object is bound to any shader image unit 1375af69d88dSmrg * and unbind it if that's the case. 1376af69d88dSmrg */ 1377af69d88dSmrgstatic void 1378af69d88dSmrgunbind_texobj_from_image_units(struct gl_context *ctx, 1379af69d88dSmrg struct gl_texture_object *texObj) 1380af69d88dSmrg{ 1381af69d88dSmrg GLuint i; 1382af69d88dSmrg 1383af69d88dSmrg for (i = 0; i < ctx->Const.MaxImageUnits; i++) { 1384af69d88dSmrg struct gl_image_unit *unit = &ctx->ImageUnits[i]; 1385af69d88dSmrg 138601e04c3fSmrg if (texObj == unit->TexObj) { 1387af69d88dSmrg _mesa_reference_texobj(&unit->TexObj, NULL); 138801e04c3fSmrg *unit = _mesa_default_image_unit(ctx); 138901e04c3fSmrg } 1390af69d88dSmrg } 1391af69d88dSmrg} 1392af69d88dSmrg 139301e04c3fSmrg 1394af69d88dSmrg/** 1395af69d88dSmrg * Unbinds all textures bound to the given texture image unit. 1396af69d88dSmrg */ 1397af69d88dSmrgstatic void 1398af69d88dSmrgunbind_textures_from_unit(struct gl_context *ctx, GLuint unit) 1399af69d88dSmrg{ 1400af69d88dSmrg struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 1401af69d88dSmrg 1402af69d88dSmrg while (texUnit->_BoundTextures) { 1403af69d88dSmrg const GLuint index = ffs(texUnit->_BoundTextures) - 1; 1404af69d88dSmrg struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index]; 1405af69d88dSmrg 1406af69d88dSmrg _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj); 1407af69d88dSmrg 1408af69d88dSmrg /* Pass BindTexture call to device driver */ 1409af69d88dSmrg if (ctx->Driver.BindTexture) 1410af69d88dSmrg ctx->Driver.BindTexture(ctx, unit, 0, texObj); 1411af69d88dSmrg 1412af69d88dSmrg texUnit->_BoundTextures &= ~(1 << index); 141301e04c3fSmrg ctx->NewState |= _NEW_TEXTURE_OBJECT; 14147ec681f3Smrg ctx->PopAttribState |= GL_TEXTURE_BIT; 1415af69d88dSmrg } 1416af69d88dSmrg} 1417af69d88dSmrg 141801e04c3fSmrg 14197117f1b4Smrg/** 14207117f1b4Smrg * Delete named textures. 14217117f1b4Smrg * 14227117f1b4Smrg * \param n number of textures to be deleted. 14237117f1b4Smrg * \param textures array of texture IDs to be deleted. 14247117f1b4Smrg * 14257117f1b4Smrg * \sa glDeleteTextures(). 14267117f1b4Smrg * 14277117f1b4Smrg * If we're about to delete a texture that's currently bound to any 14287117f1b4Smrg * texture unit, unbind the texture first. Decrement the reference 14297117f1b4Smrg * count on the texture object and delete it if it's zero. 14307117f1b4Smrg * Recall that texture objects can be shared among several rendering 14317117f1b4Smrg * contexts. 14327117f1b4Smrg */ 143301e04c3fSmrgstatic void 143401e04c3fSmrgdelete_textures(struct gl_context *ctx, GLsizei n, const GLuint *textures) 14357117f1b4Smrg{ 14367ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); /* too complex */ 14377117f1b4Smrg 14387117f1b4Smrg if (!textures) 14397117f1b4Smrg return; 14407117f1b4Smrg 144101e04c3fSmrg for (GLsizei i = 0; i < n; i++) { 14427117f1b4Smrg if (textures[i] > 0) { 14437117f1b4Smrg struct gl_texture_object *delObj 14447117f1b4Smrg = _mesa_lookup_texture(ctx, textures[i]); 14457117f1b4Smrg 14467117f1b4Smrg if (delObj) { 14473464ebd5Sriastradh _mesa_lock_texture(ctx, delObj); 14487117f1b4Smrg 14497117f1b4Smrg /* Check if texture is bound to any framebuffer objects. 14507117f1b4Smrg * If so, unbind. 14517117f1b4Smrg * See section 4.4.2.3 of GL_EXT_framebuffer_object. 14527117f1b4Smrg */ 14537117f1b4Smrg unbind_texobj_from_fbo(ctx, delObj); 14547117f1b4Smrg 14557117f1b4Smrg /* Check if this texture is currently bound to any texture units. 14567117f1b4Smrg * If so, unbind it. 14577117f1b4Smrg */ 14587117f1b4Smrg unbind_texobj_from_texunits(ctx, delObj); 14597117f1b4Smrg 1460af69d88dSmrg /* Check if this texture is currently bound to any shader 1461af69d88dSmrg * image unit. If so, unbind it. 1462af69d88dSmrg * See section 3.9.X of GL_ARB_shader_image_load_store. 1463af69d88dSmrg */ 1464af69d88dSmrg unbind_texobj_from_image_units(ctx, delObj); 1465af69d88dSmrg 146601e04c3fSmrg /* Make all handles that reference this texture object non-resident 146701e04c3fSmrg * in the current context. 146801e04c3fSmrg */ 146901e04c3fSmrg _mesa_make_texture_handles_non_resident(ctx, delObj); 147001e04c3fSmrg 14713464ebd5Sriastradh _mesa_unlock_texture(ctx, delObj); 14727117f1b4Smrg 147301e04c3fSmrg ctx->NewState |= _NEW_TEXTURE_OBJECT; 14747ec681f3Smrg ctx->PopAttribState |= GL_TEXTURE_BIT; 14757117f1b4Smrg 14767117f1b4Smrg /* The texture _name_ is now free for re-use. 14777117f1b4Smrg * Remove it from the hash table now. 14787117f1b4Smrg */ 14797117f1b4Smrg _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); 14807117f1b4Smrg 14817ec681f3Smrg if (ctx->Driver.TextureRemovedFromShared) { 14827ec681f3Smrg ctx->Driver.TextureRemovedFromShared(ctx, delObj); 14837ec681f3Smrg } 14847ec681f3Smrg 14857117f1b4Smrg /* Unreference the texobj. If refcount hits zero, the texture 14867117f1b4Smrg * will be deleted. 14877117f1b4Smrg */ 14887117f1b4Smrg _mesa_reference_texobj(&delObj, NULL); 14897117f1b4Smrg } 14907117f1b4Smrg } 14917117f1b4Smrg } 14927117f1b4Smrg} 14937117f1b4Smrg 149401e04c3fSmrg/** 149501e04c3fSmrg * This deletes a texObj without altering the hash table. 149601e04c3fSmrg */ 149701e04c3fSmrgvoid 149801e04c3fSmrg_mesa_delete_nameless_texture(struct gl_context *ctx, 149901e04c3fSmrg struct gl_texture_object *texObj) 150001e04c3fSmrg{ 150101e04c3fSmrg if (!texObj) 150201e04c3fSmrg return; 150301e04c3fSmrg 15047ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT); 150501e04c3fSmrg 150601e04c3fSmrg _mesa_lock_texture(ctx, texObj); 150701e04c3fSmrg { 150801e04c3fSmrg /* Check if texture is bound to any framebuffer objects. 150901e04c3fSmrg * If so, unbind. 151001e04c3fSmrg * See section 4.4.2.3 of GL_EXT_framebuffer_object. 151101e04c3fSmrg */ 151201e04c3fSmrg unbind_texobj_from_fbo(ctx, texObj); 151301e04c3fSmrg 151401e04c3fSmrg /* Check if this texture is currently bound to any texture units. 151501e04c3fSmrg * If so, unbind it. 151601e04c3fSmrg */ 151701e04c3fSmrg unbind_texobj_from_texunits(ctx, texObj); 151801e04c3fSmrg 151901e04c3fSmrg /* Check if this texture is currently bound to any shader 152001e04c3fSmrg * image unit. If so, unbind it. 152101e04c3fSmrg * See section 3.9.X of GL_ARB_shader_image_load_store. 152201e04c3fSmrg */ 152301e04c3fSmrg unbind_texobj_from_image_units(ctx, texObj); 152401e04c3fSmrg } 152501e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 152601e04c3fSmrg 152701e04c3fSmrg /* Unreference the texobj. If refcount hits zero, the texture 152801e04c3fSmrg * will be deleted. 152901e04c3fSmrg */ 153001e04c3fSmrg _mesa_reference_texobj(&texObj, NULL); 153101e04c3fSmrg} 153201e04c3fSmrg 153301e04c3fSmrg 153401e04c3fSmrgvoid GLAPIENTRY 153501e04c3fSmrg_mesa_DeleteTextures_no_error(GLsizei n, const GLuint *textures) 153601e04c3fSmrg{ 153701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 153801e04c3fSmrg delete_textures(ctx, n, textures); 153901e04c3fSmrg} 154001e04c3fSmrg 154101e04c3fSmrg 154201e04c3fSmrgvoid GLAPIENTRY 154301e04c3fSmrg_mesa_DeleteTextures(GLsizei n, const GLuint *textures) 154401e04c3fSmrg{ 154501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 154601e04c3fSmrg 154701e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 154801e04c3fSmrg _mesa_debug(ctx, "glDeleteTextures %d\n", n); 154901e04c3fSmrg 155001e04c3fSmrg if (n < 0) { 155101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTextures(n < 0)"); 155201e04c3fSmrg return; 155301e04c3fSmrg } 155401e04c3fSmrg 155501e04c3fSmrg delete_textures(ctx, n, textures); 155601e04c3fSmrg} 155701e04c3fSmrg 15587117f1b4Smrg 1559c1f859d4Smrg/** 1560c1f859d4Smrg * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D 1561c1f859d4Smrg * into the corresponding Mesa texture target index. 1562cdc920a0Smrg * Note that proxy targets are not valid here. 1563cdc920a0Smrg * \return TEXTURE_x_INDEX or -1 if target is invalid 1564c1f859d4Smrg */ 1565af69d88dSmrgint 1566af69d88dSmrg_mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target) 1567c1f859d4Smrg{ 1568c1f859d4Smrg switch (target) { 1569c1f859d4Smrg case GL_TEXTURE_1D: 1570af69d88dSmrg return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1; 1571c1f859d4Smrg case GL_TEXTURE_2D: 1572c1f859d4Smrg return TEXTURE_2D_INDEX; 1573c1f859d4Smrg case GL_TEXTURE_3D: 1574af69d88dSmrg return ctx->API != API_OPENGLES ? TEXTURE_3D_INDEX : -1; 1575af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 1576af69d88dSmrg return ctx->Extensions.ARB_texture_cube_map 1577af69d88dSmrg ? TEXTURE_CUBE_INDEX : -1; 1578af69d88dSmrg case GL_TEXTURE_RECTANGLE: 1579af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle 1580af69d88dSmrg ? TEXTURE_RECT_INDEX : -1; 1581af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 1582af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array 1583af69d88dSmrg ? TEXTURE_1D_ARRAY_INDEX : -1; 1584af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 1585af69d88dSmrg return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) 1586af69d88dSmrg || _mesa_is_gles3(ctx) 1587af69d88dSmrg ? TEXTURE_2D_ARRAY_INDEX : -1; 1588af69d88dSmrg case GL_TEXTURE_BUFFER: 158901e04c3fSmrg return (_mesa_has_ARB_texture_buffer_object(ctx) || 159001e04c3fSmrg _mesa_has_OES_texture_buffer(ctx)) ? 1591af69d88dSmrg TEXTURE_BUFFER_INDEX : -1; 1592af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 1593af69d88dSmrg return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external 1594af69d88dSmrg ? TEXTURE_EXTERNAL_INDEX : -1; 1595af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 159601e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx) 1597af69d88dSmrg ? TEXTURE_CUBE_ARRAY_INDEX : -1; 1598af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 159901e04c3fSmrg return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) || 160001e04c3fSmrg _mesa_is_gles31(ctx)) ? TEXTURE_2D_MULTISAMPLE_INDEX: -1; 1601af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 160201e04c3fSmrg return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) || 160301e04c3fSmrg _mesa_is_gles31(ctx)) 1604af69d88dSmrg ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1; 1605c1f859d4Smrg default: 1606c1f859d4Smrg return -1; 1607c1f859d4Smrg } 1608c1f859d4Smrg} 1609c1f859d4Smrg 1610c1f859d4Smrg 16117117f1b4Smrg/** 161201e04c3fSmrg * Do actual texture binding. All error checking should have been done prior 161301e04c3fSmrg * to calling this function. Note that the texture target (1D, 2D, etc) is 161401e04c3fSmrg * always specified by the texObj->TargetIndex. 161501e04c3fSmrg * 161601e04c3fSmrg * \param unit index of texture unit to update 161701e04c3fSmrg * \param texObj the new texture object (cannot be NULL) 161801e04c3fSmrg */ 161901e04c3fSmrgstatic void 162001e04c3fSmrgbind_texture_object(struct gl_context *ctx, unsigned unit, 162101e04c3fSmrg struct gl_texture_object *texObj) 162201e04c3fSmrg{ 162301e04c3fSmrg struct gl_texture_unit *texUnit; 162401e04c3fSmrg int targetIndex; 162501e04c3fSmrg 162601e04c3fSmrg assert(unit < ARRAY_SIZE(ctx->Texture.Unit)); 162701e04c3fSmrg texUnit = &ctx->Texture.Unit[unit]; 162801e04c3fSmrg 162901e04c3fSmrg assert(texObj); 163001e04c3fSmrg assert(valid_texture_object(texObj)); 163101e04c3fSmrg 163201e04c3fSmrg targetIndex = texObj->TargetIndex; 163301e04c3fSmrg assert(targetIndex >= 0); 163401e04c3fSmrg assert(targetIndex < NUM_TEXTURE_TARGETS); 163501e04c3fSmrg 163601e04c3fSmrg /* Check if this texture is only used by this context and is already bound. 163701e04c3fSmrg * If so, just return. For GL_OES_image_external, rebinding the texture 163801e04c3fSmrg * always must invalidate cached resources. 163901e04c3fSmrg */ 16407ec681f3Smrg if (targetIndex != TEXTURE_EXTERNAL_INDEX && 16417ec681f3Smrg ctx->Shared->RefCount == 1 && 16427ec681f3Smrg texObj == texUnit->CurrentTex[targetIndex]) 16437ec681f3Smrg return; 164401e04c3fSmrg 16457ec681f3Smrg /* Flush before changing binding. 16467ec681f3Smrg * 16477ec681f3Smrg * Note: Multisample textures don't need to flag GL_TEXTURE_BIT because 16487ec681f3Smrg * they are not restored by glPopAttrib according to the GL 4.6 16497ec681f3Smrg * Compatibility Profile specification. We set GL_TEXTURE_BIT anyway 16507ec681f3Smrg * to simplify the code. This has no effect on behavior. 16517ec681f3Smrg */ 16527ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT); 165301e04c3fSmrg 165401e04c3fSmrg /* If the refcount on the previously bound texture is decremented to 165501e04c3fSmrg * zero, it'll be deleted here. 165601e04c3fSmrg */ 165701e04c3fSmrg _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], texObj); 165801e04c3fSmrg 165901e04c3fSmrg ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed, 166001e04c3fSmrg unit + 1); 166101e04c3fSmrg 166201e04c3fSmrg if (texObj->Name != 0) 166301e04c3fSmrg texUnit->_BoundTextures |= (1 << targetIndex); 166401e04c3fSmrg else 166501e04c3fSmrg texUnit->_BoundTextures &= ~(1 << targetIndex); 166601e04c3fSmrg 166701e04c3fSmrg /* Pass BindTexture call to device driver */ 166801e04c3fSmrg if (ctx->Driver.BindTexture) { 166901e04c3fSmrg ctx->Driver.BindTexture(ctx, unit, texObj->Target, texObj); 167001e04c3fSmrg } 167101e04c3fSmrg} 167201e04c3fSmrg 167301e04c3fSmrg/** 167401e04c3fSmrg * Light-weight bind texture for internal users 167501e04c3fSmrg * 167601e04c3fSmrg * This is really just \c finish_texture_init plus \c bind_texture_object. 167701e04c3fSmrg * This is intended to be used by internal Mesa functions that use 167801e04c3fSmrg * \c _mesa_CreateTexture and need to bind textures (e.g., meta). 167901e04c3fSmrg */ 168001e04c3fSmrgvoid 168101e04c3fSmrg_mesa_bind_texture(struct gl_context *ctx, GLenum target, 168201e04c3fSmrg struct gl_texture_object *tex_obj) 168301e04c3fSmrg{ 168401e04c3fSmrg const GLint targetIndex = _mesa_tex_target_to_index(ctx, target); 168501e04c3fSmrg 168601e04c3fSmrg assert(targetIndex >= 0 && targetIndex < NUM_TEXTURE_TARGETS); 168701e04c3fSmrg 168801e04c3fSmrg if (tex_obj->Target == 0) 168901e04c3fSmrg finish_texture_init(ctx, target, tex_obj, targetIndex); 169001e04c3fSmrg 169101e04c3fSmrg assert(tex_obj->Target == target); 169201e04c3fSmrg assert(tex_obj->TargetIndex == targetIndex); 169301e04c3fSmrg 169401e04c3fSmrg bind_texture_object(ctx, ctx->Texture.CurrentUnit, tex_obj); 169501e04c3fSmrg} 169601e04c3fSmrg 16977ec681f3Smrgstruct gl_texture_object * 16987ec681f3Smrg_mesa_lookup_or_create_texture(struct gl_context *ctx, GLenum target, 16997ec681f3Smrg GLuint texName, bool no_error, bool is_ext_dsa, 17007ec681f3Smrg const char *caller) 17017117f1b4Smrg{ 17023464ebd5Sriastradh struct gl_texture_object *newTexObj = NULL; 170301e04c3fSmrg int targetIndex; 17047117f1b4Smrg 17057ec681f3Smrg if (is_ext_dsa) { 17067ec681f3Smrg if (_mesa_is_proxy_texture(target)) { 17077ec681f3Smrg /* EXT_dsa allows proxy targets only when texName is 0 */ 17087ec681f3Smrg if (texName != 0) { 17097ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(target = %s)", caller, 17107ec681f3Smrg _mesa_enum_to_string(target)); 17117ec681f3Smrg return NULL; 17127ec681f3Smrg } 17137ec681f3Smrg return _mesa_get_current_tex_object(ctx, target); 17147ec681f3Smrg } 17157ec681f3Smrg if (GL_TEXTURE_CUBE_MAP_POSITIVE_X <= target && 17167ec681f3Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { 17177ec681f3Smrg target = GL_TEXTURE_CUBE_MAP; 17187ec681f3Smrg } 17197ec681f3Smrg } 17207ec681f3Smrg 1721af69d88dSmrg targetIndex = _mesa_tex_target_to_index(ctx, target); 172201e04c3fSmrg if (!no_error && targetIndex < 0) { 17237ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target = %s)", caller, 172401e04c3fSmrg _mesa_enum_to_string(target)); 17257ec681f3Smrg return NULL; 1726c1f859d4Smrg } 1727c1f859d4Smrg assert(targetIndex < NUM_TEXTURE_TARGETS); 1728c1f859d4Smrg 17297117f1b4Smrg /* 17307117f1b4Smrg * Get pointer to new texture object (newTexObj) 17317117f1b4Smrg */ 17327117f1b4Smrg if (texName == 0) { 17333464ebd5Sriastradh /* Use a default texture object */ 17343464ebd5Sriastradh newTexObj = ctx->Shared->DefaultTex[targetIndex]; 173501e04c3fSmrg } else { 17367117f1b4Smrg /* non-default texture object */ 17377117f1b4Smrg newTexObj = _mesa_lookup_texture(ctx, texName); 17387117f1b4Smrg if (newTexObj) { 17397117f1b4Smrg /* error checking */ 174001e04c3fSmrg if (!no_error && 174101e04c3fSmrg newTexObj->Target != 0 && newTexObj->Target != target) { 174201e04c3fSmrg /* The named texture object's target doesn't match the 174301e04c3fSmrg * given target 174401e04c3fSmrg */ 17457ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17467ec681f3Smrg "%s(target mismatch)", caller); 17477ec681f3Smrg return NULL; 17487117f1b4Smrg } 1749c1f859d4Smrg if (newTexObj->Target == 0) { 175001e04c3fSmrg finish_texture_init(ctx, target, newTexObj, targetIndex); 17517117f1b4Smrg } 17527ec681f3Smrg } else { 175301e04c3fSmrg if (!no_error && ctx->API == API_OPENGL_CORE) { 175401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 17557ec681f3Smrg "%s(non-gen name)", caller); 17567ec681f3Smrg return NULL; 1757af69d88dSmrg } 1758af69d88dSmrg 17597117f1b4Smrg /* if this is a new texture id, allocate a texture object now */ 1760af69d88dSmrg newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target); 17617117f1b4Smrg if (!newTexObj) { 17627ec681f3Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 17637ec681f3Smrg return NULL; 17647117f1b4Smrg } 17657117f1b4Smrg 17667117f1b4Smrg /* and insert it into hash table */ 17677ec681f3Smrg _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj, false); 17687117f1b4Smrg } 17697117f1b4Smrg } 17707117f1b4Smrg 177101e04c3fSmrg assert(newTexObj->Target == target); 177201e04c3fSmrg assert(newTexObj->TargetIndex == targetIndex); 17737117f1b4Smrg 17747ec681f3Smrg return newTexObj; 17757ec681f3Smrg} 17767ec681f3Smrg 17777ec681f3Smrg/** 17787ec681f3Smrg * Implement glBindTexture(). Do error checking, look-up or create a new 17797ec681f3Smrg * texture object, then bind it in the current texture unit. 17807ec681f3Smrg * 17817ec681f3Smrg * \param target texture target. 17827ec681f3Smrg * \param texName texture name. 17837ec681f3Smrg * \param texunit texture unit. 17847ec681f3Smrg */ 17857ec681f3Smrgstatic ALWAYS_INLINE void 17867ec681f3Smrgbind_texture(struct gl_context *ctx, GLenum target, GLuint texName, 17877ec681f3Smrg GLenum texunit, bool no_error, const char *caller) 17887ec681f3Smrg{ 17897ec681f3Smrg struct gl_texture_object *newTexObj = 17907ec681f3Smrg _mesa_lookup_or_create_texture(ctx, target, texName, no_error, false, 17917ec681f3Smrg caller); 17927ec681f3Smrg if (!newTexObj) 17937ec681f3Smrg return; 17947ec681f3Smrg 17957ec681f3Smrg bind_texture_object(ctx, texunit, newTexObj); 179601e04c3fSmrg} 179701e04c3fSmrg 179801e04c3fSmrgvoid GLAPIENTRY 179901e04c3fSmrg_mesa_BindTexture_no_error(GLenum target, GLuint texName) 180001e04c3fSmrg{ 180101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 18027ec681f3Smrg bind_texture(ctx, target, texName, ctx->Texture.CurrentUnit, true, 18037ec681f3Smrg "glBindTexture"); 180401e04c3fSmrg} 180501e04c3fSmrg 180601e04c3fSmrg 180701e04c3fSmrgvoid GLAPIENTRY 180801e04c3fSmrg_mesa_BindTexture(GLenum target, GLuint texName) 180901e04c3fSmrg{ 181001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 181101e04c3fSmrg 181201e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 181301e04c3fSmrg _mesa_debug(ctx, "glBindTexture %s %d\n", 181401e04c3fSmrg _mesa_enum_to_string(target), (GLint) texName); 181501e04c3fSmrg 18167ec681f3Smrg bind_texture(ctx, target, texName, ctx->Texture.CurrentUnit, false, 18177ec681f3Smrg "glBindTexture"); 18187ec681f3Smrg} 18197ec681f3Smrg 18207ec681f3Smrg 18217ec681f3Smrgvoid GLAPIENTRY 18227ec681f3Smrg_mesa_BindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture) 18237ec681f3Smrg{ 18247ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 18257ec681f3Smrg 18267ec681f3Smrg unsigned unit = texunit - GL_TEXTURE0; 18277ec681f3Smrg 18287ec681f3Smrg if (texunit < GL_TEXTURE0 || unit >= _mesa_max_tex_unit(ctx)) { 18297ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBindMultiTextureEXT(texunit=%s)", 18307ec681f3Smrg _mesa_enum_to_string(texunit)); 18317ec681f3Smrg return; 18327ec681f3Smrg } 18337ec681f3Smrg 18347ec681f3Smrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 18357ec681f3Smrg _mesa_debug(ctx, "glBindMultiTextureEXT %s %d\n", 18367ec681f3Smrg _mesa_enum_to_string(texunit), (GLint) texture); 18377ec681f3Smrg 18387ec681f3Smrg bind_texture(ctx, target, texture, unit, false, "glBindMultiTextureEXT"); 183901e04c3fSmrg} 184001e04c3fSmrg 184101e04c3fSmrg 184201e04c3fSmrg/** 184301e04c3fSmrg * OpenGL 4.5 / GL_ARB_direct_state_access glBindTextureUnit(). 184401e04c3fSmrg * 184501e04c3fSmrg * \param unit texture unit. 184601e04c3fSmrg * \param texture texture name. 184701e04c3fSmrg * 184801e04c3fSmrg * \sa glBindTexture(). 184901e04c3fSmrg * 185001e04c3fSmrg * If the named texture is 0, this will reset each target for the specified 185101e04c3fSmrg * texture unit to its default texture. 185201e04c3fSmrg * If the named texture is not 0 or a recognized texture name, this throws 185301e04c3fSmrg * GL_INVALID_OPERATION. 185401e04c3fSmrg */ 185501e04c3fSmrgstatic ALWAYS_INLINE void 185601e04c3fSmrgbind_texture_unit(struct gl_context *ctx, GLuint unit, GLuint texture, 185701e04c3fSmrg bool no_error) 185801e04c3fSmrg{ 185901e04c3fSmrg struct gl_texture_object *texObj; 186001e04c3fSmrg 186101e04c3fSmrg /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec 186201e04c3fSmrg * (20141030) says: 186301e04c3fSmrg * "When texture is zero, each of the targets enumerated at the 186401e04c3fSmrg * beginning of this section is reset to its default texture for the 186501e04c3fSmrg * corresponding texture image unit." 18663464ebd5Sriastradh */ 186701e04c3fSmrg if (texture == 0) { 186801e04c3fSmrg unbind_textures_from_unit(ctx, unit); 186901e04c3fSmrg return; 187001e04c3fSmrg } 187101e04c3fSmrg 187201e04c3fSmrg /* Get the non-default texture object */ 187301e04c3fSmrg texObj = _mesa_lookup_texture(ctx, texture); 187401e04c3fSmrg if (!no_error) { 187501e04c3fSmrg /* Error checking */ 187601e04c3fSmrg if (!texObj) { 187701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 187801e04c3fSmrg "glBindTextureUnit(non-gen name)"); 187901e04c3fSmrg return; 188001e04c3fSmrg } 188101e04c3fSmrg 188201e04c3fSmrg if (texObj->Target == 0) { 188301e04c3fSmrg /* Texture object was gen'd but never bound so the target is not set */ 188401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTextureUnit(target)"); 18853464ebd5Sriastradh return; 18863464ebd5Sriastradh } 18874a49301eSmrg } 18884a49301eSmrg 188901e04c3fSmrg assert(valid_texture_object(texObj)); 18907117f1b4Smrg 189101e04c3fSmrg bind_texture_object(ctx, unit, texObj); 189201e04c3fSmrg} 18937117f1b4Smrg 1894af69d88dSmrg 189501e04c3fSmrgvoid GLAPIENTRY 189601e04c3fSmrg_mesa_BindTextureUnit_no_error(GLuint unit, GLuint texture) 189701e04c3fSmrg{ 189801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 189901e04c3fSmrg bind_texture_unit(ctx, unit, texture, true); 1900af69d88dSmrg} 1901af69d88dSmrg 1902af69d88dSmrg 1903af69d88dSmrgvoid GLAPIENTRY 190401e04c3fSmrg_mesa_BindTextureUnit(GLuint unit, GLuint texture) 1905af69d88dSmrg{ 1906af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1907af69d88dSmrg 190801e04c3fSmrg if (unit >= _mesa_max_tex_unit(ctx)) { 190901e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindTextureUnit(unit=%u)", unit); 1910af69d88dSmrg return; 1911af69d88dSmrg } 1912af69d88dSmrg 191301e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 191401e04c3fSmrg _mesa_debug(ctx, "glBindTextureUnit %s %d\n", 191501e04c3fSmrg _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture); 191601e04c3fSmrg 191701e04c3fSmrg bind_texture_unit(ctx, unit, texture, false); 191801e04c3fSmrg} 1919af69d88dSmrg 192001e04c3fSmrg 192101e04c3fSmrg/** 192201e04c3fSmrg * OpenGL 4.4 / GL_ARB_multi_bind glBindTextures(). 192301e04c3fSmrg */ 192401e04c3fSmrgstatic ALWAYS_INLINE void 192501e04c3fSmrgbind_textures(struct gl_context *ctx, GLuint first, GLsizei count, 192601e04c3fSmrg const GLuint *textures, bool no_error) 192701e04c3fSmrg{ 192801e04c3fSmrg GLsizei i; 1929af69d88dSmrg 1930af69d88dSmrg if (textures) { 1931af69d88dSmrg /* Note that the error semantics for multi-bind commands differ from 1932af69d88dSmrg * those of other GL commands. 1933af69d88dSmrg * 1934af69d88dSmrg * The issues section in the ARB_multi_bind spec says: 1935af69d88dSmrg * 1936af69d88dSmrg * "(11) Typically, OpenGL specifies that if an error is generated by 1937af69d88dSmrg * a command, that command has no effect. This is somewhat 1938af69d88dSmrg * unfortunate for multi-bind commands, because it would require 1939af69d88dSmrg * a first pass to scan the entire list of bound objects for 1940af69d88dSmrg * errors and then a second pass to actually perform the 1941af69d88dSmrg * bindings. Should we have different error semantics? 1942af69d88dSmrg * 1943af69d88dSmrg * RESOLVED: Yes. In this specification, when the parameters for 1944af69d88dSmrg * one of the <count> binding points are invalid, that binding 1945af69d88dSmrg * point is not updated and an error will be generated. However, 1946af69d88dSmrg * other binding points in the same command will be updated if 1947af69d88dSmrg * their parameters are valid and no other error occurs." 1948af69d88dSmrg */ 1949af69d88dSmrg 195001e04c3fSmrg _mesa_HashLockMutex(ctx->Shared->TexObjects); 1951af69d88dSmrg 1952af69d88dSmrg for (i = 0; i < count; i++) { 1953af69d88dSmrg if (textures[i] != 0) { 1954af69d88dSmrg struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i]; 1955af69d88dSmrg struct gl_texture_object *current = texUnit->_Current; 1956af69d88dSmrg struct gl_texture_object *texObj; 1957af69d88dSmrg 1958af69d88dSmrg if (current && current->Name == textures[i]) 1959af69d88dSmrg texObj = current; 1960af69d88dSmrg else 1961af69d88dSmrg texObj = _mesa_lookup_texture_locked(ctx, textures[i]); 1962af69d88dSmrg 1963af69d88dSmrg if (texObj && texObj->Target != 0) { 196401e04c3fSmrg bind_texture_object(ctx, first + i, texObj); 196501e04c3fSmrg } else if (!no_error) { 1966af69d88dSmrg /* The ARB_multi_bind spec says: 1967af69d88dSmrg * 1968af69d88dSmrg * "An INVALID_OPERATION error is generated if any value 1969af69d88dSmrg * in <textures> is not zero or the name of an existing 1970af69d88dSmrg * texture object (per binding)." 1971af69d88dSmrg */ 1972af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1973af69d88dSmrg "glBindTextures(textures[%d]=%u is not zero " 1974af69d88dSmrg "or the name of an existing texture object)", 1975af69d88dSmrg i, textures[i]); 1976af69d88dSmrg } 1977af69d88dSmrg } else { 1978af69d88dSmrg unbind_textures_from_unit(ctx, first + i); 1979af69d88dSmrg } 1980af69d88dSmrg } 1981af69d88dSmrg 198201e04c3fSmrg _mesa_HashUnlockMutex(ctx->Shared->TexObjects); 1983af69d88dSmrg } else { 1984af69d88dSmrg /* Unbind all textures in the range <first> through <first>+<count>-1 */ 1985af69d88dSmrg for (i = 0; i < count; i++) 1986af69d88dSmrg unbind_textures_from_unit(ctx, first + i); 1987af69d88dSmrg } 19887117f1b4Smrg} 19897117f1b4Smrg 19907117f1b4Smrg 199101e04c3fSmrgvoid GLAPIENTRY 199201e04c3fSmrg_mesa_BindTextures_no_error(GLuint first, GLsizei count, const GLuint *textures) 199301e04c3fSmrg{ 199401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 199501e04c3fSmrg bind_textures(ctx, first, count, textures, true); 199601e04c3fSmrg} 199701e04c3fSmrg 199801e04c3fSmrg 199901e04c3fSmrgvoid GLAPIENTRY 200001e04c3fSmrg_mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures) 200101e04c3fSmrg{ 200201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 200301e04c3fSmrg 200401e04c3fSmrg /* The ARB_multi_bind spec says: 200501e04c3fSmrg * 200601e04c3fSmrg * "An INVALID_OPERATION error is generated if <first> + <count> 200701e04c3fSmrg * is greater than the number of texture image units supported 200801e04c3fSmrg * by the implementation." 200901e04c3fSmrg */ 201001e04c3fSmrg if (first + count > ctx->Const.MaxCombinedTextureImageUnits) { 201101e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 201201e04c3fSmrg "glBindTextures(first=%u + count=%d > the value of " 201301e04c3fSmrg "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)", 201401e04c3fSmrg first, count, ctx->Const.MaxCombinedTextureImageUnits); 201501e04c3fSmrg return; 201601e04c3fSmrg } 201701e04c3fSmrg 201801e04c3fSmrg bind_textures(ctx, first, count, textures, false); 201901e04c3fSmrg} 202001e04c3fSmrg 202101e04c3fSmrg 20227117f1b4Smrg/** 20237117f1b4Smrg * Set texture priorities. 202401e04c3fSmrg * 20257117f1b4Smrg * \param n number of textures. 20267117f1b4Smrg * \param texName texture names. 20277117f1b4Smrg * \param priorities corresponding texture priorities. 202801e04c3fSmrg * 20297117f1b4Smrg * \sa glPrioritizeTextures(). 203001e04c3fSmrg * 20317117f1b4Smrg * Looks up each texture in the hash, clamps the corresponding priority between 20327117f1b4Smrg * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture. 20337117f1b4Smrg */ 20347117f1b4Smrgvoid GLAPIENTRY 20357117f1b4Smrg_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName, 20367117f1b4Smrg const GLclampf *priorities ) 20377117f1b4Smrg{ 20387117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 20397117f1b4Smrg GLint i; 2040af69d88dSmrg 2041af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2042af69d88dSmrg _mesa_debug(ctx, "glPrioritizeTextures %d\n", n); 2043af69d88dSmrg 20447117f1b4Smrg 20457117f1b4Smrg if (n < 0) { 20467117f1b4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" ); 20477117f1b4Smrg return; 20487117f1b4Smrg } 20497117f1b4Smrg 20507117f1b4Smrg if (!priorities) 20517117f1b4Smrg return; 20527117f1b4Smrg 20537ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT); 20547ec681f3Smrg 20557117f1b4Smrg for (i = 0; i < n; i++) { 20567117f1b4Smrg if (texName[i] > 0) { 20577117f1b4Smrg struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]); 20587117f1b4Smrg if (t) { 20597ec681f3Smrg t->Attrib.Priority = CLAMP( priorities[i], 0.0F, 1.0F ); 20607117f1b4Smrg } 20617117f1b4Smrg } 20627117f1b4Smrg } 20637117f1b4Smrg} 20647117f1b4Smrg 20653464ebd5Sriastradh 20663464ebd5Sriastradh 20677117f1b4Smrg/** 20687117f1b4Smrg * See if textures are loaded in texture memory. 206901e04c3fSmrg * 20707117f1b4Smrg * \param n number of textures to query. 20717117f1b4Smrg * \param texName array with the texture names. 20727117f1b4Smrg * \param residences array which will hold the residence status. 20737117f1b4Smrg * 207401e04c3fSmrg * \return GL_TRUE if all textures are resident and 207501e04c3fSmrg * residences is left unchanged, 207601e04c3fSmrg * 2077af69d88dSmrg * Note: we assume all textures are always resident 20787117f1b4Smrg */ 20797117f1b4SmrgGLboolean GLAPIENTRY 20807117f1b4Smrg_mesa_AreTexturesResident(GLsizei n, const GLuint *texName, 20817117f1b4Smrg GLboolean *residences) 20827117f1b4Smrg{ 20837117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 20847117f1b4Smrg GLboolean allResident = GL_TRUE; 2085af69d88dSmrg GLint i; 20867117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 20877117f1b4Smrg 2088af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2089af69d88dSmrg _mesa_debug(ctx, "glAreTexturesResident %d\n", n); 2090af69d88dSmrg 20917117f1b4Smrg if (n < 0) { 20927117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)"); 20937117f1b4Smrg return GL_FALSE; 20947117f1b4Smrg } 20957117f1b4Smrg 20967117f1b4Smrg if (!texName || !residences) 20977117f1b4Smrg return GL_FALSE; 20987117f1b4Smrg 2099af69d88dSmrg /* We only do error checking on the texture names */ 21007117f1b4Smrg for (i = 0; i < n; i++) { 21017117f1b4Smrg struct gl_texture_object *t; 21027117f1b4Smrg if (texName[i] == 0) { 21037117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); 21047117f1b4Smrg return GL_FALSE; 21057117f1b4Smrg } 21067117f1b4Smrg t = _mesa_lookup_texture(ctx, texName[i]); 21077117f1b4Smrg if (!t) { 21087117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); 21097117f1b4Smrg return GL_FALSE; 21107117f1b4Smrg } 21117117f1b4Smrg } 211201e04c3fSmrg 21137117f1b4Smrg return allResident; 21147117f1b4Smrg} 21157117f1b4Smrg 21163464ebd5Sriastradh 21177117f1b4Smrg/** 21187117f1b4Smrg * See if a name corresponds to a texture. 21197117f1b4Smrg * 21207117f1b4Smrg * \param texture texture name. 21217117f1b4Smrg * 21227117f1b4Smrg * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE 21237117f1b4Smrg * otherwise. 212401e04c3fSmrg * 21257117f1b4Smrg * \sa glIsTexture(). 21267117f1b4Smrg * 21277117f1b4Smrg * Calls _mesa_HashLookup(). 21287117f1b4Smrg */ 21297117f1b4SmrgGLboolean GLAPIENTRY 21307117f1b4Smrg_mesa_IsTexture( GLuint texture ) 21317117f1b4Smrg{ 21327117f1b4Smrg struct gl_texture_object *t; 21337117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 21347117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 21357117f1b4Smrg 2136af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2137af69d88dSmrg _mesa_debug(ctx, "glIsTexture %d\n", texture); 2138af69d88dSmrg 21397117f1b4Smrg if (!texture) 21407117f1b4Smrg return GL_FALSE; 21417117f1b4Smrg 21427117f1b4Smrg t = _mesa_lookup_texture(ctx, texture); 21437117f1b4Smrg 21447117f1b4Smrg /* IsTexture is true only after object has been bound once. */ 21457117f1b4Smrg return t && t->Target; 21467117f1b4Smrg} 21477117f1b4Smrg 2148c1f859d4Smrg 2149c1f859d4Smrg/** 21504a49301eSmrg * Simplest implementation of texture locking: grab the shared tex 21514a49301eSmrg * mutex. Examine the shared context state timestamp and if there has 21524a49301eSmrg * been a change, set the appropriate bits in ctx->NewState. 21537117f1b4Smrg * 2154c1f859d4Smrg * This is used to deal with synchronizing things when a texture object 2155c1f859d4Smrg * is used/modified by different contexts (or threads) which are sharing 2156c1f859d4Smrg * the texture. 2157c1f859d4Smrg * 2158c1f859d4Smrg * See also _mesa_lock/unlock_texture() in teximage.h 21597117f1b4Smrg */ 2160c1f859d4Smrgvoid 21613464ebd5Sriastradh_mesa_lock_context_textures( struct gl_context *ctx ) 21627117f1b4Smrg{ 21637ec681f3Smrg if (!ctx->TexturesLocked) 21647ec681f3Smrg mtx_lock(&ctx->Shared->TexMutex); 21657117f1b4Smrg 21667117f1b4Smrg if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) { 216701e04c3fSmrg ctx->NewState |= _NEW_TEXTURE_OBJECT; 21687ec681f3Smrg ctx->PopAttribState |= GL_TEXTURE_BIT; 21697117f1b4Smrg ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp; 21707117f1b4Smrg } 21717117f1b4Smrg} 21727117f1b4Smrg 21737117f1b4Smrg 2174c1f859d4Smrgvoid 21753464ebd5Sriastradh_mesa_unlock_context_textures( struct gl_context *ctx ) 21767117f1b4Smrg{ 21777117f1b4Smrg assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp); 21787ec681f3Smrg if (!ctx->TexturesLocked) 21797ec681f3Smrg mtx_unlock(&ctx->Shared->TexMutex); 2180af69d88dSmrg} 2181af69d88dSmrg 218201e04c3fSmrg 218301e04c3fSmrgvoid GLAPIENTRY 218401e04c3fSmrg_mesa_InvalidateTexSubImage_no_error(GLuint texture, GLint level, GLint xoffset, 218501e04c3fSmrg GLint yoffset, GLint zoffset, 218601e04c3fSmrg GLsizei width, GLsizei height, 218701e04c3fSmrg GLsizei depth) 218801e04c3fSmrg{ 218901e04c3fSmrg /* no-op */ 219001e04c3fSmrg} 219101e04c3fSmrg 219201e04c3fSmrg 2193af69d88dSmrgvoid GLAPIENTRY 2194af69d88dSmrg_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, 2195af69d88dSmrg GLint yoffset, GLint zoffset, GLsizei width, 2196af69d88dSmrg GLsizei height, GLsizei depth) 2197af69d88dSmrg{ 2198af69d88dSmrg struct gl_texture_object *t; 2199af69d88dSmrg struct gl_texture_image *image; 2200af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 2201af69d88dSmrg 2202af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2203af69d88dSmrg _mesa_debug(ctx, "glInvalidateTexSubImage %d\n", texture); 2204af69d88dSmrg 2205af69d88dSmrg t = invalidate_tex_image_error_check(ctx, texture, level, 2206af69d88dSmrg "glInvalidateTexSubImage"); 2207af69d88dSmrg 2208af69d88dSmrg /* The GL_ARB_invalidate_subdata spec says: 2209af69d88dSmrg * 2210af69d88dSmrg * "...the specified subregion must be between -<b> and <dim>+<b> where 2211af69d88dSmrg * <dim> is the size of the dimension of the texture image, and <b> is 2212af69d88dSmrg * the size of the border of that texture image, otherwise 2213af69d88dSmrg * INVALID_VALUE is generated (border is not applied to dimensions that 2214af69d88dSmrg * don't exist in a given texture target)." 2215af69d88dSmrg */ 2216af69d88dSmrg image = t->Image[0][level]; 2217af69d88dSmrg if (image) { 2218af69d88dSmrg int xBorder; 2219af69d88dSmrg int yBorder; 2220af69d88dSmrg int zBorder; 2221af69d88dSmrg int imageWidth; 2222af69d88dSmrg int imageHeight; 2223af69d88dSmrg int imageDepth; 2224af69d88dSmrg 2225af69d88dSmrg /* The GL_ARB_invalidate_subdata spec says: 2226af69d88dSmrg * 2227af69d88dSmrg * "For texture targets that don't have certain dimensions, this 2228af69d88dSmrg * command treats those dimensions as having a size of 1. For 2229af69d88dSmrg * example, to invalidate a portion of a two-dimensional texture, 2230af69d88dSmrg * the application would use <zoffset> equal to zero and <depth> 2231af69d88dSmrg * equal to one." 2232af69d88dSmrg */ 2233af69d88dSmrg switch (t->Target) { 2234af69d88dSmrg case GL_TEXTURE_BUFFER: 2235af69d88dSmrg xBorder = 0; 2236af69d88dSmrg yBorder = 0; 2237af69d88dSmrg zBorder = 0; 2238af69d88dSmrg imageWidth = 1; 2239af69d88dSmrg imageHeight = 1; 2240af69d88dSmrg imageDepth = 1; 2241af69d88dSmrg break; 2242af69d88dSmrg case GL_TEXTURE_1D: 2243af69d88dSmrg xBorder = image->Border; 2244af69d88dSmrg yBorder = 0; 2245af69d88dSmrg zBorder = 0; 2246af69d88dSmrg imageWidth = image->Width; 2247af69d88dSmrg imageHeight = 1; 2248af69d88dSmrg imageDepth = 1; 2249af69d88dSmrg break; 2250af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 2251af69d88dSmrg xBorder = image->Border; 2252af69d88dSmrg yBorder = 0; 2253af69d88dSmrg zBorder = 0; 2254af69d88dSmrg imageWidth = image->Width; 2255af69d88dSmrg imageHeight = image->Height; 2256af69d88dSmrg imageDepth = 1; 2257af69d88dSmrg break; 2258af69d88dSmrg case GL_TEXTURE_2D: 2259af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 2260af69d88dSmrg case GL_TEXTURE_RECTANGLE: 2261af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 2262af69d88dSmrg xBorder = image->Border; 2263af69d88dSmrg yBorder = image->Border; 2264af69d88dSmrg zBorder = 0; 2265af69d88dSmrg imageWidth = image->Width; 2266af69d88dSmrg imageHeight = image->Height; 2267af69d88dSmrg imageDepth = 1; 2268af69d88dSmrg break; 2269af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 2270af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 2271af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 2272af69d88dSmrg xBorder = image->Border; 2273af69d88dSmrg yBorder = image->Border; 2274af69d88dSmrg zBorder = 0; 2275af69d88dSmrg imageWidth = image->Width; 2276af69d88dSmrg imageHeight = image->Height; 2277af69d88dSmrg imageDepth = image->Depth; 2278af69d88dSmrg break; 2279af69d88dSmrg case GL_TEXTURE_3D: 2280af69d88dSmrg xBorder = image->Border; 2281af69d88dSmrg yBorder = image->Border; 2282af69d88dSmrg zBorder = image->Border; 2283af69d88dSmrg imageWidth = image->Width; 2284af69d88dSmrg imageHeight = image->Height; 2285af69d88dSmrg imageDepth = image->Depth; 2286af69d88dSmrg break; 2287af69d88dSmrg default: 2288af69d88dSmrg assert(!"Should not get here."); 2289af69d88dSmrg xBorder = 0; 2290af69d88dSmrg yBorder = 0; 2291af69d88dSmrg zBorder = 0; 2292af69d88dSmrg imageWidth = 0; 2293af69d88dSmrg imageHeight = 0; 2294af69d88dSmrg imageDepth = 0; 2295af69d88dSmrg break; 2296af69d88dSmrg } 2297af69d88dSmrg 2298af69d88dSmrg if (xoffset < -xBorder) { 2299af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)"); 2300af69d88dSmrg return; 2301af69d88dSmrg } 2302af69d88dSmrg 2303af69d88dSmrg if (xoffset + width > imageWidth + xBorder) { 2304af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2305af69d88dSmrg "glInvalidateSubTexImage(xoffset+width)"); 2306af69d88dSmrg return; 2307af69d88dSmrg } 2308af69d88dSmrg 2309af69d88dSmrg if (yoffset < -yBorder) { 2310af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)"); 2311af69d88dSmrg return; 2312af69d88dSmrg } 2313af69d88dSmrg 2314af69d88dSmrg if (yoffset + height > imageHeight + yBorder) { 2315af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2316af69d88dSmrg "glInvalidateSubTexImage(yoffset+height)"); 2317af69d88dSmrg return; 2318af69d88dSmrg } 2319af69d88dSmrg 2320af69d88dSmrg if (zoffset < -zBorder) { 2321af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2322af69d88dSmrg "glInvalidateSubTexImage(zoffset)"); 2323af69d88dSmrg return; 2324af69d88dSmrg } 2325af69d88dSmrg 2326af69d88dSmrg if (zoffset + depth > imageDepth + zBorder) { 2327af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2328af69d88dSmrg "glInvalidateSubTexImage(zoffset+depth)"); 2329af69d88dSmrg return; 2330af69d88dSmrg } 2331af69d88dSmrg } 2332af69d88dSmrg 2333af69d88dSmrg /* We don't actually do anything for this yet. Just return after 2334af69d88dSmrg * validating the parameters and generating the required errors. 2335af69d88dSmrg */ 2336af69d88dSmrg return; 2337af69d88dSmrg} 2338af69d88dSmrg 233901e04c3fSmrg 234001e04c3fSmrgvoid GLAPIENTRY 234101e04c3fSmrg_mesa_InvalidateTexImage_no_error(GLuint texture, GLint level) 234201e04c3fSmrg{ 234301e04c3fSmrg /* no-op */ 234401e04c3fSmrg} 234501e04c3fSmrg 234601e04c3fSmrg 2347af69d88dSmrgvoid GLAPIENTRY 2348af69d88dSmrg_mesa_InvalidateTexImage(GLuint texture, GLint level) 2349af69d88dSmrg{ 2350af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 2351af69d88dSmrg 2352af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2353af69d88dSmrg _mesa_debug(ctx, "glInvalidateTexImage(%d, %d)\n", texture, level); 2354af69d88dSmrg 2355af69d88dSmrg invalidate_tex_image_error_check(ctx, texture, level, 2356af69d88dSmrg "glInvalidateTexImage"); 2357af69d88dSmrg 2358af69d88dSmrg /* We don't actually do anything for this yet. Just return after 2359af69d88dSmrg * validating the parameters and generating the required errors. 2360af69d88dSmrg */ 2361af69d88dSmrg return; 23627117f1b4Smrg} 23637117f1b4Smrg 23647117f1b4Smrg/*@}*/ 2365