📄 texobj.c
字号:
/** * \file texobj.c * Texture object management. *//* * Mesa 3-D graphics library * Version: 7.1 * * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "colortab.h"#include "context.h"#include "enums.h"#include "fbobject.h"#include "hash.h"#include "imports.h"#include "macros.h"#include "teximage.h"#include "texstate.h"#include "texobj.h"#include "mtypes.h"/**********************************************************************//** \name Internal functions *//*@{*//** * Return the gl_texture_object for a given ID. */struct gl_texture_object *_mesa_lookup_texture(GLcontext *ctx, GLuint id){ return (struct gl_texture_object *) _mesa_HashLookup(ctx->Shared->TexObjects, id);}/** * Allocate and initialize a new texture object. But don't put it into the * texture object hash table. * * Called via ctx->Driver.NewTextureObject, unless overridden by a device * driver. * * \param shared the shared GL state structure to contain the texture object * \param name integer name for the texture object * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV. zero is ok for the sake * of GenTextures() * * \return pointer to new texture object. */struct gl_texture_object *_mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target ){ struct gl_texture_object *obj; (void) ctx; obj = MALLOC_STRUCT(gl_texture_object); _mesa_initialize_texture_object(obj, name, target); return obj;}/** * Initialize a new texture object to default values. * \param obj the texture object * \param name the texture name * \param target the texture target */void_mesa_initialize_texture_object( struct gl_texture_object *obj, GLuint name, GLenum target ){ ASSERT(target == 0 || target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D || target == GL_TEXTURE_CUBE_MAP_ARB || target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_1D_ARRAY_EXT || target == GL_TEXTURE_2D_ARRAY_EXT); _mesa_bzero(obj, sizeof(*obj)); /* init the non-zero fields */ _glthread_INIT_MUTEX(obj->Mutex); obj->RefCount = 1; obj->Name = name; obj->Target = target; obj->Priority = 1.0F; if (target == GL_TEXTURE_RECTANGLE_NV) { obj->WrapS = GL_CLAMP_TO_EDGE; obj->WrapT = GL_CLAMP_TO_EDGE; obj->WrapR = GL_CLAMP_TO_EDGE; obj->MinFilter = GL_LINEAR; } else { obj->WrapS = GL_REPEAT; obj->WrapT = GL_REPEAT; obj->WrapR = GL_REPEAT; obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR; } obj->MagFilter = GL_LINEAR; obj->MinLod = -1000.0; obj->MaxLod = 1000.0; obj->LodBias = 0.0; obj->BaseLevel = 0; obj->MaxLevel = 1000; obj->MaxAnisotropy = 1.0; obj->CompareFlag = GL_FALSE; /* SGIX_shadow */ obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX; /* SGIX_shadow */ obj->CompareMode = GL_NONE; /* ARB_shadow */ obj->CompareFunc = GL_LEQUAL; /* ARB_shadow */ obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */ obj->ShadowAmbient = 0.0F; /* ARB/SGIX_shadow_ambient */}/** * Some texture initialization can't be finished until we know which * target it's getting bound to (GL_TEXTURE_1D/2D/etc). */static voidfinish_texture_init(GLcontext *ctx, GLenum target, struct gl_texture_object *obj){ assert(obj->Target == 0); if (target == GL_TEXTURE_RECTANGLE_NV) { /* have to init wrap and filter state here - kind of klunky */ obj->WrapS = GL_CLAMP_TO_EDGE; obj->WrapT = GL_CLAMP_TO_EDGE; obj->WrapR = GL_CLAMP_TO_EDGE; obj->MinFilter = GL_LINEAR; if (ctx->Driver.TexParameter) { static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE}; static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR}; ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap); ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap); ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap); ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter); } }}/** * Deallocate a texture object struct. It should have already been * removed from the texture object pool. * Called via ctx->Driver.DeleteTexture() if not overriden by a driver. * * \param shared the shared GL state to which the object belongs. * \param texOjb the texture object to delete. */void_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj ){ GLuint i, face; (void) ctx; /* Set Target to an invalid value. With some assertions elsewhere * we can try to detect possible use of deleted textures. */ texObj->Target = 0x99; _mesa_free_colortable_data(&texObj->Palette); /* free the texture images */ for (face = 0; face < 6; face++) { for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { if (texObj->Image[face][i]) { _mesa_delete_texture_image( ctx, texObj->Image[face][i] ); } } } /* destroy the mutex -- it may have allocated memory (eg on bsd) */ _glthread_DESTROY_MUTEX(texObj->Mutex); /* free this object */ _mesa_free(texObj);}/** * Copy texture object state from one texture object to another. * Use for glPush/PopAttrib. * * \param dest destination texture object. * \param src source texture object. */void_mesa_copy_texture_object( struct gl_texture_object *dest, const struct gl_texture_object *src ){ dest->Target = src->Target; dest->Name = src->Name; dest->Priority = src->Priority; dest->BorderColor[0] = src->BorderColor[0]; dest->BorderColor[1] = src->BorderColor[1]; dest->BorderColor[2] = src->BorderColor[2]; dest->BorderColor[3] = src->BorderColor[3]; dest->WrapS = src->WrapS; dest->WrapT = src->WrapT; dest->WrapR = src->WrapR; dest->MinFilter = src->MinFilter; dest->MagFilter = src->MagFilter; dest->MinLod = src->MinLod; dest->MaxLod = src->MaxLod; dest->LodBias = src->LodBias; dest->BaseLevel = src->BaseLevel; dest->MaxLevel = src->MaxLevel; dest->MaxAnisotropy = src->MaxAnisotropy; dest->CompareFlag = src->CompareFlag; dest->CompareOperator = src->CompareOperator; dest->ShadowAmbient = src->ShadowAmbient; dest->CompareMode = src->CompareMode; dest->CompareFunc = src->CompareFunc; dest->DepthMode = src->DepthMode; dest->_MaxLevel = src->_MaxLevel; dest->_MaxLambda = src->_MaxLambda; dest->GenerateMipmap = src->GenerateMipmap; dest->Palette = src->Palette; dest->_Complete = src->_Complete;}/** * Check if the given texture object is valid by examining its Target field. * For debugging only. */static GLbooleanvalid_texture_object(const struct gl_texture_object *tex){ switch (tex->Target) { case 0: case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP_ARB: case GL_TEXTURE_RECTANGLE_NV: case GL_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: return GL_TRUE; case 0x99: _mesa_problem(NULL, "invalid reference to a deleted texture object"); return GL_FALSE; default: _mesa_problem(NULL, "invalid texture object Target value"); return GL_FALSE; }}/** * Reference (or unreference) a texture object. * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero). * If 'tex' is non-null, increment its refcount. */void_mesa_reference_texobj(struct gl_texture_object **ptr, struct gl_texture_object *tex){ assert(ptr); if (*ptr == tex) { /* no change */ return; } if (*ptr) { /* Unreference the old texture */ GLboolean deleteFlag = GL_FALSE; struct gl_texture_object *oldTex = *ptr; assert(valid_texture_object(oldTex)); _glthread_LOCK_MUTEX(oldTex->Mutex); ASSERT(oldTex->RefCount > 0); oldTex->RefCount--; deleteFlag = (oldTex->RefCount == 0); _glthread_UNLOCK_MUTEX(oldTex->Mutex); if (deleteFlag) { GET_CURRENT_CONTEXT(ctx); if (ctx) ctx->Driver.DeleteTexture(ctx, oldTex); else _mesa_problem(NULL, "Unable to delete texture, no context"); } *ptr = NULL; } assert(!*ptr); if (tex) { /* reference new texture */ assert(valid_texture_object(tex)); _glthread_LOCK_MUTEX(tex->Mutex); if (tex->RefCount == 0) { /* this texture's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ _mesa_problem(NULL, "referencing deleted texture object"); *ptr = NULL; } else { tex->RefCount++; *ptr = tex; } _glthread_UNLOCK_MUTEX(tex->Mutex); }}/** * Report why a texture object is incomplete. * * \param t texture object. * \param why string describing why it's incomplete. * * \note For debug purposes only. */#if 0static voidincomplete(const struct gl_texture_object *t, const char *why){ _mesa_printf("Texture Obj %d incomplete because: %s\n", t->Name, why);}#else#define incomplete(t, why)#endif/** * Examine a texture object to determine if it is complete. * * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE * accordingly. * * \param ctx GL context. * \param t texture object. * * According to the texture target, verifies that each of the mipmaps is * present and has the expected size. */void_mesa_test_texobj_completeness( const GLcontext *ctx, struct gl_texture_object *t ){ const GLint baseLevel = t->BaseLevel; GLint maxLog2 = 0, maxLevels = 0; t->_Complete = GL_TRUE; /* be optimistic */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -