This is texobj.c in view mode; [Download] [Up]
/* $Id: texobj.c,v 1.11 1997/05/28 03:26:49 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 2.3 * Copyright (C) 1995-1997 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Log: texobj.c,v $ * Revision 1.11 1997/05/28 03:26:49 brianp * added precompiled header (PCH) support * * Revision 1.10 1997/05/17 03:41:49 brianp * added code to update ctx->Texture.Current in gl_BindTexture() * * Revision 1.9 1997/05/03 00:52:52 brianp * removed a few unused variables * * Revision 1.8 1997/05/01 02:08:12 brianp * new implementation of gl_BindTexture() * * Revision 1.7 1997/04/28 23:38:45 brianp * added gl_test_texture_object_completeness() * * Revision 1.6 1997/04/14 02:03:05 brianp * added MinMagThresh to texture object * * Revision 1.5 1997/02/09 18:52:15 brianp * added GL_EXT_texture3D support * * Revision 1.4 1997/01/16 03:35:34 brianp * added calls to device driver DeleteTexture() and BindTexture() functions * * Revision 1.3 1997/01/09 19:49:47 brianp * added a check to switch rasterizers if needed in glBindTexture() * * Revision 1.2 1996/09/27 17:09:42 brianp * removed a redundant return statement * * Revision 1.1 1996/09/13 01:38:16 brianp * Initial revision * */ #ifdef PCH #include "all.h" #else #include <assert.h> #include <stdlib.h> #include "context.h" #include "macros.h" #include "teximage.h" #include "texobj.h" #include "types.h" #endif /* * Allocate a new texture object structure. The name and dimensionality are * set to zero here and must be initialized by the caller. */ struct gl_texture_object *gl_alloc_texture_object( void ) { struct gl_texture_object *obj; obj = (struct gl_texture_object *) calloc(1,sizeof(struct gl_texture_object)); if (obj) { /* init the non-zero fields */ obj->WrapS = GL_REPEAT; obj->WrapT = GL_REPEAT; obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR; obj->MagFilter = GL_LINEAR; obj->MinMagThresh = 0.0F; } return obj; } /* * Append a gl_texture_object struct to a list of texture objects. */ static void append_texture_object( struct gl_texture_object *list, struct gl_texture_object *obj ) { struct gl_texture_object *t; t = list; assert(t); /* always have proxy textures in the list */ while (t->Next) { t = t->Next; } t->Next = obj; } /* * Deallocate a texture object struct and all children structures * and image data. */ void gl_free_texture_object( struct gl_texture_object *t ) { GLuint i; for (i=0;i<MAX_TEXTURE_LEVELS;i++) { if (t->Image[i]) { gl_free_texture_image( t->Image[i] ); } } free( t ); } /* * Given a texture object name, return a pointer to the texture object. */ static struct gl_texture_object * find_texture_object( GLcontext *ctx, GLuint name ) { struct gl_texture_object *t; assert( name>0 ); t = ctx->Shared->TexObjectList; while (t) { if (t->Name == name) { return t; } t = t->Next; } return NULL; } /* * Examine a texture object to determine if it is complete or not. * The t->Complete flag will be set to GL_TRUE or GL_FALSE accordingly. */ void gl_test_texture_object_completeness( struct gl_texture_object *t ) { t->Complete = GL_TRUE; /* be optimistic */ /* Always need level zero image */ if (!t->Image[0] || !t->Image[0]->Data) { t->Complete = GL_FALSE; return; } if (t->MinFilter!=GL_NEAREST && t->MinFilter!=GL_LINEAR) { /* * Mipmapping: determine if we have a complete set of mipmaps */ int i; /* Test dimension-independent attributes */ for (i=1; i<MAX_TEXTURE_LEVELS; i++) { if (t->Image[i]) { if (!t->Image[i]->Data) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Format != t->Image[0]->Format) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Border != t->Image[0]->Border) { t->Complete = GL_FALSE; return; } } } /* Test things which depend on number of texture image dimensions */ if (t->Dimensions==1) { /* Test 1-D mipmaps */ GLuint width = t->Image[0]->Width2; for (i=1; i<MAX_TEXTURE_LEVELS; i++) { if (width>1) { width /= 2; } if (!t->Image[i]) { t->Complete = GL_FALSE; return; } if (!t->Image[i]->Data) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Format != t->Image[0]->Format) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Border != t->Image[0]->Border) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Width2 != width ) { t->Complete = GL_FALSE; return; } if (width==1) { return; /* found smallest needed mipmap, all done! */ } } } else if (t->Dimensions==2) { /* Test 2-D mipmaps */ GLuint width = t->Image[0]->Width2; GLuint height = t->Image[0]->Height2; for (i=1; i<MAX_TEXTURE_LEVELS; i++) { if (width>1) { width /= 2; } if (height>1) { height /= 2; } if (!t->Image[i]) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Width2 != width) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Height2 != height) { t->Complete = GL_FALSE; return; } if (width==1 && height==1) { return; /* found smallest needed mipmap, all done! */ } } } else if (t->Dimensions==3) { /* Test 3-D mipmaps */ GLuint width = t->Image[0]->Width2; GLuint height = t->Image[0]->Height2; GLuint depth = t->Image[0]->Depth2; for (i=1; i<MAX_TEXTURE_LEVELS; i++) { if (width>1) { width /= 2; } if (height>1) { height /= 2; } if (depth>1) { depth /= 2; } if (!t->Image[i]) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Width2 != width) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Height2 != height) { t->Complete = GL_FALSE; return; } if (t->Image[i]->Depth2 != depth) { t->Complete = GL_FALSE; return; } if (width==1 && height==1 && depth==1) { return; /* found smallest needed mipmap, all done! */ } } } else { /* Dimensions = ??? */ gl_problem(NULL, "Bug in gl_test_texture_object_completeness\n"); } } } /* * Execute glGenTextures */ void gl_GenTextures( GLcontext *ctx, GLsizei n, GLuint *texName ) { GLuint i; if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glGenTextures" ); return; } if (n<0) { gl_error( ctx, GL_INVALID_VALUE, "glGenTextures" ); return; } for (i=0;i<n;i++) { texName[i] = ctx->Shared->NextFreeTextureName++; } } /* * Execute glDeleteTextures */ void gl_DeleteTextures( GLcontext *ctx, GLsizei n, const GLuint *texName) { GLuint i; if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" ); return; } for (i=0;i<n;i++) { struct gl_texture_object *t, *tprev, *tcurr; if (texName[i]>0) { t = find_texture_object( ctx, texName[i] ); if (t) { if (ctx->Texture.Current1D==t) { /* revert to default 1-D texture */ ctx->Texture.Current1D = ctx->Shared->TexObjectList; t->RefCount--; assert( t->RefCount >= 0 ); } else if (ctx->Texture.Current2D==t) { /* revert to default 2-D texture */ ctx->Texture.Current2D = ctx->Shared->TexObjectList->Next; t->RefCount--; assert( t->RefCount >= 0 ); } else if (ctx->Texture.Current3D==t) { /* revert to default 3-D texture */ ctx->Texture.Current3D = ctx->Shared->TexObjectList->Next; t->RefCount--; assert( t->RefCount >= 0 ); } if (t->RefCount==0) { /* remove texture object t from the linked list */ tprev = NULL; tcurr = ctx->Shared->TexObjectList; while (tcurr) { if (tcurr==t) { assert( tprev ); tprev->Next = t->Next; gl_free_texture_object( t ); break; } tprev = tcurr; tcurr = tcurr->Next; } } /* tell device driver to delete texture */ if (ctx->Driver.DeleteTexture) { (*ctx->Driver.DeleteTexture)( ctx, texName[i] ); } } } } } /* * Execute glBindTextures */ void gl_BindTexture( GLcontext *ctx, GLenum target, GLuint texName ) { struct gl_texture_object *oldTexObj; struct gl_texture_object *newTexObj; struct gl_texture_object **targetPointer; GLuint targetDimensions; if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" ); return; } switch (target) { case GL_TEXTURE_1D: oldTexObj = ctx->Texture.Current1D; targetPointer = &ctx->Texture.Current1D; targetDimensions = 1; break; case GL_TEXTURE_2D: oldTexObj = ctx->Texture.Current2D; targetPointer = &ctx->Texture.Current2D; targetDimensions = 2; break; case GL_TEXTURE_3D_EXT: oldTexObj = ctx->Texture.Current3D; targetPointer = &ctx->Texture.Current3D; targetDimensions = 3; break; default: gl_error( ctx, GL_INVALID_ENUM, "glBindTexture" ); return; } if (texName==0) { /* use default n-D texture */ switch (target) { case GL_TEXTURE_1D: /* default 1-D texture is first in list */ *targetPointer = ctx->Shared->TexObjectList; break; case GL_TEXTURE_2D: /* default 2-D texture is second in list */ *targetPointer = ctx->Shared->TexObjectList->Next; break; case GL_TEXTURE_3D_EXT: /* default 3-D texture is third in list */ *targetPointer = ctx->Shared->TexObjectList->Next->Next; break; default: gl_problem(ctx, "Bad target in gl_BindTexture"); return; } } else { newTexObj = find_texture_object( ctx, texName ); if (newTexObj) { if (newTexObj->Dimensions==targetDimensions) { /* success! */ *targetPointer = newTexObj; } else { /* wrong dimensionality */ gl_error( ctx, GL_INVALID_OPERATION, "glBindTextureEXT" ); return; } } else { /* create new texture object */ newTexObj = gl_alloc_texture_object(); append_texture_object( ctx->Shared->TexObjectList, newTexObj ); newTexObj->Name = texName; newTexObj->Dimensions = targetDimensions; *targetPointer = newTexObj; } } /* Tidy up reference counting */ if (*targetPointer != oldTexObj && oldTexObj->Name>0) { /* decrement reference count of the prev texture object */ oldTexObj->RefCount--; assert( oldTexObj->RefCount >= 0 ); } if (newTexObj->Name>0) { newTexObj->RefCount++; } /* Check if we may have to use a new triangle rasterizer */ if ( oldTexObj->WrapS != newTexObj->WrapS || oldTexObj->WrapT != newTexObj->WrapT || oldTexObj->WrapR != newTexObj->WrapR || oldTexObj->MinFilter != newTexObj->MinFilter || oldTexObj->MagFilter != newTexObj->MagFilter) { ctx->NewState |= NEW_RASTER_OPS; } /* If we've changed the "Current" texture object (1,2, or 3) update the * ctx->Texture.Current pointer to point to the new texture object. */ if (oldTexObj==ctx->Texture.Current) { ctx->Texture.Current = newTexObj; } /* The current n-D texture object can never be NULL! */ assert(*targetPointer); /* Pass BindTexture to device driver */ if (ctx->Driver.BindTexture) { (*ctx->Driver.BindTexture)( ctx, target, texName ); } } /* * Execute glPrioritizeTextures */ void gl_PrioritizeTextures( GLcontext *ctx, GLsizei n, const GLuint *texName, const GLclampf *priorities ) { GLuint i; if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" ); return; } if (n<0) { gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)" ); return; } for (i=0;i<n;i++) { struct gl_texture_object *t; if (texName[i]>0) { t = find_texture_object( ctx, texName[i] ); if (t) { t->Priority = CLAMP( priorities[i], 0.0F, 1.0F ); } } } } /* * Execute glAreTexturesResident */ GLboolean gl_AreTexturesResident( GLcontext *ctx, GLsizei n, const GLuint *texName, GLboolean *residences ) { GLboolean resident = GL_TRUE; GLuint i; if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" ); return GL_FALSE; } if (n<0) { gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)" ); return GL_FALSE; } for (i=0;i<n;i++) { struct gl_texture_object *t; if (texName[i]==0) { gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" ); return GL_FALSE; } t = find_texture_object( ctx, texName[i] ); if (t) { /* we consider all valid texture objects to be resident */ residences[i] = GL_TRUE; } else { gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" ); return GL_FALSE; } } return resident; } /* * Execute glIsTexture */ GLboolean gl_IsTexture( GLcontext *ctx, GLuint texture ) { if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glIsTextures" ); return GL_FALSE; } if (texture>0 && find_texture_object(ctx,texture)) { return GL_TRUE; } else { return GL_FALSE; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.