d07c171f |
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 | |