Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / OGLExtRender.cpp
diff --git a/source/rice_gles/src/OGLExtRender.cpp b/source/rice_gles/src/OGLExtRender.cpp
new file mode 100755 (executable)
index 0000000..dc4eb59
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+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"
+
+#if SDL_VIDEO_OPENGL
+#include "OGLExtensions.h"
+#endif
+#include "OGLDebug.h"
+#include "OGLExtRender.h"
+#include "OGLTexture.h"
+
+void COGLExtRender::Initialize(void)
+{
+    OGLRender::Initialize();
+
+    // Initialize multitexture
+    glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&m_maxTexUnits);
+    OPENGL_CHECK_ERRORS;
+
+    for( int i=0; i<8; i++ )
+        m_textureUnitMap[i] = -1;
+    m_textureUnitMap[0] = 0;    // T0 is usually using texture unit 0
+    m_textureUnitMap[1] = 1;    // T1 is usually using texture unit 1
+}
+
+
+void COGLExtRender::BindTexture(GLuint texture, int unitno)
+{
+    if( m_bEnableMultiTexture )
+    {
+        if( unitno < m_maxTexUnits )
+        {
+            if( m_curBoundTex[unitno] != texture )
+            {
+                pglActiveTexture(GL_TEXTURE0_ARB+unitno);
+                OPENGL_CHECK_ERRORS;
+                glBindTexture(GL_TEXTURE_2D,texture);
+                OPENGL_CHECK_ERRORS;
+                m_curBoundTex[unitno] = texture;
+            }
+        }
+    }
+    else
+    {
+        OGLRender::BindTexture(texture, unitno);
+    }
+}
+
+void COGLExtRender::DisBindTexture(GLuint texture, int unitno)
+{
+    if( m_bEnableMultiTexture )
+    {
+        pglActiveTexture(GL_TEXTURE0_ARB+unitno);
+        OPENGL_CHECK_ERRORS;
+        glBindTexture(GL_TEXTURE_2D, 0);    //Not to bind any texture
+        OPENGL_CHECK_ERRORS;
+    }
+    else
+        OGLRender::DisBindTexture(texture, unitno);
+}
+
+void COGLExtRender::TexCoord2f(float u, float v)
+{
+#if SDL_VIDEO_OPENGL
+    if( m_bEnableMultiTexture )
+    {
+//printf("*SEB* overloaded TexCoord2f(%f, %f)\n", u, v);
+        for( int i=0; i<8; i++ )
+        {
+            if( m_textureUnitMap[i] >= 0 )
+            {
+                pglMultiTexCoord2f(GL_TEXTURE0_ARB+i, u, v);
+            }
+        }
+    }
+    else
+    {
+        OGLRender::TexCoord2f(u,v);
+    }
+#endif
+}
+
+void COGLExtRender::TexCoord(TLITVERTEX &vtxInfo)
+{
+#if SDL_VIDEO_OPENGL
+    if( m_bEnableMultiTexture )
+    {
+//printf("*SEB* overloaded TexCoord(%f, %f)\n", vtxInfo.tcord[0].u, vtxInfo.tcord[0].v);
+        for( int i=0; i<8; i++ )
+        {
+            if( m_textureUnitMap[i] >= 0 )
+            {
+                pglMultiTexCoord2fv(GL_TEXTURE0_ARB+i, &(vtxInfo.tcord[m_textureUnitMap[i]].u));
+            }
+        }
+    }
+    else
+    {
+        OGLRender::TexCoord(vtxInfo);
+    }
+#endif
+}
+
+
+void COGLExtRender::SetTexWrapS(int unitno,GLuint flag)
+{
+    static GLuint mflag[8];
+    static GLuint mtex[8];
+    if( m_curBoundTex[unitno] != mtex[unitno] || mflag[unitno] != flag )
+    {
+        mtex[unitno] = m_curBoundTex[0];
+        mflag[unitno] = flag;
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, flag);
+        OPENGL_CHECK_ERRORS;
+    }
+}
+void COGLExtRender::SetTexWrapT(int unitno,GLuint flag)
+{
+    static GLuint mflag[8];
+    static GLuint mtex[8];
+    if( m_curBoundTex[unitno] != mtex[unitno] || mflag[unitno] != flag )
+    {
+        mtex[unitno] = m_curBoundTex[0];
+        mflag[unitno] = flag;
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, flag);
+        OPENGL_CHECK_ERRORS;
+    }
+}
+
+extern UVFlagMap OGLXUVFlagMaps[];
+void COGLExtRender::SetTextureUFlag(TextureUVFlag dwFlag, uint32 dwTile)
+{
+    TileUFlags[dwTile] = dwFlag;
+    if( !m_bEnableMultiTexture )
+    {
+        OGLRender::SetTextureUFlag(dwFlag, dwTile);
+        return;
+    }
+
+    int tex;
+    if( dwTile == gRSP.curTile )
+        tex=0;
+    else if( dwTile == ((gRSP.curTile+1)&7) )
+        tex=1;
+    else
+    {
+        if( dwTile == ((gRSP.curTile+2)&7) )
+            tex=2;
+        else if( dwTile == ((gRSP.curTile+3)&7) )
+            tex=3;
+        else
+        {
+            TRACE2("Incorrect tile number for OGL SetTextureUFlag: cur=%d, tile=%d", gRSP.curTile, dwTile);
+            return;
+        }
+    }
+
+    for( int textureNo=0; textureNo<8; textureNo++)
+    {
+        if( m_textureUnitMap[textureNo] == tex )
+        {
+            pglActiveTexture(GL_TEXTURE0_ARB+textureNo);
+            OPENGL_CHECK_ERRORS;
+            COGLTexture* pTexture = g_textures[(gRSP.curTile+tex)&7].m_pCOGLTexture;
+            if( pTexture ) 
+            {
+                EnableTexUnit(textureNo,TRUE);
+                BindTexture(pTexture->m_dwTextureName, textureNo);
+            }
+            SetTexWrapS(textureNo, OGLXUVFlagMaps[dwFlag].realFlag);
+        }
+    }
+}
+void COGLExtRender::SetTextureVFlag(TextureUVFlag dwFlag, uint32 dwTile)
+{
+    TileVFlags[dwTile] = dwFlag;
+    if( !m_bEnableMultiTexture )
+    {
+        OGLRender::SetTextureVFlag(dwFlag, dwTile);
+        return;
+    }
+
+    int tex;
+    if( dwTile == gRSP.curTile )
+        tex=0;
+    else if( dwTile == ((gRSP.curTile+1)&7) )
+        tex=1;
+    else
+    {
+        if( dwTile == ((gRSP.curTile+2)&7) )
+            tex=2;
+        else if( dwTile == ((gRSP.curTile+3)&7) )
+            tex=3;
+        else
+        {
+            TRACE2("Incorrect tile number for OGL SetTextureVFlag: cur=%d, tile=%d", gRSP.curTile, dwTile);
+            return;
+        }
+    }
+    
+    for( int textureNo=0; textureNo<8; textureNo++)
+    {
+        if( m_textureUnitMap[textureNo] == tex )
+        {
+            COGLTexture* pTexture = g_textures[(gRSP.curTile+tex)&7].m_pCOGLTexture;
+            if( pTexture )
+            {
+                EnableTexUnit(textureNo,TRUE);
+                BindTexture(pTexture->m_dwTextureName, textureNo);
+            }
+            SetTexWrapT(textureNo, OGLXUVFlagMaps[dwFlag].realFlag);
+        }
+    }
+}
+
+void COGLExtRender::EnableTexUnit(int unitno, BOOL flag)
+{
+    if( m_texUnitEnabled[unitno] != flag )
+    {
+        m_texUnitEnabled[unitno] = flag;
+        pglActiveTexture(GL_TEXTURE0_ARB+unitno);
+        OPENGL_CHECK_ERRORS;
+        if( flag == TRUE )
+            glEnable(GL_TEXTURE_2D);
+        else
+            glDisable(GL_TEXTURE_2D);
+        OPENGL_CHECK_ERRORS;
+    }
+}
+
+void COGLExtRender::ApplyTextureFilter()
+{
+    static uint32 minflag[8], magflag[8];
+    static uint32 mtex[8];
+
+    int iMinFilter, iMagFilter;
+
+    for( int i=0; i<m_maxTexUnits; i++ )
+    {
+        //Compute iMinFilter and iMagFilter
+        if(m_dwMinFilter == FILTER_LINEAR) //Texture will use filtering
+        {
+            iMagFilter = GL_LINEAR;
+
+            //Texture filtering method user want
+            switch(options.mipmapping)
+            {
+            case TEXTURE_BILINEAR_FILTER:
+                iMinFilter = GL_LINEAR_MIPMAP_NEAREST;
+                break;
+            case TEXTURE_TRILINEAR_FILTER:
+                iMinFilter = GL_LINEAR_MIPMAP_LINEAR;
+                break;
+            case TEXTURE_NO_FILTER:
+                iMinFilter = GL_NEAREST_MIPMAP_NEAREST;
+                break;
+            case TEXTURE_NO_MIPMAP:
+            default:
+                //Bilinear without mipmap
+                iMinFilter = GL_LINEAR;
+            }
+        }
+        else    //dont use filtering, all is nearest
+        {
+            iMagFilter = GL_NEAREST;
+
+            if(options.mipmapping)
+            {
+                iMinFilter = GL_NEAREST_MIPMAP_NEAREST;
+            }
+            else
+            {
+                iMinFilter = GL_NEAREST;
+            }
+        }
+
+        if( m_texUnitEnabled[i] )
+        {
+            if( mtex[i] != m_curBoundTex[i] )
+            {
+                mtex[i] = m_curBoundTex[i];
+                pglActiveTexture(GL_TEXTURE0_ARB+i);
+                OPENGL_CHECK_ERRORS;
+                minflag[i] = m_dwMinFilter;
+                magflag[i] = m_dwMagFilter;
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iMinFilter);
+                OPENGL_CHECK_ERRORS;
+                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iMagFilter);
+                OPENGL_CHECK_ERRORS;
+            }
+            else
+            {
+                if( minflag[i] != (unsigned int)m_dwMinFilter )
+                {
+                    minflag[i] = m_dwMinFilter;
+                    pglActiveTexture(GL_TEXTURE0_ARB+i);
+                    OPENGL_CHECK_ERRORS;
+                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iMinFilter);
+                    OPENGL_CHECK_ERRORS;
+                }
+                if( magflag[i] != (unsigned int)m_dwMagFilter )
+                {
+                    magflag[i] = m_dwMagFilter;
+                    pglActiveTexture(GL_TEXTURE0_ARB+i);
+                    OPENGL_CHECK_ERRORS;
+                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iMagFilter);
+                    OPENGL_CHECK_ERRORS;
+                }
+            }
+        }
+    }
+}
+
+void COGLExtRender::SetTextureToTextureUnitMap(int tex, int unit)
+{
+    if( unit < 8 && (tex >= -1 || tex <= 1))
+        m_textureUnitMap[unit] = tex;
+}
+