#include "Gos.pch"
#include "Graphics.h"

IDirect3D8 *		Graphics::s_pD3D = NULL;
IDirect3DDevice8 *	Graphics::s_pD3DDevice = NULL;
HWND				Graphics::s_hWindow = 0;
GosTexture *		Graphics::s_apTexture[c_MaxTextures];
GosVertexBuffer *	Graphics::s_apVertexBuffer[c_MaxStreams];
UINT				Graphics::s_aStreamStride[c_MaxStreams];
GosIndexBuffer *	Graphics::s_pIndexBuffer = NULL;
UINT				Graphics::s_BaseVertexIndex = 0;
GosSurface *		Graphics::s_pRenderTarget = NULL;
GosSurface *		Graphics::s_pZStencil = NULL;
GosSurface *		Graphics::s_pDefaultRenderTarget = NULL;
GosSurface *		Graphics::s_pDefaultDepthStencil = NULL;
GosPixelShader *	Graphics::s_pPixelShader = NULL;
GosVertexShader *	Graphics::s_pVertexShader = NULL;
DWORD				Graphics::s_Left = 0;
DWORD				Graphics::s_Top = 0;
DWORD				Graphics::s_Width = 480;
DWORD				Graphics::s_Height = 640;

D3DPRESENT_PARAMETERS Graphics::s_d3dpp;

