Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / DeviceBuilder.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
20 #include "osal_opengl.h"
21
22 #include "DeviceBuilder.h"
23 #include "FrameBuffer.h"
24 #include "OGLCombiner.h"
25 #include "OGLDebug.h"
26 #include "OGLExtRender.h"
27 #include "OGLGraphicsContext.h"
28 #include "OGLTexture.h"
29 #if SDL_VIDEO_OPENGL
30 #include "OGLCombinerNV.h"
31 #include "OGLCombinerTNT2.h"
32 #include "OGLExtensions.h"
33 #include "OGLFragmentShaders.h"
34 #elif SDL_VIDEO_OPENGL_ES2
35 #include "OGLES2FragmentShaders.h"
36 #endif
37
38 //========================================================================
39 CDeviceBuilder* CDeviceBuilder::m_pInstance=NULL;
40 SupportedDeviceType CDeviceBuilder::m_deviceType = DIRECTX_DEVICE;
41 SupportedDeviceType CDeviceBuilder::m_deviceGeneralType = DIRECTX_DEVICE;
42
43 CDeviceBuilder* CDeviceBuilder::GetBuilder(void)
44 {
45     if( m_pInstance == NULL )
46         CreateBuilder(m_deviceType);
47     
48     return m_pInstance;
49 }
50
51 void CDeviceBuilder::SelectDeviceType(SupportedDeviceType type)
52 {
53     if( type != m_deviceType && m_pInstance != NULL )
54     {
55         DeleteBuilder();
56     }
57
58     CDeviceBuilder::m_deviceType = type;
59     switch(type)
60     {
61     case OGL_DEVICE:
62     case OGL_1_1_DEVICE:
63     case OGL_1_2_DEVICE:
64     case OGL_1_3_DEVICE:
65     case OGL_1_4_DEVICE:
66     case OGL_1_4_V2_DEVICE:
67     case OGL_TNT2_DEVICE:
68     case NVIDIA_OGL_DEVICE:
69     case OGL_FRAGMENT_PROGRAM:
70         CDeviceBuilder::m_deviceGeneralType = OGL_DEVICE;
71         break;
72      default:
73        break;
74     }
75 }
76
77 SupportedDeviceType CDeviceBuilder::GetDeviceType(void)
78 {
79     return CDeviceBuilder::m_deviceType;
80 }
81
82 SupportedDeviceType CDeviceBuilder::GetGeneralDeviceType(void)
83 {
84     return CDeviceBuilder::m_deviceGeneralType;
85 }
86
87 CDeviceBuilder* CDeviceBuilder::CreateBuilder(SupportedDeviceType type)
88 {
89     if( m_pInstance == NULL )
90     {
91         switch( type )
92         {
93         case    OGL_DEVICE:
94         case    OGL_1_1_DEVICE:
95         case    OGL_1_2_DEVICE:
96         case    OGL_1_3_DEVICE:
97         case    OGL_1_4_DEVICE:
98         case    OGL_1_4_V2_DEVICE:
99         case    OGL_TNT2_DEVICE:
100         case    NVIDIA_OGL_DEVICE:
101         case OGL_FRAGMENT_PROGRAM:
102             m_pInstance = new OGLDeviceBuilder();
103             break;
104         default:
105             DebugMessage(M64MSG_ERROR, "CreateBuilder: unknown OGL device type");
106             exit(1);
107         }
108
109         SAFE_CHECK(m_pInstance);
110     }
111
112     return m_pInstance;
113 }
114
115 void CDeviceBuilder::DeleteBuilder(void)
116 {
117     delete m_pInstance;
118     m_pInstance = NULL;
119 }
120
121 CDeviceBuilder::CDeviceBuilder() :
122     m_pRender(NULL),
123     m_pGraphicsContext(NULL),
124     m_pColorCombiner(NULL),
125     m_pAlphaBlender(NULL)
126 {
127 }
128
129 CDeviceBuilder::~CDeviceBuilder()
130 {
131     DeleteGraphicsContext();
132     DeleteRender();
133     DeleteColorCombiner();
134     DeleteAlphaBlender();
135 }
136
137 void CDeviceBuilder::DeleteGraphicsContext(void)
138 {
139     if( m_pGraphicsContext != NULL )
140     {
141         delete m_pGraphicsContext;
142         CGraphicsContext::g_pGraphicsContext = m_pGraphicsContext = NULL;
143     }
144
145     SAFE_DELETE(g_pFrameBufferManager);
146 }
147
148 void CDeviceBuilder::DeleteRender(void)
149 {
150     if( m_pRender != NULL )
151     {
152         delete m_pRender;
153         CRender::g_pRender = m_pRender = NULL;
154         CRender::gRenderReferenceCount = 0;
155     }
156 }
157
158 void CDeviceBuilder::DeleteColorCombiner(void)
159 {
160     if( m_pColorCombiner != NULL )
161     {
162         delete m_pColorCombiner;
163         m_pColorCombiner = NULL;
164     }
165 }
166
167 void CDeviceBuilder::DeleteAlphaBlender(void)
168 {
169     if( m_pAlphaBlender != NULL )
170     {
171         delete m_pAlphaBlender;
172         m_pAlphaBlender = NULL;
173     }
174 }
175
176
177 //========================================================================
178
179 CGraphicsContext * OGLDeviceBuilder::CreateGraphicsContext(void)
180 {
181     if( m_pGraphicsContext == NULL )
182     {
183         m_pGraphicsContext = new COGLGraphicsContext();
184         SAFE_CHECK(m_pGraphicsContext);
185         CGraphicsContext::g_pGraphicsContext = m_pGraphicsContext;
186     }
187
188     g_pFrameBufferManager = new FrameBufferManager;
189     return m_pGraphicsContext;
190 }
191
192 CRender * OGLDeviceBuilder::CreateRender(void)
193 {
194     if( m_pRender == NULL )
195     {
196         if( CGraphicsContext::g_pGraphicsContext == NULL && CGraphicsContext::g_pGraphicsContext->Ready() )
197         {
198             DebugMessage(M64MSG_ERROR, "Can not create ColorCombiner before creating and initializing GraphicsContext");
199             m_pRender = NULL;
200             SAFE_CHECK(m_pRender);
201         }
202
203         COGLGraphicsContext &context = *((COGLGraphicsContext*)CGraphicsContext::g_pGraphicsContext);
204
205         if( context.m_bSupportMultiTexture )
206         {
207             // OGL extension render
208             m_pRender = new COGLExtRender();
209         }
210         else
211         {
212             // Basic OGL Render
213             m_pRender = new OGLRender();
214         }
215         SAFE_CHECK(m_pRender);
216         CRender::g_pRender = m_pRender;
217     }
218
219     return m_pRender;
220 }
221
222 CTexture * OGLDeviceBuilder::CreateTexture(uint32 dwWidth, uint32 dwHeight, TextureUsage usage)
223 {
224     COGLTexture *txtr = new COGLTexture(dwWidth, dwHeight, usage);
225     if( txtr->m_pTexture == NULL )
226     {
227         delete txtr;
228         TRACE0("Cannot create new texture, out of video memory");
229         return NULL;
230     }
231     else
232         return txtr;
233 }
234
235 CColorCombiner * OGLDeviceBuilder::CreateColorCombiner(CRender *pRender)
236 {
237     if( m_pColorCombiner == NULL )
238     {
239         if( CGraphicsContext::g_pGraphicsContext == NULL && CGraphicsContext::g_pGraphicsContext->Ready() )
240         {
241             DebugMessage(M64MSG_ERROR, "Can not create ColorCombiner before creating and initializing GraphicsContext");
242         }
243         else
244         {
245             m_deviceType = (SupportedDeviceType)options.OpenglRenderSetting;
246
247 #if SDL_VIDEO_OPENGL
248
249             if (m_deviceType == NVIDIA_OGL_DEVICE && !bNvidiaExtensionsSupported)
250             {
251                 DebugMessage(M64MSG_WARNING, "Your video card does not support Nvidia OpenGL extensions.  Falling back to auto device.");
252                 m_deviceType = OGL_DEVICE;
253             }
254             if( m_deviceType == OGL_DEVICE )    // Best fit
255             {
256                 GLint maxUnit = 2;
257                 COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
258                 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&maxUnit);
259                 OPENGL_CHECK_ERRORS;
260
261                 if( pcontext->IsExtensionSupported("GL_ARB_fragment_program") )
262                 {
263                     m_pColorCombiner = new COGL_FragmentProgramCombiner(pRender);
264                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Fragment Program");
265                 }
266                 else if( pcontext->IsExtensionSupported("GL_NV_texture_env_combine4") || 
267                     pcontext->IsExtensionSupported("GL_NV_register_combiners") )
268                 {
269                     m_pColorCombiner = new COGLColorCombinerNvidia(pRender);
270                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: NVidia");
271                 }
272                 else if( pcontext->IsExtensionSupported("GL_NV_texture_env_combine4") )
273                 {
274                     m_pColorCombiner = new COGLColorCombinerTNT2(pRender);
275                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: TNT2");
276                 }
277                 else if( pcontext->IsExtensionSupported("GL_EXT_texture_env_combine") ||
278                          pcontext->IsExtensionSupported("GL_ARB_texture_env_combine") )
279                 {
280                     if( pcontext->IsExtensionSupported("GL_ARB_texture_env_crossbar") )
281                     {
282                         if( maxUnit > 2 )
283                         {
284                             m_pColorCombiner = new COGLColorCombiner4v2(pRender);
285                             DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4 version 2");
286                         }
287                         else
288                         {
289                             m_pColorCombiner = new COGLColorCombiner4(pRender);
290                             DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4");
291                         }
292                     }
293                     else
294                     {
295                         if( maxUnit > 2 )
296                         {
297                             m_pColorCombiner = new COGLColorCombiner4v2(pRender);
298                             DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4 version 2 (w/o env crossbar)");
299                         }
300                         else
301                         {
302                             m_pColorCombiner = new COGLColorCombiner2(pRender);
303                             DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.2/1.3");
304                         }
305                     }
306                 }
307                 else
308                 {
309                     m_pColorCombiner = new COGLColorCombiner(pRender);
310                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Basic OGL");
311                 }
312             }
313             else
314             {
315                 switch(m_deviceType)
316                 {
317                 case OGL_1_1_DEVICE:
318                     m_pColorCombiner = new COGLColorCombiner(pRender);
319                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Basic OGL");
320                     break;
321                 case OGL_1_2_DEVICE:
322                 case OGL_1_3_DEVICE:
323                     m_pColorCombiner = new COGLColorCombiner2(pRender);
324                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.2/1.3");
325                     break;
326                 case OGL_1_4_DEVICE:
327                     m_pColorCombiner = new COGLColorCombiner4(pRender);
328                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4");
329                     break;
330                 case OGL_1_4_V2_DEVICE:
331                     m_pColorCombiner = new COGLColorCombiner4v2(pRender);
332                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: OGL 1.4 Version 2");
333                     break;
334                 case OGL_TNT2_DEVICE:
335                     m_pColorCombiner = new COGLColorCombinerTNT2(pRender);
336                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: TNT2");
337                     break;
338                 case NVIDIA_OGL_DEVICE:
339                     m_pColorCombiner = new COGLColorCombinerNvidia(pRender);
340                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Nvidia");
341                     break;
342                 case OGL_FRAGMENT_PROGRAM:
343                     m_pColorCombiner = new COGL_FragmentProgramCombiner(pRender);
344                     DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Fragment Program");
345                     break;
346                  default:
347                     break;
348                 }
349             }
350
351 #elif SDL_VIDEO_OPENGL_ES2
352             m_pColorCombiner = new COGL_FragmentProgramCombiner(pRender);
353             DebugMessage(M64MSG_VERBOSE, "OpenGL Combiner: Fragment Program");
354 #endif
355         }
356
357         SAFE_CHECK(m_pColorCombiner);
358     }
359
360     return m_pColorCombiner;
361 }
362
363 CBlender * OGLDeviceBuilder::CreateAlphaBlender(CRender *pRender)
364 {
365     if( m_pAlphaBlender == NULL )
366     {
367         m_pAlphaBlender = new COGLBlender(pRender);
368         SAFE_CHECK(m_pAlphaBlender);
369     }
370
371     return m_pAlphaBlender;
372 }
373