📄 gtexmanager.cc
字号:
{
GBitmap * bmp2 = new GBitmap(w,h,false,GBitmap::RGBA);
U8 * rgbBits = bmp->getWritableBits();
U8 * alphaBits = bmpAlpha->getWritableBits();
U8 * bmpBits = bmp2->getWritableBits();
for (S32 wi=0; wi<w; wi++)
{
for (S32 hi=0; hi<h; hi++)
{
bmpBits[wi*4 + hi*4*w + 0] = rgbBits[wi*3 + hi*3*w + 0];
bmpBits[wi*4 + hi*4*w + 1] = rgbBits[wi*3 + hi*3*w + 1];
bmpBits[wi*4 + hi*4*w + 2] = rgbBits[wi*3 + hi*3*w + 2];
bmpBits[wi*4 + hi*4*w + 3] = alphaBits[wi + hi*w];
}
}
delete bmpAlpha;
delete bmp;
bmp = bmp2;
}
}
}
// If unable to load texture in current directory
// look in the parent directory. But never look in the root.
fileNameBuffer[len] = 0;
if (!bmp && recurse)
{
char *name = dStrrchr(fileNameBuffer, '/');
if (name)
{
*name++ = 0;
char *parent = dStrrchr(fileNameBuffer, '/');
if (parent)
{
parent[1] = 0;
dStrcat(fileNameBuffer, name);
return loadBitmapInstance(fileNameBuffer);
}
}
}
return bmp;
}
//--------------------------------------
TextureObject *TextureManager::loadTexture(const char* textureName, TextureHandleType type, bool clampToEdge, bool checkOnly /* = false */)
{
// Catch if we're trying to load a blank texture...
if(!textureName || dStrlen(textureName) == 0)
return NULL;
textureName = StringTable->insert(textureName);
TextureObject *ret = TextureDictionary::find(textureName, type, clampToEdge);
GBitmap *bmp = NULL;
if(!ret)
{
// Ok, no hit - is it in the current dir? If so then let's grab it
// and use it.
bmp = loadBitmapInstance(textureName, false);
if(bmp)
return registerTexture(textureName, bmp, type, clampToEdge);
// Otherwise...
// We want to check for previously loaded textures with the same
// name in higher directories. loadBitmapInstance does this too
// but we want to reuse the actual texture object, if possible,
// not just load things many times into video memory!
char fileNameBuffer[512];
dStrcpy(fileNameBuffer, textureName);
// If unable to load texture in current directory
// look in the parent directory. But never look in the root.
char *name = dStrrchr(fileNameBuffer, '/');
if (name)
{
*name++ = 0;
char *parent = dStrrchr(fileNameBuffer, '/');
if (parent)
{
parent[1] = 0;
dStrcat(fileNameBuffer, name);
ret = loadTexture(fileNameBuffer, type, clampToEdge, true);
}
}
}
if(ret)
return ret;
// If we're just checking, fail out so we eventually get around to
// loading a real bitmap.
if(checkOnly)
return NULL;
// Ok, no success so let's try actually loading a texture.
bmp = loadBitmapInstance(textureName);
if(!bmp)
{
Con::warnf("Could not locate texture: %s", textureName);
return NULL;
}
return registerTexture(textureName, bmp, type, clampToEdge);
}
//--------------------------------------
void TextureHandle::setFilterNearest()
{
if (object)
{
object->filterNearest = true;
if(object->texGLName != 0)
{
glBindTexture(GL_TEXTURE_2D, object->texGLName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
}
}
void TextureHandle::setClamp(const bool c)
{
if (object)
{
object->clamp = c;
if (object->texGLName != 0)
{
glBindTexture(GL_TEXTURE_2D, object->texGLName);
GLenum clamp;
if (c)
clamp = dglDoesSupportEdgeClamp() ? GL_CLAMP_TO_EDGE : GL_CLAMP;
else
clamp = GL_REPEAT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
}
if (object->smallTexGLName != 0)
{
glBindTexture(GL_TEXTURE_2D, object->smallTexGLName);
GLenum clamp;
if (c)
clamp = dglDoesSupportEdgeClamp() ? GL_CLAMP_TO_EDGE : GL_CLAMP;
else
clamp = GL_REPEAT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
}
}
}
#define MAX_THOBJECT 1024
static TextureObject *thobject[MAX_THOBJECT];
static int htracked = 0;
void TextureHandle::lock()
{
AssertFatal(TextureManager::isActive(), "TextureHandle::lock - TextureManager must be active to lock a texture.");
if(object)
{
#if defined(TORQUE_DEBUG)
if (object->refCount>10000 || object->refCount<0) // some reasonable numbers.
{
for (int i=0; i<htracked; i++)
{
if (thobject[i]==object)
return;
}
Con::warnf(ConsoleLogEntry::Assert, "Texture refcount out of range: tex<%p> cnt<%d>", object, object->refCount);
if (htracked<MAX_THOBJECT)
{
thobject[htracked] = object;
htracked++;
}
}
else
#endif
object->refCount++;
}
}
void TextureHandle::unlock()
{
// Do nothing if the manager isn't active.
if(!TextureManager::isActive())
return;
if(object)
{
object->refCount--;
if (object->holding == false)
{
if(!object->refCount)
TextureManager::freeTexture(object);
}
else
{
#if defined(TORQUE_DEBUG)
// dc - try outputting this error to console instead of assert box, and keep safe to continue.
if (object->refCount<0)
{
Con::warnf(ConsoleLogEntry::Assert, "Texture holding out of balance: %d (0x%x)",
object->refCount, object->refCount);
object->refCount++; // put back for safety, in case we did something we shouldn't have.
}
#else
AssertISV(object->refCount >= 0, avar("Texture holding out of balance: %d (0x%x)",
object->refCount, object->refCount));
#endif
}
object = NULL;
}
}
void TextureHandle::refresh()
{
TextureManager::refresh(object);
}
void TextureHandle::refresh(GBitmap* bmp)
{
AssertFatal(object->type == TerrainTexture, "Error, only terrain textures may be refreshed in this manner!");
TextureManager::refresh(object, bmp);
}
#ifdef TORQUE_GATHER_METRICS
F32 TextureManager::getResidentFraction()
{
U32 resident = 0;
U32 total = 0;
Vector<GLuint> names;
TextureObject* pProbe = TextureDictionary::smTOList;
while (pProbe != NULL)
{
if (pProbe->texGLName != 0)
{
total++;
names.push_back(pProbe->texGLName);
}
pProbe = pProbe->next;
}
if (total == 0)
return 1.0f;
Vector<GLboolean> isResident;
isResident.setSize(names.size());
glAreTexturesResident(names.size(), names.address(), isResident.address());
for (U32 i = 0; i < names.size(); i++)
if (isResident[i] == GL_TRUE)
resident++;
return (F32(resident) / F32(total));
}
#endif
//-------------------------------------------------------------------------
ChunkedTextureObject *gChunkedTextureList = NULL;
ChunkedTextureObject* ChunkedTextureManager::loadTexture(const char *textureName)
{
if(!textureName)
return NULL;
StringTableEntry tName = StringTable->insert(textureName);
for(ChunkedTextureObject *walk = gChunkedTextureList; walk; walk = walk->next)
if(walk->texFileName == tName)
return walk;
GBitmap *bmp = TextureManager::loadBitmapInstance(textureName);
if(!bmp)
return NULL;
return registerTexture(textureName, bmp, false);
}
ChunkedTextureObject* ChunkedTextureManager::registerTexture(const char *textureName, GBitmap *data, bool keep)
{
ChunkedTextureObject *ret = NULL;
StringTableEntry tName = NULL;
if(textureName)
{
tName = StringTable->insert(textureName);
for(ChunkedTextureObject *walk = gChunkedTextureList; walk; walk = walk->next)
{
if(walk->texFileName == tName)
{
ret = walk;
break;
}
}
}
if(ret && ret->bitmap)
{
delete ret->bitmap;
ret->bitmap = data;
}
else
{
ret = new ChunkedTextureObject;
ret->bitmap = data;
ret->texFileName = tName;
ret->next = gChunkedTextureList;
gChunkedTextureList = ret;
ret->texWidthCount = (data->getWidth() + 255) >> 8;
ret->texHeightCount = (data->getHeight() + 255) >> 8;
ret->width = data->getWidth();
ret->height = data->getHeight();
ret->textureHandles = NULL;
ret->refCount = 0;
}
refresh(ret);
if(!keep)
{
delete ret->bitmap;
ret->bitmap = NULL;
}
return ret;
}
void ChunkedTextureManager::freeTexture(ChunkedTextureObject *to)
{
// remove it from the linked list
for(ChunkedTextureObject **walk = &gChunkedTextureList; *walk; walk = &((*walk)->next))
{
if(*walk == to)
{
*walk = to->next;
delete[] to->textureHandles;
delete to->bitmap;
return;
}
}
}
void ChunkedTextureManager::refresh(ChunkedTextureObject *to)
{
if(!to->bitmap)
return;
if(to->textureHandles)
{
delete[] to->textureHandles;
to->textureHandles = NULL;
}
to->textureHandles = new TextureHandle[to->texWidthCount * to->texHeightCount];
for(U32 j = 0; j < to->texHeightCount; j++)
{
U32 y = j * 256;
U32 height = getMin(to->bitmap->getHeight() - y, U32(256));
for(U32 i = 0; i < to->texWidthCount; i++)
{
U32 index = j * to->texWidthCount + i;
U32 x = i * 256;
U32 width = getMin(to->bitmap->getWidth() - x, U32(256));
GBitmap *tempBitmap = new GBitmap(width, height, false, to->bitmap->getFormat());
for(U32 lp = 0; lp < height; lp++)
{
const U8 *src = to->bitmap->getAddress(x, y + lp);
U8 *dest = tempBitmap->getAddress(0, lp);
dMemcpy(dest, src, width * to->bitmap->bytesPerPixel);
}
to->textureHandles[index] = TextureHandle(NULL, tempBitmap, BitmapTexture, true);
}
}
}
void ChunkedTextureManager::makeZombie()
{
for(ChunkedTextureObject *walk = gChunkedTextureList; walk; walk = walk->next)
{
delete[] walk->textureHandles;
walk->textureHandles = NULL;
}
}
void ChunkedTextureManager::resurrect()
{
for(ChunkedTextureObject *walk = gChunkedTextureList; walk; walk = walk->next)
{
GBitmap *bmp = walk->bitmap;
if(!bmp)
walk->bitmap = TextureManager::loadBitmapInstance(walk->texFileName);
refresh(walk);
if(!bmp)
{
delete walk->bitmap;
walk->bitmap = NULL;
}
}
}
TextureHandle ChunkedTextureHandle::getSubTexture(U32 x, U32 y)
{
if(!object || !object->textureHandles)
return NULL;
return object->textureHandles[x + y * object->texWidthCount];
}
void ChunkedTextureHandle::lock()
{
if(object)
object->refCount++;
}
void ChunkedTextureHandle::unlock()
{
if(object)
{
object->refCount--;
if(object->refCount == 0)
ChunkedTextureManager::freeTexture(object);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -