⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtexmanager.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "platform/platformAssert.h"
#include "platform/platformGL.h"
#include "platform/platform.h"
#include "core/tVector.h"
#include "core/resManager.h"
#include "dgl/gBitmap.h"
#include "dgl/gPalette.h"
#include "dgl/gTexManager.h"
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/consoleTypes.h"
#include "dgl/gChunkedTexManager.h"

//------------------------------------------------------------------------------

bool gDGLRender = true;

bool sgResurrect = false;
bool sgForcePalettedTexture = false;
bool sgForce16BitTexture    = false;


#define  ENABLE_HOLDING    1

#ifdef TORQUE_GATHER_METRICS
U32 TextureManager::smTextureSpaceLoaded = 0;
U32 TextureManager::smTextureCacheMisses = 0;
#endif

bool TextureManager::smUseSmallTextures = false;
bool TextureManager::smIsZombie = false;
bool TextureManager::smTextureManagerActive = false;

//--------------------------------------------------------------------------
//-------------------------------------- Texture detailing control variables
//                                        0: Highest
//                                        1: ...
//                                        2: ...
//                                        3: Lowest

namespace {

struct Forced16BitMapping
{
   GLenum wanted;
   GLenum forced;
   bool   end;
};

Forced16BitMapping sg16BitMappings[] =
{
   { GL_RGB,  GL_RGB5,  false },
   { GL_RGBA, GL_RGBA4, false },
   { 0, 0, true }
};


U32    sgTextureDetailLevel         = 0;
U32    sgSkyTextureDetailLevel      = 0;
U32    sgInteriorTextureDetailLevel = 0;
bool   sgAllowTexCompression  = false;
GLenum sgCompressionHint      = GL_FASTEST;
F32    sgTextureAnisotropy    = 0.0; // default aniso, when available.  not sure why prefs.cs isn't setting.
bool   sgDisableSubImage      = false;
bool   sgTextureTrilinear      = false;

// valid texture extensions
#define EXT_ARRAY_SIZE 6
static const char* extArray[EXT_ARRAY_SIZE] = { "", ".jpg", ".png", ".gif", ".bmp", "" };
static const char* extArray_8[EXT_ARRAY_SIZE] = { "", ".bm8", ".bmp", ".jpg", ".png", ".gif" };

ConsoleFunctionGroupBegin( OpenGLTex, "Functions controlling OpenGL parameters.");

ConsoleFunction(setOpenGLMipReduction, void, 2, 2, "( n ) Sets mipmap reduction level, n ranges from 0-5.")
{
   argc;
   S32 val = dAtoi(argv[1]);
   if (val < 0)
      val = 0;
   else if (val > 5)
      val = 5;

   sgTextureDetailLevel = val;
}

ConsoleFunction(setOpenGLSkyMipReduction, void, 2, 2, "setOpenGLSkyMipReduction(0-5);")
{
   argc;
   S32 val = dAtoi(argv[1]);
   if (val < 0)
      val = 0;
   else if (val > 5)
      val = 5;

   sgSkyTextureDetailLevel = val;
}

ConsoleFunction(setOpenGLInteriorMipReduction, void, 2, 2, "setOpenGLInteriorMipReduction(0-5);")
{
   argc;
   S32 val = dAtoi(argv[1]);
   if (val < 0)
      val = 0;
   else if (val > 5)
      val = 5;

   sgInteriorTextureDetailLevel = val;
}

ConsoleFunction(setOpenGLTextureCompressionHint, void, 2, 2, "setTextureCompressionHint(GL_DONT_CARE|GL_FASTEST|GL_NICEST);")
{
   argc;

   GLenum newHint        = GL_DONT_CARE;
   const char* newString = "GL_DONT_CARE";

   if (!dStricmp(argv[1], "GL_FASTEST"))
   {
      newHint = GL_FASTEST;
      newString = "GL_FASTEST";
   }
   else if (!dStricmp(argv[1], "GL_NICEST"))
   {
      newHint = GL_NICEST;
      newString = "GL_NICEST";
   }

   sgCompressionHint = newHint;

   if (dglDoesSupportTextureCompression())
      glHint(GL_TEXTURE_COMPRESSION_HINT_ARB, sgCompressionHint);
}

ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
   argc;
   F32 val = dAtof(argv[1]);
   if (val < 0.0)
      val = 0.0;
   if (val > dglGetMaxAnisotropy())
      val = dglGetMaxAnisotropy();
   sgTextureAnisotropy = val;

