Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / DeviceBuilder.cpp
diff --git a/source/rice_gles/src/DeviceBuilder.cpp b/source/rice_gles/src/DeviceBuilder.cpp
new file mode 100755 (executable)
index 0000000..81b4e2a
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+Copyright (C) 2003 Rice1964
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU 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.
+
+*/
+
+#include "osal_opengl.h"
+
+#include "DeviceBuilder.h"
+#include "FrameBuffer.h"
+#include "OGLCombiner.h"
+#include "OGLDebug.h"
+#include "OGLExtRender.h"
+#include "OGLGraphicsContext.h"
+#include "OGLTexture.h"
+#if SDL_VIDEO_OPENGL
+#include "OGLExtCombiner.h"
+#ifndef HAVE_GLES
+#include "OGLCombinerNV.h"
+#include "OGLCombinerTNT2.h"
+#include "OGLFragmentShaders.h"
+#endif
+#include "OGLExtensions.h"
+#elif SDL_VIDEO_OPENGL_ES2
+#include "OGLES2FragmentShaders.h"
+#endif
+
+//========================================================================
+CDeviceBuilder* CDeviceBuilder::m_pInstance=NULL;
+SupportedDeviceType CDeviceBuilder::m_deviceType = DIRECTX_DEVICE;
+SupportedDeviceType CDeviceBuilder::m_deviceGeneralType = DIRECTX_DEVICE;
+
+CDeviceBuilder* CDeviceBuilder::GetBuilder(void)
+{
+    if( m_pInstance == NULL )
+        CreateBuilder(m_deviceType);
+    
+    return m_pInstance;
+}
+
+void CDeviceBuilder::SelectDeviceType(SupportedDeviceType type)
+{
+    if( type != m_deviceType && m_pInstance != NULL )
+    {
+        DeleteBuilder();
+    }
+
+    CDeviceBuilder::m_deviceType = type;
+    switch(type)
+    {
+    case OGL_DEVICE:
+    case OGL_1_1_DEVICE:
+    case OGL_1_2_DEVICE:
+    case OGL_1_3_DEVICE:
+    case OGL_1_4_DEVICE:
+    case OGL_1_4_V2_DEVICE:
+    case OGL_TNT2_DEVICE:
+    case NVIDIA_OGL_DEVICE:
+    case OGL_FRAGMENT_PROGRAM:
+        CDeviceBuilder::m_deviceGeneralType = OGL_DEVICE;
+        break;
+     default:
+       break;
+    }
+}
+
+SupportedDeviceType CDeviceBuilder::GetDeviceType(void)
+{
+    return CDeviceBuilder::m_deviceType;
+}
+
+SupportedDeviceType CDeviceBuilder::GetGeneralDeviceType(void)
+{
+    return CDeviceBuilder::m_deviceGeneralType;
+}
+
+CDeviceBuilder* CDeviceBuilder::CreateBuilder(SupportedDeviceType type)
+{
+    if( m_pInstance == NULL )
+    {
+        switch( type )
+        {
+        case    OGL_DEVICE:
+        case    OGL_1_1_DEVICE:
+        case    OGL_1_2_DEVICE:
+        case    OGL_1_3_DEVICE:
+        case    OGL_1_4_DEVICE:
+        case    OGL_1_4_V2_DEVICE:
+        case    OGL_TNT2_DEVICE:
+        case    NVIDIA_OGL_DEVICE:
+        case OGL_FRAGMENT_PROGRAM:
+            m_pInstance = new OGLDeviceBuilder();
+            break;
+        default:
+            DebugMessage(M64MSG_ERROR, "CreateBuilder: unknown OGL device type");
+            exit(1);
+        }
+
+        SAFE_CHECK(m_pInstance);
+    }
+
+    return m_pInstance;
+}
+
+void CDeviceBuilder::DeleteBuilder(void)
+{
+    delete m_pInstance;
+    m_pInstance = NULL;
+}
+
+CDeviceBuilder::CDeviceBuilder() :
+    m_pRender(NULL),
+    m_pGraphicsContext(NULL),
+    m_pColorCombiner(NULL),
+    m_pAlphaBlender(NULL)
+{
+}
+
+CDeviceBuilder::~CDeviceBuilder()
+{
+    DeleteGraphicsContext();
+    DeleteRender();
+    DeleteColorCombiner();
+    DeleteAlphaBlender();
+}
+
+void CDeviceBuilder::DeleteGraphicsContext(void)
+{
+    if( m_pGraphicsContext != NULL )
+    {
+        delete m_pGraphicsContext;
+        CGraphicsContext::g_pGraphicsContext = m_pGraphicsContext = NULL;
+    }
+
+    SAFE_DELETE(g_pFrameBufferManager);
+}
+
+void CDeviceBuilder::DeleteRender(void)
+{
+    if( m_pRender != NULL )
+    {
+        delete m_pRender;
+        CRender::g_pRender = m_pRender = NULL;
+        CRender::gRenderReferenceCount = 0;
+    }
+}
+
+void CDeviceBuilder::DeleteColorCombiner(void)
+{
+    if( m_pColorCombiner != NULL )
+    {
+        delete m_pColorCombiner;
+        m_pColorCombiner = NULL;
+    }
+}
+
+void CDeviceBuilder::DeleteAlphaBlender(void)
+{
+    if( m_pAlphaBlender != NULL )
+    {
+        delete m_pAlphaBlender;
+        m_pAlphaBlender = NULL;
+    }
+}
+
+
+//========================================================================
+
+CGraphicsContext * OGLDeviceBuilder::CreateGraphicsContext(void)
+{
+    if( m_pGraphicsContext == NULL )
+    {
+        m_pGraphicsContext = new COGLGraphicsContext();
+        SAFE_CHECK(m_pGraphicsContext);
+        CGraphicsContext::g_pGraphicsContext = m_pGraphicsContext;
+    }
+
+    g_pFrameBufferManager = new FrameBufferManager;
+    return m_pGraphicsContext;
+}
+
+CRender * OGLDeviceBuilder::CreateRender(void)
+{
+    if( m_pRender == NULL )
+    {
+        if( CGraphicsContext::g_pGraphicsContext == NULL && CGraphicsContext::g_pGraphicsContext->Ready() )
+        {
+            DebugMessage(M64MSG_ERROR, "Can not create ColorCombiner before creating and initializing GraphicsContext");
+            m_pRender = NULL;
+            SAFE_CHECK(m_pRender);
+        }
+
+        COGLGraphicsContext &context = *((COGLGraphicsContext*)CGraphicsContext::g_pGraphicsContext);
+
+        if( context.m_bSupportMultiTexture )
+        {
+            // OGL extension render
+            m_pRender = new COGLExtRender();
+        }
+        else
+        {
+            // Basic OGL Render
+            m_pRender = new OGLRender();
+        }
+        SAFE_CHECK(m_pRender);
+        CRender::g_pRender = m_pRender;
+    }
+
+    return m_pRender;
+}
+
+CTexture * OGLDeviceBuilder::CreateTexture(uint32 dwWidth, uint32 dwHeight, TextureUsage usage)
+{
+    COGLTexture *txtr = new COGLTexture(dwWidth, dwHeight, usage);
+    if( txtr->m_pTexture == NULL )
+    {
+        delete txtr;
+        TRACE0("Cannot create new texture, out of video memory");
+        return NULL;
+    }
+    else
+        return txtr;
+}
+
+CColorCombiner * OGLDeviceBuilder::CreateColorCombiner(CRender *pRender)
+{
+    if( m_pColorCombiner == NULL )
+    {
+        if( CGraphicsContext::g_pGraphicsContext == NULL && CGraphicsContext::g_pGraphicsContext->Ready() )
+        {
+            DebugMessage(M64MSG_ERROR, "Can not create ColorCombiner before creating and initializing GraphicsContext");
+        }
+        else
+        {
+            m_deviceType = (SupportedDeviceType)options.OpenglRenderSetting;
+
+#if SDL_VIDEO_OPENGL
+
+            if (m_deviceType == NVIDIA_OGL_DEVICE && !bNvidiaExtensionsSupported)
+            {
+                DebugMessage(M64MSG_WARNING, "Your video card does not support Nvidia OpenGL extensions.  Falling back to auto device.");
+                m_deviceType = OGL_DEVICE;
+            }
+            if( m_deviceType == OGL_DEVICE )    // Best fit
+            {
+                GLint maxUnit = 2;
+                COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
+                glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&maxUnit);
+                OPENGL_CHECK_ERRORS;
+#ifndef HAVE_GLES
+                if( pcontext->IsExtensionSupported("GL_ARB_fragment_program") )
+                {
+                    m_pColorCombiner = new COGL_FragmentProgramCombiner(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Fragment Program");
+                }
+                else if( pcontext->IsExtensionSupported("GL_NV_texture_env_combine4") || 
+                    pcontext->IsExtensionSupported("GL_NV_register_combiners") )
+                {
+                    m_pColorCombiner = new COGLColorCombinerNvidia(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: NVidia");
+                }
+                else if( pcontext->IsExtensionSupported("GL_NV_texture_env_combine4") )
+                {
+                    m_pColorCombiner = new COGLColorCombinerTNT2(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: TNT2");
+                }
+                else if( pcontext->IsExtensionSupported("GL_EXT_texture_env_combine") ||
+                         pcontext->IsExtensionSupported("GL_ARB_texture_env_combine") )
+                {
+                    if( pcontext->IsExtensionSupported("GL_ARB_texture_env_crossbar") )
+#endif
+                    {
+#ifndef HAVE_GLES
+                        if( maxUnit > 2 )
+                        {
+                            m_pColorCombiner = new COGLColorCombiner4v2(pRender);
+                            DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4 version 2");
+                        }
+                        else
+#endif
+                        {
+                            m_pColorCombiner = new COGLColorCombiner4(pRender);
+                            DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4");
+                        }
+                     }
+#ifndef HAVE_GLES
+                   else
+                    {
+                        if( maxUnit > 2 )
+                        {
+                            m_pColorCombiner = new COGLColorCombiner4v2(pRender);
+                            DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4 version 2 (w/o env crossbar)");
+                        }
+                        else
+                        {
+                            m_pColorCombiner = new COGLColorCombiner2(pRender);
+                            DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.2/1.3");
+                        }
+                    }
+                }
+                else
+                {
+                    m_pColorCombiner = new COGLColorCombiner(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Basic OGL");
+                }
+#endif
+            }
+            else
+            {
+                switch(m_deviceType)
+                {
+                case OGL_1_1_DEVICE:
+                    m_pColorCombiner = new COGLColorCombiner(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Basic OGL");
+                    break;
+                case OGL_1_2_DEVICE:
+                case OGL_1_3_DEVICE:
+                    m_pColorCombiner = new COGLColorCombiner2(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.2/1.3");
+                    break;
+                case OGL_1_4_DEVICE:
+                    m_pColorCombiner = new COGLColorCombiner4(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4");
+                    break;
+                case OGL_1_4_V2_DEVICE:
+                    m_pColorCombiner = new COGLColorCombiner4v2(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4 Version 2");
+                    break;
+#ifndef HAVE_GLES
+                case OGL_TNT2_DEVICE:
+                    m_pColorCombiner = new COGLColorCombinerTNT2(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: TNT2");
+                    break;
+                case NVIDIA_OGL_DEVICE:
+                    m_pColorCombiner = new COGLColorCombinerNvidia(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Nvidia");
+                    break;
+                case OGL_FRAGMENT_PROGRAM:
+                    m_pColorCombiner = new COGL_FragmentProgramCombiner(pRender);
+                    DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Fragment Program");
+                    break;
+#endif
+                 default:
+                    break;
+                }
+            }
+
+#elif SDL_VIDEO_OPENGL_ES2
+            m_pColorCombiner = new COGL_FragmentProgramCombiner(pRender);
+            DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Fragment Program");
+#endif
+        }
+
+        SAFE_CHECK(m_pColorCombiner);
+    }
+
+    return m_pColorCombiner;
+}
+
+CBlender * OGLDeviceBuilder::CreateAlphaBlender(CRender *pRender)
+{
+    if( m_pAlphaBlender == NULL )
+    {
+        m_pAlphaBlender = new COGLBlender(pRender);
+        SAFE_CHECK(m_pAlphaBlender);
+    }
+
+    return m_pAlphaBlender;
+}
+