///////////////////////////////////////////////////////////////////////////////
/// @file deDriver.hpp
///
/// @brief base header for drivers
///
/// @author Lightning, Assassin
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Aug 2001
/// @author Lightning
/// @remarks Initial Creation
///
/// @date Apr 2002
/// @author Assassin
/// @remarks Vertex Buffer mods
///
/// @date May 2002
/// @author Assassin
/// @remarks Stencil-buffer and Render-to-Texture
///
/// @date Jul 2004
/// @author poly-gone
/// @remarks Floating point surface format support (DX9 driver)
/// @remarks Two sided stencil support (DX9 driver)
///
/// @todo more stencil-buffer support
/// @todo more render-to-texture capability
/// @todo pixel shader support
/// @todo poly-gone Add HDR rendering support
/// @todo poly-gone Add hard/soft shadow support
///////////////////////////////////////////////////////////////////////////////

#ifndef DEDRIVER_HPP
#define DEDRIVER_HPP

#include "deGlobalTypes.hpp"
#include "deArray.hpp"

#if defined(DEDRIVER_DLL_EXPORTS) || defined(DESTINY3D_EXPORT_ALL)
#	define DEDRIVER_API extern "C" DEDLL_EXPORT
#elif defined(DESTINY3D_STATIC_LINK)
#	define DEDRIVER_API extern "C" 
#else
#	define DEDRIVER_API extern "C" DEDLL_IMPORT
#endif

#ifdef USING_DESTINY3D
#ifdef _DEBUG
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "deDriver_sd")
#	else
#		pragma comment(lib, "deDriverd")
#	endif //DESTINY3D_STATIC_LINK
#else
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "deDriver_s")
#	else
#		pragma comment(lib, "deDriver")
#	endif //DESTINY3D_STATIC_LINK
#endif //_DEBUG
#endif //USING_DESTINY3D


//-------------------------------------------
// Class defines
//-------------------------------------------
class IdeDriver;
class IdeVertexBuffer;
class IdeShader;
class deDriverLoad;
class IdeDriverLoad;
class IdeBitmap;
class IdeBitmapProxy;
class IdeFileSystem;
class deString;
class IdeRenderState;
class IdeFile;
struct deTransformInfo;

// factory functions down bottom

//-------------------------------------------
// Typedefs
//-------------------------------------------

//struct typedefs
typedef struct deDriverInfo deDriverInfo;

//some internal typedef's
typedef deBoolean (*ISDESTINY3DDRIVER)();
typedef IdeDriver *(*GETDRIVERINSTANCE)(long ID);
typedef const deDriverInfo *(*GETDRIVERINFO)(long StructSize);



//-------------------------------------------
// Structures
//-------------------------------------------

typedef struct deDriverInfo
{
	char *	Name;		/// name of the driver
	long	Major;
	long	Minor;
	long	Revision;
	char *	DLL;		/// dll name of the driver (filled in from DriverLoad)
} deDriverInfo;

//-------------------------------------------
// Classes
//-------------------------------------------

