/*
 * $Id:$
 *
 * Description  : One line description of file.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 *
 * Purpose      :
 *     Long description of what the file is for.
 */


#ifndef __RENDERGLMODULE_H__
#define __RENDERGLMODULE_H__

#include "rendermodule.h"
//#include "common.h"
#include "geometrynode.h"
#include "geometrytriangles.h"
#include "geometrypoints.h"
#include "VrutApi.h"
#include "SceneShadow.h"

#include "FontGlyphsTexture.h"
#include "openVRwrapper.h"

//#define RENDER_GL_PROFILING
#ifdef RENDER_GL_PROFILING
template <int SampleCount> class ProfilerStats: public VRUT::CountableThreadUnsafe
{
protected:
	float	values[SampleCount];
	int		currentSample;

	wxString	name;

	float getMin()
	{
		float min_val = FLT_MAX;
		for (int i = 0; i < SampleCount; i++)	min_val = std::min(min_val, values[i]);
		return min_val;
	}
	float getMax()
	{
		float max_val = -FLT_MAX;
		for (int i = 0; i < SampleCount; i++)	max_val = std::max(max_val, values[i]);
		return max_val;
	}
	float getSum()
	{
		float sum = 0.0f;
		for (int i = 0; i < SampleCount; i++)	sum += values[i];
		return sum;
	}
	float getAvg()
	{
		return getSum() / float(SampleCount);
	}
	float getVar(float avg)
	{
		float sq_sum = 0.0f;
		for (int i = 0; i < SampleCount; i++)	sq_sum += (values[i] - avg) * (values[i] - avg);
		return sq_sum / float(SampleCount);
	}

public:
	ProfilerStats(const wxChar *name): name(name)	{	Reset();	}

	void Reset(int curr_sample = -10)		{	currentSample = curr_sample;	}

	void InsertValue(float val)
	{
		if ((currentSample >= 0) && (currentSample < SampleCount))
		{
			values[currentSample] = val;
		}
		currentSample++;
		if (currentSample >= SampleCount)
		{
			currentSample = -2;
			float avg = getAvg();
			LOG(wxT("Profiler ") + name + wxString::Format(wxT(" Stats: min %7.3f, max %7.3f, avg %7.3f, var %8.4f"), getMin(), getMax(), avg, getVar(avg)));
		}
	}
};
typedef ProfilerStats<50> ProfilerStatsOptim;

class VRUTStopWatchPrecise
{
protected:
	wxStopWatch sw;

public:
	inline void Start()
	{
		sw.Start();
	}

	/// Returns time elapsed from last Start or last MeanTime in ms
	inline double MeanTime()
	{
#if wxCHECK_VERSION(2,9,3)
		double result = sw.TimeInMicro().ToDouble() * 1e-3;
#else
		double result = double(sw.Time());
#endif
		sw.Start();
		return result;
	}

};
#endif

namespace VRUT
{

	//------------------------------------------
	//----    Classes for text rendering    ----
	//------------------------------------------

	class FontGlyphsTextureOpenGL
	{
	protected:
		std::shared_ptr<FontGlyphsTexture> glyphs;
		GLuint texture;
		int dims[2];

		void updateFontGlyphsTexture();

	public:
		FontGlyphsTextureOpenGL(const std::shared_ptr<FontGlyphsTexture> &glyphs, int dimx, int dimy);
		~FontGlyphsTextureOpenGL();

		const std::shared_ptr<FontGlyphsTexture> GetGlyphs() const
		{
			return glyphs;
		}
		GLuint GetTexture() const
		{
			return texture;
		}
		int GetDim(int i) const
		{
			return dims[i];
		}
	};

	class FontGlyphsTexturesFactory
	{
	protected:
		std::vector<std::pair<wxFont, std::shared_ptr<FontGlyphsTextureOpenGL> > > fonts;

	public:
		std::shared_ptr<FontGlyphsTextureOpenGL> GetOrCreateFont(const wxFont &font);
		void DestroyAllFonts();
	};

