//
// DX9DeviceC.h
//
// DirectX 9 device driver.
//
// Copyright (c) 2004 memon/moppi productions
//

#ifndef __DX9DEVICEC_H__
#define __DX9DEVICEC_H__

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>

// forward declaration

namespace PajaSystem {
	class DX9DeviceC;
};

#include "PajaTypes.h"
#include "BBox2C.h"
#include "ColorC.h"
#include "Vector2C.h"
#include "DeviceInterfaceI.h"
#include "GraphicsDeviceI.h"
#include "DX9ViewportC.h"
#include "DX9GUIDrawInterfaceC.h"
#include "DeviceFeedbackC.h"
#include "DX9DeviceC.h"
#include "DX9BufferC.h"
#include <list>


//////////////////////////////////////////////////////////////////////////
//
//  OpenGL Device Driver Class ID
//

namespace PajaSystem {

	const PluginClass::ClassIdC	CLASS_DX9_DEVICEDRIVER = PluginClass::ClassIdC( 0, 30000 );


	class DX9DeviceC : public GraphicsDeviceI
	{
	public:
		static DX9DeviceC*				create_new();
		virtual Edit::DataBlockI*		create();
		virtual PluginClass::ClassIdC	get_class_id() const;
		virtual const char*				get_class_name();
		virtual DeviceInterfaceI*		query_interface( const PluginClass::SuperClassIdC& rSuperClassId );
		virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
		virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );

		virtual bool					init( HINSTANCE hInstance, HWND hParent, PajaTypes::int32 i32ID, PajaTypes::uint32 ui32Flags,
											PajaTypes::uint32 ui32Width = 0, PajaTypes::uint32 ui32Height = 0, PajaTypes::uint32 ui32BPP = 0,
											PajaSystem::DeviceFeedbackC* pFeedback = 0 );
		virtual void					destroy();
		virtual void					flush();
		virtual void					activate();
		virtual HWND					get_hwnd();
		virtual bool					configure();

		virtual bool					set_fullscreen( PajaTypes::uint32 ui32Width, PajaTypes::uint32 ui32Height,
														PajaTypes::uint32 ui32BPP = 0 );
		virtual bool					set_windowed();

		virtual void					set_size( PajaTypes::int32 int32X, PajaTypes::int32 int32Y,
														PajaTypes::int32 i32Width, PajaTypes::int32 i32Height );

		// clear device
		virtual void					clear_device( PajaTypes::uint32 ui32Flags, const PajaTypes::ColorC& rColor = PajaTypes::ColorC(),
														PajaTypes::float32 f32Depth = 1.0f, PajaTypes::int32 i32Stencil = 0 );

		virtual bool					begin_draw();
		virtual void					end_draw();

		// Pushes current state and prepares to draw effects
		virtual void					begin_effects();
		virtual void					end_effects();

		virtual GraphicsBufferI*		create_graphicsbuffer();

		virtual void								set_temp_graphicsbuffer_size( PajaTypes::uint32 ui32Width, PajaTypes::uint32 ui32Height );
		//! Returns temporary graphics buffer.
		virtual GraphicsBufferI*		get_temp_graphicsbuffer( PajaTypes::uint32 ui32Flags );
		//! Frees temporary graphics buffer.
		virtual void								free_temp_graphicsbuffer( GraphicsBufferI* pGBuf );

		virtual GraphicsBufferI*		set_render_target( GraphicsBufferI* pBuffer );
		virtual GraphicsBufferI*		get_render_target();

		virtual LPDIRECT3DDEVICE9		get_d3ddevice();

		//! returns framebuffer flags.
		virtual PajaTypes::uint32		get_flags();

		void									unregister_buffer( DX9BufferC* pBuffer );

	private:

		DX9DeviceC();
		virtual ~DX9DeviceC();

		void			init_invalidate();
		void			init_validate();

		void									register_buffer( DX9BufferC* pBuffer );

		static LRESULT CALLBACK	stub_window_proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

		void	build_device_list( PajaTypes::uint32 ui32DefaultWidth, PajaTypes::uint32 ui32DefaultHeight, PajaTypes::uint32 ui32DefaultBPP );
		bool	find_depth_stencil_format( UINT iAdapter, D3DDEVTYPE rDeviceType, D3DFORMAT rTargetFormat, D3DFORMAT* pDepthStencilFormat );

		PajaTypes::uint32			m_ui32Width;
		PajaTypes::uint32			m_ui32Height;
		HWND									m_hWnd;
		LPDIRECT3D9						m_pD3D;
		LPDIRECT3DDEVICE9			m_pD3DDevice;
		D3DPRESENT_PARAMETERS	m_rD3Dpp; 
		D3DPRESENT_PARAMETERS	m_rSavedD3Dpp;

    LPDIRECT3DSTATEBLOCK9 m_pStateBlockSaved;

		LPDIRECT3DSURFACE9		m_pBackBuffer;
		LPDIRECT3DSURFACE9		m_pBackBuffer2;		
		LPDIRECT3DSURFACE9		m_pZBuffer;
		bool									m_bBuffersSaved;

		PajaTypes::uint32			m_ui32CreateFlags;

		DX9ViewportC*					m_pInterface;
		DX9GUIDrawInterfaceC*	m_pGUIDrawInterface;
		DeviceFeedbackC*			m_pFeedback;

		DWORD									m_dwClearFlagMask;

		static PajaTypes::int32		m_i32RefCount;
		static bool					m_bClassCreated;

		LONG						m_lSavedWindowStyle;
		LONG						m_lSavedExWindowStyle;
		PajaTypes::uint32			m_ui32SavedCreateFlags;
		HWND						m_hSavedParent;
		RECT						m_rSavedWindowRect;
		PajaTypes::BBox2C			m_rSavedViewport;
		bool						m_bD3DReady;
		bool						m_bLostDevice;

		DX9BufferC*			m_pCurrentBuffer;

		std::list<DX9BufferC*>	m_lstBuffers;

		PajaTypes::uint32		m_ui32TempWidth;
		PajaTypes::uint32		m_ui32TempHeight;

		struct	TempBufferS
		{
			bool							bLocked;
			PajaTypes::uint32	ui32Flags;
			PajaTypes::uint32	ui32CreationFlags;
			DX9BufferC*				pBuffer;
		};

		std::list<TempBufferS>	m_lstTempBuffers;

		struct	ModeS
		{
			PajaTypes::uint32	ui32Width;
			PajaTypes::uint32	ui32Height;
			D3DFORMAT					TargetFormat;
			D3DFORMAT					DepthStencilFormat;
		};
		std::list<ModeS>		m_lstModes;

		DWORD					m_dwCurAdapter;

	};

};

#endif // __OPENGLDEVICEC_H__