--- /dev/null
+/*
+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;
+}
+