Engine directory for ticket #1

This commit is contained in:
DavidWyand-GG 2012-09-19 11:15:01 -04:00
parent 352279af7a
commit 7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions

View file

@ -0,0 +1,148 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
D3DX_FUNCTION( D3DXCreateBuffer, HRESULT,
(DWORD NumBytes,
LPD3DXBUFFER * ppBuffer) )
D3DX_FUNCTION( D3DXSaveSurfaceToFileA, HRESULT,
(LPCSTR pDestFile,
D3DXIMAGE_FILEFORMAT DestFormat,
LPDIRECT3DSURFACE9 pSrcSurface,
CONST PALETTEENTRY* pSrcPalette,
CONST RECT* pSrcRect) )
D3DX_FUNCTION( D3DXSaveSurfaceToFileW, HRESULT,
(LPCWSTR pDestFile,
D3DXIMAGE_FILEFORMAT DestFormat,
LPDIRECT3DSURFACE9 pSrcSurface,
CONST PALETTEENTRY* pSrcPalette,
CONST RECT* pSrcRect) )
D3DX_FUNCTION( D3DXCompileShader, HRESULT,
(LPCSTR pSrcData,
UINT srcDataLen,
CONST D3DXMACRO* pDefines,
LPD3DXINCLUDE pInclude,
LPCSTR pFunctionName,
LPCSTR pProfile,
DWORD Flags,
LPD3DXBUFFER* ppShader,
LPD3DXBUFFER* ppErrorMsgs,
LPD3DXCONSTANTTABLE * ppConstantTable) )
D3DX_FUNCTION( D3DXGetShaderConstantTable, HRESULT,
(CONST DWORD* pFunction,
LPD3DXCONSTANTTABLE* ppConstantTable) )
D3DX_FUNCTION( D3DXLoadSurfaceFromSurface, HRESULT,
(LPDIRECT3DSURFACE9 pDestSurface,
CONST PALETTEENTRY* pDestPalette,
CONST RECT* pDestRect,
LPDIRECT3DSURFACE9 pSrcSurface,
CONST PALETTEENTRY* pSrcPalette,
CONST RECT* pSrcRect,
DWORD Filter,
D3DCOLOR ColorKey) )
D3DX_FUNCTION( D3DXCreateVolumeTexture, HRESULT,
(LPDIRECT3DDEVICE9 pDevice,
UINT Width,
UINT Height,
UINT Depth,
UINT MipLevels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture) )
D3DX_FUNCTION( D3DXCreateTexture, HRESULT,
(LPDIRECT3DDEVICE9 pDevice,
UINT Width,
UINT Height,
UINT MipLevels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
LPDIRECT3DTEXTURE9* ppTexture) )
#ifdef TORQUE_OS_XENON
D3DX_FUNCTION( D3DXLoadVolumeFromMemory, HRESULT,
(LPDIRECT3DVOLUME9 pDestVolume,
CONST PALETTEENTRY* pDestPalette,
CONST D3DBOX* pDestBox,
LPCVOID pSrcMemory,
D3DFORMAT SrcFormat,
UINT SrcRowPitch,
UINT SrcSlicePitch,
CONST PALETTEENTRY* pSrcPalette,
CONST D3DBOX* pSrcBox,
BOOL SrcParentPacked,
UINT SrcParentWidth,
UINT SrcParentHeight,
UINT SrcParentDepth,
DWORD Filter,
D3DCOLOR ColorKey) )
#else
D3DX_FUNCTION( D3DXLoadVolumeFromMemory, HRESULT,
(LPDIRECT3DVOLUME9 pDestVolume,
CONST PALETTEENTRY* pDestPalette,
CONST D3DBOX* pDestBox,
LPCVOID pSrcMemory,
D3DFORMAT SrcFormat,
UINT SrcRowPitch,
UINT SrcSlicePitch,
CONST PALETTEENTRY* pSrcPalette,
CONST D3DBOX* pSrcBox,
DWORD Filter,
D3DCOLOR ColorKey) )
#endif
D3DX_FUNCTION( D3DXSaveTextureToFileInMemory, HRESULT,
(LPD3DXBUFFER *ppDestBuf,
D3DXIMAGE_FILEFORMAT DestFormat,
LPDIRECT3DBASETEXTURE9 pSrcTexture,
const PALETTEENTRY *pSrcPalette) )
D3DX_FUNCTION( D3DXGetImageInfoFromFileInMemory, HRESULT,
(LPCVOID pSrcData,
UINT SrcDataSize,
D3DXIMAGE_INFO* pSrcInfo) )
D3DX_FUNCTION( D3DXLoadSurfaceFromFileInMemory, HRESULT,
(LPDIRECT3DSURFACE9 pDestSurface,
CONST PALETTEENTRY * pDestPalette,
CONST RECT * pDestRect,
LPCVOID pSrcData,
UINT SrcData,
CONST RECT * pSrcRect,
DWORD Filter,
D3DCOLOR ColorKey,
D3DXIMAGE_INFO * pSrcInfo) )
D3DX_FUNCTION( D3DXSaveSurfaceToFileInMemory, HRESULT,
(LPD3DXBUFFER* ppDestBuf,
D3DXIMAGE_FILEFORMAT DestFormat,
LPDIRECT3DSURFACE9 pSrcSurface,
CONST PALETTEENTRY* pSrcPalette,
CONST RECT* pSrcRect) )

View file

@ -0,0 +1,161 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "console/console.h"
#include "gfx/primBuilder.h"
#include "gfx/D3D9/gfxD3D9CardProfiler.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#ifdef TORQUE_OS_WIN32
#include "platformWin32/videoInfo/wmiVideoInfo.h"
#endif
GFXD3D9CardProfiler::GFXD3D9CardProfiler() : GFXCardProfiler()
{
}
GFXD3D9CardProfiler::~GFXD3D9CardProfiler()
{
}
void GFXD3D9CardProfiler::init()
{
mD3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
AssertISV( mD3DDevice, "GFXD3D9CardProfiler::init() - No D3D9 Device found!");
// Grab the caps so we can get our adapter ordinal and look up our name.
D3DCAPS9 caps;
D3D9Assert(mD3DDevice->GetDeviceCaps(&caps), "GFXD3D9CardProfiler::init - failed to get device caps!");
#ifdef TORQUE_OS_XENON
mCardDescription = "Xbox360 GPU";
mChipSet = "ATI";
mVersionString = String::ToString(_XDK_VER);
mVideoMemory = 512 * 1024 * 1024;
#else
WMIVideoInfo wmiVidInfo;
if( wmiVidInfo.profileAdapters() )
{
const PlatformVideoInfo::PVIAdapter &adapter = wmiVidInfo.getAdapterInformation( caps.AdapterOrdinal );
mCardDescription = adapter.description;
mChipSet = adapter.chipSet;
mVersionString = adapter.driverVersion;
mVideoMemory = adapter.vram;
}
#endif
Parent::init();
}
void GFXD3D9CardProfiler::setupCardCapabilities()
{
// Get the D3D device caps
D3DCAPS9 caps;
mD3DDevice->GetDeviceCaps(&caps);
setCapability( "autoMipMapLevel", ( caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP ? 1 : 0 ) );
setCapability( "maxTextureWidth", caps.MaxTextureWidth );
setCapability( "maxTextureHeight", caps.MaxTextureHeight );
setCapability( "maxTextureSize", getMin( (U32)caps.MaxTextureWidth, (U32)caps.MaxTextureHeight) );
bool canDoLERPDetailBlend = ( caps.TextureOpCaps & D3DTEXOPCAPS_LERP ) && ( caps.MaxTextureBlendStages > 1 );
bool canDoFourStageDetailBlend = ( caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT ) &&
( caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP ) &&
( caps.MaxTextureBlendStages > 3 );
setCapability( "lerpDetailBlend", canDoLERPDetailBlend );
setCapability( "fourStageDetailBlend", canDoFourStageDetailBlend );
}
bool GFXD3D9CardProfiler::_queryCardCap(const String &query, U32 &foundResult)
{
return 0;
}
bool GFXD3D9CardProfiler::_queryFormat( const GFXFormat fmt, const GFXTextureProfile *profile, bool &inOutAutogenMips )
{
LPDIRECT3D9 pD3D = static_cast<GFXD3D9Device *>(GFX)->getD3D();
D3DDISPLAYMODE displayMode = static_cast<GFXD3D9Device *>(GFX)->getDisplayMode();
DWORD usage = 0;
D3DRESOURCETYPE rType = D3DRTYPE_TEXTURE;
D3DFORMAT adapterFormat = displayMode.Format;
D3DFORMAT texFormat = GFXD3D9TextureFormat[fmt];
#if defined(TORQUE_OS_XENON)
inOutAutogenMips = false;
adapterFormat = D3DFMT_A8B8G8R8;
if(profile->isRenderTarget())
{
texFormat = (D3DFORMAT)MAKELEFMT(texFormat);
}
#else
if( profile->isRenderTarget() )
usage |= D3DUSAGE_RENDERTARGET;
else if( profile->isZTarget() )
{
usage |= D3DUSAGE_DEPTHSTENCIL;
rType = D3DRTYPE_SURFACE;
}
if( inOutAutogenMips )
usage |= D3DUSAGE_AUTOGENMIPMAP;
#endif
// Early-check to see if the enum translation table has an unsupported value
if(texFormat == (_D3DFORMAT)GFX_UNSUPPORTED_VAL)
return false;
HRESULT hr = pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
adapterFormat, usage, rType, texFormat );
bool retVal = SUCCEEDED( hr );
#if !defined(TORQUE_OS_XENON)
// If check device format failed, and auto gen mips were requested, try again
// without autogen mips.
if( !retVal && inOutAutogenMips )
{
usage ^= D3DUSAGE_AUTOGENMIPMAP;
hr = pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
adapterFormat, usage, D3DRTYPE_TEXTURE, GFXD3D9TextureFormat[fmt] );
retVal = SUCCEEDED( hr );
// If this one passed, auto gen mips are not supported with this format,
// so set the variable properly
if( retVal )
inOutAutogenMips = false;
}
#endif
return retVal;
}

View file

@ -0,0 +1,51 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9CARDPROFILER_H_
#define _GFXD3D9CARDPROFILER_H_
#include "gfx/gfxCardProfile.h"
struct IDirect3DDevice9;
class GFXD3D9CardProfiler : public GFXCardProfiler
{
private:
typedef GFXCardProfiler Parent;
IDirect3DDevice9 *mD3DDevice;
UINT mAdapterOrdinal;
public:
GFXD3D9CardProfiler();
~GFXD3D9CardProfiler();
void init();
protected:
const String &getRendererString() const { static String sRS("D3D9"); return sRS; }
void setupCardCapabilities();
bool _queryCardCap(const String &query, U32 &foundResult);
bool _queryFormat(const GFXFormat fmt, const GFXTextureProfile *profile, bool &inOutAutogenMips);
};
#endif

View file

@ -0,0 +1,239 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Cubemap.h"
#include "gfx/gfxTextureManager.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
_D3DCUBEMAP_FACES GFXD3D9Cubemap::faceList[6] =
{
D3DCUBEMAP_FACE_POSITIVE_X, D3DCUBEMAP_FACE_NEGATIVE_X,
D3DCUBEMAP_FACE_POSITIVE_Y, D3DCUBEMAP_FACE_NEGATIVE_Y,
D3DCUBEMAP_FACE_POSITIVE_Z, D3DCUBEMAP_FACE_NEGATIVE_Z
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
GFXD3D9Cubemap::GFXD3D9Cubemap()
{
mCubeTex = NULL;
mDynamic = false;
mFaceFormat = GFXFormatR8G8B8A8;
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
GFXD3D9Cubemap::~GFXD3D9Cubemap()
{
releaseSurfaces();
if ( mDynamic )
GFXTextureManager::removeEventDelegate( this, &GFXD3D9Cubemap::_onTextureEvent );
}
//-----------------------------------------------------------------------------
// Release D3D surfaces
//-----------------------------------------------------------------------------
void GFXD3D9Cubemap::releaseSurfaces()
{
if ( !mCubeTex )
return;
mCubeTex->Release();
mCubeTex = NULL;
}
void GFXD3D9Cubemap::_onTextureEvent( GFXTexCallbackCode code )
{
// Can this happen?
if ( !mDynamic )
return;
if ( code == GFXZombify )
releaseSurfaces();
else if ( code == GFXResurrect )
initDynamic( mTexSize );
}
//-----------------------------------------------------------------------------
// Init Static
//-----------------------------------------------------------------------------
void GFXD3D9Cubemap::initStatic( GFXTexHandle *faces )
{
//if( mCubeTex )
// return;
if( faces )
{
AssertFatal( faces[0], "empty texture passed to CubeMap::create" );
GFXD3D9Device *dev = static_cast<GFXD3D9Device *>(GFX);
D3DPOOL pool = D3DPOOL_MANAGED;
if (dev->isD3D9Ex())
pool = D3DPOOL_DEFAULT;
LPDIRECT3DDEVICE9 D3D9Device = dev->getDevice();
// NOTE - check tex sizes on all faces - they MUST be all same size
mTexSize = faces[0].getWidth();
mFaceFormat = faces[0].getFormat();
D3D9Assert( D3D9Device->CreateCubeTexture( mTexSize, 1, 0, GFXD3D9TextureFormat[mFaceFormat],
pool, &mCubeTex, NULL ), NULL );
fillCubeTextures( faces, D3D9Device );
// mCubeTex->GenerateMipSubLevels();
}
}
void GFXD3D9Cubemap::initStatic( DDSFile *dds )
{
AssertFatal( dds, "GFXD3D9Cubemap::initStatic - Got null DDS file!" );
AssertFatal( dds->isCubemap(), "GFXD3D9Cubemap::initStatic - Got non-cubemap DDS file!" );
AssertFatal( dds->mSurfaces.size() == 6, "GFXD3D9Cubemap::initStatic - DDS has less than 6 surfaces!" );
GFXD3D9Device *dev = static_cast<GFXD3D9Device *>(GFX);
D3DPOOL pool = D3DPOOL_MANAGED;
if (dev->isD3D9Ex())
pool = D3DPOOL_DEFAULT;
LPDIRECT3DDEVICE9 D3D9Device = dev->getDevice();
// NOTE - check tex sizes on all faces - they MUST be all same size
mTexSize = dds->getWidth();
mFaceFormat = dds->getFormat();
U32 levels = dds->getMipLevels();
D3D9Assert( D3D9Device->CreateCubeTexture( mTexSize, levels, 0, GFXD3D9TextureFormat[mFaceFormat],
pool, &mCubeTex, NULL ), NULL );
for( U32 i=0; i < 6; i++ )
{
if ( !dds->mSurfaces[i] )
{
// TODO: The DDS can skip surfaces, but i'm unsure what i should
// do here when creating the cubemap. Ignore it for now.
continue;
}
// Now loop thru the mip levels!
for( U32 l = 0; l < levels; l++ )
{
IDirect3DSurface9 *cubeSurf = NULL;
D3D9Assert( mCubeTex->GetCubeMapSurface( faceList[i], l, &cubeSurf ),
"GFXD3D9Cubemap::initStatic - Get cubemap surface failed!" );
// Lock the dest surface.
D3DLOCKED_RECT lockedRect;
D3D9Assert( cubeSurf->LockRect( &lockedRect, NULL, 0 ),
"GFXD3D9Cubemap::initStatic - Failed to lock surface level for load!" );
dMemcpy( lockedRect.pBits, dds->mSurfaces[i]->mMips[l], dds->getSurfaceSize(l) );
cubeSurf->UnlockRect();
cubeSurf->Release();
}
}
}
//-----------------------------------------------------------------------------
// Init Dynamic
//-----------------------------------------------------------------------------
void GFXD3D9Cubemap::initDynamic( U32 texSize, GFXFormat faceFormat )
{
if ( mCubeTex )
return;
if ( !mDynamic )
GFXTextureManager::addEventDelegate( this, &GFXD3D9Cubemap::_onTextureEvent );
mDynamic = true;
mTexSize = texSize;
mFaceFormat = faceFormat;
LPDIRECT3DDEVICE9 D3D9Device = reinterpret_cast<GFXD3D9Device *>(GFX)->getDevice();
// might want to try this as a 16 bit texture...
D3D9Assert( D3D9Device->CreateCubeTexture( texSize,
1,
#ifdef TORQUE_OS_XENON
0,
#else
D3DUSAGE_RENDERTARGET,
#endif
GFXD3D9TextureFormat[faceFormat],
D3DPOOL_DEFAULT,
&mCubeTex,
NULL ), NULL );
}
//-----------------------------------------------------------------------------
// Fills in face textures of cube map from existing textures
//-----------------------------------------------------------------------------
void GFXD3D9Cubemap::fillCubeTextures( GFXTexHandle *faces, LPDIRECT3DDEVICE9 D3DDevice )
{
for( U32 i=0; i<6; i++ )
{
// get cube face surface
IDirect3DSurface9 *cubeSurf = NULL;
D3D9Assert( mCubeTex->GetCubeMapSurface( faceList[i], 0, &cubeSurf ), NULL );
// get incoming texture surface
GFXD3D9TextureObject *texObj = dynamic_cast<GFXD3D9TextureObject*>( (GFXTextureObject*)faces[i] );
IDirect3DSurface9 *inSurf;
D3D9Assert( texObj->get2DTex()->GetSurfaceLevel( 0, &inSurf ), NULL );
// copy incoming texture into cube face
D3D9Assert( GFXD3DX.D3DXLoadSurfaceFromSurface( cubeSurf, NULL, NULL, inSurf, NULL,
NULL, D3DX_FILTER_NONE, 0 ), NULL );
cubeSurf->Release();
inSurf->Release();
}
}
//-----------------------------------------------------------------------------
// Set the cubemap to the specified texture unit num
//-----------------------------------------------------------------------------
void GFXD3D9Cubemap::setToTexUnit( U32 tuNum )
{
static_cast<GFXD3D9Device *>(GFX)->getDevice()->SetTexture( tuNum, mCubeTex );
}
void GFXD3D9Cubemap::zombify()
{
// Static cubemaps are handled by D3D
if( mDynamic )
releaseSurfaces();
}
void GFXD3D9Cubemap::resurrect()
{
// Static cubemaps are handled by D3D
if( mDynamic )
initDynamic( mTexSize, mFaceFormat );
}

View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9CUBEMAP_H_
#define _GFXD3D9CUBEMAP_H_
#include "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/gfxCubemap.h"
#include "gfx/gfxResource.h"
#include "gfx/gfxTarget.h"
//**************************************************************************
// Cube map
//**************************************************************************
class GFXD3D9Cubemap : public GFXCubemap
{
public:
virtual void initStatic( GFXTexHandle *faces );
virtual void initStatic( DDSFile *dds );
virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 );
virtual void setToTexUnit( U32 tuNum );
virtual U32 getSize() const { return mTexSize; }
virtual GFXFormat getFormat() const { return mFaceFormat; }
GFXD3D9Cubemap();
virtual ~GFXD3D9Cubemap();
// GFXResource interface
virtual void zombify();
virtual void resurrect();
protected:
friend class GFXPCD3D9TextureTarget;
friend class GFX360TextureTarget;
friend class GFXD3D9Device;
LPDIRECT3DCUBETEXTURE9 mCubeTex;
static _D3DCUBEMAP_FACES faceList[6];
bool mDynamic;
U32 mTexSize;
GFXFormat mFaceFormat;
void fillCubeTextures( GFXTexHandle *faces, LPDIRECT3DDEVICE9 D3DDevice );
void releaseSurfaces();
/// The callback used to get texture events.
/// @see GFXTextureManager::addEventDelegate
void _onTextureEvent( GFXTexCallbackCode code );
};
#endif // GFXD3D9CUBEMAP

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,357 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9DEVICE_H_
#define _GFXD3D9DEVICE_H_
#include "platform/tmm_off.h"
#ifdef TORQUE_OS_XENON
# include "platformXbox/platformXbox.h"
#else
# include <d3dx9.h>
# include "platformWin32/platformWin32.h"
#endif
#ifndef _GFXD3D9STATEBLOCK_H_
#include "gfx/D3D9/gfxD3D9StateBlock.h"
#endif
#ifndef _GFXD3DTEXTUREMANAGER_H_
#include "gfx/D3D9/gfxD3D9TextureManager.h"
#endif
#ifndef _GFXD3D9CUBEMAP_H_
#include "gfx/D3D9/gfxD3D9Cubemap.h"
#endif
#ifndef _GFXD3D9PRIMITIVEBUFFER_H_
#include "gfx/D3D9/gfxD3D9PrimitiveBuffer.h"
#endif
#ifndef _GFXINIT_H_
#include "gfx/gfxInit.h"
#endif
#ifndef _PLATFORMDLIBRARY_H
#include "platform/platformDlibrary.h"
#endif
#ifndef TORQUE_OS_XENON
#include <DxErr.h>
#else
#include <dxerr9.h>
#define DXGetErrorStringA DXGetErrorString9A
#define DXGetErrorDescriptionA DXGetErrorDescription9A
#endif
#include "platform/tmm_on.h"
inline void D3D9Assert( HRESULT hr, const char *info )
{
#if defined( TORQUE_DEBUG )
if( FAILED( hr ) )
{
char buf[256];
dSprintf( buf, 256, "%s\n%s\n%s", DXGetErrorStringA( hr ), DXGetErrorDescriptionA( hr ), info );
AssertFatal( false, buf );
// DXTrace( __FILE__, __LINE__, hr, info, true );
}
#endif
}
// Typedefs
#define D3DX_FUNCTION(fn_name, fn_return, fn_args) \
typedef fn_return (WINAPI *D3DXFNPTR##fn_name##)##fn_args##;
#include "gfx/D3D9/d3dx9Functions.h"
#undef D3DX_FUNCTION
// Function table
struct D3DXFNTable
{
D3DXFNTable() : isLoaded( false ){};
bool isLoaded;
DLibraryRef dllRef;
DLibraryRef compilerDllRef;
#define D3DX_FUNCTION(fn_name, fn_return, fn_args) \
D3DXFNPTR##fn_name fn_name;
#include "gfx/D3D9/d3dx9Functions.h"
#undef D3DX_FUNCTION
};
#define GFXD3DX static_cast<GFXD3D9Device *>(GFX)->smD3DX
class GFXResource;
class GFXD3D9ShaderConstBuffer;
//------------------------------------------------------------------------------
class GFXD3D9Device : public GFXDevice
{
friend class GFXResource;
friend class GFXD3D9PrimitiveBuffer;
friend class GFXD3D9VertexBuffer;
friend class GFXD3D9TextureObject;
friend class GFXPCD3D9TextureTarget;
friend class GFXPCD3D9WindowTarget;
typedef GFXDevice Parent;
protected:
MatrixF mTempMatrix; ///< Temporary matrix, no assurances on value at all
RectI mClipRect;
typedef StrongRefPtr<GFXD3D9VertexBuffer> RPGDVB;
Vector<RPGDVB> mVolatileVBList;
class D3D9VertexDecl : public GFXVertexDecl
{
public:
virtual ~D3D9VertexDecl()
{
SAFE_RELEASE( decl );
}
IDirect3DVertexDeclaration9 *decl;
};
/// Used to lookup a vertex declaration for the vertex format.
/// @see allocVertexDecl
typedef Map<String,D3D9VertexDecl*> VertexDeclMap;
VertexDeclMap mVertexDecls;
IDirect3DSurface9 *mDeviceBackbuffer;
IDirect3DSurface9 *mDeviceDepthStencil;
IDirect3DSurface9 *mDeviceColor;
/// The stream 0 vertex buffer used for volatile VB offseting.
GFXD3D9VertexBuffer *mVolatileVB;
static void initD3DXFnTable();
//-----------------------------------------------------------------------
StrongRefPtr<GFXD3D9PrimitiveBuffer> mDynamicPB; ///< Dynamic index buffer
GFXD3D9PrimitiveBuffer *mCurrentPB;
IDirect3DVertexShader9 *mLastVertShader;
IDirect3DPixelShader9 *mLastPixShader;
S32 mCreateFenceType;
LPDIRECT3D9 mD3D; ///< D3D Handle
LPDIRECT3DDEVICE9 mD3DDevice; ///< Handle for D3DDevice
#if !defined(TORQUE_OS_XENON)
LPDIRECT3D9EX mD3DEx; ///< D3D9Ex Handle
LPDIRECT3DDEVICE9EX mD3DDeviceEx; ///< Handle for D3DDevice9Ex
#endif
U32 mAdapterIndex; ///< Adapter index because D3D supports multiple adapters
F32 mPixVersion;
U32 mNumSamplers; ///< Profiled (via caps)
U32 mNumRenderTargets; ///< Profiled (via caps)
D3DMULTISAMPLE_TYPE mMultisampleType;
DWORD mMultisampleLevel;
bool mOcclusionQuerySupported;
/// The current adapter display mode.
D3DDISPLAYMODE mDisplayMode;
/// To manage creating and re-creating of these when device is aquired
void reacquireDefaultPoolResources();
/// To release all resources we control from D3DPOOL_DEFAULT
void releaseDefaultPoolResources();
/// This you will probably never, ever use, but it is used to generate the code for
/// the initStates() function
void regenStates();
virtual GFXD3D9VertexBuffer* findVBPool( const GFXVertexFormat *vertexFormat, U32 numVertsNeeded );
virtual GFXD3D9VertexBuffer* createVBPool( const GFXVertexFormat *vertexFormat, U32 vertSize );
#ifdef TORQUE_DEBUG
/// @name Debug Vertex Buffer information/management
/// @{
///
U32 mNumAllocatedVertexBuffers; ///< To keep track of how many are allocated and freed
GFXD3D9VertexBuffer *mVBListHead;
void addVertexBuffer( GFXD3D9VertexBuffer *buffer );
void removeVertexBuffer( GFXD3D9VertexBuffer *buffer );
void logVertexBuffers();
/// @}
#endif
// State overrides
// {
///
virtual void setTextureInternal(U32 textureUnit, const GFXTextureObject* texture);
/// Called by GFXDevice to create a device specific stateblock
virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc);
/// Called by GFXDevice to actually set a stateblock.
virtual void setStateBlockInternal(GFXStateBlock* block, bool force);
/// Track the last const buffer we've used. Used to notify new constant buffers that
/// they should send all of their constants up
StrongRefPtr<GFXD3D9ShaderConstBuffer> mCurrentConstBuffer;
/// Called by base GFXDevice to actually set a const buffer
virtual void setShaderConstBufferInternal(GFXShaderConstBuffer* buffer);
// CodeReview - How exactly do we want to deal with this on the Xenon?
// Right now it's just in an #ifndef in gfxD3D9Device.cpp - AlexS 4/11/07
virtual void setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable);
virtual void setLightMaterialInternal(const GFXLightMaterial mat);
virtual void setGlobalAmbientInternal(ColorF color);
virtual void initStates()=0;
// }
// Index buffer management
// {
virtual void _setPrimitiveBuffer( GFXPrimitiveBuffer *buffer );
virtual void drawIndexedPrimitive( GFXPrimitiveType primType,
U32 startVertex,
U32 minIndex,
U32 numVerts,
U32 startIndex,
U32 primitiveCount );
// }
virtual GFXShader* createShader();
/// Device helper function
virtual D3DPRESENT_PARAMETERS setupPresentParams( const GFXVideoMode &mode, const HWND &hwnd ) const = 0;
public:
static D3DXFNTable smD3DX;
static GFXDevice *createInstance( U32 adapterIndex );
GFXTextureObject* createRenderSurface( U32 width, U32 height, GFXFormat format, U32 mipLevel );
const D3DDISPLAYMODE& getDisplayMode() const { return mDisplayMode; }
/// Constructor
/// @param d3d Direct3D object to instantiate this device with
/// @param index Adapter index since D3D can use multiple graphics adapters
GFXD3D9Device( LPDIRECT3D9 d3d, U32 index );
virtual ~GFXD3D9Device();
// Activate/deactivate
// {
virtual void init( const GFXVideoMode &mode, PlatformWindow *window = NULL ) = 0;
virtual void preDestroy() { Parent::preDestroy(); if(mTextureManager) mTextureManager->kill(); }
GFXAdapterType getAdapterType(){ return Direct3D9; }
virtual GFXCubemap *createCubemap();
virtual F32 getPixelShaderVersion() const { return mPixVersion; }
virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version; }
virtual void disableShaders();
virtual void setShader( GFXShader *shader );
virtual U32 getNumSamplers() const { return mNumSamplers; }
virtual U32 getNumRenderTargets() const { return mNumRenderTargets; }
// }
// Misc rendering control
// {
virtual void clear( U32 flags, ColorI color, F32 z, U32 stencil );
virtual bool beginSceneInternal();
virtual void endSceneInternal();
virtual void setClipRect( const RectI &rect );
virtual const RectI& getClipRect() const { return mClipRect; }
// }
/// @name Render Targets
/// @{
virtual void _updateRenderTargets();
/// @}
// Vertex/Index buffer management
// {
virtual GFXVertexBuffer* allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType );
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType );
virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff );
virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
virtual void setVertexDecl( const GFXVertexDecl *decl );
virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer );
virtual void setVertexStreamFrequency( U32 stream, U32 frequency );
// }
virtual U32 getMaxDynamicVerts() { return MAX_DYNAMIC_VERTS; }
virtual U32 getMaxDynamicIndices() { return MAX_DYNAMIC_INDICES; }
// Rendering
// {
virtual void drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount );
// }
virtual LPDIRECT3DDEVICE9 getDevice(){ return mD3DDevice; }
virtual LPDIRECT3D9 getD3D() { return mD3D; }
/// Reset
virtual void reset( D3DPRESENT_PARAMETERS &d3dpp ) = 0;
GFXShaderRef mGenericShader[GS_COUNT];
virtual void setupGenericShaders( GenericShaderType type = GSColor );
// Function only really used on the, however a centralized function for
// destroying resources is probably a good thing -patw
virtual void destroyD3DResource( IDirect3DResource9 *d3dResource ) { SAFE_RELEASE( d3dResource ); };
inline virtual F32 getFillConventionOffset() const { return 0.5f; }
virtual void doParanoidStateCheck();
GFXFence *createFence();
GFXOcclusionQuery* createOcclusionQuery();
// Default multisample parameters
D3DMULTISAMPLE_TYPE getMultisampleType() const { return mMultisampleType; }
DWORD getMultisampleLevel() const { return mMultisampleLevel; }
// Whether or not the Direct3D device was created with Direct3D9Ex support
#if !defined(TORQUE_OS_XENON)
virtual bool isD3D9Ex() { return mD3DEx != NULL; }
#else
virtual bool isD3D9Ex() { return false; }
#endif
// Get the backbuffer, currently only access for WPF support
virtual IDirect3DSurface9* getBackBuffer() { return mDeviceBackbuffer; }
};
#endif // _GFXD3D9DEVICE_H_

View file

@ -0,0 +1,92 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "console/console.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
// Cut and paste from console.log into GFXD3D9Device::initStates()
void GFXD3D9Device::regenStates()
{
DWORD temp;
Con::printf( " //-------------------------------------" );
Con::printf( " // Auto-generated default states, see regenStates() for details" );
Con::printf( " //" );
Con::printf( "" );
Con::printf( " // Render states" );
for( U32 state = GFXRenderState_FIRST; state < GFXRenderState_COUNT; state++ )
{
if( GFXD3D9RenderState[state] == GFX_UNSUPPORTED_VAL )
continue;
temp = 0;
mD3DDevice->GetRenderState( GFXD3D9RenderState[state], &temp );
Con::printf( " mD3DDevice->SetRenderState( GFXD3D9RenderState[%d], %d );", state, temp );
}
#ifndef TORQUE_OS_XENON
Con::printf( "" );
Con::printf( " // Texture Stage states" );
for( U32 stage = 0; stage < TEXTURE_STAGE_COUNT; stage++ )
{
if( stage >= GFX->getNumSamplers() )
{
Con::errorf( "Sampler %d out of range for this device, ignoring.", stage );
break;
}
for( U32 state = GFXTSS_FIRST; state < GFXTSS_COUNT; state++ )
{
if( GFXD3D9TextureStageState[state] == GFX_UNSUPPORTED_VAL )
continue;
temp = 0;
mD3DDevice->GetTextureStageState( stage, GFXD3D9TextureStageState[state], &temp );
Con::printf( " mD3DDevice->SetTextureStageState( %d, GFXD3D9TextureStageState[%d], %d );", stage, state, temp );
}
}
#endif
Con::printf( "" );
Con::printf( " // Sampler states" );
for( U32 stage = 0; stage < TEXTURE_STAGE_COUNT; stage++ )
{
if( stage >= GFX->getNumSamplers() )
{
Con::errorf( "Sampler %d out of range for this device, ignoring.", stage );
break;
}
for( U32 state = GFXSAMP_FIRST; state < GFXSAMP_COUNT; state++ )
{
if( GFXD3D9SamplerState[state] == GFX_UNSUPPORTED_VAL )
continue;
temp = 0;
mD3DDevice->GetSamplerState( stage, GFXD3D9SamplerState[state], &temp );
Con::printf( " mD3DDevice->SetSamplerState( %d, GFXD3D9SamplerState[%d], %d );", stage, state, temp );
}
}
}

View file

@ -0,0 +1,63 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Shader.h"
#include "gfx/gfxEnums.h"
//------------------------------------------------------------------------------
namespace GFXD3D9EnumTranslate
{
void init();
};
//------------------------------------------------------------------------------
extern _D3DFORMAT GFXD3D9IndexFormat[GFXIndexFormat_COUNT];
extern _D3DSAMPLERSTATETYPE GFXD3D9SamplerState[GFXSAMP_COUNT];
extern _D3DFORMAT GFXD3D9TextureFormat[GFXFormat_COUNT];
#ifdef TORQUE_OS_XENON
extern _D3DFORMAT GFXD3D9RenderTargetFormat[GFXFormat_COUNT];
#endif
extern _D3DRENDERSTATETYPE GFXD3D9RenderState[GFXRenderState_COUNT];
extern _D3DTEXTUREFILTERTYPE GFXD3D9TextureFilter[GFXTextureFilter_COUNT];
extern _D3DBLEND GFXD3D9Blend[GFXBlend_COUNT];
extern _D3DBLENDOP GFXD3D9BlendOp[GFXBlendOp_COUNT];
extern _D3DSTENCILOP GFXD3D9StencilOp[GFXStencilOp_COUNT];
extern _D3DCMPFUNC GFXD3D9CmpFunc[GFXCmp_COUNT];
extern _D3DCULL GFXD3D9CullMode[GFXCull_COUNT];
extern _D3DFILLMODE GFXD3D9FillMode[GFXFill_COUNT];
extern _D3DPRIMITIVETYPE GFXD3D9PrimType[GFXPT_COUNT];
extern _D3DTEXTURESTAGESTATETYPE GFXD3D9TextureStageState[GFXTSS_COUNT];
extern _D3DTEXTUREADDRESS GFXD3D9TextureAddress[GFXAddress_COUNT];
extern _D3DTEXTUREOP GFXD3D9TextureOp[GFXTOP_COUNT];
extern _D3DDECLTYPE GFXD3D9DeclType[GFXDeclType_COUNT];
#define GFXREVERSE_LOOKUP( tablearray, enumprefix, val ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
if( (int)tablearray##[i] == val ) \
{ \
val = i; \
break; \
} \

View file

@ -0,0 +1,163 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9OcclusionQuery.h"
#include "gui/3d/guiTSControl.h"
#ifdef TORQUE_GATHER_METRICS
// For TickMs define
#include "T3D/gameBase/processList.h"
#endif
GFXD3D9OcclusionQuery::GFXD3D9OcclusionQuery( GFXDevice *device )
: GFXOcclusionQuery( device ),
mQuery( NULL )
{
#ifdef TORQUE_GATHER_METRICS
mTimer = PlatformTimer::create();
mTimer->getElapsedMs();
mTimeSinceEnd = 0;
mBeginFrame = 0;
#endif
}
GFXD3D9OcclusionQuery::~GFXD3D9OcclusionQuery()
{
SAFE_RELEASE( mQuery );
#ifdef TORQUE_GATHER_METRICS
SAFE_DELETE( mTimer );
#endif
}
bool GFXD3D9OcclusionQuery::begin()
{
if ( GFXDevice::getDisableOcclusionQuery() )
return true;
if ( mQuery == NULL )
{
#ifdef TORQUE_OS_XENON
HRESULT hRes = static_cast<GFXD3D9Device*>( mDevice )->getDevice()->CreateQueryTiled( D3DQUERYTYPE_OCCLUSION, 2, &mQuery );
#else
HRESULT hRes = static_cast<GFXD3D9Device*>( mDevice )->getDevice()->CreateQuery( D3DQUERYTYPE_OCCLUSION, &mQuery );
#endif
AssertFatal( hRes != D3DERR_NOTAVAILABLE, "GFXD3D9OcclusionQuery::begin - Hardware does not support D3D9 Occlusion-Queries, this should be caught before this type is created" );
AssertISV( hRes != E_OUTOFMEMORY, "GFXD3D9OcclusionQuery::begin - Out of memory" );
}
// Add a begin marker to the command buffer queue.
mQuery->Issue( D3DISSUE_BEGIN );
#ifdef TORQUE_GATHER_METRICS
mBeginFrame = GuiTSCtrl::getFrameCount();
#endif
return true;
}
void GFXD3D9OcclusionQuery::end()
{
if ( GFXDevice::getDisableOcclusionQuery() )
return;
// Add an end marker to the command buffer queue.
mQuery->Issue( D3DISSUE_END );
#ifdef TORQUE_GATHER_METRICS
AssertFatal( mBeginFrame == GuiTSCtrl::getFrameCount(), "GFXD3D9OcclusionQuery::end - ended query on different frame than begin!" );
mTimer->getElapsedMs();
mTimer->reset();
#endif
}
GFXD3D9OcclusionQuery::OcclusionQueryStatus GFXD3D9OcclusionQuery::getStatus( bool block, U32 *data )
{
// If this ever shows up near the top of a profile then your system is
// GPU bound or you are calling getStatus too soon after submitting it.
//
// To test if you are GPU bound resize your window very small and see if
// this profile no longer appears at the top.
//
// To test if you are calling getStatus to soon after submitting it,
// check the value of mTimeSinceEnd in a debug build. If it is < half the length
// of time to render an individual frame you could have problems.
PROFILE_SCOPE(GFXD3D9OcclusionQuery_getStatus);
if ( GFXDevice::getDisableOcclusionQuery() )
return NotOccluded;
if ( mQuery == NULL )
return Unset;
#ifdef TORQUE_GATHER_METRICS
AssertFatal( mBeginFrame < GuiTSCtrl::getFrameCount(), "GFXD3D9OcclusionQuery::getStatus - called on the same frame as begin!" );
//U32 mTimeSinceEnd = mTimer->getElapsedMs();
//AssertFatal( mTimeSinceEnd >= 5, "GFXD3DOcculsionQuery::getStatus - less than TickMs since called ::end!" );
#endif
HRESULT hRes;
DWORD dwOccluded = 0;
if ( block )
{
while( ( hRes = mQuery->GetData( &dwOccluded, sizeof(DWORD), D3DGETDATA_FLUSH ) ) == S_FALSE )
;
}
else
{
hRes = mQuery->GetData( &dwOccluded, sizeof(DWORD), 0 );
}
if ( hRes == S_OK )
{
if ( data != NULL )
*data = dwOccluded;
return dwOccluded > 0 ? NotOccluded : Occluded;
}
if ( hRes == S_FALSE )
return Waiting;
return Error;
}
void GFXD3D9OcclusionQuery::zombify()
{
SAFE_RELEASE( mQuery );
}
void GFXD3D9OcclusionQuery::resurrect()
{
}
const String GFXD3D9OcclusionQuery::describeSelf() const
{
// We've got nothing
return String();
}

View file

@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFX_D3D9_OCCLUSIONQUERY_H_
#define _GFX_D3D9_OCCLUSIONQUERY_H_
#ifndef _GFXOCCLUSIONQUERY_H_
#include "gfx/gfxOcclusionQuery.h"
#endif
#ifdef TORQUE_GATHER_METRICS
#ifndef _PLATFORM_PLATFORMTIMER_H_
#include "platform/platformTimer.h"
#endif
#endif
struct IDirect3DQuery9;
class GFXD3D9OcclusionQuery : public GFXOcclusionQuery
{
private:
mutable IDirect3DQuery9 *mQuery;
#ifdef TORQUE_GATHER_METRICS
U32 mBeginFrame;
U32 mTimeSinceEnd;
PlatformTimer *mTimer;
#endif
public:
GFXD3D9OcclusionQuery( GFXDevice *device );
virtual ~GFXD3D9OcclusionQuery();
virtual bool begin();
virtual void end();
virtual OcclusionQueryStatus getStatus( bool block, U32 *data = NULL );
// GFXResource
virtual void zombify();
virtual void resurrect();
virtual const String describeSelf() const;
};
#endif // _GFX_D3D9_OCCLUSIONQUERY_H_

View file

@ -0,0 +1,114 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#include "gfx/D3D9/gfxD3D9PrimitiveBuffer.h"
#include "core/util/safeRelease.h"
void GFXD3D9PrimitiveBuffer::prepare()
{
static_cast<GFXD3D9Device *>( mDevice )->_setPrimitiveBuffer(this);
}
void GFXD3D9PrimitiveBuffer::unlock()
{
#ifdef TORQUE_DEBUG
if ( mDebugGuardBuffer )
{
const U32 guardSize = sizeof( _PBGuardString );
// First check the guard areas for overwrites.
AssertFatal( dMemcmp( mDebugGuardBuffer, _PBGuardString, guardSize ) == 0,
"GFXD3D9PrimitiveBuffer::unlock - Caught lock memory underrun!" );
AssertFatal( dMemcmp( mDebugGuardBuffer + mLockedSize + guardSize, _PBGuardString, guardSize ) == 0,
"GFXD3D9PrimitiveBuffer::unlock - Caught lock memory overrun!" );
// Copy the debug content down to the real PB.
dMemcpy( mLockedBuffer, mDebugGuardBuffer + guardSize, mLockedSize );
// Cleanup.
delete [] mDebugGuardBuffer;
mDebugGuardBuffer = NULL;
mLockedBuffer = NULL;
mLockedSize = 0;
}
#endif // TORQUE_DEBUG
ib->Unlock();
mLocked = false;
mIsFirstLock = false;
mVolatileBuffer = NULL;
}
GFXD3D9PrimitiveBuffer::~GFXD3D9PrimitiveBuffer()
{
if( mBufferType != GFXBufferTypeVolatile )
{
#if defined(TORQUE_OS_XENON)
if(ib->IsSet(reinterpret_cast<GFXD3D9Device *>(mDevice)->mD3DDevice))
{
reinterpret_cast<GFXD3D9Device *>(mDevice)->mD3DDevice->SetIndices(NULL);
}
#endif
SAFE_RELEASE( ib );
}
}
void GFXD3D9PrimitiveBuffer::zombify()
{
if(mBufferType == GFXBufferTypeStatic)
return;
AssertFatal(!mLocked, "GFXD3D9PrimitiveBuffer::zombify - Cannot zombify a locked buffer!");
if (mBufferType == GFXBufferTypeVolatile)
{
// We must null the volatile buffer else we're holding
// a dead pointer which can be set on the device.
ib = NULL;
return;
}
// Dynamic buffers get released.
SAFE_RELEASE(ib);
}
void GFXD3D9PrimitiveBuffer::resurrect()
{
if ( mBufferType != GFXBufferTypeDynamic )
return;
U32 usage = D3DUSAGE_WRITEONLY;
#ifndef TORQUE_OS_XENON
usage |= D3DUSAGE_DYNAMIC;
#endif
D3DPOOL pool = D3DPOOL_DEFAULT;
D3D9Assert(static_cast<GFXD3D9Device*>(mDevice)->mD3DDevice->CreateIndexBuffer( sizeof(U16) * mIndexCount ,
usage , GFXD3D9IndexFormat[GFXIndexFormat16], pool, &ib, 0),
"GFXD3D9PrimitiveBuffer::resurrect - Failed to allocate an index buffer.");
}

View file

@ -0,0 +1,88 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9PRIMITIVEBUFFER_H_
#define _GFXD3D9PRIMITIVEBUFFER_H_
#ifndef _GFXPRIMITIVEBUFFER_H_
#include "gfx/gfxPrimitiveBuffer.h"
#endif
struct IDirect3DIndexBuffer9;
class GFXD3D9PrimitiveBuffer : public GFXPrimitiveBuffer
{
public:
IDirect3DIndexBuffer9 *ib;
StrongRefPtr<GFXD3D9PrimitiveBuffer> mVolatileBuffer;
U32 mVolatileStart;
#ifdef TORQUE_DEBUG
#define _PBGuardString "GFX_PRIMTIVE_BUFFER_GUARD_STRING"
U8 *mDebugGuardBuffer;
void *mLockedBuffer;
U32 mLockedSize;
#endif TORQUE_DEBUG
bool mLocked;
bool mIsFirstLock;
GFXD3D9PrimitiveBuffer( GFXDevice *device,
U32 indexCount,
U32 primitiveCount,
GFXBufferType bufferType );
virtual ~GFXD3D9PrimitiveBuffer();
virtual void lock(U32 indexStart, U32 indexEnd, void **indexPtr);
virtual void unlock();
virtual void prepare();
#ifdef TORQUE_DEBUG
//GFXD3D9PrimitiveBuffer *next;
#endif
// GFXResource interface
virtual void zombify();
virtual void resurrect();
};
inline GFXD3D9PrimitiveBuffer::GFXD3D9PrimitiveBuffer( GFXDevice *device,
U32 indexCount,
U32 primitiveCount,
GFXBufferType bufferType )
: GFXPrimitiveBuffer( device, indexCount, primitiveCount, bufferType )
{
mVolatileStart = 0;
ib = NULL;
mIsFirstLock = true;
mLocked = false;
#ifdef TORQUE_DEBUG
mDebugGuardBuffer = NULL;
mLockedBuffer = NULL;
mLockedSize = 0;
#endif
}
#endif

View file

@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9QueryFence.h"
GFXD3D9QueryFence::~GFXD3D9QueryFence()
{
SAFE_RELEASE( mQuery );
}
//------------------------------------------------------------------------------
void GFXD3D9QueryFence::issue()
{
PROFILE_START( GFXD3D9QueryFence_issue );
// Create the query if we need to
if( mQuery == NULL )
{
HRESULT hRes = static_cast<GFXD3D9Device *>( mDevice )->getDevice()->CreateQuery( D3DQUERYTYPE_EVENT, &mQuery );
AssertFatal( hRes != D3DERR_NOTAVAILABLE, "Hardware does not support D3D9 Queries, this should be caught before this fence type is created" );
AssertISV( hRes != E_OUTOFMEMORY, "Out of memory" );
}
// Issue the query
mQuery->Issue( D3DISSUE_END );
PROFILE_END();
}
//------------------------------------------------------------------------------
GFXFence::FenceStatus GFXD3D9QueryFence::getStatus() const
{
if( mQuery == NULL )
return GFXFence::Unset;
HRESULT hRes = mQuery->GetData( NULL, 0, 0 );
return ( hRes == S_OK ? GFXFence::Processed : GFXFence::Pending );
}
//------------------------------------------------------------------------------
void GFXD3D9QueryFence::block()
{
PROFILE_SCOPE(GFXD3D9QueryFence_block);
// Calling block() before issue() is valid, catch this case
if( mQuery == NULL )
return;
HRESULT hRes;
while( ( hRes = mQuery->GetData( NULL, 0, D3DGETDATA_FLUSH ) ) == S_FALSE )
;
// Check for D3DERR_DEVICELOST, if we lost the device, the fence will get
// re-created next issue()
if( hRes == D3DERR_DEVICELOST )
SAFE_RELEASE( mQuery );
}
void GFXD3D9QueryFence::zombify()
{
// Release our query
SAFE_RELEASE( mQuery );
}
void GFXD3D9QueryFence::resurrect()
{
// Recreate the query
if( mQuery == NULL )
{
HRESULT hRes = static_cast<GFXD3D9Device *>( mDevice )->getDevice()->CreateQuery( D3DQUERYTYPE_EVENT, &mQuery );
AssertFatal( hRes != D3DERR_NOTAVAILABLE, "GFXD3D9QueryFence::resurrect - Hardware does not support D3D9 Queries, this should be caught before this fence type is created" );
AssertISV( hRes != E_OUTOFMEMORY, "GFXD3D9QueryFence::resurrect - Out of memory" );
}
}
const String GFXD3D9QueryFence::describeSelf() const
{
// We've got nothing
return String();
}

View file

@ -0,0 +1,52 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFX_D3D9_QUERYFENCE_H_
#define _GFX_D3D9_QUERYFENCE_H_
#include "gfx/gfxFence.h"
#include "gfx/gfxResource.h"
struct IDirect3DQuery9;
class GFXD3D9QueryFence : public GFXFence
{
private:
mutable IDirect3DQuery9 *mQuery;
public:
GFXD3D9QueryFence( GFXDevice *device ) : GFXFence( device ), mQuery( NULL ) {};
virtual ~GFXD3D9QueryFence();
virtual void issue();
virtual FenceStatus getStatus() const;
virtual void block();
// GFXResource interface
virtual void zombify();
virtual void resurrect();
virtual const String describeSelf() const;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,287 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9SHADER_H_
#define _GFXD3D9SHADER_H_
#ifndef _PATH_H_
#include "core/util/path.h"
#endif
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
#ifndef _GFXRESOURCE_H_
#include "gfx/gfxResource.h"
#endif
#ifndef _GENERICCONSTBUFFER_H_
#include "gfx/genericConstBuffer.h"
#endif
class GFXD3D9Shader;
struct IDirect3DVertexShader9;
struct IDirect3DPixelShader9;
struct IDirect3DDevice9;
struct ID3DXConstantTable;
struct ID3DXBuffer;
struct _D3DXMACRO;
class GFXD3D9ShaderBufferLayout : public GenericConstBufferLayout
{
protected:
/// Set a matrix, given a base pointer
virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
};
/// The D3D9 implementation of a shader constant handle.
class GFXD3D9ShaderConstHandle : public GFXShaderConstHandle
{
public:
// GFXShaderConstHandle
const String& getName() const;
GFXShaderConstType getType() const;
U32 getArraySize() const;
WeakRefPtr<GFXD3D9Shader> mShader;
bool mVertexConstant;
GenericConstBufferLayout::ParamDesc mVertexHandle;
bool mPixelConstant;
GenericConstBufferLayout::ParamDesc mPixelHandle;
/// Is true if this constant is for hardware mesh instancing.
///
/// Note: We currently store its settings in mPixelHandle.
///
bool mInstancingConstant;
void setValid( bool valid ) { mValid = valid; }
S32 getSamplerRegister() const;
// Returns true if this is a handle to a sampler register.
bool isSampler() const
{
return ( mPixelConstant && mPixelHandle.constType >= GFXSCT_Sampler ) ||
( mVertexConstant && mVertexHandle.constType >= GFXSCT_Sampler );
}
/// Restore to uninitialized state.
void clear()
{
mShader = NULL;
mVertexConstant = false;
mPixelConstant = false;
mInstancingConstant = false;
mVertexHandle.clear();
mPixelHandle.clear();
mValid = false;
}
GFXD3D9ShaderConstHandle();
};
/// The D3D9 implementation of a shader constant buffer.
class GFXD3D9ShaderConstBuffer : public GFXShaderConstBuffer
{
friend class GFXD3D9Shader;
public:
GFXD3D9ShaderConstBuffer( GFXD3D9Shader* shader,
GFXD3D9ShaderBufferLayout* vertexLayoutF,
GFXD3D9ShaderBufferLayout* vertexLayoutI,
GFXD3D9ShaderBufferLayout* pixelLayoutF,
GFXD3D9ShaderBufferLayout* pixelLayoutI );
virtual ~GFXD3D9ShaderConstBuffer();
/// Called by GFXD3D9Device to activate this buffer.
/// @param mPrevShaderBuffer The previously active buffer
void activate( GFXD3D9ShaderConstBuffer *prevShaderBuffer );
/// Used internally by GXD3D9ShaderConstBuffer to determine if it's dirty.
bool isDirty();
/// Called from GFXD3D9Shader when constants have changed and need
/// to be the shader this buffer references is reloaded.
void onShaderReload( GFXD3D9Shader *shader );
// GFXShaderConstBuffer
virtual GFXShader* getShader();
virtual void set(GFXShaderConstHandle* handle, const F32 fv);
virtual void set(GFXShaderConstHandle* handle, const Point2F& fv);
virtual void set(GFXShaderConstHandle* handle, const Point3F& fv);
virtual void set(GFXShaderConstHandle* handle, const Point4F& fv);
virtual void set(GFXShaderConstHandle* handle, const PlaneF& fv);
virtual void set(GFXShaderConstHandle* handle, const ColorF& fv);
virtual void set(GFXShaderConstHandle* handle, const S32 f);
virtual void set(GFXShaderConstHandle* handle, const Point2I& fv);
virtual void set(GFXShaderConstHandle* handle, const Point3I& fv);
virtual void set(GFXShaderConstHandle* handle, const Point4I& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv);
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv);
virtual void set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType = GFXSCT_Float4x4);
virtual void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
// GFXResource
virtual const String describeSelf() const;
virtual void zombify();
virtual void resurrect();
protected:
template<class T>
inline void SET_CONSTANT( GFXShaderConstHandle* handle,
const T& fv,
GenericConstBuffer *vBuffer,
GenericConstBuffer *pBuffer );
/// A cached direct pointer to the device.
IDirect3DDevice9 *mDevice;
/// We keep a weak reference to the shader
/// because it will often be deleted.
WeakRefPtr<GFXD3D9Shader> mShader;
GFXD3D9ShaderBufferLayout* mVertexConstBufferLayoutF;
GenericConstBuffer* mVertexConstBufferF;
GFXD3D9ShaderBufferLayout* mPixelConstBufferLayoutF;
GenericConstBuffer* mPixelConstBufferF;
GFXD3D9ShaderBufferLayout* mVertexConstBufferLayoutI;
GenericConstBuffer* mVertexConstBufferI;
GFXD3D9ShaderBufferLayout* mPixelConstBufferLayoutI;
GenericConstBuffer* mPixelConstBufferI;
};
class _gfxD3DXInclude;
typedef StrongRefPtr<_gfxD3DXInclude> _gfxD3DXIncludeRef;
/// The D3D9 implementation of a shader.
class GFXD3D9Shader : public GFXShader
{
friend class GFXD3D9Device;
friend class GFX360Device;
friend class GFXD3D9ShaderConstBuffer;
friend class GFX360ShaderConstBuffer;
public:
typedef Map<String, GFXD3D9ShaderConstHandle*> HandleMap;
GFXD3D9Shader();
virtual ~GFXD3D9Shader();
// GFXShader
virtual GFXShaderConstBufferRef allocConstBuffer();
virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
virtual U32 getAlignmentValue(const GFXShaderConstType constType) const;
virtual bool getDisassembly( String &outStr ) const;
// GFXResource
virtual void zombify();
virtual void resurrect();
protected:
virtual bool _init();
static const U32 smCompiledShaderTag;
IDirect3DDevice9 *mD3D9Device;
IDirect3DVertexShader9 *mVertShader;
IDirect3DPixelShader9 *mPixShader;
GFXD3D9ShaderBufferLayout* mVertexConstBufferLayoutF;
GFXD3D9ShaderBufferLayout* mPixelConstBufferLayoutF;
GFXD3D9ShaderBufferLayout* mVertexConstBufferLayoutI;
GFXD3D9ShaderBufferLayout* mPixelConstBufferLayoutI;
static _gfxD3DXIncludeRef smD3DXInclude;
HandleMap mHandles;
/// The shader disassembly from DX when this shader is compiled.
/// We only store this data in non-release builds.
String mDissasembly;
/// Vector of sampler type descriptions consolidated from _compileShader.
Vector<GFXShaderConstDesc> mSamplerDescriptions;
/// Vector of descriptions (consolidated for the getShaderConstDesc call)
Vector<GFXShaderConstDesc> mShaderConsts;
// These two functions are used when compiling shaders from hlsl
virtual bool _compileShader( const Torque::Path &filePath,
const String &target,
const _D3DXMACRO *defines,
GenericConstBufferLayout *bufferLayoutF,
GenericConstBufferLayout *bufferLayoutI,
Vector<GFXShaderConstDesc> &samplerDescriptions );
void _getShaderConstants( ID3DXConstantTable* table,
GenericConstBufferLayout *bufferLayoutF,
GenericConstBufferLayout *bufferLayoutI,
Vector<GFXShaderConstDesc> &samplerDescriptions );
bool _saveCompiledOutput( const Torque::Path &filePath,
ID3DXBuffer *buffer,
GenericConstBufferLayout *bufferLayoutF,
GenericConstBufferLayout *bufferLayoutI,
Vector<GFXShaderConstDesc> &samplerDescriptions );
// Loads precompiled shaders
bool _loadCompiledOutput( const Torque::Path &filePath,
const String &target,
GenericConstBufferLayout *bufferLayoutF,
GenericConstBufferLayout *bufferLayoutI,
Vector<GFXShaderConstDesc> &samplerDescriptions );
// This is used in both cases
virtual void _buildShaderConstantHandles( GenericConstBufferLayout *layout, bool vertexConst );
virtual void _buildSamplerShaderConstantHandles( Vector<GFXShaderConstDesc> &samplerDescriptions );
/// Used to build the instancing shader constants from
/// the instancing vertex format.
void _buildInstancingShaderConstantHandles();
};
inline bool GFXD3D9Shader::getDisassembly( String &outStr ) const
{
outStr = mDissasembly;
return ( outStr.isNotEmpty() );
}
#endif // _GFXD3D9SHADER_H_

View file

@ -0,0 +1,203 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxDevice.h"
#if defined(TORQUE_OS_XENON)
# include <xtl.h>
#else
# include <d3d9.h>
#endif
#include "gfx/D3D9/gfxD3D9StateBlock.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
GFXD3D9StateBlock::GFXD3D9StateBlock(const GFXStateBlockDesc& desc, LPDIRECT3DDEVICE9 d3dDevice)
{
AssertFatal(d3dDevice, "Invalid mD3DDevice!");
mDesc = desc;
mCachedHashValue = desc.getHashValue();
mD3DDevice = d3dDevice;
// Color writes
mColorMask = 0;
mColorMask |= ( mDesc.colorWriteRed ? GFXCOLORWRITEENABLE_RED : 0 );
mColorMask |= ( mDesc.colorWriteGreen ? GFXCOLORWRITEENABLE_GREEN : 0 );
mColorMask |= ( mDesc.colorWriteBlue ? GFXCOLORWRITEENABLE_BLUE : 0 );
mColorMask |= ( mDesc.colorWriteAlpha ? GFXCOLORWRITEENABLE_ALPHA : 0 );
// Z*bias
mZBias = *((U32*)&mDesc.zBias);
mZSlopeBias = *((U32*)&mDesc.zSlopeBias);
}
GFXD3D9StateBlock::~GFXD3D9StateBlock()
{
}
/// Returns the hash value of the desc that created this block
U32 GFXD3D9StateBlock::getHashValue() const
{
return mCachedHashValue;
}
/// Returns a GFXStateBlockDesc that this block represents
const GFXStateBlockDesc& GFXD3D9StateBlock::getDesc() const
{
return mDesc;
}
/// Called by D3D9 device to active this state block.
/// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
void GFXD3D9StateBlock::activate(GFXD3D9StateBlock* oldState)
{
PROFILE_SCOPE( GFXD3D9StateBlock_Activate );
// Little macro to save some typing, SD = state diff, checks for null source state block, then
// checks to see if the states differ
#if defined(TORQUE_OS_XENON)
#define SD(x, y) if (!oldState || oldState->mDesc.x != mDesc.x) \
mD3DDevice->SetRenderState_Inline(y, mDesc.x)
// Same as above, but allows you to set the data
#define SDD(x, y, z) if (!oldState || oldState->mDesc.x != mDesc.x) \
mD3DDevice->SetRenderState_Inline(y, z)
#else
#define SD(x, y) if (!oldState || oldState->mDesc.x != mDesc.x) \
mD3DDevice->SetRenderState(y, mDesc.x)
// Same as above, but allows you to set the data
#define SDD(x, y, z) if (!oldState || oldState->mDesc.x != mDesc.x) \
mD3DDevice->SetRenderState(y, z)
#endif
// Blending
SD(blendEnable, D3DRS_ALPHABLENDENABLE);
SDD(blendSrc, D3DRS_SRCBLEND, GFXD3D9Blend[mDesc.blendSrc]);
SDD(blendDest, D3DRS_DESTBLEND, GFXD3D9Blend[mDesc.blendDest]);
SDD(blendOp, D3DRS_BLENDOP, GFXD3D9BlendOp[mDesc.blendOp]);
// Separate alpha blending
SD(separateAlphaBlendEnable, D3DRS_SEPARATEALPHABLENDENABLE);
SDD(separateAlphaBlendSrc, D3DRS_SRCBLENDALPHA, GFXD3D9Blend[mDesc.separateAlphaBlendSrc]);
SDD(separateAlphaBlendDest, D3DRS_DESTBLENDALPHA, GFXD3D9Blend[mDesc.separateAlphaBlendDest]);
SDD(separateAlphaBlendOp, D3DRS_BLENDOPALPHA, GFXD3D9BlendOp[mDesc.separateAlphaBlendOp]);
// Alpha test
SD(alphaTestEnable, D3DRS_ALPHATESTENABLE);
SDD(alphaTestFunc, D3DRS_ALPHAFUNC, GFXD3D9CmpFunc[mDesc.alphaTestFunc]);
SD(alphaTestRef, D3DRS_ALPHAREF);
// Color writes
if ((oldState == NULL) || (mColorMask != oldState->mColorMask))
mD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, mColorMask);
// Culling
SDD(cullMode, D3DRS_CULLMODE, GFXD3D9CullMode[mDesc.cullMode]);
// Depth
SD(zEnable, D3DRS_ZENABLE);
SD(zWriteEnable, D3DRS_ZWRITEENABLE);
SDD(zFunc, D3DRS_ZFUNC, GFXD3D9CmpFunc[mDesc.zFunc]);
if ((!oldState) || (mZBias != oldState->mZBias))
mD3DDevice->SetRenderState(D3DRS_DEPTHBIAS, mZBias);
if ((!oldState) || (mZSlopeBias != oldState->mZSlopeBias))
mD3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, mZSlopeBias);
// Stencil
SD(stencilEnable, D3DRS_STENCILENABLE);
SDD(stencilFailOp, D3DRS_STENCILFAIL, GFXD3D9StencilOp[mDesc.stencilFailOp]);
SDD(stencilZFailOp, D3DRS_STENCILZFAIL, GFXD3D9StencilOp[mDesc.stencilZFailOp]);
SDD(stencilPassOp, D3DRS_STENCILPASS, GFXD3D9StencilOp[mDesc.stencilPassOp]);
SDD(stencilFunc, D3DRS_STENCILFUNC, GFXD3D9CmpFunc[mDesc.stencilFunc]);
SD(stencilRef, D3DRS_STENCILREF);
SD(stencilMask, D3DRS_STENCILMASK);
SD(stencilWriteMask, D3DRS_STENCILWRITEMASK);
SDD(fillMode, D3DRS_FILLMODE, GFXD3D9FillMode[mDesc.fillMode]);
#if !defined(TORQUE_OS_XENON)
SD(ffLighting, D3DRS_LIGHTING);
SD(vertexColorEnable, D3DRS_COLORVERTEX);
static DWORD swzTemp;
getOwningDevice()->getDeviceSwizzle32()->ToBuffer( &swzTemp, &mDesc.textureFactor, sizeof(ColorI) );
SDD(textureFactor, D3DRS_TEXTUREFACTOR, swzTemp);
#endif
#undef SD
#undef SDD
// NOTE: Samplers and Stages are different things.
//
// The Stages were for fixed function blending. When using shaders
// calling SetTextureStageState() is a complete waste of time. In
// fact if this function rises to the top of profiles we should
// refactor stateblocks to seperate the two.
//
// Samplers are used by both fixed function and shaders, but the
// number of samplers is limited by shader model.
#if !defined(TORQUE_OS_XENON)
#define TSS(x, y, z) if (!oldState || oldState->mDesc.samplers[i].x != mDesc.samplers[i].x) \
mD3DDevice->SetTextureStageState(i, y, z)
for ( U32 i = 0; i < 8; i++ )
{
TSS(textureColorOp, D3DTSS_COLOROP, GFXD3D9TextureOp[mDesc.samplers[i].textureColorOp]);
TSS(colorArg1, D3DTSS_COLORARG1, mDesc.samplers[i].colorArg1);
TSS(colorArg2, D3DTSS_COLORARG2, mDesc.samplers[i].colorArg2);
TSS(colorArg3, D3DTSS_COLORARG0, mDesc.samplers[i].colorArg3);
TSS(alphaOp, D3DTSS_ALPHAOP, GFXD3D9TextureOp[mDesc.samplers[i].alphaOp]);
TSS(alphaArg1, D3DTSS_ALPHAARG1, mDesc.samplers[i].alphaArg1);
TSS(alphaArg2, D3DTSS_ALPHAARG2, mDesc.samplers[i].alphaArg2);
TSS(alphaArg3, D3DTSS_ALPHAARG0, mDesc.samplers[i].alphaArg3);
TSS(textureTransform, D3DTSS_TEXTURETRANSFORMFLAGS, mDesc.samplers[i].textureTransform);
TSS(resultArg, D3DTSS_RESULTARG, mDesc.samplers[i].resultArg);
}
#undef TSS
#endif
#if defined(TORQUE_OS_XENON)
#define SS(x, y, z) if (!oldState || oldState->mDesc.samplers[i].x != mDesc.samplers[i].x) \
mD3DDevice->SetSamplerState_Inline(i, y, z)
#else
#define SS(x, y, z) if (!oldState || oldState->mDesc.samplers[i].x != mDesc.samplers[i].x) \
mD3DDevice->SetSamplerState(i, y, z)
#endif
for ( U32 i = 0; i < getOwningDevice()->getNumSamplers(); i++ )
{
SS(minFilter, D3DSAMP_MINFILTER, GFXD3D9TextureFilter[mDesc.samplers[i].minFilter]);
SS(magFilter, D3DSAMP_MAGFILTER, GFXD3D9TextureFilter[mDesc.samplers[i].magFilter]);
SS(mipFilter, D3DSAMP_MIPFILTER, GFXD3D9TextureFilter[mDesc.samplers[i].mipFilter]);
F32 bias = mDesc.samplers[i].mipLODBias;
DWORD dwBias = *( (LPDWORD)(&bias) );
SS(mipLODBias, D3DSAMP_MIPMAPLODBIAS, dwBias);
SS(maxAnisotropy, D3DSAMP_MAXANISOTROPY, mDesc.samplers[i].maxAnisotropy);
SS(addressModeU, D3DSAMP_ADDRESSU, GFXD3D9TextureAddress[mDesc.samplers[i].addressModeU]);
SS(addressModeV, D3DSAMP_ADDRESSV, GFXD3D9TextureAddress[mDesc.samplers[i].addressModeV]);
SS(addressModeW, D3DSAMP_ADDRESSW, GFXD3D9TextureAddress[mDesc.samplers[i].addressModeW]);
}
#undef SS
}

View file

@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9STATEBLOCK_H_
#define _GFXD3D9STATEBLOCK_H_
#ifndef _GFXSTATEBLOCK_H_
#include "gfx/gfxStateBlock.h"
#endif
struct IDirect3DDevice9;
class GFXD3D9StateBlock : public GFXStateBlock
{
public:
//
// GFXD3D9StateBlock interface
//
GFXD3D9StateBlock(const GFXStateBlockDesc& desc, IDirect3DDevice9 *d3dDevice);
virtual ~GFXD3D9StateBlock();
/// Called by D3D9 device to active this state block.
/// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
void activate(GFXD3D9StateBlock* oldState);
//
// GFXStateBlock interface
//
/// Returns the hash value of the desc that created this block
virtual U32 getHashValue() const;
/// Returns a GFXStateBlockDesc that this block represents
virtual const GFXStateBlockDesc& getDesc() const;
//
// GFXResource
//
virtual void zombify() { }
/// When called the resource should restore all device sensitive information destroyed by zombify()
virtual void resurrect() { }
private:
GFXStateBlockDesc mDesc;
U32 mCachedHashValue;
IDirect3DDevice9 *mD3DDevice; ///< Handle for D3DDevice
// Cached D3D specific things, these are "calculated" from GFXStateBlock
U32 mColorMask;
U32 mZBias;
U32 mZSlopeBias;
};
typedef StrongRefPtr<GFXD3D9StateBlock> GFXD3D9StateBlockRef;
#endif

View file

@ -0,0 +1,638 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
#include "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#include "gfx/bitmap/bitmapUtils.h"
#include "gfx/gfxCardProfile.h"
#include "core/strings/unicode.h"
#include "core/util/swizzle.h"
#include "core/util/safeDelete.h"
#include "console/console.h"
#include "core/resourceManager.h"
//-----------------------------------------------------------------------------
// Utility function, valid only in this file
#ifdef D3D_TEXTURE_SPEW
U32 GFXD3D9TextureObject::mTexCount = 0;
#endif
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
GFXD3D9TextureManager::GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice )
{
mD3DDevice = d3ddevice;
dMemset( mCurTexSet, 0, sizeof( mCurTexSet ) );
mD3DDevice->GetDeviceCaps(&mDeviceCaps);
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
GFXD3D9TextureManager::~GFXD3D9TextureManager()
{
// Destroy texture table now so just in case some texture objects
// are still left, we don't crash on a pure virtual method call.
SAFE_DELETE_ARRAY( mHashTable );
}
//-----------------------------------------------------------------------------
// _innerCreateTexture
//-----------------------------------------------------------------------------
void GFXD3D9TextureManager::_innerCreateTexture( GFXD3D9TextureObject *retTex,
U32 height,
U32 width,
U32 depth,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
bool forceMips,
S32 antialiasLevel)
{
GFXD3D9Device* d3d = static_cast<GFXD3D9Device*>(GFX);
// Some relevant helper information...
bool supportsAutoMips = GFX->getCardProfiler()->queryProfile("autoMipMapLevel", true);
DWORD usage = 0; // 0, D3DUSAGE_RENDERTARGET, or D3DUSAGE_DYNAMIC
D3DPOOL pool = D3DPOOL_DEFAULT;
retTex->mProfile = profile;
D3DFORMAT d3dTextureFormat = GFXD3D9TextureFormat[format];
#ifndef TORQUE_OS_XENON
if( retTex->mProfile->isDynamic() )
{
usage = D3DUSAGE_DYNAMIC;
}
else
{
usage = 0;
pool = d3d->isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
}
if( retTex->mProfile->isRenderTarget() )
{
pool = D3DPOOL_DEFAULT;
usage |= D3DUSAGE_RENDERTARGET;
}
if(retTex->mProfile->isZTarget())
{
usage |= D3DUSAGE_DEPTHSTENCIL;
pool = D3DPOOL_DEFAULT;
}
if( retTex->mProfile->isSystemMemory() )
{
pool = D3DPOOL_SYSTEMMEM;
}
if( supportsAutoMips &&
!forceMips &&
!retTex->mProfile->isSystemMemory() &&
numMipLevels == 0 &&
!(depth > 0) )
{
usage |= D3DUSAGE_AUTOGENMIPMAP;
}
#else
if(retTex->mProfile->isRenderTarget())
{
d3dTextureFormat = (D3DFORMAT)MAKELEFMT(d3dTextureFormat);
}
#endif
// Set the managed flag...
retTex->isManaged = (pool == D3DPOOL_MANAGED) || d3d->isD3D9Ex();
if( depth > 0 )
{
#ifdef TORQUE_OS_XENON
D3D9Assert( mD3DDevice->CreateVolumeTexture( width, height, depth, numMipLevels, 0 /* usage ignored on the 360 */,
d3dTextureFormat, pool, retTex->get3DTexPtr(), NULL), "Failed to create volume texture" );
#else
D3D9Assert(
GFXD3DX.D3DXCreateVolumeTexture(
mD3DDevice,
width,
height,
depth,
numMipLevels,
usage,
d3dTextureFormat,
pool,
retTex->get3DTexPtr()
), "GFXD3D9TextureManager::_createTexture - failed to create volume texture!"
);
#endif
retTex->mTextureSize.set( width, height, depth );
retTex->mMipLevels = retTex->get3DTex()->GetLevelCount();
// required for 3D texture support - John Kabus
retTex->mFormat = format;
}
else
{
#ifdef TORQUE_OS_XENON
D3D9Assert( mD3DDevice->CreateTexture(width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr(), NULL), "Failed to create texture" );
retTex->mMipLevels = retTex->get2DTex()->GetLevelCount();
#else
// Figure out AA settings for depth and render targets
D3DMULTISAMPLE_TYPE mstype;
DWORD mslevel;
switch (antialiasLevel)
{
case 0 :
mstype = D3DMULTISAMPLE_NONE;
mslevel = 0;
break;
case AA_MATCH_BACKBUFFER :
mstype = d3d->getMultisampleType();
mslevel = d3d->getMultisampleLevel();
break;
default :
{
mstype = D3DMULTISAMPLE_NONMASKABLE;
mslevel = antialiasLevel;
#ifdef TORQUE_DEBUG
DWORD MaxSampleQualities;
d3d->getD3D()->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dTextureFormat, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities);
AssertFatal(mslevel < MaxSampleQualities, "Invalid AA level!");
#endif
}
break;
}
bool fastCreate = true;
// Check for power of 2 textures - this is a problem with FX 5xxx cards
// with current drivers - 3/2/05
if( !isPow2(width) || !isPow2(height) )
{
fastCreate = false;
}
if(retTex->mProfile->isZTarget())
{
D3D9Assert(mD3DDevice->CreateDepthStencilSurface(width, height, d3dTextureFormat,
mstype, mslevel, retTex->mProfile->canDiscard(), retTex->getSurfacePtr(), NULL), "Failed to create Z surface" );
retTex->mFormat = format; // Assigning format like this should be fine.
}
else
{
// Try to create the texture directly - should gain us a bit in high
// performance cases where we know we're creating good stuff and we
// don't want to bother with D3DX - slow function.
HRESULT res = D3DERR_INVALIDCALL;
if( fastCreate )
{
res = mD3DDevice->CreateTexture(width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr(), NULL);
}
if( !fastCreate || (res != D3D_OK) )
{
D3D9Assert(
GFXD3DX.D3DXCreateTexture(
mD3DDevice,
width,
height,
numMipLevels,
usage,
d3dTextureFormat,
pool,
retTex->get2DTexPtr()
), "GFXD3D9TextureManager::_createTexture - failed to create texture!"
);
}
// If this is a render target, and it wants AA or wants to match the backbuffer (for example, to share the z)
// Check the caps though, if we can't stretchrect between textures, use the old RT method. (Which hopefully means
// that they can't force AA on us as well.)
if (retTex->mProfile->isRenderTarget() && mslevel != 0 && (mDeviceCaps.Caps2 && D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
{
D3D9Assert(mD3DDevice->CreateRenderTarget(width, height, d3dTextureFormat,
mstype, mslevel, false, retTex->getSurfacePtr(), NULL),
"GFXD3D9TextureManager::_createTexture - unable to create render target");
}
// All done!
retTex->mMipLevels = retTex->get2DTex()->GetLevelCount();
}
#endif
// Get the actual size of the texture...
D3DSURFACE_DESC probeDesc;
ZeroMemory(&probeDesc, sizeof probeDesc);
if( retTex->get2DTex() != NULL )
D3D9Assert( retTex->get2DTex()->GetLevelDesc( 0, &probeDesc ), "Failed to get surface description");
else if( retTex->getSurface() != NULL )
D3D9Assert( retTex->getSurface()->GetDesc( &probeDesc ), "Failed to get surface description");
retTex->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0);
int fmt = probeDesc.Format;
#if !defined(TORQUE_OS_XENON)
GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, fmt );
retTex->mFormat = (GFXFormat)fmt;
#else
retTex->mFormat = format;
#endif
}
}
//-----------------------------------------------------------------------------
// createTexture
//-----------------------------------------------------------------------------
GFXTextureObject *GFXD3D9TextureManager::_createTextureObject( U32 height,
U32 width,
U32 depth,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
bool forceMips,
S32 antialiasLevel,
GFXTextureObject *inTex )
{
GFXD3D9TextureObject *retTex;
if ( inTex )
{
AssertFatal( dynamic_cast<GFXD3D9TextureObject*>( inTex ), "GFXD3D9TextureManager::_createTexture() - Bad inTex type!" );
retTex = static_cast<GFXD3D9TextureObject*>( inTex );
retTex->release();
}
else
{
retTex = new GFXD3D9TextureObject( GFX, profile );
retTex->registerResourceWithDevice( GFX );
}
_innerCreateTexture(retTex, height, width, depth, format, profile, numMipLevels, forceMips, antialiasLevel);
return retTex;
}
//-----------------------------------------------------------------------------
// loadTexture - GBitmap
//-----------------------------------------------------------------------------
bool GFXD3D9TextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
{
PROFILE_SCOPE(GFXD3D9TextureManager_loadTexture);
GFXD3D9TextureObject *texture = static_cast<GFXD3D9TextureObject*>(aTexture);
#ifdef TORQUE_OS_XENON
// If the texture is currently bound, it needs to be unbound before modifying it
if( texture->getTex() && texture->getTex()->IsSet( mD3DDevice ) )
{
mD3DDevice->SetTexture( 0, NULL );
mD3DDevice->SetTexture( 1, NULL );
mD3DDevice->SetTexture( 2, NULL );
mD3DDevice->SetTexture( 3, NULL );
mD3DDevice->SetTexture( 4, NULL );
mD3DDevice->SetTexture( 5, NULL );
mD3DDevice->SetTexture( 6, NULL );
mD3DDevice->SetTexture( 7, NULL );
}
#endif
// Check with profiler to see if we can do automatic mipmap generation.
const bool supportsAutoMips = GFX->getCardProfiler()->queryProfile("autoMipMapLevel", true);
// Helper bool
const bool isCompressedTexFmt = aTexture->mFormat >= GFXFormatDXT1 && aTexture->mFormat <= GFXFormatDXT5;
GFXD3D9Device* dev = static_cast<GFXD3D9Device *>(GFX);
// Settings for mipmap generation
U32 maxDownloadMip = pDL->getNumMipLevels();
U32 nbMipMapLevel = pDL->getNumMipLevels();
if( supportsAutoMips && !isCompressedTexFmt )
{
maxDownloadMip = 1;
nbMipMapLevel = aTexture->mMipLevels;
}
// Fill the texture...
for( int i = 0; i < maxDownloadMip; i++ )
{
LPDIRECT3DSURFACE9 surf = NULL;
D3D9Assert(texture->get2DTex()->GetSurfaceLevel( i, &surf ), "Failed to get surface");
D3DLOCKED_RECT lockedRect;
#ifdef TORQUE_OS_XENON
// On the 360, doing a LockRect doesn't work like it does with untiled memory
// so instead swizzle into some temporary memory, and then later use D3DX
// to do the upload properly.
FrameTemp<U8> swizzleMem(pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
lockedRect.pBits = (void*)~swizzleMem;
#else
U32 waterMark = 0;
if (!dev->isD3D9Ex())
surf->LockRect( &lockedRect, NULL, 0 );
else
{
waterMark = FrameAllocator::getWaterMark();
lockedRect.pBits = static_cast<void*>(FrameAllocator::alloc(pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel()));
}
#endif
switch( texture->mFormat )
{
case GFXFormatR8G8B8:
{
PROFILE_SCOPE(Swizzle24_Upload);
AssertFatal( pDL->getFormat() == GFXFormatR8G8B8, "Assumption failed" );
GFX->getDeviceSwizzle24()->ToBuffer( lockedRect.pBits, pDL->getBits(i),
pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel() );
}
break;
case GFXFormatR8G8B8A8:
case GFXFormatR8G8B8X8:
{
PROFILE_SCOPE(Swizzle32_Upload);
GFX->getDeviceSwizzle32()->ToBuffer( lockedRect.pBits, pDL->getBits(i),
pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel() );
}
break;
default:
{
// Just copy the bits in no swizzle or padding
PROFILE_SCOPE(SwizzleNull_Upload);
AssertFatal( pDL->getFormat() == texture->mFormat, "Format mismatch" );
dMemcpy( lockedRect.pBits, pDL->getBits(i),
pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel() );
}
}
#ifdef TORQUE_OS_XENON
RECT srcRect;
srcRect.bottom = pDL->getHeight(i);
srcRect.top = 0;
srcRect.left = 0;
srcRect.right = pDL->getWidth(i);
D3DXLoadSurfaceFromMemory(surf, NULL, NULL, ~swizzleMem, (D3DFORMAT)MAKELINFMT(GFXD3D9TextureFormat[pDL->getFormat()]),
pDL->getWidth(i) * pDL->getBytesPerPixel(), NULL, &srcRect, false, 0, 0, D3DX_FILTER_NONE, 0);
#else
if (!dev->isD3D9Ex())
surf->UnlockRect();
else
{
RECT srcRect;
srcRect.top = 0;
srcRect.left = 0;
srcRect.right = pDL->getWidth(i);
srcRect.bottom = pDL->getHeight(i);
D3DXLoadSurfaceFromMemory(surf, NULL, NULL, lockedRect.pBits, GFXD3D9TextureFormat[pDL->getFormat()], pDL->getBytesPerPixel() * pDL->getWidth(i), NULL, &srcRect, D3DX_DEFAULT, 0);
FrameAllocator::setWaterMark(waterMark);
}
#endif
surf->Release();
}
return true;
}
//-----------------------------------------------------------------------------
// loadTexture - raw
//-----------------------------------------------------------------------------
bool GFXD3D9TextureManager::_loadTexture( GFXTextureObject *inTex, void *raw )
{
PROFILE_SCOPE(GFXD3D9TextureManager_loadTextureRaw);
GFXD3D9TextureObject *texture = (GFXD3D9TextureObject *) inTex;
// currently only for volume textures...
if( texture->getDepth() < 1 ) return false;
U32 bytesPerPix = 1;
switch( texture->mFormat )
{
case GFXFormatR8G8B8:
bytesPerPix = 3;
break;
case GFXFormatR8G8B8A8:
case GFXFormatR8G8B8X8:
bytesPerPix = 4;
break;
}
U32 rowPitch = texture->getWidth() * bytesPerPix;
U32 slicePitch = texture->getWidth() * texture->getHeight() * bytesPerPix;
D3DBOX box;
box.Left = 0;
box.Right = texture->getWidth();
box.Front = 0;
box.Back = texture->getDepth();
box.Top = 0;
box.Bottom = texture->getHeight();
LPDIRECT3DVOLUME9 volume = NULL;
D3D9Assert( texture->get3DTex()->GetVolumeLevel( 0, &volume ), "Failed to load volume" );
#ifdef TORQUE_OS_XENON
D3DLOCKED_BOX lockedBox;
volume->LockBox( &lockedBox, &box, 0 );
dMemcpy( lockedBox.pBits, raw, slicePitch * texture->getDepth() );
volume->UnlockBox();
#else
D3D9Assert(
GFXD3DX.D3DXLoadVolumeFromMemory(
volume,
NULL,
NULL,
raw,
GFXD3D9TextureFormat[texture->mFormat],
rowPitch,
slicePitch,
NULL,
&box,
#ifdef TORQUE_OS_XENON
false, 0, 0, 0, // Unique to Xenon -pw
#endif
D3DX_FILTER_NONE,
0
),
"Failed to load volume texture"
);
#endif
volume->Release();
return true;
}
//-----------------------------------------------------------------------------
// refreshTexture
//-----------------------------------------------------------------------------
bool GFXD3D9TextureManager::_refreshTexture(GFXTextureObject *texture)
{
U32 usedStrategies = 0;
GFXD3D9TextureObject *realTex = static_cast<GFXD3D9TextureObject *>( texture );
if(texture->mProfile->doStoreBitmap())
{
// SAFE_RELEASE(realTex->mD3DTexture);
// _innerCreateTexture(realTex, texture->mTextureSize.x, texture->mTextureSize.y, texture->mFormat, texture->mProfile, texture->mMipLevels);
if(texture->mBitmap)
_loadTexture(texture, texture->mBitmap);
if(texture->mDDS)
_loadTexture(texture, texture->mDDS);
usedStrategies++;
}
if(texture->mProfile->isRenderTarget() || texture->mProfile->isDynamic() ||
texture->mProfile->isZTarget())
{
realTex->release();
_innerCreateTexture(realTex, texture->getHeight(), texture->getWidth(), texture->getDepth(), texture->mFormat,
texture->mProfile, texture->mMipLevels, false, texture->mAntialiasLevel);
usedStrategies++;
}
AssertFatal(usedStrategies < 2, "GFXD3D9TextureManager::_refreshTexture - Inconsistent profile flags!");
return true;
}
//-----------------------------------------------------------------------------
// freeTexture
//-----------------------------------------------------------------------------
bool GFXD3D9TextureManager::_freeTexture(GFXTextureObject *texture, bool zombify)
{
AssertFatal(dynamic_cast<GFXD3D9TextureObject *>(texture),"Not an actual d3d texture object!");
GFXD3D9TextureObject *tex = static_cast<GFXD3D9TextureObject *>( texture );
// If it's a managed texture and we're zombifying, don't blast it, D3D allows
// us to keep it.
if(zombify && tex->isManaged)
return true;
tex->release();
return true;
}
/// Load a texture from a proper DDSFile instance.
bool GFXD3D9TextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
{
PROFILE_SCOPE(GFXD3D9TextureManager_loadTextureDDS);
GFXD3D9TextureObject *texture = static_cast<GFXD3D9TextureObject*>(aTexture);
// Fill the texture...
for( int i = 0; i < aTexture->mMipLevels; i++ )
{
PROFILE_SCOPE(GFXD3DTexMan_loadSurface);
LPDIRECT3DSURFACE9 surf = NULL;
D3D9Assert(texture->get2DTex()->GetSurfaceLevel( i, &surf ), "Failed to get surface");
#if defined(TORQUE_OS_XENON)
XGTEXTURE_DESC surfDesc;
dMemset(&surfDesc, 0, sizeof(XGTEXTURE_DESC));
XGGetSurfaceDesc(surf, &surfDesc);
RECT srcRect;
srcRect.top = srcRect.left = 0;
srcRect.bottom = dds->getHeight(i);
srcRect.right = dds->getWidth(i);
D3DXLoadSurfaceFromMemory(surf, NULL, NULL, dds->mSurfaces[0]->mMips[i],
(D3DFORMAT)MAKELINFMT(GFXD3D9TextureFormat[dds->mFormat]), dds->getSurfacePitch(i),
NULL, &srcRect, false, 0, 0, D3DX_FILTER_NONE, 0);
#else
GFXD3D9Device* dev = static_cast<GFXD3D9Device *>(GFX);
if (dev->isD3D9Ex())
{
RECT r;
r.top = r.left = 0;
r.bottom = dds->getHeight(i);
r.right = dds->getWidth(i);
D3DXLoadSurfaceFromMemory(surf, NULL, NULL, dds->mSurfaces[0]->mMips[i], GFXD3D9TextureFormat[dds->mFormat], dds->getSurfacePitch(i), NULL, &r, D3DX_DEFAULT, 0);
}
else
{
D3DLOCKED_RECT lockedRect;
D3D9Assert( surf->LockRect( &lockedRect, NULL, 0 ), "Failed to lock surface level for load" );
AssertFatal( dds->mSurfaces.size() > 0, "Assumption failed. DDSFile has no surfaces." );
if ( dds->getSurfacePitch( i ) != lockedRect.Pitch )
{
// Do a row-by-row copy.
U32 srcPitch = dds->getSurfacePitch( i );
U32 srcHeight = dds->getHeight();
U8* srcBytes = dds->mSurfaces[0]->mMips[i];
U8* dstBytes = (U8*)lockedRect.pBits;
for (U32 i = 0; i<srcHeight; i++)
{
dMemcpy( dstBytes, srcBytes, srcPitch );
dstBytes += lockedRect.Pitch;
srcBytes += srcPitch;
}
surf->UnlockRect();
surf->Release();
return true;
}
dMemcpy( lockedRect.pBits, dds->mSurfaces[0]->mMips[i], dds->getSurfaceSize(i) );
surf->UnlockRect();
}
#endif
surf->Release();
}
return true;
}

View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3DTEXTUREMANAGER_H_
#define _GFXD3DTEXTUREMANAGER_H_
#include "gfx/D3D9/gfxD3D9TextureObject.h"
#include "core/util/safeRelease.h"
// #define D3D_TEXTURE_SPEW
//*****************************************************************************
// GFX D3D Texture Manager
//*****************************************************************************
class GFXD3D9TextureManager : public GFXTextureManager
{
friend class GFXD3D9TextureObject;
public:
GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice );
virtual ~GFXD3D9TextureManager();
protected:
// GFXTextureManager
GFXTextureObject *_createTextureObject( U32 height,
U32 width,
U32 depth,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
bool forceMips = false,
S32 antialiasLevel = 0,
GFXTextureObject *inTex = NULL );
bool _loadTexture(GFXTextureObject *texture, DDSFile *dds);
bool _loadTexture(GFXTextureObject *texture, GBitmap *bmp);
bool _loadTexture(GFXTextureObject *texture, void *raw);
bool _refreshTexture(GFXTextureObject *texture);
bool _freeTexture(GFXTextureObject *texture, bool zombify = false);
private:
U32 mCurTexSet[TEXTURE_STAGE_COUNT];
LPDIRECT3DDEVICE9 mD3DDevice;
D3DCAPS9 mDeviceCaps;
void _innerCreateTexture(GFXD3D9TextureObject *obj, U32 height, U32 width,
U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels,
bool forceMips = false, S32 antialiasLevel = 0);
};
#endif

View file

@ -0,0 +1,277 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9TextureObject.h"
#include "platform/profiler.h"
#ifdef TORQUE_OS_XENON
#include "gfx/D3D9/360/gfx360Device.h"
#include "gfx/D3D9/360/gfx360Target.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#endif
U32 GFXD3D9TextureObject::mTexCount = 0;
//*****************************************************************************
// GFX D3D Texture Object
//*****************************************************************************
GFXD3D9TextureObject::GFXD3D9TextureObject( GFXDevice * d, GFXTextureProfile *profile)
: GFXTextureObject( d, profile )
{
#ifdef D3D_TEXTURE_SPEW
mTexCount++;
Con::printf("+ texMake %d %x", mTexCount, this);
#endif
isManaged = false;
mD3DTexture = NULL;
mLocked = false;
mD3DSurface = NULL;
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
GFXD3D9TextureObject::~GFXD3D9TextureObject()
{
kill();
#ifdef D3D_TEXTURE_SPEW
mTexCount--;
Con::printf("+ texkill %d %x", mTexCount, this);
#endif
}
//-----------------------------------------------------------------------------
// lock
//-----------------------------------------------------------------------------
GFXLockedRect *GFXD3D9TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect /*= NULL*/)
{
AssertFatal( !mLocked, "GFXD3D9TextureObject::lock - The texture is already locked!" );
if( mProfile->isRenderTarget() )
{
if( !mLockTex ||
mLockTex->getWidth() != getWidth() ||
mLockTex->getHeight() != getHeight() )
{
mLockTex.set( getWidth(), getHeight(), mFormat, &GFXSystemMemProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__) );
}
PROFILE_START(GFXD3D9TextureObject_lockRT);
IDirect3DSurface9 *source;
D3D9Assert( get2DTex()->GetSurfaceLevel( 0, &source ), "GFXD3D9TextureObject::lock - failed to get our own texture's surface." );
IDirect3DSurface9 *dest;
GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*mLockTex);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &dest ), "GFXD3D9TextureObject::lock - failed to get dest texture's surface." );
#ifndef TORQUE_OS_XENON
LPDIRECT3DDEVICE9 D3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
HRESULT rtLockRes = D3DDevice->GetRenderTargetData( source, dest );
#else
AssertFatal(false, "Use different functionality on the Xbox 360 to perform this task.");
HRESULT rtLockRes = E_FAIL;
#endif
source->Release();
if(!SUCCEEDED(rtLockRes))
{
// This case generally occurs if the device is lost. The lock failed
// so clean up and return NULL.
dest->Release();
PROFILE_END();
return NULL;
}
D3D9Assert( dest->LockRect( &mLockRect, NULL, D3DLOCK_READONLY ), NULL );
dest->Release();
mLocked = true;
PROFILE_END();
}
else
{
RECT r;
if(inRect)
{
r.top = inRect->point.y;
r.left = inRect->point.x;
r.bottom = inRect->point.y + inRect->extent.y;
r.right = inRect->point.x + inRect->extent.x;
}
D3D9Assert( get2DTex()->LockRect(mipLevel, &mLockRect, inRect ? &r : NULL, 0),
"GFXD3D9TextureObject::lock - could not lock non-RT texture!" );
mLocked = true;
}
// GFXLockedRect is set up to correspond to D3DLOCKED_RECT, so this is ok.
return (GFXLockedRect*)&mLockRect;
}
//-----------------------------------------------------------------------------
// unLock
//-----------------------------------------------------------------------------
void GFXD3D9TextureObject::unlock(U32 mipLevel)
{
AssertFatal( mLocked, "GFXD3D9TextureObject::unlock - Attempting to unlock a surface that has not been locked" );
#ifndef TORQUE_OS_XENON
if( mProfile->isRenderTarget() )
{
IDirect3DSurface9 *dest;
GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*mLockTex);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &dest ), NULL );
dest->UnlockRect();
dest->Release();
mLocked = false;
}
else
#endif
{
D3D9Assert( get2DTex()->UnlockRect(mipLevel),
"GFXD3D9TextureObject::unlock - could not unlock non-RT texture." );
mLocked = false;
}
}
//------------------------------------------------------------------------------
void GFXD3D9TextureObject::release()
{
static_cast<GFXD3D9Device *>( GFX )->destroyD3DResource( mD3DTexture );
static_cast<GFXD3D9Device *>( GFX )->destroyD3DResource( mD3DSurface );
mD3DTexture = NULL;
mD3DSurface = NULL;
}
void GFXD3D9TextureObject::zombify()
{
// Managed textures are managed by D3D
AssertFatal(!mLocked, "GFXD3D9TextureObject::zombify - Cannot zombify a locked texture!");
if(isManaged)
return;
release();
}
void GFXD3D9TextureObject::resurrect()
{
// Managed textures are managed by D3D
if(isManaged)
return;
static_cast<GFXD3D9TextureManager*>(TEXMGR)->refreshTexture(this);
}
//------------------------------------------------------------------------------
bool GFXD3D9TextureObject::copyToBmp(GBitmap* bmp)
{
#ifdef TORQUE_OS_XENON
// TODO: Implement Xenon version -patw
return false;
#else
if (!bmp)
return false;
// check format limitations
// at the moment we only support RGBA for the source (other 4 byte formats should
// be easy to add though)
AssertFatal(mFormat == GFXFormatR8G8B8A8, "copyToBmp: invalid format");
if (mFormat != GFXFormatR8G8B8A8)
return false;
PROFILE_START(GFXD3D9TextureObject_copyToBmp);
AssertFatal(bmp->getWidth() == getWidth(), "doh");
AssertFatal(bmp->getHeight() == getHeight(), "doh");
U32 width = getWidth();
U32 height = getHeight();
bmp->setHasTransparency(mHasTransparency);
// set some constants
const U32 sourceBytesPerPixel = 4;
U32 destBytesPerPixel = 0;
if (bmp->getFormat() == GFXFormatR8G8B8A8)
destBytesPerPixel = 4;
else if (bmp->getFormat() == GFXFormatR8G8B8)
destBytesPerPixel = 3;
else
// unsupported
AssertFatal(false, "unsupported bitmap format");
// lock the texture
D3DLOCKED_RECT* lockRect = (D3DLOCKED_RECT*) lock();
// set pointers
U8* srcPtr = (U8*)lockRect->pBits;
U8* destPtr = bmp->getWritableBits();
// we will want to skip over any D3D cache data in the source texture
const S32 sourceCacheSize = lockRect->Pitch - width * sourceBytesPerPixel;
AssertFatal(sourceCacheSize >= 0, "copyToBmp: cache size is less than zero?");
PROFILE_START(GFXD3D9TextureObject_copyToBmp_pixCopy);
// copy data into bitmap
for (int row = 0; row < height; ++row)
{
for (int col = 0; col < width; ++col)
{
destPtr[0] = srcPtr[2]; // red
destPtr[1] = srcPtr[1]; // green
destPtr[2] = srcPtr[0]; // blue
if (destBytesPerPixel == 4)
destPtr[3] = srcPtr[3]; // alpha
// go to next pixel in src
srcPtr += sourceBytesPerPixel;
// go to next pixel in dest
destPtr += destBytesPerPixel;
}
// skip past the cache data for this row (if any)
srcPtr += sourceCacheSize;
}
PROFILE_END();
// assert if we stomped or underran memory
AssertFatal(U32(destPtr - bmp->getWritableBits()) == width * height * destBytesPerPixel, "copyToBmp: doh, memory error");
AssertFatal(U32(srcPtr - (U8*)lockRect->pBits) == height * lockRect->Pitch, "copyToBmp: doh, memory error");
// unlock
unlock();
PROFILE_END();
return true;
#endif
}

View file

@ -0,0 +1,80 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D9TEXTUREOBJECT_H_
#define _GFXD3D9TEXTUREOBJECT_H_
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
#ifndef _GFXTEXTUREMANAGER_H_
#include "gfx/gfxTextureManager.h"
#endif
class GFXD3D9TextureObject : public GFXTextureObject
{
protected:
static U32 mTexCount;
GFXTexHandle mLockTex;
D3DLOCKED_RECT mLockRect;
bool mLocked;
IDirect3DBaseTexture9 *mD3DTexture;
// used for z buffers...
IDirect3DSurface9 *mD3DSurface;
public:
GFXD3D9TextureObject( GFXDevice * d, GFXTextureProfile *profile);
~GFXD3D9TextureObject();
IDirect3DBaseTexture9 * getTex(){ return mD3DTexture; }
IDirect3DTexture9 * get2DTex(){ return (LPDIRECT3DTEXTURE9) mD3DTexture; }
IDirect3DTexture9 ** get2DTexPtr(){ return (LPDIRECT3DTEXTURE9*) &mD3DTexture; }
IDirect3DVolumeTexture9 * get3DTex(){ return (LPDIRECT3DVOLUMETEXTURE9) mD3DTexture; }
IDirect3DVolumeTexture9 ** get3DTexPtr(){ return (LPDIRECT3DVOLUMETEXTURE9*) &mD3DTexture; }
void release();
bool isManaged;
virtual GFXLockedRect * lock(U32 mipLevel = 0, RectI *inRect = NULL);
virtual void unlock(U32 mipLevel = 0 );
virtual bool copyToBmp(GBitmap* bmp);
IDirect3DSurface9 *getSurface() {return mD3DSurface;}
IDirect3DSurface9 **getSurfacePtr() {return &mD3DSurface;}
// GFXResource
void zombify();
void resurrect();
#ifdef TORQUE_DEBUG
virtual void pureVirtualCrash() {};
#endif
};
#endif

View file

@ -0,0 +1,230 @@
//-----------------------------------------------------------------------------
// 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/D3D9/gfxD3D9VertexBuffer.h"
GFXD3D9VertexBuffer::~GFXD3D9VertexBuffer()
{
#ifdef TORQUE_DEBUG
SAFE_DELETE( name );
#endif
if (getOwningDevice() != NULL)
{
if (mBufferType == GFXBufferTypeDynamic)
static_cast<GFXD3D9Device *>(getOwningDevice())->deallocVertexBuffer( this );
else if (mBufferType != GFXBufferTypeVolatile)
{
static_cast<GFXD3D9Device *>(getOwningDevice())->destroyD3DResource( vb );
}
}
}
//-----------------------------------------------------------------------------
// Lock
//-----------------------------------------------------------------------------
void GFXD3D9VertexBuffer::lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr)
{
PROFILE_SCOPE(GFXD3D9VertexBuffer_lock);
AssertFatal(lockedVertexStart == 0 && lockedVertexEnd == 0, "Cannot lock a buffer more than once!");
U32 flags = 0;
GFXD3D9Device *d = static_cast<GFXD3D9Device *>( mDevice );
switch( mBufferType )
{
case GFXBufferTypeStatic:
break;
case GFXBufferTypeDynamic:
#ifndef TORQUE_OS_XENON
flags |= D3DLOCK_DISCARD;
#endif
break;
case GFXBufferTypeVolatile:
// Get or create the volatile buffer...
mVolatileBuffer = d->findVBPool( &mVertexFormat, vertexEnd );
if( !mVolatileBuffer )
mVolatileBuffer = d->createVBPool( &mVertexFormat, mVertexSize );
vb = mVolatileBuffer->vb;
// Get our range now...
AssertFatal(vertexStart == 0, "Cannot get a subrange on a volatile buffer.");
AssertFatal(vertexEnd <= MAX_DYNAMIC_VERTS, "Cannot get more than MAX_DYNAMIC_VERTS in a volatile buffer. Up the constant!");
AssertFatal(mVolatileBuffer->lockedVertexStart == 0 && mVolatileBuffer->lockedVertexEnd == 0, "Got more than one lock on the volatile pool.");
// We created the pool when we requested this volatile buffer, so assume it exists...
if( mVolatileBuffer->mNumVerts + vertexEnd > MAX_DYNAMIC_VERTS )
{
#ifdef TORQUE_OS_XENON
AssertFatal( false, "This should never, ever happen. findVBPool should have returned NULL" );
#else
flags |= D3DLOCK_DISCARD;
#endif
mVolatileStart = vertexStart = 0;
vertexEnd = vertexEnd;
}
else
{
flags |= D3DLOCK_NOOVERWRITE;
mVolatileStart = vertexStart = mVolatileBuffer->mNumVerts;
vertexEnd += mVolatileBuffer->mNumVerts;
}
mVolatileBuffer->mNumVerts = vertexEnd+1;
mVolatileBuffer->lockedVertexStart = vertexStart;
mVolatileBuffer->lockedVertexEnd = vertexEnd;
break;
}
lockedVertexStart = vertexStart;
lockedVertexEnd = vertexEnd;
// Con::printf("%x: Locking %s range (%d, %d)", this, (mBufferType == GFXBufferTypeVolatile ? "volatile" : "static"), lockedVertexStart, lockedVertexEnd);
#ifdef TORQUE_OS_XENON
// If the vertex buffer which we are trying to lock is held by the D3D device
// on Xenon it will bomb. So if that is the case, then SetStreamSource to NULL
// and also call setVertexBuffer because otherwise the state-cache will be hosed
if( d->mCurrentVB != NULL && d->mCurrentVB->vb == vb )
{
d->setVertexBuffer( NULL );
d->mD3DDevice->SetStreamSource( 0, NULL, 0, 0 );
}
// As of October 2006 XDK, range locking is no longer supported. Lock the whole buffer
// and then manually offset the pointer to simulate the subrange. -patw
D3D9Assert( vb->Lock( 0, 0, vertexPtr, flags),
"Unable to lock vertex buffer.");
U8 *tmp = (U8 *)(*vertexPtr);
tmp += ( vertexStart * mVertexSize );
*vertexPtr = tmp;
#else
U32 sizeToLock = (vertexEnd - vertexStart) * mVertexSize;
D3D9Assert( vb->Lock(vertexStart * mVertexSize, sizeToLock, vertexPtr, flags),
"Unable to lock vertex buffer.");
#ifdef TORQUE_DEBUG
// Allocate a debug buffer large enough for the lock
// plus space for over and under run guard strings.
const U32 guardSize = sizeof( _VBGuardString );
mDebugGuardBuffer = new U8[sizeToLock+(guardSize*2)];
// Setup the guard strings.
dMemcpy( mDebugGuardBuffer, _VBGuardString, guardSize );
dMemcpy( mDebugGuardBuffer + sizeToLock + guardSize, _VBGuardString, guardSize );
// Store the real lock pointer and return our debug pointer.
mLockedBuffer = *vertexPtr;
*vertexPtr = mDebugGuardBuffer + guardSize;
#endif // TORQUE_DEBUG
#endif
}
void GFXD3D9VertexBuffer::unlock()
{
PROFILE_SCOPE(GFXD3D9VertexBuffer_unlock);
#ifdef TORQUE_DEBUG
if ( mDebugGuardBuffer )
{
const U32 guardSize = sizeof( _VBGuardString );
const U32 sizeLocked = (lockedVertexEnd - lockedVertexStart) * mVertexSize;
// First check the guard areas for overwrites.
AssertFatal( dMemcmp( mDebugGuardBuffer, _VBGuardString, guardSize ) == 0,
"GFXD3D9VertexBuffer::unlock - Caught lock memory underrun!" );
AssertFatal( dMemcmp( mDebugGuardBuffer + sizeLocked + guardSize, _VBGuardString, guardSize ) == 0,
"GFXD3D9VertexBuffer::unlock - Caught lock memory overrun!" );
// Copy the debug content down to the real VB.
dMemcpy( mLockedBuffer, mDebugGuardBuffer + guardSize, sizeLocked );
// Cleanup.
delete [] mDebugGuardBuffer;
mDebugGuardBuffer = NULL;
mLockedBuffer = NULL;
}
#endif // TORQUE_DEBUG
D3D9Assert( vb->Unlock(),
"Unable to unlock vertex buffer.");
mIsFirstLock = false;
// Con::printf("%x: Unlocking %s range (%d, %d)", this, (mBufferType == GFXBufferTypeVolatile ? "volatile" : "static"), lockedVertexStart, lockedVertexEnd);
lockedVertexEnd = lockedVertexStart = 0;
if(mVolatileBuffer.isValid())
{
mVolatileBuffer->lockedVertexStart = 0;
mVolatileBuffer->lockedVertexEnd = 0;
mVolatileBuffer = NULL;
//vb->Release();
//vb = NULL;
}
}
void GFXD3D9VertexBuffer::zombify()
{
AssertFatal(lockedVertexStart == 0 && lockedVertexEnd == 0, "GFXD3D9VertexBuffer::zombify - Cannot zombify a locked buffer!");
// Static buffers are managed by D3D9 so we don't deal with them.
if(mBufferType == GFXBufferTypeDynamic)
{
SAFE_RELEASE(vb);
}
}
void GFXD3D9VertexBuffer::resurrect()
{
// Static buffers are managed by D3D9 so we don't deal with them.
if(mBufferType == GFXBufferTypeDynamic)
{
D3D9Assert(static_cast<GFXD3D9Device*>(mDevice)->mD3DDevice->CreateVertexBuffer( mVertexSize * mNumVerts,
#ifdef TORQUE_OS_XENON
D3DUSAGE_WRITEONLY,
#else
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
#endif
0,
D3DPOOL_DEFAULT,
&vb,
NULL ),
"GFXD3D9VertexBuffer::resurrect - Failed to allocate VB" );
}
}

View file

@ -0,0 +1,136 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXD3D_VERTEXBUFFER_H_
#define _GFXD3D_VERTEXBUFFER_H_
#ifndef _GFXD3D9DEVICE_H_
#include "gfx/D3D9/gfxD3D9Device.h"
#endif
#ifndef _SAFEDELETE_H_
#include "core/util/safeDelete.h"
#endif
//*****************************************************************************
// GFXD3D9VertexBuffer
//*****************************************************************************
class GFXD3D9VertexBuffer : public GFXVertexBuffer
{
public:
IDirect3DVertexBuffer9 *vb;
StrongRefPtr<GFXD3D9VertexBuffer> mVolatileBuffer;
#ifdef TORQUE_DEBUG
#define _VBGuardString "GFX_VERTEX_BUFFER_GUARD_STRING"
U8 *mDebugGuardBuffer;
void *mLockedBuffer;
#endif TORQUE_DEBUG
bool mIsFirstLock;
bool mClearAtFrameEnd;
GFXD3D9VertexBuffer();
GFXD3D9VertexBuffer( GFXDevice *device,
U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertexSize,
GFXBufferType bufferType );
virtual ~GFXD3D9VertexBuffer();
void lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr);
void unlock();
void prepare() {}
#ifdef TORQUE_DEBUG
char *name;
/// In debug compile, the verts will be chained together and the device
/// will examine the chain when it's destructor is called, this will
/// allow developers to see which vertex buffers are not destroyed
GFXD3D9VertexBuffer *next;
#endif
void setName( const char *n );
// GFXResource interface
virtual void zombify();
virtual void resurrect();
};
//-----------------------------------------------------------------------------
// This is for debugging vertex buffers and trying to track down which vbs
// aren't getting free'd
inline GFXD3D9VertexBuffer::GFXD3D9VertexBuffer()
: GFXVertexBuffer(0,0,0,0,(GFXBufferType)0)
{
#ifdef TORQUE_DEBUG
name = NULL;
#endif
vb = NULL;
mIsFirstLock = true;
lockedVertexEnd = lockedVertexStart = 0;
mClearAtFrameEnd = false;
#ifdef TORQUE_DEBUG
mDebugGuardBuffer = NULL;
mLockedBuffer = NULL;
#endif
}
inline GFXD3D9VertexBuffer::GFXD3D9VertexBuffer( GFXDevice *device,
U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertexSize,
GFXBufferType bufferType )
: GFXVertexBuffer( device, numVerts, vertexFormat, vertexSize, bufferType )
{
#ifdef TORQUE_DEBUG
name = NULL;
#endif
vb = NULL;
mIsFirstLock = true;
mClearAtFrameEnd = false;
lockedVertexEnd = lockedVertexStart = 0;
#ifdef TORQUE_DEBUG
mDebugGuardBuffer = NULL;
mLockedBuffer = NULL;
#endif
}
#ifdef TORQUE_DEBUG
inline void GFXD3D9VertexBuffer::setName( const char *n )
{
SAFE_DELETE( name );
name = new char[dStrlen( n )];
dStrcpy( name, n );
}
#else
inline void GFXD3D9VertexBuffer::setName( const char *n ) { }
#endif // !TORQUE_DEBUG
#endif // _GFXD3D_VERTEXBUFFER_H_

View file

@ -0,0 +1,87 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/pc/gfxPCD3D9Device.h"
#include "gfx/D3D9/gfxD3D9CardProfiler.h"
#include "gfx/D3D9/gfxD3D9Shader.h"
#include "gfx/D3D9/gfxD3D9VertexBuffer.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#include "core/strings/unicode.h"
#include "console/console.h"
//------------------------------------------------------------------------------
// D3DX Function binding
//------------------------------------------------------------------------------
bool d3dxBindFunction( DLibrary *dll, void *&fnAddress, const char *name )
{
fnAddress = dll->bind( name );
if (!fnAddress)
Con::warnf( "D3DX Loader: DLL bind failed for %s", name );
return fnAddress != 0;
}
void GFXD3D9Device::initD3DXFnTable()
{
if ( smD3DX.isLoaded )
return;
// We only load the d3dx version that we compiled
// and linked against which should keep unexpected
// problems from newer or older SDKs to a minimum.
String d3dxVersion = String::ToString( "d3dx9_%d.dll", (S32)D3DX_SDK_VERSION );
smD3DX.dllRef = OsLoadLibrary( d3dxVersion );
// If the d3dx version we requested didn't load then we have
// a corrupt or old install of DirectX.... prompt them to update.
if ( !smD3DX.dllRef )
{
Con::errorf( "Unsupported DirectX version!" );
Platform::messageBox( Con::getVariable( "$appName" ),
"DirectX could not be started!\r\n"
"Please be sure you have the latest version of DirectX installed.",
MBOk, MIStop );
Platform::forceShutdown( -1 );
}
smD3DX.isLoaded = true;
#define D3DX_FUNCTION(fn_name, fn_return, fn_args) \
smD3DX.isLoaded &= d3dxBindFunction(smD3DX.dllRef, *(void**)&smD3DX.fn_name, #fn_name);
# include "gfx/D3D9/d3dx9Functions.h"
#undef D3DX_FUNCTION
AssertISV( smD3DX.isLoaded, "D3DX Failed to load all functions." );
// HACK: For some reason in the latest versions of
// the D3D SDK on the PC the shader compiler will load
// and unload the compiler DLL over and over with each
// shader compiled.
//
// By loading the DLL once ourselves we keep it from
// ever unloading it which makes shader compiling faster.
//
String compilerVersion = String::ToString( "D3DCompiler_%d.dll", (S32)D3DX_SDK_VERSION );
smD3DX.compilerDllRef = OsLoadLibrary( compilerVersion );
}

View file

@ -0,0 +1,376 @@
//-----------------------------------------------------------------------------
// 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 <d3d9.h>
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#include "console/console.h"
//------------------------------------------------------------------------------
_D3DFORMAT GFXD3D9IndexFormat[GFXIndexFormat_COUNT];
_D3DSAMPLERSTATETYPE GFXD3D9SamplerState[GFXSAMP_COUNT];
_D3DFORMAT GFXD3D9TextureFormat[GFXFormat_COUNT];
_D3DRENDERSTATETYPE GFXD3D9RenderState[GFXRenderState_COUNT];
_D3DTEXTUREFILTERTYPE GFXD3D9TextureFilter[GFXTextureFilter_COUNT];
_D3DBLEND GFXD3D9Blend[GFXBlend_COUNT];
_D3DBLENDOP GFXD3D9BlendOp[GFXBlendOp_COUNT];
_D3DSTENCILOP GFXD3D9StencilOp[GFXStencilOp_COUNT];
_D3DCMPFUNC GFXD3D9CmpFunc[GFXCmp_COUNT];
_D3DCULL GFXD3D9CullMode[GFXCull_COUNT];
_D3DFILLMODE GFXD3D9FillMode[GFXFill_COUNT];
_D3DPRIMITIVETYPE GFXD3D9PrimType[GFXPT_COUNT];
_D3DTEXTURESTAGESTATETYPE GFXD3D9TextureStageState[GFXTSS_COUNT];
_D3DTEXTUREADDRESS GFXD3D9TextureAddress[GFXAddress_COUNT];
_D3DTEXTUREOP GFXD3D9TextureOp[GFXTOP_COUNT];
_D3DDECLTYPE GFXD3D9DeclType[GFXDeclType_COUNT];
//------------------------------------------------------------------------------
#define INIT_LOOKUPTABLE( tablearray, enumprefix, type ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
tablearray##[i] = (##type##)GFX_UNINIT_VAL;
#define VALIDATE_LOOKUPTABLE( tablearray, enumprefix ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
if( (int)tablearray##[i] == GFX_UNINIT_VAL ) \
Con::warnf( "GFXD3D9EnumTranslate: Unassigned value in " #tablearray ": %i", i ); \
else if( (int)tablearray##[i] == GFX_UNSUPPORTED_VAL ) \
Con::warnf( "GFXD3D9EnumTranslate: Unsupported value in " #tablearray ": %i", i );
//------------------------------------------------------------------------------
void GFXD3D9EnumTranslate::init()
{
INIT_LOOKUPTABLE( GFXD3D9IndexFormat, GFXIndexFormat, _D3DFORMAT );
GFXD3D9IndexFormat[GFXIndexFormat16] = D3DFMT_INDEX16;
GFXD3D9IndexFormat[GFXIndexFormat32] = D3DFMT_INDEX32;
VALIDATE_LOOKUPTABLE( GFXD3D9IndexFormat, GFXIndexFormat );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9SamplerState, GFXSAMP, _D3DSAMPLERSTATETYPE );
GFXD3D9SamplerState[GFXSAMPAddressU] = D3DSAMP_ADDRESSU;
GFXD3D9SamplerState[GFXSAMPAddressV] = D3DSAMP_ADDRESSV;
GFXD3D9SamplerState[GFXSAMPAddressW] = D3DSAMP_ADDRESSW;
GFXD3D9SamplerState[GFXSAMPBorderColor] = D3DSAMP_BORDERCOLOR;
GFXD3D9SamplerState[GFXSAMPMagFilter] = D3DSAMP_MAGFILTER;
GFXD3D9SamplerState[GFXSAMPMinFilter] = D3DSAMP_MINFILTER;
GFXD3D9SamplerState[GFXSAMPMipFilter] = D3DSAMP_MIPFILTER;
GFXD3D9SamplerState[GFXSAMPMipMapLODBias] = D3DSAMP_MIPMAPLODBIAS;
GFXD3D9SamplerState[GFXSAMPMaxMipLevel] = D3DSAMP_MAXMIPLEVEL;
GFXD3D9SamplerState[GFXSAMPMaxAnisotropy] = D3DSAMP_MAXANISOTROPY;
GFXD3D9SamplerState[GFXSAMPSRGBTexture] = D3DSAMP_SRGBTEXTURE;
GFXD3D9SamplerState[GFXSAMPElementIndex] = D3DSAMP_ELEMENTINDEX;
GFXD3D9SamplerState[GFXSAMPDMapOffset] = D3DSAMP_DMAPOFFSET;
VALIDATE_LOOKUPTABLE( GFXD3D9SamplerState, GFXSAMP );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9TextureFormat, GFXFormat, _D3DFORMAT );
GFXD3D9TextureFormat[GFXFormatR8G8B8] = D3DFMT_R8G8B8;
GFXD3D9TextureFormat[GFXFormatR8G8B8A8] = D3DFMT_A8R8G8B8;
GFXD3D9TextureFormat[GFXFormatR8G8B8X8] = D3DFMT_X8R8G8B8;
GFXD3D9TextureFormat[GFXFormatR5G6B5] = D3DFMT_R5G6B5;
GFXD3D9TextureFormat[GFXFormatR5G5B5A1] = D3DFMT_A1R5G5B5;
GFXD3D9TextureFormat[GFXFormatR5G5B5X1] = D3DFMT_X1R5G5B5;
GFXD3D9TextureFormat[GFXFormatR32F] = D3DFMT_R32F;
GFXD3D9TextureFormat[GFXFormatA4L4] = D3DFMT_A4L4;
GFXD3D9TextureFormat[GFXFormatA8L8] = D3DFMT_A8L8;
GFXD3D9TextureFormat[GFXFormatA8] = D3DFMT_A8;
GFXD3D9TextureFormat[GFXFormatL8] = D3DFMT_L8;
GFXD3D9TextureFormat[GFXFormatDXT1] = D3DFMT_DXT1;
GFXD3D9TextureFormat[GFXFormatDXT2] = D3DFMT_DXT2;
GFXD3D9TextureFormat[GFXFormatDXT3] = D3DFMT_DXT3;
GFXD3D9TextureFormat[GFXFormatDXT4] = D3DFMT_DXT4;
GFXD3D9TextureFormat[GFXFormatDXT5] = D3DFMT_DXT5;
GFXD3D9TextureFormat[GFXFormatR32G32B32A32F] = D3DFMT_A32B32G32R32F;
GFXD3D9TextureFormat[GFXFormatR16G16B16A16F] = D3DFMT_A16B16G16R16F;
GFXD3D9TextureFormat[GFXFormatL16] = D3DFMT_L16;
GFXD3D9TextureFormat[GFXFormatR16G16B16A16] = D3DFMT_A16B16G16R16;
GFXD3D9TextureFormat[GFXFormatR16G16] = D3DFMT_G16R16;
GFXD3D9TextureFormat[GFXFormatR16F] = D3DFMT_R16F;
GFXD3D9TextureFormat[GFXFormatR16G16F] = D3DFMT_G16R16F;
GFXD3D9TextureFormat[GFXFormatR10G10B10A2] = D3DFMT_A2R10G10B10;
GFXD3D9TextureFormat[GFXFormatD32] = D3DFMT_D32;
GFXD3D9TextureFormat[GFXFormatD24X8] = D3DFMT_D24X8;
GFXD3D9TextureFormat[GFXFormatD24S8] = D3DFMT_D24S8;
GFXD3D9TextureFormat[GFXFormatD24FS8] = D3DFMT_D24FS8;
GFXD3D9TextureFormat[GFXFormatD16] = D3DFMT_D16;
VALIDATE_LOOKUPTABLE( GFXD3D9TextureFormat, GFXFormat);
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9RenderState, GFXRenderState, _D3DRENDERSTATETYPE );
GFXD3D9RenderState[GFXRSZEnable] = D3DRS_ZENABLE;
GFXD3D9RenderState[GFXRSFillMode] = D3DRS_FILLMODE;
GFXD3D9RenderState[GFXRSZWriteEnable] = D3DRS_ZWRITEENABLE;
GFXD3D9RenderState[GFXRSAlphaTestEnable] = D3DRS_ALPHATESTENABLE;
GFXD3D9RenderState[GFXRSSrcBlend] = D3DRS_SRCBLEND;
GFXD3D9RenderState[GFXRSDestBlend] = D3DRS_DESTBLEND;
GFXD3D9RenderState[GFXRSCullMode] = D3DRS_CULLMODE;
GFXD3D9RenderState[GFXRSZFunc] = D3DRS_ZFUNC;
GFXD3D9RenderState[GFXRSAlphaRef] = D3DRS_ALPHAREF;
GFXD3D9RenderState[GFXRSAlphaFunc] = D3DRS_ALPHAFUNC;
GFXD3D9RenderState[GFXRSAlphaBlendEnable] = D3DRS_ALPHABLENDENABLE;
GFXD3D9RenderState[GFXRSStencilEnable] = D3DRS_STENCILENABLE;
GFXD3D9RenderState[GFXRSStencilFail] = D3DRS_STENCILFAIL;
GFXD3D9RenderState[GFXRSStencilZFail] = D3DRS_STENCILZFAIL;
GFXD3D9RenderState[GFXRSStencilPass] = D3DRS_STENCILPASS;
GFXD3D9RenderState[GFXRSStencilFunc] = D3DRS_STENCILFUNC;
GFXD3D9RenderState[GFXRSStencilRef] = D3DRS_STENCILREF;
GFXD3D9RenderState[GFXRSStencilMask] = D3DRS_STENCILMASK;
GFXD3D9RenderState[GFXRSStencilWriteMask] = D3DRS_STENCILWRITEMASK;
GFXD3D9RenderState[GFXRSWrap0] = D3DRS_WRAP0;
GFXD3D9RenderState[GFXRSWrap1] = D3DRS_WRAP1;
GFXD3D9RenderState[GFXRSWrap2] = D3DRS_WRAP2;
GFXD3D9RenderState[GFXRSWrap3] = D3DRS_WRAP3;
GFXD3D9RenderState[GFXRSWrap4] = D3DRS_WRAP4;
GFXD3D9RenderState[GFXRSWrap5] = D3DRS_WRAP5;
GFXD3D9RenderState[GFXRSWrap6] = D3DRS_WRAP6;
GFXD3D9RenderState[GFXRSWrap7] = D3DRS_WRAP7;
GFXD3D9RenderState[GFXRSClipPlaneEnable] = D3DRS_CLIPPLANEENABLE;
GFXD3D9RenderState[GFXRSPointSize] = D3DRS_POINTSIZE;
GFXD3D9RenderState[GFXRSPointSizeMin] = D3DRS_POINTSIZE_MIN;
GFXD3D9RenderState[GFXRSPointSize_Max] = D3DRS_POINTSIZE_MAX;
GFXD3D9RenderState[GFXRSPointSpriteEnable] = D3DRS_POINTSPRITEENABLE;
GFXD3D9RenderState[GFXRSMultiSampleantiAlias] = D3DRS_MULTISAMPLEANTIALIAS;
GFXD3D9RenderState[GFXRSMultiSampleMask] = D3DRS_MULTISAMPLEMASK;
GFXD3D9RenderState[GFXRSShadeMode] = D3DRS_SHADEMODE;
GFXD3D9RenderState[GFXRSLastPixel] = D3DRS_LASTPIXEL;
GFXD3D9RenderState[GFXRSClipping] = D3DRS_CLIPPING;
GFXD3D9RenderState[GFXRSPointScaleEnable] = D3DRS_POINTSCALEENABLE;
GFXD3D9RenderState[GFXRSPointScale_A] = D3DRS_POINTSCALE_A;
GFXD3D9RenderState[GFXRSPointScale_B] = D3DRS_POINTSCALE_B;
GFXD3D9RenderState[GFXRSPointScale_C] = D3DRS_POINTSCALE_C;
GFXD3D9RenderState[GFXRSLighting] = D3DRS_LIGHTING;
GFXD3D9RenderState[GFXRSAmbient] = D3DRS_AMBIENT;
GFXD3D9RenderState[GFXRSFogVertexMode] = D3DRS_FOGVERTEXMODE;
GFXD3D9RenderState[GFXRSColorVertex] = D3DRS_COLORVERTEX;
GFXD3D9RenderState[GFXRSLocalViewer] = D3DRS_LOCALVIEWER;
GFXD3D9RenderState[GFXRSNormalizeNormals] = D3DRS_NORMALIZENORMALS;
GFXD3D9RenderState[GFXRSDiffuseMaterialSource] = D3DRS_DIFFUSEMATERIALSOURCE;
GFXD3D9RenderState[GFXRSSpecularMaterialSource] = D3DRS_SPECULARMATERIALSOURCE;
GFXD3D9RenderState[GFXRSAmbientMaterialSource] = D3DRS_AMBIENTMATERIALSOURCE;
GFXD3D9RenderState[GFXRSEmissiveMaterialSource] = D3DRS_EMISSIVEMATERIALSOURCE;
GFXD3D9RenderState[GFXRSVertexBlend] = D3DRS_VERTEXBLEND;
GFXD3D9RenderState[GFXRSFogEnable] = D3DRS_FOGENABLE;
GFXD3D9RenderState[GFXRSSpecularEnable] = D3DRS_SPECULARENABLE;
GFXD3D9RenderState[GFXRSFogColor] = D3DRS_FOGCOLOR;
GFXD3D9RenderState[GFXRSFogTableMode] = D3DRS_FOGTABLEMODE;
GFXD3D9RenderState[GFXRSFogStart] = D3DRS_FOGSTART;
GFXD3D9RenderState[GFXRSFogEnd] = D3DRS_FOGEND;
GFXD3D9RenderState[GFXRSFogDensity] = D3DRS_FOGDENSITY;
GFXD3D9RenderState[GFXRSRangeFogEnable] = D3DRS_RANGEFOGENABLE;
GFXD3D9RenderState[GFXRSDebugMonitorToken] = D3DRS_DEBUGMONITORTOKEN;
GFXD3D9RenderState[GFXRSIndexedVertexBlendEnable] = D3DRS_INDEXEDVERTEXBLENDENABLE;
GFXD3D9RenderState[GFXRSTweenFactor] = D3DRS_TWEENFACTOR;
GFXD3D9RenderState[GFXRSTextureFactor] = D3DRS_TEXTUREFACTOR;
GFXD3D9RenderState[GFXRSPatchEdgeStyle] = D3DRS_PATCHEDGESTYLE;
GFXD3D9RenderState[GFXRSPositionDegree] = D3DRS_POSITIONDEGREE;
GFXD3D9RenderState[GFXRSNormalDegree] = D3DRS_NORMALDEGREE;
GFXD3D9RenderState[GFXRSAntiAliasedLineEnable] = D3DRS_ANTIALIASEDLINEENABLE;
GFXD3D9RenderState[GFXRSAdaptiveTess_X] = D3DRS_ADAPTIVETESS_X;
GFXD3D9RenderState[GFXRSAdaptiveTess_Y] = D3DRS_ADAPTIVETESS_Y;
GFXD3D9RenderState[GFXRSdaptiveTess_Z] = D3DRS_ADAPTIVETESS_Z;
GFXD3D9RenderState[GFXRSAdaptiveTess_W] = D3DRS_ADAPTIVETESS_W;
GFXD3D9RenderState[GFXRSEnableAdaptiveTesselation] = D3DRS_ENABLEADAPTIVETESSELLATION;
GFXD3D9RenderState[GFXRSDitherEnable] = D3DRS_DITHERENABLE;
GFXD3D9RenderState[GFXRSColorWriteEnable] = D3DRS_COLORWRITEENABLE;
GFXD3D9RenderState[GFXRSBlendOp] = D3DRS_BLENDOP;
GFXD3D9RenderState[GFXRSScissorTestEnable] = D3DRS_SCISSORTESTENABLE;
GFXD3D9RenderState[GFXRSSlopeScaleDepthBias] = D3DRS_SLOPESCALEDEPTHBIAS;
GFXD3D9RenderState[GFXRSMinTessellationLevel] = D3DRS_MINTESSELLATIONLEVEL;
GFXD3D9RenderState[GFXRSMaxTessellationLevel] = D3DRS_MAXTESSELLATIONLEVEL;
GFXD3D9RenderState[GFXRSTwoSidedStencilMode] = D3DRS_TWOSIDEDSTENCILMODE;
GFXD3D9RenderState[GFXRSCCWStencilFail] = D3DRS_CCW_STENCILFAIL;
GFXD3D9RenderState[GFXRSCCWStencilZFail] = D3DRS_CCW_STENCILZFAIL;
GFXD3D9RenderState[GFXRSCCWStencilPass] = D3DRS_CCW_STENCILPASS;
GFXD3D9RenderState[GFXRSCCWStencilFunc] = D3DRS_CCW_STENCILFUNC;
GFXD3D9RenderState[GFXRSColorWriteEnable1] = D3DRS_COLORWRITEENABLE1;
GFXD3D9RenderState[GFXRSColorWriteEnable2] = D3DRS_COLORWRITEENABLE2;
GFXD3D9RenderState[GFXRSolorWriteEnable3] = D3DRS_COLORWRITEENABLE3;
GFXD3D9RenderState[GFXRSBlendFactor] = D3DRS_BLENDFACTOR;
GFXD3D9RenderState[GFXRSSRGBWriteEnable] = D3DRS_SRGBWRITEENABLE;
GFXD3D9RenderState[GFXRSDepthBias] = D3DRS_DEPTHBIAS;
GFXD3D9RenderState[GFXRSWrap8] = D3DRS_WRAP8;
GFXD3D9RenderState[GFXRSWrap9] = D3DRS_WRAP9;
GFXD3D9RenderState[GFXRSWrap10] = D3DRS_WRAP10;
GFXD3D9RenderState[GFXRSWrap11] = D3DRS_WRAP11;
GFXD3D9RenderState[GFXRSWrap12] = D3DRS_WRAP12;
GFXD3D9RenderState[GFXRSWrap13] = D3DRS_WRAP13;
GFXD3D9RenderState[GFXRSWrap14] = D3DRS_WRAP14;
GFXD3D9RenderState[GFXRSWrap15] = D3DRS_WRAP15;
GFXD3D9RenderState[GFXRSSeparateAlphaBlendEnable] = D3DRS_SEPARATEALPHABLENDENABLE;
GFXD3D9RenderState[GFXRSSrcBlendAlpha] = D3DRS_SRCBLENDALPHA;
GFXD3D9RenderState[GFXRSDestBlendAlpha] = D3DRS_DESTBLENDALPHA;
GFXD3D9RenderState[GFXRSBlendOpAlpha] = D3DRS_BLENDOPALPHA;
VALIDATE_LOOKUPTABLE( GFXD3D9RenderState, GFXRenderState );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9TextureFilter, GFXTextureFilter, _D3DTEXTUREFILTERTYPE );
GFXD3D9TextureFilter[GFXTextureFilterNone] = D3DTEXF_NONE;
GFXD3D9TextureFilter[GFXTextureFilterPoint] = D3DTEXF_POINT;
GFXD3D9TextureFilter[GFXTextureFilterLinear] = D3DTEXF_LINEAR;
GFXD3D9TextureFilter[GFXTextureFilterAnisotropic] = D3DTEXF_ANISOTROPIC;
GFXD3D9TextureFilter[GFXTextureFilterPyramidalQuad] = D3DTEXF_PYRAMIDALQUAD;
GFXD3D9TextureFilter[GFXTextureFilterGaussianQuad] = D3DTEXF_GAUSSIANQUAD;
VALIDATE_LOOKUPTABLE( GFXD3D9TextureFilter, GFXTextureFilter );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9Blend, GFXBlend, _D3DBLEND );
GFXD3D9Blend[GFXBlendZero] = D3DBLEND_ZERO;
GFXD3D9Blend[GFXBlendOne] = D3DBLEND_ONE;
GFXD3D9Blend[GFXBlendSrcColor] = D3DBLEND_SRCCOLOR;
GFXD3D9Blend[GFXBlendInvSrcColor] = D3DBLEND_INVSRCCOLOR;
GFXD3D9Blend[GFXBlendSrcAlpha] = D3DBLEND_SRCALPHA;
GFXD3D9Blend[GFXBlendInvSrcAlpha] = D3DBLEND_INVSRCALPHA;
GFXD3D9Blend[GFXBlendDestAlpha] = D3DBLEND_DESTALPHA;
GFXD3D9Blend[GFXBlendInvDestAlpha] = D3DBLEND_INVDESTALPHA;
GFXD3D9Blend[GFXBlendDestColor] = D3DBLEND_DESTCOLOR;
GFXD3D9Blend[GFXBlendInvDestColor] = D3DBLEND_INVDESTCOLOR;
GFXD3D9Blend[GFXBlendSrcAlphaSat] = D3DBLEND_SRCALPHASAT;
VALIDATE_LOOKUPTABLE( GFXD3D9Blend, GFXBlend );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9BlendOp, GFXBlendOp, _D3DBLENDOP );
GFXD3D9BlendOp[GFXBlendOpAdd] = D3DBLENDOP_ADD;
GFXD3D9BlendOp[GFXBlendOpSubtract] = D3DBLENDOP_SUBTRACT;
GFXD3D9BlendOp[GFXBlendOpRevSubtract] = D3DBLENDOP_REVSUBTRACT;
GFXD3D9BlendOp[GFXBlendOpMin] = D3DBLENDOP_MIN;
GFXD3D9BlendOp[GFXBlendOpMax] = D3DBLENDOP_MAX;
VALIDATE_LOOKUPTABLE( GFXD3D9BlendOp, GFXBlendOp );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9StencilOp, GFXStencilOp, _D3DSTENCILOP );
GFXD3D9StencilOp[GFXStencilOpKeep] = D3DSTENCILOP_KEEP;
GFXD3D9StencilOp[GFXStencilOpZero] = D3DSTENCILOP_ZERO;
GFXD3D9StencilOp[GFXStencilOpReplace] = D3DSTENCILOP_REPLACE;
GFXD3D9StencilOp[GFXStencilOpIncrSat] = D3DSTENCILOP_INCRSAT;
GFXD3D9StencilOp[GFXStencilOpDecrSat] = D3DSTENCILOP_DECRSAT;
GFXD3D9StencilOp[GFXStencilOpInvert] = D3DSTENCILOP_INVERT;
GFXD3D9StencilOp[GFXStencilOpIncr] = D3DSTENCILOP_INCR;
GFXD3D9StencilOp[GFXStencilOpDecr] = D3DSTENCILOP_DECR;
VALIDATE_LOOKUPTABLE( GFXD3D9StencilOp, GFXStencilOp );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9CmpFunc, GFXCmp, _D3DCMPFUNC );
GFXD3D9CmpFunc[GFXCmpNever] = D3DCMP_NEVER;
GFXD3D9CmpFunc[GFXCmpLess] = D3DCMP_LESS;
GFXD3D9CmpFunc[GFXCmpEqual] = D3DCMP_EQUAL;
GFXD3D9CmpFunc[GFXCmpLessEqual] = D3DCMP_LESSEQUAL;
GFXD3D9CmpFunc[GFXCmpGreater] = D3DCMP_GREATER;
GFXD3D9CmpFunc[GFXCmpNotEqual] = D3DCMP_NOTEQUAL;
GFXD3D9CmpFunc[GFXCmpGreaterEqual] = D3DCMP_GREATEREQUAL;
GFXD3D9CmpFunc[GFXCmpAlways] = D3DCMP_ALWAYS;
VALIDATE_LOOKUPTABLE( GFXD3D9CmpFunc, GFXCmp );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9CullMode, GFXCull, _D3DCULL );
GFXD3D9CullMode[GFXCullNone] = D3DCULL_NONE;
GFXD3D9CullMode[GFXCullCW] = D3DCULL_CW;
GFXD3D9CullMode[GFXCullCCW] = D3DCULL_CCW;
VALIDATE_LOOKUPTABLE( GFXD3D9CullMode, GFXCull );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9FillMode, GFXFill, _D3DFILLMODE );
GFXD3D9FillMode[GFXFillPoint] = D3DFILL_POINT;
GFXD3D9FillMode[GFXFillWireframe] = D3DFILL_WIREFRAME;
GFXD3D9FillMode[GFXFillSolid] = D3DFILL_SOLID;
VALIDATE_LOOKUPTABLE( GFXD3D9FillMode, GFXFill );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9PrimType, GFXPT, _D3DPRIMITIVETYPE );
GFXD3D9PrimType[GFXPointList] = D3DPT_POINTLIST;
GFXD3D9PrimType[GFXLineList] = D3DPT_LINELIST;
GFXD3D9PrimType[GFXLineStrip] = D3DPT_LINESTRIP;
GFXD3D9PrimType[GFXTriangleList] = D3DPT_TRIANGLELIST;
GFXD3D9PrimType[GFXTriangleStrip] = D3DPT_TRIANGLESTRIP;
GFXD3D9PrimType[GFXTriangleFan] = D3DPT_TRIANGLEFAN;
VALIDATE_LOOKUPTABLE( GFXD3D9PrimType, GFXPT );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9TextureStageState, GFXTSS, _D3DTEXTURESTAGESTATETYPE );
GFXD3D9TextureStageState[GFXTSSColorOp] = D3DTSS_COLOROP;
GFXD3D9TextureStageState[GFXTSSColorArg1] = D3DTSS_COLORARG1;
GFXD3D9TextureStageState[GFXTSSColorArg2] = D3DTSS_COLORARG2;
GFXD3D9TextureStageState[GFXTSSAlphaOp] = D3DTSS_ALPHAOP;
GFXD3D9TextureStageState[GFXTSSAlphaArg1] = D3DTSS_ALPHAARG1;
GFXD3D9TextureStageState[GFXTSSAlphaArg2] = D3DTSS_ALPHAARG2;
GFXD3D9TextureStageState[GFXTSSBumpEnvMat00] = D3DTSS_BUMPENVMAT00;
GFXD3D9TextureStageState[GFXTSSBumpEnvMat01] = D3DTSS_BUMPENVMAT01;
GFXD3D9TextureStageState[GFXTSSBumpEnvMat10] = D3DTSS_BUMPENVMAT10;
GFXD3D9TextureStageState[GFXTSSBumpEnvMat11] = D3DTSS_BUMPENVMAT11;
GFXD3D9TextureStageState[GFXTSSTexCoordIndex] = D3DTSS_TEXCOORDINDEX;
GFXD3D9TextureStageState[GFXTSSBumpEnvlScale] = D3DTSS_BUMPENVLSCALE;
GFXD3D9TextureStageState[GFXTSSBumpEnvlOffset] = D3DTSS_BUMPENVLOFFSET;
GFXD3D9TextureStageState[GFXTSSTextureTransformFlags] = D3DTSS_TEXTURETRANSFORMFLAGS;
GFXD3D9TextureStageState[GFXTSSColorArg0] = D3DTSS_COLORARG0;
GFXD3D9TextureStageState[GFXTSSAlphaArg0] = D3DTSS_ALPHAARG0;
GFXD3D9TextureStageState[GFXTSSResultArg] = D3DTSS_RESULTARG;
GFXD3D9TextureStageState[GFXTSSConstant] = D3DTSS_CONSTANT;
VALIDATE_LOOKUPTABLE( GFXD3D9TextureStageState, GFXTSS );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9TextureAddress, GFXAddress, _D3DTEXTUREADDRESS );
GFXD3D9TextureAddress[GFXAddressWrap] = D3DTADDRESS_WRAP ;
GFXD3D9TextureAddress[GFXAddressMirror] = D3DTADDRESS_MIRROR;
GFXD3D9TextureAddress[GFXAddressClamp] = D3DTADDRESS_CLAMP;
GFXD3D9TextureAddress[GFXAddressBorder] = D3DTADDRESS_BORDER;
GFXD3D9TextureAddress[GFXAddressMirrorOnce] = D3DTADDRESS_MIRRORONCE;
VALIDATE_LOOKUPTABLE(GFXD3D9TextureAddress, GFXAddress );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9TextureOp, GFXTOP, _D3DTEXTUREOP );
GFXD3D9TextureOp[GFXTOPDisable] = D3DTOP_DISABLE;
GFXD3D9TextureOp[GFXTOPSelectARG1] = D3DTOP_SELECTARG1;
GFXD3D9TextureOp[GFXTOPSelectARG2] = D3DTOP_SELECTARG2;
GFXD3D9TextureOp[GFXTOPModulate] = D3DTOP_MODULATE;
GFXD3D9TextureOp[GFXTOPModulate2X] = D3DTOP_MODULATE2X;
GFXD3D9TextureOp[GFXTOPModulate4X] = D3DTOP_MODULATE4X;
GFXD3D9TextureOp[GFXTOPAdd] = D3DTOP_ADD;
GFXD3D9TextureOp[GFXTOPAddSigned] = D3DTOP_ADDSIGNED;
GFXD3D9TextureOp[GFXTOPAddSigned2X] = D3DTOP_ADDSIGNED2X;
GFXD3D9TextureOp[GFXTOPSubtract] = D3DTOP_SUBTRACT;
GFXD3D9TextureOp[GFXTOPAddSmooth] = D3DTOP_ADDSMOOTH;
GFXD3D9TextureOp[GFXTOPBlendDiffuseAlpha] = D3DTOP_BLENDDIFFUSEALPHA;
GFXD3D9TextureOp[GFXTOPBlendTextureAlpha] = D3DTOP_BLENDTEXTUREALPHA;
GFXD3D9TextureOp[GFXTOPBlendFactorAlpha] = D3DTOP_BLENDFACTORALPHA;
GFXD3D9TextureOp[GFXTOPBlendTextureAlphaPM] = D3DTOP_BLENDTEXTUREALPHAPM;
GFXD3D9TextureOp[GFXTOPBlendCURRENTALPHA] = D3DTOP_BLENDCURRENTALPHA;
GFXD3D9TextureOp[GFXTOPPreModulate] = D3DTOP_PREMODULATE;
GFXD3D9TextureOp[GFXTOPModulateAlphaAddColor] = D3DTOP_MODULATEALPHA_ADDCOLOR;
GFXD3D9TextureOp[GFXTOPModulateColorAddAlpha] = D3DTOP_MODULATECOLOR_ADDALPHA;
GFXD3D9TextureOp[GFXTOPModulateInvAlphaAddColor] = D3DTOP_MODULATEINVALPHA_ADDCOLOR;
GFXD3D9TextureOp[GFXTOPModulateInvColorAddAlpha] = D3DTOP_MODULATEINVCOLOR_ADDALPHA;
GFXD3D9TextureOp[GFXTOPBumpEnvMap] = D3DTOP_BUMPENVMAP;
GFXD3D9TextureOp[GFXTOPBumpEnvMapLuminance] = D3DTOP_BUMPENVMAPLUMINANCE;
GFXD3D9TextureOp[GFXTOPDotProduct3] = D3DTOP_DOTPRODUCT3;
GFXD3D9TextureOp[GFXTOPLERP] = D3DTOP_LERP;
VALIDATE_LOOKUPTABLE( GFXD3D9TextureOp, GFXTOP );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXD3D9DeclType, GFXDeclType, _D3DDECLTYPE );
GFXD3D9DeclType[GFXDeclType_Float] = D3DDECLTYPE_FLOAT1;
GFXD3D9DeclType[GFXDeclType_Float2] = D3DDECLTYPE_FLOAT2;
GFXD3D9DeclType[GFXDeclType_Float3] = D3DDECLTYPE_FLOAT3;
GFXD3D9DeclType[GFXDeclType_Float4] = D3DDECLTYPE_FLOAT4;
GFXD3D9DeclType[GFXDeclType_Color] = D3DDECLTYPE_D3DCOLOR;
VALIDATE_LOOKUPTABLE( GFXD3D9DeclType, GFXDeclType );
}

View file

@ -0,0 +1,94 @@
//-----------------------------------------------------------------------------
// 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 "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9PrimitiveBuffer.h"
#include "core/util/safeRelease.h"
void GFXD3D9PrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr)
{
AssertFatal(!mLocked, "GFXD3D9PrimitiveBuffer::lock - Can't lock a primitive buffer more than once!");
mLocked = true;
U32 flags=0;
switch(mBufferType)
{
case GFXBufferTypeStatic:
// flags |= D3DLOCK_DISCARD;
break;
case GFXBufferTypeDynamic:
// Always discard the content within a locked region.
flags |= D3DLOCK_DISCARD;
break;
case GFXBufferTypeVolatile:
// Get our range now...
AssertFatal(indexStart == 0, "Cannot get a subrange on a volatile buffer.");
AssertFatal(indexEnd < MAX_DYNAMIC_INDICES, "Cannot get more than MAX_DYNAMIC_INDICES in a volatile buffer. Up the constant!");
// Get the primtive buffer
mVolatileBuffer = ((GFXD3D9Device*)mDevice)->mDynamicPB;
AssertFatal( mVolatileBuffer, "GFXD3D9PrimitiveBuffer::lock - No dynamic primitive buffer was available!");
// We created the pool when we requested this volatile buffer, so assume it exists...
if( mVolatileBuffer->mIndexCount + indexEnd > MAX_DYNAMIC_INDICES )
{
flags |= D3DLOCK_DISCARD;
mVolatileStart = indexStart = 0;
indexEnd = indexEnd;
}
else
{
flags |= D3DLOCK_NOOVERWRITE;
mVolatileStart = indexStart = mVolatileBuffer->mIndexCount;
indexEnd += mVolatileBuffer->mIndexCount;
}
mVolatileBuffer->mIndexCount = indexEnd + 1;
ib = mVolatileBuffer->ib;
break;
}
D3D9Assert( ib->Lock(indexStart * sizeof(U16), (indexEnd - indexStart) * sizeof(U16), indexPtr, flags),
"GFXD3D9PrimitiveBuffer::lock - Could not lock primitive buffer.");
#ifdef TORQUE_DEBUG
// Allocate a debug buffer large enough for the lock
// plus space for over and under run guard strings.
mLockedSize = (indexEnd - indexStart) * sizeof(U16);
const U32 guardSize = sizeof( _PBGuardString );
mDebugGuardBuffer = new U8[mLockedSize+(guardSize*2)];
// Setup the guard strings.
dMemcpy( mDebugGuardBuffer, _PBGuardString, guardSize );
dMemcpy( mDebugGuardBuffer + mLockedSize + guardSize, _PBGuardString, guardSize );
// Store the real lock pointer and return our debug pointer.
mLockedBuffer = *indexPtr;
*indexPtr = (U16*)( mDebugGuardBuffer + guardSize );
#endif // TORQUE_DEBUG
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,81 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFX_PC_D3D9DEVICE_H_
#define _GFX_PC_D3D9DEVICE_H_
#include "gfx/D3D9/gfxD3D9Device.h"
class PlatformWindow;
class VideoFrameGrabberD3D9;
class GFXPCD3D9Device : public GFXD3D9Device
{
typedef GFXD3D9Device Parent;
public:
// Set to true to force nvperfhud device creation
static bool mEnableNVPerfHUD;
GFXPCD3D9Device( LPDIRECT3D9 d3d, U32 index )
: GFXD3D9Device( d3d, index ),
mVideoFrameGrabber( NULL ) {};
~GFXPCD3D9Device();
static GFXDevice *createInstance( U32 adapterIndex );
virtual GFXFormat selectSupportedFormat(GFXTextureProfile *profile,
const Vector<GFXFormat> &formats, bool texture, bool mustblend, bool mustfilter);
static void enumerateAdapters( Vector<GFXAdapter*> &adapterList );
virtual void enumerateVideoModes();
virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window);
virtual GFXTextureTarget *allocRenderToTextureTarget();
virtual bool beginSceneInternal();
virtual void init( const GFXVideoMode &mode, PlatformWindow *window = NULL );
virtual void enterDebugEvent(ColorI color, const char *name);
virtual void leaveDebugEvent();
virtual void setDebugMarker(ColorI color, const char *name);
virtual void setMatrix( GFXMatrixType mtype, const MatrixF &mat );
virtual void initStates();
virtual void reset( D3DPRESENT_PARAMETERS &d3dpp );
virtual D3DPRESENT_PARAMETERS setupPresentParams( const GFXVideoMode &mode, const HWND &hwnd ) const;
protected:
VideoFrameGrabberD3D9* mVideoFrameGrabber;
static GFXAdapter::CreateDeviceInstanceDelegate mCreateDeviceInstance;
static void createDirect3D9(LPDIRECT3D9 &d3d9, LPDIRECT3D9EX &d3d9ex);
HRESULT createDevice(U32 adapter, D3DDEVTYPE deviceType, HWND hFocusWindow, DWORD behaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters);
virtual void _setTextureStageState( U32 stage, U32 state, U32 value );
void _validateMultisampleParams(D3DFORMAT format, D3DMULTISAMPLE_TYPE & aatype, DWORD & aalevel) const;
};
#endif

View file

@ -0,0 +1,587 @@
//-----------------------------------------------------------------------------
// 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/D3D9/pc/gfxPCD3D9Target.h"
#include "gfx/D3D9/gfxD3D9Device.h"
#include "gfx/D3D9/gfxD3D9TextureObject.h"
#include "gfx/D3D9/gfxD3D9Cubemap.h"
#include "gfx/D3D9/gfxD3D9EnumTranslate.h"
#include "gfx/D3D9/pc/gfxPCD3D9Device.h"
#include "gfx/gfxDebugEvent.h"
#include "windowManager/win32/win32Window.h"
GFXPCD3D9TextureTarget::GFXPCD3D9TextureTarget()
: mTargetSize( Point2I::Zero ),
mTargetFormat( GFXFormatR8G8B8A8 )
{
for(S32 i=0; i<MaxRenderSlotId; i++)
{
mTargets[i] = NULL;
mResolveTargets[i] = NULL;
}
}
GFXPCD3D9TextureTarget::~GFXPCD3D9TextureTarget()
{
// Release anything we might be holding.
for(S32 i=0; i<MaxRenderSlotId; i++)
{
mResolveTargets[i] = NULL;
if( GFXDevice::devicePresent() )
{
mDevice->destroyD3DResource( mTargets[i] ); // SAFE_RELEASE
mTargets[i] = NULL;
}
else
SAFE_RELEASE( mTargets[i] );
}
zombify();
}
void GFXPCD3D9TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_attachTexture, ColorI::RED );
AssertFatal(slot < MaxRenderSlotId, "GFXPCD3D9TextureTarget::attachTexture - out of range slot.");
// TODO: The way this is implemented... you can attach a texture
// object multiple times and it will release and reset it.
//
// We should rework this to detect when no change has occured
// and skip out early.
// Mark state as dirty so device can know to update.
invalidateState();
// Release what we had, it's definitely going to change.
mDevice->destroyD3DResource( mTargets[slot] ); // SAFE_RELEASE
mTargets[slot] = NULL;
mResolveTargets[slot] = NULL;
if(slot == Color0)
{
mTargetSize = Point2I::Zero;
mTargetFormat = GFXFormatR8G8B8A8;
}
// Are we clearing?
if(!tex)
{
// Yup - just exit, it'll stay NULL.
return;
}
// Take care of default targets
if( tex == GFXTextureTarget::sDefaultDepthStencil )
{
mTargets[slot] = mDevice->mDeviceDepthStencil;
mTargets[slot]->AddRef();
}
else
{
// Cast the texture object to D3D...
AssertFatal(dynamic_cast<GFXD3D9TextureObject*>(tex),
"GFXPCD3D9TextureTarget::attachTexture - invalid texture object.");
GFXD3D9TextureObject *d3dto = static_cast<GFXD3D9TextureObject*>(tex);
// Grab the surface level.
if( slot == DepthStencil )
{
mTargets[slot] = d3dto->getSurface();
if ( mTargets[slot] )
mTargets[slot]->AddRef();
}
else
{
// getSurface will almost always return NULL. It will only return non-NULL
// if the surface that it needs to render to is different than the mip level
// in the actual texture. This will happen with MSAA.
if( d3dto->getSurface() == NULL )
{
D3D9Assert(d3dto->get2DTex()->GetSurfaceLevel(mipLevel, &mTargets[slot]),
"GFXPCD3D9TextureTarget::attachTexture - could not get surface level for the passed texture!");
}
else
{
mTargets[slot] = d3dto->getSurface();
mTargets[slot]->AddRef();
// Only assign resolve target if d3dto has a surface to give us.
//
// That usually means there is an MSAA target involved, which is why
// the resolve is needed to get the data out of the target.
mResolveTargets[slot] = d3dto;
if ( tex && slot == Color0 )
{
mTargetSize.set( tex->getSize().x, tex->getSize().y );
mTargetFormat = tex->getFormat();
}
}
}
// Update surface size
if(slot == Color0)
{
IDirect3DSurface9 *surface = mTargets[Color0];
if ( surface )
{
D3DSURFACE_DESC sd;
surface->GetDesc(&sd);
mTargetSize = Point2I(sd.Width, sd.Height);
S32 format = sd.Format;
GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, format );
mTargetFormat = (GFXFormat)format;
}
}
}
}
void GFXPCD3D9TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_attachTexture_Cubemap, ColorI::RED );
AssertFatal(slot < MaxRenderSlotId, "GFXPCD3D9TextureTarget::attachTexture - out of range slot.");
// Mark state as dirty so device can know to update.
invalidateState();
// Release what we had, it's definitely going to change.
mDevice->destroyD3DResource( mTargets[slot] ); // SAFE_RELEASE
mTargets[slot] = NULL;
mResolveTargets[slot] = NULL;
// Cast the texture object to D3D...
AssertFatal(!tex || dynamic_cast<GFXD3D9Cubemap*>(tex),
"GFXD3DTextureTarget::attachTexture - invalid cubemap object.");
GFXD3D9Cubemap *cube = static_cast<GFXD3D9Cubemap*>(tex);
if(slot == Color0)
{
mTargetSize = Point2I::Zero;
mTargetFormat = GFXFormatR8G8B8A8;
}
// Are we clearing?
if(!tex)
{
// Yup - just exit, it'll stay NULL.
return;
}
D3D9Assert(cube->mCubeTex->GetCubeMapSurface( (D3DCUBEMAP_FACES)face, mipLevel, &mTargets[slot] ),
"GFXD3DTextureTarget::attachTexture - could not get surface level for the passed texture!");
// Update surface size
if(slot == Color0)
{
IDirect3DSurface9 *surface = mTargets[Color0];
if ( surface )
{
D3DSURFACE_DESC sd;
surface->GetDesc(&sd);
mTargetSize = Point2I(sd.Width, sd.Height);
S32 format = sd.Format;
GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, format );
mTargetFormat = (GFXFormat)format;
}
}
}
void GFXPCD3D9TextureTarget::activate()
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_activate, ColorI::RED );
AssertFatal( mTargets[GFXTextureTarget::Color0],
"GFXPCD3D9TextureTarget::activate() - You can never have a NULL primary render target!" );
const U32 NumRenderTargets = getMin( mDevice->getNumRenderTargets(), (U32)Color4 - Color0 );
LPDIRECT3DDEVICE9 d3dDevice = mDevice->getDevice();
// Clear the state indicator.
stateApplied();
IDirect3DSurface9 *depth = mTargets[GFXTextureTarget::DepthStencil];
// In debug lets do a complete test to be sure we don't
// have a bad depth format for this display mode.
#ifdef TORQUE_DEBUG
if ( depth && mTargets[GFXTextureTarget::Color0] )
{
D3DSURFACE_DESC desc;
D3D9Assert( mTargets[GFXTextureTarget::Color0]->GetDesc( &desc ),
"GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
D3DFORMAT renderFormat = desc.Format;
D3D9Assert( depth->GetDesc( &desc ),
"GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
D3DFORMAT depthFormat = desc.Format;
HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
mDevice->mDisplayMode.Format,
renderFormat,
depthFormat );
D3D9Assert( hr, "GFXPCD3D9TextureTarget::activate() - Bad depth format for this target!" );
}
#endif
// First clear the non-primary targets to make the debug DX runtime happy.
for(U32 i = 1; i < NumRenderTargets; i++)
D3D9Assert(d3dDevice->SetRenderTarget( i, NULL ),
avar("GFXPCD3D9TextureTarget::activate() - failed to clear texture target %d!", i) );
// Now set all the new surfaces into the appropriate slots.
for(U32 i = 0; i < NumRenderTargets; i++)
{
IDirect3DSurface9 *target = mTargets[GFXTextureTarget::Color0 + i];
if ( target )
{
D3D9Assert(d3dDevice->SetRenderTarget(i, target),
avar("GFXPCD3D9TextureTarget::activate() - failed to set slot %d for texture target!", i) );
}
}
// TODO: This is often the same shared depth buffer used by most
// render targets. Are we getting performance hit from setting it
// multiple times... aside from the function call?
D3D9Assert(d3dDevice->SetDepthStencilSurface( depth ),
"GFXPCD3D9TextureTarget::activate() - failed to set depthstencil target!" );
}
void GFXPCD3D9TextureTarget::deactivate()
{
// Nothing to do... the next activate() call will
// set all the targets correctly.
}
void GFXPCD3D9TextureTarget::resolve()
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_resolve, ColorI::RED );
for (U32 i = 0; i < MaxRenderSlotId; i++)
{
// We use existance @ mResolveTargets as a flag that we need to copy
// data from the rendertarget into the texture.
if (mResolveTargets[i])
{
IDirect3DSurface9 *surf;
D3D9Assert( mResolveTargets[i]->get2DTex()->GetSurfaceLevel( 0, &surf ),
"GFXPCD3D9TextureTarget::resolve() - GetSurfaceLevel failed!" );
D3D9Assert( mDevice->getDevice()->StretchRect( mTargets[i], NULL, surf, NULL, D3DTEXF_NONE ),
"GFXPCD3D9TextureTarget::resolve() - StretchRect failed!" );
surf->Release();
}
}
}
void GFXPCD3D9TextureTarget::resolveTo( GFXTextureObject *tex )
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_resolveTo, ColorI::RED );
if ( mTargets[Color0] == NULL )
return;
IDirect3DSurface9 *surf;
D3D9Assert( ((GFXD3D9TextureObject*)(tex))->get2DTex()->GetSurfaceLevel( 0, &surf ),
"GFXPCD3D9TextureTarget::resolveTo() - GetSurfaceLevel failed!" );
D3D9Assert( mDevice->getDevice()->StretchRect( mTargets[Color0], NULL, surf, NULL, D3DTEXF_NONE ),
"GFXPCD3D9TextureTarget::resolveTo() - StretchRect failed!" );
surf->Release();
}
void GFXPCD3D9TextureTarget::zombify()
{
for(int i = 0; i < MaxRenderSlotId; i++)
attachTexture(RenderSlot(i), NULL);
}
void GFXPCD3D9TextureTarget::resurrect()
{
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
GFXPCD3D9WindowTarget::GFXPCD3D9WindowTarget()
{
mSwapChain = NULL;
mDepthStencil = NULL;
mWindow = NULL;
mDevice = NULL;
mBackbuffer = NULL;
mImplicit = true;
}
GFXPCD3D9WindowTarget::~GFXPCD3D9WindowTarget()
{
SAFE_RELEASE(mSwapChain);
SAFE_RELEASE(mDepthStencil);
SAFE_RELEASE(mBackbuffer);
}
void GFXPCD3D9WindowTarget::initPresentationParams()
{
// Get some video mode related info.
GFXVideoMode vm = mWindow->getVideoMode();
// Do some validation...
if(vm.fullScreen == true && mImplicit == false)
{
AssertISV(false,
"GFXPCD3D9WindowTarget::initPresentationParams - Cannot go fullscreen with secondary window!");
}
Win32Window *win = dynamic_cast<Win32Window*>(mWindow);
AssertISV(win, "GFXPCD3D9WindowTarget::initPresentationParams() - got a non Win32Window window passed in! Did DX go crossplatform?");
HWND hwnd = win->getHWND();
// At some point, this will become GFXPCD3D9WindowTarget like trunk has,
// so this cast isn't as bad as it looks. ;) BTR
GFXPCD3D9Device* pcdevice = dynamic_cast<GFXPCD3D9Device*>(mDevice);
mPresentationParams = pcdevice->setupPresentParams(vm, hwnd);
if (mImplicit)
{
pcdevice->mMultisampleType = mPresentationParams.MultiSampleType;
pcdevice->mMultisampleLevel = mPresentationParams.MultiSampleQuality;
}
}
const Point2I GFXPCD3D9WindowTarget::getSize()
{
return mWindow->getVideoMode().resolution;
}
GFXFormat GFXPCD3D9WindowTarget::getFormat()
{
S32 format = mPresentationParams.BackBufferFormat;
GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, format );
return (GFXFormat)format;
}
bool GFXPCD3D9WindowTarget::present()
{
AssertFatal(mSwapChain, "GFXPCD3D9WindowTarget::present - no swap chain present to present!");
HRESULT res = mSwapChain->Present(NULL, NULL, NULL, NULL, NULL);
return (res == S_OK);
}
void GFXPCD3D9WindowTarget::setImplicitSwapChain()
{
AssertFatal(mImplicit, "Invalid swap chain type! Additional swap chains are created as needed");
// Reacquire our swapchain & DS
if(!mSwapChain)
mDevice->getDevice()->GetSwapChain(0, &mSwapChain);
if(!mDepthStencil)
mDevice->getDevice()->GetDepthStencilSurface(&mDepthStencil);
if (!mBackbuffer)
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackbuffer);
}
void GFXPCD3D9WindowTarget::createAdditionalSwapChain()
{
AssertFatal(!mImplicit, "Invalid swap chain type! Implicit swap chains use the device");
// Since we're not going to do a device reset for an additional swap
// chain, we can just release our resources and regrab them.
SAFE_RELEASE(mSwapChain);
SAFE_RELEASE(mDepthStencil);
SAFE_RELEASE(mBackbuffer);
// If there's a fullscreen window active, don't try to create these additional swap chains.
// CodeReview, we need to store the window target with the implicit swap chain better, this line below
// could fail if the current render target isn't what we expect.
GFXPCD3D9WindowTarget* currTarget = dynamic_cast<GFXPCD3D9WindowTarget*>(mDevice->getActiveRenderTarget());
if (currTarget && currTarget->getWindow()->getVideoMode().fullScreen)
return;
// Setup our presentation params.
initPresentationParams();
// Create our resources!
D3D9Assert(mDevice->getDevice()->CreateAdditionalSwapChain(&mPresentationParams, &mSwapChain),
"GFXPCD3D9WindowTarget::createAdditionalSwapChain - couldn't reallocate additional swap chain!");
D3D9Assert(mDevice->getDevice()->CreateDepthStencilSurface(mPresentationParams.BackBufferWidth, mPresentationParams.BackBufferHeight,
D3DFMT_D24S8, mPresentationParams.MultiSampleType, mPresentationParams.MultiSampleQuality, false, &mDepthStencil, NULL),
"GFXPCD3D9WindowTarget::createAdditionalSwapChain: Unable to create stencil/depth surface");
D3D9Assert(mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackbuffer),
"GFXPCD3D9WindowTarget::createAdditionalSwapChain: Unable to get backbuffer!");
}
void GFXPCD3D9WindowTarget::resetMode()
{
mWindow->setSuppressReset(true);
if (mSwapChain)
{
// The current video settings.
D3DPRESENT_PARAMETERS pp;
mSwapChain->GetPresentParameters(&pp);
bool ppFullscreen = !pp.Windowed;
Point2I backbufferSize(pp.BackBufferWidth, pp.BackBufferHeight);
// The settings we are now applying.
const GFXVideoMode &mode = mWindow->getVideoMode();
// Convert the current multisample parameters into something
// we can compare with our GFXVideoMode.antialiasLevel value.
U32 ppAntiAliaseLevel = 0;
if ( pp.MultiSampleType != D3DMULTISAMPLE_NONE )
ppAntiAliaseLevel = pp.MultiSampleQuality + 1;
// Early out if none of the settings which require a device reset
// have changed.
if ( backbufferSize == getSize() &&
ppFullscreen == mode.fullScreen &&
ppAntiAliaseLevel == mode.antialiasLevel )
return;
}
// So, the video mode has changed - if we're an additional swap chain
// just kill the swapchain and reallocate to match new vid mode.
if(mImplicit == false)
{
createAdditionalSwapChain();
}
else
{
// Setup our presentation params.
initPresentationParams();
// Otherwise, we have to reset the device, if we're the implicit swapchain.
mDevice->reset(mPresentationParams);
}
// Update our size, too.
mSize = Point2I(mPresentationParams.BackBufferWidth, mPresentationParams.BackBufferHeight);
mWindow->setSuppressReset(false);
}
void GFXPCD3D9WindowTarget::zombify()
{
// Release our resources
SAFE_RELEASE(mSwapChain);
SAFE_RELEASE(mDepthStencil);
SAFE_RELEASE(mBackbuffer);
}
void GFXPCD3D9WindowTarget::resurrect()
{
if(mImplicit)
{
setImplicitSwapChain();
}
else if(!mSwapChain)
{
createAdditionalSwapChain();
}
}
void GFXPCD3D9WindowTarget::activate()
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9WindowTarget_activate, ColorI::RED );
LPDIRECT3DDEVICE9 d3dDevice = mDevice->getDevice();
// In debug lets do a complete test to be sure we don't
// have a bad depth format for this display mode.
#ifdef TORQUE_DEBUG
if ( mDepthStencil && mBackbuffer )
{
D3DSURFACE_DESC desc;
D3D9Assert( mBackbuffer->GetDesc( &desc ),
"GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
D3DFORMAT renderFormat = desc.Format;
D3D9Assert( mDepthStencil->GetDesc( &desc ),
"GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
D3DFORMAT depthFormat = desc.Format;
HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
mDevice->mDisplayMode.Format,
renderFormat,
depthFormat );
D3D9Assert( hr, "GFXPCD3D9WindowTarget::activate() - Bad depth format for this back buffer!" );
}
#endif
D3D9Assert( d3dDevice->SetRenderTarget( 0, mBackbuffer ),
"GFXPCD3D9WindowTarget::activate() - Failed to set backbuffer target!" );
D3D9Assert( d3dDevice->SetDepthStencilSurface( mDepthStencil ),
"GFXPCD3D9WindowTarget::activate() - Failed to set depthstencil target!" );
D3DPRESENT_PARAMETERS pp;
mSwapChain->GetPresentParameters(&pp);
// Update our video mode here, too.
GFXVideoMode vm;
vm = mWindow->getVideoMode();
vm.resolution.x = pp.BackBufferWidth;
vm.resolution.y = pp.BackBufferHeight;
vm.fullScreen = !pp.Windowed;
mSize = vm.resolution;
}
void GFXPCD3D9WindowTarget::resolveTo( GFXTextureObject *tex )
{
GFXDEBUGEVENT_SCOPE( GFXPCD3D9WindowTarget_resolveTo, ColorI::RED );
IDirect3DSurface9 *surf;
D3D9Assert( ((GFXD3D9TextureObject*)(tex))->get2DTex()->GetSurfaceLevel( 0, &surf ),
"GFXPCD3D9WindowTarget::resolveTo() - GetSurfaceLevel failed!" );
D3D9Assert( mDevice->getDevice()->StretchRect( mBackbuffer, NULL, surf, NULL, D3DTEXF_NONE ),
"GFXPCD3D9WindowTarget::resolveTo() - StretchRect failed!" );
surf->Release();
}

View file

@ -0,0 +1,130 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFX_D3D_GFXD3D9TARGET_H_
#define _GFX_D3D_GFXD3D9TARGET_H_
#ifndef _GFXTARGET_H_
#include "gfx/gfxTarget.h"
#endif
#ifndef _MPOINT3_H_
#include "math/mPoint3.h"
#endif
#ifndef _MPOINT2_H_
#include "math/mPoint2.h"
#endif
#include <d3d9.h>
struct IDirect3DSurface9;
struct IDirect3DSwapChain9;
class GFXD3D9TextureObject;
class GFXPCD3D9TextureTarget : public GFXTextureTarget
{
friend class GFXPCD3D9Device;
// Array of target surfaces, this is given to us by attachTexture
IDirect3DSurface9 * mTargets[MaxRenderSlotId];
// Array of texture objects which correspond to the target surfaces above,
// needed for copy from RenderTarget to texture situations. Current only valid in those situations
GFXD3D9TextureObject* mResolveTargets[MaxRenderSlotId];
/// Owning d3d device.
GFXD3D9Device *mDevice;
Point2I mTargetSize;
GFXFormat mTargetFormat;
public:
GFXPCD3D9TextureTarget();
~GFXPCD3D9TextureTarget();
// Public interface.
virtual const Point2I getSize() { return mTargetSize; }
virtual GFXFormat getFormat() { return mTargetFormat; }
virtual void attachTexture(RenderSlot slot, GFXTextureObject *tex, U32 mipLevel=0, U32 zOffset = 0);
virtual void attachTexture(RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel=0);
virtual void resolve();
/// Note we always copy the Color0 RenderSlot.
virtual void resolveTo( GFXTextureObject *tex );
virtual void activate();
virtual void deactivate();
void zombify();
void resurrect();
};
class GFXPCD3D9WindowTarget : public GFXWindowTarget
{
friend class GFXPCD3D9Device;
/// Our depth stencil buffer, if any.
IDirect3DSurface9 *mDepthStencil;
/// Our backbuffer
IDirect3DSurface9 *mBackbuffer;
/// Maximum size we can render to.
Point2I mSize;
/// Our swap chain, potentially the implicit device swap chain.
IDirect3DSwapChain9 *mSwapChain;
/// D3D presentation info.
D3DPRESENT_PARAMETERS mPresentationParams;
/// Owning d3d device.
GFXD3D9Device *mDevice;
/// Is this the implicit swap chain?
bool mImplicit;
/// Internal interface that notifies us we need to reset our video mode.
void resetMode();
public:
GFXPCD3D9WindowTarget();
~GFXPCD3D9WindowTarget();
virtual const Point2I getSize();
virtual GFXFormat getFormat();
virtual bool present();
void initPresentationParams();
void setImplicitSwapChain();
void createAdditionalSwapChain();
virtual void activate();
void zombify();
void resurrect();
virtual void resolveTo( GFXTextureObject *tex );
};
#endif // _GFX_D3D_GFXD3D9TARGET_H_

View file

@ -0,0 +1,110 @@
//-----------------------------------------------------------------------------
// 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/D3D9/screenshotD3D9.h"
#include "gfx/D3D9/gfxD3D9Device.h"
#include <d3d9.h>
#include <d3dx9core.h>
#include <d3dx9tex.h>
GBitmap* ScreenShotD3D::_captureBackBuffer()
{
#ifdef TORQUE_OS_XENON
return NULL;
#else
LPDIRECT3DDEVICE9 D3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
IDirect3DSurface9 * backBuffer;
D3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer );
// Figure the size we're snagging.
D3DSURFACE_DESC desc;
backBuffer->GetDesc(&desc);
Point2I size;
size.x = desc.Width;
size.y = desc.Height;
// set up the 2 copy surfaces
GFXTexHandle tex[2];
IDirect3DSurface9 *surface[2];
tex[0].set( size.x, size.y, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile, avar("%s() - tex[0] (line %d)", __FUNCTION__, __LINE__) );
tex[1].set( size.x, size.y, GFXFormatR8G8B8X8, &GFXSystemMemProfile, avar("%s() - tex[1] (line %d)", __FUNCTION__, __LINE__) );
// grab the top level surface of tex 0
GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*tex[0]);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &surface[0] ), NULL );
// use StretchRect because it allows a copy from a multisample surface
// to a normal rendertarget surface
D3DDevice->StretchRect( backBuffer, NULL, surface[0], NULL, D3DTEXF_NONE );
// grab the top level surface of tex 1
to = (GFXD3D9TextureObject *) &(*tex[1]);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &surface[1] ), NULL );
// copy the data from the render target to the system memory texture
D3DDevice->GetRenderTargetData( surface[0], surface[1] );
// Allocate a GBitmap and copy into it.
GBitmap *gb = new GBitmap(size.x, size.y);
D3DLOCKED_RECT r;
D3DSURFACE_DESC d;
surface[1]->GetDesc(&d);
surface[1]->LockRect( &r, NULL, D3DLOCK_READONLY);
// We've got the X8 in there so we have to manually copy stuff.
ColorI c;
for(S32 i=0; i<size.y; i++)
{
const U8 *a = ((U8*)r.pBits) + i * size.x * 4;
for(S32 j=0; j<size.x; j++)
{
c.blue = *(a++);
c.green = *(a++);
c.red = *(a++);
a++; // Ignore X.
gb->setColor(j, i, c);
}
}
surface[1]->UnlockRect();
// Also save it out with D3DX
//D3DXSaveSurfaceToFile( dT( "testScreen.png" ), D3DXIFF_PNG, surface[1], NULL, NULL );
// release the COM pointers
surface[0]->Release();
surface[1]->Release();
backBuffer->Release();
return gb;
#endif
}

View file

@ -0,0 +1,39 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _SCREENSHOTD3D_H_
#define _SCREENSHOTD3D_H_
#include "gfx/screenshot.h"
//**************************************************************************
// D3D implementation of screenshot
//**************************************************************************
class ScreenShotD3D : public ScreenShot
{
protected:
GBitmap* _captureBackBuffer();
};
#endif // _SCREENSHOTD3D_H_

View file

@ -0,0 +1,210 @@
//-----------------------------------------------------------------------------
// 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 "videoCaptureD3D9.h"
#include "gfx/D3D9/gfxD3D9Device.h"
#include "platform/tmm_off.h"
#include <d3d9.h>
#include <d3dx9core.h>
#include <d3dx9tex.h>
VideoFrameGrabberD3D9::VideoFrameGrabberD3D9()
{
GFXDevice::getDeviceEventSignal().notify( this, &VideoFrameGrabberD3D9::_handleGFXEvent );
mCurrentCapture = 0;
}
VideoFrameGrabberD3D9::~VideoFrameGrabberD3D9()
{
GFXDevice::getDeviceEventSignal().remove( this, &VideoFrameGrabberD3D9::_handleGFXEvent );
}
void VideoFrameGrabberD3D9::captureBackBuffer()
{
AssertFatal( mCapture[mCurrentCapture].stage != eInSystemMemory, "Error! Trying to override a capture resource in \"SystemMemory\" stage!" );
#ifndef TORQUE_OS_XENON
LPDIRECT3DDEVICE9 D3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
IDirect3DSurface9 * backBuffer;
D3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer );
GFXTexHandle &vidMemTex = mCapture[mCurrentCapture].vidMemTex;
// Re-init video memory texture if needed
if (vidMemTex.isNull() || vidMemTex.getWidthHeight() != mResolution)
vidMemTex.set(mResolution.x, mResolution.y,GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile, avar("%s() - mVidMemTex (line %d)", __FUNCTION__, __LINE__) );
// set up the copy surface
IDirect3DSurface9 *surface;
// grab the top level surface of tex 0
GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*vidMemTex);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &surface ), NULL );
// use StretchRect because it allows a copy from a multisample surface
// to a normal rendertarget surface
D3DDevice->StretchRect( backBuffer, NULL, surface, NULL, D3DTEXF_LINEAR );
// Reelase surfaces
backBuffer->Release();
surface->Release();
// Update the stage
mCapture[mCurrentCapture].stage = eInVideoMemory;
#endif
}
void VideoFrameGrabberD3D9::makeBitmap()
{
// Advance the stages for all resources, except the one used for the last capture
for (U32 i=0; i<eNumStages; i++)
{
if (i == mCurrentCapture)
continue;
switch (mCapture[i].stage)
{
case eInVideoMemory:
copyToSystemMemory(mCapture[i]);
break;
case eInSystemMemory:
copyToBitmap(mCapture[i]);
break;
}
}
// Change the resource being used for backbuffer captures
mCurrentCapture = (mCurrentCapture + 1) % eNumStages;
AssertFatal( mCapture[mCurrentCapture].stage != eInSystemMemory, "Error! A capture resource with an invalid state was picked for making captures!" );
}
void VideoFrameGrabberD3D9::releaseTextures()
{
for (U32 i=0; i<eNumStages; i++)
{
mCapture[i].sysMemTex.free();
mCapture[i].vidMemTex.free();
mCapture[i].stage = eReadyToCapture;
}
}
void VideoFrameGrabberD3D9::copyToSystemMemory(CaptureResource &capture)
{
AssertFatal( capture.stage == eInVideoMemory, "Error! copyToSystemMemory() can only work in resources in 'eInVideoMemory' stage!" );
#ifndef TORQUE_OS_XENON
GFXTexHandle &vidMemTex = capture.vidMemTex;
GFXTexHandle &sysMemTex = capture.sysMemTex;
// Initialize system memory texture if necessary
Point2I size = vidMemTex.getWidthHeight();
if (sysMemTex.isNull() || sysMemTex.getWidthHeight() != size)
sysMemTex.set( size.x, size.y, GFXFormatR8G8B8X8, &GFXSystemMemProfile, avar("%s() - tex (line %d)", __FUNCTION__, __LINE__) );
// set up the 2 copy surfaces
IDirect3DSurface9 *surface[2];
// grab the top level surface of tex 0
GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*vidMemTex);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &surface[0] ), NULL );
// grab the top level surface of tex 1
to = (GFXD3D9TextureObject *) &(*sysMemTex);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &surface[1] ), NULL );
// copy the data from the render target to the system memory texture
LPDIRECT3DDEVICE9 D3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
D3DDevice->GetRenderTargetData( surface[0], surface[1] );
// celease surfaces
surface[0]->Release();
surface[1]->Release();
// Change the resource state
capture.stage = eInSystemMemory;
#endif
}
void VideoFrameGrabberD3D9::copyToBitmap(CaptureResource &capture)
{
AssertFatal( capture.stage == eInSystemMemory, "Error! copyToBitmap() can only work in resources in 'eInSystemMemory' stage!" );
GFXTexHandle &sysMemTex = capture.sysMemTex;
Point2I size = sysMemTex.getWidthHeight();
// Setup a surface
IDirect3DSurface9 *surface;
GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*sysMemTex);
D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &surface ), NULL );
// Lock the system memory surface
D3DLOCKED_RECT r;
D3DSURFACE_DESC d;
surface->GetDesc(&d);
surface->LockRect( &r, NULL, D3DLOCK_READONLY);
// Allocate a GBitmap and copy into it.
GBitmap *gb = new GBitmap(size.x, size.y);
// We've got the X8 in there so we have to manually copy stuff.
const U32* src = (const U32*)r.pBits;
U8* dst = gb->getWritableBits();
S32 pixels = size.x*size.y;
for(S32 i=0; i<pixels; i++)
{
U32 px = *src++;
*dst++ = px >> 16;
*dst++ = px >> 8;
*dst++ = px;
}
surface->UnlockRect();
// celease surfaces
surface->Release();
// Push this new bitmap
pushNewBitmap(gb);
// Change the resource state
capture.stage = eReadyToCapture;
}
bool VideoFrameGrabberD3D9::_handleGFXEvent( GFXDevice::GFXDeviceEventType event_ )
{
switch ( event_ )
{
case GFXDevice::deDestroy :
releaseTextures();
break;
default:
break;
}
return true;
}

View file

@ -0,0 +1,82 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _VIDEOCAPTURE_H_
#include "gfx/video/videoCapture.h"
#endif
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
class VideoFrameGrabberD3D9 : public VideoFrameGrabber
{
protected:
enum CaptureStage {
eReadyToCapture,
eInVideoMemory,
eInSystemMemory,
eNumStages
};
// Contains all elements involved in single frame capture and
// is used to spread the multiple "stages" needed to capture a bitmap
// over various frames to keep GPU resources from locking the CPU.
struct CaptureResource {
GFXTexHandle vidMemTex; //Video memory texture
GFXTexHandle sysMemTex; //System memory texture
CaptureStage stage; //This resource's capture stage
CaptureResource() : stage(eReadyToCapture) {};
~CaptureResource()
{
vidMemTex.free();
sysMemTex.free();
}
};
// Capture resource array. One item for each capture pipeline stage
CaptureResource mCapture[eNumStages];
// Current capture index
S32 mCurrentCapture;
// Copies a capture's video memory content to system memory
void copyToSystemMemory(CaptureResource &capture);
// Copies a capture's syste memory content to a new bitmap
void copyToBitmap(CaptureResource &capture);
bool _handleGFXEvent(GFXDevice::GFXDeviceEventType event);
//------------------------------------------------
// Overloaded from VideoFrameGrabber
//------------------------------------------------
void captureBackBuffer();
void makeBitmap();
void releaseTextures();
public:
VideoFrameGrabberD3D9();
~VideoFrameGrabberD3D9();
};

View file

@ -0,0 +1,343 @@
//-----------------------------------------------------------------------------
// 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/Null/gfxNullDevice.h"
#include "core/strings/stringFunctions.h"
#include "gfx/gfxCubemap.h"
#include "gfx/screenshot.h"
#include "gfx/gfxPrimitiveBuffer.h"
#include "gfx/gfxCardProfile.h"
#include "gfx/gfxTextureManager.h"
#include "gfx/bitmap/gBitmap.h"
#include "core/util/safeDelete.h"
GFXAdapter::CreateDeviceInstanceDelegate GFXNullDevice::mCreateDeviceInstance(GFXNullDevice::createInstance);
class GFXNullCardProfiler: public GFXCardProfiler
{
private:
typedef GFXCardProfiler Parent;
public:
///
virtual const String &getRendererString() const { static String sRS("GFX Null Device Renderer"); return sRS; }
protected:
virtual void setupCardCapabilities() { };
virtual bool _queryCardCap(const String &query, U32 &foundResult){ return false; }
virtual bool _queryFormat(const GFXFormat fmt, const GFXTextureProfile *profile, bool &inOutAutogenMips) { inOutAutogenMips = false; return false; }
public:
virtual void init()
{
mCardDescription = "GFX Null Device Card";
mChipSet = "NULL Device";
mVersionString = "0";
Parent::init(); // other code notes that not calling this is "BAD".
};
};
class GFXNullTextureObject : public GFXTextureObject
{
public:
GFXNullTextureObject(GFXDevice * aDevice, GFXTextureProfile *profile);
~GFXNullTextureObject() { kill(); };
virtual void pureVirtualCrash() { };
virtual GFXLockedRect * lock( U32 mipLevel = 0, RectI *inRect = NULL ) { return NULL; };
virtual void unlock( U32 mipLevel = 0) {};
virtual bool copyToBmp(GBitmap *) { return false; };
virtual void zombify() {}
virtual void resurrect() {}
};
GFXNullTextureObject::GFXNullTextureObject(GFXDevice * aDevice, GFXTextureProfile *profile) :
GFXTextureObject(aDevice, profile)
{
mProfile = profile;
mTextureSize.set( 0, 0, 0 );
}
class GFXNullTextureManager : public GFXTextureManager
{
protected:
virtual GFXTextureObject *_createTextureObject( U32 height,
U32 width,
U32 depth,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
bool forceMips = false,
S32 antialiasLevel = 0,
GFXTextureObject *inTex = NULL )
{
GFXNullTextureObject *retTex;
if ( inTex )
{
AssertFatal( dynamic_cast<GFXNullTextureObject*>( inTex ), "GFXNullTextureManager::_createTexture() - Bad inTex type!" );
retTex = static_cast<GFXNullTextureObject*>( inTex );
}
else
{
retTex = new GFXNullTextureObject( GFX, profile );
retTex->registerResourceWithDevice( GFX );
}
SAFE_DELETE( retTex->mBitmap );
retTex->mBitmap = new GBitmap(width, height);
return retTex;
};
/// Load a texture from a proper DDSFile instance.
virtual bool _loadTexture(GFXTextureObject *texture, DDSFile *dds){ return true; };
/// Load data into a texture from a GBitmap using the internal API.
virtual bool _loadTexture(GFXTextureObject *texture, GBitmap *bmp){ return true; };
/// Load data into a texture from a raw buffer using the internal API.
///
/// Note that the size of the buffer is assumed from the parameters used
/// for this GFXTextureObject's _createTexture call.
virtual bool _loadTexture(GFXTextureObject *texture, void *raw){ return true; };
/// Refresh a texture using the internal API.
virtual bool _refreshTexture(GFXTextureObject *texture){ return true; };
/// Free a texture (but do not delete the GFXTextureObject) using the internal
/// API.
///
/// This is only called during zombification for textures which need it, so you
/// don't need to do any internal safety checks.
virtual bool _freeTexture(GFXTextureObject *texture, bool zombify=false) { return true; };
virtual U32 _getTotalVideoMemory() { return 0; };
virtual U32 _getFreeVideoMemory() { return 0; };
};
class GFXNullCubemap : public GFXCubemap
{
friend class GFXDevice;
private:
// should only be called by GFXDevice
virtual void setToTexUnit( U32 tuNum ) { };
public:
virtual void initStatic( GFXTexHandle *faces ) { };
virtual void initStatic( DDSFile *dds ) { };
virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 ) { };
virtual U32 getSize() const { return 0; }
virtual GFXFormat getFormat() const { return GFXFormatR8G8B8A8; }
virtual ~GFXNullCubemap(){};
virtual void zombify() {}
virtual void resurrect() {}
};
class GFXNullVertexBuffer : public GFXVertexBuffer
{
unsigned char* tempBuf;
public:
GFXNullVertexBuffer( GFXDevice *device,
U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertexSize,
GFXBufferType bufferType ) :
GFXVertexBuffer(device, numVerts, vertexFormat, vertexSize, bufferType) { };
virtual void lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr);
virtual void unlock();
virtual void prepare();
virtual void zombify() {}
virtual void resurrect() {}
};
void GFXNullVertexBuffer::lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr)
{
tempBuf = new unsigned char[(vertexEnd - vertexStart) * mVertexSize];
*vertexPtr = (void*) tempBuf;
lockedVertexStart = vertexStart;
lockedVertexEnd = vertexEnd;
}
void GFXNullVertexBuffer::unlock()
{
delete[] tempBuf;
tempBuf = NULL;
}
void GFXNullVertexBuffer::prepare()
{
}
class GFXNullPrimitiveBuffer : public GFXPrimitiveBuffer
{
private:
U16* temp;
public:
GFXNullPrimitiveBuffer( GFXDevice *device,
U32 indexCount,
U32 primitiveCount,
GFXBufferType bufferType ) :
GFXPrimitiveBuffer(device, indexCount, primitiveCount, bufferType), temp( NULL ) {};
virtual void lock(U32 indexStart, U32 indexEnd, void **indexPtr); ///< locks this primitive buffer for writing into
virtual void unlock(); ///< unlocks this primitive buffer.
virtual void prepare() { }; ///< prepares this primitive buffer for use on the device it was allocated on
virtual void zombify() {}
virtual void resurrect() {}
};
void GFXNullPrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr)
{
temp = new U16[indexEnd - indexStart];
*indexPtr = temp;
}
void GFXNullPrimitiveBuffer::unlock()
{
delete[] temp;
temp = NULL;
}
//
// GFXNullStateBlock
//
class GFXNullStateBlock : public GFXStateBlock
{
public:
/// Returns the hash value of the desc that created this block
virtual U32 getHashValue() const { return 0; };
/// Returns a GFXStateBlockDesc that this block represents
virtual const GFXStateBlockDesc& getDesc() const { return mDefaultDesc; }
//
// GFXResource
//
virtual void zombify() { }
/// When called the resource should restore all device sensitive information destroyed by zombify()
virtual void resurrect() { }
private:
GFXStateBlockDesc mDefaultDesc;
};
//
// GFXNullDevice
//
GFXDevice *GFXNullDevice::createInstance( U32 adapterIndex )
{
return new GFXNullDevice();
}
GFXNullDevice::GFXNullDevice()
{
clip.set(0, 0, 800, 800);
mTextureManager = new GFXNullTextureManager();
gScreenShot = new ScreenShot();
mCardProfiler = new GFXNullCardProfiler();
mCardProfiler->init();
}
GFXNullDevice::~GFXNullDevice()
{
}
GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType )
{
return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType);
}
GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType)
{
return new GFXNullPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
}
GFXCubemap* GFXNullDevice::createCubemap()
{
return new GFXNullCubemap();
};
void GFXNullDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
{
// Add the NULL renderer
GFXAdapter *toAdd = new GFXAdapter();
toAdd->mIndex = 0;
toAdd->mType = NullDevice;
toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance;
GFXVideoMode vm;
vm.bitDepth = 32;
vm.resolution.set(800,600);
toAdd->mAvailableModes.push_back(vm);
dStrcpy(toAdd->mName, "GFX Null Device");
adapterList.push_back(toAdd);
}
void GFXNullDevice::setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable)
{
}
void GFXNullDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
{
mCardProfiler = new GFXNullCardProfiler();
mCardProfiler->init();
}
GFXStateBlockRef GFXNullDevice::createStateBlockInternal(const GFXStateBlockDesc& desc)
{
return new GFXNullStateBlock();
}
//
// Register this device with GFXInit
//
class GFXNullRegisterDevice
{
public:
GFXNullRegisterDevice()
{
GFXInit::getRegisterDeviceSignal().notify(&GFXNullDevice::enumerateAdapters);
}
};
static GFXNullRegisterDevice pNullRegisterDevice;

View file

@ -0,0 +1,185 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXNullDevice_H_
#define _GFXNullDevice_H_
#include "platform/platform.h"
//-----------------------------------------------------------------------------
#include "gfx/gfxDevice.h"
#include "gfx/gfxInit.h"
#include "gfx/gfxFence.h"
class GFXNullWindowTarget : public GFXWindowTarget
{
public:
virtual bool present()
{
return true;
}
virtual const Point2I getSize()
{
// Return something stupid.
return Point2I(1,1);
}
virtual GFXFormat getFormat() { return GFXFormatR8G8B8A8; }
virtual void resetMode()
{
}
virtual void zombify() {};
virtual void resurrect() {};
};
class GFXNullDevice : public GFXDevice
{
public:
GFXNullDevice();
virtual ~GFXNullDevice();
static GFXDevice *createInstance( U32 adapterIndex );
static void enumerateAdapters( Vector<GFXAdapter*> &adapterList );
void init( const GFXVideoMode &mode, PlatformWindow *window = NULL );
virtual void activate() { };
virtual void deactivate() { };
virtual GFXAdapterType getAdapterType() { return NullDevice; };
/// @name Debug Methods
/// @{
virtual void enterDebugEvent(ColorI color, const char *name) { };
virtual void leaveDebugEvent() { };
virtual void setDebugMarker(ColorI color, const char *name) { };
/// @}
/// Enumerates the supported video modes of the device
virtual void enumerateVideoModes() { };
/// Sets the video mode for the device
virtual void setVideoMode( const GFXVideoMode &mode ) { };
protected:
static GFXAdapter::CreateDeviceInstanceDelegate mCreateDeviceInstance;
/// Called by GFXDevice to create a device specific stateblock
virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc);
/// Called by GFXDevice to actually set a stateblock.
virtual void setStateBlockInternal(GFXStateBlock* block, bool force) { };
/// @}
/// Called by base GFXDevice to actually set a const buffer
virtual void setShaderConstBufferInternal(GFXShaderConstBuffer* buffer) { };
virtual void setTextureInternal(U32 textureUnit, const GFXTextureObject*texture) { };
virtual void setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable);
virtual void setLightMaterialInternal(const GFXLightMaterial mat) { };
virtual void setGlobalAmbientInternal(ColorF color) { };
/// @name State Initalization.
/// @{
/// State initalization. This MUST BE CALLED in setVideoMode after the device
/// is created.
virtual void initStates() { };
virtual void setMatrix( GFXMatrixType mtype, const MatrixF &mat ) { };
virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType );
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType );
virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; }
virtual void setVertexDecl( const GFXVertexDecl *decl ) { }
virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer ) { }
virtual void setVertexStreamFrequency( U32 stream, U32 frequency ) { }
public:
virtual GFXCubemap * createCubemap();
virtual F32 getFillConventionOffset() const { return 0.0f; };
///@}
virtual GFXTextureTarget *allocRenderToTextureTarget(){return NULL;};
virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window)
{
return new GFXNullWindowTarget();
};
virtual void _updateRenderTargets(){};
virtual F32 getPixelShaderVersion() const { return 0.0f; };
virtual void setPixelShaderVersion( F32 version ) { };
virtual U32 getNumSamplers() const { return 0; };
virtual U32 getNumRenderTargets() const { return 0; };
virtual GFXShader* createShader() { return NULL; };
virtual void clear( U32 flags, ColorI color, F32 z, U32 stencil ) { };
virtual bool beginSceneInternal() { return true; };
virtual void endSceneInternal() { };
virtual void drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) { };
virtual void drawIndexedPrimitive( GFXPrimitiveType primType,
U32 startVertex,
U32 minIndex,
U32 numVerts,
U32 startIndex,
U32 primitiveCount ) { };
virtual void setClipRect( const RectI &rect ) { };
virtual const RectI &getClipRect() const { return clip; };
virtual void preDestroy() { Parent::preDestroy(); };
virtual U32 getMaxDynamicVerts() { return 16384; };
virtual U32 getMaxDynamicIndices() { return 16384; };
virtual GFXFormat selectSupportedFormat( GFXTextureProfile *profile,
const Vector<GFXFormat> &formats,
bool texture,
bool mustblend,
bool mustfilter ) { return GFXFormatR8G8B8A8; };
GFXFence *createFence() { return new GFXGeneralFence( this ); }
GFXOcclusionQuery* createOcclusionQuery() { return NULL; }
private:
typedef GFXDevice Parent;
RectI clip;
};
#endif

View file

@ -0,0 +1,284 @@
//-----------------------------------------------------------------------------
// 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 "gfx/bitmap/bitmapUtils.h"
#include "platform/platform.h"
void bitmapExtrude5551_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
{
const U16 *src = (const U16 *) srcMip;
U16 *dst = (U16 *) mip;
U32 stride = srcHeight != 1 ? srcWidth : 0;
U32 width = srcWidth >> 1;
U32 height = srcHeight >> 1;
if (width == 0) width = 1;
if (height == 0) height = 1;
if (srcWidth != 1)
{
for(U32 y = 0; y < height; y++)
{
for(U32 x = 0; x < width; x++)
{
U32 a = src[0];
U32 b = src[1];
U32 c = src[stride];
U32 d = src[stride+1];
#if defined(TORQUE_BIG_ENDIAN)
dst[x] = ((( (a >> 10) + (b >> 10) + (c >> 10) + (d >> 10)) >> 2) << 10) |
((( ((a >> 5) & 0x1F) + ((b >> 5) & 0x1F) + ((c >> 5) & 0x1F) + ((d >> 5) & 0x1F)) >> 2) << 5) |
((( ((a >> 0) & 0x1F) + ((b >> 0) & 0x1F) + ((c >> 0) & 0x1F) + ((d >> 0) & 0x1F)) >> 2) << 0);
#else
dst[x] = ((( (a >> 11) + (b >> 11) + (c >> 11) + (d >> 11)) >> 2) << 11) |
((( ((a >> 6) & 0x1F) + ((b >> 6) & 0x1F) + ((c >> 6) & 0x1F) + ((d >> 6) & 0x1F)) >> 2) << 6) |
((( ((a >> 1) & 0x1F) + ((b >> 1) & 0x1F) + ((c >> 1) & 0x1F) + ((d >> 1) & 0x1F)) >> 2) << 1);
#endif
src += 2;
}
src += stride;
dst += width;
}
}
else
{
for(U32 y = 0; y < height; y++)
{
U32 a = src[0];
U32 c = src[stride];
#if defined(TORQUE_OS_MAC)
dst[y] = ((( (a >> 10) + (c >> 10)) >> 1) << 10) |
((( ((a >> 5) & 0x1F) + ((c >> 5) & 0x1f)) >> 1) << 5) |
((( ((a >> 0) & 0x1F) + ((c >> 0) & 0x1f)) >> 1) << 0);
#else
dst[y] = ((( (a >> 11) + (c >> 11)) >> 1) << 11) |
((( ((a >> 6) & 0x1f) + ((c >> 6) & 0x1f)) >> 1) << 6) |
((( ((a >> 1) & 0x1F) + ((c >> 1) & 0x1f)) >> 1) << 1);
#endif
src += 1 + stride;
}
}
}
//--------------------------------------------------------------------------
void bitmapExtrudeRGB_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
{
const U8 *src = (const U8 *) srcMip;
U8 *dst = (U8 *) mip;
U32 stride = srcHeight != 1 ? (srcWidth) * 3 : 0;
U32 width = srcWidth >> 1;
U32 height = srcHeight >> 1;
if (width == 0) width = 1;
if (height == 0) height = 1;
if (srcWidth != 1)
{
for(U32 y = 0; y < height; y++)
{
for(U32 x = 0; x < width; x++)
{
*dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3]) + 2) >> 2;
src++;
*dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3]) + 2) >> 2;
src++;
*dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3]) + 2) >> 2;
src += 4;
}
src += stride; // skip
}
}
else
{
for(U32 y = 0; y < height; y++)
{
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src++;
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src++;
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src += 4;
src += stride; // skip
}
}
}
//--------------------------------------------------------------------------
void bitmapExtrudeRGBA_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
{
const U8 *src = (const U8 *) srcMip;
U8 *dst = (U8 *) mip;
U32 stride = srcHeight != 1 ? (srcWidth) * 4 : 0;
U32 width = srcWidth >> 1;
U32 height = srcHeight >> 1;
if (width == 0) width = 1;
if (height == 0) height = 1;
if (srcWidth != 1)
{
for(U32 y = 0; y < height; y++)
{
for(U32 x = 0; x < width; x++)
{
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
src++;
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
src++;
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
src++;
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
src += 5;
}
src += stride; // skip
}
}
else
{
for(U32 y = 0; y < height; y++)
{
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src++;
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src++;
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src++;
*dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
src += 5;
src += stride; // skip
}
}
}
void (*bitmapExtrude5551)(const void *srcMip, void *mip, U32 height, U32 width) = bitmapExtrude5551_c;
void (*bitmapExtrudeRGB)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudeRGB_c;
void (*bitmapExtrudeRGBA)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudeRGBA_c;
//--------------------------------------------------------------------------
void bitmapConvertRGB_to_1555_c(U8 *src, U32 pixels)
{
U16 *dst = (U16 *)src;
for(U32 j = 0; j < pixels; j++)
{
U32 r = src[0] >> 3;
U32 g = src[1] >> 3;
U32 b = src[2] >> 3;
#if defined(TORQUE_OS_MAC)
*dst++ = 0x8000 | (b << 10) | (g << 5) | (r << 0);
#else
*dst++ = b | (g << 5) | (r << 10) | 0x8000;
#endif
src += 3;
}
}
void (*bitmapConvertRGB_to_1555)(U8 *src, U32 pixels) = bitmapConvertRGB_to_1555_c;
//------------------------------------------------------------------------------
void bitmapConvertRGB_to_5551_c(U8 *src, U32 pixels)
{
U16 *dst = (U16 *)src;
for(U32 j = 0; j < pixels; j++)
{
U32 r = src[0] >> 3;
U32 g = src[1] >> 3;
U32 b = src[2] >> 3;
#if defined(TORQUE_OS_MAC)
*dst++ = (1 << 15) | (b << 10) | (g << 5) | (r << 0);
#else
*dst++ = (b << 1) | (g << 6) | (r << 11) | 1;
#endif
src += 3;
}
}
void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels) = bitmapConvertRGB_to_5551_c;
//------------------------------------------------------------------------------
void bitmapConvertRGB_to_RGBX_c( U8 **src, U32 pixels )
{
const U8 *oldBits = *src;
U8 *newBits = new U8[pixels * 4];
dMemset( newBits, 0xFF, pixels * 4 ); // This is done to set alpha values -patw
// Copy the bits over to the new memory
for( U32 i = 0; i < pixels; i++ )
dMemcpy( &newBits[i * 4], &oldBits[i * 3], sizeof(U8) * 3 );
// Now hose the old bits
delete [] *src;
*src = newBits;
}
void (*bitmapConvertRGB_to_RGBX)( U8 **src, U32 pixels ) = bitmapConvertRGB_to_RGBX_c;
//------------------------------------------------------------------------------
void bitmapConvertRGBX_to_RGB_c( U8 **src, U32 pixels )
{
const U8 *oldBits = *src;
U8 *newBits = new U8[pixels * 3];
// Copy the bits over to the new memory
for( U32 i = 0; i < pixels; i++ )
dMemcpy( &newBits[i * 3], &oldBits[i * 4], sizeof(U8) * 3 );
// Now hose the old bits
delete [] *src;
*src = newBits;
}
void (*bitmapConvertRGBX_to_RGB)( U8 **src, U32 pixels ) = bitmapConvertRGBX_to_RGB_c;
//------------------------------------------------------------------------------
void bitmapConvertA8_to_RGBA_c( U8 **src, U32 pixels )
{
const U8 *oldBits = *src;
U8 *newBits = new U8[pixels * 4];
// Zero new bits
dMemset( newBits, 0, pixels * 4 );
// Copy Alpha values
for( U32 i = 0; i < pixels; i++ )
newBits[i * 4 + 3] = oldBits[i];
// Now hose the old bits
delete [] *src;
*src = newBits;
}
void (*bitmapConvertA8_to_RGBA)( U8 **src, U32 pixels ) = bitmapConvertA8_to_RGBA_c;

View file

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _BITMAPUTILS_H_
#define _BITMAPUTILS_H_
#ifndef _TORQUE_TYPES_H_
#include "platform/types.h"
#endif
extern void (*bitmapExtrude5551)(const void *srcMip, void *mip, U32 height, U32 width);
extern void (*bitmapExtrudeRGB)(const void *srcMip, void *mip, U32 height, U32 width);
extern void (*bitmapExtrudeRGBA)(const void *srcMip, void *mip, U32 height, U32 width);
extern void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels);
extern void (*bitmapConvertRGB_to_1555)(U8 *src, U32 pixels);
extern void (*bitmapConvertRGB_to_RGBX)( U8 **src, U32 pixels );
extern void (*bitmapConvertRGBX_to_RGB)( U8 **src, U32 pixels );
extern void (*bitmapConvertA8_to_RGBA)( U8 **src, U32 pixels );
void bitmapExtrudeRGB_c(const void *srcMip, void *mip, U32 height, U32 width);
#endif //_BITMAPUTILS_H_

View file

@ -0,0 +1,205 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _DDSFILE_H_
#define _DDSFILE_H_
#ifndef _GFXSTRUCTS_H_
#include "gfx/gfxStructs.h"
#endif
#ifndef _BITSET_H_
#include "core/bitSet.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef __RESOURCE_H__
#include "core/resource.h"
#endif
class Stream;
class GBitmap;
struct DDSFile
{
enum DDSFlags
{
ComplexFlag = BIT(0), ///< Indicates this includes a mipchain, cubemap, or
/// volume texture, ie, isn't a plain old bitmap.
MipMapsFlag = BIT(1), ///< Indicates we have a mipmap chain in the file.
CubeMapFlag = BIT(2), ///< Indicates we are a cubemap. Requires all six faces.
VolumeFlag = BIT(3), ///< Indicates we are a volume texture.
PitchSizeFlag = BIT(4), ///< Cue as to how to interpret our pitchlinear value.
LinearSizeFlag = BIT(5), ///< Cue as to how to interpret our pitchlinear value.
RGBData = BIT(6), ///< Indicates that this is straight out RGBA data.
CompressedData = BIT(7), ///< Indicates that this is compressed or otherwise
/// exotic data.
/// These are the flags for which cubemap
/// surfaces are included in the file.
CubeMap_PosX_Flag = BIT(8),
CubeMap_NegX_Flag = BIT(9),
CubeMap_PosY_Flag = BIT(10),
CubeMap_NegY_Flag = BIT(11),
CubeMap_PosZ_Flag = BIT(12),
CubeMap_NegZ_Flag = BIT(13),
};
/// The index into mSurfaces for each
/// cubemap face.
enum
{
Cubemap_Surface_PosX,
Cubemap_Surface_NegX,
Cubemap_Surface_PosY,
Cubemap_Surface_NegY,
Cubemap_Surface_PosZ,
Cubemap_Surface_NegZ,
Cubemap_Surface_Count,
};
BitSet32 mFlags;
U32 mHeight;
U32 mWidth;
U32 mDepth;
U32 mPitchOrLinearSize;
U32 mMipMapCount;
GFXFormat mFormat;
U32 mBytesPerPixel; ///< Ignored if we're a compressed texture.
U32 mFourCC;
String mCacheString;
Torque::Path mSourcePath;
bool mHasTransparency;
// This is ugly... but it allows us to pass the number of
// mips to drop into the ResourceManager loading process.
static U32 smDropMipCount;
struct SurfaceData
{
SurfaceData()
{
VECTOR_SET_ASSOCIATION( mMips );
}
~SurfaceData()
{
// Free our mips!
for(S32 i=0; i<mMips.size(); i++)
delete[] mMips[i];
}
Vector<U8*> mMips;
// Helper function to read in a mipchain.
bool readMipChain();
void dumpImage(DDSFile *dds, U32 mip, const char *file);
/// Helper for reading a mip level.
void readNextMip(DDSFile *dds, Stream &s, U32 height, U32 width, U32 mipLevel, bool skip);
/// Helper for writing a mip level.
void writeNextMip(DDSFile *dds, Stream &s, U32 height, U32 width, U32 mipLevel);
};
Vector<SurfaceData*> mSurfaces;
/// Clear all our information; used before reading.
void clear();
/// Reads a DDS file from the stream.
bool read(Stream &s, U32 dropMipCount);
/// Called from read() to read in the DDS header.
bool readHeader(Stream &s);
/// Writes this DDS file to the stream.
bool write(Stream &s);
/// Called from write() to write the DDS header.
bool writeHeader(Stream &s);
/// For our current format etc., what is the size of a surface with the
/// given dimensions?
U32 getSurfaceSize( U32 mipLevel = 0 ) const { return getSurfaceSize( mHeight, mWidth, mipLevel ); }
U32 getSurfaceSize( U32 height, U32 width, U32 mipLevel = 0 ) const;
// Helper for getting the size in bytes of a compressed DDS texture.
static U32 getSizeInBytes( GFXFormat format, U32 height, U32 width, U32 mipLevels );
/// Returns the total video memory size of the texture
/// including all mipmaps and compression settings.
U32 getSizeInBytes() const;
U32 getWidth( U32 mipLevel = 0 ) const { return getMax( U32(1), mWidth >> mipLevel ); }
U32 getHeight( U32 mipLevel = 0 ) const { return getMax(U32(1), mHeight >> mipLevel); }
U32 getDepth( U32 mipLevel = 0 ) const { return getMax(U32(1), mDepth >> mipLevel); }
U32 getMipLevels() const { return mMipMapCount; }
bool getHasTransparency() const { return mHasTransparency; }
bool isCubemap() const { return mFlags.test( CubeMapFlag ); }
GFXFormat getFormat() const { return mFormat; }
U32 getSurfacePitch( U32 mipLevel = 0 ) const;
const Torque::Path &getSourcePath() const { return mSourcePath; }
const String &getTextureCacheString() const { return mCacheString; }
static Resource<DDSFile> load( const Torque::Path &path, U32 dropMipCount );
// For debugging fun!
static S32 smActiveCopies;
DDSFile()
{
VECTOR_SET_ASSOCIATION( mSurfaces );
smActiveCopies++;
mHasTransparency = false;
}
DDSFile( const DDSFile &dds );
~DDSFile()
{
smActiveCopies--;
// Free our surfaces!
for(S32 i=0; i<mSurfaces.size(); i++)
delete mSurfaces[i];
mSurfaces.clear();
}
static DDSFile *createDDSFileFromGBitmap( const GBitmap *gbmp );
};
#endif // _DDSFILE_H_

View file

@ -0,0 +1,922 @@
//-----------------------------------------------------------------------------
// 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/bitmap/ddsFile.h"
#include "gfx/gfxDevice.h"
#include "core/util/fourcc.h"
#include "console/console.h"
#include "core/resourceManager.h"
#include "core/stream/fileStream.h"
#include "gfx/bitmap/gBitmap.h"
#include "console/engineAPI.h"
S32 DDSFile::smActiveCopies = 0;
U32 DDSFile::smDropMipCount = 0;
// These were copied from the DX9 docs. The names are changed
// from the "real" defines since not all platforms have them.
enum DDSSurfaceDescFlags
{
DDSDCaps = 0x00000001l,
DDSDHeight = 0x00000002l,
DDSDWidth = 0x00000004l,
DDSDPitch = 0x00000008l,
DDSDPixelFormat = 0x00001000l,
DDSDMipMapCount = 0x00020000l,
DDSDLinearSize = 0x00080000l,
DDSDDepth = 0x00800000l,
};
enum DDSPixelFormatFlags
{
DDPFAlphaPixels = 0x00000001,
DDPFFourCC = 0x00000004,
DDPFRGB = 0x00000040,
DDPFLUMINANCE = 0x00020000
};
enum DDSCapFlags
{
DDSCAPSComplex = 0x00000008,
DDSCAPSTexture = 0x00001000,
DDSCAPSMipMap = 0x00400000,
DDSCAPS2Cubemap = 0x00000200,
DDSCAPS2Cubemap_POSITIVEX = 0x00000400,
DDSCAPS2Cubemap_NEGATIVEX = 0x00000800,
DDSCAPS2Cubemap_POSITIVEY = 0x00001000,
DDSCAPS2Cubemap_NEGATIVEY = 0x00002000,
DDSCAPS2Cubemap_POSITIVEZ = 0x00004000,
DDSCAPS2Cubemap_NEGATIVEZ = 0x00008000,
DDSCAPS2Volume = 0x00200000,
};
#define FOURCC_DXT1 (MakeFourCC('D','X','T','1'))
#define FOURCC_DXT2 (MakeFourCC('D','X','T','2'))
#define FOURCC_DXT3 (MakeFourCC('D','X','T','3'))
#define FOURCC_DXT4 (MakeFourCC('D','X','T','4'))
#define FOURCC_DXT5 (MakeFourCC('D','X','T','5'))
DDSFile::DDSFile( const DDSFile &dds )
: mFlags( dds.mFlags ),
mHeight( dds.mHeight ),
mWidth( dds.mWidth ),
mDepth( dds.mDepth ),
mPitchOrLinearSize( dds.mPitchOrLinearSize ),
mMipMapCount( dds.mMipMapCount ),
mFormat( dds.mFormat ),
mBytesPerPixel( dds.mBytesPerPixel ),
mFourCC( dds.mFourCC ),
mCacheString( dds.mCacheString ),
mSourcePath( dds.mSourcePath ),
mHasTransparency( dds.mHasTransparency )
{
VECTOR_SET_ASSOCIATION( mSurfaces );
smActiveCopies++;
for ( U32 i=0; i < dds.mSurfaces.size(); i++ )
{
SurfaceData *surface = NULL;
if ( dds.mSurfaces[i] )
surface = new SurfaceData;
mSurfaces.push_back( surface );
if ( !surface )
continue;
for ( U32 m=0; m < dds.mSurfaces[i]->mMips.size(); m++ )
{
U32 size = dds.getSurfaceSize( m );
surface->mMips.push_back(new U8[size]);
dMemcpy( surface->mMips.last(), dds.mSurfaces[i]->mMips[m], size );
}
}
}
void DDSFile::clear()
{
mFlags = 0;
mHeight = mWidth = mDepth = mPitchOrLinearSize = mMipMapCount = 0;
mFormat = GFXFormatR8G8B8;
}
U32 DDSFile::getSurfacePitch( U32 mipLevel ) const
{
if(mFlags.test(CompressedData))
{
U32 sizeMultiple = 0;
switch(mFormat)
{
case GFXFormatDXT1:
sizeMultiple = 8;
break;
case GFXFormatDXT2:
case GFXFormatDXT3:
case GFXFormatDXT4:
case GFXFormatDXT5:
sizeMultiple = 16;
break;
default:
AssertISV(false, "DDSFile::getPitch - invalid compressed texture format, we only support DXT1-5 right now.");
break;
}
// Maybe need to be DWORD aligned?
U32 align = getMax(U32(1), getWidth(mipLevel)/4) * sizeMultiple;
align += 3; align >>=2; align <<=2;
return align;
}
else
return getWidth(mipLevel) * mBytesPerPixel;
}
U32 DDSFile::getSurfaceSize( U32 height, U32 width, U32 mipLevel ) const
{
// Bump by the mip level.
height = getMax(U32(1), height >> mipLevel);
width = getMax(U32(1), width >> mipLevel);
if(mFlags.test(CompressedData))
{
// From the directX docs:
// max(1, width ÷ 4) x max(1, height ÷ 4) x 8(DXT1) or 16(DXT2-5)
U32 sizeMultiple = 0;
switch(mFormat)
{
case GFXFormatDXT1:
sizeMultiple = 8;
break;
case GFXFormatDXT2:
case GFXFormatDXT3:
case GFXFormatDXT4:
case GFXFormatDXT5:
sizeMultiple = 16;
break;
default:
AssertISV(false, "DDSFile::getSurfaceSize - invalid compressed texture format, we only support DXT1-5 right now.");
break;
}
return getMax(U32(1), width/4) * getMax(U32(1), height/4) * sizeMultiple;
}
else
{
return height * width* mBytesPerPixel;
}
}
U32 DDSFile::getSizeInBytes() const
{
// TODO: This doesn't take mDepth into account, so
// it doesn't work right for volume or cubemap textures!
U32 bytes = 0;
for ( U32 i=0; i < mMipMapCount; i++ )
bytes += getSurfaceSize( mHeight, mWidth, i );
return bytes;
}
U32 DDSFile::getSizeInBytes( GFXFormat format, U32 height, U32 width, U32 mipLevels )
{
AssertFatal( format >= GFXFormatDXT1 && format <= GFXFormatDXT5,
"DDSFile::getSizeInBytes - Must be a DXT format!" );
// From the directX docs:
// max(1, width ÷ 4) x max(1, height ÷ 4) x 8(DXT1) or 16(DXT2-5)
U32 sizeMultiple = 0;
if ( format == GFXFormatDXT1 )
sizeMultiple = 8;
else
sizeMultiple = 16;
U32 mipHeight, mipWidth;
U32 bytes = 0;
for ( U32 m=0; m < mipLevels; m++ )
{
mipHeight = getMax( U32(1), height >> m );
mipWidth = getMax( U32(1), width >> m );
bytes += getMax( U32(1), mipWidth / 4 ) *
getMax( U32(1), mipHeight / 4 ) * sizeMultiple;
}
return bytes;
}
bool DDSFile::readHeader(Stream &s)
{
U32 tmp;
// Read the FOURCC
s.read(&tmp);
if(tmp != MakeFourCC('D', 'D', 'S', ' '))
{
Con::errorf("DDSFile::readHeader - unexpected magic number, wanted 'DDS '!");
return false;
}
// Read the size of the header.
s.read(&tmp);
if(tmp != 124)
{
Con::errorf("DDSFile::readHeader - incorrect header size. Expected 124 bytes.");
return false;
}
// Read some flags...
U32 ddsdFlags;
s.read(&ddsdFlags);
// "Always include DDSD_CAPS, DDSD_PIXELFORMAT, DDSD_WIDTH, DDSD_HEIGHT."
if(!(ddsdFlags & (DDSDCaps | DDSDPixelFormat | DDSDWidth | DDSDHeight)))
{
Con::errorf("DDSFile::readHeader - incorrect surface description flags.");
return false;
}
// Read height and width (always present)
s.read(&mHeight);
s.read(&mWidth);
// Read pitch or linear size.
// First make sure we have valid flags (either linear size or pitch).
if((ddsdFlags & (DDSDLinearSize | DDSDPitch)) == (DDSDLinearSize | DDSDPitch))
{
// Both are invalid!
Con::errorf("DDSFile::readHeader - encountered both DDSD_LINEARSIZE and DDSD_PITCH!");
return false;
}
// Ok, some flags are set, so let's do some reading.
s.read(&mPitchOrLinearSize);
if(ddsdFlags & DDSDLinearSize)
{
mFlags.set(LinearSizeFlag); // ( mHeight / 4 ) * ( mWidth / 4 ) * DDSSIZE
}
else if (ddsdFlags & DDSDPitch)
{
mFlags.set(PitchSizeFlag); // ( mWidth / 4 ) * DDSSIZE ???
}
else
{
// Neither set! This appears to be depressingly common.
// Con::warnf("DDSFile::readHeader - encountered neither DDSD_LINEARSIZE nor DDSD_PITCH!");
}
// Do we need to read depth? If so, we are a volume texture!
s.read(&mDepth);
if(ddsdFlags & DDSDDepth)
{
mFlags.set(VolumeFlag);
}
else
{
// Wipe it if the flag wasn't set!
mDepth = 0;
}
// Deal with mips!
s.read(&mMipMapCount);
if(ddsdFlags & DDSDMipMapCount)
{
mFlags.set(MipMapsFlag);
}
else
{
// Wipe it if the flag wasn't set!
mMipMapCount = 1;
}
// Deal with 11 DWORDS of reserved space (this reserved space brought to
// you by DirectDraw and the letters F and U).
for(U32 i=0; i<11; i++)
s.read(&tmp);
// Now we're onto the pixel format!
s.read(&tmp);
if(tmp != 32)
{
Con::errorf("DDSFile::readHeader - pixel format chunk has unexpected size!");
return false;
}
U32 ddpfFlags;
s.read(&ddpfFlags);
// Read the next few values so we can deal with them all in one go.
U32 pfFourCC, pfBitCount, pfRMask, pfGMask, pfBMask, pfAlphaMask;
s.read(&pfFourCC);
s.read(&pfBitCount);
s.read(&pfRMask);
s.read(&pfGMask);
s.read(&pfBMask);
s.read(&pfAlphaMask);
// Sanity check flags...
if(!(ddpfFlags & (DDPFRGB | DDPFFourCC | DDPFLUMINANCE)))
{
Con::errorf("DDSFile::readHeader - incoherent pixel flags, neither RGB, FourCC, or Luminance!");
return false;
}
// For now let's just dump the header info.
if(ddpfFlags & DDPFLUMINANCE)
{
mFlags.set(RGBData);
mBytesPerPixel = pfBitCount / 8;
bool hasAlpha = ddpfFlags & DDPFAlphaPixels;
mHasTransparency = hasAlpha;
// Try to match a format.
if(hasAlpha)
{
// If it has alpha it is one of...
// GFXFormatA8L8
// GFXFormatA4L4
if(pfBitCount == 16)
mFormat = GFXFormatA8L8;
else if(pfBitCount == 8)
mFormat = GFXFormatA4L4;
else
{
Con::errorf("DDSFile::readHeader - unable to match alpha Luminance format!");
return false;
}
}
else
{
// Otherwise it is one of...
// GFXFormatL16
// GFXFormatL8
if(pfBitCount == 16)
mFormat = GFXFormatL16;
else if(pfBitCount == 8)
mFormat = GFXFormatL8;
else
{
Con::errorf("DDSFile::readHeader - unable to match non-alpha Luminance format!");
return false;
}
}
}
else if(ddpfFlags & DDPFRGB)
{
mFlags.set(RGBData);
//Con::printf("RGB Pixel format of DDS:");
//Con::printf(" bitcount = %d (16, 24, 32)", pfBitCount);
mBytesPerPixel = pfBitCount / 8;
//Con::printf(" red mask = %x", pfRMask);
//Con::printf(" green mask = %x", pfGMask);
//Con::printf(" blue mask = %x", pfBMask);
bool hasAlpha = false;
if(ddpfFlags & DDPFAlphaPixels)
{
hasAlpha = true;
//Con::printf(" alpha mask = %x", pfAlphaMask);
}
else
{
//Con::printf(" no alpha.");
}
mHasTransparency = hasAlpha;
// Try to match a format.
if(hasAlpha)
{
// If it has alpha it is one of...
// GFXFormatR8G8B8A8
// GFXFormatR5G5B5A1
// GFXFormatA8
if(pfBitCount == 32)
mFormat = GFXFormatR8G8B8A8;
else if(pfBitCount == 16)
mFormat = GFXFormatR5G5B5A1;
else if(pfBitCount == 8)
mFormat = GFXFormatA8;
else
{
Con::errorf("DDSFile::readHeader - unable to match alpha RGB format!");
return false;
}
}
else
{
// Otherwise it is one of...
// GFXFormatR8G8B8
// GFXFormatR8G8B8X8
// GFXFormatR5G6B5
// GFXFormatL8
if(pfBitCount == 24)
mFormat = GFXFormatR8G8B8;
else if(pfBitCount == 32)
mFormat = GFXFormatR8G8B8X8;
else if(pfBitCount == 16)
mFormat = GFXFormatR5G6B5;
else if(pfBitCount == 8)
{
// luminance
mFormat = GFXFormatL8;
}
else
{
Con::errorf("DDSFile::readHeader - unable to match non-alpha RGB format!");
return false;
}
}
// Sweet, all done.
}
else if (ddpfFlags & DDPFFourCC)
{
mHasTransparency = (ddpfFlags & DDPFAlphaPixels);
mFlags.set(CompressedData);
/* Con::printf("FourCC Pixel format of DDS:");
Con::printf(" fourcc = '%c%c%c%c'", ((U8*)&pfFourCC)[0], ((U8*)&pfFourCC)[1], ((U8*)&pfFourCC)[2], ((U8*)&pfFourCC)[3]); */
// Ok, make a format determination.
switch(pfFourCC)
{
case FOURCC_DXT1:
mFormat = GFXFormatDXT1;
break;
case FOURCC_DXT2:
mFormat = GFXFormatDXT2;
break;
case FOURCC_DXT3:
mFormat = GFXFormatDXT3;
break;
case FOURCC_DXT4:
mFormat = GFXFormatDXT4;
break;
case FOURCC_DXT5:
mFormat = GFXFormatDXT5;
break;
default:
Con::errorf("DDSFile::readHeader - unknown fourcc = '%c%c%c%c'", ((U8*)&pfFourCC)[0], ((U8*)&pfFourCC)[1], ((U8*)&pfFourCC)[2], ((U8*)&pfFourCC)[3]);
break;
}
}
// Deal with final caps bits... Is this really necessary?
U32 caps1, caps2;
s.read(&caps1);
s.read(&caps2);
s.read(&tmp);
s.read(&tmp); // More icky reserved space.
// Screw caps1.
// if(!(caps1 & DDSCAPS_TEXTURE)))
// {
// }
// Caps2 has cubemap/volume info. Care about that.
if(caps2 & DDSCAPS2Cubemap)
{
mFlags.set(CubeMapFlag);
// Store the face flags too.
if ( caps2 & DDSCAPS2Cubemap_POSITIVEX ) mFlags.set( CubeMap_PosX_Flag );
if ( caps2 & DDSCAPS2Cubemap_NEGATIVEX ) mFlags.set( CubeMap_NegX_Flag );
if ( caps2 & DDSCAPS2Cubemap_POSITIVEY ) mFlags.set( CubeMap_PosY_Flag );
if ( caps2 & DDSCAPS2Cubemap_NEGATIVEY ) mFlags.set( CubeMap_NegY_Flag );
if ( caps2 & DDSCAPS2Cubemap_POSITIVEZ ) mFlags.set( CubeMap_PosZ_Flag );
if ( caps2 & DDSCAPS2Cubemap_NEGATIVEZ ) mFlags.set( CubeMap_NegZ_Flag );
}
// MS has ANOTHER reserved word here. This one particularly sucks.
s.read(&tmp);
return true;
}
bool DDSFile::read(Stream &s, U32 dropMipCount)
{
if( !readHeader(s) || mMipMapCount == 0 )
{
Con::errorf("DDSFile::read - error reading header!");
return false;
}
// If we're droping mips then make sure we have enough.
dropMipCount = getMin( dropMipCount, mMipMapCount - 1 );
// At this point we know what sort of image we contain. So we should
// allocate some buffers, and read it in.
// How many surfaces are we talking about?
if(mFlags.test(CubeMapFlag))
{
mSurfaces.setSize( Cubemap_Surface_Count );
for ( U32 i=0; i < Cubemap_Surface_Count; i++ )
{
// Does the cubemap contain this surface?
if ( mFlags.test( CubeMap_PosX_Flag + ( i << 1 ) ) )
mSurfaces[i] = new SurfaceData();
else
{
mSurfaces[i] = NULL;
continue;
}
// Load all the mips.
for(S32 l=0; l<mMipMapCount; l++)
mSurfaces[i]->readNextMip(this, s, mHeight, mWidth, l, l < dropMipCount );
}
}
else if (mFlags.test(VolumeFlag))
{
// Do something with volume
}
else
{
// It's a plain old texture.
// First allocate a SurfaceData to stick this in.
mSurfaces.push_back(new SurfaceData());
// Load however many mips there are.
for(S32 i=0; i<mMipMapCount; i++)
mSurfaces.last()->readNextMip(this, s, mHeight, mWidth, i, i < dropMipCount);
// Ok, we're done.
}
// If we're dropping mips then fix up the stats.
if ( dropMipCount > 0 )
{
// Fix up the pitch and/or linear size.
if( mFlags.test( LinearSizeFlag ) )
mPitchOrLinearSize = getSurfaceSize( dropMipCount );
else if ( mFlags.test( PitchSizeFlag ) )
mPitchOrLinearSize = getSurfacePitch( dropMipCount );
else
mPitchOrLinearSize = mPitchOrLinearSize; // Do nothing?
// Now fix up the rest of the
mMipMapCount = getMax( (U32)1, mMipMapCount - dropMipCount );
mHeight = getHeight( dropMipCount );
mWidth = getWidth( dropMipCount );
}
return true;
}
bool DDSFile::writeHeader( Stream &s )
{
// Read the FOURCC
s.write( 4, "DDS " );
U32 tmp = 0;
// Read the size of the header.
s.write( 124 );
// Read some flags...
U32 ddsdFlags = DDSDCaps | DDSDPixelFormat | DDSDWidth | DDSDHeight;
if ( mFlags.test( CompressedData ) )
ddsdFlags |= DDSDLinearSize;
else
ddsdFlags |= DDSDPitch;
if ( mMipMapCount > 0 )
ddsdFlags |= DDSDMipMapCount;
s.write( ddsdFlags );
// Read height and width (always present)
s.write( mHeight );
s.write( mWidth );
// Ok, some flags are set, so let's do some reading.
s.write( mPitchOrLinearSize );
// Do we need to read depth? If so, we are a volume texture!
s.write( mDepth );
// Deal with mips!
s.write( mMipMapCount );
// Deal with 11 DWORDS of reserved space (this reserved space brought to
// you by DirectDraw and the letters F and U).
for(U32 i=0; i<11; i++)
s.write( tmp ); // is this right?
// Now we're onto the pixel format!
// This is the size, in bits,
// of the pixel format data.
tmp = 32;
s.write( tmp );
U32 ddpfFlags;
U32 fourCC = 0;
if ( mFlags.test( CompressedData ) )
{
ddpfFlags = DDPFFourCC;
if (mFormat == GFXFormatDXT1)
fourCC = FOURCC_DXT1;
if (mFormat == GFXFormatDXT3)
fourCC = FOURCC_DXT3;
if (mFormat == GFXFormatDXT5)
fourCC = FOURCC_DXT5;
}
else
ddpfFlags = mBytesPerPixel == 4 ? DDPFRGB | DDPFAlphaPixels : DDPFRGB;
s.write( ddpfFlags );
// Read the next few values so we can deal with them all in one go.
//U32 pfFourCC, pfBitCount, pfRMask, pfGMask, pfBMask, pfAlphaMask;
s.write( fourCC );
s.write( mBytesPerPixel * 8 );
s.write( 0x000000FF );
s.write( 0x00FF0000 );
s.write( 0x0000FF00 );
s.write( 0xFF000000 );
// Deal with final caps bits... Is this really necessary?
U32 caps1 = DDSCAPSTexture;
if ( mMipMapCount > 0 )
caps1 |= DDSCAPSComplex | DDSCAPSMipMap;
tmp = 0;
s.write( caps1 );
s.write( tmp );
s.write( tmp );
s.write( tmp );// More icky reserved space.
// MS has ANOTHER reserved word here. This one particularly sucks.
s.write( tmp );
return true;
}
bool DDSFile::write( Stream &s )
{
if(!writeHeader(s))
{
Con::errorf("DDSFile::write - error writing header!");
return false;
}
// At this point we know what sort of image we contain. So we should
// allocate some buffers, and read it in.
// How many surfaces are we talking about?
if(mFlags.test(CubeMapFlag))
{
// Do something with cubemaps.
}
else if (mFlags.test(VolumeFlag))
{
// Do something with volume
}
else
{
// It's a plain old texture.
// Load however many mips there are.
for ( S32 i = 0; i < mMipMapCount; i++ )
mSurfaces.last()->writeNextMip(this, s, mHeight, mWidth, i);
// Ok, we're done.
}
return true;
}
void DDSFile::SurfaceData::dumpImage(DDSFile *dds, U32 mip, const char *file)
{
GBitmap *foo = new GBitmap(dds->mWidth >> mip, dds->mHeight >> mip, false, dds->mFormat);
// Copy our data in.
dMemcpy(foo->getWritableBits(), mMips[mip], dds->getSurfaceSize(dds->mHeight, dds->mWidth, mip) );
FileStream stream;
stream.open( file, Torque::FS::File::Write );
if ( stream.getStatus() == Stream::Ok )
{
// Write it out.
foo->writeBitmap("png", stream);
}
// Clean up.
delete foo;
}
void DDSFile::SurfaceData::readNextMip(DDSFile *dds, Stream &s, U32 height, U32 width, U32 mipLevel, bool skip)
{
U32 size = dds->getSurfaceSize(height, width, mipLevel);
// If we're skipping this mip then seek forward.
if ( skip )
s.setPosition( s.getPosition() + size );
else
{
mMips.push_back(new U8[size]);
if(!s.read(size, mMips.last()))
Con::errorf("DDSFile::SurfaceData::addNextMip - failed to read mip!");
}
}
void DDSFile::SurfaceData::writeNextMip(DDSFile *dds, Stream &s, U32 height, U32 width, U32 mipLevel)
{
U32 size = dds->getSurfaceSize(height, width, mipLevel);
if(!s.write(size, mMips[mipLevel]))
Con::errorf("DDSFile::SurfaceData::writeNextMip - failed to write mip!");
}
//------------------------------------------------------------------------------
template<> void *Resource<DDSFile>::create( const Torque::Path &path )
{
#ifdef TORQUE_DEBUG_RES_MANAGER
Con::printf( "Resource<DDSFile>::create - [%s]", path.getFullPath().c_str() );
#endif
FileStream stream;
stream.open( path.getFullPath(), Torque::FS::File::Read );
if ( stream.getStatus() != Stream::Ok )
return NULL;
DDSFile *retDDS = new DDSFile;
if( !retDDS->read( stream, DDSFile::smDropMipCount ) )
{
delete retDDS;
return NULL;
}
else
{
// Set source file name
retDDS->mSourcePath = path;
retDDS->mCacheString = Torque::Path::Join( path.getRoot(), ':', path.getPath() );
retDDS->mCacheString = Torque::Path::Join( retDDS->mCacheString, '/', path.getFileName() );
}
return retDDS;
}
template<> ResourceBase::Signature Resource<DDSFile>::signature()
{
return MakeFourCC('D','D','S',' '); // Direct Draw Surface
}
Resource<DDSFile> DDSFile::load( const Torque::Path &path, U32 dropMipCount )
{
PROFILE_SCOPE( DDSFile_load );
// HACK: It sucks that we cannot pass parameters into
// the resource manager loading system.
DDSFile::smDropMipCount = dropMipCount;
Resource<DDSFile> ret = ResourceManager::get().load( path );
DDSFile::smDropMipCount = 0;
// Any kind of error checking or path stepping can happen here
return ret;
}
//------------------------------------------------------------------------------
DDSFile *DDSFile::createDDSFileFromGBitmap( const GBitmap *gbmp )
{
if( gbmp == NULL )
return NULL;
DDSFile *ret = new DDSFile;
// Set up the DDSFile properties that matter. Since this is a GBitmap, there
// are assumptions that can be made
ret->mHeight = gbmp->getHeight();
ret->mWidth = gbmp->getWidth();
ret->mDepth = 0;
ret->mFormat = gbmp->getFormat();
ret->mFlags.set(RGBData);
ret->mBytesPerPixel = gbmp->getBytesPerPixel();
ret->mMipMapCount = gbmp->getNumMipLevels();
ret->mHasTransparency = gbmp->getHasTransparency();
// ASSUMPTION!!!
// This _most likely_ does not belong here, but it is safe to assume that if
// a GBitmap is 24-bit, and it's being converted to a DDS, it is most likely
// going to be either:
// a) Uploaded as a 32-bit texture, and just needs to be padded to RGBX
// b) Uploaded as a compressed format, and needs to be padded to 32-bits anyway
if( ret->mFormat == GFXFormatR8G8B8 )
{
ret->mFormat = GFXFormatR8G8B8X8;
ret->mBytesPerPixel = 4;
}
if( ret->mMipMapCount > 1 )
ret->mFlags.set(MipMapsFlag);
// One surface per GBitmap
ret->mSurfaces.push_back( new SurfaceData() );
// Load the mips
for( int i = 0; i < ret->mMipMapCount; i++ )
{
const U32 mipSz = ret->getSurfaceSize(i);
ret->mSurfaces.last()->mMips.push_back( new U8[mipSz] );
U8 *mipMem = ret->mSurfaces.last()->mMips.last();
// If this is a straight copy, just do it, otherwise (ugh)
if( ret->mFormat == gbmp->getFormat() )
dMemcpy( mipMem, gbmp->getBits(i), mipSz );
else
{
// Assumption:
AssertFatal( gbmp->getBytesPerPixel() + 1 == ret->mBytesPerPixel, "Assumption failed, not 24->32 bit straight convert." );
for( int pxl = 0; pxl < gbmp->getWidth(i) * gbmp->getHeight(i); pxl++ )
{
U8 *dst = &mipMem[pxl * ret->mBytesPerPixel];
const U8 *src = &gbmp->getBits(i)[pxl * gbmp->getBytesPerPixel()];
dMemcpy( dst, src, gbmp->getBytesPerPixel() * sizeof(U8) );
dst[ret->mBytesPerPixel - 1] = 255;
}
}
// Uncomment to debug-dump each mip level
//ret->mSurfaces.last()->dumpImage( ret, i, avar( "%d_Gbmp_xmip%d", ret, i ) );
}
return ret;
}
DefineEngineFunction( getActiveDDSFiles, S32, (),,
"Returns the count of active DDSs files in memory.\n"
"@ingroup Rendering\n" )
{
return DDSFile::smActiveCopies;
}

View file

@ -0,0 +1,116 @@
//-----------------------------------------------------------------------------
// 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 "squish/squish.h"
#include "gfx/bitmap/ddsFile.h"
#include "gfx/bitmap/ddsUtils.h"
//------------------------------------------------------------------------------
// If false is returned, from this method, the source DDS is not modified
bool DDSUtil::squishDDS( DDSFile *srcDDS, const GFXFormat dxtFormat )
{
// Sanity check
if( srcDDS->mBytesPerPixel != 4 )
{
AssertFatal( false, "Squish wants 32-bit source data" );
return false;
}
// Build flags, start with fast compress
U32 squishFlags = squish::kColourRangeFit;
// Flag which format we are using
switch( dxtFormat )
{
case GFXFormatDXT1:
squishFlags |= squish::kDxt1;
break;
case GFXFormatDXT2:
case GFXFormatDXT3:
squishFlags |= squish::kDxt3;
break;
case GFXFormatDXT4:
case GFXFormatDXT5:
squishFlags |= squish::kDxt5;
break;
default:
AssertFatal( false, "Assumption failed" );
return false;
break;
}
// We got this far, so assume we can finish (gosh I hope so)
srcDDS->mFormat = dxtFormat;
srcDDS->mFlags.set( DDSFile::CompressedData );
// If this has alpha, set the flag
if( srcDDS->mFormat == GFXFormatR8G8B8A8 )
squishFlags |= squish::kWeightColourByAlpha;
// The source surface is the original surface of the file
DDSFile::SurfaceData *srcSurface = srcDDS->mSurfaces.last();
// Create a new surface, this will be the DXT compressed surface. Once we
// are done, we can discard the old surface, and replace it with this one.
DDSFile::SurfaceData *newSurface = new DDSFile::SurfaceData();
for( int i = 0; i < srcDDS->mMipMapCount; i++ )
{
const U8 *srcBits = srcSurface->mMips[i];
const U32 mipSz = srcDDS->getSurfaceSize(i);
U8 *dstBits = new U8[mipSz];
newSurface->mMips.push_back( dstBits );
PROFILE_START(SQUISH_DXT_COMPRESS);
// Compress with Squish
//
// squish::CompressImageOMP will call squish::CompressImage if OpenMP is
// not enabled.
squish::CompressImageOMP( srcBits, srcDDS->getWidth(i), srcDDS->getHeight(i),
dstBits, squishFlags );
PROFILE_END();
}
// Now delete the source surface, and return.
srcDDS->mSurfaces.pop_back();
delete srcSurface;
srcDDS->mSurfaces.push_back( newSurface );
return true;
}
//------------------------------------------------------------------------------
void DDSUtil::swizzleDDS( DDSFile *srcDDS, const Swizzle<U8, 4> &swizzle )
{
for( int i = 0; i < srcDDS->mMipMapCount; i++ )
{
swizzle.InPlace( srcDDS->mSurfaces.last()->mMips[i], srcDDS->getSurfaceSize( i ) );
}
}

View file

@ -0,0 +1,34 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _DDS_UTILS_H_
#define _DDS_UTILS_H_
struct DDSFile;
namespace DDSUtil
{
bool squishDDS( DDSFile *srcDDS, const GFXFormat dxtFormat );
void swizzleDDS( DDSFile *srcDDS, const Swizzle<U8, 4> &swizzle );
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,327 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GBITMAP_H_
#define _GBITMAP_H_
#ifndef __RESOURCE_H__
#include "core/resource.h"
#endif
#ifndef _SWIZZLE_H_
#include "core/util/swizzle.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h" // For the format
#endif
//-------------------------------------- Forward decls.
class Stream;
class RectI;
class Point2I;
class ColorI;
class ColorF;
//------------------------------------------------------------------------------
//-------------------------------------- GBitmap
class GBitmap
{
public:
enum Constants
{
/// The maximum mipmap levels we support. The current
/// value lets us support up to 4096 x 4096 images.
c_maxMipLevels = 13
};
struct Registration
{
/// The read function prototype.
typedef bool(*ReadFunc)(Stream &stream, GBitmap *bitmap);
/// The write function prototype. Compression levels are image-specific - see their registration declaration for details.
typedef bool(*WriteFunc)(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
/// Used to sort the registrations so that
/// lookups occur in a fixed order.
U32 priority;
Vector<String> extensions; ///< the list of file extensions for this bitmap type [these should be lower case]
ReadFunc readFunc; ///< the read function to call for this bitmap type
WriteFunc writeFunc; ///< the write function to call for this bitmap type
U32 defaultCompression; ///< the default compression level [levels are image-specific - see their registration declaration for details]
Registration()
{
priority = 0;
VECTOR_SET_ASSOCIATION( extensions );
}
};
/// Load the given bitmap file. It will try known file
/// extensions if one is not specified. If all else fails
/// it will look up the folder hierarchy for a match.
///
/// Important: Don't do something like this...
///
/// @code
/// GBitmap* bitmap; // WRONG TYPE!
/// bitmap = GBitmap::load( filename );
/// @endcode
///
/// Resources are reference-counted and the smart pointer conversion will
/// release the bitmap and thus render the resulting bitmap pointer invalid!
/// The right way is like this:
///
/// @code
/// Resource<GBitmap> bitmap; // Correct!
/// bitmap = GBitmap::load( filename );
/// @endcode
///
static Resource<GBitmap> load(const Torque::Path &path);
protected:
static Resource<GBitmap> _load(const Torque::Path &path);
static Resource<GBitmap> _search(const Torque::Path &path);
public:
GBitmap();
GBitmap(const GBitmap&);
GBitmap(const U32 in_width,
const U32 in_height,
const bool in_extrudeMipLevels = false,
const GFXFormat in_format = GFXFormatR8G8B8 );
// This builds a GBitmap with the R8G8B8A8 format using the passed in
// data (assumes that there is width * height * 4 U8's in data)
GBitmap(const U32 in_width,
const U32 in_height,
const U8* data );
virtual ~GBitmap();
static void sRegisterFormat( const Registration &reg );
static const Registration* sFindRegInfo( const String &extension );
/// Find the first file matching the registered extensions
/// skipping the original.
static bool sFindFile( const Torque::Path &path, Torque::Path *outPath );
/// Given a path to a file, try all known extensions. If the file exists on disk, fill in path
/// with the correct extension and return true. Otherwise, return false.
static bool sFindFiles( const Torque::Path &path, Vector<Torque::Path> *outFoundPaths );
/// Returns a space separated string of all registered extensions.
static String sGetExtensionList();
void allocateBitmap(const U32 in_width,
const U32 in_height,
const bool in_extrudeMipLevels = false,
const GFXFormat in_format = GFXFormatR8G8B8 );
void extrudeMipLevels(bool clearBorders = false);
void extrudeMipLevelsDetail();
U32 getNumMipLevels() const { return mNumMipLevels; }
GBitmap *createPaddedBitmap() const;
GBitmap *createPow2Bitmap() const;
/// Copies a color channel by index into the first channel
/// of the output bitmap. The output bitmap must be the same
/// dimensions as the source.
void copyChannel( U32 index, GBitmap *outBitmap ) const;
void copyRect(const GBitmap *in, const RectI &srcRect, const Point2I &dstPoint, const U32 srcMipLevel = 0, const U32 dstMipLevel = 0);
GFXFormat getFormat() const { return mInternalFormat; }
bool setFormat(GFXFormat fmt);
U32 getWidth(const U32 in_mipLevel = 0) const;
U32 getHeight(const U32 in_mipLevel = 0) const;
U32 getDepth(const U32 in_mipLevel = 0) const;
U8* getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = 0);
const U8* getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = 0) const;
const U8* getBits(const U32 in_mipLevel = 0) const;
U8* getWritableBits(const U32 in_mipLevel = 0);
U32 getByteSize() const { return mByteSize; }
U32 getBytesPerPixel() const { return mBytesPerPixel; }
/// Use these functions to set and get the mHasTransparency value
/// This is used to indicate that this bitmap has pixels that have
/// an alpha value less than 255 (used by the auto-Material mapper)
bool getHasTransparency() const { return mHasTransparency; }
void setHasTransparency(bool hasTransparency) { mHasTransparency = hasTransparency; }
/// In general you will want to use this function if there is not a
/// good spot in the bitmap loader(s) to check the alpha value of
/// the pixels. This function uses the texture format to loop over
/// the bitmap bits and to check for alpha values less than 255
bool checkForTransparency();
ColorF sampleTexel(F32 u, F32 v) const;
bool getColor(const U32 x, const U32 y, ColorI& rColor) const;
bool setColor(const U32 x, const U32 y, const ColorI& rColor);
/// This method will combine bitmapA and bitmapB using the operation specified
/// by combineOp. The result will be stored in the bitmap that this method is
/// called on. The size of the resulting bitmap will be the larger of A and B.
/// The format of the resulting bitmap will be the format of A or B, whichever
/// has a larger byte size.
///
/// @note There are some restrictions on ops and formats that will probably change
/// based on how we use this function.
bool combine( const GBitmap *bitmapA, const GBitmap *bitmapB, const GFXTextureOp combineOp );
/// Fills the first mip level of the bitmap with the specified color.
void fill( const ColorI &rColor );
/// An optimized version of fill().
void fillWhite();
//-------------------------------------- Internal data/operators
void deleteImage();
//-------------------------------------- Input/Output interface
/// Read a bitmap from a stream
/// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
/// @param ioStream The stream to read from
bool readBitmap( const String &bmType, Stream &ioStream );
/// Write a bitmap to a stream
/// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
/// @param ioStream The stream to read from
/// @param compressionLevel Image format-specific compression level. If set to U32_MAX, we use the default compression defined when the format was registered.
bool writeBitmap( const String &bmType, Stream &ioStream, U32 compressionLevel = U32_MAX );
bool readMNG(Stream& io_rStream); // located in bitmapMng.cc
bool writeMNG(Stream& io_rStream) const;
bool read(Stream& io_rStream);
bool write(Stream& io_rStream) const;
template<class T, dsize_t mapLength>
void swizzle(const Swizzle<T,mapLength> *s);
static Vector<Registration> sRegistrations;
private:
GFXFormat mInternalFormat;
U8* mBits; // Master bytes
U32 mByteSize;
U32 mWidth;
U32 mHeight;
U32 mBytesPerPixel;
U32 mNumMipLevels;
U32 mMipLevelOffsets[c_maxMipLevels];
bool mHasTransparency;
static const U32 csFileVersion;
};
//------------------------------------------------------------------------------
//-------------------------------------- Inlines
//
inline U32 GBitmap::getWidth(const U32 in_mipLevel) const
{
AssertFatal(in_mipLevel < mNumMipLevels,
avar("GBitmap::getWidth: mip level out of range: (%d, %d)",
in_mipLevel, mNumMipLevels));
U32 retVal = mWidth >> in_mipLevel;
return (retVal != 0) ? retVal : 1;
}
inline U32 GBitmap::getHeight(const U32 in_mipLevel) const
{
AssertFatal(in_mipLevel < mNumMipLevels,
avar("Bitmap::getHeight: mip level out of range: (%d, %d)",
in_mipLevel, mNumMipLevels));
U32 retVal = mHeight >> in_mipLevel;
return (retVal != 0) ? retVal : 1;
}
inline const U8* GBitmap::getBits(const U32 in_mipLevel) const
{
AssertFatal(in_mipLevel < mNumMipLevels,
avar("GBitmap::getBits: mip level out of range: (%d, %d)",
in_mipLevel, mNumMipLevels));
return &mBits[mMipLevelOffsets[in_mipLevel]];
}
inline U8* GBitmap::getWritableBits(const U32 in_mipLevel)
{
AssertFatal(in_mipLevel < mNumMipLevels,
avar("GBitmap::getWritableBits: mip level out of range: (%d, %d)",
in_mipLevel, mNumMipLevels));
return &mBits[mMipLevelOffsets[in_mipLevel]];
}
inline U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel)
{
return (getWritableBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * mBytesPerPixel);
}
inline const U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel) const
{
return (getBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * mBytesPerPixel);
}
template<class T, dsize_t mapLength>
void GBitmap::swizzle(const Swizzle<T,mapLength> *s )
{
const U32 memSize = getWidth() * getHeight() * mBytesPerPixel;
void *b = dMalloc(memSize);
s->ToBuffer(b, getWritableBits(), memSize);
dMemcpy(getWritableBits(), b, memSize);
dFree(b);
}
#endif //_GBITMAP_H_

View file

@ -0,0 +1,245 @@
//-----------------------------------------------------------------------------
// 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 "core/stream/stream.h"
#include "gfx/bitmap/gBitmap.h"
static bool sReadBMP(Stream &stream, GBitmap *bitmap);
static bool sWriteBMP(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
static struct _privateRegisterBMP
{
_privateRegisterBMP()
{
GBitmap::Registration reg;
reg.extensions.push_back( "bmp" );
reg.readFunc = sReadBMP;
reg.writeFunc = sWriteBMP;
GBitmap::sRegisterFormat( reg );
}
} sStaticRegisterBMP;
// structures mirror those defined by the win32 API
struct RGBQUAD
{
U8 rgbBlue;
U8 rgbGreen;
U8 rgbRed;
U8 rgbReserved;
};
struct BITMAPFILEHEADER
{
U16 bfType;
U32 bfSize;
U16 bfReserved1;
U16 bfReserved2;
U32 bfOffBits;
};
struct BITMAPINFOHEADER
{
U32 biSize;
S32 biWidth;
S32 biHeight;
U16 biPlanes;
U16 biBitCount;
U32 biCompression;
U32 biSizeImage;
S32 biXPelsPerMeter;
S32 biYPelsPerMeter;
U32 biClrUsed;
U32 biClrImportant;
};
// constants for the biCompression field
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
#define BI_BITFIELDS 3L
//------------------------------------------------------------------------------
//-------------------------------------- Supplementary I/O (Partially located in
// bitmapPng.cc)
//
static bool sReadBMP(Stream &stream, GBitmap *bitmap)
{
BITMAPINFOHEADER bi;
BITMAPFILEHEADER bf;
RGBQUAD rgb[256];
stream.read(&bf.bfType);
stream.read(&bf.bfSize);
stream.read(&bf.bfReserved1);
stream.read(&bf.bfReserved2);
stream.read(&bf.bfOffBits);
stream.read(&bi.biSize);
stream.read(&bi.biWidth);
stream.read(&bi.biHeight);
stream.read(&bi.biPlanes);
stream.read(&bi.biBitCount);
stream.read(&bi.biCompression);
stream.read(&bi.biSizeImage);
stream.read(&bi.biXPelsPerMeter);
stream.read(&bi.biYPelsPerMeter);
stream.read(&bi.biClrUsed);
stream.read(&bi.biClrImportant);
GFXFormat fmt = GFXFormatR8G8B8;
if(bi.biBitCount == 8)
{
// read in texture palette
if(!bi.biClrUsed)
bi.biClrUsed = 256;
stream.read(sizeof(RGBQUAD) * bi.biClrUsed, rgb);
}
bitmap->allocateBitmap(bi.biWidth, bi.biHeight, false, fmt);
U32 width = bitmap->getWidth();
U32 height = bitmap->getHeight();
U32 bytesPerPixel = bitmap->getBytesPerPixel();
for(U32 i = 0; i < bi.biHeight; i++)
{
U8 *rowDest = bitmap->getAddress(0, height - i - 1);
if (bi.biBitCount == 8)
{
// use palette...don't worry about being slow
for (S32 j=0; j<width; j++)
{
U8 palIdx;
stream.read(&palIdx);
U8 * pixelLocation = &rowDest[j*bytesPerPixel];
pixelLocation[0] = rgb[palIdx].rgbRed;
pixelLocation[1] = rgb[palIdx].rgbGreen;
pixelLocation[2] = rgb[palIdx].rgbBlue;
if (bytesPerPixel==3)
pixelLocation[3] = 255;
}
}
else
stream.read(bytesPerPixel * width, rowDest);
}
if(bytesPerPixel == 3 && bi.biBitCount != 8) // do BGR swap
{
U8 *ptr = bitmap->getAddress(0,0);
for(int i = 0; i < width * height; i++)
{
U8 tmp = ptr[0];
ptr[0] = ptr[2];
ptr[2] = tmp;
ptr += 3;
}
}
// We know BMP's don't have any transparency
bitmap->setHasTransparency(false);
return true;
}
static bool sWriteBMP(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
TORQUE_UNUSED( compressionLevel ); // BMP does not use compression
BITMAPINFOHEADER bi;
BITMAPFILEHEADER bf;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bitmap->getWidth();
bi.biHeight = bitmap->getHeight(); //our data is top-down
bi.biPlanes = 1;
if(bitmap->getFormat() == GFXFormatR8G8B8)
{
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biClrUsed = 0;
}
else
{
bi.biBitCount = 0;
bi.biCompression = BI_RGB; // Removes warning C4701 on line
AssertISV(false, "GBitmap::writeMSBmp - only support R8G8B8 formats!");
}
U32 width = bitmap->getWidth();
U32 height = bitmap->getHeight();
U32 bytesPP = bi.biBitCount >> 3;
bi.biSizeImage = width * height * bytesPP;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bf.bfType = makeFourCCTag('B','M',0,0); //Type of file 'BM'
bf.bfOffBits= sizeof(BITMAPINFOHEADER)
+ sizeof(BITMAPFILEHEADER)
+ (sizeof(RGBQUAD)*bi.biClrUsed);
bf.bfSize = bf.bfOffBits + bi.biSizeImage;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
stream.write(bf.bfType);
stream.write(bf.bfSize);
stream.write(bf.bfReserved1);
stream.write(bf.bfReserved2);
stream.write(bf.bfOffBits);
stream.write(bi.biSize);
stream.write(bi.biWidth);
stream.write(bi.biHeight);
stream.write(bi.biPlanes);
stream.write(bi.biBitCount);
stream.write(bi.biCompression);
stream.write(bi.biSizeImage);
stream.write(bi.biXPelsPerMeter);
stream.write(bi.biYPelsPerMeter);
stream.write(bi.biClrUsed);
stream.write(bi.biClrImportant);
//write the bitmap bits
U8* pMSUpsideDownBits = new U8[bi.biSizeImage];
for (U32 i = 0; i < height; i++)
{
const U8* pSrc = bitmap->getAddress(0, i);
U8* pDst = pMSUpsideDownBits + (height - i - 1) * width * bytesPP;
dMemcpy(pDst, pSrc, width * bytesPP);
}
stream.write(bi.biSizeImage, pMSUpsideDownBits);
delete [] pMSUpsideDownBits;
return stream.getStatus() == Stream::Ok;
}

View file

@ -0,0 +1,231 @@
//-----------------------------------------------------------------------------
// 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 "core/stream/fileStream.h"
#include "core/util/path.h"
#include "gfx/bitmap/gBitmap.h"
// This must come after our headers due to a conflicting definition of VoidPtr
#include "lungif/gif_lib.h"
using namespace Torque;
static bool sReadGIF(Stream &stream, GBitmap *bitmap);
static bool sWriteGIF(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
static struct _privateRegisterGIF
{
_privateRegisterGIF()
{
GBitmap::Registration reg;
reg.extensions.push_back( "gif" );
reg.readFunc = sReadGIF;
reg.writeFunc = sWriteGIF;
GBitmap::sRegisterFormat( reg );
}
} sStaticRegisterGIF;
//-------------------------------------- Replacement I/O for standard LIBjpeg
// functions. we don't wanna use
// FILE*'s...
static int gifReadDataFn(GifFileType *gifinfo, GifByteType *data, int length)
{
Stream *stream = (Stream*)gifinfo->UserData;
AssertFatal(stream != NULL, "gifReadDataFn::No stream.");
int pos = stream->getPosition();
if (stream->read(length, data))
return length;
if (stream->getStatus() == Stream::EOS)
return (stream->getPosition()-pos);
else
return 0;
}
//--------------------------------------
#if 0
// CodeReview - until we can write these, get rid of warning by disabling method.
static int gifWriteDataFn(GifFileType *gifinfo, GifByteType *data, int length)
{
Stream *stream = (Stream*)gifinfo->UserData;
AssertFatal(stream != NULL, "gifWriteDataFn::No stream.");
if (stream->write(length, data))
return length;
else
return 0;
}
#endif
//--------------------------------------
static bool sReadGIF( Stream &stream, GBitmap *bitmap )
{
GifFileType *gifinfo = DGifOpen( (void*)&stream, gifReadDataFn);
if (!gifinfo)
return false;
GifRecordType recordType;
do
{
if (DGifGetRecordType(gifinfo, &recordType) == GIF_ERROR)
break;
if (recordType == IMAGE_DESC_RECORD_TYPE)
{
if (DGifGetImageDesc(gifinfo) == GIF_ERROR)
break;
GFXFormat format = (gifinfo->SBackGroundColor == 0 ) ? GFXFormatR8G8B8 : GFXFormatR8G8B8A8;
bitmap->allocateBitmap(gifinfo->SWidth, gifinfo->SHeight, false, format);
// Assume no transparency until proven otherwise
bitmap->setHasTransparency(false);
U32 gwidth = gifinfo->Image.Width ? gifinfo->Image.Width : bitmap->getWidth();
U32 gheight= gifinfo->Image.Height ? gifinfo->Image.Height : bitmap->getHeight();
U32 gifSize = gwidth * gheight;
U8 *data = new U8[gifSize];
if (DGifGetLine(gifinfo, data, gifSize) != GIF_ERROR)
{
// use the global or local color table ?
GifColorType *color = NULL;
if (gifinfo->Image.ColorMap)
color = gifinfo->Image.ColorMap->Colors;
else if (gifinfo->SColorMap)
color = gifinfo->SColorMap->Colors;
if (color)
{
U8 *dst = bitmap->getAddress(gifinfo->Image.Left, gifinfo->Image.Top);
U8 *src = data;
U32 right = gifinfo->Image.Left + gwidth;
U32 bottom = gifinfo->Image.Top + gheight;
U32 next = (bitmap->getWidth() - gwidth) * bitmap->getBytesPerPixel();
if (format == GFXFormatR8G8B8A8)
{
for (U32 y=gifinfo->Image.Top; y<bottom; y++)
{
for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
{
if (*src == gifinfo->SBackGroundColor)
{
// this is a transparent pixel
dst[0] = 0; // red
dst[1] = 0; // green
dst[2] = 0; // blue
dst[3] = 0; // alpha
bitmap->setHasTransparency(true);
}
else
{
dst[0] = color[*src].Red;
dst[1] = color[*src].Green;
dst[2] = color[*src].Blue;
dst[3] = 0; // alpha
}
dst += bitmap->getBytesPerPixel();
}
dst += next;
}
}
else
{
for (U32 y=gifinfo->Image.Top; y<bottom; y++)
{
for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
{
dst[0] = color[*src].Red;
dst[1] = color[*src].Green;
dst[2] = color[*src].Blue;
dst += bitmap->getBytesPerPixel();
}
dst += next;
}
}
delete [] data;
DGifCloseFile(gifinfo);
return true;
}
}
// failure
delete [] data;
break;
}
else if (recordType == EXTENSION_RECORD_TYPE)
{
GifByteType *extension;
S32 extCode;
// Skip any extension blocks in file
if (DGifGetExtension(gifinfo, &extCode, &extension) != GIF_ERROR)
{
while (extension != NULL)
{
if (DGifGetExtensionNext(gifinfo, &extension) == GIF_ERROR)
{
return false;
}
}
}
else
{
return false;
}
}
// There used to be a break right here. This caused the while condition to
// never get processed, and so it never looped through all the records in
// the GIF. I took a quick peek back at TGB and TGE histories and I am not
// sure where this change got made, but I can't figure out why the loading
// worked at all, ever, with that break in there. The only case I can think
// of is if the first record in the GIF was the bitmap data.
// [6/6/2007 Pat]
}while (recordType != TERMINATE_RECORD_TYPE);
DGifCloseFile(gifinfo);
return true;
}
//--------------------------------------------------------------------------
static bool sWriteGIF(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
TORQUE_UNUSED( bitmap );
TORQUE_UNUSED( stream );
TORQUE_UNUSED( compressionLevel );
return false;
}

View file

@ -0,0 +1,250 @@
//-----------------------------------------------------------------------------
// 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 "ljpeg/jpeglib.h"
#include "core/stream/stream.h"
#include "gfx/bitmap/gBitmap.h"
static bool sReadJPG(Stream &stream, GBitmap *bitmap);
static bool sWriteJPG(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
static struct _privateRegisterJPG
{
_privateRegisterJPG()
{
GBitmap::Registration reg;
reg.priority = 50;
reg.extensions.push_back( "jpeg" );
reg.extensions.push_back( "jpg" );
reg.readFunc = sReadJPG;
reg.writeFunc = sWriteJPG;
GBitmap::sRegisterFormat( reg );
}
} sStaticRegisterJPG;
//-------------------------------------- Replacement I/O for standard LIBjpeg
// functions. we don't wanna use
// FILE*'s...
static int jpegReadDataFn(void *client_data, unsigned char *data, int length)
{
Stream *stream = (Stream*)client_data;
AssertFatal(stream != NULL, "jpegReadDataFn::No stream.");
int pos = stream->getPosition();
if (stream->read(length, data))
return length;
if (stream->getStatus() == Stream::EOS)
return (stream->getPosition()-pos);
else
return 0;
}
//--------------------------------------
static int jpegWriteDataFn(void *client_data, unsigned char *data, int length)
{
Stream *stream = (Stream*)client_data;
AssertFatal(stream != NULL, "jpegWriteDataFn::No stream.");
if (stream->write(length, data))
return length;
else
return 0;
}
//--------------------------------------
static int jpegFlushDataFn(void *)
{
// do nothing since we can't flush the stream object
return 0;
}
//--------------------------------------
static int jpegErrorFn(void *client_data)
{
Stream *stream = (Stream*)client_data;
AssertFatal(stream != NULL, "jpegErrorFn::No stream.");
return (stream->getStatus() != Stream::Ok);
}
//--------------------------------------
static bool sReadJPG(Stream &stream, GBitmap *bitmap)
{
JFREAD = jpegReadDataFn;
JFERROR = jpegErrorFn;
jpeg_decompress_struct cinfo;
jpeg_error_mgr jerr;
// We set up the normal JPEG error routines, then override error_exit.
//cinfo.err = jpeg_std_error(&jerr.pub);
//jerr.pub.error_exit = my_error_exit;
// if (setjmp(jerr.setjmp_buffer))
// {
// // If we get here, the JPEG code has signaled an error.
// // We need to clean up the JPEG object, close the input file, and return.
// jpeg_destroy_decompress(&cinfo);
// return false;
// }
cinfo.err = jpeg_std_error(&jerr); // set up the normal JPEG error routines.
cinfo.client_data = (void*)&stream; // set the stream into the client_data
// Now we can initialize the JPEG decompression object.
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo);
// Read file header, set default decompression parameters
jpeg_read_header(&cinfo, true);
GFXFormat format;
switch (cinfo.out_color_space)
{
case JCS_GRAYSCALE: format = GFXFormatA8; break;
case JCS_RGB: format = GFXFormatR8G8B8; break;
default:
jpeg_destroy_decompress(&cinfo);
return false;
}
// Start decompressor
jpeg_start_decompress(&cinfo);
// allocate the bitmap space and init internal variables...
bitmap->allocateBitmap(cinfo.output_width, cinfo.output_height, false, format);
// Set up the row pointers...
U32 rowBytes = cinfo.output_width * cinfo.output_components;
U8* pBase = (U8*)bitmap->getBits();
for (U32 i = 0; i < bitmap->getHeight(); i++)
{
JSAMPROW rowPointer = pBase + (i * rowBytes);
jpeg_read_scanlines(&cinfo, &rowPointer, 1);
}
// Finish decompression
jpeg_finish_decompress(&cinfo);
// Release JPEG decompression object
// This is an important step since it will release a good deal of memory.
jpeg_destroy_decompress(&cinfo);
// We know JPEG's don't have any transparency
bitmap->setHasTransparency(false);
return true;
}
//--------------------------------------------------------------------------
static bool sWriteJPG(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
TORQUE_UNUSED(compressionLevel); // compression level not currently hooked up
GFXFormat format = bitmap->getFormat();
// JPEG format does not support transparency so any image
// in Alpha format should be saved as a grayscale which coincides
// with how the readJPEG function will read-in a JPEG. So the
// only formats supported are RGB and Alpha, not RGBA.
AssertFatal(format == GFXFormatR8G8B8 || format == GFXFormatA8,
"GBitmap::writeJPEG: ONLY RGB bitmap writing supported at this time.");
if (format != GFXFormatR8G8B8 && format != GFXFormatA8)
return false;
// maximum image size allowed
#define MAX_HEIGHT 4096
if (bitmap->getHeight() > MAX_HEIGHT)
return false;
// Bind our own stream writing, error, and memory flush functions
// to the jpeg library interface
JFWRITE = jpegWriteDataFn;
JFFLUSH = jpegFlushDataFn;
JFERROR = jpegErrorFn;
// Allocate and initialize our jpeg compression structure and error manager
jpeg_compress_struct cinfo;
jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr); // set up the normal JPEG error routines.
cinfo.client_data = (void*)&stream; // set the stream into the client_data
jpeg_create_compress(&cinfo); // allocates a small amount of memory
// specify the destination for the compressed data(our stream)
jpeg_stdio_dest(&cinfo);
// set the image properties
cinfo.image_width = bitmap->getWidth(); // image width
cinfo.image_height = bitmap->getHeight(); // image height
cinfo.input_components = bitmap->getBytesPerPixel(); // samples per pixel(RGB:3, Alpha:1)
switch (format)
{
case GFXFormatA8: // no alpha support in JPEG format, so turn it into a grayscale
cinfo.in_color_space = JCS_GRAYSCALE;
break;
case GFXFormatR8G8B8: // otherwise we are writing in RGB format
cinfo.in_color_space = JCS_RGB;
break;
default:
AssertFatal( false, "Format not handled in GBitmap::writeJPEG() switch" );
break;
}
// use default compression params(75% compression)
jpeg_set_defaults(&cinfo);
// begin JPEG compression cycle
jpeg_start_compress(&cinfo, true);
// Set up the row pointers...
U32 rowBytes = cinfo.image_width * cinfo.input_components;
U8* pBase = (U8*)bitmap->getBits();
for (U32 i = 0; i < bitmap->getHeight(); i++)
{
// write the image data
JSAMPROW rowPointer = pBase + (i * rowBytes);
jpeg_write_scanlines(&cinfo, &rowPointer, 1);
}
// complete the compression cycle
jpeg_finish_compress(&cinfo);
// release the JPEG compression object
jpeg_destroy_compress(&cinfo);
// return success
return true;
}

View file

@ -0,0 +1,421 @@
//-----------------------------------------------------------------------------
// 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 "core/stream/stream.h"
#include "gfx/bitmap/gBitmap.h"
#include "core/color.h"
#define MNG_NO_CMS
#define MNG_SUPPORT_READ
#define MNG_SUPPORT_WRITE
#define MNG_SUPPORT_DISPLAY
#define MNG_STORE_CHUNKS
#define MNG_ACCESS_CHUNKS
#include "lmng/libmng.h"
static bool sReadMNG(Stream &stream, GBitmap *bitmap);
static bool sWriteMNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
static struct _privateRegisterMNG
{
_privateRegisterMNG()
{
GBitmap::Registration reg;
reg.extensions.push_back( "jng" );
reg.extensions.push_back( "mng" );
reg.readFunc = sReadMNG;
reg.writeFunc = sWriteMNG;
GBitmap::sRegisterFormat( reg );
}
} sStaticRegisterMNG;
typedef struct
{
GBitmap* image;
Stream* stream;
} mngstuff;
static mng_ptr mngMallocFn(mng_size_t size)
{
mng_ptr data = dMalloc(size);
return dMemset(data, 0, size);
}
static void mngFreeFn(mng_ptr p, mng_size_t size)
{
dFree(p);
}
static mng_bool mngOpenDataFn(mng_handle mng)
{
return MNG_TRUE;
}
static mng_bool mngCloseDataFn(mng_handle mng)
{
return MNG_TRUE;
}
static mng_bool mngReadDataFn(mng_handle mng, mng_ptr data, mng_uint32 length, mng_uint32 *bytesread)
{
mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
AssertFatal(mymng->stream != NULL, "No stream?");
bool success = mymng->stream->read(length, data);
*bytesread = length; // stupid hack
AssertFatal(success, "MNG read catastrophic error!");
if(success)
return MNG_TRUE;
else
return MNG_FALSE;
}
#if 0
// CodeReview - until we can write these, get rid of warning by disabling method.
static mng_bool mngWriteDataFn(mng_handle mng, mng_ptr data, mng_uint32 length, mng_uint32 *iWritten)
{
mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
AssertFatal(mymng->stream != NULL, "No stream?");
bool success = mymng->stream->write(length, data);
*iWritten = length; // stupid hack
AssertFatal(success, "MNG write catastrophic error!");
if(success)
return MNG_TRUE;
else
return MNG_FALSE;
}
#endif
static mng_bool mngProcessHeaderFn(mng_handle mng, mng_uint32 width, mng_uint32 height)
{
mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
GFXFormat format;
mng_uint8 colorType = mng_get_colortype(mng);
mng_uint8 alphaDepth = mng_get_alphadepth(mng);
switch(colorType)
{
case MNG_COLORTYPE_GRAY:
case MNG_COLORTYPE_JPEGGRAY:
format = GFXFormatR8G8B8;
mng_set_canvasstyle(mng, MNG_CANVAS_RGB8);
break;
case MNG_COLORTYPE_INDEXED:
if(alphaDepth >= 1)
{
format = GFXFormatR8G8B8A8;
mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
}
else
{
format = GFXFormatR8G8B8;
mng_set_canvasstyle(mng, MNG_CANVAS_RGB8);
}
case MNG_COLORTYPE_RGB:
case MNG_COLORTYPE_JPEGCOLOR:
if(alphaDepth >= 1)
{
format = GFXFormatR8G8B8A8;
mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
}
else
{
format = GFXFormatR8G8B8;
mng_set_canvasstyle(mng, MNG_CANVAS_RGB8);
}
break;
case MNG_COLORTYPE_RGBA:
case MNG_COLORTYPE_JPEGCOLORA:
format = GFXFormatR8G8B8A8;
mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
break;
default:
// This case should never get hit, however it resolves a compiler
// warning
format = GFXFormat_FIRST;
AssertISV( false, "Unknown color format in bitmap MNG Loading" );
}
mymng->image->allocateBitmap(width, height, false, format);
return MNG_TRUE;
}
static mng_ptr mngCanvasLineFn(mng_handle mng, mng_uint32 line)
{
mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
return (mng_ptr) mymng->image->getAddress(0, line);
}
static mng_bool mngRefreshFn(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
{
return MNG_TRUE;
}
static mng_uint32 mngGetTicksFn(mng_handle mng)
{
return 0;
}
static mng_bool mngSetTimerFn(mng_handle mng, mng_uint32 msecs)
{
return MNG_TRUE;
}
static mng_bool mngFatalErrorFn(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text)
{
mng_cleanup(&mng);
AssertISV(false, avar("Error reading MNG file:\n %s", (const char*)text));
return MNG_FALSE;
}
static bool sReadMNG(Stream &stream, GBitmap *bitmap)
{
mngstuff mnginfo;
dMemset(&mnginfo, 0, sizeof(mngstuff));
mng_handle mng = mng_initialize(&mnginfo, mngMallocFn, mngFreeFn, MNG_NULL);
if(mng == NULL)
return false;
// setup the callbacks
mng_setcb_errorproc(mng, mngFatalErrorFn);
mng_setcb_openstream(mng, mngOpenDataFn);
mng_setcb_closestream(mng, mngCloseDataFn);
mng_setcb_readdata(mng, mngReadDataFn);
mng_setcb_processheader(mng, mngProcessHeaderFn);
mng_setcb_getcanvasline(mng, mngCanvasLineFn);
mng_setcb_refresh(mng, mngRefreshFn);
mng_setcb_gettickcount(mng, mngGetTicksFn);
mng_setcb_settimer(mng, mngSetTimerFn);
mnginfo.image = bitmap;
mnginfo.stream = &stream;
mng_read(mng);
mng_display(mng);
// hacks :(
// libmng doesn't support returning data in gray/gray alpha format,
// so we grab as RGB/RGBA and just cut off the g and b
mng_uint8 colorType = mng_get_colortype(mng);
switch(colorType)
{
case MNG_COLORTYPE_GRAY:
case MNG_COLORTYPE_JPEGGRAY:
{
GBitmap temp(*bitmap);
bitmap->deleteImage();
bitmap->allocateBitmap(temp.getWidth(), temp.getHeight(), false, GFXFormatA8);
// force getColor to read in in the same color value for each channel
// since the gray colortype has the real alpha in the first channel
temp.setFormat( GFXFormatA8 );
ColorI color;
for(U32 row = 0; row < bitmap->getHeight(); row++)
{
for(U32 col = 0; col < bitmap->getWidth(); col++)
{
temp.getColor(col, row, color);
bitmap->setColor(col, row, color);
}
}
}
break;
}
mng_cleanup(&mng);
// Check this bitmap for transparency
bitmap->checkForTransparency();
return true;
}
static bool sWriteMNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
TORQUE_UNUSED( bitmap );
TORQUE_UNUSED( stream );
TORQUE_UNUSED( compressionLevel );
return false;
#if 0
// ONLY RGB bitmap writing supported at this time!
AssertFatal(getFormat() == GFXFormatR8G8B8 || getFormat() == GFXFormatR8G8B8A8 || getFormat() == GFXFormatA8, "GBitmap::writeMNG: ONLY RGB bitmap writing supported at this time.");
if(getFormat() != GFXFormatR8G8B8 && getFormat() != GFXFormatR8G8B8A8 && getFormat() != GFXFormatA8)
return (false);
// maximum image size allowed
#define MAX_HEIGHT 4096
if(getHeight() >= MAX_HEIGHT)
return false;
mngstuff mnginfo;
dMemset(&mnginfo, 0, sizeof(mngstuff));
mng_handle mng = mng_initialize(&mnginfo, mngMallocFn, mngFreeFn, MNG_NULL);
if(mng == NULL) {
return false;
}
// setup the callbacks
mng_setcb_openstream(mng, mngOpenDataFn);
mng_setcb_closestream(mng, mngCloseDataFn);
mng_setcb_writedata(mng, mngWriteDataFn);
// create the file in memory
mng_create(mng);
mng_putchunk_defi(mng, 0, 0, 0, MNG_FALSE, 0, 0, MNG_FALSE, 0, getWidth(), 0, getHeight());
mnginfo.image = (GBitmap*)this;
mnginfo.stream = &stream;
switch(getFormat()) {
case GFXFormatA8:
mng_putchunk_ihdr(mng, getWidth(), getHeight(),
MNG_BITDEPTH_8,
MNG_COLORTYPE_GRAY,
MNG_COMPRESSION_DEFLATE,
MNG_FILTER_ADAPTIVE,
MNG_INTERLACE_NONE);
// not implemented in lib yet
//mng_putimgdata_ihdr(mng, getWidth(), getHeight(),
// MNG_COLORTYPE_GRAY,
// MNG_BITDEPTH_8,
// MNG_COMPRESSION_DEFLATE,
// MNG_FILTER_ADAPTIVE,
// MNG_INTERLACE_NONE,
// MNG_CANVAS_GRAY8, mngCanvasLineFn);
break;
case GFXFormatR8G8B8:
mng_putchunk_ihdr(mng, getWidth(), getHeight(),
MNG_BITDEPTH_8,
MNG_COLORTYPE_RGB,
MNG_COMPRESSION_DEFLATE,
MNG_FILTER_ADAPTIVE,
MNG_INTERLACE_NONE);
// not implemented in lib yet
//mng_putimgdata_ihdr(mng, getWidth(), getHeight(),
// MNG_COLORTYPE_RGB,
// MNG_BITDEPTH_8,
// MNG_COMPRESSION_DEFLATE,
// MNG_FILTER_ADAPTIVE,
// MNG_INTERLACE_NONE,
// MNG_CANVAS_RGB8, mngCanvasLineFn);
break;
case GFXFormatR8G8B8A8:
mng_putchunk_ihdr(mng, getWidth(), getHeight(),
MNG_BITDEPTH_8,
MNG_COLORTYPE_RGBA,
MNG_COMPRESSION_DEFLATE,
MNG_FILTER_ADAPTIVE,
MNG_INTERLACE_NONE);
// not implemented in lib yet
//mng_putimgdata_ihdr(mng, getWidth(), getHeight(),
// MNG_COLORTYPE_RGBA,
// MNG_BITDEPTH_8,
// MNG_COMPRESSION_DEFLATE,
// MNG_FILTER_ADAPTIVE,
// MNG_INTERLACE_NONE,
// MNG_CANVAS_RGBA8, mngCanvasLineFn);
break;
}
// below is a hack until libmng is mature enough to handle this itself
//-----------------------------------------------------------------------------
U8 *tmpbuffer = new U8[this->byteSize + getHeight()];
if(tmpbuffer == 0)
{
mng_cleanup(&mng);
return false;
}
// transfer data, add filterbyte
U32 effwdt = getWidth() * this->bytesPerPixel;
for(U32 Row = 0; Row < getHeight(); Row++)
{
// first Byte in each scanline is filterbyte: currently 0 -> no filter
tmpbuffer[Row * (effwdt + 1)] = 0;
// copy the scanline
dMemcpy(tmpbuffer + Row * (effwdt + 1) + 1, getAddress(0, Row), effwdt);
}
// compress data with zlib
U8 *dstbuffer = new U8[this->byteSize + getHeight()];
if(dstbuffer == 0)
{
delete [] tmpbuffer;
mng_cleanup(&mng);
return false;
}
U32 dstbufferSize = this->byteSize + getHeight();
if(Z_OK != compress2((Bytef*)dstbuffer,(uLongf*)&dstbufferSize, (const Bytef*)tmpbuffer, dstbufferSize, 9))
{
delete [] tmpbuffer;
delete [] dstbuffer;
mng_cleanup(&mng);
return false;
}
mng_putchunk_idat(mng, dstbufferSize, (mng_ptr*)dstbuffer);
//-----------------------------------------------------------------------------
mng_putchunk_iend(mng);
delete [] tmpbuffer;
delete [] dstbuffer;
mng_write(mng);
mng_cleanup(&mng);
return true;
#endif
}

View file

@ -0,0 +1,647 @@
//-----------------------------------------------------------------------------
// 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 "core/stream/fileStream.h"
#include "core/stream/memStream.h"
#include "core/strings/stringFunctions.h"
#include "gfx/bitmap/gBitmap.h"
#include "gfx/bitmap/pngUtils.h"
#define PNG_INTERNAL 1
#include <time.h>
#include "lpng/png.h"
#include "zlib/zlib.h"
#ifdef NULL
#undef NULL
#define NULL 0
#endif
static bool sReadPNG(Stream &stream, GBitmap *bitmap);
/// Compression levels for PNGs range from 0-9.
/// A value outside that range will cause the write routine to look for the best compression for a given PNG. This can be slow.
static bool sWritePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
static bool _writePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel, U32 strategy, U32 filter);
static struct _privateRegisterPNG
{
_privateRegisterPNG()
{
GBitmap::Registration reg;
reg.priority = 100;
reg.extensions.push_back( "png" );
reg.readFunc = sReadPNG;
reg.writeFunc = sWritePNG;
reg.defaultCompression = 6;
GBitmap::sRegisterFormat( reg );
}
} sStaticRegisterPNG;
//-------------------------------------- Replacement I/O for standard LIBPng
// functions. we don't wanna use
// FILE*'s...
static void pngReadDataFn(png_structp png_ptr,
png_bytep data,
png_size_t length)
{
AssertFatal(png_ptr->io_ptr != NULL, "No stream?");
Stream *strm = (Stream*)png_ptr->io_ptr;
bool success = strm->read(length, data);
AssertFatal(success, "pngReadDataFn - failed to read from stream!");
}
//--------------------------------------
static void pngWriteDataFn(png_structp png_ptr,
png_bytep data,
png_size_t length)
{
AssertFatal(png_ptr->io_ptr != NULL, "No stream?");
Stream *strm = (Stream*)png_ptr->io_ptr;
bool success = strm->write(length, data);
AssertFatal(success, "pngWriteDataFn - failed to write to stream!");
}
//--------------------------------------
static void pngFlushDataFn(png_structp /*png_ptr*/)
{
//
}
static png_voidp pngMallocFn(png_structp /*png_ptr*/, png_size_t size)
{
return FrameAllocator::alloc(size);
}
static void pngFreeFn(png_structp /*png_ptr*/, png_voidp /*mem*/)
{
}
static png_voidp pngRealMallocFn(png_structp /*png_ptr*/, png_size_t size)
{
return (png_voidp)dMalloc(size);
}
static void pngRealFreeFn(png_structp /*png_ptr*/, png_voidp mem)
{
dFree(mem);
}
//--------------------------------------
static void pngFatalErrorFn(png_structp /*png_ptr*/,
png_const_charp pMessage)
{
AssertISV(false, avar("Error reading PNG file:\n %s", pMessage));
}
//--------------------------------------
static void pngWarningFn(png_structp, png_const_charp /*pMessage*/)
{
// AssertWarn(false, avar("Warning reading PNG file:\n %s", pMessage));
}
//--------------------------------------
static bool sReadPNG(Stream &stream, GBitmap *bitmap)
{
static const U32 cs_headerBytesChecked = 8;
U8 header[cs_headerBytesChecked];
stream.read(cs_headerBytesChecked, header);
bool isPng = png_check_sig(header, cs_headerBytesChecked) != 0;
if (isPng == false)
{
AssertWarn(false, "GBitmap::readPNG: stream doesn't contain a PNG");
return false;
}
U32 prevWaterMark = FrameAllocator::getWaterMark();
png_structp png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
NULL,
pngFatalErrorFn,
pngWarningFn,
NULL,
pngRealMallocFn,
pngRealFreeFn);
if (png_ptr == NULL)
{
FrameAllocator::setWaterMark(prevWaterMark);
return false;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
png_destroy_read_struct(&png_ptr,
(png_infopp)NULL,
(png_infopp)NULL);
FrameAllocator::setWaterMark(prevWaterMark);
return false;
}
png_infop end_info = png_create_info_struct(png_ptr);
if (end_info == NULL)
{
png_destroy_read_struct(&png_ptr,
&info_ptr,
(png_infopp)NULL);
FrameAllocator::setWaterMark(prevWaterMark);
return false;
}
png_set_read_fn(png_ptr, &stream, pngReadDataFn);
// Read off the info on the image.
png_set_sig_bytes(png_ptr, cs_headerBytesChecked);
png_read_info(png_ptr, info_ptr);
// OK, at this point, if we have reached it ok, then we can reset the
// image to accept the new data...
//
bitmap->deleteImage();
png_uint_32 width;
png_uint_32 height;
S32 bit_depth;
S32 color_type;
png_get_IHDR(png_ptr, info_ptr,
&width, &height, // obv.
&bit_depth, &color_type, // obv.
NULL, // interlace
NULL, // compression_type
NULL); // filter_type
// First, handle the color transformations. We need this to read in the
// data as RGB or RGBA, _always_, with a maximal channel width of 8 bits.
//
bool transAlpha = false;
GFXFormat format = GFXFormatR8G8B8;
// Strip off any 16 bit info
//
if (bit_depth == 16 && color_type != PNG_COLOR_TYPE_GRAY)
{
png_set_strip_16(png_ptr);
}
// Expand a transparency channel into a full alpha channel...
//
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
{
png_set_expand(png_ptr);
transAlpha = true;
}
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
png_set_expand(png_ptr);
format = transAlpha ? GFXFormatR8G8B8A8 : GFXFormatR8G8B8;
}
else if (color_type == PNG_COLOR_TYPE_GRAY)
{
png_set_expand(png_ptr);
if (bit_depth == 16)
format = GFXFormatR5G6B5;
else
format = GFXFormatA8;
}
else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
png_set_expand(png_ptr);
png_set_gray_to_rgb(png_ptr);
format = GFXFormatR8G8B8A8;
}
else if (color_type == PNG_COLOR_TYPE_RGB)
{
format = transAlpha ? GFXFormatR8G8B8A8 : GFXFormatR8G8B8;
png_set_expand(png_ptr);
}
else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
png_set_expand(png_ptr);
format = GFXFormatR8G8B8A8;
}
// Update the info pointer with the result of the transformations
// above...
png_read_update_info(png_ptr, info_ptr);
png_uint_32 rowBytes = png_get_rowbytes(png_ptr, info_ptr);
if (format == GFXFormatR8G8B8)
{
AssertFatal(rowBytes == width * 3,
"Error, our rowbytes are incorrect for this transform... (3)");
}
else if (format == GFXFormatR8G8B8A8)
{
AssertFatal(rowBytes == width * 4,
"Error, our rowbytes are incorrect for this transform... (4)");
}
else if (format == GFXFormatR5G6B5)
{
AssertFatal(rowBytes == width * 2,
"Error, our rowbytes are incorrect for this transform... (2)");
}
// actually allocate the bitmap space...
bitmap->allocateBitmap(width, height,
false, // don't extrude miplevels...
format); // use determined format...
// Set up the row pointers...
png_bytep* rowPointers = new png_bytep[ height ];
U8* pBase = (U8*)bitmap->getBits();
for (U32 i = 0; i < height; i++)
rowPointers[i] = pBase + (i * rowBytes);
// And actually read the image!
png_read_image(png_ptr, rowPointers);
// We're outta here, destroy the png structs, and release the lock
// as quickly as possible...
//png_read_end(png_ptr, end_info);
delete [] rowPointers;
png_read_end(png_ptr, NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
// Ok, the image is read in, now we need to finish up the initialization,
// which means: setting up the detailing members, init'ing the palette
// key, etc...
//
// actually, all of that was handled by allocateBitmap, so we're outta here
//
// Check this bitmap for transparency
bitmap->checkForTransparency();
FrameAllocator::setWaterMark(prevWaterMark);
return true;
}
//--------------------------------------------------------------------------
static bool _writePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel, U32 strategy, U32 filter)
{
GFXFormat format = bitmap->getFormat();
// ONLY RGB bitmap writing supported at this time!
AssertFatal( format == GFXFormatR8G8B8 ||
format == GFXFormatR8G8B8A8 ||
format == GFXFormatR8G8B8X8 ||
format == GFXFormatA8 ||
format == GFXFormatR5G6B5, "_writePNG: ONLY RGB bitmap writing supported at this time.");
if ( format != GFXFormatR8G8B8 &&
format != GFXFormatR8G8B8A8 &&
format != GFXFormatR8G8B8X8 &&
format != GFXFormatA8 &&
format != GFXFormatR5G6B5 )
return false;
png_structp png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
NULL,
pngFatalErrorFn,
pngWarningFn,
NULL,
pngMallocFn,
pngFreeFn);
if (png_ptr == NULL)
return (false);
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return false;
}
png_set_write_fn(png_ptr, &stream, pngWriteDataFn, pngFlushDataFn);
// Set the compression level, image filters, and compression strategy...
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
png_ptr->zlib_strategy = strategy;
png_set_compression_window_bits(png_ptr, 15);
png_set_compression_level(png_ptr, compressionLevel);
png_set_filter(png_ptr, 0, filter);
// Set the image information here. Width and height are up to 2^31,
// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
// or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
U32 width = bitmap->getWidth();
U32 height = bitmap->getHeight();
if (format == GFXFormatR8G8B8)
{
png_set_IHDR(png_ptr, info_ptr,
width, height, // the width & height
8, PNG_COLOR_TYPE_RGB, // bit_depth, color_type,
NULL, // no interlace
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8)
{
png_set_IHDR(png_ptr, info_ptr,
width, height, // the width & height
8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type,
NULL, // no interlace
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatA8)
{
png_set_IHDR(png_ptr, info_ptr,
width, height, // the width & height
8, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type,
NULL, // no interlace
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatR5G6B5)
{
png_set_IHDR(png_ptr, info_ptr,
width, height, // the width & height
16, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type,
PNG_INTERLACE_NONE, // no interlace
PNG_COMPRESSION_TYPE_DEFAULT, // compression type
PNG_FILTER_TYPE_DEFAULT); // filter type
png_color_8_struct sigBit = { 0 };
sigBit.gray = 16;
png_set_sBIT(png_ptr, info_ptr, &sigBit );
png_set_swap( png_ptr );
}
png_write_info(png_ptr, info_ptr);
FrameAllocatorMarker marker;
png_bytep* row_pointers = (png_bytep*)marker.alloc( height * sizeof( png_bytep ) );
for (U32 i=0; i<height; i++)
row_pointers[i] = const_cast<png_bytep>(bitmap->getAddress(0, i));
png_write_image(png_ptr, row_pointers);
// Write S3TC data if present...
// Write FXT1 data if present...
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return true;
}
//--------------------------------------------------------------------------
static bool sWritePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
U32 waterMark = FrameAllocator::getWaterMark();
if ( compressionLevel < 10 )
{
bool retVal = _writePNG(bitmap, stream, compressionLevel, 0, PNG_ALL_FILTERS);
FrameAllocator::setWaterMark(waterMark);
return retVal;
}
// check all our methods of compression to find the best one and use it
U8* buffer = new U8[1 << 22]; // 4 Megs. Should be enough...
MemStream* pMemStream = new MemStream(1 << 22, buffer, false, true);
const U32 zStrategies[] = { Z_DEFAULT_STRATEGY,
Z_FILTERED };
const U32 pngFilters[] = { PNG_FILTER_NONE,
PNG_FILTER_SUB,
PNG_FILTER_UP,
PNG_FILTER_AVG,
PNG_FILTER_PAETH,
PNG_ALL_FILTERS };
U32 minSize = 0xFFFFFFFF;
U32 bestStrategy = 0xFFFFFFFF;
U32 bestFilter = 0xFFFFFFFF;
U32 bestCLevel = 0xFFFFFFFF;
for (U32 cl = 0; cl <=9; cl++)
{
for (U32 zs = 0; zs < 2; zs++)
{
for (U32 pf = 0; pf < 6; pf++)
{
pMemStream->setPosition(0);
U32 waterMarkInner = FrameAllocator::getWaterMark();
if (_writePNG(bitmap, *pMemStream, cl, zStrategies[zs], pngFilters[pf]) == false)
AssertFatal(false, "Handle this error!");
FrameAllocator::setWaterMark(waterMarkInner);
if (pMemStream->getPosition() < minSize)
{
minSize = pMemStream->getPosition();
bestStrategy = zs;
bestFilter = pf;
bestCLevel = cl;
}
}
}
}
AssertFatal(minSize != 0xFFFFFFFF, "Error, no best found?");
delete pMemStream;
delete [] buffer;
bool retVal = _writePNG(bitmap, stream,
bestCLevel,
zStrategies[bestStrategy],
pngFilters[bestFilter]);
FrameAllocator::setWaterMark(waterMark);
return retVal;
}
//--------------------------------------------------------------------------
// Stores PNG stream data
struct DeferredPNGWriterData {
png_structp png_ptr;
png_infop info_ptr;
U32 width;
U32 height;
};
DeferredPNGWriter::DeferredPNGWriter() :
mData( NULL ),
mActive(false)
{
mData = new DeferredPNGWriterData();
}
DeferredPNGWriter::~DeferredPNGWriter()
{
delete mData;
}
bool DeferredPNGWriter::begin( GFXFormat format, S32 width, S32 height, Stream &stream, U32 compressionLevel )
{
// ONLY RGB bitmap writing supported at this time!
AssertFatal( format == GFXFormatR8G8B8 ||
format == GFXFormatR8G8B8A8 ||
format == GFXFormatR8G8B8X8 ||
format == GFXFormatA8 ||
format == GFXFormatR5G6B5, "_writePNG: ONLY RGB bitmap writing supported at this time.");
if ( format != GFXFormatR8G8B8 &&
format != GFXFormatR8G8B8A8 &&
format != GFXFormatR8G8B8X8 &&
format != GFXFormatA8 &&
format != GFXFormatR5G6B5 )
return false;
mData->png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
NULL,
pngFatalErrorFn,
pngWarningFn,
NULL,
pngRealMallocFn,
pngRealFreeFn);
if (mData->png_ptr == NULL)
return (false);
mData->info_ptr = png_create_info_struct(mData->png_ptr);
if (mData->info_ptr == NULL)
{
png_destroy_write_struct(&mData->png_ptr, (png_infopp)NULL);
return false;
}
png_set_write_fn(mData->png_ptr, &stream, pngWriteDataFn, pngFlushDataFn);
// Set the compression level, image filters, and compression strategy...
mData->png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
mData->png_ptr->zlib_strategy = 0;
png_set_compression_window_bits(mData->png_ptr, 15);
png_set_compression_level(mData->png_ptr, compressionLevel);
png_set_filter(mData->png_ptr, 0, PNG_ALL_FILTERS);
// Set the image information here. Width and height are up to 2^31,
// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
// or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
if (format == GFXFormatR8G8B8)
{
png_set_IHDR(mData->png_ptr, mData->info_ptr,
width, height, // the width & height
8, PNG_COLOR_TYPE_RGB, // bit_depth, color_type,
NULL, // no interlace
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8)
{
png_set_IHDR(mData->png_ptr, mData->info_ptr,
width, height, // the width & height
8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type,
NULL, // no interlace
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatA8)
{
png_set_IHDR(mData->png_ptr, mData->info_ptr,
width, height, // the width & height
8, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type,
NULL, // no interlace
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatR5G6B5)
{
png_set_IHDR(mData->png_ptr, mData->info_ptr,
width, height, // the width & height
16, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type,
PNG_INTERLACE_NONE, // no interlace
PNG_COMPRESSION_TYPE_DEFAULT, // compression type
PNG_FILTER_TYPE_DEFAULT); // filter type
png_color_8_struct sigBit = { 0 };
sigBit.gray = 16;
png_set_sBIT(mData->png_ptr, mData->info_ptr, &sigBit );
png_set_swap( mData->png_ptr );
}
png_write_info(mData->png_ptr, mData->info_ptr);
mActive = true;
return true;
}
void DeferredPNGWriter::append( GBitmap* bitmap, U32 rows)
{
AssertFatal(mActive, "Cannot append to an inactive DeferredPNGWriter!");
U32 height = getMin( bitmap->getHeight(), rows);
FrameAllocatorMarker marker;
png_bytep* row_pointers = (png_bytep*)marker.alloc( height * sizeof( png_bytep ) );
for (U32 i=0; i<height; i++)
row_pointers[i] = const_cast<png_bytep>(bitmap->getAddress(0, i));
png_write_rows(mData->png_ptr, row_pointers, height);
}
void DeferredPNGWriter::end()
{
AssertFatal(mActive, "Cannot end an inactive DeferredPNGWriter!");
png_write_end(mData->png_ptr, mData->info_ptr);
png_destroy_write_struct(&mData->png_ptr, (png_infopp)NULL);
mActive = false;
}

View file

@ -0,0 +1,489 @@
//-----------------------------------------------------------------------------
// 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 "core/stream/stream.h"
#include "gfx/bitmap/gBitmap.h"
static bool sReadTGA(Stream &stream, GBitmap *bitmap);
static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
static struct _privateRegisterTGA
{
_privateRegisterTGA()
{
GBitmap::Registration reg;
reg.extensions.push_back( "tga" );
reg.readFunc = sReadTGA;
reg.writeFunc = sWriteTGA;
GBitmap::sRegisterFormat( reg );
}
} sStaticRegisterTGA;
//------------------------------------------------------------------------------
//-------------------------------------- Supplementary I/O
//
enum eImageType
{
TypeNoData = 0,
TypeUncPaletted = 1,
TypeUncTruecolor = 2,
TypeUncGrayscale = 3,
TypeRlePaletted = 9,
TypeRleTruecolor = 10,
TypeRleGrayscale = 11
};
enum ePixelMap
{
MapLowerLeft = 0,
MapLowerRight = 1,
MapUpperLeft = 2,
MapUpperRight = 3,
};
static void tga_write_pixel_to_mem( U8 * dat, U8 img_spec, U32 number,
U32 w, U32 h, U32 pixel, U32 bppOut )
{
// write the pixel to the data regarding how the
// header says the data is ordered.
U32 x, y;
switch( (img_spec & 0x30) >> 4 )
{
case MapLowerRight:
x = w - 1 - (number % w);
y = h - 1 - (number / w);
break;
case MapUpperLeft:
x = number % w;
y = number / w;
break;
case MapUpperRight:
x = w - 1 - (number % w);
y = number / w;
break;
case MapLowerLeft:
default:
x = number % w;
y = h - 1 - (number / w);
break;
}
U32 addy = (y * w + x) * bppOut;
for ( U32 j = 0; j < bppOut; j++ )
dat[addy + j] = (U8)((pixel >> (j * 8)) & 0xFF);
}
static U32 tga_get_pixel( Stream& stream, U8 bppIn,
U8 * colormap, U8 cmapBytesEntry )
{
/* get the image data value out */
U32 tmp_int32 = 0;
for ( U32 j = 0; j < bppIn; j++ )
{
U8 tmp_byte;
if ( !stream.read( &tmp_byte ) )
tmp_int32 = 0;
else
tmp_int32 += tmp_byte << (j * 8);
}
/* byte-order correct the thing */
switch( bppIn )
{
case 2:
tmp_int32 = convertLEndianToHost( (U16)tmp_int32 );
break;
case 3: /* intentional fall-thru */
case 4:
tmp_int32 = convertLEndianToHost( tmp_int32 );
break;
}
U32 tmp_col;
if ( colormap )
{
/* need to look up value to get real color */
tmp_col = 0;
for ( U32 j = 0; j < cmapBytesEntry; j++ )
tmp_col += colormap[cmapBytesEntry * tmp_int32 + j] << (8 * j);
}
else
{
tmp_col = tmp_int32;
}
return tmp_col;
}
static U32 tga_convert_color( U32 pixel, U32 bppIn, U8 alphabits, U32 bppOut )
{
// this is not only responsible for converting from different depths
// to other depths, it also switches BGR to RGB.
// this thing will also premultiply alpha, on a pixel by pixel basis.
U8 r, g, b, a;
switch( bppIn )
{
case 32:
if ( alphabits == 0 )
goto is_24_bit_in_disguise;
// 32-bit to 32-bit -- nop.
break;
case 24:
is_24_bit_in_disguise:
// 24-bit to 32-bit; (only force alpha to full)
pixel |= 0xFF000000;
break;
case 15:
is_15_bit_in_disguise:
r = (U8)(((F32)((pixel & 0x7C00) >> 10)) * 8.2258f);
g = (U8)(((F32)((pixel & 0x03E0) >> 5 )) * 8.2258f);
b = (U8)(((F32)(pixel & 0x001F)) * 8.2258f);
// 15-bit to 32-bit; (force alpha to full)
pixel = 0xFF000000 + (r << 16) + (g << 8) + b;
break;
case 16:
if ( alphabits == 1 )
goto is_15_bit_in_disguise;
// 16-bit to 32-bit; (force alpha to full)
r = (U8)(((F32)((pixel & 0xF800) >> 11)) * 8.2258f);
g = (U8)(((F32)((pixel & 0x07E0) >> 5 )) * 4.0476f);
b = (U8)(((F32)(pixel & 0x001F)) * 8.2258f);
pixel = 0xFF000000 + (r << 16) + (g << 8) + b;
break;
}
// convert the 32-bit pixel from BGR to RGB.
pixel = (pixel & 0xFF00FF00) + ((pixel & 0xFF) << 16) + ((pixel & 0xFF0000) >> 16);
r = pixel & 0x000000FF;
g = (pixel & 0x0000FF00) >> 8;
b = (pixel & 0x00FF0000) >> 16;
a = (pixel & 0xFF000000) >> 24;
// not premultiplied alpha -- multiply.
r = (U8)(((F32)r / 255.0f) * ((F32)a / 255.0f) * 255.0f);
g = (U8)(((F32)g / 255.0f) * ((F32)a / 255.0f) * 255.0f);
b = (U8)(((F32)b / 255.0f) * ((F32)a / 255.0f) * 255.0f);
pixel = r + (g << 8) + (b << 16) + (a << 24);
/* now convert from 32-bit to whatever they want. */
switch( bppOut )
{
case 4:
// 32 to 32 -- nop.
break;
case 3:
// 32 to 24 -- discard alpha.
pixel &= 0x00FFFFFF;
break;
}
return pixel;
}
static bool sReadTGA(Stream &stream, GBitmap *bitmap)
{
struct Header
{
U8 idLength; // length of the image_id string below.
U8 cmapType; // paletted image <=> cmapType
U8 imageType; // can be any of the IMG_TYPE constants above.
U16 cmapFirst; //
U16 cmapLength; // how long the colormap is
U8 cmapEntrySize; // how big a palette entry is.
U16 xOrigin; // the x origin of the image in the image data.
U16 yOrigin; // the y origin of the image in the image data.
U16 width; // the width of the image.
U16 height; // the height of the image.
U8 pixelDepth; // the depth of a pixel in the image.
U8 imageDesc; // the image descriptor.
};
// Read header
Header header;
stream.read( &header.idLength );
stream.read( &header.cmapType );
stream.read( &header.imageType );
stream.read( &header.cmapFirst );
stream.read( &header.cmapLength );
stream.read( &header.cmapEntrySize );
stream.read( &header.xOrigin );
stream.read( &header.yOrigin );
stream.read( &header.width );
stream.read( &header.height );
stream.read( &header.pixelDepth );
stream.read( &header.imageDesc );
U32 numPixels = header.width * header.height;
if ( numPixels == 0 )
{
//Con::errorf( "Texture has width and/or height set to 0" );
return false;
}
U8 alphabits = header.imageDesc & 0x0F;
/* seek past the image id, if there is one */
if ( header.idLength )
{
if ( !stream.setPosition( stream.getPosition() + header.idLength ) )
{
//Con::errorf( "Unexpected end of stream encountered" );
return false;
}
}
/* if this is a 'nodata' image, just jump out. */
if ( header.imageType == TypeNoData )
{
//Con::errorf( "Texture contains no data" );
return false;
}
/* deal with the colormap, if there is one. */
U8* colormap = NULL;
U32 cmapBytes = 0;
U8 cmapBytesEntry = 0;
if ( header.cmapType )
{
switch( header.imageType )
{
case TypeUncPaletted:
case TypeRlePaletted:
break;
case TypeUncTruecolor:
case TypeRleTruecolor:
// this should really be an error, but some really old
// crusty targas might actually be like this (created by TrueVision, no less!)
// so, we'll hack our way through it.
break;
case TypeUncGrayscale:
case TypeRleGrayscale:
//Con::errorf( "Found colormap for a grayscale image" );
return false;
}
/* ensure colormap entry size is something we support */
if ( !(header.cmapEntrySize == 15 ||
header.cmapEntrySize == 16 ||
header.cmapEntrySize == 24 ||
header.cmapEntrySize == 32) )
{
//Con::errorf( "Unsupported colormap entry size" );
return false;
}
/* allocate memory for a colormap */
if ( header.cmapEntrySize & 0x07 )
cmapBytesEntry = (((8 - (header.cmapEntrySize & 0x07)) + header.cmapEntrySize) >> 3);
else
cmapBytesEntry = (header.cmapEntrySize >> 3);
cmapBytes = cmapBytesEntry * header.cmapLength;
colormap = new U8[ cmapBytes ];
for ( U32 i = 0; i < header.cmapLength; i++ )
{
/* seek ahead to first entry used */
if ( header.cmapFirst != 0 )
stream.setPosition( stream.getPosition() + header.cmapFirst * cmapBytesEntry );
U32 tmp_int32 = 0;
for ( U32 j = 0; j < cmapBytesEntry; j++ )
{
U8 tmp_byte;
if ( !stream.read( &tmp_byte ) )
{
delete [] colormap;
//Con::errorf( "Bad colormap" );
return false;
}
tmp_int32 += tmp_byte << (j * 8);
}
// byte order correct.
tmp_int32 = convertLEndianToHost( tmp_int32 );
for ( U32 j = 0; j < cmapBytesEntry; j++ )
colormap[i * cmapBytesEntry + j] = (tmp_int32 >> (8 * j)) & 0xFF;
}
}
// compute number of bytes in an image data unit (either index or BGR triple)
U8 inBytesPerPixel = 0;
if ( header.pixelDepth & 0x07 )
inBytesPerPixel = (((8 - (header.pixelDepth & 0x07)) + header.pixelDepth) >> 3);
else
inBytesPerPixel = (header.pixelDepth >> 3);
/* assume that there's one byte per pixel */
if ( inBytesPerPixel == 0 )
inBytesPerPixel = 1;
GFXFormat gfxFmt;
U32 outBytesPerPixel;
switch ( header.pixelDepth )
{
case 32:
gfxFmt = GFXFormatR8G8B8A8;
outBytesPerPixel = 4;
break;
case 24:
default:
gfxFmt = GFXFormatR8G8B8;
outBytesPerPixel = 3;
break;
}
bitmap->allocateBitmap( header.width, header.height, false, gfxFmt );
// compute the true number of bits per pixel
U8 trueBitsPerPixel = header.cmapType ? header.cmapEntrySize : header.pixelDepth;
// Override the number of alpha bits if necessary
// Some apps generate transparent TGAs with alphabits set to 0 in the image descriptor
if ( ( trueBitsPerPixel == 32 ) && ( alphabits == 0 ) )
alphabits = 8;
switch( header.imageType )
{
case TypeUncTruecolor:
case TypeUncGrayscale:
case TypeUncPaletted:
/* FIXME: support grayscale */
for ( U32 i = 0; i < numPixels; i++ )
{
// get the color value.
U32 tmp_col = tga_get_pixel( stream, inBytesPerPixel, colormap, cmapBytesEntry );
tmp_col = tga_convert_color( tmp_col, trueBitsPerPixel, alphabits, outBytesPerPixel );
// now write the data out.
tga_write_pixel_to_mem( bitmap->getAddress( 0, 0 ), header.imageDesc,
i, header.width, header.height, tmp_col, outBytesPerPixel );
}
break;
case TypeRleTruecolor:
case TypeRleGrayscale:
case TypeRlePaletted:
// FIXME: handle grayscale..
for ( U32 i = 0; i < numPixels; )
{
/* a bit of work to do to read the data.. */
U8 packet_header;
if ( !stream.read( 1, &packet_header ) )
{
// well, just let them fill the rest with null pixels then...
packet_header = 1;
}
if ( packet_header & 0x80 )
{
/* run length packet */
U32 tmp_col = tga_get_pixel( stream, inBytesPerPixel, colormap, cmapBytesEntry );
tmp_col = tga_convert_color( tmp_col, trueBitsPerPixel, alphabits, outBytesPerPixel );
U8 repcount = (packet_header & 0x7F) + 1;
/* write all the data out */
for ( U32 j = 0; j < repcount; j++ )
{
tga_write_pixel_to_mem( bitmap->getAddress( 0, 0 ), header.imageDesc,
i + j, header.width, header.height, tmp_col, outBytesPerPixel );
}
i += repcount;
}
else
{
/* raw packet */
/* get pixel from file */
U8 repcount = (packet_header & 0x7F) + 1;
for ( U32 j = 0; j < repcount; j++ )
{
U32 tmp_col = tga_get_pixel( stream, inBytesPerPixel, colormap, cmapBytesEntry );
tmp_col = tga_convert_color( tmp_col, trueBitsPerPixel, alphabits, outBytesPerPixel );
tga_write_pixel_to_mem( bitmap->getAddress( 0, 0 ), header.imageDesc,
i + j, header.width, header.height, tmp_col, outBytesPerPixel );
}
i += repcount;
}
}
break;
default:
//Con::errorf( "Unknown image type" );
return false;
}
delete [] colormap;
// 32-bit tgas have an alpha channel
bitmap->setHasTransparency( header.pixelDepth == 32 );
return true;
}
static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!")
return false;
}

View file

@ -0,0 +1,49 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _PNG_UTILS_H_
#define _PNG_UTILS_H_
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
struct DeferredPNGWriterData; // This is used to avoid including png.h in this header
class GBitmap;
class Stream;
/// This class is used to write PNGs in row batches
class DeferredPNGWriter {
protected:
DeferredPNGWriterData *mData;
bool mActive;
public:
DeferredPNGWriter();
~DeferredPNGWriter();
bool begin( GFXFormat format, S32 width, S32 height, Stream &stream, U32 compressionLevel );
void append( GBitmap* bitmap, U32 rows );
void end();
};
#endif

1289
Engine/source/gfx/gFont.cpp Normal file

File diff suppressed because it is too large Load diff

194
Engine/source/gfx/gFont.h Normal file
View file

@ -0,0 +1,194 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFONT_H_
#define _GFONT_H_
//Includes
#ifndef _RESOURCE_H_
#include "core/resource.h"
#endif
#ifndef _PLATFORMFONT_H_
#include "platform/platformFont.h"
#endif
#ifndef _GBITMAP_H_
#include "gfx/bitmap/gBitmap.h"
#endif
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
GFX_DeclareTextureProfile(GFXFontTextureProfile);
class GFont
{
public:
enum Constants
{
TabWidthInSpaces = 3,
TextureSheetSize = 256,
};
public:
GFont();
virtual ~GFont();
static Resource<GFont> create(const String &faceName, U32 size, const char *cacheDirectory = 0, U32 charset = TGE_ANSI_CHARSET);
GFXTexHandle getTextureHandle(S32 index) const { return mTextureSheets[index]; }
const PlatformFont::CharInfo& getCharInfo(const UTF16 in_charIndex);
static const PlatformFont::CharInfo& getDefaultCharInfo();
U32 getCharHeight(const UTF16 in_charIndex);
U32 getCharWidth(const UTF16 in_charIndex);
U32 getCharXIncrement(const UTF16 in_charIndex);
bool isValidChar(const UTF16 in_charIndex) const;
const U32 getHeight() const { return mHeight; }
const U32 getBaseline() const { return mBaseline; }
const U32 getAscent() const { return mAscent; }
const U32 getDescent() const { return mDescent; }
U32 getBreakPos(const UTF16 *string, U32 strlen, U32 width, bool breakOnWhitespace);
/// These are the preferred width functions.
U32 getStrNWidth(const UTF16*, U32 n);
U32 getStrNWidthPrecise(const UTF16*, U32 n);
/// These UTF8 versions of the width functions will be deprecated, please avoid them.
U32 getStrWidth(const UTF8*); // Note: ignores c/r
U32 getStrNWidth(const UTF8*, U32 n);
U32 getStrWidthPrecise(const UTF8*); // Note: ignores c/r
U32 getStrNWidthPrecise(const UTF8*, U32 n);
void wrapString(const UTF8 *string, U32 width, Vector<U32> &startLineOffset, Vector<U32> &lineLen);
/// Dump information about this font to the console.
void dumpInfo() const;
/// Export to an image strip for image processing.
void exportStrip(const char *fileName, U32 padding, U32 kerning);
/// Import an image strip generated with exportStrip, make sure parameters match!
void importStrip(const char *fileName, U32 padding, U32 kerning);
void setPlatformFont(PlatformFont *inPlatformFont);
/// Query as to presence of platform font. If absent, we cannot generate more
/// chars!
const bool hasPlatformFont() const
{
return mPlatformFont != NULL;
}
/// Query to determine if we should use add or modulate (as A8 textures
/// are treated as having 0 for RGB).
bool isAlphaOnly() const
{
return mTextureSheets[0]->getBitmap()->getFormat() == GFXFormatA8;
}
/// Get the filename for a cached font.
static String getFontCacheFilename(const String &faceName, U32 faceSize);
/// Get the face name of the font.
String getFontFaceName() const { return mFaceName; };
U32 getFontSize() const { return mSize; }
U32 getFontCharSet() const { return mCharSet; }
bool read(Stream& io_rStream);
bool write(Stream& io_rStream);
static GFont* load( const Torque::Path& path );
protected:
bool loadCharInfo(const UTF16 ch);
void addBitmap(PlatformFont::CharInfo &charInfo);
void addSheet(void);
void assignSheet(S32 sheetNum, GBitmap *bmp);
void *mMutex;
private:
static const U32 csm_fileVersion;
PlatformFont *mPlatformFont;
Vector<GFXTexHandle>mTextureSheets;
S32 mCurX;
S32 mCurY;
S32 mCurSheet;
bool mNeedSave;
Torque::Path mGFTFile;
String mFaceName;
U32 mSize;
U32 mCharSet;
U32 mHeight;
U32 mBaseline;
U32 mAscent;
U32 mDescent;
/// List of character info structures, must be accessed through the
/// getCharInfo(U32) function to account for remapping.
Vector<PlatformFont::CharInfo> mCharInfoList;
/// Index remapping
S32 mRemapTable[65536];
};
inline U32 GFont::getCharXIncrement(const UTF16 in_charIndex)
{
const PlatformFont::CharInfo& rChar = getCharInfo(in_charIndex);
return rChar.xIncrement;
}
inline U32 GFont::getCharWidth(const UTF16 in_charIndex)
{
const PlatformFont::CharInfo& rChar = getCharInfo(in_charIndex);
return rChar.width;
}
inline U32 GFont::getCharHeight(const UTF16 in_charIndex)
{
const PlatformFont::CharInfo& rChar = getCharInfo(in_charIndex);
return rChar.height;
}
inline bool GFont::isValidChar(const UTF16 in_charIndex) const
{
if(mRemapTable[in_charIndex] != -1)
return true;
if(mPlatformFont)
return mPlatformFont->isValidChar(in_charIndex);
return false;
}
#endif //_GFONT_H_

View file

@ -0,0 +1,284 @@
//-----------------------------------------------------------------------------
// 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/genericConstBuffer.h"
#include "platform/profiler.h"
#include "core/stream/stream.h"
GenericConstBufferLayout::GenericConstBufferLayout()
{
VECTOR_SET_ASSOCIATION( mParams );
mBufferSize = 0;
mCurrentIndex = 0;
mTimesCleared = 0;
}
void GenericConstBufferLayout::addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue)
{
#ifdef TORQUE_DEBUG
// Make sure we don't have overlapping parameters
S32 start = offset;
S32 end = offset + size;
for (Params::iterator i = mParams.begin(); i != mParams.end(); i++)
{
const ParamDesc& dp = *i;
S32 pstart = dp.offset;
S32 pend = pstart + dp.size;
pstart -= start;
pend -= end;
// This is like a minkowski sum for two line segments, if the newly formed line contains
// the origin, then they intersect
bool intersect = ((pstart >= 0 && 0 >= pend) || ((pend >= 0 && 0 >= pstart)));
AssertFatal(!intersect, "Overlapping shader parameter!");
}
#endif
ParamDesc desc;
desc.name = name;
desc.constType = constType;
desc.offset = offset;
desc.size = size;
desc.arraySize = arraySize;
desc.alignValue = alignValue;
desc.index = mCurrentIndex++;
mParams.push_back(desc);
mBufferSize = getMax(desc.offset + desc.size, mBufferSize);
AssertFatal(mBufferSize, "Empty constant buffer!");
}
bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
{
PROFILE_SCOPE(GenericConstBufferLayout_set);
// Shader compilers like to optimize float4x4 uniforms into float3x3s.
// So long as the real paramater is a matrix of-some-type and the data
// passed in is a MatrixF ( which is will be ), we DO NOT have a
// mismatched const type.
AssertFatal( pd.constType == constType ||
(
( pd.constType == GFXSCT_Float2x2 ||
pd.constType == GFXSCT_Float3x3 ||
pd.constType == GFXSCT_Float4x4 ) &&
( constType == GFXSCT_Float2x2 ||
constType == GFXSCT_Float3x3 ||
constType == GFXSCT_Float4x4 )
), "Mismatched const type!" );
// This "cute" bit of code allows us to support 2x3 and 3x3 matrices in shader constants but use our MatrixF class. Yes, a hack. -BTR
switch (pd.constType)
{
case GFXSCT_Float2x2 :
case GFXSCT_Float3x3 :
case GFXSCT_Float4x4 :
return setMatrix(pd, constType, size, data, basePointer);
break;
default :
break;
}
AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
// Ok, we only set data if it's different than the data we already have, this maybe more expensive than just setting the data, but
// we'll have to do some timings to see. For example, the lighting shader constants rarely change, but we can't assume that at the
// renderInstMgr level, but we can check down here. -BTR
if (dMemcmp(basePointer+pd.offset, data, size) != 0)
{
dMemcpy(basePointer+pd.offset, data, size);
return true;
}
return false;
}
bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
{
PROFILE_SCOPE(GenericConstBufferLayout_setMatrix);
// We're generic, so just copy the full MatrixF in
AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
// Matrices are an annoying case because of the alignment issues. There are alignment issues in the matrix itself, and then potential inter matrices alignment issues.
// So GL and DX will need to derive their own GenericConstBufferLayout classes and override this method to deal with that stuff. For GenericConstBuffer, copy the whole
// 4x4 matrix regardless of the target case.
if (dMemcmp(basePointer+pd.offset, data, size) != 0)
{
dMemcpy(basePointer+pd.offset, data, size);
return true;
}
return false;
}
bool GenericConstBufferLayout::getDesc(const String& name, ParamDesc& param) const
{
for (U32 i = 0; i < mParams.size(); i++)
{
if (mParams[i].name.equal(name))
{
param = mParams[i];
return true;
}
}
return false;
}
bool GenericConstBufferLayout::getDesc(const U32 index, ParamDesc& param) const
{
if ( index < mParams.size() )
{
param = mParams[index];
return true;
}
return false;
}
bool GenericConstBufferLayout::write(Stream* s)
{
// Write out the size of the ParamDesc structure as a sanity check.
if (!s->write((U32) sizeof(ParamDesc)))
return false;
// Next, write out the number of elements we've got.
if (!s->write(mParams.size()))
return false;
for (U32 i = 0; i < mParams.size(); i++)
{
s->write(mParams[i].name);
if (!s->write(mParams[i].offset))
return false;
if (!s->write(mParams[i].size))
return false;
U32 t = (U32) mParams[i].constType;
if (!s->write(t))
return false;
if (!s->write(mParams[i].arraySize))
return false;
if (!s->write(mParams[i].alignValue))
return false;
if (!s->write(mParams[i].index))
return false;
}
return true;
}
/// Load this layout from a stream
bool GenericConstBufferLayout::read(Stream* s)
{
U32 structSize;
if (!s->read(&structSize))
return false;
if (structSize != sizeof(ParamDesc))
{
AssertFatal(false, "Invalid shader layout structure size!");
return false;
}
U32 numParams;
if (!s->read(&numParams))
return false;
mParams.setSize(numParams);
mBufferSize = 0;
mCurrentIndex = 0;
for (U32 i = 0; i < mParams.size(); i++)
{
s->read(&mParams[i].name);
if (!s->read(&mParams[i].offset))
return false;
if (!s->read(&mParams[i].size))
return false;
U32 t;
if (!s->read(&t))
return false;
mParams[i].constType = (GFXShaderConstType) t;
if (!s->read(&mParams[i].arraySize))
return false;
if (!s->read(&mParams[i].alignValue))
return false;
if (!s->read(&mParams[i].index))
return false;
mBufferSize = getMax(mParams[i].offset + mParams[i].size, mBufferSize);
mCurrentIndex = getMax(mParams[i].index, mCurrentIndex);
}
mCurrentIndex++;
return true;
}
void GenericConstBufferLayout::clear()
{
mParams.clear();
mBufferSize = 0;
mCurrentIndex = 0;
mTimesCleared++;
}
GenericConstBuffer::GenericConstBuffer(GenericConstBufferLayout* layout)
: mBuffer( NULL ),
mLayout( layout ),
mDirtyStart( U32_MAX ),
mDirtyEnd( 0 )
{
if ( layout && layout->getBufferSize() > 0 )
{
mBuffer = new U8[mLayout->getBufferSize()];
// Always set a default value, that way our isEqual checks
// will work in release as well.
dMemset( mBuffer, 0xFFFF, mLayout->getBufferSize() );
#ifdef TORQUE_DEBUG
// Clear the debug assignment tracking.
mWasAssigned.setSize( layout->getParameterCount() );
dMemset( mWasAssigned.address(), 0, mWasAssigned.memSize() );
#endif
}
}
GenericConstBuffer::~GenericConstBuffer()
{
delete [] mBuffer;
}
#ifdef TORQUE_DEBUG
void GenericConstBuffer::assertUnassignedConstants( const char *shaderName )
{
for ( U32 i=0; i < mWasAssigned.size(); i++ )
{
if ( mWasAssigned[i] )
continue;
GenericConstBufferLayout::ParamDesc pd;
mLayout->getDesc( i, pd );
// Assert on the unassigned constant.
AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",
pd.name.c_str(), shaderName ) );
}
}
#endif

View file

@ -0,0 +1,360 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GENERICCONSTBUFFER_H_
#define _GENERICCONSTBUFFER_H_
#ifndef _TORQUE_STRING_H_
#include "core/util/str.h"
#endif
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _ALIGNEDARRAY_H_
#include "core/util/tAlignedArray.h"
#endif
#ifndef _COLOR_H_
#include "core/color.h"
#endif
#ifndef _MMATRIX_H_
#include "math/mMatrix.h"
#endif
#ifndef _MPOINT2_H_
#include "math/mPoint2.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
class Stream;
/// This class defines the memory layout for a GenericConstBuffer.
class GenericConstBufferLayout
{
public:
/// Describes the parameters we contain
struct ParamDesc
{
ParamDesc()
: name(),
offset( 0 ),
size( 0 ),
constType( GFXSCT_Float ),
arraySize( 0 ),
alignValue( 0 ),
index( 0 )
{
}
void clear()
{
name = String::EmptyString;
offset = 0;
size = 0;
constType = GFXSCT_Float;
arraySize = 0;
alignValue = 0;
index = 0;
}
/// Parameter name
String name;
/// Offset into the memory block
U32 offset;
/// Size of the block
U32 size;
/// Type of data
GFXShaderConstType constType;
// For arrays, how many elements
U32 arraySize;
// Array element alignment value
U32 alignValue;
/// 0 based index of this param, in order of addParameter calls.
U32 index;
};
GenericConstBufferLayout();
virtual ~GenericConstBufferLayout() {}
/// Add a parameter to the buffer
void addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue);
/// Get the size of the buffer
inline U32 getBufferSize() const { return mBufferSize; }
/// Get the number of parameters
inline U32 getParameterCount() const { return mParams.size(); }
/// Returns the ParamDesc of a parameter
bool getDesc(const String& name, ParamDesc& param) const;
/// Returns the ParamDesc of a parameter
bool getDesc(const U32 index, ParamDesc& param) const;
/// Set a parameter, given a base pointer
virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
/// Save this layout to a stream
bool write(Stream* s);
/// Load this layout from a stream
bool read(Stream* s);
/// Restore to initial state.
void clear();
protected:
/// Set a matrix, given a base pointer.
virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
/// Vector of parameter descriptions.
typedef Vector<ParamDesc> Params;
/// Vector of parameter descriptions.
Params mParams;
U32 mBufferSize;
U32 mCurrentIndex;
// This if for debugging shader reloading and can be removed later.
U32 mTimesCleared;
};
/// This class manages shader constant data in a system memory buffer. It is
/// used by device specific classes for batching together many constant changes
/// which are then copied to the device thru a single API call.
///
/// @see GenericConstBufferLayout
///
class GenericConstBuffer
{
public:
GenericConstBuffer(GenericConstBufferLayout* layout);
~GenericConstBuffer();
/// @name Set shader constant values
/// @{
/// Actually set shader constant values
/// @param name Name of the constant, this should be a name contained in the array returned in getShaderConstDesc,
/// if an invalid name is used, its ignored, but it's not an error.
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const F32 f) { internalSet(pd, GFXSCT_Float, sizeof(F32), &f); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2F& fv) { internalSet(pd, GFXSCT_Float2, sizeof(Point2F), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3F& fv) { internalSet(pd, GFXSCT_Float3, sizeof(Point3F), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4F& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const PlaneF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(PlaneF), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const ColorF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const S32 f) { internalSet(pd, GFXSCT_Int, sizeof(S32), &f); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2I& fv) { internalSet(pd, GFXSCT_Int2, sizeof(Point2I), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3I& fv) { internalSet(pd, GFXSCT_Int3, sizeof(Point3I), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4I& fv) { internalSet(pd, GFXSCT_Int4, sizeof(Point4I), &fv); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<F32>& fv) { internalSet(pd, GFXSCT_Float, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point2F>& fv) { internalSet(pd, GFXSCT_Float2, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point3F>& fv) { internalSet(pd, GFXSCT_Float3, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point4F>& fv) { internalSet(pd, GFXSCT_Float4, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<S32>& fv) { internalSet(pd, GFXSCT_Int, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point2I>& fv) { internalSet(pd, GFXSCT_Int2, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point3I>& fv) { internalSet(pd, GFXSCT_Int3, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray<Point4I>& fv) { internalSet(pd, GFXSCT_Int4, fv.getElementSize() * fv.size(), fv.getBuffer()); }
inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF& mat, const GFXShaderConstType matrixType )
{
AssertFatal( matrixType == GFXSCT_Float2x2 ||
matrixType == GFXSCT_Float3x3 ||
matrixType == GFXSCT_Float4x4,
"GenericConstBuffer::set() - Invalid matrix type!" );
internalSet( pd, matrixType, sizeof(MatrixF), &mat );
}
inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType )
{
AssertFatal( matrixType == GFXSCT_Float2x2 ||
matrixType == GFXSCT_Float3x3 ||
matrixType == GFXSCT_Float4x4,
"GenericConstBuffer::set() - Invalid matrix type!" );
internalSet( pd, matrixType, sizeof(MatrixF)*arraySize, mat );
}
/// Gets the dirty buffer range and clears the dirty
/// state at the same time.
inline const U8* getDirtyBuffer( U32 *start, U32 *size );
/// Sets the entire buffer as dirty or clears the dirty state.
inline void setDirty( bool dirty );
/// Returns true if the buffer has been modified since the
/// last call to getDirtyBuffer or setDirty. The buffer is
/// not dirty on initial creation.
///
/// @see getDirtyBuffer
/// @see setDirty
inline bool isDirty() const { return mDirtyEnd != 0; }
/// Returns true if have the same layout and hold the same
/// data as the input buffer.
inline bool isEqual( const GenericConstBuffer *buffer ) const;
/// Returns our layout object.
inline GenericConstBufferLayout* getLayout() const { return mLayout; }
#ifdef TORQUE_DEBUG
/// Helper function used to assert on unset constants.
void assertUnassignedConstants( const char *shaderName );
#endif
protected:
/// Returns a pointer to the raw buffer
inline const U8* getBuffer() const { return mBuffer; }
/// Called by the inlined set functions above to do the
/// real dirty work of copying the data to the right location
/// within the buffer.
inline void internalSet( const GenericConstBufferLayout::ParamDesc &pd,
const GFXShaderConstType constType,
const U32 size,
const void *data );
/// The buffer layout.
GenericConstBufferLayout *mLayout;
/// The pointer to the contant store or
/// NULL if the layout is empty.
U8 *mBuffer;
/// The byte offset to the start of the dirty
/// range within the buffer or U32_MAX if the
/// buffer is not dirty.
U32 mDirtyStart;
/// The btye offset to the end of the dirty
/// range within the buffer or 0 if the buffer
/// is not dirty.
U32 mDirtyEnd;
#ifdef TORQUE_DEBUG
/// A vector used to keep track if a constant
/// has beed assigned a value or not.
///
/// @see assertUnassignedConstants
Vector<bool> mWasAssigned;
#endif
};
// NOTE: These inlines below are here to get the very best possible
// performance when setting the device shader constants and can be
// called 4000-8000 times per frame or more.
//
// You need a very good reason to consider changing them.
inline void GenericConstBuffer::internalSet( const GenericConstBufferLayout::ParamDesc &pd,
const GFXShaderConstType constType,
const U32 size,
const void *data )
{
// NOTE: We should have never gotten here if the buffer
// was null as no valid shader constant could have been
// assigned.
//
// If this happens its a bug in another part of the code.
//
AssertFatal( mBuffer, "GenericConstBuffer::internalSet - The buffer is NULL!" );
if ( mLayout->set( pd, constType, size, data, mBuffer ) )
{
#ifdef TORQUE_DEBUG
// Update the debug assignment tracking.
mWasAssigned[ pd.index ] = true;
#endif
// Keep track of the dirty range so it can be queried
// later in GenericConstBuffer::getDirtyBuffer.
mDirtyStart = getMin( pd.offset, mDirtyStart );
mDirtyEnd = getMax( pd.offset + pd.size, mDirtyEnd );
}
}
inline void GenericConstBuffer::setDirty( bool dirty )
{
if ( !mBuffer )
return;
if ( dirty )
{
mDirtyStart = 0;
mDirtyEnd = mLayout->getBufferSize();
}
else if ( !dirty )
{
mDirtyStart = U32_MAX;
mDirtyEnd = 0;
}
}
inline const U8* GenericConstBuffer::getDirtyBuffer( U32 *start, U32 *size )
{
AssertFatal( isDirty(), "GenericConstBuffer::getDirtyBuffer() - Buffer is not dirty!" );
AssertFatal( mDirtyEnd > mDirtyStart, "GenericConstBuffer::getDirtyBuffer() - Dirty range is invalid!" );
AssertFatal( mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!" );
// Use the area we calculated during internalSet.
*size = mDirtyEnd - mDirtyStart;
*start = mDirtyStart;
const U8 *buffer = mBuffer + mDirtyStart;
// Clear the dirty state while we're here.
mDirtyStart = U32_MAX;
mDirtyEnd = 0;
return buffer;
}
inline bool GenericConstBuffer::isEqual( const GenericConstBuffer *buffer ) const
{
U32 bsize = mLayout->getBufferSize();
if ( bsize != buffer->mLayout->getBufferSize() )
return false;
return dMemcmp( mBuffer, buffer->getBuffer(), bsize ) == 0;
}
#endif // _GENERICCONSTBUFFER_H_

View file

@ -0,0 +1,247 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxAPI.h"
IMPLEMENT_SCOPE( GFXAPI, GFX,,
"Graphics subystem." );
IMPLEMENT_STRUCT( GFXVideoMode,
GFXVideoMode, GFXAPI,
"Descriptor for a specific video mode." )
FIELD( resolution, resolution, 1, "Width and height of the mode's resolution in pixels." )
FIELD( bitDepth, bitDepth, 1, "Bits per pixel." )
FIELD( refreshRate, refreshRate, 1, "Frequency at which the screen is refreshed (in Hertz)." )
FIELD( fullScreen, fullScreen, 1, "Whether this is a fullscreen or windowed mode." )
FIELD( wideScreen, wideScreen, 1, "Whether this is a widescreen display mode." )
FIELD( antialiasLevel, antialiasLevel, 1, "Maximum or desired antialiasing level." )
END_IMPLEMENT_STRUCT;
ImplementEnumType( GFXAdapterType,
"Back-end graphics API used by the GFX subsystem.\n\n"
"@ingroup GFX" )
{ OpenGL, "OpenGL", "OpenGL." },
{ Direct3D8, "D3D8", "Direct3D 8." },
{ Direct3D9, "D3D9", "Direct3D 9." },
{ NullDevice, "NullDevice", "Null device for dedicated servers." },
{ Direct3D9_360, "Xenon", "Direct3D 9 on Xbox 360." }
EndImplementEnumType;
ImplementEnumType( GFXBlend,
"The supported blend modes.\n"
"@ingroup GFX" )
{ GFXBlendZero, "GFXBlendZero", "(0, 0, 0, 0)" },
{ GFXBlendOne, "GFXBlendOne", "(1, 1, 1, 1)" },
{ GFXBlendSrcColor, "GFXBlendSrcColor", "(Rs, Gs, Bs, As)" },
{ GFXBlendInvSrcColor, "GFXBlendInvSrcColor", "(1 - Rs, 1 - Gs, 1 - Bs, 1 - As)" },
{ GFXBlendSrcAlpha, "GFXBlendSrcAlpha", "(As, As, As, As)" },
{ GFXBlendInvSrcAlpha, "GFXBlendInvSrcAlpha", "( 1 - As, 1 - As, 1 - As, 1 - As)" },
{ GFXBlendDestAlpha, "GFXBlendDestAlpha", "(Ad Ad Ad Ad)" },
{ GFXBlendInvDestAlpha, "GFXBlendInvDestAlpha", "(1 - Ad 1 - Ad 1 - Ad 1 - Ad)" },
{ GFXBlendDestColor, "GFXBlendDestColor", "(Rd, Gd, Bd, Ad)" },
{ GFXBlendInvDestColor, "GFXBlendInvDestColor", "(1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad)" },
{ GFXBlendSrcAlphaSat, "GFXBlendSrcAlphaSat", "(f, f, f, 1) where f = min(As, 1 - Ad)" }
EndImplementEnumType;
ImplementEnumType( GFXCmpFunc,
"The supported comparison functions.\n"
"@ingroup GFX" )
{ GFXCmpNever, "GFXCmpNever" },
{ GFXCmpLess, "GFXCmpLess" },
{ GFXCmpEqual, "GFXCmpEqual" },
{ GFXCmpLessEqual, "GFXCmpLessEqual" },
{ GFXCmpGreater, "GFXCmpGreater" },
{ GFXCmpNotEqual, "GFXCmpNotEqual" },
{ GFXCmpGreaterEqual, "GFXCmpGreaterEqual" },
{ GFXCmpAlways, "GFXCmpAlways" },
EndImplementEnumType;
ImplementEnumType( GFXTextureAddressMode,
"The texture address modes.\n"
"@ingroup GFX" )
{ GFXAddressWrap, "GFXAddressWrap" },
{ GFXAddressMirror, "GFXAddressMirror" },
{ GFXAddressClamp, "GFXAddressClamp" },
{ GFXAddressBorder, "GFXAddressBorder" },
{ GFXAddressMirrorOnce, "GFXAddressMirrorOnce" }
EndImplementEnumType;
ImplementEnumType( GFXTextureFilterType,
"The texture filter types.\n"
"@ingroup GFX" )
{ GFXTextureFilterNone, "GFXTextureFilterNone" },
{ GFXTextureFilterPoint, "GFXTextureFilterPoint" },
{ GFXTextureFilterLinear, "GFXTextureFilterLinear" },
{ GFXTextureFilterAnisotropic, "GFXTextureFilterAnisotropic" },
{ GFXTextureFilterPyramidalQuad, "GFXTextureFilterPyramidalQuad" },
{ GFXTextureFilterGaussianQuad, "GFXTextureFilterGaussianQuad" }
EndImplementEnumType;
ImplementEnumType( GFXTextureOp,
"The texture operators.\n"
"@ingroup GFX" )
{ GFXTOPDisable, "GFXTOPDisable" },
{ GFXTOPSelectARG1, "GFXTOPSelectARG1" },
{ GFXTOPSelectARG2, "GFXTOPSelectARG2" },
{ GFXTOPModulate, "GFXTOPModulate" },
{ GFXTOPModulate2X, "GFXTOPModulate2X" },
{ GFXTOPModulate4X, "GFXTOPModulate4X" },
{ GFXTOPAdd, "GFXTOPAdd" },
{ GFXTOPAddSigned, "GFXTOPAddSigned" },
{ GFXTOPAddSigned2X, "GFXTOPAddSigned2X" },
{ GFXTOPSubtract, "GFXTOPSubtract" },
{ GFXTOPAddSmooth, "GFXTOPAddSmooth" },
{ GFXTOPBlendDiffuseAlpha, "GFXTOPBlendDiffuseAlpha" },
{ GFXTOPBlendTextureAlpha, "GFXTOPBlendTextureAlpha" },
{ GFXTOPBlendFactorAlpha, "GFXTOPBlendFactorAlpha" },
{ GFXTOPBlendTextureAlphaPM, "GFXTOPBlendTextureAlphaPM" },
{ GFXTOPBlendCURRENTALPHA, "GFXTOPBlendCURRENTALPHA" },
{ GFXTOPPreModulate, "GFXTOPPreModulate" },
{ GFXTOPModulateAlphaAddColor, "GFXTOPModulateAlphaAddColor" },
{ GFXTOPModulateColorAddAlpha, "GFXTOPModulateColorAddAlpha" },
{ GFXTOPModulateInvAlphaAddColor, "GFXTOPModulateInvAlphaAddColor" },
{ GFXTOPModulateInvColorAddAlpha, "GFXTOPModulateInvColorAddAlpha" },
{ GFXTOPBumpEnvMap, "GFXTOPBumpEnvMap" },
{ GFXTOPBumpEnvMapLuminance, "GFXTOPBumpEnvMapLuminance" },
{ GFXTOPDotProduct3, "GFXTOPDotProduct3" },
{ GFXTOPLERP, "GFXTOPLERP" }
EndImplementEnumType;
ImplementEnumType( GFXTextureArgument,
"The texture arguments.\n"
"@ingroup GFX" )
{ GFXTADiffuse, "GFXTADiffuse" },
{ GFXTACurrent, "GFXTACurrent" },
{ GFXTATexture, "GFXTATexture" },
{ GFXTATFactor, "GFXTATFactor" },
{ GFXTASpecular, "GFXTASpecular" },
{ GFXTATemp, "GFXTATemp" },
{ GFXTAConstant, "GFXTAConstant" },
{ GFXTAComplement, "OneMinus" },
{ GFXTAAlphaReplicate, "AlphaReplicate" }
EndImplementEnumType;
ImplementEnumType( GFXTextureTransformFlags,
"The texture transform state flags.\n"
"@ingroup GFX" )
{ GFXTTFFDisable, "GFXTTFDisable" },
{ GFXTTFFCoord1D, "GFXTTFFCoord1D" },
{ GFXTTFFCoord2D, "GFXTTFFCoord2D" },
{ GFXTTFFCoord3D, "GFXTTFFCoord3D" },
{ GFXTTFFCoord4D, "GFXTTFFCoord4D" },
{ GFXTTFFProjected, "GFXTTFProjected" }
EndImplementEnumType;
ImplementEnumType( GFXFormat,
"The texture formats.\n"
"@note Not all formats are supported on all platforms.\n"
"@ingroup GFX" )
{ GFXFormatR8G8B8, "GFXFormatR8G8B8" },
{ GFXFormatR8G8B8A8, "GFXFormatR8G8B8A8" },
{ GFXFormatR8G8B8X8, "GFXFormatR8G8B8X8" },
{ GFXFormatR32F, "GFXFormatR32F" },
{ GFXFormatR5G6B5, "GFXFormatR5G6B5" },
{ GFXFormatR5G5B5A1, "GFXFormatR5G5B5A1" },
{ GFXFormatR5G5B5X1, "GFXFormatR5G5B5X1" },
{ GFXFormatA4L4, "GFXFormatA4L4" },
{ GFXFormatA8L8, "GFXFormatA8L8" },
{ GFXFormatA8, "GFXFormatA8" },
{ GFXFormatL8, "GFXFormatL8" },
{ GFXFormatDXT1, "GFXFormatDXT1" },
{ GFXFormatDXT2, "GFXFormatDXT2" },
{ GFXFormatDXT3, "GFXFormatDXT3" },
{ GFXFormatDXT4, "GFXFormatDXT4" },
{ GFXFormatDXT5, "GFXFormatDXT5" },
{ GFXFormatD32, "GFXFormatD32" },
{ GFXFormatD24X8, "GFXFormatD24X8" },
{ GFXFormatD24S8, "GFXFormatD24S8" },
{ GFXFormatD24FS8, "GFXFormatD24FS8" },
{ GFXFormatD16, "GFXFormatD16" },
{ GFXFormatR32G32B32A32F, "GFXFormatR32G32B32A32F" },
{ GFXFormatR16G16B16A16F, "GFXFormatR16G16B16A16F" },
{ GFXFormatL16, "GFXFormatL16" },
{ GFXFormatR16G16B16A16, "GFXFormatR16G16B16A16" },
{ GFXFormatR16G16, "GFXFormatR16G16" },
{ GFXFormatR16F, "GFXFormatR16F" },
{ GFXFormatR16G16F, "GFXFormatR16G16F" },
{ GFXFormatR10G10B10A2, "GFXFormatR10G10B10A2" },
EndImplementEnumType;
ImplementEnumType( GFXCullMode,
"The render cull modes.\n"
"@ingroup GFX" )
{ GFXCullNone, "GFXCullNone" },
{ GFXCullCW, "GFXCullCW" },
{ GFXCullCCW, "GFXCullCCW" }
EndImplementEnumType;
ImplementEnumType( GFXStencilOp,
"The stencil operators.\n"
"@ingroup GFX" )
{ GFXStencilOpKeep, "GFXStencilOpKeep" },
{ GFXStencilOpZero, "GFXStencilOpZero" },
{ GFXStencilOpReplace, "GFXStencilOpReplace" },
{ GFXStencilOpIncrSat, "GFXStencilOpIncrSat" },
{ GFXStencilOpDecrSat, "GFXStencilOpDecrSat" },
{ GFXStencilOpInvert, "GFXStencilOpInvert" },
{ GFXStencilOpIncr, "GFXStencilOpIncr" },
{ GFXStencilOpDecr, "GFXStencilOpDecr" },
EndImplementEnumType;
ImplementEnumType( GFXBlendOp,
"The blend operators.\n"
"@ingroup GFX" )
{ GFXBlendOpAdd, "GFXBlendOpAdd" },
{ GFXBlendOpSubtract, "GFXBlendOpSubtract" },
{ GFXBlendOpRevSubtract, "GFXBlendOpRevSubtract" },
{ GFXBlendOpMin, "GFXBlendOpMin" },
{ GFXBlendOpMax, "GFXBlendOpMax" }
EndImplementEnumType;

View file

@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXAPI_H_
#define _GFXAPI_H_
#ifndef _ENGINEAPI_H_
#include "console/engineAPI.h"
#endif
#ifndef _GFXSTRUCTS_H_
#include "gfx/gfxStructs.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
DECLARE_SCOPE( GFXAPI );
DefineEnumType( GFXBlend );
DefineEnumType( GFXCmpFunc );
DefineEnumType( GFXTextureAddressMode );
DefineEnumType( GFXFormat );
DefineEnumType( GFXTextureTransformFlags );
DefineEnumType( GFXTextureFilterType );
DefineEnumType( GFXTextureOp );
DefineEnumType( GFXTextureArgument );
DefineEnumType( GFXCullMode );
DefineEnumType( GFXStencilOp );
DefineEnumType( GFXBlendOp );
DefineEnumType( GFXAdapterType );
DECLARE_STRUCT( GFXVideoMode );
DefineConsoleType( TypeGFXAdapterType, GFXAdapterType );
DefineConsoleType( TypeGFXBlend, GFXBlend );
DefineConsoleType( TypeGFXCmpFunc, GFXCmpFunc );
DefineConsoleType( TypeGFXTextureAddressMode, GFXTextureAddressMode );
DefineConsoleType( TypeGFXFormat, GFXFormat );
DefineConsoleType( TypeGFXTextureTransformFlags, GFXTextureTransformFlags );
DefineConsoleType( TypeGFXTextureFilterType, GFXTextureFilterType );
DefineConsoleType( TypeGFXTextureOp, GFXTextureOp );
DefineConsoleType( TypeGFXTextureArgument, GFXTextureArgument );
DefineConsoleType( TypeGFXCullMode, GFXCullMode );
DefineConsoleType( TypeGFXStencilOp, GFXStencilOp );
DefineConsoleType( TypeGFXBlendOp, GFXBlendOp );
#endif // !_GFXAPI_H_

View file

@ -0,0 +1,80 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXADAPTER_H_
#define _GFXADAPTER_H_
#ifndef _GFXSTRUCTS_H_
#include "gfx/gfxStructs.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _UTIL_DELEGATE_H_
#include "core/util/delegate.h"
#endif
struct GFXAdapter
{
public:
typedef Delegate<GFXDevice* (U32 adapterIndex)> CreateDeviceInstanceDelegate;
enum
{
MaxAdapterNameLen = 512,
};
char mName[MaxAdapterNameLen];
/// List of available full-screen modes. Windows can be any size,
/// so we do not enumerate them here.
Vector<GFXVideoMode> mAvailableModes;
/// Supported shader model. 0.f means none supported.
F32 mShaderModel;
const char * getName() const { return mName; }
GFXAdapterType mType;
U32 mIndex;
CreateDeviceInstanceDelegate mCreateDeviceInstanceDelegate;
GFXAdapter()
{
VECTOR_SET_ASSOCIATION( mAvailableModes );
mName[0] = 0;
mShaderModel = 0.f;
mIndex = 0;
}
~GFXAdapter()
{
mAvailableModes.clear();
}
private:
// Disallow copying to prevent mucking with our data above.
GFXAdapter(const GFXAdapter&);
};
#endif // _GFXADAPTER_H_

View file

@ -0,0 +1,233 @@
//-----------------------------------------------------------------------------
// 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/gfxCardProfile.h"
#include "console/console.h"
#include "console/engineAPI.h"
#include "core/volume.h"
// NOTE: The script class docs are in
// Documentation\scriptDocs\docs\classGFXCardProfiler.txt
void GFXCardProfiler::loadProfileScript(const char* aScriptName)
{
const String profilePath = Con::getVariable( "$pref::Video::profilePath" );
String scriptName = !profilePath.isEmpty() ? profilePath.c_str() : "profile";
scriptName += "/";
scriptName += aScriptName;
void *data = NULL;
U32 dataSize = 0;
Torque::FS::ReadFile( scriptName.c_str(), data, dataSize, true );
if(data == NULL)
{
Con::warnf(" - No card profile %s exists", scriptName.c_str());
return;
}
const char *script = static_cast<const char *>(data);
Con::printf(" - Loaded card profile %s", scriptName.c_str());
Con::executef("eval", script);
delete[] script;
}
void GFXCardProfiler::loadProfileScripts(const String& render, const String& vendor, const String& card, const String& version)
{
String script = render + ".cs";
loadProfileScript(script);
script = render + "." + vendor + ".cs";
loadProfileScript(script);
script = render + "." + vendor + "." + card + ".cs";
loadProfileScript(script);
script = render + "." + vendor + "." + card + "." + version + ".cs";
loadProfileScript(script);
}
GFXCardProfiler::GFXCardProfiler() : mVideoMemory( 0 )
{
}
GFXCardProfiler::~GFXCardProfiler()
{
mCapDictionary.clear();
}
String GFXCardProfiler::strippedString(const char *string)
{
String res = "";
// And fill it with the stripped string...
const char *a=string;
while(*a)
{
if(isalnum(*a))
{
res += *a;
}
a++;
}
return res;
}
void GFXCardProfiler::init()
{
// Spew a bit...
Con::printf("Initializing GFXCardProfiler (%s)", getRendererString().c_str());
Con::printf(" o Chipset : '%s'", getChipString().c_str());
Con::printf(" o Card : '%s'", getCardString().c_str());
Con::printf(" o Version : '%s'", getVersionString().c_str());
// Do card-specific setup...
Con::printf(" - Scanning card capabilities...");
setupCardCapabilities();
// And finally, load stuff up...
String render = strippedString(getRendererString());
String chipset = strippedString(getChipString());
String card = strippedString(getCardString());
String version = strippedString(getVersionString());
Con::printf(" - Loading card profiles...");
loadProfileScripts(render, chipset, card, version);
}
U32 GFXCardProfiler::queryProfile(const String &cap)
{
U32 res;
if( _queryCardCap( cap, res ) )
return res;
if(mCapDictionary.contains(cap))
return mCapDictionary[cap];
Con::errorf( "GFXCardProfiler (%s) - Unknown capability '%s'.", getRendererString().c_str(), cap.c_str() );
return 0;
}
U32 GFXCardProfiler::queryProfile(const String &cap, U32 defaultValue)
{
PROFILE_SCOPE( GFXCardProfiler_queryProfile );
U32 res;
if( _queryCardCap( cap, res ) )
return res;
if( mCapDictionary.contains( cap ) )
return mCapDictionary[cap];
else
return defaultValue;
}
void GFXCardProfiler::setCapability(const String &cap, U32 value)
{
// Check for dups.
if( mCapDictionary.contains( cap ) )
{
Con::warnf( "GFXCardProfiler (%s) - Setting capability '%s' multiple times.", getRendererString().c_str(), cap.c_str() );
mCapDictionary[cap] = value;
return;
}
// Insert value as necessary.
Con::printf( "GFXCardProfiler (%s) - Setting capability '%s' to %d.", getRendererString().c_str(), cap.c_str(), value );
mCapDictionary.insert( cap, value );
}
bool GFXCardProfiler::checkFormat( const GFXFormat fmt, const GFXTextureProfile *profile, bool &inOutAutogenMips )
{
return _queryFormat( fmt, profile, inOutAutogenMips );
}
DECLARE_SCOPE( GFXCardProfilerAPI );
IMPLEMENT_SCOPE( GFXCardProfilerAPI, GFXCardProfiler,, "");
ConsoleDoc(
"@class GFXCardProfilerAPI\n"
"@brief This class is the interface between TorqueScript and GFXCardProfiler.\n\n"
"You will not actually declare GFXCardProfilerAPI in TorqueScript. It exists solely "
"to give access to the GFXCardProfiler's querying functions, such as GFXCardProfiler::getRenderer.\n\n"
"@tsexample\n"
"// Example of accessing GFXCardProfiler function from script\n"
"// Notice you are not using the API version\n"
"%videoMem = GFXCardProfiler::getVideoMemoryMB();\n"
"@endtsexample\n\n"
"@see GFXCardProfiler for more information\n\n"
"@ingroup GFX\n"
);
DefineEngineStaticMethod( GFXCardProfilerAPI, getVersion, String, (),,
"Returns the driver version string." )
{
return GFX->getCardProfiler()->getVersionString();
}
DefineEngineStaticMethod( GFXCardProfilerAPI, getCard, String, (),,
"Returns the card name." )
{
return GFX->getCardProfiler()->getCardString();
}
DefineEngineStaticMethod( GFXCardProfilerAPI, getVendor, String, (),,
"Returns the card vendor name." )
{
// TODO: Fix all of this vendor crap, it's not consistent
return GFX->getCardProfiler()->getChipString();
}
DefineEngineStaticMethod( GFXCardProfilerAPI, getRenderer, String, (),,
"Returns the renderer name. For example D3D9 or OpenGL." )
{
return GFX->getCardProfiler()->getRendererString();
}
DefineEngineStaticMethod( GFXCardProfilerAPI, getVideoMemoryMB, S32, (),,
"Returns the amount of video memory in megabytes." )
{
return GFX->getCardProfiler()->getVideoMemoryInMB();
}
DefineEngineStaticMethod( GFXCardProfilerAPI, setCapability, void, ( const char *name, S32 value ),,
"Used to set the value for a specific card capability.\n"
"@param name The name of the capability being set.\n"
"@param value The value to set for that capability." )
{
GFX->getCardProfiler()->setCapability( name, (U32)value );
}
DefineEngineStaticMethod( GFXCardProfilerAPI, queryProfile, S32, ( const char *name, S32 defaultValue ),,
"Used to query the value of a specific card capability.\n"
"@param name The name of the capability being queried.\n"
"@param defaultValue The value to return if the capability is not defined." )
{
return (S32)GFX->getCardProfiler()->queryProfile( name, (U32)defaultValue );
}

View file

@ -0,0 +1,153 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXCARDPROFILE_H_
#define _GFXCARDPROFILE_H_
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
#ifndef _TORQUE_STRING_H_
#include "core/util/str.h"
#endif
/// GFXCardProfiler provides a device independent wrapper around both the
/// capabilities reported by the card/drivers and the exceptions recorded
/// in various scripts.
///
/// See the Torque Scripting Manual for more details.
///
class GFXCardProfiler
{
/// @name icpi Internal Card Profile Interface
///
/// This is the interface implemented by subclasses of this class in order
/// to provide implementation-specific information about the current
/// card/drivers.
///
/// Basically, the implementation needs to provide some unique strings:
/// - mVersionString indicating the current driver version of the
/// card in question. (For instance, "53.36")
/// - mCardDescription indicating the name of the card ("Radeon 8500")
/// - getRendererString() indicating the name of the renderer ("DX9", "GL1.2").
/// Each card profiler subclass must return a unique constant so we can keep
/// data separate. Bear in mind that punctuation is stripped from filenames.
///
/// The profiler also needs to implement setupCardCapabilities(), which is responsible
/// for querying the active device and setting defaults based on the reported capabilities,
/// and _queryCardCap, which is responsible for recognizing and responding to
/// device-specific capability queries.
///
/// @{
public:
///
const String &getVersionString() const { return mVersionString; }
const String &getCardString() const { return mCardDescription; }
const String &getChipString() const { return mChipSet; }
U32 getVideoMemoryInMB() const { return mVideoMemory; }
virtual const String &getRendererString() const = 0;
protected:
String mVersionString;
String mCardDescription;
String mChipSet;
U32 mVideoMemory;
virtual void setupCardCapabilities()=0;
/// Implementation specific query code.
///
/// This function is meant to be overridden by the specific implementation class.
///
/// Some query strings are handled by the external implementation while others must
/// be done by the specific implementation. This is given first chance to return
/// a result, then the generic rules are applied.
///
/// @param query Capability being queried.
/// @param foundResult Result to return to the caller. If the function returns true
/// then this value is returned as the result of the query.
virtual bool _queryCardCap(const String &query, U32 &foundResult)=0;
virtual bool _queryFormat( const GFXFormat fmt, const GFXTextureProfile *profile, bool &inOutAutogenMips ) = 0;
/// @}
/// @name helpergroup Helper Functions
///
/// Various helper functions.
/// Load a specified script file from the profiles directory, if it exists.
void loadProfileScript(const char* scriptName);
/// Load the script files in order for the specified card profile tuple.
void loadProfileScripts(const String& render, const String& vendor, const String& card, const String& version);
String strippedString(const char*string);
/// @}
/// Capability dictionary.
Map<String, U32> mCapDictionary;
public:
/// @name ecpi External Card Profile Interface
///
/// @{
/// Called for a profile for a given device.
GFXCardProfiler();
virtual ~GFXCardProfiler();
/// Set load script files and generally initialize things.
virtual void init()=0;
/// Called to query a capability. Given a query string it returns a
/// bool indicating whether or not the capability holds. If you call
/// this and cap isn't recognized then it returns false and prints
/// a console error.
U32 queryProfile(const String &cap);
/// Same as queryProfile(), but a default can be specified to indicate
/// what value should be returned if the profiler doesn't know anything
/// about it. If cap is not recognized, defaultValue is returned and
/// no error is reported.
U32 queryProfile(const String &cap, U32 defaultValue);
/// Set the specified capability to the specified value.
void setCapability(const String &cap, U32 value);
/// Queries support for the specified texture format, and texture profile
bool checkFormat( const GFXFormat fmt, const GFXTextureProfile *profile, bool &inOutAutogenMips );
/// @}
};
#endif

View file

@ -0,0 +1,109 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxCubemap.h"
#include "gfx/gfxDevice.h"
#include "gfx/bitmap/gBitmap.h"
#include "gfx/gfxTextureManager.h"
GFXCubemap::~GFXCubemap()
{
// If we're not dynamic and we were loaded from a
// file then give the texture manager a chance to
// remove us from the cache.
if ( mPath.isNotEmpty() )
TEXMGR->releaseCubemap( this );
}
void GFXCubemap::initNormalize( U32 size )
{
Point3F axis[6] =
{Point3F(1.0, 0.0, 0.0), Point3F(-1.0, 0.0, 0.0),
Point3F(0.0, 1.0, 0.0), Point3F( 0.0, -1.0, 0.0),
Point3F(0.0, 0.0, 1.0), Point3F( 0.0, 0.0, -1.0),};
Point3F s[6] =
{Point3F(0.0, 0.0, -1.0), Point3F( 0.0, 0.0, 1.0),
Point3F(1.0, 0.0, 0.0), Point3F( 1.0, 0.0, 0.0),
Point3F(1.0, 0.0, 0.0), Point3F(-1.0, 0.0, 0.0),};
Point3F t[6] =
{Point3F(0.0, -1.0, 0.0), Point3F(0.0, -1.0, 0.0),
Point3F(0.0, 0.0, 1.0), Point3F(0.0, 0.0, -1.0),
Point3F(0.0, -1.0, 0.0), Point3F(0.0, -1.0, 0.0),};
F32 span = 2.0;
F32 start = -1.0;
F32 stride = span / F32(size - 1);
GFXTexHandle faces[6];
for(U32 i=0; i<6; i++)
{
GFXTexHandle &tex = faces[i];
GBitmap *bitmap = new GBitmap(size, size);
// fill in...
for(U32 v=0; v<size; v++)
{
for(U32 u=0; u<size; u++)
{
Point3F vector;
vector = axis[i] +
((F32(u) * stride) + start) * s[i] +
((F32(v) * stride) + start) * t[i];
vector.normalizeSafe();
vector = ((vector * 0.5) + Point3F(0.5, 0.5, 0.5)) * 255.0;
vector.x = mClampF(vector.x, 0.0f, 255.0f);
vector.y = mClampF(vector.y, 0.0f, 255.0f);
vector.z = mClampF(vector.z, 0.0f, 255.0f);
// easy way to avoid knowledge of the format (RGB, RGBA, RGBX, ...)...
U8 *bits = bitmap->getAddress(u, v);
bits[0] = U8(vector.x);
bits[1] = U8(vector.y);
bits[2] = U8(vector.z);
}
}
tex.set(bitmap, &GFXDefaultStaticDiffuseProfile, true, "Cubemap");
}
initStatic(faces);
}
const String GFXCubemap::describeSelf() const
{
// We've got nothing
return String();
}
bool GFXCubemapHandle::set( const String &cubemapDDS )
{
/// Free the previous handle to give us
/// back any texture memory when it can.
free();
// Let the texture manager find this for us.
StrongRefPtr<GFXCubemap>::set( TEXMGR->createCubemap( cubemapDDS ) );
return isValid();
}

View file

@ -0,0 +1,96 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXCUBEMAP_H_
#define _GFXCUBEMAP_H_
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
class GFXDevice;
struct DDSFile;
///
class GFXCubemap : public StrongRefBase, public GFXResource
{
friend class GFXDevice;
friend class GFXTextureManager;
protected:
// should only be called by GFXDevice
virtual void setToTexUnit( U32 tuNum ) = 0;
/// The path to the cubemap file.
String mPath;
/// Sets the cubemap file path.
void _setPath( const String &path ) { mPath = path; }
public:
/// Create a static cubemap from a list of 6 face textures.
virtual void initStatic( GFXTexHandle *faces ) = 0;
/// Create a static cubemap from a DDS cubemap file.
virtual void initStatic( DDSFile *dds ) = 0;
///
virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8 ) = 0;
void initNormalize(U32 size);
virtual ~GFXCubemap();
/// Returns the size of the faces.
virtual U32 getSize() const = 0;
/// Returns the face texture format.
virtual GFXFormat getFormat() const = 0;
/// Returns the cubemap file path set at creation.
const String& getPath() const { return mPath; }
// GFXResource interface
/// The resource should put a description of itself (number of vertices, size/width of texture, etc.) in buffer
virtual const String describeSelf() const;
};
/// A reference counted handle to a cubemap resource.
class GFXCubemapHandle : public StrongRefPtr<GFXCubemap>
{
public:
GFXCubemapHandle() {}
GFXCubemapHandle( GFXCubemap *cubemap ) { StrongRefPtr<GFXCubemap>::set( cubemap ); }
GFXCubemapHandle( const String &cubemapDDS ) { set( cubemapDDS ); }
/// Set a cubemap from a DDS cubemap texture file.
bool set( const String &cubemapDDS );
/// Releases the texture handle.
void free() { StrongObjectRef::set( NULL ); }
};
#endif // GFXCUBEMAP

View file

@ -0,0 +1,83 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXDEBUGEVENT_H_
#define _GFXDEBUGEVENT_H_
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
/// See TorqueConfig.h to enable this.
#ifdef TORQUE_ENABLE_GFXDEBUGEVENTS
/// You shouldn't use this class directly... use the
/// following macros:
///
/// GFXDEBUGEVENT_START / GFXDEBUGEVENT_END
/// GFXDEBUGEVENT_SCOPE
///
class GFXDebugEventScope
{
public:
GFXDebugEventScope( const char* name, const ColorI &color )
{
GFX->enterDebugEvent( color, name );
}
~GFXDebugEventScope()
{
GFX->leaveDebugEvent();
}
};
#define GFXDEBUGEVENT_START( name, color ) GFX->enterDebugEvent( color, #name )
#define GFXDEBUGEVENT_END() GFX->leaveDebugEvent()
#define GFXDEBUGEVENT_MARKER( name, color ) GFX->setDebugMarker( color, #name )
///
/// Will add start/end GFX debug events around the
/// current scope.
///
/// @param name The unquoted name for the event.
/// @param color A ColorI to associate with the event.
///
#define GFXDEBUGEVENT_SCOPE( name, color ) GFXDebugEventScope GFXDebugEventScope##name##Obj( #name, color )
#define GFXDEBUGEVENT_SCOPE_EX( name, color, desc ) GFXDebugEventScope GFXDebugEventScope##name##Obj( desc, color )
#else // !TORQUE_ENABLE_GFXDEBUGEVENTS
/// These are disabled in shipping builds or maybe you
/// forgot to include "platform/platform.h" first?
#define GFXDEBUGEVENT_START(n,c)
#define GFXDEBUGEVENT_END()
#define GFXDEBUGEVENT_MARKER(n,c)
#define GFXDEBUGEVENT_SCOPE(n,c)
#define GFXDEBUGEVENT_SCOPE_EX(n,c,d)
#endif
#endif // _GFXDEBUGEVENT_H_

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,74 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxDeviceStatistics.h"
#include "platform/platform.h"
#include "console/console.h"
GFXDeviceStatistics::GFXDeviceStatistics()
{
clear();
}
void GFXDeviceStatistics::setPrefix(const String& prefix)
{
// This is a bit silly, but we don't want to construct these
// strings every frame.
vnPolyCount = prefix + "polyCount";
vnDrawCalls = prefix + "drawCalls";
vnRenderTargetChanges = prefix + "renderTargetChanges";
}
/// Clear stats
void GFXDeviceStatistics::clear()
{
mPolyCount = 0;
mDrawCalls = 0;
mRenderTargetChanges = 0;
}
/// Copy from source (should just be a memcpy, but that may change later) used in
/// conjunction with end to get a subset of statistics. For example, statistics
/// for a particular render bin.
void GFXDeviceStatistics::start(GFXDeviceStatistics * source)
{
mPolyCount = source->mPolyCount;
mDrawCalls = source->mDrawCalls;
mRenderTargetChanges = source->mRenderTargetChanges;
}
/// Used with start to get a subset of stats on a device. Basically will do
/// this->mPolyCount = source->mPolyCount - this->mPolyCount. (Fancy!)
void GFXDeviceStatistics::end(GFXDeviceStatistics * source)
{
mPolyCount = source->mPolyCount - mPolyCount;
mDrawCalls = source->mDrawCalls - mDrawCalls;
mRenderTargetChanges = source->mRenderTargetChanges - mRenderTargetChanges;
}
/// Exports the stats to the console
void GFXDeviceStatistics::exportToConsole()
{
Con::setIntVariable(vnPolyCount, mPolyCount);
Con::setIntVariable(vnDrawCalls, mDrawCalls);
Con::setIntVariable(vnRenderTargetChanges, mRenderTargetChanges);
}

View file

@ -0,0 +1,62 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXDEVICESTATISTICS_H_
#define _GFXDEVICESTATISTICS_H_
#ifndef _TORQUE_STRING_H_
#include "core/util/str.h"
#endif
// A class that hold a simple set of device stats.
class GFXDeviceStatistics
{
public:
// Actual stats
S32 mPolyCount;
S32 mDrawCalls;
S32 mRenderTargetChanges;
GFXDeviceStatistics();
void setPrefix(const String& prefix);
/// Clear stats
void clear();
/// Copy from source (should just be a memcpy, but that may change later) used in
/// conjunction with end to get a subset of statistics. For example, statistics
/// for a particular render bin.
void start(GFXDeviceStatistics * source);
/// Used with start to get a subset of stats on a device. Basically will do
/// this->mPolyCount = source->mPolyCount - this->mPolyCount. (Fancy!)
void end(GFXDeviceStatistics * source);
/// Exports the stats to the console
void exportToConsole();
private:
String vnPolyCount;
String vnDrawCalls;
String vnRenderTargetChanges;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,181 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFX_GFXDRAWER_H_
#define _GFX_GFXDRAWER_H_
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
#ifndef _MPOLYHEDRON_H_
#include "math/mPolyhedron.h"
#endif
class FontRenderBatcher;
class Frustum;
/// Helper class containing utility functions for useful drawing routines
/// (line, box, rect, billboard, text).
class GFXDrawUtil
{
public:
GFXDrawUtil(GFXDevice *);
~GFXDrawUtil();
//-----------------------------------------------------------------------------
// Draw Rectangles
//-----------------------------------------------------------------------------
void drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color );
void drawRect( const RectF &rect, const ColorI &color );
void drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color );
void drawRect( const RectI &rect, const ColorI &color );
void drawRectFill( const Point2F &upperL, const Point2F &lowerR, const ColorI &color );
void drawRectFill( const RectF &rect, const ColorI &color );
void drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color );
void drawRectFill( const RectI &rect, const ColorI &color );
void draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle );
//-----------------------------------------------------------------------------
// Draw Lines
//-----------------------------------------------------------------------------
void drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color );
void drawLine( const Point2F &startPt, const Point2F &endPt, const ColorI &color );
void drawLine( const Point2I &startPt, const Point2I &endPt, const ColorI &color );
void drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color );
void drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color );
//-----------------------------------------------------------------------------
// Draw Text
//-----------------------------------------------------------------------------
U32 drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawTextN( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, U32 n, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, U32 n, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawText( GFont *font, const Point2F &ptDraw, const UTF8 *in_string, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawTextN( GFont *font, const Point2F &ptDraw, const UTF8 *in_string, U32 n, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawText( GFont *font, const Point2F &ptDraw, const UTF16 *in_string, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
U32 drawTextN( GFont *font, const Point2F &ptDraw, const UTF16 *in_string, U32 n, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9, F32 rot = 0.f );
//-----------------------------------------------------------------------------
// Color Modulation
//-----------------------------------------------------------------------------
void setBitmapModulation( const ColorI &modColor );
void setTextAnchorColor( const ColorI &ancColor );
void clearBitmapModulation();
void getBitmapModulation( ColorI *color );
//-----------------------------------------------------------------------------
// Draw Bitmaps
//-----------------------------------------------------------------------------
void drawBitmap( GFXTextureObject*texture, const Point2F &in_rAt, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmapSR( GFXTextureObject*texture, const Point2F &in_rAt, const RectF &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmapStretch( GFXTextureObject*texture, const RectF &dstRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmapStretchSR( GFXTextureObject*texture, const RectF &dstRect, const RectF &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmap( GFXTextureObject*texture, const Point2I &in_rAt, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmapSR( GFXTextureObject*texture, const Point2I &in_rAt, const RectI &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmapStretch( GFXTextureObject*texture, const RectI &dstRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
void drawBitmapStretchSR( GFXTextureObject*texture, const RectI &dstRect, const RectI &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true );
//-----------------------------------------------------------------------------
// Draw 3D Shapes
//-----------------------------------------------------------------------------
void drawTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm = NULL );
void drawPolygon( const GFXStateBlockDesc& desc, const Point3F* points, U32 numPoints, const ColorI& color, const MatrixF* xfm = NULL );
void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL );
void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL );
void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color );
void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL );
void drawCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm = NULL );
void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color );
void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color );
void drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color );
void drawFrustum( const Frustum& f, const ColorI &color );
/// Draw a solid or wireframe (depending on fill mode of @a desc) polyhedron with the given color.
///
/// @param desc Render state description.
/// @param poly Polyhedron.
/// @param color Color.
/// @param xfm Optional matrix to transform all vertices of the given polyhedron by.
void drawPolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm = NULL );
/// Draws a solid XY plane centered on the point with the specified dimensions.
void drawSolidPlane( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const ColorI &color );
enum Plane
{
PlaneXY,
PlaneXZ,
PlaneYZ
};
/// Draws a grid on XY, XZ, or YZ plane centered on the point with the specified size and step size.
void drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const Point2F &step, const ColorI &color, Plane plane = PlaneXY );
/// Draws axis lines representing the passed matrix.
/// If scale is NULL axes will be drawn the length they exist within the MatrixF.
/// If colors is NULL the default colors are RED, GREEEN, BLUE ( x, y, z ).
void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL );
protected:
void _setupStateBlocks();
void _drawWireTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm = NULL );
void _drawSolidTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm = NULL );
void _drawWireCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL );
void _drawSolidCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL );
void _drawWireCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm = NULL );
void _drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm = NULL );
void _drawWirePolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm = NULL );
void _drawSolidPolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm = NULL );
protected:
/// The device we're rendering to.
GFXDevice *mDevice;
/// Bitmap modulation color; bitmaps are multiplied by this color when
/// drawn.
GFXVertexColor mBitmapModulation;
/// Base text color; what color text is drawn at when no other color is
/// specified.
GFXVertexColor mTextAnchorColor;
GFXStateBlockRef mBitmapStretchSB;
GFXStateBlockRef mBitmapStretchLinearSB;
GFXStateBlockRef mBitmapStretchWrapSB;
GFXStateBlockRef mBitmapStretchWrapLinearSB;
GFXStateBlockRef mRectFillSB;
FontRenderBatcher* mFontRenderBatcher;
};
#endif // _GFX_GFXDRAWER_H_

View file

@ -0,0 +1,624 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXENUMS_H_
#define _GFXENUMS_H_
#include "core/util/fourcc.h"
// These are for the enum translation. It will help with porting to other platforms
// and API's.
#define GFX_UNSUPPORTED_VAL 0xDEADBEEF
#define GFX_UNINIT_VAL 0xDECAFBAD
// Adjust these pools to your app's needs. Be aware dynamic vertices are much more
// expensive than static vertices. These are in gfxEnums because they should be
// consistant across all APIs/platforms so that the dynamic buffer performance
// and behavior is also consistant. -patw
#define MAX_DYNAMIC_VERTS (8192*2)
#define MAX_DYNAMIC_INDICES (8192*4)
enum GFXBufferType
{
GFXBufferTypeStatic, ///< Static vertex buffers are created and filled one time.
///< incur a performance penalty. Resizing a static vertex buffer is not
///< allowed.
GFXBufferTypeDynamic, ///< Dynamic vertex buffers are meant for vertices that can be changed
///< often. Vertices written into dynamic vertex buffers will remain valid
///< until the dynamic vertex buffer is released. Resizing a dynamic vertex buffer is not
///< allowed.
GFXBufferTypeVolatile, ///< Volatile vertex or index buffers are meant for vertices or indices that are essentially
///< only used once. They can be resized without any performance penalty.
GFXBufferType_COUNT ///< Number of buffer types.
};
enum GFXTexCallbackCode
{
GFXZombify,
GFXResurrect,
};
enum GFXPrimitiveType
{
GFXPT_FIRST = 0,
GFXPointList = 0,
GFXLineList,
GFXLineStrip,
GFXTriangleList,
GFXTriangleStrip,
GFXTriangleFan,
GFXPT_COUNT
};
enum GFXTextureType
{
GFXTextureType_Normal,
GFXTextureType_KeepBitmap,
GFXTextureType_Dynamic,
GFXTextureType_RenderTarget,
GFXTextureType_Count
};
enum GFXBitmapFlip
{
GFXBitmapFlip_None = 0,
GFXBitmapFlip_X = 1 << 0,
GFXBitmapFlip_Y = 1 << 1,
GFXBitmapFlip_XY = GFXBitmapFlip_X | GFXBitmapFlip_Y
};
enum GFXTextureOp
{
GFXTOP_FIRST = 0,
GFXTOPDisable = 0,
GFXTOPSelectARG1,
GFXTOPSelectARG2,
GFXTOPModulate,
GFXTOPModulate2X,
GFXTOPModulate4X,
GFXTOPAdd,
GFXTOPAddSigned,
GFXTOPAddSigned2X,
GFXTOPSubtract,
GFXTOPAddSmooth,
GFXTOPBlendDiffuseAlpha,
GFXTOPBlendTextureAlpha,
GFXTOPBlendFactorAlpha,
GFXTOPBlendTextureAlphaPM,
GFXTOPBlendCURRENTALPHA,
GFXTOPPreModulate,
GFXTOPModulateAlphaAddColor,
GFXTOPModulateColorAddAlpha,
GFXTOPModulateInvAlphaAddColor,
GFXTOPModulateInvColorAddAlpha,
GFXTOPBumpEnvMap,
GFXTOPBumpEnvMapLuminance,
GFXTOPDotProduct3,
GFXTOPLERP,
GFXTOP_COUNT
};
enum GFXTextureAddressMode
{
GFXAddress_FIRST = 0,
GFXAddressWrap = 0,
GFXAddressMirror,
GFXAddressClamp,
GFXAddressBorder,
GFXAddressMirrorOnce,
GFXAddress_COUNT
};
enum GFXTextureFilterType
{
GFXTextureFilter_FIRST = 0,
GFXTextureFilterNone = 0,
GFXTextureFilterPoint,
GFXTextureFilterLinear,
GFXTextureFilterAnisotropic,
GFXTextureFilterPyramidalQuad,
GFXTextureFilterGaussianQuad,
GFXTextureFilter_COUNT
};
enum GFXFillMode
{
GFXFill_FIRST = 1,
GFXFillPoint = 1,
GFXFillWireframe,
GFXFillSolid,
GFXFill_COUNT
};
enum GFXFormat
{
// when adding formats make sure to place
// them in the correct group!
//
// if displacing the first entry in the group
// make sure to update the GFXFormat_xBIT entries!
//
GFXFormat_FIRST = 0,
// 8 bit texture formats...
GFXFormatA8 = 0,// first in group...
GFXFormatL8,
GFXFormatA4L4,
// 16 bit texture formats...
GFXFormatR5G6B5,// first in group...
GFXFormatR5G5B5A1,
GFXFormatR5G5B5X1,
GFXFormatA8L8,
GFXFormatL16,
GFXFormatR16F,
GFXFormatD16,
// 24 bit texture formats...
GFXFormatR8G8B8,// first in group...
// 32 bit texture formats...
GFXFormatR8G8B8A8,// first in group...
GFXFormatR8G8B8X8,
GFXFormatR32F,
GFXFormatR16G16,
GFXFormatR16G16F,
GFXFormatR10G10B10A2,
GFXFormatD32,
GFXFormatD24X8,
GFXFormatD24S8,
GFXFormatD24FS8,
// 64 bit texture formats...
GFXFormatR16G16B16A16,// first in group...
GFXFormatR16G16B16A16F,
// 128 bit texture formats...
GFXFormatR32G32B32A32F,// first in group...
// unknown size...
GFXFormatDXT1,// first in group...
GFXFormatDXT2,
GFXFormatDXT3,
GFXFormatDXT4,
GFXFormatDXT5,
GFXFormat_COUNT,
GFXFormat_8BIT = GFXFormatA8,
GFXFormat_16BIT = GFXFormatR5G6B5,
GFXFormat_24BIT = GFXFormatR8G8B8,
GFXFormat_32BIT = GFXFormatR8G8B8A8,
GFXFormat_64BIT = GFXFormatR16G16B16A16,
GFXFormat_128BIT = GFXFormatR32G32B32A32F,
GFXFormat_UNKNOWNSIZE = GFXFormatDXT1,
};
/// Returns the byte size of the pixel for non-compressed formats.
inline U32 GFXFormat_getByteSize( GFXFormat format )
{
AssertFatal( format < GFXFormat_UNKNOWNSIZE,
"GFXDevice::formatByteSize - Cannot size a compressed format!" );
if ( format < GFXFormat_16BIT )
return 1;// 8 bit...
else if ( format < GFXFormat_24BIT )
return 2;// 16 bit...
else if ( format < GFXFormat_32BIT )
return 3;// 24 bit...
else if ( format < GFXFormat_64BIT )
return 4;// 32 bit...
else if ( format < GFXFormat_128BIT )
return 8;// 64 bit...
// This should be 128bits... else its a DDS and
// the assert should have gone off above.
return 16;
}
enum GFXShadeMode
{
GFXShadeFlat = 1,
GFXShadeGouraud,
GFXShadePhong,
};
enum GFXClearFlags
{
GFXClearTarget = 1 << 0,
GFXClearZBuffer = 1 << 1,
GFXClearStencil = 1 << 2,
};
/// The supported blend modes.
enum GFXBlend
{
GFXBlend_FIRST = 0,
GFXBlendZero = 0, /// (0, 0, 0, 0)
GFXBlendOne, /// (1, 1, 1, 1)
GFXBlendSrcColor, /// (Rs, Gs, Bs, As)
GFXBlendInvSrcColor, /// (1 - Rs, 1 - Gs, 1 - Bs, 1 - As)
GFXBlendSrcAlpha, /// (As, As, As, As)
GFXBlendInvSrcAlpha, /// ( 1 - As, 1 - As, 1 - As, 1 - As)
GFXBlendDestAlpha, /// (Ad Ad Ad Ad)
GFXBlendInvDestAlpha, /// (1 - Ad 1 - Ad 1 - Ad 1 - Ad)
GFXBlendDestColor, /// (Rd, Gd, Bd, Ad)
GFXBlendInvDestColor, /// (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad)
GFXBlendSrcAlphaSat, /// (f, f, f, 1) where f = min(As, 1 - Ad)
GFXBlend_COUNT
};
/// Constants that name each GFXDevice type. Any new GFXDevice subclass must be
/// added to this enum. A string representing its name must also be added to
/// GFXInit::getAdapterNameFromType().
enum GFXAdapterType
{
OpenGL = 0,
Direct3D9,
Direct3D8,
NullDevice,
Direct3D9_360,
GFXAdapterType_Count
};
enum GFXCullMode
{
GFXCull_FIRST = 0,
GFXCullNone = 0,
GFXCullCW,
GFXCullCCW,
GFXCull_COUNT
};
enum GFXCmpFunc
{
GFXCmp_FIRST = 0,
GFXCmpNever = 0,
GFXCmpLess,
GFXCmpEqual,
GFXCmpLessEqual,
GFXCmpGreater,
GFXCmpNotEqual,
GFXCmpGreaterEqual,
GFXCmpAlways,
GFXCmp_COUNT
};
enum GFXStencilOp
{
GFXStencilOp_FIRST = 0,
GFXStencilOpKeep = 0,
GFXStencilOpZero,
GFXStencilOpReplace,
GFXStencilOpIncrSat,
GFXStencilOpDecrSat,
GFXStencilOpInvert,
GFXStencilOpIncr,
GFXStencilOpDecr,
GFXStencilOp_COUNT
};
enum GFXMaterialColorSource
{
GFXMCSMaterial = 0,
GFXMCSColor1,
GFXMCSColor2,
};
enum GFXBlendOp
{
GFXBlendOp_FIRST = 0,
GFXBlendOpAdd = 0,
GFXBlendOpSubtract,
GFXBlendOpRevSubtract,
GFXBlendOpMin,
GFXBlendOpMax,
GFXBlendOp_COUNT
};
enum GFXRenderState
{
GFXRenderState_FIRST = 0,
GFXRSZEnable = 0,
GFXRSFillMode,
GFXRSShadeMode,
GFXRSZWriteEnable,
GFXRSAlphaTestEnable,
GFXRSLastPixel,
GFXRSSrcBlend,
GFXRSDestBlend,
GFXRSCullMode,
GFXRSZFunc,
GFXRSAlphaRef,
GFXRSAlphaFunc,
GFXRSDitherEnable,
GFXRSAlphaBlendEnable,
GFXRSFogEnable,
GFXRSSpecularEnable,
GFXRSFogColor,
GFXRSFogTableMode,
GFXRSFogStart,
GFXRSFogEnd,
GFXRSFogDensity,
GFXRSRangeFogEnable,
GFXRSStencilEnable,
GFXRSStencilFail,
GFXRSStencilZFail,
GFXRSStencilPass,
GFXRSStencilFunc,
GFXRSStencilRef,
GFXRSStencilMask,
GFXRSStencilWriteMask,
GFXRSTextureFactor,
GFXRSWrap0,
GFXRSWrap1,
GFXRSWrap2,
GFXRSWrap3,
GFXRSWrap4,
GFXRSWrap5,
GFXRSWrap6,
GFXRSWrap7,
GFXRSClipping,
GFXRSLighting,
GFXRSAmbient,
GFXRSFogVertexMode,
GFXRSColorVertex,
GFXRSLocalViewer,
GFXRSNormalizeNormals,
GFXRSDiffuseMaterialSource,
GFXRSSpecularMaterialSource,
GFXRSAmbientMaterialSource,
GFXRSEmissiveMaterialSource,
GFXRSVertexBlend,
GFXRSClipPlaneEnable,
GFXRSPointSize,
GFXRSPointSizeMin,
GFXRSPointSpriteEnable,
GFXRSPointScaleEnable,
GFXRSPointScale_A,
GFXRSPointScale_B,
GFXRSPointScale_C,
GFXRSMultiSampleantiAlias,
GFXRSMultiSampleMask,
GFXRSPatchEdgeStyle,
GFXRSDebugMonitorToken,
GFXRSPointSize_Max,
GFXRSIndexedVertexBlendEnable,
GFXRSColorWriteEnable,
GFXRSTweenFactor,
GFXRSBlendOp,
GFXRSPositionDegree,
GFXRSNormalDegree,
GFXRSScissorTestEnable,
GFXRSSlopeScaleDepthBias,
GFXRSAntiAliasedLineEnable,
GFXRSMinTessellationLevel,
GFXRSMaxTessellationLevel,
GFXRSAdaptiveTess_X,
GFXRSAdaptiveTess_Y,
GFXRSdaptiveTess_Z,
GFXRSAdaptiveTess_W,
GFXRSEnableAdaptiveTesselation,
GFXRSTwoSidedStencilMode,
GFXRSCCWStencilFail,
GFXRSCCWStencilZFail,
GFXRSCCWStencilPass,
GFXRSCCWStencilFunc,
GFXRSColorWriteEnable1,
GFXRSColorWriteEnable2,
GFXRSolorWriteEnable3,
GFXRSBlendFactor,
GFXRSSRGBWriteEnable,
GFXRSDepthBias,
GFXRSWrap8,
GFXRSWrap9,
GFXRSWrap10,
GFXRSWrap11,
GFXRSWrap12,
GFXRSWrap13,
GFXRSWrap14,
GFXRSWrap15,
GFXRSSeparateAlphaBlendEnable,
GFXRSSrcBlendAlpha,
GFXRSDestBlendAlpha,
GFXRSBlendOpAlpha,
GFXRenderState_COUNT ///< Don't use this one, this is a counter
};
#define GFXCOLORWRITEENABLE_RED 1
#define GFXCOLORWRITEENABLE_GREEN 2
#define GFXCOLORWRITEENABLE_BLUE 4
#define GFXCOLORWRITEENABLE_ALPHA 8
enum GFXTextureStageState
{
GFXTSS_FIRST = 0,
GFXTSSColorOp = 0,
GFXTSSColorArg1,
GFXTSSColorArg2,
GFXTSSAlphaOp,
GFXTSSAlphaArg1,
GFXTSSAlphaArg2,
GFXTSSBumpEnvMat00,
GFXTSSBumpEnvMat01,
GFXTSSBumpEnvMat10,
GFXTSSBumpEnvMat11,
GFXTSSTexCoordIndex,
GFXTSSBumpEnvlScale,
GFXTSSBumpEnvlOffset,
GFXTSSTextureTransformFlags,
GFXTSSColorArg0,
GFXTSSAlphaArg0,
GFXTSSResultArg,
GFXTSSConstant,
GFXTSS_COUNT ///< Don't use this one, this is a counter
};
enum GFXTextureTransformFlags
{
GFXTTFFDisable = 0,
GFXTTFFCoord1D = 1,
GFXTTFFCoord2D = 2,
GFXTTFFCoord3D = 3,
GFXTTFFCoord4D = 4,
GFXTTFFProjected = 256,
};
// CodeReview: This number is used for the declaration of variables, but it
// should *not* be used for any run-time purposes [7/2/2007 Pat]
#define TEXTURE_STAGE_COUNT 16
enum GFXSamplerState
{
GFXSAMP_FIRST = 0,
GFXSAMPAddressU = 0,
GFXSAMPAddressV,
GFXSAMPAddressW,
GFXSAMPBorderColor,
GFXSAMPMagFilter,
GFXSAMPMinFilter,
GFXSAMPMipFilter,
GFXSAMPMipMapLODBias,
GFXSAMPMaxMipLevel,
GFXSAMPMaxAnisotropy,
GFXSAMPSRGBTexture,
GFXSAMPElementIndex,
GFXSAMPDMapOffset,
GFXSAMP_COUNT ///< Don't use this one, this is a counter
};
enum GFXTextureArgument
{
GFXTA_FIRST = 0,
GFXTADiffuse = 0,
GFXTACurrent,
GFXTATexture,
GFXTATFactor,
GFXTASpecular,
GFXTATemp,
GFXTAConstant,
GFXTA_COUNT,
GFXTAComplement = 0x00000010, // take 1.0 - x (read modifier)
GFXTAAlphaReplicate = 0x00000020, // replicate alpha to color components (read modifier)
};
// Matrix stuff
#define WORLD_STACK_MAX 24
enum GFXMatrixType
{
GFXMatrixWorld = 256,
GFXMatrixView = 2,
GFXMatrixProjection = 3,
GFXMatrixTexture = 16, // This value is texture matrix for sampler 0, can use this for offset
GFXMatrixTexture0 = 16,
GFXMatrixTexture1 = 17,
GFXMatrixTexture2 = 18,
GFXMatrixTexture3 = 19,
GFXMatrixTexture4 = 20,
GFXMatrixTexture5 = 21,
GFXMatrixTexture6 = 22,
GFXMatrixTexture7 = 23,
};
// Light define
#define LIGHT_STAGE_COUNT 8
#define GFXVERTEXFLAG_F32 3
#define GFXVERTEXFLAG_POINT2F 0
#define GFXVERTEXFLAG_POINT3F 1
#define GFXVERTEXFLAG_POINT4F 2
#define GFXVERTEXFLAG_TEXCOORD_F32(CoordIndex) ( GFXVERTEXFLAG_F32 << ( CoordIndex * 2 + 16 ) )
#define GFXVERTEXFLAG_TEXCOORD_POINT2F(CoordIndex) ( GFXVERTEXFLAG_POINT2F )
#define GFXVERTEXFLAG_TEXCOORD_POINT3F(CoordIndex) ( GFXVERTEXFLAG_POINT3F << ( CoordIndex * 2 + 16 ) )
#define GFXVERTEXFLAG_TEXCOORD_POINT4F(CoordIndex) ( GFXVERTEXFLAG_POINT4F << ( CoordIndex * 2 + 16 ) )
#define STATE_STACK_SIZE 32
// Index Formats
enum GFXIndexFormat
{
GFXIndexFormat_FIRST = 0,
GFXIndexFormat16 = 0,
GFXIndexFormat32,
GFXIndexFormat_COUNT
};
enum GFXShaderConstType
{
/// GFX"S"hader"C"onstant"T"ype
// Scalar
GFXSCT_Float,
// Vectors
GFXSCT_Float2,
GFXSCT_Float3,
GFXSCT_Float4,
// Matrices
GFXSCT_Float2x2,
GFXSCT_Float3x3,
GFXSCT_Float4x4,
// Scalar
GFXSCT_Int,
// Vectors
GFXSCT_Int2,
GFXSCT_Int3,
GFXSCT_Int4,
// Samplers
GFXSCT_Sampler,
GFXSCT_SamplerCube
};
/// Defines a vertex declaration type.
/// @see GFXVertexElement
/// @see GFXVertexFormat
enum GFXDeclType
{
GFXDeclType_FIRST = 0,
/// A single component F32.
GFXDeclType_Float = 0,
/// A two-component F32.
/// @see Point2F
GFXDeclType_Float2,
/// A three-component F32.
/// @see Point3F
GFXDeclType_Float3,
/// A four-component F32.
/// @see Point4F
GFXDeclType_Float4,
/// A four-component, packed, unsigned bytes mapped to 0 to 1 range.
/// @see GFXVertexColor
GFXDeclType_Color,
/// The count of total GFXDeclTypes.
GFXDeclType_COUNT,
};
#endif // _GFXENUMS_H_

View file

@ -0,0 +1,142 @@
//-----------------------------------------------------------------------------
// 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/gfxFence.h"
#include "gfx/primBuilder.h"
#include "gfx/gfxTextureManager.h"
GFXGeneralFence::~GFXGeneralFence()
{
// Release the ref pointers
mRenderTarget = NULL;
mRTTexHandle = NULL;
// Unregister texture callback
GFXTextureManager::removeEventDelegate( this, &GFXGeneralFence::_onTextureEvent );
}
//------------------------------------------------------------------------------
void GFXGeneralFence::_init()
{
// Register texture callback to re-create resources
if ( !mInitialized )
GFXTextureManager::addEventDelegate( this, &GFXGeneralFence::_onTextureEvent );
// Set this to true for error checking
mInitialized = true;
// Allocate resources
mInitialized &= mRTTexHandle.set( 2, 2, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile, avar("%s() - mInitialized (line %d)", __FUNCTION__, __LINE__) );
mRenderTarget = GFX->allocRenderToTextureTarget();
mInitialized &= ( mRenderTarget != NULL );
GFXStateBlockDesc d;
mRenderSB = GFX->createStateBlock(d);
}
//------------------------------------------------------------------------------
void GFXGeneralFence::issue()
{
PROFILE_SCOPE(GFXGeneralFence_Issue);
// Resource creation will be done on first call to issue()
if( !mInitialized )
_init();
// If we can't init, return.
if(!mInitialized)
return;
AssertFatal( mInitialized, "Error occured during GFXGeneralFence::_init, sorry I can't be more specific, break and debug." );
RectI viewport = GFX->getViewport();
GFX->pushActiveRenderTarget();
mRenderTarget->attachTexture( GFXTextureTarget::Color0, mRTTexHandle );
GFX->setActiveRenderTarget( mRenderTarget );
// Set-up states
GFX->setStateBlock(mRenderSB);
GFX->pushWorldMatrix();
GFX->setWorldMatrix( MatrixF::Identity );
// CodeReview: We can re-do this with a static vertex buffer at some point. [5/9/2007 Pat]
PrimBuild::begin( GFXTriangleList, 3 );
PrimBuild::vertex2f( 0.f, 0.f );
PrimBuild::vertex2f( 0.f, 1.f );
PrimBuild::vertex2f( 1.f, 0.f );
PrimBuild::end();
GFX->popWorldMatrix();
GFX->popActiveRenderTarget();
GFX->setViewport(viewport);
}
//------------------------------------------------------------------------------
void GFXGeneralFence::block()
{
PROFILE_SCOPE(GFXGeneralFence_block);
if( !mInitialized )
return;
// We have to deal with the case where the lock fails (usually due to
// a device reset).
if(mRTTexHandle.lock())
mRTTexHandle.unlock();
}
void GFXGeneralFence::_onTextureEvent( GFXTexCallbackCode code )
{
switch( code )
{
case GFXZombify:
mRTTexHandle = NULL;
break;
case GFXResurrect:
mRTTexHandle.set( 2, 2, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile, avar("%s() - GFXGeneralFence->mRTTexHandle (line %d)", __FUNCTION__, __LINE__) );
break;
}
}
void GFXGeneralFence::zombify()
{
mRTTexHandle = NULL;
}
void GFXGeneralFence::resurrect()
{
mRTTexHandle.set( 2, 2, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile, avar("%s() - mRTTexHandle (line %d)", __FUNCTION__, __LINE__) );
}
const String GFXGeneralFence::describeSelf() const
{
// We've got nothing
return String();
}

View file

@ -0,0 +1,105 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXFENCE_H_
#define _GFXFENCE_H_
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
///
class GFXFence : public GFXResource
{
protected:
GFXDevice *mDevice;
public:
/// The states returned by getStatus()
enum FenceStatus
{
Unset, ///< The fence has not been set
Pending, ///< The fence has been set and has not been hit
Processed, ///< The fence has been processed
Unsupported ///< A non-blocking query of fence status is not supported by the implementation
};
public:
GFXFence( GFXDevice *device ) : mDevice( device ) {};
virtual ~GFXFence(){};
/// This method inserts the fence into the command buffer
virtual void issue() = 0;
// CodeReview: Do we need a remove() [5/10/2007 Pat]
/// This is a non-blocking call to get the status of the fence
/// @see GFXFence::FenceStatus
virtual FenceStatus getStatus() const = 0;
/// This method will not return until the fence has been processed by the GPU
virtual void block() = 0;
};
///
class GFXGeneralFence : public GFXFence
{
protected:
bool mInitialized;
GFXTextureTargetRef mRenderTarget;
GFXTexHandle mRTTexHandle;
GFXStateBlockRef mRenderSB;
void _init();
/// The callback used to get texture events.
/// @see GFXTextureManager::addEventDelegate
void _onTextureEvent( GFXTexCallbackCode code );
public:
GFXGeneralFence( GFXDevice *device )
: GFXFence( device ),
mInitialized( false )
{
}
virtual ~GFXGeneralFence();
virtual void issue();
virtual FenceStatus getStatus() const { return GFXFence::Unsupported; };
virtual void block();
// GFXResource interface
virtual void zombify();
virtual void resurrect();
/// The resource should put a description of itself (number of vertices, size/width of texture, etc.) in buffer
virtual const String describeSelf() const;
};
#endif // _GFXFENCE_H_

View file

@ -0,0 +1,242 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxFontRenderBatcher.h"
#include "gfx/gFont.h"
FontRenderBatcher::FontRenderBatcher() : mStorage(8096)
{
if (!mFontSB)
{
GFXStateBlockDesc f;
f.zDefined = true;
f.zEnable = false;
f.zWriteEnable = false;
f.cullDefined = true;
f.cullMode = GFXCullNone;
f.blendDefined = true;
f.blendEnable = true;
f.blendSrc = GFXBlendSrcAlpha;
f.blendDest = GFXBlendInvSrcAlpha;
f.samplersDefined = true;
f.samplers[0].alphaOp = GFXTOPModulate;
f.samplers[0].magFilter = GFXTextureFilterPoint;
f.samplers[0].minFilter = GFXTextureFilterPoint;
f.samplers[0].addressModeU = GFXAddressClamp;
f.samplers[0].addressModeV = GFXAddressClamp;
f.samplers[0].alphaArg1 = GFXTATexture;
f.samplers[0].alphaArg2 = GFXTADiffuse;
// This is an add operation because in D3D, when a texture of format D3DFMT_A8
// is used, the RGB channels are all set to 0. Therefore a modulate would
// result in the text always being black. This may not be the case in OpenGL
// so it may have to change. -bramage
f.samplers[0].textureColorOp = GFXTOPAdd;
mFontSB = GFX->createStateBlock(f);
}
}
void FontRenderBatcher::render( F32 rot, const Point2F &offset )
{
if( mLength == 0 )
return;
GFX->setStateBlock(mFontSB);
GFX->disableShaders();
for(U32 i = 0; i < GFX->getNumSamplers(); i++)
GFX->setTexture(i, NULL);
MatrixF rotMatrix;
bool doRotation = rot != 0.f;
if(doRotation)
rotMatrix.set( EulerF( 0.0, 0.0, mDegToRad( rot ) ) );
// Write verts out.
U32 currentPt = 0;
GFXVertexBufferHandle<GFXVertexPCT> verts(GFX, mLength * 6, GFXBufferTypeVolatile);
verts.lock();
for( S32 i = 0; i < mSheets.size(); i++ )
{
// Do some early outs...
if(!mSheets[i])
continue;
if(!mSheets[i]->numChars)
continue;
mSheets[i]->startVertex = currentPt;
const GFXTextureObject *tex = mFont->getTextureHandle(i);
for( S32 j = 0; j < mSheets[i]->numChars; j++ )
{
// Get some general info to proceed with...
const CharMarker &m = mSheets[i]->charIndex[j];
const PlatformFont::CharInfo &ci = mFont->getCharInfo( m.c );
// Where are we drawing it?
F32 drawY = offset.y + mFont->getBaseline() - ci.yOrigin * TEXT_MAG;
F32 drawX = offset.x + m.x + ci.xOrigin;
// Figure some values.
const F32 texWidth = (F32)tex->getWidth();
const F32 texHeight = (F32)tex->getHeight();
const F32 texLeft = (F32)(ci.xOffset) / texWidth;
const F32 texRight = (F32)(ci.xOffset + ci.width) / texWidth;
const F32 texTop = (F32)(ci.yOffset) / texHeight;
const F32 texBottom = (F32)(ci.yOffset + ci.height) / texHeight;
const F32 fillConventionOffset = GFX->getFillConventionOffset();
const F32 screenLeft = drawX - fillConventionOffset;
const F32 screenRight = drawX - fillConventionOffset + ci.width * TEXT_MAG;
const F32 screenTop = drawY - fillConventionOffset;
const F32 screenBottom = drawY - fillConventionOffset + ci.height * TEXT_MAG;
// Build our vertices. We NEVER read back from the buffer, that's
// incredibly slow, so for rotation do it into tmp. This code is
// ugly as sin.
Point3F tmp;
tmp.set( screenLeft, screenTop, 0.f );
if(doRotation)
rotMatrix.mulP( tmp, &verts[currentPt].point);
else
verts[currentPt].point = tmp;
verts[currentPt].color = m.color;
verts[currentPt].texCoord.set( texLeft, texTop );
currentPt++;
tmp.set( screenLeft, screenBottom, 0.f );
if(doRotation)
rotMatrix.mulP( tmp, &verts[currentPt].point);
else
verts[currentPt].point = tmp;
verts[currentPt].color = m.color;
verts[currentPt].texCoord.set( texLeft, texBottom );
currentPt++;
tmp.set( screenRight, screenBottom, 0.f );
if(doRotation)
rotMatrix.mulP( tmp, &verts[currentPt].point);
else
verts[currentPt].point = tmp;
verts[currentPt].color = m.color;
verts[currentPt].texCoord.set( texRight, texBottom );
currentPt++;
tmp.set( screenRight, screenBottom, 0.f );
if(doRotation)
rotMatrix.mulP( tmp, &verts[currentPt].point);
else
verts[currentPt].point = tmp;
verts[currentPt].color = m.color;
verts[currentPt].texCoord.set( texRight, texBottom );
currentPt++;
tmp.set( screenRight, screenTop, 0.f );
if(doRotation)
rotMatrix.mulP( tmp, &verts[currentPt].point);
else
verts[currentPt].point = tmp;
verts[currentPt].color = m.color;
verts[currentPt].texCoord.set( texRight, texTop );
currentPt++;
tmp.set( screenLeft, screenTop, 0.f );
if(doRotation)
rotMatrix.mulP( tmp, &verts[currentPt].point);
else
verts[currentPt].point = tmp;
verts[currentPt].color = m.color;
verts[currentPt].texCoord.set( texLeft, texTop );
currentPt++;
}
}
verts->unlock();
AssertFatal(currentPt <= mLength * 6, "FontRenderBatcher::render - too many verts for length of string!");
GFX->setVertexBuffer(verts);
// Now do an optimal render!
for( S32 i = 0; i < mSheets.size(); i++ )
{
if(!mSheets[i])
continue;
if(!mSheets[i]->numChars )
continue;
GFX->setupGenericShaders( GFXDevice::GSAddColorTexture );
GFX->setTexture( 0, mFont->getTextureHandle(i) );
GFX->drawPrimitive(GFXTriangleList, mSheets[i]->startVertex, mSheets[i]->numChars * 2);
}
}
void FontRenderBatcher::queueChar( UTF16 c, S32 &currentX, GFXVertexColor &currentColor )
{
const PlatformFont::CharInfo &ci = mFont->getCharInfo( c );
U32 sidx = ci.bitmapIndex;
if( ci.width != 0 && ci.height != 0 )
{
SheetMarker &sm = getSheetMarker(sidx);
CharMarker &m = sm.charIndex[sm.numChars];
sm.numChars++;
m.c = c;
m.x = (F32)currentX;
m.color = currentColor;
}
currentX += ci.xIncrement;
}
FontRenderBatcher::SheetMarker & FontRenderBatcher::getSheetMarker( U32 sheetID )
{
// Allocate if it doesn't exist...
if(mSheets.size() <= sheetID || !mSheets[sheetID])
{
if(sheetID >= mSheets.size())
mSheets.setSize(sheetID+1);
S32 size = sizeof( SheetMarker) + mLength * sizeof( CharMarker );
mSheets[sheetID] = (SheetMarker *)mStorage.alloc(size);
mSheets[sheetID]->numChars = 0;
mSheets[sheetID]->startVertex = 0; // cosmetic initialization
}
return *mSheets[sheetID];
}
void FontRenderBatcher::init( GFont *font, U32 n )
{
// Clear out batched results
dMemset(mSheets.address(), 0, mSheets.memSize());
mSheets.clear();
mStorage.freeBlocks(true);
mFont = font;
mLength = n;
}

View file

@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXFONTBATCHER_H_
#define _GFXFONTBATCHER_H_
#include "core/dataChunker.h"
#include "gfx/gfxDevice.h"
#include "gfx/gFont.h"
#define TEXT_MAG 1
class FontRenderBatcher
{
struct CharMarker
{
S32 c;
F32 x;
GFXVertexColor color;
PlatformFont::CharInfo *ci;
};
struct SheetMarker
{
S32 numChars;
S32 startVertex;
CharMarker charIndex[1];
};
DataChunker mStorage;
Vector<SheetMarker *> mSheets;
GFont *mFont;
U32 mLength;
GFXStateBlockRef mFontSB;
SheetMarker &getSheetMarker(U32 sheetID);
public:
FontRenderBatcher();
void init(GFont *font, U32 n);
void queueChar(UTF16 c, S32 &currentX, GFXVertexColor &currentColor);
void render(F32 rot, const Point2F &offset );
};
#endif

View file

@ -0,0 +1,90 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxFormatUtils.h"
#include "gfx/gfxDevice.h"
//RDTODO: complete format infos
//-----------------------------------------------------------------------------
GFXFormatInfo::Data GFXFormatInfo::smFormatInfos[ GFXFormat_COUNT ] =
{
// 8 bit texture formats...
GFXFormatInfo::Data( 1, false, false, false ), // GFXFormatA8
GFXFormatInfo::Data( 1, false, false, false ), // GFXFormatL8
GFXFormatInfo::Data( 1, true, false, false ), // GFXFormatA4L4
// 16 bit texture formats...
GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatR5G6B5
GFXFormatInfo::Data( 2, true, false, false ), // GFXFormatR5G5B5A1
GFXFormatInfo::Data( 2, true, false, false ), // GFXFormatA8L8
GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatL16
GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatR16F
GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatD16
// 24 bit texture formats...
GFXFormatInfo::Data( 3, false, false, false ), // GFXFormatR8G8B8
// 32 bit texture formats...
GFXFormatInfo::Data( 4, true, false, false ), // GFXFormatR8G8B8A8
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatR8G8B8X8
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatR32F
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatR16G16
GFXFormatInfo::Data( 4, false, false, true ), // GFXFormatR16G16F
GFXFormatInfo::Data( 4, true, false, false ), // GFXFormatR10G10B10A2
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatD32
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatD24X8
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatD24S8
GFXFormatInfo::Data( 4, false, false, false ), // GFXFormatD24FS8
// 64 bit texture formats...
GFXFormatInfo::Data( 8, true, false, false ), // GFXFormatR16G16B16A16
GFXFormatInfo::Data( 8, true, false, true ), // GFXFormatR16G16B16A16F
// 128 bit texture formats...
GFXFormatInfo::Data( 16, true, false, true ), // GFXFormatR32G32B32A32F
// Compressed formats...
GFXFormatInfo::Data( 0, false, true, false ), // GFXFormatDXT1
GFXFormatInfo::Data( 0, true, true, false ), // GFXFormatDXT2
GFXFormatInfo::Data( 0, true, true, false ), // GFXFormatDXT3
GFXFormatInfo::Data( 0, true, true, false ), // GFXFormatDXT4
GFXFormatInfo::Data( 0, true, true, false ), // GFXFormatDXT5
};
//-----------------------------------------------------------------------------
void GFXCopyPixels( GFXFormat fromFormat, U32 fromWidth, U32 fromHeight, U8* fromData,
GFXFormat toFormat, U32 toWidth, U32 toHeight, U8* toData )
{
if( fromFormat == toFormat
&& fromWidth == toWidth
&& fromHeight == fromHeight )
dMemcpy( toData, fromData, fromWidth * fromHeight * GFXFormatInfo( fromFormat ).getBytesPerPixel() );
else
{
AssertFatal( false, "Not implemented" );
}
}

View file

@ -0,0 +1,143 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXFORMATUTILS_H_
#define _GFXFORMATUTILS_H_
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _COLOR_H_
#include "core/color.h"
#endif
//WIP: still in early stages
/// Some information about a GFXFormat.
struct GFXFormatInfo
{
protected:
struct Data
{
/// Bytes per single pixel.
U32 mBytesPerPixel;
/// If true, format has alpha channel.
bool mHasAlpha;
/// If true, format uses compression.
bool mIsCompressed;
/// If true, channels are in floating-point.
bool mIsFloatingPoint;
Data() {}
Data( U32 bpp, bool hasAlpha = false, bool isCompressed = false, bool isFP = false )
: mBytesPerPixel( bpp ),
mHasAlpha( hasAlpha ),
mIsCompressed( isCompressed ),
mIsFloatingPoint( isFP ) {}
};
GFXFormat mFormat;
static Data smFormatInfos[ GFXFormat_COUNT ];
public:
GFXFormatInfo( GFXFormat format )
: mFormat( format ) {}
/// @return the number of bytes per pixel in this format.
/// @note For compressed formats that can't give a fixed value per pixel,
/// this will be zero.
U32 getBytesPerPixel() const { return smFormatInfos[ mFormat ].mBytesPerPixel; }
/// @return true if the format has an alpha channel.
bool hasAlpha() const { return smFormatInfos[ mFormat ].mHasAlpha; }
/// @return true if format uses compression.
bool isCompressed() const { return smFormatInfos[ mFormat ].mIsCompressed; }
/// @return true if channels are stored in floating-point format.
bool isFloatingPoint() const { return smFormatInfos[ mFormat ].mIsFloatingPoint; }
};
#if 0
///
extern void GFXCopyPixels( GFXFormat fromFormat, U32 fromWidth, U32 fromHeight, U8* fromData,
GFXFormat toFormat, U32 toWidth, U32 toHeight, U8* toData );
#endif
inline void GFXPackPixel( GFXFormat format, U8*& ptr, U8 red, U8 green, U8 blue, U8 alpha, bool leastSignficantFirst = true )
{
switch( format )
{
case GFXFormatR8G8B8A8:
if( leastSignficantFirst )
{
ptr[ 0 ] = blue;
ptr[ 1 ] = green;
ptr[ 2 ] = red;
ptr[ 3 ] = alpha;
}
else
{
ptr[ 0 ] = red;
ptr[ 1 ] = green;
ptr[ 2 ] = blue;
ptr[ 3 ] = alpha;
}
ptr += 4;
break;
case GFXFormatR8G8B8:
if( leastSignficantFirst )
{
ptr[ 0 ] = blue;
ptr[ 1 ] = green;
ptr[ 2 ] = red;
}
else
{
ptr[ 0 ] = red;
ptr[ 1 ] = green;
ptr[ 2 ] = blue;
}
ptr += 3;
break;
default:
AssertISV( false, "GFXPackPixel() - pixel format not implemented." );
}
}
#endif // _GFXFORMATUTILS_H_

View file

@ -0,0 +1,499 @@
//-----------------------------------------------------------------------------
// 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/gfxInit.h"
#include "gfx/gfxTextureManager.h"
#include "gfx/gfxAPI.h"
#include "console/console.h"
#include "windowManager/platformWindowMgr.h"
#include "core/module.h"
Vector<GFXAdapter*> GFXInit::smAdapters( __FILE__, __LINE__ );
GFXInit::RegisterDeviceSignal* GFXInit::smRegisterDeviceSignal;
MODULE_BEGIN( GFX )
MODULE_INIT
{
GFXInit::init();
if( engineAPI::gUseConsoleInterop )
GFXDevice::initConsole();
GFXTextureManager::init();
}
MODULE_SHUTDOWN
{
GFXDevice::destroy();
GFXInit::cleanup();
}
MODULE_END;
IMPLEMENT_STATIC_CLASS( GFXInit, GFXAPI,
"Functions for tracking GFX adapters and initializing them into devices."
);
ConsoleDoc(
"@class GFXInit\n"
"@ingroup GFX\n"
"@brief Functions for tracking GFX adapters and initializing them into devices.\n"
);
inline static void _GFXInitReportAdapters(Vector<GFXAdapter*> &adapters)
{
for (U32 i = 0; i < adapters.size(); i++)
{
switch (adapters[i]->mType)
{
case Direct3D9:
Con::printf(" Direct 3D (version 9.x) device found");
break;
case OpenGL:
Con::printf(" OpenGL device found");
break;
case NullDevice:
Con::printf(" Null device found");
break;
case Direct3D8:
Con::printf(" Direct 3D (version 8.1) device found");
break;
default :
Con::printf(" Unknown device found");
break;
}
}
}
inline static void _GFXInitGetInitialRes(GFXVideoMode &vm, const Point2I &initialSize)
{
const U32 kDefaultWindowSizeX = 800;
const U32 kDefaultWindowSizeY = 600;
const bool kDefaultFullscreen = false;
const U32 kDefaultBitDepth = 32;
const U32 kDefaultRefreshRate = 60;
// cache the desktop size of the main screen
GFXVideoMode desktopVm = GFXInit::getDesktopResolution();
// load pref variables, properly choose windowed / fullscreen
const String resString = Con::getVariable("$pref::Video::mode");
// Set defaults into the video mode, then have it parse the user string.
vm.resolution.x = kDefaultWindowSizeX;
vm.resolution.y = kDefaultWindowSizeY;
vm.fullScreen = kDefaultFullscreen;
vm.bitDepth = kDefaultBitDepth;
vm.refreshRate = kDefaultRefreshRate;
vm.wideScreen = false;
vm.parseFromString(resString);
}
GFXInit::RegisterDeviceSignal& GFXInit::getRegisterDeviceSignal()
{
if (smRegisterDeviceSignal)
return *smRegisterDeviceSignal;
smRegisterDeviceSignal = new RegisterDeviceSignal();
return *smRegisterDeviceSignal;
}
void GFXInit::init()
{
// init only once.
static bool doneOnce = false;
if(doneOnce)
return;
doneOnce = true;
Con::printf( "GFX Init:" );
//find our adapters
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::enumerateAdapters();
GFXInit::getAdapters(&adapters);
if(!adapters.size())
Con::errorf("Could not find a display adapter");
//loop through and tell the user what kind of adapters we found
_GFXInitReportAdapters(adapters);
Con::printf( "" );
}
void GFXInit::cleanup()
{
while( smAdapters.size() )
{
GFXAdapter* adapter = smAdapters.last();
smAdapters.decrement();
delete adapter;
}
if( smRegisterDeviceSignal )
SAFE_DELETE( smRegisterDeviceSignal );
}
GFXAdapter* GFXInit::getAdapterOfType( GFXAdapterType type )
{
GFXAdapter* adapter = NULL;
for( U32 i = 0; i < smAdapters.size(); i++ )
{
if( smAdapters[i]->mType == type )
{
adapter = smAdapters[i];
break;
}
}
return adapter;
}
GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type)
{
GFXAdapter* adapter = GFXInit::getAdapterOfType(type);
if(!adapter && type != OpenGL)
{
Con::errorf("The requested renderer, %s, doesn't seem to be available."
" Trying the default, OpenGL.", getAdapterNameFromType(type));
adapter = GFXInit::getAdapterOfType(OpenGL);
}
if(!adapter)
{
Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice.");
adapter = GFXInit::getAdapterOfType(NullDevice);
}
AssertFatal( adapter, "There is no rendering device available whatsoever.");
return adapter;
}
const char* GFXInit::getAdapterNameFromType(GFXAdapterType type)
{
static const char* _names[] = { "OpenGL", "D3D9", "D3D8", "NullDevice", "Xenon" };
if( type < 0 || type >= GFXAdapterType_Count )
{
Con::errorf( "GFXInit::getAdapterNameFromType - Invalid renderer type, defaulting to OpenGL" );
return _names[OpenGL];
}
return _names[type];
}
GFXAdapterType GFXInit::getAdapterTypeFromName(const char* name)
{
S32 ret = -1;
for(S32 i = 0; i < GFXAdapterType_Count; i++)
{
if( !dStricmp( getAdapterNameFromType((GFXAdapterType)i), name ) )
ret = i;
}
if( ret == -1 )
{
Con::errorf( "GFXInit::getAdapterTypeFromName - Invalid renderer name, defaulting to D3D9" );
ret = Direct3D9;
}
return (GFXAdapterType)ret;
}
GFXAdapter *GFXInit::getBestAdapterChoice()
{
// Get the user's preference for device...
const String renderer = Con::getVariable("$pref::Video::displayDevice");
GFXAdapterType adapterType = getAdapterTypeFromName(renderer);
GFXAdapter *adapter = chooseAdapter(adapterType);
// Did they have one? Return it.
if(adapter)
return adapter;
// Didn't have one. So make it up. Find the highest SM available. Prefer
// D3D to GL because if we have a D3D device at all we're on windows,
// and in an unknown situation on Windows D3D is probably the safest bet.
//
// If D3D is unavailable, we're not on windows, so GL is de facto the
// best choice!
F32 highestSM9 = 0.f, highestSMGL = 0.f;
GFXAdapter *foundAdapter8 = NULL, *foundAdapter9 = NULL,
*foundAdapterGL = NULL;
for(S32 i=0; i<smAdapters.size(); i++)
{
GFXAdapter *currAdapter = smAdapters[i];
switch(currAdapter->mType)
{
case Direct3D9:
if(currAdapter->mShaderModel > highestSM9)
{
highestSM9 = currAdapter->mShaderModel;
foundAdapter9 = currAdapter;
}
break;
case OpenGL:
if(currAdapter->mShaderModel > highestSMGL)
{
highestSMGL = currAdapter->mShaderModel;
foundAdapterGL = currAdapter;
}
break;
case Direct3D8:
if(!foundAdapter8)
foundAdapter8 = currAdapter;
break;
default:
break;
}
}
// Return best found in order DX9, GL, DX8.
if(foundAdapter9)
return foundAdapter9;
if(foundAdapterGL)
return foundAdapterGL;
if(foundAdapter8)
return foundAdapter8;
// Uh oh - we didn't find anything. Grab whatever we can that's not Null...
for(S32 i=0; i<smAdapters.size(); i++)
if(smAdapters[i]->mType != NullDevice)
return smAdapters[i];
// Dare we return a null device? No. Just return NULL.
return NULL;
}
GFXVideoMode GFXInit::getInitialVideoMode()
{
GFXVideoMode vm;
_GFXInitGetInitialRes(vm, Point2I(800,600));
return vm;
}
S32 GFXInit::getAdapterCount()
{
return smAdapters.size();
}
void GFXInit::getAdapters(Vector<GFXAdapter*> *adapters)
{
adapters->clear();
for (U32 k = 0; k < smAdapters.size(); k++)
adapters->push_back(smAdapters[k]);
}
GFXVideoMode GFXInit::getDesktopResolution()
{
GFXVideoMode resVm;
// Retrieve Resolution Information.
resVm.bitDepth = WindowManager->getDesktopBitDepth();
resVm.resolution = WindowManager->getDesktopResolution();
resVm.fullScreen = false;
resVm.refreshRate = 60;
// Return results
return resVm;
}
void GFXInit::enumerateAdapters()
{
// Call each device class and have it report any adapters it supports.
if(smAdapters.size())
{
// CodeReview Seems like this is ok to just ignore? [bjg, 5/19/07]
//Con::warnf("GFXInit::enumerateAdapters - already have a populated adapter list, aborting re-analysis.");
return;
}
getRegisterDeviceSignal().trigger(GFXInit::smAdapters);
}
GFXDevice *GFXInit::createDevice( GFXAdapter *adapter )
{
Con::printf("Attempting to create GFX device: %s", adapter->getName());
GFXDevice* temp = adapter->mCreateDeviceInstanceDelegate(adapter->mIndex);
if (temp)
{
Con::printf("Device created, setting adapter and enumerating modes");
temp->setAdapter(*adapter);
temp->enumerateVideoModes();
temp->getVideoModeList();
}
else
Con::errorf("Failed to create GFX device");
GFXDevice::getDeviceEventSignal().trigger(GFXDevice::deCreate);
return temp;
}
DefineEngineFunction( getDesktopResolution, Point3F, (),,
"Returns the width, height, and bitdepth of the screen/desktop.\n\n@ingroup GFX" )
{
GFXVideoMode res = GFXInit::getDesktopResolution();
return Point3F( res.resolution.x, res.resolution.y, res.bitDepth );
}
DefineEngineStaticMethod( GFXInit, getAdapterCount, S32, (),,
"Return the number of graphics adapters available. @ingroup GFX")
{
return GFXInit::getAdapterCount();
}
DefineEngineStaticMethod( GFXInit, getAdapterName, String, ( S32 index ),,
"Returns the name of the graphics adapter.\n"
"@param index The index of the adapter." )
{
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::getAdapters(&adapters);
if(index >= 0 && index < adapters.size())
return adapters[index]->mName;
Con::errorf( "GFXInit::getAdapterName - Out of range adapter index." );
return String::EmptyString;
}
DefineEngineStaticMethod( GFXInit, getAdapterType, GFXAdapterType, ( S32 index ),,
"Returns the type (D3D9, D3D8, GL, Null) of a graphics adapter.\n"
"@param index The index of the adapter." )
{
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::getAdapters(&adapters);
if( index >= 0 && index < adapters.size())
return adapters[index]->mType;
Con::errorf( "GFXInit::getAdapterType - Out of range adapter index." );
return GFXAdapterType_Count;
}
DefineEngineStaticMethod( GFXInit, getAdapterShaderModel, F32, ( S32 index ),,
"Returns the supported shader model of the graphics adapter or -1 if the index is bad.\n"
"@param index The index of the adapter." )
{
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::getAdapters(&adapters);
if(index < 0 || index >= adapters.size())
{
Con::errorf("GFXInit::getAdapterShaderModel - Out of range adapter index.");
return -1.0f;
}
return adapters[index]->mShaderModel;
}
DefineEngineStaticMethod( GFXInit, getDefaultAdapterIndex, S32, (),,
"Returns the index of the default graphics adapter. This is the graphics device "
"which will be used to initialize the engine." )
{
GFXAdapter *a = GFXInit::getBestAdapterChoice();
// We have to find the index of the adapter in the list to
// return an index that makes sense to the script.
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::getAdapters(&adapters);
for(S32 i=0; i<adapters.size(); i++)
if ( adapters[i]->mIndex == a->mIndex &&
adapters[i]->mType == a->mType )
return i;
Con::warnf( "GFXInit::getDefaultAdapterIndex - Didn't find the adapter in the list!" );
return -1;
}
DefineEngineStaticMethod( GFXInit, getAdapterModeCount, S32, ( S32 index ),,
"Gets the number of modes available on the specified adapter.\n\n"
"@param index Index of the adapter to get modes from.\n"
"@return The number of video modes supported by the adapter or -1 if the given adapter was not found." )
{
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::getAdapters(&adapters);
if( index < 0 || index >= adapters.size())
{
Con::warnf( "GFXInit::getAdapterModeCount - The index was out of range." );
return -1;
}
return adapters[index]->mAvailableModes.size();
}
DefineConsoleStaticMethod( GFXInit, getAdapterMode, String, ( S32 index, S32 modeIndex ),,
"Gets the details of the specified adapter mode.\n\n"
"@param index Index of the adapter to query.\n"
"@param modeIndex Index of the mode to get data from.\n"
"@return A video mode string in the format 'width height fullscreen bitDepth refreshRate aaLevel'.\n"
"@see GuiCanvas::getVideoMode()" )
{
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
GFXInit::getAdapters(&adapters);
if ( index < 0 || index >= adapters.size() )
{
Con::warnf( "GFXInit::getAdapterMode - The adapter index was out of range." );
return String::EmptyString;
}
if ( modeIndex < 0 || modeIndex >= adapters[index]->mAvailableModes.size() )
{
Con::warnf( "GFXInit::getAdapterMode - The mode index was out of range." );
return String::EmptyString;
}
const GFXVideoMode &vm = adapters[index]->mAvailableModes[modeIndex];
return vm.toString();
}
DefineEngineStaticMethod( GFXInit, createNullDevice, void, (),,
"Create the NULL graphics device used for testing or headless operation." )
{
// Enumerate things for GFX before we have an active device.
GFXInit::enumerateAdapters();
// Create a device.
GFXAdapter *a = GFXInit::chooseAdapter(NullDevice);
GFXDevice *newDevice = GFX;
// Do we have a global device already? (This is the site if you want
// to start rendering to multiple devices simultaneously)
if(newDevice == NULL)
newDevice = GFXInit::createDevice(a);
newDevice->setAllowRender( false );
}

101
Engine/source/gfx/gfxInit.h Normal file
View file

@ -0,0 +1,101 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXINIT_H_
#define _GFXINIT_H_
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
#ifndef _ENGINEOBJECT_H_
#include "console/engineObject.h"
#endif
/// Interface for tracking GFX adapters and initializing them into devices.
/// @note Implement this class per platform.
/// @note This is just a class so it can be friends with GFXDevice)
class GFXInit
{
DECLARE_STATIC_CLASS( GFXInit );
public:
/// Allows device to register themselves as available
typedef Signal<void (Vector<GFXAdapter*>&)> RegisterDeviceSignal;
static RegisterDeviceSignal& getRegisterDeviceSignal();
/// Prepares the adapter list.
static void init();
/// Cleans out the adapter list.
static void cleanup();
/// Creates a GFXDevice based on an adapter from the
/// enumerateAdapters method.
///
/// @param adapter Graphics adapter to create device
static GFXDevice *createDevice( GFXAdapter *adapter );
/// Enumerate all the graphics adapters on the system
static void enumerateAdapters();
/// Get the enumerated adapters. Should only call this after
/// a call to enumerateAdapters.
static void getAdapters( Vector<GFXAdapter*> *adapters );
/// Get the number of available adapters.
static S32 getAdapterCount();
/// Chooses a suitable GFXAdapter, based on type, preferences, and fallbacks.
/// If the requested type is omitted, we use the prefs value.
/// If the requested type isn't found, we use fallbacks: OpenGL, NullDevice
/// This method never returns NULL.
static GFXAdapter *chooseAdapter( GFXAdapterType type);
/// Gets the first adapter of the requested type from the list of enumerated
/// adapters. Should only call this after a call to enumerateAdapters.
static GFXAdapter *getAdapterOfType( GFXAdapterType type );
/// Converts a GFXAdapterType to a string name. Useful for writing out prefs
static const char *getAdapterNameFromType( GFXAdapterType type );
/// Converts a string to a GFXAdapterType. Useful for reading in prefs.
static GFXAdapterType getAdapterTypeFromName( const char* name );
/// Returns a GFXVideoMode that describes the current state of the main monitor.
/// This should probably move to the abstract window manager
static GFXVideoMode getDesktopResolution();
/// Based on user preferences (or in the absence of a valid user selection,
/// a heuristic), return a "best" adapter.
static GFXAdapter *getBestAdapterChoice();
/// Get the initial video mode based on user preferences (or a heuristic).
static GFXVideoMode getInitialVideoMode();
private:
/// List of known adapters.
static Vector<GFXAdapter*> smAdapters;
static RegisterDeviceSignal* smRegisterDeviceSignal;
};
#endif

View file

@ -0,0 +1,43 @@
//-----------------------------------------------------------------------------
// 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/gfxOcclusionQuery.h"
String GFXOcclusionQuery::statusToString( OcclusionQueryStatus status )
{
String outStr;
if ( status == GFXOcclusionQuery::Unset )
outStr = "Unset";
else if ( status == GFXOcclusionQuery::Waiting )
outStr = "Waiting";
else if ( status == GFXOcclusionQuery::Occluded )
outStr = "Occluded";
else if ( status == GFXOcclusionQuery::NotOccluded )
outStr = "Visible";
else if ( status == GFXOcclusionQuery::Error )
outStr = "Error";
else
outStr = "Unknown";
return outStr;
}

View file

@ -0,0 +1,85 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXOCCLUSIONQUERY_H_
#define _GFXOCCLUSIONQUERY_H_
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
/// A geometry visibility query object.
/// @see GFXDevice::createOcclusionQuery
class GFXOcclusionQuery : public GFXResource
{
protected:
GFXDevice *mDevice;
GFXOcclusionQuery( GFXDevice *device )
: mDevice( device )
{
}
public:
/// The states returned by getStatus()
/// If you modify this enum you should also modify statusToString()
enum OcclusionQueryStatus
{
Unset, ///<
Waiting, ///<
Error, ///<
Occluded,
NotOccluded
};
virtual ~GFXOcclusionQuery() {}
/// Prepares the query returning true if the last query
/// has been processed and more geometry can be issued.
/// @see getStatus
virtual bool begin() = 0;
/// Called after your geometry is drawn to submit
/// the query for processing.
virtual void end() = 0;
/// Returns the status of the last submitted query. In general
/// you should avoid blocking for the result until the frame
/// following your query to keep from stalling the CPU.
/// @return Status
/// @param block If true CPU will block until the query finishes.
/// @param data Number of pixels rendered, valid only if status returned is NotOccluded.
virtual OcclusionQueryStatus getStatus( bool block, U32 *data = NULL ) = 0;
/// Returns a status string.
static String statusToString( OcclusionQueryStatus status );
// GFXResource
virtual void zombify() = 0;
virtual void resurrect() = 0;
virtual const String describeSelf() const = 0;
};
#endif // _GFXOCCLUSIONQUERY_H_

View file

@ -0,0 +1,82 @@
//-----------------------------------------------------------------------------
// 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 "core/strings/stringFunctions.h"
#include "console/console.h"
#include "gfx/gfxDevice.h"
#include "gfx/gfxPrimitiveBuffer.h"
//-----------------------------------------------------------------------------
#ifdef TORQUE_DEBUG
GFXPrimitiveBuffer *GFXPrimitiveBuffer::smHead = NULL;
U32 GFXPrimitiveBuffer::smActivePBCount = 0;
void GFXPrimitiveBuffer::dumpActivePBs()
{
if(!smActivePBCount)
{
Con::printf("GFXPrimitiveBuffer::dumpActivePBs - no currently active PBs to dump. You are A-OK!");
return;
}
Con::printf("GFXPrimitiveBuffer Usage Report - %d active PBs", smActivePBCount);
Con::printf("---------------------------------------------------------------");
Con::printf(" Addr #idx #prims Profiler Path RefCount");
for(GFXPrimitiveBuffer *walk = smHead; walk; walk=walk->mDebugNext)
{
#if defined(TORQUE_ENABLE_PROFILER)
Con::printf(" %x %6d %6d %s %d", walk, walk->mIndexCount, walk->mPrimitiveCount, walk->mDebugCreationPath.c_str(), walk->getRefCount());
#else
Con::printf(" %x %6d %6d %s %d", walk, walk->mIndexCount, walk->mPrimitiveCount, "", walk->getRefCount());
#endif
}
Con::printf("----- dump complete -------------------------------------------");
AssertFatal(false, "There is a primitive buffer leak, check the log for more details.");
}
#endif
/// The resource should put a description of itself (number of vertices, size/width of texture, etc.) in buffer
const String GFXPrimitiveBuffer::describeSelf() const
{
#if defined(TORQUE_DEBUG) && defined(TORQUE_ENABLE_PROFILER)
return String::ToString("indexCount: %6d primCount: %6d refCount: %d path: %s",
mIndexCount, mPrimitiveCount, getRefCount(), mDebugCreationPath.c_str());
#else
return String::ToString("indexCount: %6d primCount: %6d refCount: %d path: %s",
mIndexCount, mPrimitiveCount, getRefCount(), "");
#endif
}
//-----------------------------------------------------------------------------
// Set
//-----------------------------------------------------------------------------
void GFXPrimitiveBufferHandle::set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc)
{
StrongRefPtr<GFXPrimitiveBuffer>::operator=( theDevice->allocPrimitiveBuffer(indexCount, primitiveCount, bufferType) );
#ifdef TORQUE_DEBUG
if( desc.isNotEmpty() )
getPointer()->mDebugCreationPath = desc;
#endif
}

View file

@ -0,0 +1,175 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXPRIMITIVEBUFFER_H_
#define _GFXPRIMITIVEBUFFER_H_
#ifndef _GFXSTRUCTS_H_
#include "gfx/gfxStructs.h"
#endif
#ifdef TORQUE_ENABLE_PROFILER
#include "platform/profiler.h"
#endif
class GFXPrimitiveBuffer : public StrongRefBase, public GFXResource
{
friend class GFXPrimitiveBufferHandle;
friend class GFXDevice;
public: //protected:
U32 mIndexCount;
U32 mPrimitiveCount;
GFXBufferType mBufferType;
GFXPrimitive *mPrimitiveArray;
GFXDevice *mDevice;
#ifdef TORQUE_DEBUG
// In debug builds we provide a TOC leak tracking system.
static U32 smActivePBCount;
static GFXPrimitiveBuffer *smHead;
static void dumpActivePBs();
String mDebugCreationPath;
GFXPrimitiveBuffer *mDebugNext;
GFXPrimitiveBuffer *mDebugPrev;
#endif
GFXPrimitiveBuffer( GFXDevice *device,
U32 indexCount,
U32 primitiveCount,
GFXBufferType bufferType )
{
mDevice = device;
mIndexCount = indexCount;
mPrimitiveCount = primitiveCount;
mBufferType = bufferType;
if(primitiveCount)
{
mPrimitiveArray = new GFXPrimitive[primitiveCount];
dMemset((void *) mPrimitiveArray, 0, primitiveCount * sizeof(GFXPrimitive));
}
else
mPrimitiveArray = NULL;
#if defined(TORQUE_DEBUG)
// Active copy tracking.
smActivePBCount++;
#if defined(TORQUE_ENABLE_PROFILE_PATH)
mDebugCreationPath = gProfiler->getProfilePath();
#endif
mDebugNext = smHead;
mDebugPrev = NULL;
if(smHead)
{
AssertFatal(smHead->mDebugPrev == NULL, "GFXPrimitiveBuffer::GFXPrimitiveBuffer - found unexpected previous in current head!");
smHead->mDebugPrev = this;
}
smHead = this;
#endif
}
virtual ~GFXPrimitiveBuffer()
{
if( mPrimitiveArray != NULL )
{
delete [] mPrimitiveArray;
mPrimitiveArray = NULL;
}
#ifdef TORQUE_DEBUG
if(smHead == this)
smHead = this->mDebugNext;
if(mDebugNext)
mDebugNext->mDebugPrev = mDebugPrev;
if(mDebugPrev)
mDebugPrev->mDebugNext = mDebugNext;
mDebugPrev = mDebugNext = NULL;
smActivePBCount--;
#endif
}
virtual void lock(U32 indexStart, U32 indexEnd, void **indexPtr)=0; ///< locks this primitive buffer for writing into
virtual void unlock()=0; ///< unlocks this primitive buffer.
virtual void prepare()=0; ///< prepares this primitive buffer for use on the device it was allocated on
// GFXResource interface
/// The resource should put a description of itself (number of vertices, size/width of texture, etc.) in buffer
virtual const String describeSelf() const;
};
class GFXPrimitiveBufferHandle : public StrongRefPtr<GFXPrimitiveBuffer>
{
typedef StrongRefPtr<GFXPrimitiveBuffer> Parent;
public:
enum Constants {
MaxIndexCount = 65535,
};
GFXPrimitiveBufferHandle() {};
GFXPrimitiveBufferHandle(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString )
{
set(theDevice, indexCount, primitiveCount, bufferType, desc);
}
void set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString );
void lock(U16 **indexBuffer, GFXPrimitive **primitiveBuffer = NULL, U32 indexStart = 0, U32 indexEnd = 0)
{
if(indexEnd == 0)
indexEnd = getPointer()->mIndexCount;
AssertFatal(indexStart < indexEnd && indexEnd <= getPointer()->mIndexCount, "Out of range index lock!");
getPointer()->lock(indexStart, indexEnd, (void**)indexBuffer);
if(primitiveBuffer)
*primitiveBuffer = getPointer()->mPrimitiveArray;
}
void unlock()
{
getPointer()->unlock();
}
void prepare()
{
getPointer()->prepare();
}
bool operator==(const GFXPrimitiveBufferHandle &buffer) const {
return getPointer() == buffer.getPointer();
}
GFXPrimitiveBufferHandle& operator=(GFXPrimitiveBuffer *ptr)
{
StrongObjectRef::set(ptr);
return *this;
}
};
#endif // _GFXPRIMITIVEBUFFER_H_

View file

@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxResource.h"
#include "gfx/gfxDevice.h"
GFXResource::GFXResource()
{
mPrevResource = mNextResource = NULL;
mOwningDevice = NULL;
mFlagged = false;
}
GFXResource::~GFXResource()
{
// Make sure we're not the head of the list and referencd on the device.
if(mOwningDevice && mOwningDevice->mResourceListHead == this)
{
AssertFatal(mPrevResource == NULL,
"GFXResource::~GFXResource - head of list but have a previous item!");
mOwningDevice->mResourceListHead = mNextResource;
}
// Unlink ourselves from the list.
if(mPrevResource)
mPrevResource->mNextResource = mNextResource;
if(mNextResource)
mNextResource->mPrevResource = mPrevResource;
mPrevResource = mNextResource = NULL;
}
void GFXResource::registerResourceWithDevice( GFXDevice *device )
{
mOwningDevice = device;
mNextResource = device->mResourceListHead;
device->mResourceListHead = this;
if(mNextResource)
mNextResource->mPrevResource = this;
}

View file

@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXRESOURCE_H_
#define _GFXRESOURCE_H_
#ifndef _TORQUE_TYPES_H_
#include "platform/types.h"
#endif
#ifndef _TORQUE_STRING_H_
#include "core/util/str.h"
#endif
class GFXDevice;
/// Mixin for the purpose of tracking GFX resources owned by a GFXDevice.
///
/// There are many types of resource that are allocated from a GFXDevice that
/// must be participatory in device resets. For instance, all default pool
/// DirectX resources have to be involved when the device resets. Render
/// targets in all APIs need to unbind themselves when resets happen.
///
/// This system is also handy for accounting purposes. For instance, we may
/// want to traverse all registered VBs, IBs, Textures, or RTs in order to
/// determine what, if any, items are still allocated. This can be used in
/// leak reports, memory usage reports, etc.
class GFXResource
{
private:
friend class GFXDevice;
GFXResource *mPrevResource;
GFXResource *mNextResource;
GFXDevice *mOwningDevice;
/// Helper flag to check new resource allocations
bool mFlagged;
public:
GFXResource();
virtual ~GFXResource();
/// Registers this resource with the given device
void registerResourceWithDevice(GFXDevice *device);
/// When called the resource should destroy all device sensitive information (e.g. D3D resources in D3DPOOL_DEFAULT
virtual void zombify()=0;
/// When called the resource should restore all device sensitive information destroyed by zombify()
virtual void resurrect()=0;
/// The resource should put a description of itself (number of vertices, size/width of texture, etc.) in buffer
virtual const String describeSelf() const = 0;
inline GFXResource *getNextResource() const
{
return mNextResource;
}
inline GFXResource *getPrevResource() const
{
return mPrevResource;
}
inline GFXDevice *getOwningDevice() const
{
return mOwningDevice;
}
inline bool isFlagged()
{
return mFlagged;
}
inline void setFlag()
{
mFlagged = true;
}
inline void clearFlag()
{
mFlagged = false;
}
};
#endif

View file

@ -0,0 +1,174 @@
//-----------------------------------------------------------------------------
// 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/gfxShader.h"
#include "shaderGen/conditionerFeature.h"
#include "core/volume.h"
#include "console/engineAPI.h"
Vector<GFXShaderMacro> GFXShader::smGlobalMacros;
bool GFXShader::smLogErrors = true;
bool GFXShader::smLogWarnings = true;
GFXShader::GFXShader()
: mPixVersion( 0.0f ),
mReloadKey( 0 )
{
}
GFXShader::~GFXShader()
{
Torque::FS::RemoveChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
Torque::FS::RemoveChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
}
bool GFXShader::init( const Torque::Path &vertFile,
const Torque::Path &pixFile,
F32 pixVersion,
const Vector<GFXShaderMacro> &macros )
{
// Store the inputs for use in reloading.
mVertexFile = vertFile;
mPixelFile = pixFile;
mPixVersion = pixVersion;
mMacros = macros;
// Before we compile the shader make sure the
// conditioner features have been updated.
ConditionerFeature::updateConditioners();
// Now do the real initialization.
if ( !_init() )
return false;
_updateDesc();
// Add file change notifications for reloads.
Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
return true;
}
bool GFXShader::reload()
{
// Before we compile the shader make sure the
// conditioner features have been updated.
ConditionerFeature::updateConditioners();
mReloadKey++;
// Init does the work.
bool success = _init();
if ( success )
_updateDesc();
// Let anything that cares know that
// this shader has reloaded
mReloadSignal.trigger();
return success;
}
void GFXShader::_updateDesc()
{
mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ",
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion );
GFXShaderMacro::stringize( smGlobalMacros, &mDescription );
GFXShaderMacro::stringize( mMacros, &mDescription );
}
void GFXShader::addGlobalMacro( const String &name, const String &value )
{
// Check to see if we already have this macro.
Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
for ( ; iter != smGlobalMacros.end(); iter++ )
{
if ( iter->name == name )
{
if ( iter->value != value )
iter->value = value;
return;
}
}
// Add a new macro.
smGlobalMacros.increment();
smGlobalMacros.last().name = name;
smGlobalMacros.last().value = value;
}
bool GFXShader::removeGlobalMacro( const String &name )
{
Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
for ( ; iter != smGlobalMacros.end(); iter++ )
{
if ( iter->name == name )
{
smGlobalMacros.erase( iter );
return true;
}
}
return false;
}
void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf )
{
Vector<GFXShaderConstBuffer*>::iterator iter = mActiveBuffers.begin();
for ( ; iter != mActiveBuffers.end(); iter++ )
{
if ( *iter == buf )
{
mActiveBuffers.erase_fast( iter );
return;
}
}
AssertFatal( false, "GFXShader::_unlinkBuffer - buffer was not found?" );
}
DefineEngineFunction( addGlobalShaderMacro, void,
( const char *name, const char *value ), ( NULL ),
"Adds a global shader macro which will be merged with the script defined "
"macros on every shader. The macro will replace the value of an existing "
"macro of the same name. For the new macro to take effect all the shaders "
"in the system need to be reloaded.\n"
"@see resetLightManager, removeGlobalShaderMacro\n"
"@ingroup Rendering\n" )
{
GFXShader::addGlobalMacro( name, value );
}
DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),,
"Removes an existing global macro by name.\n"
"@see addGlobalShaderMacro\n"
"@ingroup Rendering\n" )
{
GFXShader::removeGlobalMacro( name );
}

View file

@ -0,0 +1,365 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXSHADER_H_
#define _GFXSHADER_H_
#ifndef _GFXRESOURCE_H_
#include "gfx/gfxResource.h"
#endif
#ifndef _TORQUE_STRING_H_
#include "core/util/str.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _ALIGNEDARRAY_H_
#include "core/util/tAlignedArray.h"
#endif
#ifndef _MMATRIX_H_
#include "math/mMatrix.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _GFXSTRUCTS_H_
#include "gfx/gfxStructs.h"
#endif
#ifndef _COLOR_H_
#include "core/color.h"
#endif
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#ifndef _PATH_H_
#include "core/util/path.h"
#endif
#ifndef _TSIGNAL_H_
#include "core/util/tSignal.h"
#endif
class Point2I;
class Point2F;
class ColorF;
class MatrixF;
class GFXShader;
class GFXVertexFormat;
/// Instances of this struct are returned GFXShaderConstBuffer
struct GFXShaderConstDesc
{
public:
String name;
GFXShaderConstType constType;
U32 arraySize; // > 1 means it is an array!
};
/// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants.
/// Derived classes can put whatever info they need into here, these handles are owned by the shader constant buffer
/// (or shader). Client code should not free these.
class GFXShaderConstHandle
{
public:
GFXShaderConstHandle() { mValid = false; }
virtual ~GFXShaderConstHandle() {}
/// Returns true if this constant is valid and can
/// be set on the shader.
bool isValid() const { return mValid; }
/// Returns the name of the constant handle.
virtual const String& getName() const = 0;
/// Returns the type of the constant handle.
virtual GFXShaderConstType getType() const = 0;
virtual U32 getArraySize() const = 0;
/// Returns -1 if this handle does not point to a Sampler.
virtual S32 getSamplerRegister() const = 0;
protected:
/// The state of the constant which is
/// set from the derived class.
bool mValid;
};
/// GFXShaderConstBuffer is a collection of shader data which
/// are sent to the device in one call in most cases.
///
/// The content of the buffer is persistant and if a value
/// does not change frequently there is a savings in not setting
/// the value every frame.
///
class GFXShaderConstBuffer : public GFXResource, public StrongRefBase
{
protected:
/// The lost state of the buffer content.
///
/// Derived classes need to set the lost state
/// on first creation of the buffer and shader
/// reloads.
///
/// @see wasLost
bool mWasLost;
GFXShaderConstBuffer()
: mWasLost( true ),
mInstPtr( NULL )
{
}
public:
/// Return the shader that created this buffer
virtual GFXShader* getShader() = 0;
/// The content of the buffer is in the lost state when
/// first created or when the shader is reloaded. When
/// the content is lost you must refill the buffer
/// with all the constants used by your shader.
///
/// Use this property to avoid setting constants which do
/// not changefrom one frame to the next.
///
bool wasLost() const { return mWasLost; }
/// An inline helper which ensures the handle is valid
/// before the virtual set method is called.
///
/// You should prefer using this method unless your sure the
/// handle is always valid or if your doing your own test.
///
template< typename VALUE >
inline void setSafe( GFXShaderConstHandle *handle, const VALUE& v )
{
if ( handle->isValid() )
set( handle, v );
}
/// Set a shader constant.
///
/// The constant handle is assumed to be valid.
///
/// Perfer using setSafe unless you can check the handle
/// validity yourself and skip a significat amount of work.
///
/// @see GFXShaderConstHandle::isValid()
///
virtual void set(GFXShaderConstHandle* handle, const F32 f) = 0;
virtual void set(GFXShaderConstHandle* handle, const Point2F& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const Point3F& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const Point4F& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const PlaneF& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const ColorF& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const S32 f) = 0;
virtual void set(GFXShaderConstHandle* handle, const Point2I& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const Point3I& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const Point4I& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv) = 0;
virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv) = 0;
/// Set a variable sized matrix shader constant.
virtual void set( GFXShaderConstHandle* handle,
const MatrixF& mat,
const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0;
/// Set a variable sized matrix shader constant from
/// an array of matricies.
virtual void set( GFXShaderConstHandle* handle,
const MatrixF* mat,
const U32 arraySize,
const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0;
// TODO: Make this protected and put a real API around it.
U8 *mInstPtr;
};
typedef StrongRefPtr<GFXShaderConstBuffer> GFXShaderConstBufferRef;
//**************************************************************************
// Shader
//**************************************************************************
class GFXShader : public StrongRefBase, public GFXResource
{
friend class GFXShaderConstBuffer;
protected:
/// These are system wide shader macros which are
/// merged with shader specific macros at creation.
static Vector<GFXShaderMacro> smGlobalMacros;
/// If true the shader errors are spewed to the console.
static bool smLogErrors;
/// If true the shader warnings are spewed to the console.
static bool smLogWarnings;
/// The vertex shader file.
Torque::Path mVertexFile;
/// The pixel shader file.
Torque::Path mPixelFile;
/// The macros to be passed to the shader.
Vector<GFXShaderMacro> mMacros;
/// The pixel version this is compiled for.
F32 mPixVersion;
///
String mDescription;
/// Counter that is incremented each time this shader is reloaded.
U32 mReloadKey;
Signal<void()> mReloadSignal;
/// Vector of buffers that reference this shader.
/// It is the responsibility of the derived shader class to populate this
/// vector and to notify them when this shader is reloaded. Classes
/// derived from GFXShaderConstBuffer should call _unlinkBuffer from
/// their destructor.
Vector<GFXShaderConstBuffer*> mActiveBuffers;
/// A protected constructor so it cannot be instantiated.
GFXShader();
public:
// TODO: Add this into init().
GFXVertexFormat mInstancingFormat;
/// Adds a global shader macro which will be merged with
/// the script defined macros on every shader reload.
///
/// The macro will replace the value of an existing macro
/// of the same name.
///
/// For the new macro to take effect all the shaders/materials
/// in the system need to be reloaded.
///
/// @see MaterialManager::flushAndReInitInstances
/// @see ShaderData::reloadAll
static void addGlobalMacro( const String &name, const String &value = String::EmptyString );
/// Removes an existing global macro by name.
/// @see addGlobalMacro
static bool removeGlobalMacro( const String &name );
/// Toggle logging for shader errors.
static void setLogging( bool logErrors,
bool logWarning )
{
smLogErrors = logErrors;
smLogWarnings = logWarning;
}
/// The destructor.
virtual ~GFXShader();
///
bool init( const Torque::Path &vertFile,
const Torque::Path &pixFile,
F32 pixVersion,
const Vector<GFXShaderMacro> &macros );
/// Reloads the shader from disk.
bool reload();
Signal<void()> getReloadSignal() { return mReloadSignal; }
/// Allocate a constant buffer
virtual GFXShaderConstBufferRef allocConstBuffer() = 0;
/// Returns our list of shader constants, the material can get this and just set the constants it knows about
virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const = 0;
/// Returns a shader constant handle for the name constant.
///
/// Since shaders can reload and later have handles that didn't
/// exist originally this will return a handle in an invalid state
/// if the constant doesn't exist at this time.
virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0;
/// Returns the alignment value for constType
virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0;
/// Returns the required vertex format for this shader.
/// Returns the pixel shader version.
F32 getPixVersion() const { return mPixVersion; }
/// Returns a counter which is incremented each time this shader is reloaded.
U32 getReloadKey() const { return mReloadKey; }
/// Device specific shaders can override this method to return
/// the shader disassembly.
virtual bool getDisassembly( String &outStr ) const { return false; }
/// Returns the vertex shader file path.
const String& getVertexShaderFile() const { return mVertexFile.getFullPath(); }
/// Returns the pixel shader file path.
const String& getPixelShaderFile() const { return mPixelFile.getFullPath(); }
// GFXResource
const String describeSelf() const { return mDescription; }
protected:
/// Called when the shader files change on disk.
void _onFileChanged( const Torque::Path &path ) { reload(); }
/// Internal initialization function overloaded for
/// each GFX device type.
virtual bool _init() = 0;
/// Buffers call this from their destructor (so we don't have to ref count them).
void _unlinkBuffer( GFXShaderConstBuffer *buf );
/// Called to update the description string after init.
void _updateDesc();
};
/// A strong pointer to a reference counted GFXShader.
typedef StrongRefPtr<GFXShader> GFXShaderRef;
/// A weak pointer to a reference counted GFXShader.
typedef WeakRefPtr<GFXShader> GFXShaderWeakRef;
#endif // GFXSHADER

View file

@ -0,0 +1,336 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxStateBlock.h"
#include "core/crc.h"
#include "gfx/gfxDevice.h"
#include "core/strings/stringFunctions.h"
#include "gfx/gfxStringEnumTranslate.h"
///
/// GFXStateBlock
///
const String GFXStateBlock::describeSelf() const
{
return String::ToString("hashvalue: 0x%x", getDesc().getHashValue());
}
///
/// GFXStateBlockDesc
///
GFXStateBlockDesc::GFXStateBlockDesc()
{
// Alpha blending
blendDefined = false;
blendEnable = false;
blendSrc = GFXBlendOne;
blendDest = GFXBlendZero;
blendOp = GFXBlendOpAdd;
// Separate alpha blending
separateAlphaBlendDefined = false;
separateAlphaBlendEnable = false;
separateAlphaBlendSrc = GFXBlendOne;
separateAlphaBlendDest = GFXBlendZero;
separateAlphaBlendOp = GFXBlendOpAdd;
// Alpha test
alphaDefined = false;
alphaTestEnable = false;
alphaTestRef = 0;
alphaTestFunc = GFXCmpGreaterEqual;
// Color Writes
colorWriteDefined = false;
colorWriteRed = true;
colorWriteBlue = true;
colorWriteGreen = true;
colorWriteAlpha = true;
// Rasterizer
cullDefined = false;
cullMode = GFXCullCCW;
// Depth
zDefined = false;
zEnable = true;
zWriteEnable = true;
zFunc = GFXCmpLessEqual;
zBias = 0;
zSlopeBias = 0;
// Stencil
stencilDefined = false;
stencilEnable = false;
stencilFailOp = GFXStencilOpKeep;
stencilZFailOp = GFXStencilOpKeep;
stencilPassOp = GFXStencilOpKeep;
stencilFunc = GFXCmpNever;
stencilRef = 0;
stencilMask = 0xFFFFFFFF;
stencilWriteMask = 0xFFFFFFFF;
// FF lighting
ffLighting = false;
vertexColorEnable = false;
fillMode = GFXFillSolid;
samplersDefined = false;
textureFactor.set( 255, 255, 255, 255 );
}
// This method just needs to return a unique value based on its contents.
U32 GFXStateBlockDesc::getHashValue() const
{
return CRC::calculateCRC(this, sizeof(GFXStateBlockDesc));
}
/// Adds data from desc to this description, uses *defined parameters in desc to figure out
/// what blocks of state to actually copy from desc.
void GFXStateBlockDesc::addDesc(const GFXStateBlockDesc& desc)
{
// Alpha blending
if (desc.blendDefined)
{
blendDefined = true;
blendEnable = desc.blendEnable;
blendSrc = desc.blendSrc;
blendDest = desc.blendDest;
blendOp = desc.blendOp;
}
// Separate alpha blending
if ( desc.separateAlphaBlendDefined )
{
separateAlphaBlendDefined = true;
separateAlphaBlendEnable = desc.separateAlphaBlendEnable;
separateAlphaBlendSrc = desc.separateAlphaBlendSrc;
separateAlphaBlendDest = desc.separateAlphaBlendDest;
separateAlphaBlendOp = desc.separateAlphaBlendOp;
}
// Alpha test
if (desc.alphaDefined)
{
alphaDefined = true;
alphaTestEnable = desc.alphaTestEnable;
alphaTestRef = desc.alphaTestRef;
alphaTestFunc = desc.alphaTestFunc;
}
// Color Writes
if (desc.colorWriteDefined)
{
colorWriteDefined = true;
colorWriteRed = desc.colorWriteRed;
colorWriteBlue = desc.colorWriteBlue;
colorWriteGreen = desc.colorWriteGreen;
colorWriteAlpha = desc.colorWriteAlpha;
}
// Rasterizer
if (desc.cullDefined)
{
cullDefined = true;
cullMode = desc.cullMode;
}
// Depth
if (desc.zDefined)
{
zDefined = true;
zEnable = desc.zEnable;
zWriteEnable = desc.zWriteEnable;
zFunc = desc.zFunc;
zBias = desc.zBias;
zSlopeBias = desc.zSlopeBias;
}
// Stencil
if (desc.stencilDefined)
{
stencilDefined = true;
stencilEnable = desc.stencilEnable;
stencilFailOp = desc.stencilFailOp;
stencilZFailOp = desc.stencilZFailOp;
stencilPassOp = desc.stencilPassOp;
stencilFunc = desc.stencilFunc;
stencilRef = desc.stencilRef;
stencilMask = desc.stencilMask;
stencilWriteMask = desc.stencilWriteMask;
}
if (desc.samplersDefined)
{
samplersDefined = true;
for (U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
{
samplers[i] = desc.samplers[i];
}
textureFactor = desc.textureFactor;
}
vertexColorEnable = desc.vertexColorEnable;
fillMode = desc.fillMode;
}
/// Returns a string that describes the options set (used by GFXStateBlock::describeSelf)
const String GFXStateBlockDesc::describeSelf() const
{
GFXStringEnumTranslate::init();
String ret;
ret = String::ToString(" AlphaBlend: %d, BlendSrc: %s, BlendDest: %s, BlendOp: %s\n",
blendEnable, GFXStringBlend[blendSrc], GFXStringBlend[blendDest], GFXStringBlendOp[blendOp]);
ret += String::ToString(" SeparateAlphaBlend: %d, SeparateAlphaBlendSrc: %s, SeparateAlphaBlendDest: %s, SeparateAlphaBlendOp: %s\n",
separateAlphaBlendEnable, GFXStringBlend[separateAlphaBlendSrc], GFXStringBlend[separateAlphaBlendDest], GFXStringBlendOp[separateAlphaBlendOp]);
ret += String::ToString(" AlphaTest: %d, AlphaTestFunc: %s, AlphaTestRef: %d\n",
alphaTestEnable, GFXStringCmpFunc[alphaTestFunc], alphaTestRef);
ret += String::ToString(" ColorWrites: r: %d g: %d b: %d a: %d",
colorWriteRed, colorWriteGreen, colorWriteBlue, colorWriteAlpha);
ret += String::ToString(" CullMode: %s\n", GFXStringCullMode[cullMode]);
ret += String::ToString(" ZEnable: %d, ZWriteEnable: %d, ZFunc: %s, ZBias: %f, ZSlopeBias: %f\n",
zEnable, zWriteEnable, GFXStringCmpFunc[zFunc], zBias, zSlopeBias);
ret += String::ToString(" Stencil: %d, StencilFailOp: %s, StencilZFailOp: %s, StencilPassOp: %s, \n stencilFunc: %s, stencilRef: %d, stencilMask: 0x%x, stencilWriteMask: 0x%x\n",
stencilEnable, GFXStringCmpFunc[stencilFailOp], GFXStringCmpFunc[stencilZFailOp], GFXStringCmpFunc[stencilPassOp],
GFXStringCmpFunc[stencilFunc], stencilRef, stencilMask, stencilWriteMask);
ret += String::ToString(" FF Lighting: %d, VertexColors: %d, fillMode: %s",
ffLighting, vertexColorEnable, GFXStringFillMode[fillMode]);
return ret;
}
//
// Utility functions
//
void GFXStateBlockDesc::setCullMode( GFXCullMode m )
{
cullDefined = true;
cullMode = m;
}
void GFXStateBlockDesc::setZReadWrite( bool read, bool write )
{
zDefined = true;
zEnable = read;
zWriteEnable = write;
}
void GFXStateBlockDesc::setAlphaTest( bool enable, GFXCmpFunc func, S32 alphaRef )
{
alphaDefined = true;
alphaTestEnable = enable;
alphaTestFunc = func;
alphaTestRef = alphaRef;
}
void GFXStateBlockDesc::setBlend( bool enable, GFXBlend src, GFXBlend dest, GFXBlendOp op )
{
blendDefined = true;
blendEnable = enable;
blendSrc = src;
blendDest = dest;
blendOp = op;
}
void GFXStateBlockDesc::setSeparateAlphaBlend( bool enable, GFXBlend src, GFXBlend dest, GFXBlendOp op )
{
separateAlphaBlendDefined = true;
separateAlphaBlendEnable = enable;
separateAlphaBlendSrc = src;
separateAlphaBlendDest = dest;
separateAlphaBlendOp = op;
}
void GFXStateBlockDesc::setColorWrites( bool red, bool green, bool blue, bool alpha )
{
colorWriteDefined = true;
colorWriteRed = red;
colorWriteGreen = green;
colorWriteBlue = blue;
colorWriteAlpha = alpha;
}
GFXSamplerStateDesc::GFXSamplerStateDesc()
{
textureColorOp = GFXTOPDisable;
addressModeU = GFXAddressWrap;
addressModeV = GFXAddressWrap;
addressModeW = GFXAddressWrap;
magFilter = GFXTextureFilterLinear;
minFilter = GFXTextureFilterLinear;
mipFilter = GFXTextureFilterLinear;
maxAnisotropy = 1;
alphaArg1 = GFXTATexture;
alphaArg2 = GFXTADiffuse;
alphaArg3 = GFXTACurrent;
colorArg1 = GFXTACurrent;
colorArg2 = GFXTATexture;
colorArg3 = GFXTACurrent;
alphaOp = GFXTOPModulate;
textureTransform = GFXTTFFDisable;
resultArg = GFXTACurrent;
mipLODBias = 0.0f;
}
GFXSamplerStateDesc GFXSamplerStateDesc::getWrapLinear()
{
// Linear with wrapping is already the default
GFXSamplerStateDesc ssd;
ssd.textureColorOp = GFXTOPModulate;
return ssd;
}
GFXSamplerStateDesc GFXSamplerStateDesc::getWrapPoint()
{
GFXSamplerStateDesc ssd;
ssd.textureColorOp = GFXTOPModulate;
ssd.magFilter = GFXTextureFilterPoint;
ssd.minFilter = GFXTextureFilterPoint;
ssd.mipFilter = GFXTextureFilterPoint;
return ssd;
}
GFXSamplerStateDesc GFXSamplerStateDesc::getClampLinear()
{
GFXSamplerStateDesc ssd;
ssd.textureColorOp = GFXTOPModulate;
ssd.addressModeU = GFXAddressClamp;
ssd.addressModeV = GFXAddressClamp;
ssd.addressModeW = GFXAddressClamp;
return ssd;
}
GFXSamplerStateDesc GFXSamplerStateDesc::getClampPoint()
{
GFXSamplerStateDesc ssd;
ssd.textureColorOp = GFXTOPModulate;
ssd.addressModeU = GFXAddressClamp;
ssd.addressModeV = GFXAddressClamp;
ssd.addressModeW = GFXAddressClamp;
ssd.magFilter = GFXTextureFilterPoint;
ssd.minFilter = GFXTextureFilterPoint;
ssd.mipFilter = GFXTextureFilterPoint;
return ssd;
}

View file

@ -0,0 +1,219 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXSTATEBLOCK_H_
#define _GFXSTATEBLOCK_H_
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _GFXRESOURCE_H_
#include "gfx/gfxResource.h"
#endif
#ifndef _COLOR_H_
#include "core/color.h"
#endif
struct GFXSamplerStateDesc
{
GFXTextureAddressMode addressModeU;
GFXTextureAddressMode addressModeV;
GFXTextureAddressMode addressModeW;
GFXTextureFilterType magFilter;
GFXTextureFilterType minFilter;
GFXTextureFilterType mipFilter;
/// The maximum anisotropy used when one of the filter types
/// is set to anisotropic.
///
/// Defaults to 1.
///
/// @see GFXTextureFilterType
U32 maxAnisotropy;
/// Used to offset the mipmap selection by whole or
/// fractional amounts either postively or negatively.
///
/// Defaults to zero.
F32 mipLODBias;
GFXTextureOp textureColorOp;
GFXTextureOp alphaOp;
GFXTextureArgument alphaArg1;
GFXTextureArgument alphaArg2;
GFXTextureArgument alphaArg3;
GFXTextureArgument colorArg1;
GFXTextureArgument colorArg2;
GFXTextureArgument colorArg3;
GFXTextureArgument resultArg;
GFXTextureTransformFlags textureTransform;
GFXSamplerStateDesc();
/// Returns an modulate, wrap, and linear sampled state.
static GFXSamplerStateDesc getWrapLinear();
/// Returns an modulate, wrap, and point sampled state.
static GFXSamplerStateDesc getWrapPoint();
/// Returns an modulate, clamp, and linear sampled state.
static GFXSamplerStateDesc getClampLinear();
/// Returns an modulate, clamp, and point sampled state.
static GFXSamplerStateDesc getClampPoint();
};
/// GFXStateBlockDesc defines a render state, which is then used to create a GFXStateBlock instance.
struct GFXStateBlockDesc
{
// Blending
bool blendDefined;
bool blendEnable;
GFXBlend blendSrc;
GFXBlend blendDest;
GFXBlendOp blendOp;
/// @name Separate Alpha Blending
/// @{
bool separateAlphaBlendDefined;
bool separateAlphaBlendEnable;
GFXBlend separateAlphaBlendSrc;
GFXBlend separateAlphaBlendDest;
GFXBlendOp separateAlphaBlendOp;
/// @}
// Alpha test
bool alphaDefined;
bool alphaTestEnable;
S32 alphaTestRef;
GFXCmpFunc alphaTestFunc;
// Color Writes
bool colorWriteDefined;
bool colorWriteRed;
bool colorWriteBlue;
bool colorWriteGreen;
bool colorWriteAlpha;
// Rasterizer
bool cullDefined;
GFXCullMode cullMode;
// Depth
bool zDefined;
bool zEnable;
bool zWriteEnable;
GFXCmpFunc zFunc;
F32 zBias;
F32 zSlopeBias;
// Stencil
bool stencilDefined;
bool stencilEnable;
GFXStencilOp stencilFailOp;
GFXStencilOp stencilZFailOp;
GFXStencilOp stencilPassOp;
GFXCmpFunc stencilFunc;
U32 stencilRef;
U32 stencilMask;
U32 stencilWriteMask;
// FF lighting
bool ffLighting;
bool vertexColorEnable;
GFXFillMode fillMode;
// Sampler states
bool samplersDefined;
GFXSamplerStateDesc samplers[TEXTURE_STAGE_COUNT];
ColorI textureFactor;
GFXStateBlockDesc();
/// Returns the hash value of this state description
U32 getHashValue() const;
/// Adds data from desc to this description, uses *defined parameters in desc to figure out
/// what blocks of state to actually copy from desc.
void addDesc( const GFXStateBlockDesc& desc );
/// Returns a string that describes the options set (used by GFXStateBlock::describeSelf)
const String describeSelf() const;
/// Utility functions to make setting up stateblock descriptions less wordy.
void setCullMode( GFXCullMode m );
/// Helpers for setting the fill modes.
void setFillModePoint() { fillMode = GFXFillPoint; }
void setFillModeWireframe() { fillMode = GFXFillWireframe; }
void setFillModeSolid() { fillMode = GFXFillSolid; }
void setZReadWrite( bool read, bool write = true );
void setAlphaTest( bool enable,
GFXCmpFunc func = GFXCmpGreaterEqual,
S32 alphaRef = 0 );
void setBlend( bool enable,
GFXBlend src = GFXBlendSrcAlpha,
GFXBlend dest = GFXBlendInvSrcAlpha,
GFXBlendOp op = GFXBlendOpAdd );
void setSeparateAlphaBlend( bool enable,
GFXBlend src = GFXBlendOne,
GFXBlend dest = GFXBlendZero,
GFXBlendOp op = GFXBlendOpAdd );
///
void setColorWrites( bool red, bool green, bool blue, bool alpha );
};
class GFXStateBlock : public StrongRefBase, public GFXResource
{
public:
virtual ~GFXStateBlock() { }
/// Returns the hash value of the desc that created this block
virtual U32 getHashValue() const = 0;
/// Returns a GFXStateBlockDesc that this block represents
virtual const GFXStateBlockDesc& getDesc() const = 0;
/// Default implementation for GFXResource::describeSelf
virtual const String describeSelf() const;
};
typedef StrongRefPtr<GFXStateBlock> GFXStateBlockRef;
#endif

View file

@ -0,0 +1,418 @@
//-----------------------------------------------------------------------------
// 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 "core/strings/stringFunctions.h"
#include "gfx/gfxStringEnumTranslate.h"
#include "gfx/gfxAPI.h"
#include "console/console.h"
//------------------------------------------------------------------------------
const char *GFXStringIndexFormat[GFXIndexFormat_COUNT];
const char *GFXStringSamplerState[GFXSAMP_COUNT];
const char *GFXStringTextureFormat[GFXFormat_COUNT];
const char *GFXStringTiledTextureFormat[GFXFormat_COUNT];
const char *GFXStringRenderTargetFormat[GFXFormat_COUNT];
const char *GFXStringRenderState[GFXRenderState_COUNT];
const char *GFXStringTextureFilter[GFXTextureFilter_COUNT];
const char *GFXStringBlend[GFXBlend_COUNT];
const char *GFXStringBlendOp[GFXBlendOp_COUNT];
const char *GFXStringStencilOp[GFXStencilOp_COUNT];
const char *GFXStringCmpFunc[GFXCmp_COUNT];
const char *GFXStringCullMode[GFXCull_COUNT];
const char *GFXStringPrimType[GFXPT_COUNT];
const char *GFXStringTextureStageState[GFXTSS_COUNT];
const char *GFXStringTextureAddress[GFXAddress_COUNT];
const char *GFXStringTextureOp[GFXTOP_COUNT];
const char *GFXStringFillMode[GFXFill_COUNT];
StringValueLookupFn GFXStringRenderStateValueLookup[GFXRenderState_COUNT];
StringValueLookupFn GFXStringSamplerStateValueLookup[GFXSAMP_COUNT];
StringValueLookupFn GFXStringTextureStageStateValueLookup[GFXTSS_COUNT];
//------------------------------------------------------------------------------
const char *defaultStringValueLookup( const U32 &value )
{
static char retbuffer[256];
dSprintf( retbuffer, sizeof( retbuffer ), "%d", value );
return retbuffer;
}
#define _STRING_VALUE_LOOKUP_FXN( table ) \
const char * table##_lookup( const U32 &value ) { return table[value]; }
_STRING_VALUE_LOOKUP_FXN(GFXStringTextureAddress);
_STRING_VALUE_LOOKUP_FXN(GFXStringTextureFilter);
_STRING_VALUE_LOOKUP_FXN(GFXStringBlend);
_STRING_VALUE_LOOKUP_FXN(GFXStringTextureOp);
_STRING_VALUE_LOOKUP_FXN(GFXStringCmpFunc);
_STRING_VALUE_LOOKUP_FXN(GFXStringStencilOp);
_STRING_VALUE_LOOKUP_FXN(GFXStringCullMode);
_STRING_VALUE_LOOKUP_FXN(GFXStringBlendOp);
//------------------------------------------------------------------------------
#define INIT_LOOKUPTABLE( tablearray, enumprefix, type ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
tablearray[i] = (type)GFX_UNINIT_VAL;
#define INIT_LOOKUPTABLE_EX( tablearray, enumprefix, type, typeTable ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
{\
tablearray[i] = (type)GFX_UNINIT_VAL;\
typeTable[i] = &defaultStringValueLookup;\
}
#define VALIDATE_LOOKUPTABLE( tablearray, enumprefix ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
if( (int)tablearray[i] == GFX_UNINIT_VAL ) \
Con::warnf( "GFXStringEnumTranslate: Unassigned value in " #tablearray ": %i", i ); \
else if( (int)tablearray[i] == GFX_UNSUPPORTED_VAL ) \
Con::warnf( "GFXStringEnumTranslate: Unsupported value in " #tablearray ": %i", i );
//------------------------------------------------------------------------------
#define GFX_STRING_ASSIGN_MACRO( table, indexEnum ) table[indexEnum] = #indexEnum;
#define GFX_STRING_ASSIGN_MACRO_EX( table, indexEnum, typeTable ) table[indexEnum] = #indexEnum; table##ValueLookup[indexEnum] = &typeTable##_lookup;
void GFXStringEnumTranslate::init()
{
static bool sInitCalled = false;
if( sInitCalled )
return;
sInitCalled = true;
INIT_LOOKUPTABLE( GFXStringIndexFormat, GFXIndexFormat, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringIndexFormat, GFXIndexFormat16 );
GFX_STRING_ASSIGN_MACRO( GFXStringIndexFormat, GFXIndexFormat32 );
VALIDATE_LOOKUPTABLE( GFXStringIndexFormat, GFXIndexFormat );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE_EX( GFXStringSamplerState, GFXSAMP, const char *, GFXStringSamplerStateValueLookup );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringSamplerState, GFXSAMPAddressU, GFXStringTextureAddress );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringSamplerState, GFXSAMPAddressV, GFXStringTextureAddress );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringSamplerState, GFXSAMPAddressW, GFXStringTextureAddress );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPBorderColor );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringSamplerState, GFXSAMPMagFilter, GFXStringTextureFilter );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringSamplerState, GFXSAMPMinFilter, GFXStringTextureFilter );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringSamplerState, GFXSAMPMipFilter, GFXStringTextureFilter );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPMipMapLODBias );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPMaxMipLevel );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPMaxAnisotropy );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPSRGBTexture );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPElementIndex );
GFX_STRING_ASSIGN_MACRO( GFXStringSamplerState, GFXSAMPDMapOffset );
VALIDATE_LOOKUPTABLE( GFXStringSamplerState, GFXSAMP );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringTextureFormat, GFXFormat, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR8G8B8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR8G8B8A8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR8G8B8X8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR32F );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR5G6B5 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR5G5B5A1 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR5G5B5X1 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatA4L4 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatA8L8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatA8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatL8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatDXT1 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatDXT2 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatDXT3 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatDXT4 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatDXT5 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatD32 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatD24X8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatD24S8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatD24FS8 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatD16 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR32G32B32A32F );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR16G16B16A16F );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatL16 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR16G16B16A16 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR16G16 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR16F );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR16G16F );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR10G10B10A2 );
VALIDATE_LOOKUPTABLE( GFXStringTextureFormat, GFXFormat);
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE_EX( GFXStringRenderState, GFXRenderState, const char *, GFXStringRenderStateValueLookup );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSZEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFillMode );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSZWriteEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAlphaTestEnable );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSSrcBlend, GFXStringBlend );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSDestBlend, GFXStringBlend );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSCullMode, GFXStringCullMode );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSZFunc, GFXStringCmpFunc );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAlphaRef );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSAlphaFunc, GFXStringCmpFunc );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAlphaBlendEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSStencilEnable );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSStencilFail, GFXStringStencilOp );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSStencilZFail, GFXStringStencilOp );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSStencilPass, GFXStringStencilOp );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSStencilFunc, GFXStringCmpFunc );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSStencilRef );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSStencilMask );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSStencilWriteMask );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap0 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap1 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap2 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap3 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap4 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap5 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap6 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap7 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSClipPlaneEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointSize );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointSizeMin );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointSize_Max );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointSpriteEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSMultiSampleantiAlias );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSMultiSampleMask );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSShadeMode );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSLastPixel );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSClipping );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointScaleEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointScale_A );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointScale_B );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPointScale_C );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSLighting );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAmbient );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogVertexMode );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSColorVertex );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSLocalViewer );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSNormalizeNormals );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSDiffuseMaterialSource );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSSpecularMaterialSource );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAmbientMaterialSource );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSEmissiveMaterialSource );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSVertexBlend );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSSpecularEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogColor );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogTableMode );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogStart );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogEnd );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSFogDensity );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSRangeFogEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSDebugMonitorToken );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSIndexedVertexBlendEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSTweenFactor );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSTextureFactor );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPatchEdgeStyle );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSDitherEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSColorWriteEnable );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSBlendOp, GFXStringBlendOp );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSPositionDegree );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSNormalDegree );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAntiAliasedLineEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAdaptiveTess_X );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAdaptiveTess_Y );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSdaptiveTess_Z );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSAdaptiveTess_W );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSEnableAdaptiveTesselation );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSScissorTestEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSSlopeScaleDepthBias );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSMinTessellationLevel );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSMaxTessellationLevel );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSTwoSidedStencilMode );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSCCWStencilFail );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSCCWStencilZFail );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSCCWStencilPass );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSCCWStencilFunc );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSColorWriteEnable1 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSColorWriteEnable2 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSolorWriteEnable3 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSBlendFactor );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSSRGBWriteEnable );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSDepthBias );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap8 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap9 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap10 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap11 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap12 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap13 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap14 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSWrap15 );
GFX_STRING_ASSIGN_MACRO( GFXStringRenderState, GFXRSSeparateAlphaBlendEnable );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSSrcBlendAlpha, GFXStringBlend );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSDestBlendAlpha, GFXStringBlend );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringRenderState, GFXRSBlendOpAlpha, GFXStringBlendOp );
VALIDATE_LOOKUPTABLE( GFXStringRenderState, GFXRenderState );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringTextureFilter, GFXTextureFilter, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFilter, GFXTextureFilterNone );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFilter, GFXTextureFilterPoint );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFilter, GFXTextureFilterLinear );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFilter, GFXTextureFilterAnisotropic );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFilter, GFXTextureFilterPyramidalQuad );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFilter, GFXTextureFilterGaussianQuad );
VALIDATE_LOOKUPTABLE( GFXStringTextureFilter, GFXTextureFilter );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringBlend, GFXBlend, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendZero );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendOne );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendSrcColor );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendInvSrcColor );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendSrcAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendInvSrcAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendDestAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendInvDestAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendDestColor );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendInvDestColor );
GFX_STRING_ASSIGN_MACRO( GFXStringBlend, GFXBlendSrcAlphaSat );
VALIDATE_LOOKUPTABLE( GFXStringBlend, GFXBlend );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringBlendOp, GFXBlendOp, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringBlendOp, GFXBlendOpAdd );
GFX_STRING_ASSIGN_MACRO( GFXStringBlendOp, GFXBlendOpSubtract );
GFX_STRING_ASSIGN_MACRO( GFXStringBlendOp, GFXBlendOpRevSubtract );
GFX_STRING_ASSIGN_MACRO( GFXStringBlendOp, GFXBlendOpMin );
GFX_STRING_ASSIGN_MACRO( GFXStringBlendOp, GFXBlendOpMax );
VALIDATE_LOOKUPTABLE( GFXStringBlendOp, GFXBlendOp );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringStencilOp, GFXStencilOp, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpKeep );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpZero );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpReplace );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpIncrSat );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpDecrSat );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpInvert );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpIncr );
GFX_STRING_ASSIGN_MACRO( GFXStringStencilOp, GFXStencilOpDecr );
VALIDATE_LOOKUPTABLE( GFXStringStencilOp, GFXStencilOp );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringCmpFunc, GFXCmp, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpNever );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpLess );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpEqual );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpLessEqual );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpGreater );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpNotEqual );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpGreaterEqual );
GFX_STRING_ASSIGN_MACRO( GFXStringCmpFunc, GFXCmpAlways );
VALIDATE_LOOKUPTABLE( GFXStringCmpFunc, GFXCmp );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringCullMode, GFXCull, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringCullMode, GFXCullNone );
GFX_STRING_ASSIGN_MACRO( GFXStringCullMode, GFXCullCW );
GFX_STRING_ASSIGN_MACRO( GFXStringCullMode, GFXCullCCW );
VALIDATE_LOOKUPTABLE( GFXStringCullMode, GFXCull );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringPrimType, GFXPT, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringPrimType, GFXPointList );
GFX_STRING_ASSIGN_MACRO( GFXStringPrimType, GFXLineList );
GFX_STRING_ASSIGN_MACRO( GFXStringPrimType, GFXLineStrip );
GFX_STRING_ASSIGN_MACRO( GFXStringPrimType, GFXTriangleList );
GFX_STRING_ASSIGN_MACRO( GFXStringPrimType, GFXTriangleStrip );
GFX_STRING_ASSIGN_MACRO( GFXStringPrimType, GFXTriangleFan );
VALIDATE_LOOKUPTABLE( GFXStringPrimType, GFXPT );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE_EX( GFXStringTextureStageState, GFXTSS, const char *, GFXStringTextureStageStateValueLookup );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringTextureStageState, GFXTSSColorOp, GFXStringTextureOp );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSColorArg1 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSColorArg2 );
GFX_STRING_ASSIGN_MACRO_EX( GFXStringTextureStageState, GFXTSSAlphaOp, GFXStringTextureOp );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSAlphaArg1 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSAlphaArg2 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSBumpEnvMat00 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSBumpEnvMat01 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSBumpEnvMat10 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSBumpEnvMat11 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSTexCoordIndex );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSBumpEnvlScale );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSBumpEnvlOffset );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSTextureTransformFlags );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSColorArg0 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSAlphaArg0 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSResultArg );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureStageState, GFXTSSConstant );
VALIDATE_LOOKUPTABLE( GFXStringTextureStageState, GFXTSS );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringTextureAddress, GFXAddress, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureAddress, GFXAddressWrap );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureAddress, GFXAddressMirror );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureAddress, GFXAddressClamp );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureAddress, GFXAddressBorder );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureAddress, GFXAddressMirrorOnce );
VALIDATE_LOOKUPTABLE(GFXStringTextureAddress, GFXAddress );
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
INIT_LOOKUPTABLE( GFXStringTextureOp, GFXTOP, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPDisable );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPSelectARG1 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPSelectARG2 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulate );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulate2X );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulate4X );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPAdd );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPAddSigned );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPAddSigned2X );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPSubtract );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPAddSmooth );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBlendDiffuseAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBlendTextureAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBlendFactorAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBlendTextureAlphaPM );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBlendCURRENTALPHA );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPPreModulate );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulateAlphaAddColor );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulateColorAddAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulateInvAlphaAddColor );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPModulateInvColorAddAlpha );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBumpEnvMap );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPBumpEnvMapLuminance );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPDotProduct3 );
GFX_STRING_ASSIGN_MACRO( GFXStringTextureOp, GFXTOPLERP );
VALIDATE_LOOKUPTABLE( GFXStringTextureOp, GFXTOP );
INIT_LOOKUPTABLE( GFXStringFillMode, GFXFill, const char * );
GFX_STRING_ASSIGN_MACRO( GFXStringFillMode, GFXFillPoint );
GFX_STRING_ASSIGN_MACRO( GFXStringFillMode, GFXFillWireframe );
GFX_STRING_ASSIGN_MACRO( GFXStringFillMode, GFXFillSolid );
VALIDATE_LOOKUPTABLE( GFXStringFillMode, GFXFill );
}

View file

@ -0,0 +1,89 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXSTRINGENUMTRANSLATE_H_
#define _GFXSTRINGENUMTRANSLATE_H_
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _CONSOLE_H_
#include "console/console.h"
#endif
#ifndef _DYNAMIC_CONSOLETYPES_H_
#include "console/dynamicTypes.h"
#endif
#ifndef _GFXAPI_H_
#include "gfx/gfxAPI.h"
#endif
//------------------------------------------------------------------------------
namespace GFXStringEnumTranslate
{
void init();
};
//------------------------------------------------------------------------------
extern const char *GFXStringIndexFormat[GFXIndexFormat_COUNT];
extern const char *GFXStringSamplerState[GFXSAMP_COUNT];
extern const char *GFXStringTextureFormat[GFXFormat_COUNT];
extern const char *GFXStringRenderState[GFXRenderState_COUNT];
extern const char *GFXStringTextureFilter[GFXTextureFilter_COUNT];
extern const char *GFXStringBlend[GFXBlend_COUNT];
extern const char *GFXStringBlendOp[GFXBlendOp_COUNT];
extern const char *GFXStringStencilOp[GFXStencilOp_COUNT];
extern const char *GFXStringCmpFunc[GFXCmp_COUNT];
extern const char *GFXStringCullMode[GFXCull_COUNT];
extern const char *GFXStringPrimType[GFXPT_COUNT];
extern const char *GFXStringTextureStageState[GFXTSS_COUNT];
extern const char *GFXStringTextureAddress[GFXAddress_COUNT];
extern const char *GFXStringTextureOp[GFXTOP_COUNT];
extern const char *GFXStringFillMode[GFXFill_COUNT];
typedef const char *(*StringValueLookupFn)( const U32 &value );
extern StringValueLookupFn GFXStringRenderStateValueLookup[GFXRenderState_COUNT];
extern StringValueLookupFn GFXStringSamplerStateValueLookup[GFXSAMP_COUNT];
extern StringValueLookupFn GFXStringTextureStageStateValueLookup[GFXTSS_COUNT];
#define GFXREVERSE_LOOKUP( tablearray, enumprefix, val ) \
for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \
if( (int)tablearray##[i] == val ) \
{ \
val = i; \
break; \
} \
// TODOS!
extern EnumTable gTextureArgumentEnumTable_M;
//extern EnumTable srcBlendFactorTable;
//extern EnumTable dstBlendFactorTable;
//extern EnumTable::Enums srcBlendFactorLookup[9];
//extern EnumTable::Enums dstBlendFactorLookup[9];
#endif

View file

@ -0,0 +1,79 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxDevice.h"
GFXVideoMode::GFXVideoMode()
{
bitDepth = 32;
fullScreen = false;
refreshRate = 60;
wideScreen = false;
resolution.set(800,600);
antialiasLevel = 0;
}
void GFXVideoMode::parseFromString( const char *str )
{
if(!str)
return;
// Copy the string, as dStrtok is destructive
char *tempBuf = new char[dStrlen( str ) + 1];
dStrcpy( tempBuf, str );
#define PARSE_ELEM(type, var, func, tokParam, sep) \
if(const char *ptr = dStrtok( tokParam, sep)) \
{ type tmp = func(ptr); if(tmp > 0) var = tmp; }
PARSE_ELEM(S32, resolution.x, dAtoi, tempBuf, " x\0")
PARSE_ELEM(S32, resolution.y, dAtoi, NULL, " x\0")
PARSE_ELEM(S32, fullScreen, dAtob, NULL, " \0")
PARSE_ELEM(S32, bitDepth, dAtoi, NULL, " \0")
PARSE_ELEM(S32, refreshRate, dAtoi, NULL, " \0")
PARSE_ELEM(S32, antialiasLevel, dAtoi, NULL, " \0")
#undef PARSE_ELEM
delete [] tempBuf;
}
const String GFXVideoMode::toString() const
{
return String::ToString("%d %d %s %d %d %d", resolution.x, resolution.y, (fullScreen ? "true" : "false"), bitDepth, refreshRate, antialiasLevel);
}
void GFXShaderMacro::stringize( const Vector<GFXShaderMacro> &macros, String *outString )
{
Vector<GFXShaderMacro>::const_iterator itr = macros.begin();
for ( ; itr != macros.end(); itr++ )
{
(*outString) += itr->name;
if ( itr->value.isNotEmpty() )
{
(*outString) += "=";
(*outString) += itr->value;
}
(*outString) += ";";
}
}

View file

@ -0,0 +1,194 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXSTRUCTS_H_
#define _GFXSTRUCTS_H_
#ifndef _COLOR_H_
#include "core/color.h"
#endif
#ifndef _GFXVERTEXCOLOR_H_
#include "gfx/gfxVertexColor.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _MMATH_H_
#include "math/mMath.h"
#endif
#ifndef _PROFILER_H_
#include "platform/profiler.h"
#endif
#ifndef _GFXRESOURCE_H_
#include "gfx/gfxResource.h"
#endif
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#ifndef _GFXVERTEXTYPES_H_
#include "gfx/gfxVertexTypes.h"
#endif
//-----------------------------------------------------------------------------
// This class is used to interact with an API's fixed function lights. See GFX->setLight
class GFXLightInfo
{
public:
enum Type {
Point = 0,
Spot = 1,
Vector = 2,
Ambient = 3,
};
Type mType;
Point3F mPos;
VectorF mDirection;
ColorF mColor;
ColorF mAmbient;
F32 mRadius;
F32 mInnerConeAngle;
F32 mOuterConeAngle;
/// @todo Revisit below (currently unused by fixed function lights)
Point3F position;
ColorF ambient;
ColorF diffuse;
ColorF specular;
VectorF spotDirection;
F32 spotExponent;
F32 spotCutoff;
F32 constantAttenuation;
F32 linearAttenuation;
F32 quadraticAttenuation;
};
//-----------------------------------------------------------------------------
// Material definition for FF lighting
struct GFXLightMaterial
{
ColorF ambient;
ColorF diffuse;
ColorF specular;
ColorF emissive;
F32 shininess;
};
//-----------------------------------------------------------------------------
struct GFXVideoMode
{
GFXVideoMode();
Point2I resolution;
U32 bitDepth;
U32 refreshRate;
bool fullScreen;
bool wideScreen;
// When this is returned from GFX, it's the max, otherwise it's the desired AA level.
U32 antialiasLevel;
inline bool operator == ( const GFXVideoMode &otherMode ) const
{
if( otherMode.fullScreen != fullScreen )
return false;
if( otherMode.resolution != resolution )
return false;
if( otherMode.bitDepth != bitDepth )
return false;
if( otherMode.refreshRate != refreshRate )
return false;
if( otherMode.wideScreen != wideScreen )
return false;
if( otherMode.antialiasLevel != antialiasLevel)
return false;
return true;
}
inline bool operator !=( const GFXVideoMode& otherMode ) const
{
return !( *this == otherMode );
}
/// Fill whatever fields we can from the passed string, which should be
/// of form "width height [bitDepth [refreshRate] [antialiasLevel]]" Unspecified fields
/// aren't modified, so you may want to set defaults before parsing.
void parseFromString( const char *str );
/// Gets a string representation of the object as
/// "resolution.x resolution.y fullScreen bitDepth refreshRate antialiasLevel"
///
/// \return (string) A string representation of the object.
const String toString() const;
};
//-----------------------------------------------------------------------------
struct GFXPrimitive
{
GFXPrimitiveType type;
U32 startVertex; /// offset into vertex buffer to change where vertex[0] is
U32 minIndex; /// minimal value we will see in the indices
U32 startIndex; /// start of indices in buffer
U32 numPrimitives; /// how many prims to render
U32 numVertices; /// how many vertices... (used for locking, we lock from minIndex to minIndex + numVertices)
GFXPrimitive()
{
dMemset( this, 0, sizeof( GFXPrimitive ) );
}
};
/// Passed to GFX for shader defines.
struct GFXShaderMacro
{
GFXShaderMacro() {}
GFXShaderMacro( const GFXShaderMacro &macro )
: name( macro.name ),
value( macro.value )
{}
GFXShaderMacro( const String &name_,
const String &value_ = String::EmptyString )
: name( name_ ),
value( value_ )
{}
~GFXShaderMacro() {}
/// The macro name.
String name;
/// The optional macro value.
String value;
static void stringize( const Vector<GFXShaderMacro> &macros, String *outString );
};
#endif // _GFXSTRUCTS_H_

View file

@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
// 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 "gfx/gfxTarget.h"
#include "console/console.h"
GFXTextureObject *GFXTextureTarget::sDefaultDepthStencil = reinterpret_cast<GFXTextureObject *>( 0x1 );
const String GFXTarget::describeSelf() const
{
return String();
}

View file

@ -0,0 +1,207 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXTARGET_H_
#define _GFXTARGET_H_
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _GFXRESOURCE_H_
#include "gfx/gfxResource.h"
#endif
#ifndef _MPOINT3_H_
#include "math/mPoint3.h"
#endif
class Point2I;
class PlatformWindow;
class GFXCubemap;
class GFXTextureObject;
/// Base class for a target to which GFX can render.
///
/// Most modern graphics hardware supports selecting render targets. However,
/// there may be multiple types of render target, with wildly varying
/// device-level implementations, resource requirements, and so forth.
///
/// This base class is used to represent a render target; it might be a context
/// tied to a window, or a set of surfaces or textures.
class GFXTarget : public StrongRefBase, public GFXResource
{
friend class GFXD3D9Device;
friend class GFX360Device;
private:
S32 mChangeToken;
S32 mLastAppliedChange;
protected:
/// Called whenever a change is made to this target.
inline void invalidateState()
{
mChangeToken++;
}
/// Called when the device has applied pending state.
inline void stateApplied()
{
mLastAppliedChange = mChangeToken;
}
public:
/// Constructor to initialize the state tracking logic.
GFXTarget() : mChangeToken( 0 ),
mLastAppliedChange( 0 )
{
}
virtual ~GFXTarget() {}
/// Called to check if we have pending state for the device to apply.
inline const bool isPendingState() const
{
return (mChangeToken != mLastAppliedChange);
}
/// Returns the size in pixels of the render target.
virtual const Point2I getSize()=0;
/// Returns the texture format of the render target.
virtual GFXFormat getFormat()=0;
// GFXResourceInterface
/// The resource should put a description of itself (number of vertices, size/width of texture, etc.) in buffer
virtual const String describeSelf() const;
/// This is called to set the render target.
virtual void activate() { }
/// This is called when the target is not being used anymore.
virtual void deactivate() { }
/// This tells the target that the contents of this target should be restored
/// when activate() is next called.
virtual void preserve() { }
/// Copy this surface to the passed GFXTextureObject.
/// @param tex The GFXTextureObject to copy to.
virtual void resolveTo( GFXTextureObject *tex ) { }
};
/// A render target associated with an OS window.
///
/// Various API/OS combinations will implement their own GFXTargets for
/// rendering to a window. However, they are all subclasses of GFXWindowTarget.
///
/// This allows platform-neutral code to safely distinguish between various
/// types of render targets (using dynamic_cast<>), as well as letting it
/// gain access to useful things like the corresponding PlatformWindow.
class GFXWindowTarget : public GFXTarget
{
protected:
PlatformWindow *mWindow;
public:
GFXWindowTarget() : mWindow(NULL){};
GFXWindowTarget( PlatformWindow *windowObject )
{
mWindow = windowObject;
}
virtual ~GFXWindowTarget() {}
/// Returns a pointer to the window this target is bound to.
inline PlatformWindow *getWindow() { return mWindow; };
/// Present latest buffer, if buffer swapping is in effect.
virtual bool present()=0;
/// Notify the target that the video mode on the window has changed.
virtual void resetMode()=0;
};
/// A render target associated with one or more textures.
///
/// Although some APIs allow directly selecting any texture or surfaces, in
/// some cases it is necessary to allocate helper resources to enable RTT
/// operations.
///
/// @note A GFXTextureTarget will retain references to textures that are
/// attached to it, so be sure to clear them out when you're done!
///
/// @note Different APIs have different restrictions on what they can support
/// here. Be aware when mixing cubemaps vs. non-cubemaps, or targets of
/// different resolutions. The devices will attempt to limit behavior
/// to things that are safely portable, but they cannot catch every
/// possible situation for all drivers and API - so make sure to
/// actually test things!
class GFXTextureTarget : public GFXTarget
{
public:
enum RenderSlot
{
DepthStencil,
Color0, Color1, Color2, Color3, Color4,
MaxRenderSlotId,
};
static GFXTextureObject *sDefaultDepthStencil;
virtual ~GFXTextureTarget() {}
/// Attach a surface to a given slot as part of this render target.
///
/// @param slot What slot is used for multiple render target (MRT) effects.
/// Most of the time you'll use Color0.
/// @param tex A texture and miplevel to bind for rendering, or else NULL/0
/// to clear a slot.
/// @param mipLevel What level of this texture are we rendering to?
/// @param zOffset If this is a depth texture, what z level are we
/// rendering to?
virtual void attachTexture(RenderSlot slot, GFXTextureObject *tex, U32 mipLevel=0, U32 zOffset = 0) = 0;
/// Support binding to cubemaps.
///
/// @param slot What slot is used for multiple render target (MRT) effects.
/// Most of the time you'll use Color0.
/// @param tex What cubemap will we be rendering to?
/// @param face A face identifier.
/// @param mipLevel What level of this texture are we rendering to?
virtual void attachTexture(RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel=0) = 0;
/// Resolve the current render target data to the associated textures. This method
/// will get called automatically when a rendertarget is changed, before new geometry
/// is drawn to a different rendertarget. This method can also be called to
/// gather render target data without switching targets.
///
/// By default, this method will resolve all color targets.
virtual void resolve()=0;
};
typedef StrongRefPtr<GFXTarget> GFXTargetRef;
typedef StrongRefPtr<GFXWindowTarget> GFXWindowTargetRef;
typedef StrongRefPtr<GFXTextureTarget> GFXTextureTargetRef;
#endif // _GFXTARGET_H_

View file

@ -0,0 +1,161 @@
//-----------------------------------------------------------------------------
// 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/gfxTextureHandle.h"
#include "gfx/gfxDevice.h"
#include "gfx/gfxTextureManager.h"
GFXTexHandle GFXTexHandle::ZERO;
GFXTexHandle GFXTexHandle::ONE;
GFXTexHandle GFXTexHandle::ZUP;
GFXTexHandle::GFXTexHandle( GFXTextureObject *obj )
{
StrongObjectRef::set( obj );
}
GFXTexHandle::GFXTexHandle( const GFXTexHandle &handle, const String &desc )
{
StrongObjectRef::set( handle.getPointer() );
#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif
}
GFXTexHandle::GFXTexHandle( const String &texName, GFXTextureProfile *profile, const String &desc )
{
set( texName, profile, desc );
}
bool GFXTexHandle::set( const String &texName, GFXTextureProfile *profile, const String &desc )
{
// Clear the existing texture first, so that
// its memory is free for the new allocation.
free();
// Create and set the new texture.
AssertFatal( texName.isNotEmpty(), "Texture name is empty" );
StrongObjectRef::set( TEXMGR->createTexture( texName, profile ) );
#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif
return isValid();
}
GFXTexHandle::GFXTexHandle( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc )
{
set( bmp, profile, deleteBmp, desc );
}
bool GFXTexHandle::set( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc )
{
// Clear the existing texture first, so that
// its memory is free for the new allocation.
free();
// Create and set the new texture.
AssertFatal( bmp, "Bitmap is NULL" );
StrongObjectRef::set( TEXMGR->createTexture( bmp, String(), profile, deleteBmp ) );
#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif
return isValid();
}
GFXTexHandle::GFXTexHandle( DDSFile *dds, GFXTextureProfile *profile, bool deleteDDS, const String &desc )
{
set( dds, profile, deleteDDS, desc );
}
bool GFXTexHandle::set( DDSFile *dds, GFXTextureProfile *profile, bool deleteDDS, const String &desc )
{
// Clear the existing texture first, so that
// its memory is free for the new allocation.
free();
// Create and set the new texture.
AssertFatal( dds, "Bitmap is NULL" );
StrongObjectRef::set( TEXMGR->createTexture( dds, profile, deleteDDS ) );
#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif
return isValid();
}
GFXTexHandle::GFXTexHandle( U32 width, U32 height, GFXFormat format, GFXTextureProfile *profile, const String &desc, U32 numMipLevels, S32 antialiasLevel)
{
set( width, height, format, profile, desc, numMipLevels, antialiasLevel );
}
bool GFXTexHandle::set( U32 width, U32 height, GFXFormat format, GFXTextureProfile *profile, const String &desc, U32 numMipLevels, S32 antialiasLevel)
{
// Clear the existing texture first, so that
// its memory is free for the new allocation.
free();
// Create and set the new texture.
StrongObjectRef::set( TEXMGR->createTexture( width, height, format, profile, numMipLevels, antialiasLevel ) );
#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif
return isValid();
}
bool GFXTexHandle::set( U32 width, U32 height, U32 depth, void *pixels, GFXFormat format, GFXTextureProfile *profile, const String &desc, U32 numMipLevels )
{
// Clear the existing texture first, so that
// its memory is free for the new allocation.
free();
// Create and set the new texture.
StrongObjectRef::set( TEXMGR->createTexture( width, height, depth, pixels, format, profile ) );
#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif
return isValid();
}
void GFXTexHandle::refresh()
{
TEXMGR->reloadTexture( getPointer() );
}

View file

@ -0,0 +1,129 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXTEXTUREHANDLE_H_
#define _GFXTEXTUREHANDLE_H_
#ifndef _GFXTEXTUREOBJECT_H_
#include "gfx/gfxTextureObject.h"
#endif
#ifndef _MPOINT2_H_
#include "math/mPoint2.h"
#endif
class GFXTextureProfile;
/// A reference counted handle to a texture resource.
class GFXTexHandle : public StrongRefPtr<GFXTextureObject>
{
public:
GFXTexHandle() {}
GFXTexHandle( GFXTextureObject* obj );
GFXTexHandle( const GFXTexHandle &handle, const String &desc );
// load texture
GFXTexHandle( const String &texName, GFXTextureProfile *profile, const String &desc );
bool set( const String &texName, GFXTextureProfile *profile, const String &desc );
// register texture
GFXTexHandle( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc );
bool set( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc );
GFXTexHandle( DDSFile *bmp, GFXTextureProfile *profile, bool deleteDDS, const String &desc );
bool set( DDSFile *bmp, GFXTextureProfile *profile, bool deleteDDS, const String &desc );
// Sized bitmap
GFXTexHandle( U32 width, U32 height, GFXFormat format, GFXTextureProfile *profile, const String &desc, U32 numMipLevels = 1, S32 antialiasLevel = 0);
bool set( U32 width, U32 height, GFXFormat format, GFXTextureProfile *profile, const String &desc, U32 numMipLevels = 1, S32 antialiasLevel = 0);
bool set( U32 width, U32 height, U32 depth, void *pixels, GFXFormat format, GFXTextureProfile *profile, const String &desc, U32 numMipLevels = 1 );
/// Returns the width and height as a point.
Point2I getWidthHeight() const { return getPointer() ? Point2I( getPointer()->getWidth(), getPointer()->getHeight() ) : Point2I::Zero; }
U32 getWidth() const { return getPointer() ? getPointer()->getWidth() : 0; }
U32 getHeight() const { return getPointer() ? getPointer()->getHeight() : 0; }
U32 getDepth() const { return getPointer() ? getPointer()->getDepth() : 0; }
GFXFormat getFormat() const { return getPointer() ? getPointer()->getFormat() : GFXFormat_COUNT; }
/// Reloads the texture.
/// @see GFXTextureManager::reloadTexture
void refresh();
/// Releases the texture handle.
void free() { StrongObjectRef::set( NULL ); }
GFXLockedRect *lock( U32 mipLevel = 0, RectI *inRect = NULL )
{
return getPointer()->lock(mipLevel, inRect);
}
void unlock( U32 mipLevel = 0)
{
getPointer()->unlock(mipLevel);
}
// copy to bitmap. see gfxTetureObject.h for description of what types of textures
// can be copied into bitmaps. returns true if successful, false otherwise
bool copyToBmp(GBitmap* bmp) { return getPointer() ? getPointer()->copyToBmp(bmp) : false; }
//---------------------------------------------------------------------------
// Operator overloads
//---------------------------------------------------------------------------
GFXTexHandle& operator=(const GFXTexHandle &t)
{
StrongObjectRef::set(t.getPointer());
return *this;
}
GFXTexHandle& operator=( GFXTextureObject *to)
{
StrongObjectRef::set(to);
return *this;
}
bool operator==(const GFXTexHandle &t) const { return t.getPointer() == getPointer(); }
bool operator!=(const GFXTexHandle &t) const { return t.getPointer() != getPointer(); }
/// Returns the texture object.
operator GFXTextureObject*() const { return getPointer(); }
/// Returns the backing bitmap for this texture.
GBitmap* getBitmap() { return getPointer() ? getPointer()->getBitmap() : NULL; }
const GBitmap* getBitmap() const { return getPointer() ? getPointer()->getBitmap() : NULL; }
/// Helper 2x2 R8G8B8A8 texture filled with 0.
static GFXTexHandle ZERO;
/// Helper 2x2 R8G8B8A8 texture filled with 255.
static GFXTexHandle ONE;
/// Helper 2x2 R8G8B8A8 normal map texture filled
/// with 128, 128, 255.
static GFXTexHandle ZUP;
};
#endif // _GFXTEXTUREHANDLE_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,348 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _GFXTEXTUREMANAGER_H_
#define _GFXTEXTUREMANAGER_H_
#ifndef _GFXTEXTUREOBJECT_H_
#include "gfx/gfxTextureObject.h"
#endif
#ifndef _GBITMAP_H_
#include "gfx/bitmap/gBitmap.h"
#endif
#ifndef _DDSFILE_H_
#include "gfx/bitmap/ddsFile.h"
#endif
#ifndef _RESOURCEMANAGER_H_
#include "core/resourceManager.h"
#endif
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#ifndef _TSIGNAL_H_
#include "core/util/tSignal.h"
#endif
namespace Torque
{
class Path;
}
class GFXCubemap;
class GFXTextureManager
{
public:
enum
{
AA_MATCH_BACKBUFFER = -1
};
GFXTextureManager();
virtual ~GFXTextureManager();
/// Set up some global script interface stuff.
static void init();
/// Update width and height based on available resources.
///
/// We provide a simple interface for managing texture memory usage. Specifically,
/// if the total video memory is below a certain threshold, we scale all texture
/// resolutions down by a specific factor (you can specify different scale factors
/// for different types of textures).
///
/// @note The base GFXTextureManager class provides all the logic to do this scaling.
/// Subclasses need only implement getTotalVideoMemory().
///
/// @param type Type of the requested texture. This is used to determine scaling factors.
/// @param width Requested width - is changed to the actual width that should be used.
/// @param height Requested height - is changed to the actual height that should be used.
/// @return True if the texture request should be granted, false otherwise.
virtual bool validateTextureQuality(GFXTextureProfile *profile, U32 &width, U32 &height);
///
static U32 getTextureDownscalePower( GFXTextureProfile *profile );
virtual GFXTextureObject *createTexture( GBitmap *bmp,
const String &resourceName,
GFXTextureProfile *profile,
bool deleteBmp);
virtual GFXTextureObject *createTexture( DDSFile *dds,
GFXTextureProfile *profile,
bool deleteDDS);
virtual GFXTextureObject *createTexture( const Torque::Path &path,
GFXTextureProfile *profile );
virtual GFXTextureObject *createTexture( U32 width,
U32 height,
void *pixels,
GFXFormat format,
GFXTextureProfile *profile);
virtual GFXTextureObject *createTexture( U32 width,
U32 height,
U32 depth,
void *pixels,
GFXFormat format,
GFXTextureProfile *profile );
virtual GFXTextureObject *createTexture( U32 width,
U32 height,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
S32 antialiasLevel);
void deleteTexture( GFXTextureObject *texture );
void reloadTexture( GFXTextureObject *texture );
/// Request that the texture be deleted which will
/// either occur immediately or delayed if its cached.
void requestDeleteTexture( GFXTextureObject *texture );
/// @name Texture Necromancy
///
/// Texture necromancy in three easy steps:
/// - If you want to destroy the texture manager, call kill().
/// - If you want to switch resolutions, or otherwise reset the device, call zombify().
/// - When you want to bring the manager back from zombie state, call resurrect().
/// @{
///
void kill();
void zombify();
void resurrect();
/// This releases any pooled textures which are
/// currently unused freeing up video memory.
void cleanupPool();
///
void reloadTextures();
/// This releases cached textures that have not
/// been referenced for a period of time.
void cleanupCache( U32 secondsToLive = 0 );
/// Registers a callback for texture zombify and resurrect events.
/// @see GFXTexCallbackCode
/// @see removeEventDelegate
template <class T,class U>
static void addEventDelegate( T obj, U func );
/// Unregisteres a texture event callback.
/// @see addEventDelegate
template <class T,class U>
static void removeEventDelegate( T obj, U func ) { smEventSignal.remove( obj, func ); }
/// @}
/// Load a cubemap from a texture file.
GFXCubemap* createCubemap( const Torque::Path &path );
/// Used to remove a cubemap from the cache.
void releaseCubemap( GFXCubemap *cubemap );
protected:
/// The amount of texture mipmaps to skip when loading a
/// texture that allows downscaling.
///
/// Exposed to script via $pref::Video::textureReductionLevel.
///
/// @see GFXTextureProfile::PreserveSize
///
static S32 smTextureReductionLevel;
GFXTextureObject *mListHead;
GFXTextureObject *mListTail;
// We have a hash table for fast texture lookups
GFXTextureObject **mHashTable;
U32 mHashCount;
GFXTextureObject *hashFind( const String &name );
void hashInsert(GFXTextureObject *object);
void hashRemove(GFXTextureObject *object);
// The cache of loaded cubemap textures.
typedef HashTable<String,GFXCubemap*> CubemapTable;
CubemapTable mCubemapTable;
/// The textures waiting to be deleted.
Vector<GFXTextureObject*> mToDelete;
enum TextureManagerState
{
Living,
Zombie,
Dead
} mTextureManagerState;
/// The texture pool collection type.
typedef HashTable<GFXTextureProfile*,StrongRefPtr<GFXTextureObject> > TexturePoolMap;
/// All the allocated texture pool textures.
TexturePoolMap mTexturePool;
//-----------------------------------------------------------------------
// Protected methods
//-----------------------------------------------------------------------
/// Returns a free texture of the requested attributes from
/// from the shared texture pool. It returns NULL if no match
/// is found.
GFXTextureObject* _findPooledTexure( U32 width,
U32 height,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
S32 antialiasLevel );
GFXTextureObject *_createTexture( GBitmap *bmp,
const String &resourceName,
GFXTextureProfile *profile,
bool deleteBmp,
GFXTextureObject *inObj );
GFXTextureObject *_createTexture( DDSFile *dds,
GFXTextureProfile *profile,
bool deleteDDS,
GFXTextureObject *inObj );
/// Frees the API handles to the texture, for D3D this is a release call
///
/// @note freeTexture MUST NOT DELETE THE TEXTURE OBJECT
virtual void freeTexture( GFXTextureObject *texture, bool zombify = false );
virtual void refreshTexture( GFXTextureObject *texture );
/// @group Internal Texture Manager Interface
///
/// These pure virtual functions are overloaded by each API-specific
/// subclass.
///
/// The order of calls is:
/// @code
/// _createTexture()
/// _loadTexture
/// _refreshTexture()
/// _refreshTexture()
/// _refreshTexture()
/// ...
/// _freeTexture()
/// @endcode
///
/// @{
/// Allocate a texture with the internal API.
///
/// @param height Height of the texture.
/// @param width Width of the texture.
/// @param depth Depth of the texture. (Will normally be 1 unless
/// we are doing a cubemap or volumetexture.)
/// @param format Pixel format of the texture.
/// @param profile Profile for the texture.
/// @param numMipLevels If not-NULL, then use that many mips.
/// If NULL create the full mip chain
/// @param antialiasLevel, Use GFXTextureManager::AA_MATCH_BACKBUFFER to match the backbuffer settings (for render targets that want to share
/// the backbuffer z buffer. 0 for no antialiasing, > 0 for levels that match the GFXVideoMode struct.
virtual GFXTextureObject *_createTextureObject( U32 height,
U32 width,
U32 depth,
GFXFormat format,
GFXTextureProfile *profile,
U32 numMipLevels,
bool forceMips = false,
S32 antialiasLevel = 0,
GFXTextureObject *inTex = NULL ) = 0;
/// Load a texture from a proper DDSFile instance.
virtual bool _loadTexture(GFXTextureObject *texture, DDSFile *dds)=0;
/// Load data into a texture from a GBitmap using the internal API.
virtual bool _loadTexture(GFXTextureObject *texture, GBitmap *bmp)=0;
/// Load data into a texture from a raw buffer using the internal API.
///
/// Note that the size of the buffer is assumed from the parameters used
/// for this GFXTextureObject's _createTexture call.
virtual bool _loadTexture(GFXTextureObject *texture, void *raw)=0;
/// Refresh a texture using the internal API.
virtual bool _refreshTexture(GFXTextureObject *texture)=0;
/// Free a texture (but do not delete the GFXTextureObject) using the internal
/// API.
///
/// This is only called during zombification for textures which need it, so you
/// don't need to do any internal safety checks.
virtual bool _freeTexture(GFXTextureObject *texture, bool zombify=false)=0;
/// @}
/// Store texture into the hash table cache and linked list.
void _linkTexture( GFXTextureObject *obj );
/// Validate the parameters for creating a texture.
void _validateTexParams( const U32 width, const U32 height, const GFXTextureProfile *profile,
U32 &inOutNumMips, GFXFormat &inOutFormat );
// New texture manager methods for the cleanup work:
GFXTextureObject *_lookupTexture( const char *filename, const GFXTextureProfile *profile );
GFXTextureObject *_lookupTexture( const DDSFile *ddsFile, const GFXTextureProfile *profile );
void _onFileChanged( const Torque::Path &path );
/// The texture event signal type.
typedef Signal<void(GFXTexCallbackCode code)> EventSignal;
/// The texture event signal.
static EventSignal smEventSignal;
};
template <class T,class U>
inline void GFXTextureManager::addEventDelegate( T obj, U func )
{
EventSignal::DelegateSig d( obj, func );
AssertFatal( !smEventSignal.contains( d ),
"GFXTextureManager::addEventDelegate() - This is already registered!" );
smEventSignal.notify( d );
}
inline void GFXTextureManager::reloadTexture( GFXTextureObject *texture )
{
refreshTexture( texture );
}
/// Returns the GFXTextureManager singleton. Should only be
/// called after the GFX device has been initialized.
#define TEXMGR GFXDevice::get()->getTextureManager()
#endif // _GFXTEXTUREMANAGER_H_

Some files were not shown because too many files have changed in this diff Show more