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