/// The base class that every driver is derived from.
/// The driver is a generic interface between the engine or application and the
/// specific hardware API being used - usually Direct3D or OpenGL. Through this
/// interface, various rendering states are set, resources are exposed to the
/// video hardware, and rendering of geometric objects takes place. Relevant
/// details about the video hardware itself can be queried, allowing the engine
/// or an application to appropriately allocate resources and choose render states.
/// IdeDriver is the final stopping point for data from the engine or application
/// before it's shipped off to the hardware, so it does some error and
/// redundancy checking when setting states and resources.
/// An application should generally not interface directly with IdeDriver, instead
/// using the IdeRender interface to handle things in an established manner.
//class IdeDriver
DE3D_INTERFACE_(IdeDriver)
{
public:
	/// different driver types
	enum Types
	{
		DRIVER_INVALID = -1,			///< invalid option
		DRIVER_DIRECT3D8 = 0,			///< Direct3D driver	
		DRIVER_DIRECT3D9 = 2,			///< Direct3D driver	
		DRIVER_OPENGL = 1,				///< OpenGL driver
		DRIVER_COUNT,					// max value
		DRIVER_FORCE_32BIT = 0x7FFFFFFF	// force the enum size to 32bits
	};

	/// types of color formats, indicating number of bits per channel
	enum BPP
	{
		BPP_UNKNOWN = 0,		///< unknown the possible bits
		BPP_X1R5G5B5,			///< 16bit rgb, 5 bits for r, g, b
		BPP_A1R5G5B5,			///< 16bit argb, 1 bit for a, 5 bits for r, g, b
		BPP_A4R4G4B4,			///< 16bit argb, 4 bits for a, r, g, b
		BPP_X4R4G4B4,			///< 16bit rgb, 4 bits for r, g, b
		BPP_A8,					///< 8bit alpha
		BPP_R3G3B2,				///< 8bit rgb, 3 bits for r, g, 2 bits for b
		BPP_A8R3G3B2,			///< 16bit argb, 8 bits for a, 3 bits for r, g, 2 bits for b
		BPP_A2B10G10R10,		///< 32bit abgr, 2 bits for a, 10 bits for b, g, r
		BPP_G16R16,				///< 32bit rg, 16 bits for g, r
		BPP_R5G6B5,				///< 16bit rgb, 5 bits for r, b, 6 bits for g
		BPP_R8G8B8,				///< 24bit rgb, 8 bits for r, g, b
		BPP_A8R8G8B8,			///< 32bit argb, 8 bits for a, r, g, b
		BPP_X8R8G8B8,			///< 32bit rgb, 8 bits for r, g, b
		BPP_P8,					///< 8bit color indexed
		BPP_A8P8,				///< 8bit color index, 8bit alph
		BPP_L8,					///< 8bit luminance
		BPP_A8L8,				///< 16bit luminance with alpha 8 bits for a, l
		BPP_A4L4,				///< 8bit luminance with alpha, 4 bits for a, l
		BPP_V8U8,				///< 16bit bumpmap, 8 bits for v, u
		BPP_Q8W8V8U8,			///< 32bit bumpmap, 8 bits for q, w, v, u
		BPP_V16U16,				///< 32bit bumpmap, 16 bits for u, v
		BPP_W11V11U10,			///< 32bit bumpmap, 11 bits for w, v, 10 bits for u
		BPP_L6V5U5,				///< 16bit bumpmap with luminance, 6 bits for l, 5 bits for v, u
		BPP_X8L8V8U8,			///< 32bit bumpmap with luminance, 8 bits for l, v, u
		BPP_A2W10V10U10,		///< 32bit bumpmap with alpha, 2 bits for a, 10 bits for w, v, u
		BPP_UYVY,				///< UYVY format
		BPP_YUY2,				///< YUY2 format
		BPP_DXT1,				///< DXT texture compression format
		BPP_DXT2,				///< DXT texture compression format
		BPP_DXT3,				///< DXT texture compression format
		BPP_DXT4,				///< DXT texture compression format
		BPP_DXT5,				///< DXT texture compression format
		BPP_R16F,				///< 16-bpc single channel floating point format
		BPP_G16R16F,			///< 16-bpc double channel floating point format
		BPP_A16B16G16R16F,		///< 16-bpc ABGR floating point format
		BPP_R32F,				///< 32-bpc single channel floating point format
		BPP_G32R32F,			///< 32-bpc double channel floating point format
		BPP_A32B32G32R32F,		///< 32-bpc ABGR floating point format
		BPP_COUNT,				// max value
		BPP_FORCE_32BIT = 0x7FFFFFFF	// force the enum size to 32bits
	};

	/// possible z-buffer formats
	enum ZPP
	{
		ZPP_UNKNOWN = 0,		///< bad value
		ZPP_D16,				///< 16-bit depth buffer
		ZPP_D15S1,				///< 15-bit depth with 1-bit stencil (0,1)
		ZPP_D24,				///< 24-bit depth buffer
		ZPP_D24S4,				///< 24-bit depth with 4-bit stencil (0-15)
		ZPP_D24S8,				///< 24-bit depth with 8-bit stencil (0-255)
		ZPP_D32,				///< 32-bit depth (some cards might not work with this)
		ZPP_COUNT,
		ZPP_FORCE_32BIT = 0x7FFFFFFF
	};

	/// list of renderstates that can be changed.
	/// specify deTRUE or deFALSE as the 2nd parameter to SetRenderState unless otherwise noted
	enum RenderState
	{
		RENDER_ZENABLE = 0,				///< enable z buffer for depth testing
		RENDER_ZENABLEUSEW,				///< enable w buffer for depth testing
		RENDER_ZWRITESENABLE,			///< enable z-buffer writes
		RENDER_DEPTHFUNCTION,			///< type of depth compare to do (2nd param: RenderCmpFunc)
		RENDER_DEPTHBIAS,				///< bias to apply when coplanar faces are rendered. higher is closer.
		RENDER_FILLMODE,				///< type of fill mode (2nd param: RenderFillMode)
		RENDER_SHADEMODE,				///< type of shading (2nd param: RenderShadeMode)
		RENDER_COLORMASK,				///< mask for color channels (2nd param: deARGB with zero or non-zero in each channel)
		RENDER_ALPHATESTENABLE,			///< enable alpha testing on tri's
		RENDER_ALPHAREF,				///< reference alpha value to test against (2nd param: DWORD value)
		RENDER_ALPHAFUNCTION,			///< type of alpha compare to do (2nd param: RenderCmpFunc)
		RENDER_ALPHABLENDENABLE,		///< enable alpha blending
		RENDER_SOURCEBLEND,				///< type of blending on source (2nd param: RenderBlend)
		RENDER_DESTBLEND,				///< type of blending on dest (2nd param: RenderBlend)
		RENDER_TEXTUREFACTOR,			///< color to be used on multi-tex blending (2nd param: deARGB color)
		RENDER_CULLMODE,				///< type of culling (2nd param: RenderCullMode)
		RENDER_FSAAENABLE,				///< enable full-scene anti-aliasing
		RENDER_FSAAMASK,				///< set the mask for FSAA (example: 0x05)
		RENDER_FOGENABLE,				///< enable fogging (0 = off, 1 = depth-based, 2 = range-based)
		RENDER_FOGSTART,				///< start of fog as float, *((long *)&FogStart) to pass
		RENDER_FOGEND,					///< end of fog as float, *((long *)&FogStart) to pass
		RENDER_FOGCOLOR,				///< color of fod (2nd param: deARGB color)
		RENDER_CLIPPINGENABLE,			///< enable clipping
		RENDER_SWVERTEXPROCESS,			///< enable software vertex processing
		RENDER_HWLIGHTINGENABLE,		///< enable fixed-function vertex lighting
		RENDER_AMBIENTLIGHT,			///< ambient light color value (2nd param: deARGB color)
		RENDER_DITHERENABLE,			///< enable dithering, useful in 16-bit display modes
		RENDER_SPECULARENABLE,			///< enable specular highlighting for fixed-function lighting
		RENDER_SPECULARPERSPECTIVE,		///< set specular calculations to use perspective projection
		RENDER_PERVERTEXCOLOR,			///< enable per-vertex color values to be used in lighting model
		RENDER_STENCILENABLE,			///< enable stencil buffering
		RENDER_TWOSIDEDSTENCILENABLE,	///< enable two sided stencil buffering
		RENDER_STENCILREF,				///< set the stencil reference value (2nd param: DWORD value, default value: 0)
		RENDER_STENCILMASK,				///< set the stencil mask value (2nd param: DWORD value, default value: 0xFFFFFFFF)
		RENDER_STENCILWRITEMASK,		///< set the stencil write-mask value (2nd param: DWORD value, default value: 0xFFFFFFFF)
		RENDER_STENCILFUNCTION,			///< type of stencil comparison to perform (2nd param: RenderCmpFunc)
		RENDER_STENCILFAIL,				///< operation to perform when both the stencil and depth tests fail (2nd param: RenderStencilOp)
		RENDER_STENCILZFAIL,			///< operation to perform when stencil test passes and depth test fails (2nd param: RenderStencilOp)
		RENDER_STENCILPASS,				///< operatoin to perform when both the stencil and depth tests pass (2nd param: RenderStencilOp)
		RENDER_CCW_STENCILFUNCTION,		///< type of stencil comparison to perform for second stencil "side" (2nd param: RenderCmpFunc)
		RENDER_CCW_STENCILFAIL,			///< operation to perform when both the stencil and depth tests fail (2nd param: RenderStencilOp)
		RENDER_CCW_STENCILZFAIL,		///< operation to perform when stencil test passes and depth test fails for second stencil "side" (2nd param: RenderStencilOp)
		RENDER_CCW_STENCILPASS,			///< operation to perform when both the stencil and depth tests pass for second stencil "side" (2nd param: RenderStencilOp)
		RENDER_COUNT,					//number of renderstates
		RENDER_FORCE_32BIT = 0x7FFFFFFF
	};

	/// list of fill modes for RENDER_FILLMODE
	enum RenderFillMode
	{
		FILL_POINT = 0,			///< just show points
		FILL_WIREFRAME,			///< show a wireframe view
		FILL_SOLID,				///< show everything in solid (default behavior, can still render lines)
		FILL_COUNT,				//number of fills
		FILL_FORCE_32BIT = 0x7FFFFFFF
	};

	/// list of culling modes for RENDER_CULLMODE
	enum RenderCullMode
	{
		CULL_NONE = 0,		///< no culling
		CULL_CW,			///< cull backfaces with clockwise vertex winding
		CULL_CCW,			///< cull backfaces with counter-clockwise vertex winding
		CULL_COUNT,			//number of culls
		CULL_FORCE_32BIT = 0x7FFFFFFF
	};

	/// list of shading modes for RENDER_SHADEMODE
	enum RenderShadeMode
	{
		SHADE_FLAT = 0,		///< flat shading
		SHADE_GOURAUD,		///< gouraud shading
		SHADE_COUNT,		//number of shades
		SHADE_FORCE_32BIT = 0x7FFFFFFF
	};

	/// function for comparing values when performing per-pixel tests
	enum RenderCmpFunc
	{
		COMPARE_NEVER = 0,		///< never use pixel
		COMPARE_LESS,			///< use pixel if value is less than current
		COMPARE_EQUAL,			///< use pixel if equal value
		COMPARE_LESSEQUAL,		///< use pixel if less than or equal to current (default depth comparison)
		COMPARE_GREATER,		///< use pixel if greater than current
		COMPARE_GREATEREQUAL,	///< use pixel if greater than or equal to current
		COMPARE_NOTEQUAL,		///< use pixel if not equal to current
		COMPARE_ALWAYS,			///< always use pixel (default stencil comparison, default alpha comparison)
		COMPARE_COUNT,			//count of compares
		COMPARE_FORCE_32BIT = 0x7FFFFFFF
	};

	/// operation to perform for stenciling.
	/// "max" value is (2^n)-1 where n is the bit-depth of the stencil buffer (unsigned integer).
	/// (StencilRef & StencilMask) RenderCmpFunc (StencilBufferValue & StencilMask)
	enum RenderStencilOp
	{
		STENCIL_KEEP = 0,	///< (default value) keep the current value 
		STENCIL_ZERO,		///< set the stencil-buffer entry to 0
		STENCIL_REPLACE,	///< replace the stencil-buffer entry with the reference value
		STENCIL_INCRWRAP,	///< increment the stencil-buffer entry, clamping to max
		STENCIL_DECRWRAP,	///< decrement the stencil-buffer entry, clamping to 0
		STENCIL_INVERT,		///< invert the bits in the stencil-buffer entry
		STENCIL_INCR,		///< increment the stencil-buffer entry, wrapping to 0
		STENCIL_DECR,		///< decrement the stencil-buffer entry, wrapping to max
		STENCIL_COUNT,
		STENCIL_FORCE_32BIT = 0x7FFFFFFF
	};

	/// blending operation to perform
	enum RenderBlend
	{
		BLEND_ZERO = 0,				///< never overwrite
		BLEND_ONE,					///< always overwrite
		BLEND_SOURCE,				///< blend with source
		BLEND_INVERSESOURCE,		///< blend with inverse source
		BLEND_SOURCEALPHA,			///< blend with source alpha
		BLEND_INVERSESOURCEALPHA,	///< blend with inverse source alpha
		BLEND_DEST,					///< blend with destination
		BLEND_INVERSEDEST,			///< blend with inverse destination alpha
		BLEND_DESTALPHA,			///< blend with destination alpha
		BLEND_INVERSEDESTALPHA,		///< blend with inverse destination alpha
		BLEND_SOURCEALPHASAT,		///< blend with source alpha saturation
		BLEND_COUNT,				//number of blends
		BLEND_FORCE_32BIT = 0x7FFFFFFF
	};

	/// resource types to feed into ValidFormat
	enum Resource
	{
		RESOURCE_UNKNOWN = -1,		///< invalid value
		RESOURCE_DISPLAY,			///< resource is a full-screen display
		RESOURCE_DISPLAYWINDOWED,	///< resource is a windowed display
		RESOURCE_TEXTURE,			///< resource is a texture
		RESOURCE_RENDERTARGET,		///< resource is a color-buffer render-target
		RESOURCE_DEPTHSTENCIL,		///< resource is a z-buffer with depth and possibly stencil information
		RESOURCE_FSAA,				///< resource alias for a full-scene anti-aliased device
		RESOURCE_FSAAWINDOWED,		///< resource alias for a full-scene anti-aliased device, in windowed mode
		RESOURCE_COUNT,
		RESOURCE_FORCE_32BIT = 0x7FFFFFFF
	};

	/// settings for how the engine should allow quality compromises
	enum QualityFlag
	{
		QUALITY_UNKNOWN = -1,
		QUALITY_ALLOW_TEXTURE_MANGLING,		///< allow the engine to resize and adjust bitdepth of textures. boolean value.
		QUALITY_ALLOW_INVALID_TEXTURES,		///< engine will complain but allow invalid (bitdepth or size) textures to be created. boolean value.
		QUALITY_FLAG_COUNT,
		QUALITY_FORCE_32BIT = 0x7FFFFFFF
	};

	/// a basic struct used to hold display information
	struct deDisplay
	{
		long		Adapter;		///< adapter number
		long		Width;			///< the width of the display
		long		Height;			///< the height
		HMONITOR	MonitorHandle;	///< the handle to the attached monitor
		BPP			BackBpp;		///< the BPP format for the backbuffer/rendertarget
		BPP			FrontBpp;		///< the BPP format for the actual display
		ZPP			Zpp;			///< the Z-buffer format for the display
		long		ZDepth;			///< bit-depth for the depth channel
		long		StencilDepth;	///< bit-depth for the stencil channel
		long		RefreshRate;	///< the refresh rate of the screen, in Hertz
		long		FSAASamples;	///< number of anti-aliasing samples to take per screen pixel
		deBoolean	TripleBuffer;	///< enable triple-buffering, which can alleviate frame timing issues with VSync enabled.
		deBoolean	Windowed;		///< false for full-screen, true for windowed
		deBoolean	IgnoreVSync;	///< set to true to disable v-sync
	};

	/// structure for keeping track of things that happen between BeginFrame calls
	struct deDriverStats
	{
		long VBufferUploads;		///< number of driver vertex buffer uploads
		long TextureUploads;		///< number of driver texture uploads
		long BytesUsed;				///< number of unique bytes of data referenced during the frame
	};

	/// structure for evaluating the capabilities of a hardware device
	struct deDriverCaps
	{
		char		AdapterDescription[255];	///< name of the video card, as it identifies itself
		deBoolean	HWTnL;				///< does the card support hardware transform and lighting?
		deBoolean	Dot3Support;		///< does the card support dot-product3 for textures?
		long		MaxTextureBitDepth;	///< highest texture bitdepth (16 for old cards, 32 or higher for new ones)
		long		SimulTextures;		///< number of textures that can be used at once to render
		long		TexWidth;			///< maximum texture width
		long		TexHeight;			///< maximum texture height
		long		NumStreams;			///< number of vertex streams supported
		long		MaxVert;			///< highest index value for a vertex
		long		MaxPrim;			///< maximum number of primitives renderable in a call
		long		MaxLights;			///< limit of lights in hardware fixed-function pipeline
		long		VertCacheSize;		///< number of vertices stored in post-transform cache (if known)
		deFloat		VShader;			///< supported version number of vertex shader/program
		deFloat		PShader;			///< supported version number of pixel/fragment shader/program
	};

protected:
	virtual ~IdeDriver() {}
public:
	/// Delete the object
	virtual long Release() = 0;
	virtual deBoolean Init(HWND WindowHandle) = 0;
	//display modification functions

	/// Set the display up, creating a new internal render device
	/// @param Display [in] user-defined display settings, may not be NULL
	virtual deBoolean SetDisplay(deDisplay *Display) = 0;
	/// Reset the driver, possibly with altered display properties.
	/// Resetting will cause all vertex buffers and textures to be flushed
	/// @param Display [in] user-defined display settings, may be NULL to keep current settings
	virtual deBoolean Reset(deDisplay *Display = NULL) = 0;
	/// Get a pointer to the driver's internally-held display struct
	virtual const deDisplay* GetDisplay() const = 0;
	/// Fill a deDisplay with an adapter's CURRENT (even un-renderable) display settings.
	/// If a fullscreen rendering mode has not been set up, this will be the desktop settings.
	virtual deBoolean GetCurrentDisplay(long Adapter, deDisplay * Display) const = 0;
	/// Feed in a display struct to be filled in for the enumerated mode
	/// @param Display [in, out] pointer to a user-created deDisplay struct to be filled in, may not be NULL
	virtual deBoolean GetDisplayMode(long Adapter, long Mode, deDisplay *Display) const = 0;
	/// Fill a deDriverCaps structure with an adapter's device capabilities
	virtual const deDriverCaps* GetCaps(long Adapter) const = 0;
	/// Update the driver's knowledge of the client-window rect
	virtual deRect UpdateWindowRect() = 0;
	/// Get the driver's internally-held client-window rect
	virtual deRect GetDisplayRect() const = 0;
	
	/// Get the number of adapters supported under this driver
	virtual long GetAdapterCount() const = 0;
	/// Get the number of modes for a particular adapter
	virtual long GetModeCount(long Adapter) const = 0;
	/// Test whether windowed mode is allowed on a particular adapter
	virtual deBoolean WindowedAllowed(long Adapter) const = 0;
	/// Test for a valid format for various resource types
	virtual deBoolean ValidFormat(long Adapter, Resource ResourceType, BPP BPPType, ZPP ZPPType, BPP FrontBuffer, long ExtraFlag=0) const = 0;
	/// Get the bit-depth of a particular color format
	virtual long BitDepth(BPP BPPType) const = 0;
	/// Get the bit-depth of a particular z-buffer format
	virtual long BitDepth(ZPP ZPPType) const = 0;
	/// Get the bit-depth devoted to stencil channel in z-buffer format
	virtual long StencilDepth(ZPP ZPPType) const = 0;
	/// Test whether a particular z-buffer format supports stenciling
	virtual deBoolean HasStencil(ZPP ZPPType) const = 0;
	
	//vertex buffer functions
	/// Add a vertex buffer to the driver
	virtual deBoolean AddVertexBuffer(IdeVertexBuffer *Vertex) = 0;
	/// Remove a vertex buffer from the driver
	virtual deBoolean RemoveVertexBuffer(IdeVertexBuffer *Vertex) = 0;
	/// Update a vertex buffer so the driver's internal data matches it
	virtual deBoolean UpdateVertexBuffer(IdeVertexBuffer *Vertex) = 0;

	// Shader functions (incomplete)
	virtual deBoolean AddShader(IdeShader * Shader) = 0;
	virtual deBoolean SetShader(IdeShader * Shader) = 0;
	virtual deBoolean RemoveShader(IdeShader * Shader) = 0;

	//frame functions
	/// Call before rendering anything
	virtual	deBoolean BeginFrame() = 0;
	/// Finish the render and update the front-buffer
	virtual deBoolean EndFrame() = 0;
	
	/// Clear the frame with a particular color
	virtual deBoolean ClearFrame(deARGB Color, deBoolean ClearTarget = deTRUE, deBoolean ClearZBuffer = deTRUE, deBoolean ClearStencil = deTRUE) = 0;

	/// Render the selected Vertex Buffer to the back-buffer
	virtual deBoolean Render(IdeVertexBuffer *VBuffer, long IndexOffset, IdeVertexBuffer *IndexOverride = NULL) = 0;

	//viewport/FOV functions
	/// Set the screen-space viewport
	virtual deBoolean SetViewport(long X, long Y, long Width, long Height, deFloat MinZ, deFloat MaxZ) = 0;
	virtual deBoolean SetDepthRange(deFloat MinZ, deFloat MaxZ) = 0;
	/// Set up a perspective view transformation
	virtual deBoolean SetFOVClipping(deFloat FOV, deFloat Aspect, deFloat ClipNear, deFloat ClipFar) = 0;
	/// Set up an orthographic (parallel projection) view transformation
	virtual deBoolean SetOrthoClipping(deFloat Width, deFloat Height, deFloat ClipNear, deFloat ClipFar, deBoolean Invert = deFALSE) = 0;
	/// Set up a perspective view transformation with a sub-rect specified in the [0,1] range
	virtual deBoolean SetFOVClippingSubRect(deFloat FOVY, deFloat Aspect, deFloat ClipNear, deFloat ClipFar, deRect SubRect) = 0;
	virtual deBoolean SetFOVClippingSubRectFloat(deFloat FOVY, deFloat Aspect, deFloat ClipNear, deFloat ClipFar, deFloatRect SubRect) = 0;
	/// Set up an orthographic (parallel projection) view transformation with a sub-rect specified in the [0,1] range
	virtual deBoolean SetOrthoClippingSubRect(deFloat Width, deFloat Height, deFloat ClipNear, deFloat ClipFar, deBoolean Invert, deRect SubRect) = 0;
	virtual deBoolean SetOrthoClippingSubRectFloat(deFloat Width, deFloat Height, deFloat ClipNear, deFloat ClipFar, deBoolean Invert, deFloatRect SubRect) = 0;
	virtual deBoolean SetScissorRect(deRect ScissorRect) = 0;
	
	//camera transformation functions
	/// Set the camera transform (position and orientation)
	virtual deBoolean SetCameraTransform(deTransformInfo *M) = 0;

	//world transformation functions
	/// Set the world transform (to take things from "object space" to "world space")
	virtual deBoolean SetWorldTransform(deTransformInfo * Mat) = 0;

	// texture transformation functions
	/// Set the texture transform for a particular stage
	virtual deBoolean SetTextureTransform(long StageNum, deTransformInfo * Mat) = 0;
	
	//texture functions
	/// Adds a bitmap to the driver, turning it into a driver texture, and possibly a render-target.
	virtual deBoolean AddBitmap(IdeBitmap *Bitmap) = 0;
	/// Adds a bitmap to the driver, turning it into a driver texture, and possibly a render-target.
	virtual deBoolean AddBitmapProxy(IdeBitmapProxy *BitmapProxy) = 0;
	/// Removes a bitmap from a driver by deleting the internal driver texture.
	virtual deBoolean RemoveBitmap(IdeBitmap *Bitmap) = 0;

	//render-to-texture functions
	/// Sets the current render-target to the bitmap passed in, if the bitmap
	/// can be a render-target.
	/// @param pBitmap [in] Bitmap that is a render-target to be rendered to. This bitmap
	///                will only act as a handle to the internal driver texture being used,
	///                it doesn't contain a copy of what the video card's texture stores
	virtual deBoolean RenderTo(IdeBitmap *pBitmap, long CubeMapFace = 0) = 0;
	/// Copies the frontbuffer into the bitmap specified
	/// cannot be a render-target
	/// @param pBitmap [out] Bitmap pointer that is to have the screen data copied into.
	///                A new deBitmap object will be created internally, and its address stored into this parameter.
	///                After the data is copied, you must save the file to disk manually, if desired.
	virtual deBoolean ScreenShot(IdeBitmap * &pBitmap, deBoolean GrabWindow = deTRUE) = 0;
	virtual deBoolean GetVideoTexture(IdeBitmap* pBitmap, long CubeMapFace = 0) = 0;

	//render states
	/// Get current value of the State passed in
	virtual unsigned long GetRenderState(RenderState State) = 0;
	/// Set a class-based render-state (texture, material, or light).
	virtual deBoolean SetRenderState(const IdeRenderState *State) = 0;
	/// Set a value-based render-state
	virtual deBoolean SetRenderState(RenderState State, unsigned long Value) = 0;
	virtual deBoolean EnableLight(long LightID, deBoolean Enable) = 0;
	/// Disable all fixed-function lights
	virtual deBoolean DisableAllLights() = 0;
	/// Get the status of a particular quality flag
	virtual unsigned long GetQualityFlag(QualityFlag Flag) = 0;
	/// Set the status of a particular quality flag
	virtual deBoolean SetQualityFlag(QualityFlag Flag, unsigned long Value) = 0;

	//driver info
	/// Get the type of driver this is
	virtual IdeDriver::Types GetType() const = 0;
	/// Get some information about the driver
	virtual deDriverInfo *GetInfo() const = 0;
	virtual long GetCount() = 0;

	//logging info
	/// Log text to the driver's log file
	virtual void LogInfo(char *Data, ...) = 0;
	/// Get a pointer to the driver's internal statistics structure
	virtual deDriverStats* GetDriverStats() = 0;
	/// Reset the driver's internal statistics structure to all zeroes
	virtual void ResetDriverStats() = 0;
};