	class VirtualCamera : public RenderTarget
	{
	public:
		int textureWidth, textureHeight;
		VirtualCamera(int textureWidth = 512, int textureHeight = 512) : RenderTarget(), textureWidth(textureWidth), textureHeight(textureHeight) {}
		bool SetupAttachments()
		{
			if (!GetTextureAttachmentOfType(GL_COLOR_ATTACHMENT0_EXT))
			{
				//Stencil buffer is ommited. I think we will not be doing stencil effects when rendering into cube maps.
				//If the future proves me wrong, just add it like in the RenderGlModule::updateSingleSampledRenderTarget.
				//Multisampled rendering into the cube map is also neglected.
				AddRenderBufferAttachment(RenderTarget::RenderBufferAttachmentParams(textureWidth, textureHeight, GL_DEPTH_COMPONENT, 1, 1, GL_DEPTH_ATTACHMENT_EXT, RenderTarget::NONE));

				//Hey, it is 2010, let's support HDR rendering by default
#define VIRTUAL_CAMERA_SUPPORT_TRANSPARENCY 1
#if VIRTUAL_CAMERA_SUPPORT_TRANSPARENCY
				AddTextureAttachment(RenderTarget::TextureAttachmentParams(textureWidth, textureHeight, /*GL_RGB8*/GL_RGBA16F_ARB, GL_COLOR_ATTACHMENT0_EXT, GL_RGBA, /*GL_UNSIGNED_BYTE*/GL_HALF_FLOAT_ARB));
#else
				AddTextureAttachment(RenderTarget::TextureAttachmentParams(textureWidth, textureHeight, /*GL_RGB8*/GL_RGB16F_ARB, GL_COLOR_ATTACHMENT0_EXT, GL_RGB, /*GL_UNSIGNED_BYTE*/GL_HALF_FLOAT_ARB));
#endif
				return true;
			}
			return false;
		}
	};

	//------------------------------
	//----    RenderGlModule    ----
	//------------------------------

	///Basic renderglmodule module class
	class VRUT_CORE_API RenderGlModule : public RenderModule
	{
	protected:
		struct TexObject
		{
			GLuint object;
			bool has_mipmaps;
		};
		WX_DECLARE_STRING_HASH_MAP(TexObject, TextureIDMap);
		WX_DECLARE_STRING_HASH_MAP(bool, ResetTexturesMap);
		typedef std::vector<GLuint> GLIDList;

		/// ShaderHandler2 extends ShaderHandler with strings containing shader source code,
		/// allowing us check whether the code changed before recompiling the shader
		struct ShaderHandler2: public ShaderHandler
		{
			wxString vertexShaderSource;
			wxString fragmentShaderSource;
			wxString geometryShaderSource;
			// Use default constructors and operators
		};

		WX_DECLARE_STRING_HASH_MAP(ShaderHandler2, ShaderIDMap);
		///OpenGL vendors. Useful for patching driver bugs.
		enum OpenGLVendor
		{
			NVIDIA,
			AMD
		};
		///IDs for VBO
		struct VBOID
		{
			GLuint verticesID;
			GLuint indicesID;
			GLenum vertexType;
			size_t verticesCount;		// Number of vertices for which this group of VBOs are created
			VBOID() : verticesID(GL_ID_NONE), indicesID(GL_ID_NONE), vertexType(0), verticesCount(0)  {}
			void DeleteBuffers()
			{
				if (verticesID!=GL_ID_NONE)
				{
					glDeleteBuffersARB(1, &verticesID);
					verticesID=GL_ID_NONE;
				}
				if (indicesID!=GL_ID_NONE)
				{
					glDeleteBuffersARB(1, &indicesID);
					indicesID=GL_ID_NONE;
				}
				vertexType = 0;
				verticesCount = 0;
			}
		};
		typedef std::vector<VBOID> VBOIDList;

