Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / OGLCombiner.cpp
diff --git a/source/rice_gles/src/OGLCombiner.cpp b/source/rice_gles/src/OGLCombiner.cpp
new file mode 100644 (file)
index 0000000..2986c7a
--- /dev/null
@@ -0,0 +1,359 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus - OGLCombiner.cpp                                         *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "osal_opengl.h"
+
+#include "OGLCombiner.h"
+#include "OGLDebug.h"
+#include "OGLRender.h"
+#include "OGLGraphicsContext.h"
+#include "OGLDecodedMux.h"
+#include "OGLTexture.h"
+
+//========================================================================
+uint32 DirectX_OGL_BlendFuncMaps [] =
+{
+    GL_SRC_ALPHA,               //Nothing
+    GL_ZERO,                    //BLEND_ZERO               = 1,
+    GL_ONE,                     //BLEND_ONE                = 2,
+    GL_SRC_COLOR,               //BLEND_SRCCOLOR           = 3,
+    GL_ONE_MINUS_SRC_COLOR,     //BLEND_INVSRCCOLOR        = 4,
+    GL_SRC_ALPHA,               //BLEND_SRCALPHA           = 5,
+    GL_ONE_MINUS_SRC_ALPHA,     //BLEND_INVSRCALPHA        = 6,
+    GL_DST_ALPHA,               //BLEND_DESTALPHA          = 7,
+    GL_ONE_MINUS_DST_ALPHA,     //BLEND_INVDESTALPHA       = 8,
+    GL_DST_COLOR,               //BLEND_DESTCOLOR          = 9,
+    GL_ONE_MINUS_DST_COLOR,     //BLEND_INVDESTCOLOR       = 10,
+    GL_SRC_ALPHA_SATURATE,      //BLEND_SRCALPHASAT        = 11,
+    GL_SRC_ALPHA_SATURATE,      //BLEND_BOTHSRCALPHA       = 12,    
+    GL_SRC_ALPHA_SATURATE,      //BLEND_BOTHINVSRCALPHA    = 13,
+};
+
+//========================================================================
+COGLColorCombiner::COGLColorCombiner(CRender *pRender) :
+    CColorCombiner(pRender),
+    m_pOGLRender((OGLRender*)pRender),
+    m_bSupportAdd(false), m_bSupportSubtract(false)
+{
+    m_pDecodedMux = new COGLDecodedMux;
+    m_pDecodedMux->m_maxConstants = 0;
+    m_pDecodedMux->m_maxTextures = 1;
+}
+
+COGLColorCombiner::~COGLColorCombiner()
+{
+    delete m_pDecodedMux;
+    m_pDecodedMux = NULL;
+}
+
+bool COGLColorCombiner::Initialize(void)
+{
+    m_bSupportAdd = false;
+    m_bSupportSubtract = false;
+    m_supportedStages = 1;
+    m_bSupportMultiTexture = false;
+
+#ifndef HAVE_GLES
+    COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
+    if( pcontext->IsExtensionSupported(OSAL_GL_ARB_TEXTURE_ENV_ADD) || pcontext->IsExtensionSupported("GL_EXT_texture_env_add") )
+#endif
+    {
+        m_bSupportAdd = true;
+    }
+#ifndef HAVE_GLES
+    if( pcontext->IsExtensionSupported("GL_EXT_blend_subtract") )
+#endif
+    {
+        m_bSupportSubtract = true;
+    }
+
+    return true;
+}
+
+void COGLColorCombiner::DisableCombiner(void)
+{
+    m_pOGLRender->DisableMultiTexture();
+    glEnable(GL_BLEND);
+    OPENGL_CHECK_ERRORS;
+    glBlendFunc(GL_ONE, GL_ZERO);
+    OPENGL_CHECK_ERRORS;
+    
+    if( m_bTexelsEnable )
+    {
+        COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
+        if( pTexture ) 
+        {
+            m_pOGLRender->EnableTexUnit(0,TRUE);
+            m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
+            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            OPENGL_CHECK_ERRORS;
+            m_pOGLRender->SetAllTexelRepeatFlag();
+        }
+#ifdef DEBUGGER
+        else
+        {
+            DebuggerAppendMsg("Check me, texture is NULL but it is enabled");
+        }
+#endif
+    }
+    else
+    {
+        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+        OPENGL_CHECK_ERRORS;
+        m_pOGLRender->EnableTexUnit(0,FALSE);
+    }
+}
+
+void COGLColorCombiner::InitCombinerCycleCopy(void)
+{
+    m_pOGLRender->DisableMultiTexture();
+    m_pOGLRender->EnableTexUnit(0,TRUE);
+    COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
+    if( pTexture )
+    {
+        m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
+        m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile);
+    }
+#ifdef DEBUGGER
+    else
+    {
+        DebuggerAppendMsg("Check me, texture is NULL");
+    }
+#endif
+
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    OPENGL_CHECK_ERRORS;
+}
+
+void COGLColorCombiner::InitCombinerCycleFill(void)
+{
+    m_pOGLRender->DisableMultiTexture();
+    m_pOGLRender->EnableTexUnit(0,FALSE);
+}
+
+
+void COGLColorCombiner::InitCombinerCycle12(void)
+{
+    m_pOGLRender->DisableMultiTexture();
+    if( !m_bTexelsEnable )
+    {
+        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+        OPENGL_CHECK_ERRORS;
+        m_pOGLRender->EnableTexUnit(0,FALSE);
+        return;
+    }
+
+#if SDL_VIDEO_OPENGL
+    uint32 mask = 0x1f;
+    COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
+    if( pTexture )
+    {
+        m_pOGLRender->EnableTexUnit(0,TRUE);
+        m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
+        m_pOGLRender->SetAllTexelRepeatFlag();
+    }
+#ifdef DEBUGGER
+    else
+    {
+        DebuggerAppendMsg("Check me, texture is NULL");
+    }
+#endif
+
+    bool texIsUsed = m_pDecodedMux->isUsed(MUX_TEXEL0);
+    bool shadeIsUsedInColor = m_pDecodedMux->isUsedInCycle(MUX_SHADE, 0, COLOR_CHANNEL);
+    bool texIsUsedInColor = m_pDecodedMux->isUsedInCycle(MUX_TEXEL0, 0, COLOR_CHANNEL);
+
+    if( texIsUsed )
+    {
+        // Parse the simplified the mux, because the OGL 1.1 combiner function is so much
+        // limited, we only parse the 1st N64 combiner setting and only the RGB part
+
+        N64CombinerType & comb = m_pDecodedMux->m_n64Combiners[0];
+        switch( m_pDecodedMux->mType )
+        {
+        case CM_FMT_TYPE_NOT_USED:
+        case CM_FMT_TYPE_D:             // = A
+            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            OPENGL_CHECK_ERRORS;
+            break;
+        case CM_FMT_TYPE_A_ADD_D:           // = A+D
+            if( shadeIsUsedInColor && texIsUsedInColor )
+            {
+                if( m_bSupportAdd )
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
+                else
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+            }
+            else if( texIsUsedInColor )
+            {
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            }
+            else
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            OPENGL_CHECK_ERRORS;
+            break;
+        case CM_FMT_TYPE_A_SUB_B:           // = A-B
+            if( shadeIsUsedInColor && texIsUsedInColor )
+            {
+                if( m_bSupportSubtract )
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_SUBTRACT_ARB);
+                else
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+            }
+            else if( texIsUsedInColor )
+            {
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            }
+            else
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            OPENGL_CHECK_ERRORS;
+            break;
+        case CM_FMT_TYPE_A_MOD_C:           // = A*C
+        case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D
+            if( shadeIsUsedInColor && texIsUsedInColor )
+            {
+                if( ((comb.c & mask) == MUX_SHADE && !(comb.c&MUX_COMPLEMENT)) ||
+                    ((comb.a & mask) == MUX_SHADE && !(comb.a&MUX_COMPLEMENT)) )
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+                else
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            }
+            else if( texIsUsedInColor )
+            {
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            }
+            else
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            OPENGL_CHECK_ERRORS;
+            break;
+        case CM_FMT_TYPE_A_LERP_B_C:    // = A*C+D
+            if( (comb.b&mask) == MUX_SHADE && (comb.c&mask)==MUX_TEXEL0 && ((comb.a&mask)==MUX_PRIM||(comb.a&mask)==MUX_ENV))
+            {
+                float *fv;
+                if( (comb.a&mask)==MUX_PRIM )
+                {
+                    fv = GetPrimitiveColorfv();
+                }
+                else
+                {
+                    fv = GetEnvColorfv();
+                }
+
+                glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,fv);
+                OPENGL_CHECK_ERRORS;
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+                OPENGL_CHECK_ERRORS;
+                break;
+            }
+        default:        // = (A-B)*C+D
+            if( shadeIsUsedInColor )
+            {
+                if( ((comb.c & mask) == MUX_SHADE && !(comb.c&MUX_COMPLEMENT)) ||
+                    ((comb.a & mask) == MUX_SHADE && !(comb.a&MUX_COMPLEMENT)) )
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+                else
+                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            }
+            else
+            {
+                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            }
+            OPENGL_CHECK_ERRORS;
+            break;
+        }
+    }
+    else
+    {
+        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+        OPENGL_CHECK_ERRORS;
+    }
+#endif
+}
+
+void COGLBlender::NormalAlphaBlender(void)
+{
+    glEnable(GL_BLEND);
+    OPENGL_CHECK_ERRORS;
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    OPENGL_CHECK_ERRORS;
+}
+
+void COGLBlender::DisableAlphaBlender(void)
+{
+    glEnable(GL_BLEND);
+    OPENGL_CHECK_ERRORS;
+    glBlendFunc(GL_ONE, GL_ZERO);
+    OPENGL_CHECK_ERRORS;
+}
+
+
+void COGLBlender::BlendFunc(uint32 srcFunc, uint32 desFunc)
+{
+    glBlendFunc(DirectX_OGL_BlendFuncMaps[srcFunc], DirectX_OGL_BlendFuncMaps[desFunc]);
+    OPENGL_CHECK_ERRORS;
+}
+
+void COGLBlender::Enable()
+{
+    glEnable(GL_BLEND);
+    OPENGL_CHECK_ERRORS;
+}
+
+void COGLBlender::Disable()
+{
+    glDisable(GL_BLEND);
+    OPENGL_CHECK_ERRORS;
+}
+
+void COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
+{
+    m_pOGLRender->DisableMultiTexture();
+    if( g_textures[tile].m_pCTexture )
+    {
+        m_pOGLRender->EnableTexUnit(0,TRUE);
+        glBindTexture(GL_TEXTURE_2D, ((COGLTexture*)(g_textures[tile].m_pCTexture))->m_dwTextureName);
+        OPENGL_CHECK_ERRORS;
+    }
+    m_pOGLRender->SetAllTexelRepeatFlag();
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    OPENGL_CHECK_ERRORS;
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+    OPENGL_CHECK_ERRORS;
+    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
+    OPENGL_CHECK_ERRORS;
+    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
+    OPENGL_CHECK_ERRORS;
+
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    OPENGL_CHECK_ERRORS;
+    m_pOGLRender->SetAlphaTestEnable(FALSE);
+}
+
+#ifdef DEBUGGER
+extern const char *translatedCombTypes[];
+void COGLColorCombiner::DisplaySimpleMuxString(void)
+{
+    TRACE0("\nSimplified Mux\n");
+    m_pDecodedMux->DisplaySimpliedMuxString("Used");
+}
+#endif
+