   if(dglDoesSupportTexAnisotropy())
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, sgTextureAnisotropy * dglGetMaxAnisotropy());
}

ConsoleFunctionGroupEnd( OpenGLTex );

} // namespace {}


//--------------------------------------
struct TextureDictionary
{
   static TextureObject **smTable;
   static TextureObject *smTOList;
   static U32 smHashTableSize;

   static void create();
   static void preDestroy();
   static void destroy();

   static void insert(TextureObject *object);
   static TextureObject *find(StringTableEntry name, TextureHandleType type, bool clamp);
   static void remove(TextureObject *object);
   static S32 clearHolds();
};

TextureObject **TextureDictionary::smTable = NULL;
TextureObject *TextureDictionary::smTOList = NULL;
U32 TextureDictionary::smHashTableSize = 0;

//--------------------------------------
void TextureDictionary::create()
{
   smTOList = NULL;
   smHashTableSize = 1023;
   smTable = new TextureObject *[smHashTableSize];
   for(U32 i = 0; i < smHashTableSize; i++)
      smTable[i] = NULL;

   Con::addVariable("$pref::OpenGL::force16BitTexture",    TypeBool, &sgForce16BitTexture);
   Con::addVariable("$pref::OpenGL::forcePalettedTexture", TypeBool, &sgForcePalettedTexture);
   Con::addVariable("$pref::OpenGL::allowCompression",     TypeBool, &sgAllowTexCompression);
   Con::addVariable("$pref::OpenGL::disableSubImage",      TypeBool, &sgDisableSubImage);

   Con::addVariable("$pref::OpenGL::textureTrilinear",     TypeBool, &sgTextureTrilinear);
   Con::addVariable("$pref::OpenGL::textureAnisotropy",    TypeF32,  &sgTextureAnisotropy);
}


//--------------------------------------
TextureObject *TextureDictionary::find(StringTableEntry name, TextureHandleType type, bool clamp)
{
   U32 key = HashPointer(name) % smHashTableSize;
   TextureObject *walk = smTable[key];
   for(; walk; walk = walk->hashNext)
      if(walk->texFileName == name && walk->type == type && walk->clamp == clamp)
         break;
   return walk;
}


//--------------------------------------
void TextureDictionary::remove(TextureObject *object)
{
   if(object->next)
      object->next->prev = object->prev;

   if(object->prev)
      object->prev->next = object->next;
   else
      smTOList = object->next;

   if(!object->texFileName)
      return;

   U32 key = HashPointer(object->texFileName) % smHashTableSize;
   TextureObject **walk = &smTable[key];
   while(*walk)
   {
      if(*walk == object)
      {
         *walk = object->hashNext;
         break;
      }
      walk = &((*walk)->hashNext);
   }
}


//--------------------------------------
void TextureDictionary::insert(TextureObject *object)
{
   object->next = smTOList;
   object->prev = NULL;
   if(smTOList)
      smTOList->prev = object;
   smTOList = object;

   if(object->texFileName)
   {
      U32 key = HashPointer(object->texFileName) % smHashTableSize;

      object->hashNext = smTable[key];
      smTable[key] = object;
   }
}

//--------------------------------------
void TextureDictionary::preDestroy()
{
   // This is a horrid hack, but it will have to do for now.  (DMM, aided
   //  and abetted by MF.)
   TextureObject* walk = smTOList;
   while (walk)
   {
      if((gDGLRender || sgResurrect) && walk->texGLName)
         glDeleteTextures(1, (const GLuint*)&walk->texGLName);
      if((gDGLRender || sgResurrect) && walk->smallTexGLName)
         glDeleteTextures(1, (const GLuint*)&walk->smallTexGLName);
      delete walk->bitmap;
      walk->texGLName = 0;
      walk->smallTexGLName = 0;
      walk->bitmap = NULL;

      walk = walk->next;
   }
}

//--------------------------------------
void TextureDictionary::destroy()
{
   // This is a horrid hack, but it will have to do for now.  (DMM, aided
   //  and abetted by MF.)
   while(smTOList)
      TextureManager::freeTexture(smTOList);
   delete[] smTable;
}