/// used to load up a driver from a set location.
/// Related functions: IdeDriverLoad_CreateDriverLoad
//class IdeDriverLoad
DE3D_INTERFACE_(IdeDriverLoad)
{
protected:
	virtual ~IdeDriverLoad() {}
public:
	virtual long Release() = 0;

	//basic driver info functions
	/// get the number of drivers found
	virtual long GetCount() = 0;
	virtual const deDriverInfo *GetInfo(long DriverNumber) = 0;
	virtual const deDriverInfo *GetInfo(char *DriverName) = 0;
	/// get an instance of an enumerated driver
	virtual IdeDriver *GetDriver(long DriverNumber) = 0;
	virtual IdeDriver *GetDriver(char *DriverName) = 0;
};

/// used to store vertex information in order to render triangulated meshes.
/// Related functions: IdeVertexBuffer_CreateVBuffer, IdeVertexBuffer_CreateSubVBuffer
//class IdeVertexBuffer : virtual public IdeRefCountBase
DE3D_INTERFACE(IdeVertexBuffer, IdeRefCountBase)
{
public:
	/// internal buffer types possible to create and use
	enum BufferType
	{
		BUFFER_POSITION = 0,
		BUFFER_NORMAL,
		BUFFER_DIFFUSE,
		BUFFER_SPECULAR,
		BUFFER_TEXTURECOORDS0,
		BUFFER_TEXTURECOORDS1,
		BUFFER_TEXTURECOORDS2,
		BUFFER_TEXTURECOORDS3,
		BUFFER_TEXTURECOORDS4,
		BUFFER_TEXTURECOORDS5,
		BUFFER_TEXTURECOORDS6,
		BUFFER_TEXTURECOORDS7,
		BUFFER_INDICES16,
		BUFFER_INDICES32,
		BUFFER_COUNT,
		BUFFER_FORCE_32BIT = 0x7FFFFFFF
	};

	/// type of rendering for the buffer
	enum RenderType
	{
		RENDER_POINTLIST = 0,
		RENDER_LINELIST,
		RENDER_LINESTRIP,
		RENDER_TRIANGLELIST,
		RENDER_TRIANGLESTRIP,
		RENDER_TRIANGLEFAN,
		RENDER_COUNT,
		RENDER_FORCE_32BIT = 0x7FFFFFFF
	};

	/// data types that the different buffers are (with different byte-sizes)
	enum BufferDataType
	{
		BUFFER_DATALONG = 0,
		BUFFER_DATAFLOAT,
		BUFFER_DATAFLOAT2,
		BUFFER_DATAFLOAT3,
		BUFFER_DATASHORT,
		BUFFER_DATACOUNT,
		BUFFER_DATAFORCE_32BIT = 0x7FFFFFFF
	};

	/// types of vbuffer that this could be
	enum VBufferType
	{
		BUFFERTYPE_REAL = 0,
		BUFFERTYPE_SUB,
		BUFFERTYPE_COUNT,
		BUFFERTYPE_FORCE_32BIT = 0x7FFFFFFF
	};

protected:
	//destructor
	virtual ~IdeVertexBuffer() {}

public:
	virtual const IdeVertexBuffer& operator=(const IdeVertexBuffer &S) = 0;

	//buffer information
	virtual void* GetBuffer(BufferType Type) const = 0;

	//vertex information
	virtual long GetVertexCount() const = 0;
	virtual long GetVertexStart() const = 0;

	//index information
	virtual long GetIndexCount() const = 0;
	virtual long GetIndexStart() const = 0;

	//tri information
	virtual long GetTriCount() const = 0;
	virtual deBoolean CalcTriCount() = 0;

	//static/dynamic information
	virtual deBoolean GetDynamicStatusVertex() const = 0;
	virtual deBoolean GetDynamicStatusIndex() const = 0;
	virtual void SetDynamicStatus(deBoolean Vertex, deBoolean Index) = 0;

	//type of rendering we are doing
	virtual RenderType GetRenderType() const = 0;
	virtual deBoolean SetRenderType(RenderType Type) = 0;

	//buffer functions
	virtual deBoolean SetBufferSize(long EntryCount, deBoolean IndicesNotVertices = deFALSE) = 0;
	virtual deBoolean CreateBuffer(BufferType Type, deBoolean Clear) = 0;
	virtual deBoolean DestroyBuffer(BufferType Type) = 0;
	virtual deBoolean FillBuffer(BufferType Type, const void *Buffer, long StartEntry, long EntryCount) = 0;
	virtual void DirtyBuffer(BufferType Type) = 0;
	virtual deBoolean BufferExists(BufferType Type) const = 0;

	//for doing separate index and data buffers
	virtual deBoolean BindDataBuffer(IdeVertexBuffer* DataBuffer) = 0;
	virtual IdeVertexBuffer* GetBoundDataBuffer() const = 0;

	//a function to obtain the buffer data type
	virtual BufferDataType GetBufferDataType(BufferType Type, long *Size) const = 0;

	//lock/unlock functions
	virtual deBoolean Lock() = 0;
	virtual deBoolean Unlock() = 0;

	//functions for the driver class to tell the vertex class of info to store
	virtual deBoolean SetDriverBuffer(long ID, void *Buffer, IdeDriver * Driver) = 0;
	virtual void *GetDriverBuffer(long ID, long *BufferUpdateList) const = 0;

	// stuff for the sub-vbuffer capability
	virtual VBufferType GetVBufferType() const = 0;
	virtual IdeVertexBuffer* GetParentBuffer() const = 0;
};

