Torque3D/Engine/source/gfx/D3D9/gfxD3D9Device.h
DavidWyand-GG 0d77cdc270 GFX now handles non-default adapters
The GFX (DirectX) pipeline did not respect the choice of adapter and
always went for the default one.  Normally this isn't an issue unless
you wish to target a particular adapter and display device combination.
This has been corrected.

The GFX initialize functions now attempt to find the best adapter that
matches a given display device (i.e. monitor) if one has been passed in.
To aid with choosing a display device some new monitor enumeration
methods have been added to the platform window manager.  These methods
have been exposed to the Canvas.
2013-04-09 12:50:17 -04:00

359 lines
12 KiB
C++

//-----------------------------------------------------------------------------
// 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; }
U32 getAdaterIndex() const { return mAdapterIndex; }
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_