//--------------------------------------
S32 TextureDictionary::clearHolds()
{
   Vector<TextureObject *>    holds;

   // Find held textures to delete.  Clear holding flag too so they're free
   // to go away.
   for (TextureObject * walk = smTOList; walk; walk = walk->next)
   {
      if (walk->holding)
      {
         if (!walk->refCount)
            holds.push_back(walk);
         else
            walk->holding = false;
      }
   }

   // Remove them-
   for (S32 i = 0; i < holds.size(); i++)
      TextureManager::freeTexture(holds[i]);

   return holds.size();
}

ConsoleFunction(clearTextureHolds, S32, 1, 1, "clearTextureHolds();")
{
   argc; argv;
   return TextureDictionary::clearHolds();
}


//--------------------------------------------------------------------------
//--------------------------------------
//
struct EventCallbackEntry
{
   TextureEventCallback callback;
   void *               userData;
   U32                  key;
};
static U32                        sgCurrCallbackKey = 0;
static Vector<EventCallbackEntry> sgEventCallbacks(__FILE__, __LINE__);

U32  TextureManager::registerEventCallback(TextureEventCallback callback, void *userData)
{
   sgEventCallbacks.increment();
   sgEventCallbacks.last().callback = callback;
   sgEventCallbacks.last().userData = userData;
   sgEventCallbacks.last().key      = sgCurrCallbackKey++;

   return sgEventCallbacks.last().key;
}

void TextureManager::unregisterEventCallback(const U32 callbackKey)
{
   for (S32 i = 0; i < sgEventCallbacks.size(); i++)
      if (sgEventCallbacks[i].key == callbackKey) {
         sgEventCallbacks.erase(i);
         return;
      }
}

void TextureManager::postTextureEvent(const U32 eventCode)
{
   for (S32 i = 0; i < sgEventCallbacks.size(); i++)
      (sgEventCallbacks[i].callback)(eventCode, sgEventCallbacks[i].userData);
}


void TextureManager::create()
{
   AssertISV(!smTextureManagerActive, "TextureManager::create - already created!");

   TextureDictionary::create();
   smTextureManagerActive = true;
}

void TextureManager::preDestroy()
{
   AssertISV(smTextureManagerActive, "TextureManager::preDestroy - nothing to destroy!");

   TextureDictionary::preDestroy();
}

void TextureManager::destroy()
{
   AssertISV(smTextureManagerActive, "TextureManager::destroy - nothing to destroy!");

   TextureDictionary::destroy();

   AssertFatal(sgEventCallbacks.size() == 0,
               "Error, some object didn't unregister it's texture event callback function!");

   smTextureManagerActive = false;
}


//--------------------------------------
void TextureManager::makeZombie()
{
   if (smIsZombie == true)
      return;
   smIsZombie = true;

   postTextureEvent(BeginZombification);
   ChunkedTextureManager::makeZombie();
   
   // Publish flush event?

   Vector<GLuint> deleteNames(4096);

   TextureObject* probe = TextureDictionary::smTOList;
   while (probe) 
   {
      AssertFatal(probe->type != TerrainTexture, "Error, all the terrain textureobjects should be gone by now!");
      
      if (probe->type == BitmapNoDownloadTexture)
      {
         probe = probe->next;
         continue;
      }

      if (probe->texGLName != 0)
         deleteNames.push_back(probe->texGLName);
      if (probe->smallTexGLName != 0)
         deleteNames.push_back(probe->smallTexGLName);

#ifdef TORQUE_GATHER_METRICS
      AssertFatal(probe->textureSpace <= smTextureSpaceLoaded, "Error, that shouldn't happen!");
      smTextureSpaceLoaded -= probe->textureSpace;
      probe->textureSpace   = 0;
#endif

      probe->texGLName      = 0;
      probe->smallTexGLName = 0;

      probe = probe->next;
   }

   glDeleteTextures(deleteNames.size(), deleteNames.address());
}

void TextureManager::resurrect()
{
   if (smIsZombie == false)
      return;
   smIsZombie = false;

   sgResurrect = true;

   // Get rid of any chunked textures created while the app was inactive
   ChunkedTextureManager::makeZombie();

   // Reload textures...
   TextureObject* probe = TextureDictionary::smTOList;
   while (probe) 
   {
      // reload texture...
      AssertFatal(probe->type != TerrainTexture, "Error, all the terrain textureobjects should be gone by now!");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -