Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / OGLCombiner.cpp
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - OGLCombiner.cpp                                         *
3  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
4  *   Copyright (C) 2003 Rice1964                                           *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 #include "osal_opengl.h"
23
24 #include "OGLCombiner.h"
25 #include "OGLDebug.h"
26 #include "OGLRender.h"
27 #include "OGLGraphicsContext.h"
28 #include "OGLDecodedMux.h"
29 #include "OGLTexture.h"
30
31 //========================================================================
32 uint32 DirectX_OGL_BlendFuncMaps [] =
33 {
34     GL_SRC_ALPHA,               //Nothing
35     GL_ZERO,                    //BLEND_ZERO               = 1,
36     GL_ONE,                     //BLEND_ONE                = 2,
37     GL_SRC_COLOR,               //BLEND_SRCCOLOR           = 3,
38     GL_ONE_MINUS_SRC_COLOR,     //BLEND_INVSRCCOLOR        = 4,
39     GL_SRC_ALPHA,               //BLEND_SRCALPHA           = 5,
40     GL_ONE_MINUS_SRC_ALPHA,     //BLEND_INVSRCALPHA        = 6,
41     GL_DST_ALPHA,               //BLEND_DESTALPHA          = 7,
42     GL_ONE_MINUS_DST_ALPHA,     //BLEND_INVDESTALPHA       = 8,
43     GL_DST_COLOR,               //BLEND_DESTCOLOR          = 9,
44     GL_ONE_MINUS_DST_COLOR,     //BLEND_INVDESTCOLOR       = 10,
45     GL_SRC_ALPHA_SATURATE,      //BLEND_SRCALPHASAT        = 11,
46     GL_SRC_ALPHA_SATURATE,      //BLEND_BOTHSRCALPHA       = 12,    
47     GL_SRC_ALPHA_SATURATE,      //BLEND_BOTHINVSRCALPHA    = 13,
48 };
49
50 //========================================================================
51 COGLColorCombiner::COGLColorCombiner(CRender *pRender) :
52     CColorCombiner(pRender),
53     m_pOGLRender((OGLRender*)pRender),
54     m_bSupportAdd(false), m_bSupportSubtract(false)
55 {
56     m_pDecodedMux = new COGLDecodedMux;
57     m_pDecodedMux->m_maxConstants = 0;
58     m_pDecodedMux->m_maxTextures = 1;
59 }
60
61 COGLColorCombiner::~COGLColorCombiner()
62 {
63     delete m_pDecodedMux;
64     m_pDecodedMux = NULL;
65 }
66
67 bool COGLColorCombiner::Initialize(void)
68 {
69     m_bSupportAdd = false;
70     m_bSupportSubtract = false;
71     m_supportedStages = 1;
72     m_bSupportMultiTexture = false;
73
74 #ifndef HAVE_GLES
75     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
76     if( pcontext->IsExtensionSupported(OSAL_GL_ARB_TEXTURE_ENV_ADD) || pcontext->IsExtensionSupported("GL_EXT_texture_env_add") )
77 #endif
78     {
79         m_bSupportAdd = true;
80     }
81 #ifndef HAVE_GLES
82     if( pcontext->IsExtensionSupported("GL_EXT_blend_subtract") )
83 #endif
84     {
85         m_bSupportSubtract = true;
86     }
87
88     return true;
89 }
90
91 void COGLColorCombiner::DisableCombiner(void)
92 {
93     m_pOGLRender->DisableMultiTexture();
94     glEnable(GL_BLEND);
95     OPENGL_CHECK_ERRORS;
96     glBlendFunc(GL_ONE, GL_ZERO);
97     OPENGL_CHECK_ERRORS;
98     
99     if( m_bTexelsEnable )
100     {
101         COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
102         if( pTexture ) 
103         {
104             m_pOGLRender->EnableTexUnit(0,TRUE);
105             m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
106             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
107             OPENGL_CHECK_ERRORS;
108             m_pOGLRender->SetAllTexelRepeatFlag();
109         }
110 #ifdef DEBUGGER
111         else
112         {
113             DebuggerAppendMsg("Check me, texture is NULL but it is enabled");
114         }
115 #endif
116     }
117     else
118     {
119         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
120         OPENGL_CHECK_ERRORS;
121         m_pOGLRender->EnableTexUnit(0,FALSE);
122     }
123 }
124
125 void COGLColorCombiner::InitCombinerCycleCopy(void)
126 {
127     m_pOGLRender->DisableMultiTexture();
128     m_pOGLRender->EnableTexUnit(0,TRUE);
129     COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
130     if( pTexture )
131     {
132         m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
133         m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile);
134     }
135 #ifdef DEBUGGER
136     else
137     {
138         DebuggerAppendMsg("Check me, texture is NULL");
139     }
140 #endif
141
142     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
143     OPENGL_CHECK_ERRORS;
144 }
145
146 void COGLColorCombiner::InitCombinerCycleFill(void)
147 {
148     m_pOGLRender->DisableMultiTexture();
149     m_pOGLRender->EnableTexUnit(0,FALSE);
150 }
151
152
153 void COGLColorCombiner::InitCombinerCycle12(void)
154 {
155     m_pOGLRender->DisableMultiTexture();
156     if( !m_bTexelsEnable )
157     {
158         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
159         OPENGL_CHECK_ERRORS;
160         m_pOGLRender->EnableTexUnit(0,FALSE);
161         return;
162     }
163
164 #if SDL_VIDEO_OPENGL
165     uint32 mask = 0x1f;
166     COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
167     if( pTexture )
168     {
169         m_pOGLRender->EnableTexUnit(0,TRUE);
170         m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
171         m_pOGLRender->SetAllTexelRepeatFlag();
172     }
173 #ifdef DEBUGGER
174     else
175     {
176         DebuggerAppendMsg("Check me, texture is NULL");
177     }
178 #endif
179
180     bool texIsUsed = m_pDecodedMux->isUsed(MUX_TEXEL0);
181     bool shadeIsUsedInColor = m_pDecodedMux->isUsedInCycle(MUX_SHADE, 0, COLOR_CHANNEL);
182     bool texIsUsedInColor = m_pDecodedMux->isUsedInCycle(MUX_TEXEL0, 0, COLOR_CHANNEL);
183
184     if( texIsUsed )
185     {
186         // Parse the simplified the mux, because the OGL 1.1 combiner function is so much
187         // limited, we only parse the 1st N64 combiner setting and only the RGB part
188
189         N64CombinerType & comb = m_pDecodedMux->m_n64Combiners[0];
190         switch( m_pDecodedMux->mType )
191         {
192         case CM_FMT_TYPE_NOT_USED:
193         case CM_FMT_TYPE_D:             // = A
194             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
195             OPENGL_CHECK_ERRORS;
196             break;
197         case CM_FMT_TYPE_A_ADD_D:           // = A+D
198             if( shadeIsUsedInColor && texIsUsedInColor )
199             {
200                 if( m_bSupportAdd )
201                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
202                 else
203                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
204             }
205             else if( texIsUsedInColor )
206             {
207                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
208             }
209             else
210                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
211             OPENGL_CHECK_ERRORS;
212             break;
213         case CM_FMT_TYPE_A_SUB_B:           // = A-B
214             if( shadeIsUsedInColor && texIsUsedInColor )
215             {
216                 if( m_bSupportSubtract )
217                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_SUBTRACT_ARB);
218                 else
219                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
220             }
221             else if( texIsUsedInColor )
222             {
223                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
224             }
225             else
226                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
227             OPENGL_CHECK_ERRORS;
228             break;
229         case CM_FMT_TYPE_A_MOD_C:           // = A*C
230         case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D
231             if( shadeIsUsedInColor && texIsUsedInColor )
232             {
233                 if( ((comb.c & mask) == MUX_SHADE && !(comb.c&MUX_COMPLEMENT)) ||
234                     ((comb.a & mask) == MUX_SHADE && !(comb.a&MUX_COMPLEMENT)) )
235                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
236                 else
237                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
238             }
239             else if( texIsUsedInColor )
240             {
241                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
242             }
243             else
244                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
245             OPENGL_CHECK_ERRORS;
246             break;
247         case CM_FMT_TYPE_A_LERP_B_C:    // = A*C+D
248             if( (comb.b&mask) == MUX_SHADE && (comb.c&mask)==MUX_TEXEL0 && ((comb.a&mask)==MUX_PRIM||(comb.a&mask)==MUX_ENV))
249             {
250                 float *fv;
251                 if( (comb.a&mask)==MUX_PRIM )
252                 {
253                     fv = GetPrimitiveColorfv();
254                 }
255                 else
256                 {
257                     fv = GetEnvColorfv();
258                 }
259
260                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,fv);
261                 OPENGL_CHECK_ERRORS;
262                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
263                 OPENGL_CHECK_ERRORS;
264                 break;
265             }
266         default:        // = (A-B)*C+D
267             if( shadeIsUsedInColor )
268             {
269                 if( ((comb.c & mask) == MUX_SHADE && !(comb.c&MUX_COMPLEMENT)) ||
270                     ((comb.a & mask) == MUX_SHADE && !(comb.a&MUX_COMPLEMENT)) )
271                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
272                 else
273                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
274             }
275             else
276             {
277                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
278             }
279             OPENGL_CHECK_ERRORS;
280             break;
281         }
282     }
283     else
284     {
285         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
286         OPENGL_CHECK_ERRORS;
287     }
288 #endif
289 }
290
291 void COGLBlender::NormalAlphaBlender(void)
292 {
293     glEnable(GL_BLEND);
294     OPENGL_CHECK_ERRORS;
295     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
296     OPENGL_CHECK_ERRORS;
297 }
298
299 void COGLBlender::DisableAlphaBlender(void)
300 {
301     glEnable(GL_BLEND);
302     OPENGL_CHECK_ERRORS;
303     glBlendFunc(GL_ONE, GL_ZERO);
304     OPENGL_CHECK_ERRORS;
305 }
306
307
308 void COGLBlender::BlendFunc(uint32 srcFunc, uint32 desFunc)
309 {
310     glBlendFunc(DirectX_OGL_BlendFuncMaps[srcFunc], DirectX_OGL_BlendFuncMaps[desFunc]);
311     OPENGL_CHECK_ERRORS;
312 }
313
314 void COGLBlender::Enable()
315 {
316     glEnable(GL_BLEND);
317     OPENGL_CHECK_ERRORS;
318 }
319
320 void COGLBlender::Disable()
321 {
322     glDisable(GL_BLEND);
323     OPENGL_CHECK_ERRORS;
324 }
325
326 void COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
327 {
328     m_pOGLRender->DisableMultiTexture();
329     if( g_textures[tile].m_pCTexture )
330     {
331         m_pOGLRender->EnableTexUnit(0,TRUE);
332         glBindTexture(GL_TEXTURE_2D, ((COGLTexture*)(g_textures[tile].m_pCTexture))->m_dwTextureName);
333         OPENGL_CHECK_ERRORS;
334     }
335     m_pOGLRender->SetAllTexelRepeatFlag();
336
337     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
338     OPENGL_CHECK_ERRORS;
339     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
340     OPENGL_CHECK_ERRORS;
341     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
342     OPENGL_CHECK_ERRORS;
343     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
344     OPENGL_CHECK_ERRORS;
345
346     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
347     OPENGL_CHECK_ERRORS;
348     m_pOGLRender->SetAlphaTestEnable(FALSE);
349 }
350
351 #ifdef DEBUGGER
352 extern const char *translatedCombTypes[];
353 void COGLColorCombiner::DisplaySimpleMuxString(void)
354 {
355     TRACE0("\nSimplified Mux\n");
356     m_pDecodedMux->DisplaySimpliedMuxString("Used");
357 }
358 #endif
359