/* ** Copyright 1991,1992, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. ** */ #include "precomp.h" #pragma hdrstop #include void __glTexPriListRealize(__GLcontext *gc) { __GLtextureObject *high, *low; GLboolean tryUnload = GL_TRUE; MCDHANDLE loadKey; __GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray); // Attempt to load as many of the highest priority textures as // possible. If a lower priority texture is resident and a // higher priority texture is unable to load, kick it out // and try again high = gc->texture.shared->priorityListHighest; low = gc->texture.shared->priorityListLowest; while (high != NULL) { // We only want to load textures that have image data // Consider - Should check all mipmap levels? if (high->loadKey == 0 && high->texture.map.level[0].buffer != NULL) { for (;;) { // If high == low then there are no longer any // lower-priority textures to consider for unloading if (high == low) { tryUnload = GL_FALSE; } loadKey = __glGenLoadTexture(gc, &high->texture.map, 0); if (loadKey != 0) { high->resident = GL_TRUE; high->loadKey = loadKey; break; } if (tryUnload) { while (low->loadKey == 0 && low != high) { low = low->higherPriority; } if (low->loadKey != 0) { __glGenFreeTexture(gc, &low->texture.map, low->loadKey); low->loadKey = 0; low->resident = GL_FALSE; } } else { break; } } } high = high->lowerPriority; } } void __glTexPriListAddToList(__GLcontext *gc, __GLtextureObject *texobj) { __GLtextureObject *texobjLower; __GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray); // Walk the priority list to find a lower priority texture object texobjLower = gc->texture.shared->priorityListHighest; while (texobjLower != NULL && texobjLower->texture.map.texobjs.priority > texobj->texture.map.texobjs.priority) { texobjLower = texobjLower->lowerPriority; } if (texobjLower == NULL) { // Place at end of list if (gc->texture.shared->priorityListLowest != NULL) { gc->texture.shared->priorityListLowest->lowerPriority = texobj; } else { gc->texture.shared->priorityListHighest = texobj; } texobj->higherPriority = gc->texture.shared->priorityListLowest; gc->texture.shared->priorityListLowest = texobj; } else { if (texobjLower->higherPriority != NULL) { texobjLower->higherPriority->lowerPriority = texobj; } else { gc->texture.shared->priorityListHighest = texobj; } texobj->higherPriority = texobjLower->higherPriority; texobjLower->higherPriority = texobj; } texobj->lowerPriority = texobjLower; } void __glTexPriListAdd(__GLcontext *gc, __GLtextureObject *texobj, GLboolean realize) { __glNamesLockArray(gc, gc->texture.shared->namesArray); __glTexPriListAddToList(gc, texobj); if (realize) { __glTexPriListRealize(gc); } __glNamesUnlockArray(gc, gc->texture.shared->namesArray); } void __glTexPriListRemoveFromList(__GLcontext *gc, __GLtextureObject *texobj) { __GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray); #if DBG { __GLtextureObject *t; for (t = gc->texture.shared->priorityListHighest; t != NULL; t = t->lowerPriority) { if (t == texobj) { break; } } ASSERTOPENGL(t != NULL, "Removing an unlisted texobj"); } #endif if (texobj->higherPriority != NULL) { texobj->higherPriority->lowerPriority = texobj->lowerPriority; } else { gc->texture.shared->priorityListHighest = texobj->lowerPriority; } if (texobj->lowerPriority != NULL) { texobj->lowerPriority->higherPriority = texobj->higherPriority; } else { gc->texture.shared->priorityListLowest = texobj->higherPriority; } } void __glTexPriListRemove(__GLcontext *gc, __GLtextureObject *texobj, GLboolean realize) { __glNamesLockArray(gc, gc->texture.shared->namesArray); __glTexPriListRemoveFromList(gc, texobj); __glGenFreeTexture(gc, &texobj->texture.map, texobj->loadKey); texobj->loadKey = 0; texobj->resident = GL_FALSE; if (realize) { __glTexPriListRealize(gc); } __glNamesUnlockArray(gc, gc->texture.shared->namesArray); } void __glTexPriListChangePriority(__GLcontext *gc, __GLtextureObject *texobj, GLboolean realize) { __glNamesLockArray(gc, gc->texture.shared->namesArray); __glTexPriListRemoveFromList(gc, texobj); __glTexPriListAddToList(gc, texobj); // If we're re-realizing, don't bother calling the MCD texture-priority // function: if (realize) { __glTexPriListRealize(gc); } else if (((__GLGENcontext *)gc)->pMcdState && texobj->loadKey) { GenMcdUpdateTexturePriority((__GLGENcontext *)gc, &texobj->texture.map, texobj->loadKey); } __glNamesUnlockArray(gc, gc->texture.shared->namesArray); } void __glTexPriListLoadSubImage(__GLcontext *gc, GLenum target, GLint lod, GLint xoffset, GLint yoffset, GLsizei w, GLsizei h) { __GLtextureObject *pto; // Always mark things as resident: pto = __glLookUpTextureObject(gc, target); pto->resident = GL_TRUE; __glGenUpdateTexture(gc, &pto->texture.map, pto->loadKey); // For MCD, send down the full subimage command: if (((__GLGENcontext *)gc)->pMcdState && pto->loadKey) { GenMcdUpdateSubTexture((__GLGENcontext *)gc, &pto->texture.map, pto->loadKey, lod, xoffset, yoffset, w, h); } } void __glTexPriListLoadImage(__GLcontext *gc, GLenum target) { __GLtextureObject *pto; // If we're unaccelerated then always mark things as resident pto = __glLookUpTextureObject(gc, target); pto->resident = GL_TRUE; __glGenUpdateTexture(gc, &pto->texture.map, pto->loadKey); // For simplicity, we will assume that the texture size or format // has changed, so delete the texture and re-realize the list. // // !!! If this becomes a performance issue, we *could* be smart about // !!! detecting the cases where the texture size and format remains the // !!! same. However, modifying a texture should really be done through // !!! SubImage calls. if (((__GLGENcontext *)gc)->pMcdState) { if (pto->loadKey) { GenMcdDeleteTexture((__GLGENcontext *)gc, pto->loadKey); pto->loadKey = 0; } __glNamesLockArray(gc, gc->texture.shared->namesArray); __glTexPriListRealize(gc); __glNamesUnlockArray(gc, gc->texture.shared->namesArray); } } void __glTexPriListUnloadAll(__GLcontext *gc) { __GLtextureObject *texobj; __GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray); texobj = gc->texture.shared->priorityListHighest; while (texobj != NULL) { __glGenFreeTexture(gc, &texobj->texture.map, texobj->loadKey); texobj->loadKey = 0; texobj->resident = GL_FALSE; texobj = texobj->lowerPriority; } }