GLE2RICE: Some fixes from muppen64plus-ae
[mupen64plus-pandora.git] / source / gles2rice / src / OGLExtRender.cpp
1 /*
2 Copyright (C) 2003 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18
19 #include "osal_opengl.h"
20
21 #if SDL_VIDEO_OPENGL
22 #include "OGLExtensions.h"
23 #endif
24 #include "OGLDebug.h"
25 #include "OGLExtRender.h"
26 #include "OGLTexture.h"
27
28 void COGLExtRender::Initialize(void)
29 {
30     OGLRender::Initialize();
31
32     // Initialize multitexture
33     glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&m_maxTexUnits);
34     OPENGL_CHECK_ERRORS;
35
36     for( int i=0; i<8; i++ )
37         m_textureUnitMap[i] = -1;
38     m_textureUnitMap[0] = 0;    // T0 is usually using texture unit 0
39     m_textureUnitMap[1] = 1;    // T1 is usually using texture unit 1
40 }
41
42
43 void COGLExtRender::BindTexture(GLuint texture, int unitno)
44 {
45     if( m_bEnableMultiTexture )
46     {
47         if( unitno < m_maxTexUnits )
48         {
49             if( m_curBoundTex[unitno] != texture )
50             {
51                 pglActiveTexture(GL_TEXTURE0_ARB+unitno);
52                 OPENGL_CHECK_ERRORS;
53                 glBindTexture(GL_TEXTURE_2D,texture);
54                 OPENGL_CHECK_ERRORS;
55                 m_curBoundTex[unitno] = texture;
56             }
57         }
58     }
59     else
60     {
61         OGLRender::BindTexture(texture, unitno);
62     }
63 }
64
65 void COGLExtRender::DisBindTexture(GLuint texture, int unitno)
66 {
67     if( m_bEnableMultiTexture )
68     {
69         pglActiveTexture(GL_TEXTURE0_ARB+unitno);
70         OPENGL_CHECK_ERRORS;
71         glBindTexture(GL_TEXTURE_2D, 0);    //Not to bind any texture
72         OPENGL_CHECK_ERRORS;
73     }
74     else
75         OGLRender::DisBindTexture(texture, unitno);
76 }
77
78 void COGLExtRender::TexCoord2f(float u, float v)
79 {
80 #if SDL_VIDEO_OPENGL
81     if( m_bEnableMultiTexture )
82     {
83         for( int i=0; i<8; i++ )
84         {
85             if( m_textureUnitMap[i] >= 0 )
86             {
87                 pglMultiTexCoord2f(GL_TEXTURE0_ARB+i, u, v);
88             }
89         }
90     }
91     else
92     {
93         OGLRender::TexCoord2f(u,v);
94     }
95 #endif
96 }
97
98 void COGLExtRender::TexCoord(TLITVERTEX &vtxInfo)
99 {
100 #if SDL_VIDEO_OPENGL
101     if( m_bEnableMultiTexture )
102     {
103         for( int i=0; i<8; i++ )
104         {
105             if( m_textureUnitMap[i] >= 0 )
106             {
107                 pglMultiTexCoord2fv(GL_TEXTURE0_ARB+i, &(vtxInfo.tcord[m_textureUnitMap[i]].u));
108             }
109         }
110     }
111     else
112     {
113         OGLRender::TexCoord(vtxInfo);
114     }
115 #endif
116 }
117
118
119 void COGLExtRender::SetTexWrapS(int unitno,GLuint flag)
120 {
121     static GLuint mflag[8];
122     static GLuint mtex[8];
123     if( m_curBoundTex[unitno] != mtex[unitno] || mflag[unitno] != flag )
124     {
125         mtex[unitno] = m_curBoundTex[0];
126         mflag[unitno] = flag;
127         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, flag);
128         OPENGL_CHECK_ERRORS;
129     }
130 }
131 void COGLExtRender::SetTexWrapT(int unitno,GLuint flag)
132 {
133     static GLuint mflag[8];
134     static GLuint mtex[8];
135     if( m_curBoundTex[unitno] != mtex[unitno] || mflag[unitno] != flag )
136     {
137         mtex[unitno] = m_curBoundTex[0];
138         mflag[unitno] = flag;
139         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, flag);
140         OPENGL_CHECK_ERRORS;
141     }
142 }
143
144 extern UVFlagMap OGLXUVFlagMaps[];
145 void COGLExtRender::SetTextureUFlag(TextureUVFlag dwFlag, uint32 dwTile)
146 {
147     TileUFlags[dwTile] = dwFlag;
148     if( !m_bEnableMultiTexture )
149     {
150         OGLRender::SetTextureUFlag(dwFlag, dwTile);
151         return;
152     }
153
154     int tex;
155     if( dwTile == gRSP.curTile )
156         tex=0;
157     else if( dwTile == ((gRSP.curTile+1)&7) )
158         tex=1;
159     else
160     {
161         if( dwTile == ((gRSP.curTile+2)&7) )
162             tex=2;
163         else if( dwTile == ((gRSP.curTile+3)&7) )
164             tex=3;
165         else
166         {
167             TRACE2("Incorrect tile number for OGL SetTextureUFlag: cur=%d, tile=%d", gRSP.curTile, dwTile);
168             return;
169         }
170     }
171
172     for( int textureNo=0; textureNo<8; textureNo++)
173     {
174         if( m_textureUnitMap[textureNo] == tex )
175         {
176             pglActiveTexture(GL_TEXTURE0_ARB+textureNo);
177             OPENGL_CHECK_ERRORS;
178             COGLTexture* pTexture = g_textures[(gRSP.curTile+tex)&7].m_pCOGLTexture;
179             if( pTexture ) 
180             {
181                 EnableTexUnit(textureNo,TRUE);
182                 BindTexture(pTexture->m_dwTextureName, textureNo);
183             }
184             SetTexWrapS(textureNo, OGLXUVFlagMaps[dwFlag].realFlag);
185         }
186     }
187 }
188 void COGLExtRender::SetTextureVFlag(TextureUVFlag dwFlag, uint32 dwTile)
189 {
190     TileVFlags[dwTile] = dwFlag;
191     if( !m_bEnableMultiTexture )
192     {
193         OGLRender::SetTextureVFlag(dwFlag, dwTile);
194         return;
195     }
196
197     int tex;
198     if( dwTile == gRSP.curTile )
199         tex=0;
200     else if( dwTile == ((gRSP.curTile+1)&7) )
201         tex=1;
202     else
203     {
204         if( dwTile == ((gRSP.curTile+2)&7) )
205             tex=2;
206         else if( dwTile == ((gRSP.curTile+3)&7) )
207             tex=3;
208         else
209         {
210             TRACE2("Incorrect tile number for OGL SetTextureVFlag: cur=%d, tile=%d", gRSP.curTile, dwTile);
211             return;
212         }
213     }
214     
215     for( int textureNo=0; textureNo<8; textureNo++)
216     {
217         if( m_textureUnitMap[textureNo] == tex )
218         {
219             COGLTexture* pTexture = g_textures[(gRSP.curTile+tex)&7].m_pCOGLTexture;
220             if( pTexture )
221             {
222                 EnableTexUnit(textureNo,TRUE);
223                 BindTexture(pTexture->m_dwTextureName, textureNo);
224             }
225             SetTexWrapT(textureNo, OGLXUVFlagMaps[dwFlag].realFlag);
226         }
227     }
228 }
229
230 void COGLExtRender::EnableTexUnit(int unitno, BOOL flag)
231 {
232     if( m_texUnitEnabled[unitno] != flag )
233     {
234         m_texUnitEnabled[unitno] = flag;
235         pglActiveTexture(GL_TEXTURE0_ARB+unitno);
236         OPENGL_CHECK_ERRORS;
237         if( flag == TRUE )
238             glEnable(GL_TEXTURE_2D);
239         else
240             glDisable(GL_TEXTURE_2D);
241         OPENGL_CHECK_ERRORS;
242     }
243 }
244
245 void COGLExtRender::ApplyTextureFilter()
246 {
247     static uint32 minflag[8], magflag[8];
248     static uint32 mtex[8];
249
250     int iMinFilter, iMagFilter;
251
252     for( int i=0; i<m_maxTexUnits; i++ )
253     {
254         //Compute iMinFilter and iMagFilter
255         if(m_dwMinFilter == FILTER_LINEAR) //Texture will use filtering
256         {
257             iMagFilter = GL_LINEAR;
258
259             //Texture filtering method user want
260             switch(options.mipmapping)
261             {
262             case TEXTURE_BILINEAR_FILTER:
263                 iMinFilter = GL_LINEAR_MIPMAP_NEAREST;
264                 break;
265             case TEXTURE_TRILINEAR_FILTER:
266                 iMinFilter = GL_LINEAR_MIPMAP_LINEAR;
267                 break;
268             case TEXTURE_NO_FILTER:
269                 iMinFilter = GL_NEAREST_MIPMAP_NEAREST;
270                 break;
271             case TEXTURE_NO_MIPMAP:
272             default:
273                 //Bilinear without mipmap
274                 iMinFilter = GL_LINEAR;
275             }
276         }
277         else    //dont use filtering, all is nearest
278         {
279             iMagFilter = GL_NEAREST;
280
281             if(options.mipmapping)
282             {
283                 iMinFilter = GL_NEAREST_MIPMAP_NEAREST;
284             }
285             else
286             {
287                 iMinFilter = GL_NEAREST;
288             }
289         }
290
291         if( m_texUnitEnabled[i] )
292         {
293             if( mtex[i] != m_curBoundTex[i] )
294             {
295                 mtex[i] = m_curBoundTex[i];
296                 pglActiveTexture(GL_TEXTURE0_ARB+i);
297                 OPENGL_CHECK_ERRORS;
298                 minflag[i] = m_dwMinFilter;
299                 magflag[i] = m_dwMagFilter;
300                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iMinFilter);
301                 OPENGL_CHECK_ERRORS;
302                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iMagFilter);
303                 OPENGL_CHECK_ERRORS;
304             }
305             else
306             {
307                 if( minflag[i] != (unsigned int)m_dwMinFilter )
308                 {
309                     minflag[i] = m_dwMinFilter;
310                     pglActiveTexture(GL_TEXTURE0_ARB+i);
311                     OPENGL_CHECK_ERRORS;
312                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iMinFilter);
313                     OPENGL_CHECK_ERRORS;
314                 }
315                 if( magflag[i] != (unsigned int)m_dwMagFilter )
316                 {
317                     magflag[i] = m_dwMagFilter;
318                     pglActiveTexture(GL_TEXTURE0_ARB+i);
319                     OPENGL_CHECK_ERRORS;
320                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iMagFilter);
321                     OPENGL_CHECK_ERRORS;
322                 }
323             }
324         }
325     }
326 }
327
328 void COGLExtRender::SetTextureToTextureUnitMap(int tex, int unit)
329 {
330     if( unit < 8 && (tex >= -1 || tex <= 1))
331         m_textureUnitMap[unit] = tex;
332 }
333