/*
 * This source file is part of KEOS (Free 3D Engine)
 * For the latest info, see http://www.keosengine.org/
 * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
 * http://www.gnu.org/copyleft/lesser.txt.
 *
 */

#ifndef KEOS_OGLRENDERSYSTEM_H
#define KEOS_OGLRENDERSYSTEM_H

#include "KeosOGLPrerequisites.h"
#include "KeosRenderSystem.h"
#include "KeosRenderWindow.h"

namespace Keos
{
    #define BUFFER_OFFSET(n) ((char*)NULL + (n))

    //-----------------------------------------------------------------------
    /** Class for OpenGL renderer system.
     *
     */
    class COGLRenderSystem : public IRenderSystem
    {
    public :

        /** Constructor.
         */
        COGLRenderSystem();

        /** Destructor.
         */
        ~COGLRenderSystem();

		/** See RenderSystem
         */
        const String& GetName(void) const;

        /** See IRenderSystem.
         */
        IRenderWindow* CreateRenderWindow(const String &strName, uint nWidth, uint nHeight, uint nColourDepth, bool bFullScreen);

        /** See IRenderSystem.
         */
        IRenderWindow* Initialise(bool bAutoCreateWindow, const String& strWindowTitle = "KEOS Render Window");

        /** See IRenderSystem.
         */
        void Reinitialise(void); // Used if settings changed mid-rendering
        
        /** See IRenderSystem.
         */
        void Shutdown(void);

        void InitGL(void);

        /** Start a scene render.
         */
        virtual void BeginScene(void) const;

        /** End a scene render.
         */
        virtual void EndScene(void) const;

        /** Print information on the API.
         */
        virtual void PrintInfo(void) const;

        /** See IRenderSystem.
         */
        virtual IBufferBase* _CreateVB(ulong nSize, ulong nStride, ulong nFlags) const;

        /** See IRenderSystem.
         */
        virtual IBufferBase* _CreateIB(ulong nSize, ulong nStride, ulong nFlags) const;

        /** See IRenderSystem.
         */
        virtual IDeclaration* CreateDeclaration(const TDeclarationElement* Elements, size_t nCount) const;

        /** See IRenderSystem.
         */
        virtual void _SetVB(uint nStream, const IBufferBase* pBuffer, ulong nStride, ulong nMinVertex, ulong nMaxVertex);

        /** See IRenderSystem.
         */
        virtual void _SetIB(const IBufferBase* pBuffer, ulong nStride);

        /** See IRenderSystem.
         */
        virtual void SetDeclaration(const IDeclaration* Declaration);

        /** See IRenderSystem.
         */
        virtual void DrawPrimitives(TPrimitiveType Type, ulong nFirstVertex, ulong nCount) const;

        /** See IRenderSystem.
         */
        virtual void DrawIndexedPrimitives(TPrimitiveType Type, ulong nFirstIndex, ulong nCount) const;

        /** See IRenderSystem.
         */
        virtual void PushMatrix(TMatrixType Type);

        /** See IRenderSystem.
         */
        virtual void PopMatrix(TMatrixType Type);

        /** See IRenderSystem.
         */
        virtual void LoadMatrix(TMatrixType Type, const CMatrix4& Matrix);

        /** See IRenderSystem.
         */
        virtual void LoadMatrixMult(TMatrixType Type, const CMatrix4& Matrix);

        /** See IRenderSystem.
         */
        virtual void GetMatrix(TMatrixType Type, CMatrix4& Matrix) const;

        /** See IRenderSystem.
         */
        virtual ulong ConvertColor(const CColor& Color) const;

        /** See IRenderSystem.
         */
        virtual ITextureBase* CreateTexture(const TVector2I& Size, TPixelFormat Format, ulong nFlags = 0) const;
        
        /** See IRenderSystem.
         */
        virtual void SetTexture(uint nUnit, const ITextureBase* pTexture) const;

        /** See IRenderSystem.
         */
        virtual void SetupAlphaBlending(TBlend Src, TBlend Dest) const;

        /** See IRenderSystem.
         */
        virtual void SetupTextureUnit(uint nUnit, TTextureOp Op, TTextureArg Arg1, TTextureArg Arg2 = TXA_DIFFUSE, const CColor& Constant = 0x00) const;

        /** See IRenderSystem.
         */
        virtual void Enable(TRenderParameter Param, bool bValue) const;

        /** See IRenderSystem.
         */
        virtual IShaderBase* CreateShader(CGprogram Program, TShaderType Type) const;

        /** See IRenderSystem.
         */
        virtual void SetVertexShader(const IShaderBase* pShader);

        /** See IRenderSystem.
         */
        virtual void SetPixelShader(const IShaderBase* pShader);

		/** See IRenderSystem.
         */
		virtual void SetClearColor(const CColor& Color);


        // OpenGL extensions    
        static PFNGLBINDBUFFERARBPROC               glBindBufferARB;
        static PFNGLDELETEBUFFERSARBPROC            glDeleteBuffersARB;
        static PFNGLGENBUFFERSARBPROC               glGenBuffersARB;
        static PFNGLBUFFERDATAARBPROC               glBufferDataARB;
        static PFNGLBUFFERSUBDATAARBPROC            glBufferSubDataARB;
        static PFNGLGETBUFFERSUBDATAARBPROC         glGetBufferSubDataARB;
        static PFNGLMAPBUFFERARBPROC                glMapBufferARB;
        static PFNGLUNMAPBUFFERARBPROC              glUnmapBufferARB;
        static PFNGLACTIVETEXTUREARBPROC            glActiveTextureARB;
        static PFNGLCLIENTACTIVETEXTUREARBPROC      glClientActiveTextureARB;
        static PFNGLCOMPRESSEDTEXIMAGE2DARBPROC     glCompressedTexImage2DARB;
        static PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC  glCompressedTexSubImage2DARB;

    private:

        /** Check validity of one extension.
         *  @param strExtension Name of the extension.
         */
        bool CheckExtension(const String& strExtension) const;

        /** Load OpenGL extensions.
         */
        void LoadExtensions(void);

        //! Current declaration
        const COGLDeclaration* m_CurrentDeclaration; 

        //! Cuurent size of index
        ulong m_nIndexStride;  

        //! Extensions OpenGL supported by the card
        String m_strExtensions;  

        //! OpenGL is initialized ?
        bool m_bGLInitialized;
    };

} // namespace Keos


#endif // KEOS_OGLRENDERSYSTEM_H