/// a rewritten vertex buffer class
/// (new, not finished yet)
//class IdeVertexBuffer2 : public IdeRefCountBase
DE3D_INTERFACE(IdeVertexBuffer2, IdeRefCountBase)
{
public:
	/// type of rendering for the buffer
	enum Primitive_t
	{
		RENDER_POINTLIST = 0,	///< render points (v1),(v2)...
		RENDER_LINELIST,		///< render lines (v1,v2),(v3,v4)...
		RENDER_LINESTRIP,		///< render lines (v1,v2),(v2,v3)...
		RENDER_TRIANGLELIST,	///< render triangles (v1,v2,v3),(v4,v5,v6)...
		RENDER_TRIANGLESTRIP,	///< render triangles (v1,v2,v3),(v3,v2,v4)...
		RENDER_TRIANGLEFAN,		///< render triangles (v1,v2,v3),(v1,v4,v5)...
		RENDER_COUNT,
		RENDER_FORCE_32BIT = 0x7FFFFFFF
	};
	/// Usage specifier for a vertex stream.
	enum DataUsage_t
	{
		// basic
		USAGE_POSITION = 0,	///< untransformed position
		USAGE_NORMAL,		///< vertex normal
		USAGE_TEXCOORD,		///< texture coordinates
		USAGE_COLOR,		///< vertex color
		// esoteric
		USAGE_TANGENT,		///< 
		USAGE_BINORMAL,		///< 
		USAGE_BLENDWEIGHT,	///< 
		USAGE_BLENDINDICES,	///< 
		USAGE_FOG,			///< 
		USAGE_TESSFACTOR,	///< 
		USAGE_POSITION_T,	///< 
		USAGE_DEPTH,		///< 
		USAGE_SAMPLE,		///< 
		USAGE_COUNT,
		USAGE_FORCE_32BIT = 0x7FFFFFFF
	};
	
	/// Data types that the different buffers are (with different byte-sizes).
	/// All have sizes that are multiples of 32 bytes, and may be padded if necessary.
	enum DataType_t
	{
		DATA_FLOAT32_1,		///< (float_1, 0, 0, 1)
		DATA_FLOAT32_2,		///< (float_1, float_2, 0, 1)
		DATA_FLOAT32_3,		///< (float_1, float_2, float_3, 1)
		DATA_FLOAT32_4,		///< (float_1, float_2, float_3, float_4)
		DATA_ARGB,			///< (R, G, B, A)
		DATA_U8_4,			///< (u8_1, u8_2, u8_3, u8_4)
		DATA_S16_2,			///< (s16_1, s16_2, 0, 1)
		DATA_S16_4,			///< (s16_1, s16_2, s16_3, s16_4)
		DATA_U8_4N,			///< normalized version of DATA_U8_4
		DATA_S16_2N,		///< normalized version of DATA_S16_2
		DATA_S16_4N,		///< normalized version of DATA_S16_4
		DATA_U16_2N,		///< normalized, unsigned version of DATA_S16_2
		DATA_U16_4N,		///< normalized, unsigned version of DATA_S16_4
		DATA_U10_3,			///< (u10_1, u10_2, u10_3, 1)
		DATA_S10_3N,		///< normalized, signed version of DATA_U10_3
		DATA_FLOAT16_2,		///< (float_1, float_2, 0, 1)
		DATA_FLOAT16_4,		///< (float_1, float_2, float_3, float_4)
		DATA_COUNT,
		DATA_FORCE_32BIT = 0x7FFFFFFF
	};
	enum StreamFlag_t
	{
		FLAG_DYNAMIC,
		FLAG_INSTANCES,
		FLAG_COUNT,
		FLAG_FORCE_32BIT = 0x7FFFFFFF
	};
	struct UsageDescriptor_t
	{
		DataUsage_t Usage;		///< semantic of vertex element
		u32			UsageIndex;	///< instance of this semantic
	};
	/// Used to store the specifics of a vertex element
	struct StreamDescriptor_t
	{
		UsageDescriptor_t Usage;	///< how the element is to be used
		DataType_t	Type;			///< what kind of data is stored in the element
	};
	
protected:
	virtual ~IdeVertexBuffer2() {}
public:
/// @todo implement IdeVertexBuffer2

	virtual void*		LockStream(UsageDescriptor_t element) = 0;
	virtual deBoolean	UnlockStream(UsageDescriptor_t element, deBoolean modified = deTRUE) = 0;
	virtual deBoolean	CreateStream(UsageDescriptor_t element, DataType_t datatype) = 0;
	virtual deBoolean	SetStreamFlag(UsageDescriptor_t element, StreamFlag_t flag, u32 value) = 0;
	virtual deBoolean	GetStreamFlag(UsageDescriptor_t element, StreamFlag_t flag, u32* value) = 0;

	virtual DataType_t	GetStreamDataType(UsageDescriptor_t element) const = 0;
	virtual deBoolean	StreamExists(UsageDescriptor_t element) const = 0;

	virtual deBoolean	SetVertexCount(u32 count) = 0;
	virtual deBoolean	SetIndexCount(u32 count) = 0;
	virtual deBoolean	SetPrimitiveType(Primitive_t primitiveType) = 0;

	virtual u32			GetVertexCount() const = 0;
	virtual u32			GetIndexCount() const = 0;
	virtual u32			GetPrimitiveCount() const = 0;
	virtual Primitive_t	GetPrimitiveType() const = 0;

	//functions for the driver class to tell the vertex class of info to store
	virtual deBoolean	DriverSetInfo(IdeDriver * pDriver, void *Info) = 0;
	virtual void *		DriverGetInfo(IdeDriver * pDriver, deBoolean* &UpdatedStreams) const = 0;
	virtual u32			DriverGetNumStreams() = 0;
	virtual StreamDescriptor_t*	DriverGetStreamDescriptors();
	virtual u32			DriverLock() = 0;
	virtual u32			DriverUnlock() = 0;
};

/// The interface for vertex and pixel shaders
//class IdeShader : virtual public IdeRefCountBase
DE3D_INTERFACE(IdeShader, IdeRefCountBase)
{
public:
	/// Shader types.
	enum ShaderType
	{
		SHADER_INVALID = -1,	///< Invalid Shader
		SHADER_VERTEX,			///< Vertex shader
		SHADER_PIXEL,			///< Pixel shader
		SHADER_FORCE_32BIT = 0x7FFFFFFF ///< Force a 32 bit enum
	};

	/// Shader instruction types
	enum deShaderInstructionType
	{
		INSTRUCTION_VERSION_VERTEX = 0,	///< Vertex Shader Version Instruction
		INSTRUCTION_VERSION_PIXEL,		///< Pixel Shader Version Instruction
		INSTRUCTION_ADD,				///< "add" instruction
		INSTRUCTION_DP3, 				///< "dp3" instruction
		INSTRUCTION_DP4, 				///< "dp4" instruction
		INSTRUCTION_DST, 				///< "dst" instruction
		INSTRUCTION_EXPP,				///< "expp" instruction
		INSTRUCTION_LIT,				///< "lit" instruction
		INSTRUCTION_LOGP,				///< "logp" instruction
		INSTRUCTION_MAD,				///< "mad" instruction
		INSTRUCTION_MAX,				///< "max" instruction
		INSTRUCTION_MIN,				///< "min" instruction
		INSTRUCTION_MOV,				///< "mov" instruction
		INSTRUCTION_MUL,				///< "mul" instruction
		INSTRUCTION_RCP,				///< "rcp" instruction
		INSTRUCTION_RSQ,				///< "rsq" instruction
		INSTRUCTION_SGE,				///< "sge" instruction
		INSTRUCTION_SLT,				///< "slt" instruction
		INSTRUCTION_SUB,				///< "sub" instruction
		INSTRUCTION_DECLARE_CONSTANT,	///< "DECLARE_CONSTANT" instruction
		INSTRUCTION_DECLARE_MATRIX,		///< "DECLARE_MATRIX" instruction
		INSTRUCTION_FORCE_32BIT = 0x7FFFFFFF ///< Force a 32-Bit enumeration
	};

	// Shader arguments
	enum Argument
	{
		ARGUMENT_INVALID = 0,					///< Invalid Argument
		ARGUMENT_VERSION_1 = 0x00000001,		///< 1.0 version argument
		ARGUMENT_CONSTANT = 0x00010000,			///< Constant registers start
		ARGUMENT_TEMP = 0x00610000,				///< Temporary registers start
		ARGUMENT_VERTEX = 0x006D0000,			///< Vertex data registers Start
		ARGUMENT_OUTPOS = 0x007D0000,			///< Output position register
		ARGUMENT_OUTCOLOR = 0x007E0000,			///< Output color registers
		ARGUMENT_OUTFOG = 0x00800000,			///< Output fog register
		ARGUMENT_OUTPTS = 0x00810000,			///< Point size register
		ARGUMENT_OUTTEX = 0x00820000,			///< Output texture coordinates registers start
		ARGUMENT_OUTTEX_END = 0x008A0000,		///< Output texture coordinates registers end
		ARGUMENT_DE_TRANSFORM = 0,				///< DE_TRANSFORM argument
		ARGUMENT_DE_PROJECTION = 1,				///< DE_PROJECTION argument
		ARGUMENT_DE_TRANSFORM_PROJECTION = 2,	///< DE_TRANSFORM_PROJECTION argument
		ARGUMENT_DE_IDENTITY = 3,				///< DE_IDENTITY argument
		ARGUMENT_DE_INVERSE = 4,				///< DE_INVERSE argument
		ARGUMENT_DE_TRANSPOSE = 5,				///< DE_TRANSPOSE argument
		ARGUMENT_DE_INVERSE_TRANSPOSE = 6,		///< DE_INVERSE_TRANSPOSE argument
		ARGUMENT_FORCE_32BIT = 0x7FFFFFFF ///< Force a 32-Bit enumeration
	};

	/// A struct used to hold information about a shader instruction
	struct deShaderInstruction
	{
		deShaderInstructionType Type;
		DWORD Arguments[3];
	};

	/// A struct used to hold information about a shader constant
	struct deShaderConstant
	{
		deShaderInstructionType Type;
		float Arguments[5];
	};

protected:
	// destructor
	virtual ~IdeShader() {}

	// Public member functions
public:
	/// Assembles a shader.
	/// @param Code [in] Shader code to assemble.
	/// @param ErrorCallback [in] Callback function that is called when parsing errors occur.
	virtual deBoolean Assemble(char * Code,void (*ErrorCallback)(long LineNumber,char * Error)) = 0;

	/// Disassembles the shader.
	/// @param Code [out] A pointer to a valid deString to put the shader code in.
	virtual deBoolean Disassemble(deString * Code) = 0;

	/// Returns the shader's type.
	virtual ShaderType GetShaderType() const = 0;

	/// Returns the number of instructions the shader contains
	virtual long GetInstructionCount() const = 0;

	/// Return the shader's instruction array
	virtual const deTArray<deShaderInstruction> * GetInstructions() const = 0;

	/// Return the number of constants the shader contains
	virtual long GetConstantCount() const = 0;

	/// Return the shader's constant array
	virtual const deTArray<deShaderConstant> * GetConstants() const = 0;

	/// Writes the assembled shader to a file
	/// @param FileSystem [in] A pointer to a valid IdeFileSystem to write to
	virtual deBoolean Write(IdeFile * File) const = 0;

	/// Reads an  assembled shader from a file
	/// @param FileSystem [in] A pointer to a valid IdeFileSystem to read a shader from
	virtual deBoolean Read(IdeFile * File) = 0;
	
	/// Called by the driver to set driver specific shader data
	/// @param Shader [in] A pointer to the driver's private data
	virtual deBoolean SetDriverShader(void * Shader) = 0;

	/// Called by the driver. Returns the driver's private data
	virtual void * GetDriverShader() const = 0;
};

//-------------------------------------------
// C exports
//-------------------------------------------

// factory functions
//a common function for filling in version information about the drivers based on compile date/time
DEDRIVER_API deBoolean IdeDriver_FillVersionInfo(deDriverInfo *DriverInfo, char *Date, char *Time);

DEDRIVER_API IdeDriverLoad* IdeDriverLoad_CreateDriverLoad(char const * path);

DEDRIVER_API deBoolean IdeDriver_Initialize();
DEDRIVER_API long IdeDriver_BPPBitDepth(IdeDriver::BPP BPPType);
/// Create an instance of IdeVertexBuffer
DEDRIVER_API IdeVertexBuffer* IdeVertexBuffer_CreateVBuffer();
/// Create an instance of IdeVertexBuffer, as a sub-vbuffer inside a parent buffer
/// @param Composite Parent buffer to create this sub-vbuffer inside of
DEDRIVER_API IdeVertexBuffer* IdeVertexBuffer_CreateSubVBuffer(IdeVertexBuffer * Composite);
DEDRIVER_API long IdeVertexBuffer_EntrySize(IdeVertexBuffer::BufferType Type);
DEDRIVER_API IdeVertexBuffer::BufferDataType IdeVertexBuffer_FillBufferDataType(IdeVertexBuffer::BufferType Type, long *Size);
DEDRIVER_API IdeShader* IdeShader_Create();


#endif
