Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / Combiner / SimpleTexEnvCombiner.cpp
1 /******************************************************************************
2  * Arachnoid Graphics Plugin for Mupen64Plus
3  * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4  *
5  * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *****************************************************************************/
21
22 #include "SimpleTexEnvCombiner.h"
23 #include "CombinerStructs.h"
24 #include "MultiTexturingExt.h"
25 #include "ExtensionChecker.h"
26 #include "m64p.h"
27 #include "OpenGL.h"
28
29 //-----------------------------------------------------------------------------
30 //! Constructor
31 //-----------------------------------------------------------------------------
32 SimpleTexEnvCombiner::SimpleTexEnvCombiner()
33 {
34 }
35
36 //-----------------------------------------------------------------------------
37 //! Destructor
38 //-----------------------------------------------------------------------------
39 SimpleTexEnvCombiner::~SimpleTexEnvCombiner()
40 {
41 }
42
43 //-----------------------------------------------------------------------------
44 //* Initialize
45 //! Checks if multitexturing is supported 
46 //-----------------------------------------------------------------------------
47 void SimpleTexEnvCombiner::initialize()
48 {
49     ARB_multitexture = isExtensionSupported("GL_ARB_multitexture");
50 }
51
52 //-----------------------------------------------------------------------------
53 //* Begin Texture Update
54 //! Called before texture channels are updated on the RDP
55 //-----------------------------------------------------------------------------
56 void SimpleTexEnvCombiner::beginTextureUpdate()
57 {
58     //Ignore?
59 }
60
61 //-----------------------------------------------------------------------------
62 //* End Texture Update
63 //! Called after texture channels are updated on the RDP
64 //! @param[in] texEnv Texture Environment
65 //-----------------------------------------------------------------------------
66 void SimpleTexEnvCombiner::endTextureUpdate(TexEnvCombiner* texEnv)
67 {  
68     //Ignore
69 }
70
71 //-----------------------------------------------------------------------------
72 //! Set Texture Envirorment Colors
73 //! @param[in] texEnv Texture Environment
74 //-----------------------------------------------------------------------------
75 void SimpleTexEnvCombiner::setTextureEnviromentColors(TexEnvCombiner* texEnv)
76 {
77     //Ignore
78 }
79
80 //-----------------------------------------------------------------------------
81 //* Set Texture Environment
82 //! Enables texturing and sets texture environment in OpenGL
83 //! @param[in] texEnv Texture Environment
84 //-----------------------------------------------------------------------------
85 void SimpleTexEnvCombiner::setTextureEnviroment(TexEnvCombiner* texEnv)
86 {
87     if ( ARB_multitexture )
88         glActiveTextureARB( GL_TEXTURE0_ARB );
89
90     if (texEnv->usesT0 || texEnv->usesT1)
91         glEnable( GL_TEXTURE_2D );
92     else
93         glDisable( GL_TEXTURE_2D );
94
95     //Set Mode
96     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texEnv->mode);
97 }
98
99 //-----------------------------------------------------------------------------
100 //* Create New Texture Enviornment
101 //! Allocates a new texture enviroment
102 //! @param[in] colorCombiner How to combine and get a color
103 //! @param[in] alphaCombiner How to combine and get an alpha value
104 //! @return The texture enviroment that was created
105 //-----------------------------------------------------------------------------
106 TexEnvCombiner* SimpleTexEnvCombiner::createNewTextureEnviroment(Combiner* colorCombiner, Combiner *alphaCombiner)
107 {
108     TexEnvCombiner* texEnv = new TexEnvCombiner();
109
110     bool m_usesTexture0 = false;
111     bool m_usesTexture1 = false;
112     int mode = GL_REPLACE;
113     unsigned short m_color = COMBINED;
114     unsigned short m_alpha = COMBINED;    
115
116     //For each stage in alpha combiner
117     for (int i = 0; i < alphaCombiner->numStages; i++)
118     {
119         //For each operation in stage
120         for (int j = 0; j < alphaCombiner->stage[i].numOps; j++)
121         {
122             CombinerOp* op = &alphaCombiner->stage[i].op[j];
123
124             //Apply operation
125             switch ( alphaCombiner->stage[i].op[j].op )
126             {
127                 case LOAD:
128                     if ( op->param1 != TEXEL0_ALPHA &&  op->param1 != TEXEL1_ALPHA  )
129                     {
130                         m_alpha = op->param1;
131                         m_usesTexture0 = false;
132                         m_usesTexture1 = false;
133                     }
134                     else
135                     {
136                         mode = GL_REPLACE;
137                         m_usesTexture0 = op->param1 == TEXEL0_ALPHA;
138                         m_usesTexture1 = op->param1 == TEXEL1_ALPHA;
139                     }
140                     break;
141                 case MUL: {
142                         CombinerOp* prevOp = &alphaCombiner->stage[i].op[j-1];
143
144                         if (((op->param1 == TEXEL0_ALPHA) || (op->param1 == TEXEL1_ALPHA)) &&
145                             ((prevOp->param1 != TEXEL0_ALPHA) || (prevOp->param1 != TEXEL1_ALPHA)))
146                         {
147                             mode = GL_MODULATE;
148                         }
149                         else if ( ( op->param1 != TEXEL0_ALPHA || op->param1 != TEXEL1_ALPHA) &&
150                                 (prevOp->param1 == TEXEL0_ALPHA || prevOp->param1 == TEXEL1_ALPHA) )
151                         {
152                             m_alpha = op->param1;
153                             mode = GL_MODULATE;
154                         }
155                     }
156                     break;
157             }
158         }
159     }
160
161
162     //For each stage in colorCombiner
163     for (int i = 0; i < colorCombiner->numStages; i++)
164     {
165         for (int j = 0; j < colorCombiner->stage[i].numOps; j++)
166         {
167             CombinerOp* op = &colorCombiner->stage[i].op[j];
168
169             switch ( colorCombiner->stage[i].op[j].op )
170             {
171                 case LOAD:
172                     if (op->param1 == TEXEL0 || op->param1 == TEXEL0_ALPHA)
173                     {
174                         if ( mode == GL_MODULATE )
175                             m_color = ONE;
176
177                         m_usesTexture0 = true;
178                         m_usesTexture1 = false;
179                     }
180                     else if ( op->param1 == TEXEL1 || op->param1 == TEXEL1_ALPHA )
181                     {
182                         if ( mode == GL_MODULATE )
183                             m_color = ONE;
184
185                         m_usesTexture0 = false;
186                         m_usesTexture1 = true;
187                     }
188                     else
189                     {
190                         m_color = op->param1;
191                         m_usesTexture0 = m_usesTexture1 = false;
192                     }
193                     break;
194                 case MUL:
195                     if ( op->param1 == TEXEL0 || op->param1 == TEXEL0_ALPHA )
196                     {
197                         if (!m_usesTexture0 && !m_usesTexture1)
198                         {
199                             mode = GL_MODULATE;
200                             m_usesTexture0 = true;
201                             m_usesTexture1 = false;
202                         }
203                     }
204                     else if ( op->param1 == TEXEL1 || op->param1 == TEXEL1_ALPHA )
205                     {
206                         if (!m_usesTexture0 && !m_usesTexture1)
207                         {
208                             mode = GL_MODULATE;
209                             m_usesTexture0 = false;
210                             m_usesTexture1 = true;
211                         }
212                     }
213                     else if ( m_usesTexture0 || m_usesTexture1 )
214                     {
215                         mode = GL_MODULATE;
216                         m_color = op->param1;
217                     }
218                     break;
219                 case INTERPOLATE:
220                     if ((op->param1 == TEXEL0) &&
221                         ((op->param2 != TEXEL0) && (op->param2 != TEXEL0_ALPHA) &&
222                          (op->param2 != TEXEL1) && (op->param2 != TEXEL1_ALPHA)) &&
223                          (op->param3 == TEXEL0_ALPHA))
224                     {
225                         mode = GL_DECAL;
226                         m_color = op->param2;
227                         m_usesTexture0 = true;
228                         m_usesTexture1 = false;
229                     }
230                     else if ((op->param1 == TEXEL0) &&
231                         ((op->param2 != TEXEL0) && (op->param2 != TEXEL0_ALPHA) &&
232                          (op->param2 != TEXEL1) && (op->param2 != TEXEL1_ALPHA)) &&
233                          (op->param3 == TEXEL0_ALPHA))
234                     {
235                         mode = GL_DECAL;
236                         m_color = op->param2;
237                         m_usesTexture0 = false;
238                         m_usesTexture1 = true;
239                     }
240                     break;
241             }
242         }
243     }
244
245     texEnv->usesT0         = m_usesTexture0;
246     texEnv->usesT1         = m_usesTexture1;
247     texEnv->mode           = mode;
248     texEnv->vertex.color   = m_color;
249     texEnv->vertex.alpha   = m_alpha;     
250     return texEnv;
251 }