Files
eepp/src/graphics/ctexturefactory.cpp
2010-07-09 19:04:25 -03:00

392 lines
12 KiB
C++
Executable File

#include "ctexturefactory.hpp"
#include "../window/cengine.hpp"
using namespace EE::Window;
namespace EE { namespace Graphics {
cTextureFactory::cTextureFactory() :
mCurrentTexture(0),
mIsCalcPowOfTwo(false),
mMemSize(0)
{
mTextures.clear();
mTextures.push_back( NULL );
Log = cLog::instance();
BR = cGlobalBatchRenderer::instance();
}
cTextureFactory::~cTextureFactory() {
UnloadTextures();
}
GLint cTextureFactory::GetPrevTex() {
GLint PreviousTexture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture);
return PreviousTexture;
}
void cTextureFactory::BindPrev( const GLint& PreviousTexture ) {
glBindTexture(GL_TEXTURE_2D, PreviousTexture);
mCurrentTexture = PreviousTexture;
}
Uint32 cTextureFactory::CreateEmptyTexture( const eeUint& Width, const eeUint& Height, const eeColorA& DefaultColor, const bool& mipmap, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy ) {
std::vector<eeColorA> tmpTex( Width * Height, DefaultColor );
Uint32 TexId = LoadFromPixels( reinterpret_cast<unsigned char*> ( &tmpTex[0] ), Width, Height, 4, mipmap, eeRGB(true), ClampMode, CompressTexture, KeepLocalCopy );
tmpTex.clear();
return TexId;
}
Uint32 cTextureFactory::LoadFromPixels( const unsigned char* Surface, const eeUint& Width, const eeUint& Height, const eeUint& Channels, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, const std::string& FileName ) {
return iLoadFromPixels( Surface, Width, Height, Channels, mipmap, ColorKey, ClampMode, CompressTexture, KeepLocalCopy, FileName );
}
Uint32 cTextureFactory::iLoadFromPixels( const unsigned char* Surface, const eeUint& Width, const eeUint& Height, const eeUint& Channels, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, const std::string& FileName, const Uint32& TexPos ) {
Uint32 tTexId = 0;
if ( NULL != Surface ) {
int width = Width;
int height = Height;
Uint32 flags = mipmap ? SOIL_FLAG_MIPMAPS : 0;
flags = (ClampMode == EE_CLAMP_REPEAT) ? (flags | SOIL_FLAG_TEXTURE_REPEATS) : flags;
flags = (CompressTexture) ? ( flags | SOIL_FLAG_COMPRESS_TO_DXT ) : flags;
GLint PreviousTexture = GetPrevTex();
tTexId = SOIL_create_OGL_texture(Surface, &width, &height, Channels, ( ( TexPos==0 ) ? SOIL_CREATE_NEW_ID : GetTexture(TexPos)->Texture() ), flags);
BindPrev( PreviousTexture );
if ( tTexId )
return iPushTexture( FileName, tTexId, Width, Height, width, height, mipmap, static_cast<Uint8>( Channels ), ColorKey, ClampMode, CompressTexture, KeepLocalCopy, TexPos );
} else {
Log->Write( SOIL_last_result() );
}
return 0;
}
Uint32 cTextureFactory::LoadFromPack( cPack* Pack, const std::string& FilePackPath, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy ) {
std::vector<Uint8> TmpData;
if ( Pack->IsOpen() && Pack->ExtractFileToMemory( FilePackPath, TmpData ) )
return LoadFromMemory( reinterpret_cast<const Uint8*> (&TmpData[0]), TmpData.size(), mipmap, ColorKey, ClampMode, CompressTexture, KeepLocalCopy );
return 0;
}
Uint32 cTextureFactory::LoadFromMemory( const unsigned char* Surface, const eeUint& Size, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy ) {
int ImgWidth, ImgHeight, ImgChannels;
unsigned char * PixelsPtr = SOIL_load_image_from_memory(Surface, Size, &ImgWidth, &ImgHeight, &ImgChannels, SOIL_LOAD_AUTO);
if ( NULL != PixelsPtr )
return LoadFromPixels( PixelsPtr, ImgWidth, ImgHeight, ImgChannels, mipmap, ColorKey, ClampMode, CompressTexture, KeepLocalCopy );
else
Log->Write( SOIL_last_result() );
return 0;
}
Uint32 cTextureFactory::Load( const std::string& filepath, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy ) {
return iLoad( filepath, mipmap, ColorKey, ClampMode, CompressTexture, KeepLocalCopy, 0 );
}
Uint32 cTextureFactory::iLoad( const std::string& filepath, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, const Uint32& TexPos ) {
int ImgWidth, ImgHeight, ImgChannels;
if ( FileExists( filepath ) ) {
unsigned char * PixelsPtr = SOIL_load_image(filepath.c_str(), &ImgWidth, &ImgHeight, &ImgChannels, SOIL_LOAD_AUTO);
if ( NULL != PixelsPtr ) {
Uint32 Result = iLoadFromPixels( PixelsPtr, ImgWidth, ImgHeight, ImgChannels, mipmap, ColorKey, ClampMode, CompressTexture, KeepLocalCopy, filepath, TexPos );
SOIL_free_image_data( PixelsPtr );
return Result;
} else
Log->Write( SOIL_last_result() );
}
return 0;
}
Uint32 cTextureFactory::PushTexture( const std::string& filepath, const Uint32& TexId, const eeUint& Width, const eeUint& Height, const eeUint& ImgWidth, const eeUint& ImgHeight, const bool& Mipmap, const eeUint& Channels, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& LocalCopy ) {
return iPushTexture( filepath, TexId, Width, Height, ImgWidth, ImgHeight, Mipmap, Channels, ColorKey, ClampMode, CompressTexture, LocalCopy );
}
Uint32 cTextureFactory::iPushTexture( const std::string& filepath, const Uint32& TexId, const eeUint& Width, const eeUint& Height, const eeUint& ImgWidth, const eeUint& ImgHeight, const bool& Mipmap, const eeUint& Channels, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture, const bool& LocalCopy, const Uint32& TexPos ) {
cTexture * Tex = NULL;
Uint32 Pos;
eeInt MyWidth = ImgWidth;
eeInt MyHeight = ImgHeight;
if ( TexPos != 0 ) {
Pos = TexPos;
Tex = GetTexture( TexPos );
// Recover the real image size
if ( NULL != Tex && TexId == Tex->Texture() ) {
Tex->Width( Width );
Tex->Height( Height );
MyWidth = Tex->ImgWidth();
MyHeight = Tex->ImgHeight();
mMemSize -= GetTexMemSize( TexPos );
}
} else {
Pos = FindFreeSlot();
Tex = mTextures[ Pos ] = new cTexture();
}
Tex->Create( TexId, Width, Height, MyWidth, MyHeight, Mipmap, Channels, filepath, ColorKey, ClampMode, CompressTexture );
Tex->TexId( Pos );
if ( !ColorKey.voidRGB )
Tex->CreateMaskFromColor( eeColor( ColorKey.R(), ColorKey.G(), ColorKey.B() ) , 0 );
if ( LocalCopy ) {
Tex->Lock();
Tex->Unlock( true, false );
}
mMemSize += GetTexMemSize( Pos );
return Pos;
}
Uint32 cTextureFactory::FindFreeSlot() {
if ( mVectorFreeSlots.size() ) {
Uint32 Pos = mVectorFreeSlots.front();
mVectorFreeSlots.pop();
return Pos;
}
mTextures.push_back( NULL );
return mTextures.size() - 1;
}
void cTextureFactory::Bind( const cTexture* Tex ) {
if( NULL != Tex && mCurrentTexture != (Int32)Tex->Texture() ) {
glBindTexture( GL_TEXTURE_2D, Tex->Texture() );
mCurrentTexture = Tex->Texture();
}
}
void cTextureFactory::Bind( const Uint32& TexId ) {
Bind( GetTexture( TexId ) );
}
void cTextureFactory::UnloadTextures() {
try {
for ( Uint32 i = 1; i < mTextures.size(); i++ )
if ( mTextures[i] != NULL )
delete mTextures[i];
mTextures.clear();
Log->Write( "Textures Unloaded." );
} catch (...) {
Log->Write("An error ocurred on: UnloadTextures.");
}
}
bool cTextureFactory::Remove( const Uint32& TexId ) {
if ( TexId < mTextures.size() && NULL != mTextures[ TexId ] ) {
mMemSize -= GetTexMemSize( TexId );
GLint glTexId = mTextures[ TexId ]->Texture();
eeSAFE_DELETE( mTextures[ TexId ] );
if ( mCurrentTexture == (Int32)glTexId )
mCurrentTexture = 0;
mVectorFreeSlots.push( TexId );
return true;
}
return false;
}
Uint32 cTextureFactory::Reload( const Uint32& TexId, const std::string& filepath, const bool& mipmap, const eeRGB& ColorKey, const EE_CLAMP_MODE& ClampMode, const bool& CompressTexture ) {
Uint32 Id = 0;
if ( !filepath.empty() ) {
Id = iLoad(filepath, mipmap, ColorKey, ClampMode, CompressTexture, TexId);
return Id;
} else {
cTexture* Tex = GetTexture(TexId);
if ( Tex->LocalCopy() )
Id = iLoadFromPixels( Tex->GetPixelsPtr(), (int)Tex->Width(), (int)Tex->Height(), SOIL_LOAD_RGBA, Tex->Mipmap(), Tex->ColorKey(), Tex->ClampMode(), Tex->Compressed(), ( Tex->LocalCopy() && !Tex->Grabed() ), Tex->Filepath(), TexId );
else
Id = iLoad( Tex->Filepath(), Tex->Mipmap(), Tex->ColorKey(), Tex->ClampMode(), Tex->Compressed(), TexId );
return Id;
}
}
GLint cTextureFactory::GetCurrentTexture() const {
return mCurrentTexture;
}
void cTextureFactory::SetCurrentTexture( const GLint& TexId ) {
mCurrentTexture = TexId;
}
void cTextureFactory::ReloadAllTextures() {
try {
for ( Uint32 i = 1; i < mTextures.size(); i++ ) {
cTexture* Tex = GetTexture(i);
if ( Tex ) {
if ( ( Tex->Filepath() != "" && FileExists( Tex->Filepath() ) ) || Tex->LocalCopy() )
Reload(i);
else {
Tex->Lock();
Reload(i);
Tex->Unlock(false, false);
}
}
}
Log->Write("Textures Reloaded.");
} catch (...) {
Log->Write("An error ocurred on: ReloadAllTextures.");
}
}
void cTextureFactory::GrabTextures() {
for ( Uint32 i = 1; i < mTextures.size(); i++ ) {
cTexture* Tex = GetTexture(i);
if ( Tex ) {
if ( !( Tex->Filepath() != "" || Tex->LocalCopy() ) ) {
Tex->Lock();
Tex->Unlock(true, false);
Tex->Grabed(true);
}
}
}
}
void cTextureFactory::SetBlendFunc( const EE_RENDERALPHAS& blend, const bool& force ) {
if ( mLastBlend != blend || force ) {
if (blend == ALPHA_NONE)
glDisable( GL_BLEND );
else {
glEnable( GL_BLEND );
switch (blend) {
case ALPHA_NORMAL:
glBlendFunc(GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA);
break;
case ALPHA_BLENDONE:
glBlendFunc(GL_SRC_ALPHA , GL_ONE);
break;
case ALPHA_BLENDTWO:
glBlendFunc(GL_SRC_ALPHA , GL_SRC_ALPHA);
glBlendFunc(GL_DST_ALPHA , GL_ONE);
break;
case ALPHA_BLENDTHREE:
glBlendFunc(GL_SRC_ALPHA , GL_ONE);
glBlendFunc(GL_DST_ALPHA , GL_SRC_ALPHA);
break;
case ALPHA_ALPHACHANNELS:
glBlendFunc(GL_SRC_ALPHA , GL_SRC_ALPHA);
break;
case ALPHA_DESTALPHA:
glBlendFunc(GL_SRC_ALPHA , GL_DST_ALPHA);
break;
case ALPHA_MULTIPLY:
glBlendFunc(GL_DST_COLOR,GL_ZERO);
break;
case ALPHA_NONE:
// COMPILER WARNING MY BALLS
break;
}
}
mLastBlend = blend;
}
}
eeUint cTextureFactory::GetValidTextureSize(const eeUint& Size) {
if (!mIsCalcPowOfTwo) {
if ( cEngine::instance()->Running() ) { // This need the GL context initialized
char *extensions = (char *)glGetString(GL_EXTENSIONS);
if ( strstr(extensions, "GL_ARB_texture_non_power_of_two") )
mPowOfTwo = false;
else
mPowOfTwo = true;
mIsCalcPowOfTwo = true;
} else
mPowOfTwo = false;
}
if ( !mPowOfTwo )
return Size;
else
return NextPowOfTwo(Size);
}
bool cTextureFactory::SaveImage( const std::string& filepath, const EE_SAVETYPE& Format, const eeUint& Width, const eeUint& Height, const eeUint& Channels, const unsigned char* data ) {
return 0 != SOIL_save_image ( filepath.c_str(), Format, Width, Height, Channels, data );
}
bool cTextureFactory::TextureIdExists( const Uint32& TexId ) {
return ( TexId < mTextures.size() && TexId > 0 && NULL != mTextures[ TexId ] );
}
cTexture * cTextureFactory::GetTexture( const Uint32& TexId ) {
return mTextures[TexId];
}
void cTextureFactory::Allocate( const eeUint& size ) {
if ( size > mTextures.size() ) {
mTextures.resize( size + 1, NULL );
for ( eeUint i = 1; i < mTextures.size(); i++ )
mVectorFreeSlots.push( i );
}
}
eeUint cTextureFactory::GetTexMemSize( const eeUint& TexId ) {
eeUint Size = 0;
if ( TexId < mTextures.size() && TexId > 0 ) {
cTexture* Tex = mTextures[ TexId ];
if ( Tex != NULL ) {
eeUint w = static_cast<eeUint>( Tex->Width() );
eeUint h = static_cast<eeUint>( Tex->Height() );
Size = ( w * h * Tex->Channels() );
if( Tex->Mipmap() ) {
while(w > 2 && h > 2) {
w>>=1;
h>>=1;
Size += ( w * h * Tex->Channels() );
}
}
}
return Size;
}
return 0;
}
}}