		class OpenGLStateTracker {
		private:
			bool blend;
			bool alphaTest;
			bool alphaToCoverage;
			GLenum alphaFunc;
			float alphaFuncValue;
			void enable(bool &val, const GLenum cap)
			{
				if (!val)
				{
					glEnable(cap);
					val=true;
				}
			}
			void disable(bool &val, const GLenum cap)
			{
				if (val)
				{
					glDisable(cap);
					val=false;
				}
			}
		public:
			OpenGLStateTracker() : blend(false), alphaTest(false), alphaToCoverage(false), alphaFunc(GL_ALWAYS), alphaFuncValue(0.0f) {}
			void enableBlend()
			{
				enable(blend, GL_BLEND);
			}
			void disableBlend()
			{
				disable(blend, GL_BLEND);
			}
			void enableAlphaTest()
			{
				enable(alphaTest, GL_ALPHA_TEST);
			}
			void disableAlphaTest()
			{
				disable(alphaTest, GL_ALPHA_TEST);
			}
			void enableAlphaToCoverage()
			{
				enable(alphaToCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
			}
			void disableAlphaToCoverage()
			{
				disable(alphaToCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
			}
			void setAlphaFunc(const GLenum alphaFunc, const float alphaFuncValue)
			{
				if ((alphaFunc!=this->alphaFunc) || (alphaFuncValue!=this->alphaFuncValue))
				{
					this->alphaFunc=alphaFunc;
					this->alphaFuncValue=alphaFuncValue;
					glAlphaFunc(alphaFunc, alphaFuncValue);
				}
			}
		};

		Matrix cubeMapGenerationViewMatrix[6];

		///Used for executing code depending on the OpenGL vendor. Used as a driver bug compensation measure.
		OpenGLVendor openGLVendor;
		///rendering of second camera (active stereo)
		bool cameraLeft;

		//synchronization parameters
		///this renderer is synchronized, so it should send messages and wait for barrier
		bool synchronized;
		///shortcut for synchronization
		RENDER_WINDOW_ID windowID;
		//last rendered state
		int lastRenderedState;
		//last release barrier state
		int lastBarrierState;
		SceneShadow *sceneShadow;

		//size_t drawCount;

		///GL IDs of cached geometry and material in display lists
		GLIDList dispListMatIDs;
		GLIDList dispListGeomIDs;
		///Request to redraw
		bool rerender;
		///enabled light cache
		int enabledLightCount;
		MATERIAL_ID lastMaterialID;
		///GL IDs of cached geometry in VBOs
		VBOIDList VBOIDs;
		///Map of texture filenames to cached Gl texture ID
		TextureIDMap texture2DIDMap, textureCubeIDMap;
		///Map of material names to cached Gl shader handler
		ShaderIDMap shaderIDMap;
		///Use VBO or display list?
		bool useVBO;
		///\c useVBO param identifier
		Parameter::ParameterIdentifier useVBOParamID;
		///Is VBO supported?
		bool vboSupported;
		///Is FBO supported?
		bool fboSupported;
		///Is fragment shader?
		bool shaderSupported;
		///Draw wireframe?
		bool wireframe;
		///\c wireframe param identifier
		Parameter::ParameterIdentifier wireframeParamID;
		///Enable lighting?
		bool lighting;
		///\c lighting param identifier
		Parameter::ParameterIdentifier lightingParamID;
		///Renderer-global texturing override. Useful for debugging.
		bool texturing;
		///\c texturing param identifier
		Parameter::ParameterIdentifier texturingParamID;
		///Enable headlight?
		bool headlight;
		///\c headlight param identifier
		Parameter::ParameterIdentifier headlightParamID;
		///Enable back face culling?
		bool backFaceCull;
		///\c backFaceCull param identifier
		Parameter::ParameterIdentifier backFaceCullParamID;
		///Enable alpha to coverage?
		bool alphaToCoverage;
		///\c alphaToCoverage param identifier
		Parameter::ParameterIdentifier alphaToCoverageParamID;
		///Anti aliasing color sample count
		int antiAliasingColorSampleCount;
		///\c antiAliasingColorSampleCount param identifier
		Parameter::ParameterIdentifier antiAliasingColorSampleCountParamID;
		///Anti aliasing coverage sample count
		int antiAliasingCoverageSampleCount;
		///\c antiAliasingColorSampleCount param identifier
		Parameter::ParameterIdentifier antiAliasingCoverageSampleCountParamID;
		///\c antiAliasingMethod param id
		Parameter::ParameterIdentifier antiAliasingMethodParamID;
		///Anti aliasing method
		RenderTarget::AntiAliasingType antiAliasingMethod;
		///Anti aliasing method names
		wxArrayString antiAliasingMethodStringList;
		///Frame buffer object colorattachment0's internal format
		GLint fboInternalFormat;
		///Index into the string list
		int fboInternalFormatStringListIndex;
		///Frame buffer object colorattachment0's internal format names
		wxArrayString fboInternalFormatStringList;
		std::vector<GLint> fboInternalFormatValuesList;
		///\c fboInternalFormat param id
		Parameter::ParameterIdentifier fboInternalFormatParamID;
		///Draw using a Frame Buffer Object
		bool drawUsingFBO;
		///Draw using a Frame Buffer Object
		Parameter::ParameterIdentifier drawUsingFBOParamID;

		///Use double FBO for stereo rendering with openVR
		bool openVR;
		Parameter::ParameterIdentifier openVRParamID;
		// Scene unit of measurement - openVR works in meters
		float sceneUnits;//ratio to meters, so for mm it must be 1000
		Parameter::ParameterIdentifier sceneUnitsParamID;
		// use hidden area - render triangles on near plane distance over hidden area for OpenVR
		bool useHiddenArea;
		Parameter::ParameterIdentifier useHiddenAreaParamID;
		enum stereo {
			LEFT_EYE,
			RIGHT_EYE,
		};

		NODE_ID renderingRootID;
		Parameter::ParameterIdentifier renderingRootIDParamID;

		bool mHudSupport;
		Parameter::ParameterIdentifier mHudSupportParamID;
		
		///Support for dual dvi 30 bit colors (10 bit per component)
		bool dualDVI30BitColors;
		///Variables used for detecting real window resize and not just the camera projection change. We need to differentiate these two cases.
		unsigned int windowWidth, windowHeight;
		///\c dualDVI30BitColors param id
		Parameter::ParameterIdentifier dualDVI30BitColorsParamID;
		///Is GL initialized - global GL states
		bool initialized;
		///AA GUI is initialised later depending on the GPU caps, so we need this.
		bool antiAliasingGUIInitialized;
		///Is scene initialized - display lists, VBOs, textures...
		bool sceneInitialized;
		///Is the nVidia extension supported?
		bool nvMultisampleCoverageSupported;
		///Is multisampling supported?
		bool multisampleSupported;
		///Nodes (new nodes or modified nodes) to be reinitialized next draw cycle
		std::vector<bool> resetGeometries;
		std::vector<bool> resetMaterials;
		ResetTexturesMap resetTextures;
		///Any node needs reset?
		bool resetGeometry;
		bool resetMaterial;
		///Are BVH AABBs to be drawn?
		bool drawBVH;
		///\c drawBVH param identifier
		Parameter::ParameterIdentifier drawBVHParamID;
		///Textures used in the last draw cycle
		size_t texturesUsedLast;
		///Allow redundant deletes of cached data during scene import?
		///Can fix problems with caching during import (missing textures) but slightly slower
		int sortGeometries;
		wxArrayString sortGeometriesStringList;
		///\c sortGeometries param identifier
		Parameter::ParameterIdentifier sortGeometriesParamID;

		//std::vector<std::list<NODE_ID> > matnodes;
		///Ensures render update only once when building VBOs auxiliary
		bool vboRenderUpdated;
		///Saves us some headaches and OpenGL calls
		bool viewDependentCubemapEnabled;
		///Maximal value of anisotropic filtering, if it is 1.0 then anisotropic filtering is not used at all
		float maximumAnisotropy;
		///Maximum number of clipping planes
		GLint maxClippingPlanes;
		///number of enabled clipping planes
		int enabledClippingPlanesCount;
		///Default clear color
		Vector4 defaultClearColor;
		///Multi sampled render target
		RenderTarget multiSampledRenderTarget;
		/// STEREO rendering with openVR, RIGHT SIDE
		///Render target right
		RenderTarget *renderTargetR;
		///Multi sampled render target
		RenderTarget *multiSampledRenderTargetR;
		///OGL impl. data logged?
		bool openGLDetailsDataLogged;
		///Helper variable to avoid camera locking
		smart_pointer<Camera> clonedCamera;
		///Helper variable to avoid camera locking
		Scene *clonedCameraScene;
		///Shader programs for 30 bit rendering
		ShaderProgram dualDVI30BitColorsProgram;
		///Shader program handlers for 30 bit rendering
		ShaderHandler dualDVI30BitColorsProgramHandler;
		///Initialization flag
		bool dualDVI30BitColorsProgramInitialized;
		///use V-sync
		bool useVSync;
		bool vSyncEnabled;
		Parameter::ParameterIdentifier useVSyncParamID;

		///Factory creating font textures
		FontGlyphsTexturesFactory fontFactory;

		wxULongLong lastEndTime;
		SceneShadow::ItemsList itemsList, blendedItemsList, reflectiveItemsList, backgroundItemsList, virtualCameraItemsList, itemsListR, blendedItemsListR, reflectiveItemsListR;

		Matrix camMatInverse, lastMatrix;

		Matrix getProjectionMatrix(Scene *scene, smart_pointer<Camera> camera, bool cameraLeft = false);

		Matrix camMat, projectionMatrix;
		const Matrix *TMTMatrix;

		/// true if frame stats is shown as overlay
		bool showStatsString;

		///\c show stats string param id
		Parameter::ParameterIdentifier showStatsStringParamID;
		
		/// string containing arbitrary message (intended for use trhough an external module)
		wxString messageString;
		///\c messageString param id
		Parameter::ParameterIdentifier messageStringParamID;

		/// Defines whether render in render loop
		bool runRenderLoop;
		///\c runRenderLoop param id
		Parameter::ParameterIdentifier runRenderLoopParamID;

		/// Defines whether clear also color buffer
		bool clearColorBuffer;
		Parameter::ParameterIdentifier clearColorBufferParamID;

		///defines the culling strategy, currently used as workaround for cache all and mirrors in CAVE
		wxArrayString cullingMethodStringList;
		int cullingMethod;
		Parameter::ParameterIdentifier cullingMethodParamID;

		/// vector of string messages shown as text overlay
		/// every message is kept for a predefined amount of seconds
		struct TextMessageInfo {
			// time when the message was issued
			long time;
			// the message itself
			wxString message;
			TextMessageInfo():time(0), message() {}
		};
		
		std::vector<TextMessageInfo> messages;

		struct LightInfo
		{
			smart_pointer<LightNode> lightNode;
			Matrix matrix;
			LightInfo(smart_pointer<LightNode> lightNode, const Matrix &matrix) : lightNode(lightNode), matrix(matrix)
			{
			}
		};

		WX_DECLARE_HASH_MAP(VRUT::NODE_ID, VirtualCamera *, wxIntegerHash, wxIntegerEqual, VirtualCamerasMap);
		VirtualCamerasMap virtualCamerasMap;

		///Logs the OpenGL vendor, version, all supported extensions...
		void logOpenGLDetailsData();
		///Release cached geometry
		void clearCachedGeometry();
		///Check support for some extensions
		void checkExtSupport();
		///Sets parameters which are not unique to any shader but are globally useful and their value has to be computed on the CPU
		void setDefaultShaderParams(std::vector<ShaderParam>& shaderParams);
		///Set fragment shader states or compile program if not available
		void drawShader(const smart_pointer<Material> & material);
		///Set light states
		void drawLights(const std::vector<LightInfo> &lights);
		///Enable clipping planes
		void enableClippingPlanes();
		///Disable clipping planes
		void disableClippingPlanes();
		///Draw background
		void drawBackground();
		///Set material, texture states, render reflections
		void drawMaterial(const smart_pointer<Material> & material);
		///Spetial case of setting material for GeometryText
		void drawMaterialGeometryText(const smart_pointer<Material> & material);
		///Return textureID, optionally build new if not built already
		GLuint getTextureID(const wxString &imageName, Image::TEXTURE_SAMPLER_TYPE buildAsType, bool use_mipmaps, bool buildIfNeeded);
		///Render geometry node using VBO or build it if not available
		void drawVBO(const SceneNodeShadow *node);
		///Render geometry node using VBO or build it if not available
		void drawVBOMaterial(const SceneNodeShadow *node);
		///Render geometry node using VBO or build it if not available
		void drawVBOGeometry(const SceneNodeShadow *node);

		///Render geometry node using display list or build it if not available
		void drawDispList(const SceneNodeShadow *node);
		///Render geometry node using display list or build it if not available
		void drawDispListMaterial(const SceneNodeShadow *node);
		///Render geometry node using display list or build it if not available
		void drawDispListGeometry(const SceneNodeShadow *node);
		///Render flat mirrors
		void drawFlatMirrorReflection(SceneShadow::ItemInfo& item, SceneShadow::ItemsList mirrorList, const std::vector<LightInfo> &lights);
		///Render scene from the virtual space behind the mirror
		void drawSceneReflection(const Matrix& reflectedMatrix, SceneNodeShadow &mirrorNode, const std::vector<LightInfo> &lights, NODE_ID clonedCameraID, const Vector4 &reflectionPlane);
		///Renders the mirror geometry into the depth buffer
		void drawFlatMirrorGeometryIntoDepthAndColorBuffer(SceneShadow::ItemsList& mirrorList, NODE_ID doNotDrawMe = NODE_ID_NONE);
		///Renders the mirror shape stencil into the stencil buffer
		void drawFlatMirrorStencilAndSetupClippingPlane(const SceneShadow::ItemInfo& mirrorNodeInfo, const Matrix& reflectedMatrix, const Vector4 &clipPlane);
		///The doNotDrawMe parameter was added to avoid erasing single element from the beginning of the itemsList vector. This caused trouble with releasing wrong smart pointer.
		void drawSolidGeometry(SceneShadow::ItemsList& itemsList, bool reverseFaceWinding = false, NODE_ID doNotDrawMe = NODE_ID_NONE);
		void drawReflectiveGeometry(SceneShadow::ItemsList& itemsList, const std::vector<LightInfo> &lights);
		void drawTransparentGeometry(SceneShadow::ItemsList& blendedItemsList, bool reverseFaceWinding = false, bool useCameraMatrix = true);
		void drawIntoEnvironmentProbe(smart_pointer<EnvironmentProbe> &environmentProbe, const std::vector<LightInfo> &lights);
		void updateEnvironmentProbes(Scene& scene, const std::vector<LightInfo> &lights, int openVREyeID = -1);
		void drawIntoVirtualCamera(smart_pointer<Camera> &virtualCamera, const std::vector<LightInfo> &lights);
		void updateVirtualCameras(Scene& scene, SceneShadow::ItemsList& itemsList, const std::vector<LightInfo> &lights, int openVREyeID = -1);
		///Draws a sky box
		void drawBox();
		///Draws a screen aligned quad
		void drawQuad();
		///Draws a screen aligned quad. No GL matrix setup.
		void drawQuadCore();
		///Draws contents of a FBO to a screen aligned quad
		void drawFromFBO(int openVREyeID = -1);
		void Reset();
		///Render AABBs of all nodes
		void drawBVHHierarchy(const SceneShadow::ItemsList &itemsList);
		///Process render event - \c RenderModule overload
		virtual void processEvent(Event * evt) override;
		///Setup AA GUI
		void setupAAGUI();
		///Enables or disables the text fields according to the selected AA mode
		void enableAASampleTextControl(RenderTarget::AntiAliasingType aaType);
		///Multiplies the texture matrix by the transpose camera rotation. Should be used if you are sure the view dependent cube map should be enabled.
		void startViewDependentCubemapCore();
		///Multiplies the texture matrix by the camera rotation. Should be used if you are sure the view dependent reflection should be enabled.
		void startViewDependentCubemapReflectionCore();
		///Sets the texture matrix back to identity.
		void stopViewDependentCubemap();
		///Binds current frame buffer objects according to selected params
		void updateFrameBufferObjectBinds(int openVREyeID = -1);
		///Updates the single sampled attachment params
		void updateSingleSampledRenderTarget(GLsizei w = -1, GLsizei h = -1, int openVREyeID = -1);
		///Updates the multisampled attachment params
		void updateMultiSampledRenderTarget(GLsizei w = -1, GLsizei h = -1, int openVREyeID = -1);
		// Wrappers for updating all targets
		void updateAllSingleSampledRenderTargets(GLsizei w = -1, GLsizei h = -1);
		void updateAllMultiSampledRenderTargets(GLsizei w = -1, GLsizei h = -1);
		///Initializes the dual dvi 30 bit color programs
		void initDualDVI30BitColorsProgram();
		///Deletes the dual dvi 30 bit color programs
		void deleteDualDVI30BitColorsProgram();
		///Sets the projection to use only half of the window
		void setDualDVI30BitColorsProjection();
		///Sets the projection to use only half of the window when the window is resized
		void resizeDualDVI30BitColorsProjection();
		///Debugging method for saving ogl buffers
		void snapshotBuffer(int windowWidth, int windowHeight, GLenum format, const char* filename);
		///Debugging method for saving ogl textures
		void snapshotTexture(const int level, const char* filename);
		
		///Method for drawing a text overlay specified in the textMessage parameter
		void drawTextOverlay(wxString text, float x, float y, float step);
		
		virtual void cleanAfterLoop() override;

#ifdef RENDER_GL_PROFILING
		smart_pointer_v2<ProfilerStatsOptim>	drawTimeCPUProf;
#endif	// RENDER_GL_PROFILING

	public:
		///Class constructor
		RenderGlModule(MODULE_ID _id, const wxString & _name, Kernel * _kernel);
		///Class destructor
		virtual ~RenderGlModule();

		///Get module description - \c Module overload
		virtual wxString GetDesc() const override;
		///Main draw method with OpenGL calls - \c RenderModule overload
		virtual void Draw() override;
		///Special Draw for OpenVR (might be generalized in future)
		void Draw(int openVREyeID, const Matrix &cameraWorldMatrix, const Matrix &cameraProjectionMatrix, GLsizei width, GLsizei height, SceneShadow::ItemsList &itemsList, SceneShadow::ItemsList &blendedItemsList,
			SceneShadow::ItemsList &reflectiveItemsList, SceneShadow::ItemsList &backgroundItemsList, SceneShadow::ItemsList &virtualCameraItemsList, OpenVRWrapper *openVRWrapper);
		///Helper method for drawing views of temporary cameras
		void debugDraw(smart_pointer<Camera> camera);
		///Release OpenGL allocated video memory - \c RenderModule overload
		///If called explicitly, be sure to set GLContext associated with window/module
		virtual void Deinitialize() override;
	  	/// initialize Opengl 
	  	virtual bool Initialize();
		///Check if GL extension is supported (NeHeGL)
		static bool IsExtensionSupported(const char * szTargetExtension);
		///Convert primitive type from \c GeometryTriangles::PRIMITIVE_TYPE to OpenGL definitions
		bool SetSwapInterval(const int interval);
		inline static int GetOglPrimitiveType(GeometryTriangles::PRIMITIVE_TYPE primType)
		{
			switch (primType) {
				case GeometryTriangles::TRI_LIST:
					return GL_TRIANGLES;
				case GeometryTriangles::TRI_FAN:
					return GL_TRIANGLE_FAN;
				case GeometryTriangles::TRI_STRIP:
					return GL_TRIANGLE_STRIP;
				case GeometryTriangles::POLYGON:
					return GL_POLYGON;
				case GeometryTriangles::LINES:
					return GL_LINES;
				case GeometryTriangles::LINE_STRIP:
					return GL_LINE_STRIP;
				case GeometryTriangles::POINTS:
					return GL_POINTS;
				case GeometryTriangles::QUADS:
					return GL_QUADS;
				default:
					return 0xffffffff;
			}
		}
	};

	//Delete me, if snapshotBuffer is obsolete
#ifndef __WINDOWS__
	struct BITMAPFILEHEADER {
		unsigned short    bfType;
		unsigned long   bfSize;
		unsigned short    bfReserved1;
		unsigned short    bfReserved2;
		unsigned long   bfOffBits;
	};

	struct BITMAPINFOHEADER {
		unsigned long      biSize;
		long       biWidth;
		long       biHeight;
		unsigned short       biPlanes;
		unsigned short       biBitCount;
		unsigned long      biCompression;
		unsigned long      biSizeImage;
		long       biXPelsPerMeter;
		long       biYPelsPerMeter;
		unsigned long      biClrUsed;
		unsigned long      biClrImportant;
	};
#endif

}

#endif
