288 lines
8.6 KiB
C
288 lines
8.6 KiB
C
/*
|
|
** 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 <namesint.h>
|
|
|
|
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;
|
|
}
|
|
}
|