bool	(*Gos3D::Initialize)( HWND ) = Graphics::Initialize;
void	(*Gos3D::Shutdown)() = Graphics::Shutdown;
void	(*Gos3D::Done)() = Graphics::Done;
HRESULT	(*Gos3D::SetCursorProperties)( UINT, UINT, GosSurface* ) = Graphics::SetCursorProperties;
void	(*Gos3D::SetCursorPosition)( UINT, UINT, DWORD ) = Graphics::SetCursorPosition;
BOOL	(*Gos3D::ShowCursor)( BOOL ) = Graphics::ShowCursor;
void	(*Gos3D::SetDisplay)(UINT, UINT, D3DFORMAT, bool ) = Graphics::SetDisplay;
DWORD	(*Gos3D::Left)() = Graphics::Left;
DWORD	(*Gos3D::Top)() = Graphics::Top;
DWORD	(*Gos3D::Width)() = Graphics::Width;
DWORD	(*Gos3D::Height)() = Graphics::Height;
void	(*Gos3D::SetGammaRamp)( DWORD, D3DGAMMARAMP* ) = Graphics::SetGammaRamp;
void	(*Gos3D::GetGammaRamp)( D3DGAMMARAMP* ) = Graphics::GetGammaRamp;
HRESULT	(*Gos3D::GetRasterStatus)( D3DRASTER_STATUS* ) = Graphics::GetRasterStatus;
HRESULT	(*Gos3D::CopyRects)( GosSurface*, RECT*, UINT, GosSurface*, POINT* ) = Graphics::CopyRects;
HRESULT	(*Gos3D::GetFrontBuffer)( GosSurface* ) = Graphics::GetFrontBuffer;
HRESULT	(*Gos3D::BeginScene)( ) = Graphics::BeginScene;
HRESULT	(*Gos3D::EndScene)( ) = Graphics::EndScene;
HRESULT	(*Gos3D::Clear)( DWORD, D3DRECT*, DWORD, D3DCOLOR, float, DWORD ) = Graphics::Clear;
HRESULT	(*Gos3D::SetRenderTarget)( GosSurface*, GosSurface* ) = Graphics::SetRenderTarget;
HRESULT	(*Gos3D::GetRenderTarget)( GosSurface** ) = Graphics::GetRenderTarget;
HRESULT	(*Gos3D::GetDepthStencilSurface)( GosSurface** ) = Graphics::GetDepthStencilSurface;
HRESULT	(*Gos3D::SetTransform)( D3DTRANSFORMSTATETYPE, D3DMATRIX* ) = Graphics::SetTransform;
HRESULT	(*Gos3D::GetTransform)( D3DTRANSFORMSTATETYPE, D3DMATRIX* ) = Graphics::GetTransform;
HRESULT	(*Gos3D::MultiplyTransform)( D3DTRANSFORMSTATETYPE, D3DMATRIX* ) = Graphics::MultiplyTransform;
HRESULT	(*Gos3D::SetMaterial)( D3DMATERIAL8* ) = Graphics::SetMaterial;
HRESULT	(*Gos3D::GetMaterial)( D3DMATERIAL8* ) = Graphics::GetMaterial;
HRESULT	(*Gos3D::SetLight)( DWORD, D3DLIGHT8* ) = Graphics::SetLight;
HRESULT	(*Gos3D::GetLight)( DWORD, D3DLIGHT8* ) = Graphics::GetLight;
HRESULT	(*Gos3D::LightEnable)( DWORD, BOOL ) = Graphics::LightEnable;
HRESULT	(*Gos3D::GetLightEnable)( DWORD, BOOL* ) = Graphics::GetLightEnable;
HRESULT	(*Gos3D::SetRenderState)( D3DRENDERSTATETYPE, DWORD ) = Graphics::SetRenderState;
HRESULT	(*Gos3D::GetRenderState)( D3DRENDERSTATETYPE, DWORD* ) = Graphics::GetRenderState;
HRESULT	(*Gos3D::ApplyStateBlock)( GosStateBlock * ) = Graphics::ApplyStateBlock;
HRESULT	(*Gos3D::SetClipPlane)( DWORD, float* ) = Graphics::SetClipPlane;
HRESULT	(*Gos3D::GetClipPlane)( DWORD, float* ) = Graphics::GetClipPlane;
HRESULT	(*Gos3D::SetClipStatus)( D3DCLIPSTATUS8* ) = Graphics::SetClipStatus;
HRESULT	(*Gos3D::GetClipStatus)( D3DCLIPSTATUS8* ) = Graphics::GetClipStatus;
HRESULT	(*Gos3D::SetViewport)( D3DVIEWPORT8* ) = Graphics::SetViewport;
HRESULT	(*Gos3D::GetViewport)( D3DVIEWPORT8* ) = Graphics::GetViewport;
HRESULT	(*Gos3D::SetTexture)( DWORD, GosTexture* ) = Graphics::SetTexture;
HRESULT	(*Gos3D::GetTexture)( DWORD, GosTexture** ) = Graphics::GetTexture;
HRESULT	(*Gos3D::SetTextureStageState)( DWORD, D3DTEXTURESTAGESTATETYPE, DWORD ) = Graphics::SetTextureStageState;
HRESULT	(*Gos3D::GetTextureStageState)( DWORD, D3DTEXTURESTAGESTATETYPE, DWORD* ) = Graphics::GetTextureStageState;
HRESULT	(*Gos3D::SetPaletteEntries)( UINT, PALETTEENTRY* ) = Graphics::SetPaletteEntries;
HRESULT	(*Gos3D::GetPaletteEntries)( UINT, PALETTEENTRY* ) = Graphics::GetPaletteEntries;
HRESULT	(*Gos3D::SetCurrentTexturePalette)( UINT ) = Graphics::SetCurrentTexturePalette;
HRESULT	(*Gos3D::GetCurrentTexturePalette)( UINT * ) = Graphics::GetCurrentTexturePalette;
HRESULT	(*Gos3D::SetStreamSource)( UINT, GosVertexBuffer*, UINT ) = Graphics::SetStreamSource;
HRESULT	(*Gos3D::GetStreamSource)( UINT, GosVertexBuffer**, UINT* ) = Graphics::GetStreamSource;
HRESULT	(*Gos3D::SetIndices)( GosIndexBuffer*, UINT ) = Graphics::SetIndices;
HRESULT	(*Gos3D::GetIndices)( GosIndexBuffer**, UINT* ) = Graphics::GetIndices;
HRESULT	(*Gos3D::DrawPrimitive)( D3DPRIMITIVETYPE, UINT, UINT ) = Graphics::DrawPrimitive;
HRESULT	(*Gos3D::DrawIndexedPrimitive)( D3DPRIMITIVETYPE, UINT, UINT, UINT, UINT ) = Graphics::DrawIndexedPrimitive;
HRESULT	(*Gos3D::DrawPrimitiveUP)( D3DPRIMITIVETYPE, UINT, void*, UINT ) = Graphics::DrawPrimitiveUP;
HRESULT (*Gos3D::DrawQuadUP)( UINT, void*, UINT ) = Graphics::DrawQuadUP;
HRESULT	(*Gos3D::DrawIndexedPrimitiveUP)( D3DPRIMITIVETYPE, UINT, UINT, UINT, void*, D3DFORMAT, void*, UINT ) = Graphics::DrawIndexedPrimitiveUP;
HRESULT	(*Gos3D::ProcessVertices)( UINT, UINT, UINT, GosVertexBuffer*, DWORD ) = Graphics::ProcessVertices;
HRESULT	(*Gos3D::SetFVFShader)( DWORD ) = Graphics::SetFVFShader;
HRESULT	(*Gos3D::SetVertexShader)( GosVertexShader * ) = Graphics::SetVertexShader;
HRESULT	(*Gos3D::GetVertexShader)( GosVertexShader ** ) = Graphics::GetVertexShader;
HRESULT	(*Gos3D::SetVertexShaderConstant)( DWORD, void*, DWORD ) = Graphics::SetVertexShaderConstant;
HRESULT	(*Gos3D::GetVertexShaderConstant)( DWORD, void*, DWORD ) = Graphics::GetVertexShaderConstant;
HRESULT	(*Gos3D::SetPixelShader)( GosPixelShader * ) = Graphics::SetPixelShader;
HRESULT	(*Gos3D::GetPixelShader)( GosPixelShader ** ) = Graphics::GetPixelShader;
HRESULT	(*Gos3D::SetPixelShaderConstant)( DWORD, void*, DWORD ) = Graphics::SetPixelShaderConstant;
HRESULT	(*Gos3D::GetPixelShaderConstant)( DWORD, void*, DWORD ) = Graphics::GetPixelShaderConstant;
HRESULT	(*Gos3D::DrawRectPatch)( UINT, float*, D3DRECTPATCH_INFO* ) = Graphics::DrawRectPatch;
HRESULT	(*Gos3D::DrawTriPatch)( UINT, float*, D3DTRIPATCH_INFO* ) = Graphics::DrawTriPatch;
void (*Gos3D::SetupViewport)( bool, float, bool, DWORD, float, float, float, float, bool, DWORD ) = Graphics::SetupViewport;

DWORD gPerfPolyCount = 0;	// TEMPORARY - THIS MUST BE REMOVED!

bool Graphics::Initialize( HWND hWnd )
{
	HRESULT rc;

	s_hWindow = hWnd;

	s_pD3D = Direct3DCreate8( D3D_SDK_VERSION );
	if( !s_pD3D )
		return false;

	ZeroMemory( &s_d3dpp, sizeof(s_d3dpp) );

    s_d3dpp.Windowed               = true;
    s_d3dpp.BackBufferCount        = 1;
    s_d3dpp.MultiSampleType        = D3DMULTISAMPLE_NONE;
    s_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
    s_d3dpp.EnableAutoDepthStencil = true;
    s_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    s_d3dpp.hDeviceWindow          = hWnd;
	s_d3dpp.BackBufferFormat       = D3DFMT_R5G6B5;

	D3DDISPLAYMODE d3ddmDesktop;
	s_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddmDesktop );

    s_d3dpp.BackBufferWidth  = d3ddmDesktop.Width;
    s_d3dpp.BackBufferHeight = d3ddmDesktop.Height;
    s_d3dpp.BackBufferFormat = d3ddmDesktop.Format;


	GosApp::CurrentApp()->PreferredDisplay( s_d3dpp.Windowed, s_d3dpp.BackBufferWidth,
		s_d3dpp.BackBufferHeight, s_d3dpp.BackBufferFormat );

#ifdef _VERTEXBLENDREQUIRED
	rc = s_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 32/* D3DCREATE_HARDWARE_VERTEXPROCESSING */ ,
		&s_d3dpp, &s_pD3DDevice );
#else
	rc = s_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 64/* D3DCREATE_HARDWARE_VERTEXPROCESSING */ ,
		&s_d3dpp, &s_pD3DDevice );
#endif

	if( FAILED(rc) )
	{
		if( rc == D3DERR_INVALIDCALL )
			return false;
		if( rc == D3DERR_NOTAVAILABLE )
			return false;
		if( rc == D3DERR_OUTOFVIDEOMEMORY )
			return false;
		return false;
	}
#if 0
    if( true /* m_bWindowed */ )
    {
		RECT rcWindowBounds;
	    GetClientRect( hWnd, &rcWindowBounds );
        SetWindowPos( hWnd, HWND_NOTOPMOST, 
                      rcWindowBounds.left, rcWindowBounds.top,
                      ( rcWindowBounds.right - rcWindowBounds.left ), 
                      ( rcWindowBounds.bottom - rcWindowBounds.top ), 
                      SWP_SHOWWINDOW );
    }
#endif

	IDirect3DSurface8 *pRenderTarget;
	s_pD3DDevice->GetRenderTarget( &pRenderTarget );
	s_pDefaultRenderTarget = new Surface( pRenderTarget );

	IDirect3DSurface8 *pDepthStencil;
	s_pD3DDevice->GetDepthStencilSurface( &pDepthStencil );
	s_pDefaultDepthStencil = new Surface( pDepthStencil );

	s_pZStencil = s_pDefaultDepthStencil;
	s_pRenderTarget = s_pDefaultRenderTarget;


	return true;
}

void Graphics::Shutdown()
{
	if( s_pDefaultRenderTarget )
	{
		delete s_pDefaultRenderTarget;
		s_pDefaultRenderTarget = NULL;
	}

	if( s_pDefaultDepthStencil )
	{
		delete s_pDefaultDepthStencil;
		s_pDefaultDepthStencil = NULL;
	}

	if( s_pD3DDevice )
	{
		s_pD3DDevice->Release();
		s_pD3DDevice = NULL;
	}

	if( s_pD3D )
	{
		s_pD3D->Release();
		s_pD3D = NULL;
	}
}

void Graphics::Done()
{
	HRESULT rc = s_pD3DDevice->Present(NULL,NULL,NULL,NULL);

	s_pZStencil = s_pDefaultDepthStencil;
	s_pRenderTarget = s_pDefaultRenderTarget;

	if( rc == D3DERR_DEVICELOST )
	{
		s_pD3DDevice->Reset( &s_d3dpp);
	}

#if 0
	if( FAILED(rc) )
	{
		{

		}
		if( rc == D3DERR_INVALIDCALL )
			_asm int 3;
		if( rc == D3DERR_NOTAVAILABLE )
			_asm int 3;
		if( rc == D3DERR_OUTOFVIDEOMEMORY )
			_asm int 3;
			_asm int 3;
	}
#endif

	rc;
}

HRESULT Graphics::SetCursorProperties( UINT XHotSpot, UINT YHotSpot, GosSurface* pCursorBitmap )
{
	HRESULT rc;
	LOG_API("Graphics::SetCursorProperties");
	rc = s_pD3DDevice->SetCursorProperties( XHotSpot, YHotSpot, ((Surface *)pCursorBitmap)->D3DSurface() );
	CHECK_RC;
}


void Graphics::SetCursorPosition( UINT XScreenSpace, UINT YScreenSpace, DWORD Flags )
{
	LOG_API("Graphics::SetCursorPosition");
	s_pD3DDevice->SetCursorPosition( XScreenSpace, YScreenSpace, Flags );
}


BOOL Graphics::ShowCursor( BOOL bShow )
{
	LOG_API("Graphics::ShowCursor");
	return s_pD3DDevice->ShowCursor( bShow );
}

void Graphics::SetDisplay(UINT width, UINT height, D3DFORMAT format, bool windowed )
{
	LOG_API("Graphics::SetDisplay");

//	windowed = false;	 // TEMPORARY!

	ZeroMemory( &s_d3dpp, sizeof(s_d3dpp) );
	s_d3dpp.BackBufferCount = 1;
	s_d3dpp.Windowed = windowed;
	s_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	s_d3dpp.EnableAutoDepthStencil = true;
	s_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	s_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
	s_d3dpp.FullScreen_RefreshRateInHz = windowed?0:60;
	s_d3dpp.FullScreen_PresentationInterval = windowed?0:1;
	s_d3dpp.BackBufferFormat       = D3DFMT_R5G6B5;
    if( s_d3dpp.Windowed )
    {
		D3DDISPLAYMODE d3ddmDesktop;
		s_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddmDesktop );

        s_d3dpp.BackBufferWidth  = width; // rcWindowClient.right - rcWindowClient.left;
        s_d3dpp.BackBufferHeight = height; // rcWindowClient.bottom - rcWindowClient.top;
        s_d3dpp.BackBufferFormat = d3ddmDesktop.Format;
    }
    else
    {
        s_d3dpp.BackBufferWidth  = width;
        s_d3dpp.BackBufferHeight = height;
        s_d3dpp.BackBufferFormat = format;
    }

	s_pD3DDevice->Reset( &s_d3dpp );

	s_Top = 0;
	s_Left = 0;
	s_Height = height;
	s_Width = width;

	SetWindowPos( s_hWindow, 0, 0, 0, width, height, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_FRAMECHANGED);
	UpdateWindowDimensions();

	ShowWindow( s_hWindow, SW_SHOWDEFAULT );
	UpdateWindow( s_hWindow );

	// reset the default surfaces in case they changed:

	if( s_pDefaultRenderTarget )
	{
		delete s_pDefaultRenderTarget;
		s_pDefaultRenderTarget = NULL;
	}

	if( s_pDefaultDepthStencil )
	{
		delete s_pDefaultDepthStencil;
		s_pDefaultDepthStencil = NULL;
	}

	IDirect3DSurface8 *pRenderTarget;
	s_pD3DDevice->GetRenderTarget( &pRenderTarget );
	s_pDefaultRenderTarget = new Surface( pRenderTarget );

	IDirect3DSurface8 *pDepthStencil;
	s_pD3DDevice->GetDepthStencilSurface( &pDepthStencil );
	s_pDefaultDepthStencil = new Surface( pDepthStencil );

	s_pZStencil = s_pDefaultDepthStencil;
	s_pRenderTarget = s_pDefaultRenderTarget;


}

DWORD Graphics::Left() { return s_Left; }
DWORD Graphics::Top() { return s_Top; }
DWORD Graphics::Width() { return s_Width; }
DWORD Graphics::Height() { return s_Height; }

void Graphics::UpdateWindowDimensions()
{
	RECT rect1;
	RECT rect2;
	GetWindowRect( s_hWindow, &rect1 );
	GetClientRect( s_hWindow, &rect2 );
	int border = (( rect1.right - rect1.left ) - ( rect2.right - rect2.left )) / 2;
	s_Width = rect2.right - rect2.left;
	s_Height = rect2.bottom - rect2.top;
	s_Left = rect1.left + border;
	s_Top = rect1.top + ( rect1.bottom-rect1.top-s_Height ) - border;
}

void Graphics::SetGammaRamp( DWORD Flags, D3DGAMMARAMP* pRamp )
{
	LOG_API("Graphics::SetGammaRamp");
	s_pD3DDevice->SetGammaRamp( Flags, pRamp );
}


void Graphics::GetGammaRamp( D3DGAMMARAMP* pRamp )
{
	LOG_API("Graphics::GetGammaRamp");
	s_pD3DDevice->GetGammaRamp( pRamp );
}

HRESULT Graphics::GetRasterStatus( D3DRASTER_STATUS* pRasterStatus )
{
	HRESULT rc;
	LOG_API("Graphics::GetRasterStatus");
	rc = s_pD3DDevice->GetRasterStatus( pRasterStatus );
	CHECK_RC;
}

HRESULT Graphics::CopyRects( GosSurface* pSourceSurface, RECT* pSourceRectsArray, UINT cRects, GosSurface* pDestinationSurface, POINT* pDestPointsArray )
{
	HRESULT rc;
	LOG_API("Graphics::CopyRects");
	rc = s_pD3DDevice->CopyRects( ((Surface *)pSourceSurface)->D3DSurface(), pSourceRectsArray, cRects, ((Surface *)pDestinationSurface)->D3DSurface(), pDestPointsArray );
	CHECK_RC;
}

HRESULT Graphics::GetFrontBuffer( GosSurface* pDestSurface )
{
	HRESULT rc;
	LOG_API("Graphics::GetFrontBuffer");
	rc = s_pD3DDevice->GetFrontBuffer( ((Surface *)pDestSurface)->D3DSurface() );
	CHECK_RC;
}

HRESULT Graphics::BeginScene()
{
	HRESULT rc;
	LOG_API("Graphics::BeginScene");
	UpdateWindowDimensions();
	rc = s_pD3DDevice->BeginScene();
	CHECK_RC;
}


HRESULT Graphics::EndScene()
{
	HRESULT rc;
	LOG_API("Graphics::EndScene");
	rc = s_pD3DDevice->EndScene();
	CHECK_RC;
}


HRESULT Graphics::Clear( DWORD Count, D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil )
{
	HRESULT rc;
	LOG_API("Graphics::Clear");
	rc = s_pD3DDevice->Clear( Count, pRects, Flags, Color, Z, Stencil );
	CHECK_RC;
}

HRESULT Graphics::SetRenderTarget( GosSurface* pRenderTarget, GosSurface* pNewZStencil )
{
	HRESULT rc;
	LOG_API("Graphics::SetRenderTarget");
	rc = s_pD3DDevice->SetRenderTarget( ((Surface *)pRenderTarget)->D3DSurface(), ((Surface *)pNewZStencil)->D3DSurface() );
	if( pRenderTarget )
		s_pRenderTarget = pRenderTarget;
	s_pZStencil = pNewZStencil;
	CHECK_RC;
}


HRESULT Graphics::GetRenderTarget( GosSurface** ppRenderTarget )
{
	LOG_API("Graphics::GetRenderTarget");
	if( s_pRenderTarget )
		*ppRenderTarget = s_pRenderTarget;
	else
		*ppRenderTarget = s_pDefaultRenderTarget;
	return D3D_OK;
}


HRESULT Graphics::GetDepthStencilSurface( GosSurface** ppZStencilSurface )
{
	LOG_API("Graphics::GetDepthStencilSurface");
	*ppZStencilSurface = s_pZStencil;
	return D3D_OK;
}

HRESULT Graphics::SetTransform( D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix )
{
	HRESULT rc;
	LOG_API("Graphics::SetTransform");
	rc = s_pD3DDevice->SetTransform( State, pMatrix );
	CHECK_RC;
}


HRESULT Graphics::GetTransform( D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix )
{
	HRESULT rc;
	LOG_API("Graphics::GetTransform");
	rc = s_pD3DDevice->GetTransform( State, pMatrix );
	CHECK_RC;
}


HRESULT Graphics::MultiplyTransform( D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix )
{
	HRESULT rc;
	LOG_API("Graphics::MultiplyTransform");
	rc = s_pD3DDevice->MultiplyTransform( State, pMatrix );
	CHECK_RC;
}

HRESULT Graphics::SetMaterial( D3DMATERIAL8* pMaterial )
{
	HRESULT rc;
	LOG_API("Graphics::SetMaterial");
	rc = s_pD3DDevice->SetMaterial( pMaterial );
	CHECK_RC;
}


HRESULT Graphics::GetMaterial( D3DMATERIAL8* pMaterial )
{
	HRESULT rc;
	LOG_API("Graphics::GetMaterial");
	rc = s_pD3DDevice->GetMaterial( pMaterial );
	CHECK_RC;
}


HRESULT Graphics::SetLight( DWORD Index, D3DLIGHT8* pLight )
{
	HRESULT rc;
	LOG_API("Graphics::SetLight");
	rc = s_pD3DDevice->SetLight( Index, pLight );
	CHECK_RC;
}


HRESULT Graphics::GetLight( DWORD Index, D3DLIGHT8* pLight )
{
	HRESULT rc;
	LOG_API("Graphics::GetLight");
	rc = s_pD3DDevice->GetLight( Index, pLight );
	CHECK_RC;
}


HRESULT Graphics::LightEnable( DWORD Index, BOOL Enable )
{
	HRESULT rc;
	LOG_API("Graphics::LightEnable");
	rc = s_pD3DDevice->LightEnable( Index, Enable );
	CHECK_RC;
}


HRESULT Graphics::GetLightEnable( DWORD Index, BOOL* pEnable )
{
	HRESULT rc;
	LOG_API("Graphics::GetLightEnable");
	rc = s_pD3DDevice->GetLightEnable( Index, pEnable );
	CHECK_RC;
}

HRESULT Graphics::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
{
	HRESULT rc;
	LOG_API("Graphics::SetRenderState");
	rc = s_pD3DDevice->SetRenderState( State, Value );
	CHECK_RC;
}


HRESULT Graphics::GetRenderState( D3DRENDERSTATETYPE State, DWORD* pValue )
{
	HRESULT rc;
	LOG_API("Graphics::GetRenderState");
	rc = s_pD3DDevice->GetRenderState( State, pValue );
	CHECK_RC;
}

HRESULT Graphics::ApplyStateBlock( GosStateBlock *pBlock )
{
	HRESULT rc;
	LOG_API("Graphics::ApplyStateBlock");
	rc = s_pD3DDevice->ApplyStateBlock( ((StateBlock *)pBlock)->Token() );
	CHECK_RC;
}

HRESULT Graphics::SetClipPlane( DWORD Index, float* pPlane )
{
	HRESULT rc;
	LOG_API("Graphics::SetClipPlane");
	rc = s_pD3DDevice->SetClipPlane( Index, pPlane );
	CHECK_RC;
}


HRESULT Graphics::GetClipPlane( DWORD Index, float* pPlane )
{
	HRESULT rc;
	LOG_API("Graphics::GetClipPlane");
	rc = s_pD3DDevice->GetClipPlane( Index, pPlane );
	CHECK_RC;
}

HRESULT Graphics::SetClipStatus( D3DCLIPSTATUS8* pClipStatus )
{
	HRESULT rc;
	LOG_API("Graphics::SetClipStatus");
	rc = s_pD3DDevice->SetClipStatus( pClipStatus );
	CHECK_RC;
}


HRESULT Graphics::GetClipStatus( D3DCLIPSTATUS8* pClipStatus )
{
	HRESULT rc;
	LOG_API("Graphics::GetClipStatus");
	rc = s_pD3DDevice->GetClipStatus( pClipStatus );
	CHECK_RC;
}

HRESULT Graphics::SetViewport( D3DVIEWPORT8* pViewport )
{
	HRESULT rc;
	LOG_API("Graphics::SetViewport");
	rc = s_pD3DDevice->SetViewport( pViewport );
	CHECK_RC;
}


HRESULT Graphics::GetViewport( D3DVIEWPORT8* pViewport )
{
	HRESULT rc;
	LOG_API("Graphics::GetViewport");
	rc = s_pD3DDevice->GetViewport( pViewport );
	CHECK_RC;
}

HRESULT Graphics::SetTexture( DWORD Stage, GosTexture* pTexture )
{
	HRESULT rc;
	LOG_API("Graphics::SetTexture");
	s_apTexture[Stage] = pTexture;
	rc = s_pD3DDevice->SetTexture( Stage, pTexture?(((Texture *)pTexture)->D3DTexture()):0 );
	CHECK_RC;
}

HRESULT Graphics::GetTexture( DWORD Stage, GosTexture** ppTexture )
{
	LOG_API("Graphics::GetTexture");
	*ppTexture = s_apTexture[Stage];
	return D3D_OK;
}

HRESULT Graphics::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value )
{
	HRESULT rc;
	LOG_API("Graphics::SetTextureStageState");
	rc = s_pD3DDevice->SetTextureStageState( Stage, Type, Value );
	CHECK_RC;
}

HRESULT Graphics::GetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue )
{
	HRESULT rc;
	LOG_API("Graphics::GetTextureStageState");
	rc = s_pD3DDevice->GetTextureStageState( Stage, Type, pValue );
	CHECK_RC;
}

HRESULT Graphics::SetPaletteEntries( UINT PaletteNumber, PALETTEENTRY* pEntries )
{
	HRESULT rc;
	LOG_API("Graphics::SetPaletteEntries");
	rc = s_pD3DDevice->SetPaletteEntries( PaletteNumber, pEntries );
	CHECK_RC;
}


HRESULT Graphics::GetPaletteEntries( UINT PaletteNumber, PALETTEENTRY* pEntries )
{
	HRESULT rc;
	LOG_API("Graphics::GetPaletteEntries");
	rc = s_pD3DDevice->GetPaletteEntries( PaletteNumber, pEntries );
	CHECK_RC;
}


HRESULT Graphics::SetCurrentTexturePalette( UINT PaletteNumber )
{
	HRESULT rc;
	LOG_API("Graphics::SetCurrentTexturePalette");
	rc = s_pD3DDevice->SetCurrentTexturePalette( PaletteNumber );
	CHECK_RC;
}


HRESULT Graphics::GetCurrentTexturePalette( UINT *PaletteNumber )
{
	HRESULT rc;
	LOG_API("Graphics::GetCurrentTexturePalette");
	rc = s_pD3DDevice->GetCurrentTexturePalette( PaletteNumber );
	CHECK_RC;
}

HRESULT Graphics::SetStreamSource( UINT StreamNumber, GosVertexBuffer* pStreamData, UINT Stride )
{
	HRESULT rc;
	LOG_API("Graphics::SetStreamSource");
	s_apVertexBuffer[StreamNumber] = pStreamData;
	s_aStreamStride[StreamNumber] = Stride;
	rc = s_pD3DDevice->SetStreamSource( StreamNumber, ((VertexBuffer *)pStreamData)->D3DVertexBuffer(), Stride );
	CHECK_RC;
}


HRESULT Graphics::GetStreamSource( UINT StreamNumber, GosVertexBuffer** ppStreamData, UINT* pStride )
{
	LOG_API("Graphics::GetStreamSource");
	if( ppStreamData )
		*ppStreamData = s_apVertexBuffer[StreamNumber];
	if( pStride )
		*pStride = s_aStreamStride[StreamNumber];
	return D3D_OK;
}

HRESULT Graphics::SetIndices( GosIndexBuffer* pIndexData, UINT BaseVertexIndex )
{
	HRESULT rc;
	LOG_API("Graphics::SetIndices");
	s_pIndexBuffer = pIndexData;
	s_BaseVertexIndex = BaseVertexIndex;
	rc = s_pD3DDevice->SetIndices( ((IndexBuffer *)pIndexData)->D3DIndexBuffer(), BaseVertexIndex );
	CHECK_RC;
}

HRESULT Graphics::GetIndices( GosIndexBuffer** ppIndexData, UINT* pBaseVertexIndex )
{
	LOG_API("Graphics::GetIndices");
	if( ppIndexData )
		*ppIndexData = s_pIndexBuffer;
	if( pBaseVertexIndex )
		 *pBaseVertexIndex = s_BaseVertexIndex;
	return D3D_OK;
}

HRESULT Graphics::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount )
{
	HRESULT rc;
	LOG_API("Graphics::DrawPrimitive");
	gPerfPolyCount += PrimitiveCount;
	rc = s_pD3DDevice->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount );
	CHECK_RC;
}

HRESULT Graphics::DrawQuadUP( UINT PrimitiveCount, void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
{
	LOG_API("Graphics::DrawQuadUP");
	HRESULT rc = D3D_OK;

	gPerfPolyCount += PrimitiveCount;

	for( UINT quad=0; quad<PrimitiveCount; quad++ )
	{
		rc = DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2,
			(void *)(((char *)pVertexStreamZeroData)+quad * VertexStreamZeroStride  * 4),
			VertexStreamZeroStride );
	}

	CHECK_RC;
}

HRESULT Graphics::DrawIndexedPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT minIndex, UINT NumIndices, UINT startIndex, UINT PrimitiveCount )
{
	HRESULT rc;
	LOG_API("Graphics::DrawIndexedPrimitive");
	gPerfPolyCount += PrimitiveCount;
	rc = s_pD3DDevice->DrawIndexedPrimitive( PrimitiveType, minIndex, NumIndices, startIndex, PrimitiveCount );
	CHECK_RC;
}


HRESULT Graphics::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
{
	HRESULT rc;
	LOG_API("Graphics::DrawPrimitiveUP");
	gPerfPolyCount += PrimitiveCount;
	rc = s_pD3DDevice->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride );
	CHECK_RC;
}


HRESULT Graphics::DrawIndexedPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices, UINT PrimitiveCount, void* pIndexData, D3DFORMAT IndexDataFormat, void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
{
	HRESULT rc;
	LOG_API("Graphics::DrawIndexedPrimitiveUP");
	gPerfPolyCount += PrimitiveCount;
	rc = s_pD3DDevice->DrawIndexedPrimitiveUP( PrimitiveType, MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride );
	CHECK_RC;
}


HRESULT Graphics::ProcessVertices( UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, GosVertexBuffer* pDestBuffer, DWORD Flags )
{
	HRESULT rc;
	LOG_API("Graphics::ProcessVertices");
	rc = s_pD3DDevice->ProcessVertices( SrcStartIndex, DestIndex, VertexCount, ((VertexBuffer *)pDestBuffer)->D3DVertexBuffer(), Flags );
	CHECK_RC;
}

HRESULT Graphics::SetFVFShader( DWORD vertexFormat )
{
	HRESULT rc;
	LOG_API("Graphics::SetFVFShader");
	rc = s_pD3DDevice->SetVertexShader( vertexFormat );
	CHECK_RC;
}

HRESULT Graphics::SetVertexShader( GosVertexShader *pVertexShader )
{
	HRESULT rc;
	LOG_API("Graphics::SetVertexShader");
	s_pVertexShader = pVertexShader;
	rc = s_pD3DDevice->SetVertexShader( ((VertexShader *)pVertexShader)->Handle() );
	CHECK_RC;
}


HRESULT Graphics::GetVertexShader( GosVertexShader **ppVertexShader )
{
	LOG_API("Graphics::GetVertexShader");
	*ppVertexShader = s_pVertexShader;
	return D3D_OK;
}

HRESULT Graphics::SetVertexShaderConstant( DWORD Register, void* pConstantData, DWORD ConstantCount )
{
	HRESULT rc;
	LOG_API("Graphics::SetVertexShaderConstant");
	rc = s_pD3DDevice->SetVertexShaderConstant( Register, pConstantData, ConstantCount );
	CHECK_RC;
}


HRESULT Graphics::GetVertexShaderConstant( DWORD Register, void* pConstantData, DWORD ConstantCount )
{
	HRESULT rc;
	LOG_API("Graphics::GetVertexShaderConstant");
	rc = s_pD3DDevice->GetVertexShaderConstant( Register, pConstantData, ConstantCount );
	CHECK_RC;
}

HRESULT Graphics::SetPixelShader( GosPixelShader *pPixelShader )
{
	HRESULT rc;
	LOG_API("Graphics::SetPixelShader");
	s_pPixelShader = pPixelShader;
	rc = s_pD3DDevice->SetPixelShader( ((PixelShader *)pPixelShader)->Handle() );
	CHECK_RC;
}


HRESULT Graphics::GetPixelShader( GosPixelShader **ppPixelShader )
{
	LOG_API("Graphics::GetPixelShader");
	*ppPixelShader = s_pPixelShader;
	return D3D_OK;
}

HRESULT Graphics::SetPixelShaderConstant( DWORD Register, void* pConstantData, DWORD ConstantCount )
{
	HRESULT rc;
	LOG_API("Graphics::SetPixelShaderConstant");
	rc = s_pD3DDevice->SetPixelShaderConstant( Register, pConstantData, ConstantCount );
	CHECK_RC;
}


HRESULT Graphics::GetPixelShaderConstant( DWORD Register, void* pConstantData, DWORD ConstantCount )
{
	HRESULT rc;
	LOG_API("Graphics::GetPixelShaderConstant");
	rc = s_pD3DDevice->GetPixelShaderConstant( Register, pConstantData, ConstantCount );
	CHECK_RC;
}

HRESULT Graphics::DrawRectPatch( UINT Handle, float* pNumSegs, D3DRECTPATCH_INFO* pSurf )
{
	HRESULT rc;
	LOG_API("Graphics::DrawRectPatch");
	rc = s_pD3DDevice->DrawRectPatch( Handle, pNumSegs, pSurf );
	CHECK_RC;
}


HRESULT Graphics::DrawTriPatch( UINT Handle, float* pNumSegs, D3DTRIPATCH_INFO* pSurf )
{
	HRESULT rc;
	LOG_API("Graphics::DrawTriPatch");
	rc = s_pD3DDevice->DrawTriPatch( Handle, pNumSegs, pSurf );
	CHECK_RC;
}


void Graphics::SetupViewport( bool FillZ, float ZBuffer, bool FillBG, DWORD BGColor, float top, float left, float bottom, float right, bool ClearStencil, DWORD StencilValue )
{
	LOG_API("Graphics::SetupViewport");
	 FillZ;  ZBuffer;  FillBG;  BGColor;  top;  left;  bottom;  right;  ClearStencil;  StencilValue;
	// _asm int 3;
}




#if 0







HRESULT Graphics::GetBackBuffer( UINT BackBuffer, D3DBACKBUFFER_TYPE Type, GosSurface** ppBackBuffer )
{
	HRESULT rc;
	LOG_API("Graphics::GetBackBuffer");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->GetBackBuffer( BackBuffer, Type, ppBackBuffer );
	CHECK_RC;
}




HRESULT Graphics::CreateTexture( UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture )
{
	HRESULT rc;
	LOG_API("Graphics::CreateTexture");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateTexture( Width, Height, Levels, Usage, Format, Pool, ppTexture );
	CHECK_RC;
}


HRESULT Graphics::CreateVolumeTexture( UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture )
{
	HRESULT rc;
	LOG_API("Graphics::CreateVolumeTexture");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateVolumeTexture( Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture );
	CHECK_RC;
}


HRESULT Graphics::CreateCubeTexture( UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture )
{
	HRESULT rc;
	LOG_API("Graphics::CreateCubeTexture");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateCubeTexture( EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture );
	CHECK_RC;
}


HRESULT Graphics::CreateVertexBuffer( UINT Length, DWORD FVF, DWORD Usage, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer )
{
	HRESULT rc;
	LOG_API("Graphics::CreateVertexBuffer");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateVertexBuffer( Length, FVF, Usage, Pool, ppVertexBuffer );
	CHECK_RC;
}


HRESULT Graphics::CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer )
{
	HRESULT rc;
	LOG_API("Graphics::CreateIndexBuffer");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateIndexBuffer( Length, Usage, Format, Pool, ppIndexBuffer );
	CHECK_RC;
}


HRESULT Graphics::CreateRenderTarget( UINT Width, UINT Height, DWORD Usage, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, GosSurface** ppSurface )
{
	HRESULT rc;
	LOG_API("Graphics::CreateRenderTarget");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateRenderTarget( Width, Height, Usage, Format, MultiSample, ppSurface );
	CHECK_RC;
}


HRESULT Graphics::CreateDepthStencilSurface( UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, GosSurface** ppSurface )
{
	HRESULT rc;
	LOG_API("Graphics::CreateDepthStencilSurface");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateDepthStencilSurface( Width, Height, Usage, Format, MultiSample, ppSurface );
	CHECK_RC;
}


HRESULT Graphics::CreateImageSurface( UINT Width, UINT Height, D3DFORMAT Format, GosSurface** ppSurface )
{
	HRESULT rc;
	LOG_API("Graphics::CreateImageSurface");
	NOT_IMPLEMENTED;
//	rc = s_pD3DDevice->CreateImageSurface( Width, Height, Format, ppSurface );
	CHECK_RC;
}



HRESULT Graphics::UpdateTexture( IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture )
{
	HRESULT rc;
	LOG_API("Graphics::UpdateTexture");
	rc = s_pD3DDevice->UpdateTexture( pSourceTexture, pDestinationTexture );
	CHECK_RC;
}










HRESULT Graphics::BeginStateBlock()
{
	HRESULT rc;
	LOG_API("Graphics::BeginStateBlock");
	rc = s_pD3DDevice->BeginStateBlock();
	CHECK_RC;
}


HRESULT Graphics::EndStateBlock( DWORD* pToken )
{
	HRESULT rc;
	LOG_API("Graphics::EndStateBlock");
	rc = s_pD3DDevice->EndStateBlock( pToken );
	CHECK_RC;
}



HRESULT Graphics::CaptureStateBlock( DWORD Token )
{
	HRESULT rc;
	LOG_API("Graphics::CaptureStateBlock");
	rc = s_pD3DDevice->CaptureStateBlock( Token );
	CHECK_RC;
}


HRESULT Graphics::DeleteStateBlock( DWORD Token )
{
	HRESULT rc;
	LOG_API("Graphics::DeleteStateBlock");
	rc = s_pD3DDevice->DeleteStateBlock( Token );
	CHECK_RC;
}


HRESULT Graphics::CreateStateBlock( D3DSTATEBLOCKTYPE Type, DWORD* pToken )
{
	HRESULT rc;
	LOG_API("Graphics::CreateStateBlock");
	rc = s_pD3DDevice->CreateStateBlock( Type, pToken );
	CHECK_RC;
}




HRESULT Graphics::ValidateDevice( DWORD* pNumPasses )
{
	HRESULT rc;
	LOG_API("Graphics::ValidateDevice");
	rc = s_pD3DDevice->ValidateDevice( pNumPasses );
	CHECK_RC;
}


HRESULT Graphics::GetInfo( DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize )
{
	HRESULT rc;
	LOG_API("Graphics::GetInfo");
	rc = s_pD3DDevice->GetInfo( DevInfoID, pDevInfoStruct, DevInfoStructSize );
	CHECK_RC;
}




HRESULT Graphics::CreateVertexShader( DWORD* pDeclaration, DWORD* pFunction, DWORD* pHandle, DWORD Usage )
{
	HRESULT rc;
	LOG_API("Graphics::CreateVertexShader");
	rc = s_pD3DDevice->CreateVertexShader( pDeclaration, pFunction, pHandle, Usage );
	CHECK_RC;
}




HRESULT Graphics::DeleteVertexShader( DWORD Handle )
{
	HRESULT rc;
	LOG_API("Graphics::DeleteVertexShader");
	rc = s_pD3DDevice->DeleteVertexShader( Handle );
	CHECK_RC;
}



HRESULT Graphics::GetVertexShaderDeclaration( DWORD Handle, void* pData, DWORD* pSizeOfData )
{
	HRESULT rc;
	LOG_API("Graphics::GetVertexShaderDeclaration");
	rc = s_pD3DDevice->GetVertexShaderDeclaration( Handle, pData, pSizeOfData );
	CHECK_RC;
}


HRESULT Graphics::GetVertexShaderFunction( DWORD Handle, void* pData, DWORD* pSizeOfData )
{
	HRESULT rc;
	LOG_API("Graphics::GetVertexShaderFunction");
	rc = s_pD3DDevice->GetVertexShaderFunction( Handle, pData, pSizeOfData );
	CHECK_RC;
}



HRESULT Graphics::CreatePixelShader( DWORD* pFunction, DWORD* pHandle )
{
	HRESULT rc;
	LOG_API("Graphics::CreatePixelShader");
	rc = s_pD3DDevice->CreatePixelShader( pFunction, pHandle );
	CHECK_RC;
}



HRESULT Graphics::DeletePixelShader( DWORD Handle )
{
	HRESULT rc;
	LOG_API("Graphics::DeletePixelShader");
	rc = s_pD3DDevice->DeletePixelShader( Handle );
	CHECK_RC;
}



HRESULT Graphics::GetPixelShaderFunction( DWORD Handle, void* pData, DWORD* pSizeOfData )
{
	HRESULT rc;
	LOG_API("Graphics::GetPixelShaderFunction");
	rc = s_pD3DDevice->GetPixelShaderFunction( Handle, pData, pSizeOfData );
	CHECK_RC;
}



#endif