Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / DeviceBuilder.cpp
CommitLineData
d07c171f 1/*
2Copyright (C) 2003 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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//========================================================================
42CDeviceBuilder* CDeviceBuilder::m_pInstance=NULL;
43SupportedDeviceType CDeviceBuilder::m_deviceType = DIRECTX_DEVICE;
44SupportedDeviceType CDeviceBuilder::m_deviceGeneralType = DIRECTX_DEVICE;
45
46CDeviceBuilder* CDeviceBuilder::GetBuilder(void)
47{
48 if( m_pInstance == NULL )
49 CreateBuilder(m_deviceType);
50
51 return m_pInstance;
52}
53
54void 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
80SupportedDeviceType CDeviceBuilder::GetDeviceType(void)
81{
82 return CDeviceBuilder::m_deviceType;
83}
84
85SupportedDeviceType CDeviceBuilder::GetGeneralDeviceType(void)
86{
87 return CDeviceBuilder::m_deviceGeneralType;
88}
89
90CDeviceBuilder* 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
118void CDeviceBuilder::DeleteBuilder(void)
119{
120 delete m_pInstance;
121 m_pInstance = NULL;
122}
123
124CDeviceBuilder::CDeviceBuilder() :
125 m_pRender(NULL),
126 m_pGraphicsContext(NULL),
127 m_pColorCombiner(NULL),
128 m_pAlphaBlender(NULL)
129{
130}
131
132CDeviceBuilder::~CDeviceBuilder()
133{
134 DeleteGraphicsContext();
135 DeleteRender();
136 DeleteColorCombiner();
137 DeleteAlphaBlender();
138}
139
140void 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
151void 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
161void CDeviceBuilder::DeleteColorCombiner(void)
162{
163 if( m_pColorCombiner != NULL )
164 {
165 delete m_pColorCombiner;
166 m_pColorCombiner = NULL;
167 }
168}
169
170void CDeviceBuilder::DeleteAlphaBlender(void)
171{
172 if( m_pAlphaBlender != NULL )
173 {
174 delete m_pAlphaBlender;
175 m_pAlphaBlender = NULL;
176 }
177}
178
179
180//========================================================================
181
182CGraphicsContext * 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
195CRender * 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
225CTexture * 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
238CColorCombiner * 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
373CBlender * 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