| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 | //-----------------------------------------------------------------------------// Copyright (c) 2012 GarageGames, LLC//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS// IN THE SOFTWARE.//-----------------------------------------------------------------------------#include "platform/platform.h"#include "gfx/gfxTextureObject.h"#include "gfx/gfxDevice.h"#include "gfx/gfxTextureManager.h"#include "core/util/safeDelete.h"#include "core/strings/stringFunctions.h"#include "core/stream/fileStream.h"#include "console/console.h"#include "console/engineAPI.h"// TODO: Change this to be in non-shipping builds maybe?#ifdef TORQUE_DEBUGGFXTextureObject *GFXTextureObject::smHead = NULL;U32 GFXTextureObject::smActiveTOCount = 0;U32 GFXTextureObject::dumpActiveTOs(){   if(!smActiveTOCount)   {      Con::printf( "GFXTextureObject::dumpActiveTOs - no active TOs to dump." );      return 0;   }   Con::printf("GFXTextureObject Usage Report - %d active TOs", smActiveTOCount);   Con::printf("---------------------------------------------------------------");   Con::printf(" Addr   Dim. GFXTextureProfile  ProfilerPath DebugDescription");   for(GFXTextureObject *walk = smHead; walk; walk=walk->mDebugNext)      Con::printf(" %x  (%4d, %4d)  %s    %s    %s", walk, walk->getWidth(),       walk->getHeight(), walk->mProfile->getName().c_str(), walk->mDebugCreationPath.c_str(), walk->mDebugDescription.c_str());   Con::printf("----- dump complete -------------------------------------------");   return smActiveTOCount;}#endif // TORQUE_DEBUGDefineEngineFunction( dumpTextureObjects, void, (),,   "Dumps a list of all active texture objects to the console.\n"   "@note This function is only available in debug builds.\n"   "@ingroup GFX\n" ){#ifdef TORQUE_DEBUG   GFXTextureObject::dumpActiveTOs();#endif}//-----------------------------------------------------------------------------// GFXTextureObject//-----------------------------------------------------------------------------GFXTextureObject::GFXTextureObject(GFXDevice *aDevice, GFXTextureProfile *aProfile) {   mHashNext = mNext = mPrev = NULL;   mDevice = aDevice;   mProfile = aProfile;   mBitmap         = NULL;   mMipLevels      = 1;   mAntialiasLevel = 0;   mTextureSize.set( 0, 0, 0 );   mDead = false;   mDeleteTime = 0;   mBitmap = NULL;   mDDS    = NULL;      mFormat = GFXFormatR8G8B8;   mHasTransparency = false;#if defined(TORQUE_DEBUG)   // Active object tracking.   smActiveTOCount++;   mDebugDescription = "Anonymous Texture Object";#if defined(TORQUE_ENABLE_PROFILE_PATH)      mDebugCreationPath = gProfiler->getProfilePath();#endif   mDebugNext = smHead;   mDebugPrev = NULL;   if(smHead)   {      AssertFatal(smHead->mDebugPrev == NULL, "GFXTextureObject::GFXTextureObject - found unexpected previous in current head!");      smHead->mDebugPrev = this;   }   smHead = this;#endif}//-----------------------------------------------------------------------------// Destructor//-----------------------------------------------------------------------------GFXTextureObject::~GFXTextureObject() {   kill();#ifdef TORQUE_DEBUG   if(smHead == this)      smHead = this->mDebugNext;   if(mDebugNext)      mDebugNext->mDebugPrev = mDebugPrev;   if(mDebugPrev)      mDebugPrev->mDebugNext = mDebugNext;   mDebugPrev = mDebugNext = NULL;   smActiveTOCount--;#endif}void GFXTextureObject::destroySelf(){   mDevice->mTextureManager->requestDeleteTexture(this);}//-----------------------------------------------------------------------------// kill - this function clears out the data in texture object.  It's done like// this because the texture object needs to release its pointers to textures// before the GFXDevice is shut down.  The texture objects themselves get// deleted by the refcount structure - which may be after the GFXDevice has// been destroyed.//-----------------------------------------------------------------------------void GFXTextureObject::kill(){   if( mDead )      return;#ifdef TORQUE_DEBUG   // This makes sure that nobody is forgetting to call kill from the derived   // destructor.  If they are, then we should get a pure virtual function   // call here.   pureVirtualCrash();#endif   // If we're a dummy, don't do anything...   if( !mDevice || !mDevice->mTextureManager )    {      mDead = true;      return;   }   // Remove ourselves from the texture list and hash   mDevice->mTextureManager->deleteTexture(this);   // Delete the stored bitmap.   SAFE_DELETE(mBitmap)   SAFE_DELETE(mDDS);   // Clean up linked list   if(mNext)      mNext->mPrev = mPrev;   if(mPrev)      mPrev->mNext = mNext;   mDead = true;}const String GFXTextureObject::describeSelf() const{   return String::ToString(" (width: %4d, height: %4d)  profile: %s   creation path: %s", getWidth(), #if defined(TORQUE_DEBUG) && defined(TORQUE_ENABLE_PROFILER)        getHeight(), mProfile->getName().c_str(), mDebugCreationPath.c_str());#else                        getHeight(), mProfile->getName().c_str(), "");#endif}F32 GFXTextureObject::getMaxUCoord() const{   return 1.0f;}F32 GFXTextureObject::getMaxVCoord() const{   return 1.0f;}U32 GFXTextureObject::getEstimatedSizeInBytes() const{   // We have to deal with DDS specially.   if ( mFormat >= GFXFormatDXT1 )      return DDSFile::getSizeInBytes( mFormat, mTextureSize.x, mTextureSize.y, mMipLevels );   // Else we need to calculate the size ourselves.   S32 texSizeX = mTextureSize.x;   S32 texSizeY = mTextureSize.y;   S32 volDepth = getMax( 1, mTextureSize.z );   U32 byteSize = GFXFormat_getByteSize( mFormat );   U32 totalBytes = texSizeX * texSizeY * volDepth * byteSize;   // Without mips we're done.   if ( mProfile->noMip() )      return totalBytes;   // NOTE: While we have mMipLevels, at the time of this   // comment it only stores the accessable mip levels and   // not the count of the autogen mips.   //   // So we figure out the mip count ourselves assuming its   // a complete mip chain.   while ( texSizeX > 1 || texSizeY > 1 )   {      texSizeX = getMax( texSizeX >> 1, 1 );      texSizeY = getMax( texSizeY >> 1, 1 );      volDepth = getMax( volDepth >> 1, 1 );      totalBytes += texSizeX * texSizeY * volDepth * byteSize;   }   return totalBytes;}bool GFXTextureObject::dumpToDisk( const String &bmType, const String &path ){      FileStream stream;   if ( !stream.open( path, Torque::FS::File::Write ) )      return false;   if ( mBitmap )      return mBitmap->writeBitmap( bmType, stream );   GBitmap bitmap( getWidth(), getHeight(), false, getFormat() );   copyToBmp( &bitmap );   return bitmap.writeBitmap( bmType, stream );}
 |