Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / GraphicsPlugin.cpp
1 /******************************************************************************
2  * Arachnoid Graphics Plugin for Mupen64Plus
3  * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4  *
5  * Copyright (C) 2009 Jon Ring
6  * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *****************************************************************************/
22
23 #include "GraphicsPlugin.h"
24 #include "VI.h"                  //Video interface
25 #include "Memory.h"              //Access to memory (RDRAM, Texture Memory)
26 #include "OpenGLRenderer.h"      //Renderer
27 #include "FrameBuffer.h"         //Framebuffer
28 #include "DisplayListParser.h"   //Displaylist parser
29 #include "FogManager.h"          //Fog 
30 #include "RSP.h"                 //Reality Signal Processor
31 #include "RDP.h"                 //Reality Drawing Processor
32 #include "GBI.h"                 //Graphics Binary Interface 
33 #include "ConfigMap.h"           //Configuration
34 #include "Logger.h"              //Debug logger
35 #include "RomDetector.h"
36 #include <ctime>
37 #ifdef HAVE_GLES
38 #include "eglport.h"
39 #include <SDL.h>
40 #include <SDL_opengles.h>
41 #endif
42
43 //FrameBuffer framebuffer01;
44 //FrameBuffer framebuffer02;
45
46 //-----------------------------------------------------------------------------
47 //! Constructor
48 //-----------------------------------------------------------------------------
49 GraphicsPlugin::GraphicsPlugin() 
50 : m_openGLMgr( OpenGLManager::getSingleton() )
51 {
52     m_vi = 0;
53     m_initialized = false;
54     m_updateConfig = false;
55     m_fogManager = 0;
56 }
57
58 //-----------------------------------------------------------------------------
59 //! Destructor
60 //-----------------------------------------------------------------------------
61 GraphicsPlugin::~GraphicsPlugin()
62 {
63     dispose();
64 }
65
66 //-----------------------------------------------------------------------------
67 // Initialize
68 //-----------------------------------------------------------------------------
69 bool GraphicsPlugin::initialize(GFX_INFO* graphicsInfo)
70 {
71     //Initialize video output
72     if (CoreVideo_Init() != M64ERR_SUCCESS)
73     {
74         Logger::getSingleton().printMsg("Could not initialize video.", M64MSG_ERROR);
75         return false;
76     }
77
78     //Save pointer to graphics info
79     m_graphicsInfo = graphicsInfo;
80
81     m_numDListProcessed = 0;
82
83     //Detect what rom it is
84     m_romDetector = &ROMDetector::getSingleton();        
85     m_romDetector->initialize( m_graphicsInfo->HEADER );
86 #ifdef HAVE_GLES
87         SDL_SetVideoMode(m_config->fullscreenWidth, m_config->fullscreenHeight, m_config->fullscreenBitDepth, SDL_FULLSCREEN);
88     SDL_ShowCursor(SDL_DISABLE);
89         EGL_Open(m_config->fullscreenWidth, m_config->fullscreenHeight);
90 #else
91     if (m_config->multiSampling > 0)
92     {
93         CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLEBUFFERS, 1);
94         if (m_config->multiSampling <= 2)
95             CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 2);
96         else if (m_config->multiSampling <= 4)
97             CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 4);
98         else if (m_config->multiSampling <= 8)
99             CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 8);
100         else
101             CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 16);
102     }
103
104     if (CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1) != M64ERR_SUCCESS ||
105         CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 32) != M64ERR_SUCCESS ||
106         CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 24)  != M64ERR_SUCCESS)
107     {
108         Logger::getSingleton().printMsg("Could not set video attributes.", M64MSG_ERROR);
109         return false;
110     }
111
112     if (CoreVideo_SetVideoMode(m_config->fullscreenWidth, m_config->fullscreenHeight, m_config->fullscreenBitDepth, 
113         m_config->startFullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)
114     {
115         Logger::getSingleton().printMsg("Could not set video mode.", M64MSG_ERROR);
116         return false;
117     }
118
119     CoreVideo_SetCaption("Arachnoid");
120 #endif
121     //Initialize Video Interface
122     m_vi = new VI();
123     m_vi->calcSize(m_graphicsInfo);
124
125     //Initialize Memory
126     m_memory = new Memory();
127     if ( !m_memory->initialize(m_graphicsInfo->RDRAM, m_graphicsInfo->DMEM) ) 
128     {
129         return false;
130     }
131     
132     m_displayListParser = new DisplayListParser();
133     m_displayListParser->initialize(&m_rsp, &m_rdp, &m_gbi, m_memory);
134
135     //Init OpenGL
136     if ( !m_openGLMgr.initialize(m_config->startFullscreen, m_config->fullscreenWidth, m_config->fullscreenHeight, m_config->fullscreenBitDepth, m_config->fullscreenRefreshRate, true, false) ) 
137     {
138         Logger::getSingleton().printMsg("Unable to initialize OpenGL", M64MSG_ERROR);
139         return false;
140     }
141
142     
143     m_openGLMgr.calcViewScale(m_vi->getWidth(), m_vi->getHeight());
144
145     //Initialize Fog Manager
146     m_fogManager = new FogManager();
147     m_fogManager->initialize();
148
149
150
151     //Initialize Texture Cache
152     //! @todo Not "hardcode" TextureBitDepth.
153     m_textureCache.initialize(&m_rsp, &m_rdp, m_memory, 16);
154     m_textureCache.setMipmap( m_config->mipmapping );
155
156     //Initialize OpenGL Renderer
157     if ( !OpenGLRenderer::getSingleton().initialize(&m_rsp, &m_rdp, &m_textureCache, m_vi, m_fogManager) ) 
158     {
159         Logger::getSingleton().printMsg("Unable to initialize OpenGL Renderer", M64MSG_ERROR);
160         return false;
161     }
162
163     //Initialize Processors
164     m_rdp.initialize(m_graphicsInfo, &m_rsp, m_memory, &m_gbi, &m_textureCache, m_vi, m_displayListParser, m_fogManager);
165     m_rsp.initialize(m_graphicsInfo, &m_rdp, m_memory, m_vi, m_displayListParser, m_fogManager);
166     m_gbi.initialize(&m_rsp, &m_rdp, m_memory, m_displayListParser);    
167         
168
169     //Set Background color
170     m_openGLMgr.setClearColor(0.0f, 0.0f, 0.0f);
171     m_openGLMgr.setLighting(false);
172     glDisable(GL_LIGHTING);
173     m_openGLMgr.setCullMode(false, true);
174     m_openGLMgr.setWireFrame(m_config->wireframe);   
175
176     //Initialize framebuffer
177     //framebuffer01.initialize(width, height);
178    // framebuffer02.initialize(width, height);
179
180     m_initialized = true;
181     return true;
182 }
183
184 //-----------------------------------------------------------------------------
185 // Dispose
186 //-----------------------------------------------------------------------------
187 void GraphicsPlugin::dispose()
188 {    
189     //Dispose of Textures
190     m_textureCache.dispose();
191
192     //Dispose of member objects
193     if ( m_vi )                { delete m_vi;                m_vi = 0;                }
194     if ( m_memory )            { delete m_memory;            m_memory = 0;            }
195     if ( m_displayListParser ) { delete m_displayListParser; m_displayListParser = 0; }
196     if ( m_fogManager )        { delete m_fogManager;        m_fogManager = 0;        }
197     
198     m_gbi.dispose();
199     m_rdp.dispose();
200     m_rsp.dispose();
201     
202     //Dispose of OpenGL
203     //framebuffer01.dispose();
204    // framebuffer02.dispose();
205     m_openGLMgr.dispose();
206
207     if (m_initialized)
208 #ifdef HAVE_GLES
209         {
210                 EGL_Close();
211                 SDL_Quit();             // *SEB* *TODO* Close Subsystem only?
212         }
213 #else
214         CoreVideo_Quit();
215 #endif
216
217     m_initialized = false;
218 }
219
220 void renderMotionBlur()
221 {
222     ///glPushMatrix();
223
224         glDisable(GL_DEPTH_TEST);            
225         glBlendFunc(GL_SRC_ALPHA,GL_ONE);    
226         glEnable(GL_BLEND);
227         glColor4f(1, 1, 1, 0.9f);  //Alpha blending
228         
229 //        framebuffer01.render2();
230
231         glColor4f(1, 1, 1, 1.0f);  //Alpha blending
232         glEnable(GL_DEPTH_TEST);                        
233         glDisable(GL_BLEND);
234
235     //glPopMatrix();
236 }
237
238 bool animate(int frameRate)
239 {
240     static clock_t lastTime;
241     clock_t currentTime = clock() * 1000 / CLOCKS_PER_SEC;
242     clock_t elapsedTime = currentTime - lastTime;
243     if (elapsedTime > ((clock_t)1000 / frameRate))
244     {
245         lastTime = currentTime;
246         return true;
247     }
248     return false;
249     
250 #if 0
251     //Todo: test against new version
252     static float lastTime = 0.0f;
253     float elapsedTime = 0.0;
254     float currentTime = GetTickCount() * 0.001f; 
255     elapsedTime = currentTime - lastTime;
256
257     if( elapsedTime > (1.0f / frameRate) )
258     {
259         lastTime = currentTime;    
260         return true;
261     }
262
263     return false;
264 #endif
265
266 }
267
268 void renderQuad()
269 {
270     static float dt = 0;
271     dt += 0.2f;
272     
273     //glDisable(GL_CULL_FACE);
274     glMatrixMode(GL_MODELVIEW);
275     glPushMatrix();
276    // glRotatef(dt, 0, 1, 0);
277     {
278 #ifdef HAVE_GLES
279 //*SEB* *TODO*
280 #else
281         glBegin(GL_QUADS);
282         {
283             glColor3f(1,0,0);   glVertex3f(-1,-1,0);
284             glColor3f(1,1,0);   glVertex3f( 1,-1,0);
285             glColor3f(0,1,1);   glVertex3f( 1, 1,0);
286             glColor3f(0,0,1);   glVertex3f(-1, 1,0);
287         }
288         glEnd();
289 #endif
290     }
291     glPopMatrix();
292 }
293
294 void renderRedBox(float x, float y, float z, float width, float height,  float length)
295 {
296     static float dt = 0;
297     dt += 10.6f;
298     glRotatef(dt, 1,1,1);
299     x = x - width  / 2;
300     y = y - height / 2;
301     z = z - length / 2;
302 #ifdef HAVE_GLES
303 //*SEB* *TODO*
304 #else
305     glBegin(GL_QUADS);                
306         glColor3f(1,0,0);        
307         glVertex3f(x,         y,          z);
308         glVertex3f(x,         y + height, z);
309         glVertex3f(x + width, y + height, z); 
310         glVertex3f(x + width, y,          z);
311         glVertex3f(x,         y,          z + length);
312         glVertex3f(x,         y + height, z + length);
313         glVertex3f(x + width, y + height, z + length); 
314         glVertex3f(x + width, y,          z + length);        
315         glVertex3f(x,         y,          z);
316         glVertex3f(x,            y,       z + length);
317         glVertex3f(x + width, y,          z + length); 
318         glVertex3f(x + width, y,          z);
319         glVertex3f(x,         y + height, z);
320         glVertex3f(x,         y + height, z + length);
321         glVertex3f(x + width, y + height, z + length); 
322         glVertex3f(x + width, y + height, z);    
323         glVertex3f(x,         y,          z);
324         glVertex3f(x,         y,          z + length);
325         glVertex3f(x,         y + height, z + length); 
326         glVertex3f(x,         y + height, z);
327         glVertex3f(x + width, y,          z);
328         glVertex3f(x + width, y,          z + length);
329         glVertex3f(x + width, y + height, z + length); 
330         glVertex3f(x + width, y + height, z);
331         glColor3f(1,1,1);
332     glEnd();
333 #endif
334 }
335
336 //-----------------------------------------------------------------------------
337 // ProcessDisplayList
338 //-----------------------------------------------------------------------------
339 void GraphicsPlugin::processDisplayList()
340 {
341     if ( (m_numDListProcessed == 1 && m_romDetector->getClearType() == CT_AFTER_ONE_DISPLAY_LIST) ||
342          (m_numDListProcessed == 2 && m_romDetector->getClearType() == CT_AFTER_TWO_DISPLAY_LIST) ||
343          (m_numDListProcessed == 3 && m_romDetector->getClearType() == CT_AFTER_THREE_DISPLAY_LIST) )
344     {
345         bool scissors = OpenGLManager::getSingleton().getScissorEnabled();
346         OpenGLManager::getSingleton().setScissorEnabled(false);
347         glClear(GL_COLOR_BUFFER_BIT);
348         m_numDListProcessed = 0;
349         OpenGLManager::getSingleton().setScissorEnabled(scissors);
350     }
351
352     //Update Config?
353     if ( m_updateConfig )
354     {        
355         m_vi->calcSize(m_graphicsInfo);    
356         m_openGLMgr.calcViewScale(m_vi->getWidth(), m_vi->getHeight());
357         OpenGLManager::getSingleton().setViewport(0, 0, m_config->windowWidth, m_config->windowHeight);
358         m_openGLMgr.setWireFrame( m_config->wireframe );
359         _setTextureCacheSize( m_config->textureCacheSize );
360         m_updateConfig = false;
361
362         //if ( OpenGLManager::getSingleton().getFullscreen() )
363         //{
364         //    //Initialize framebuffer
365         //    FrameBuffer::getSingleton().dispose();
366            // FrameBuffer::getSingleton().initialize(m_config->fullscreenWidth,  m_config->fullscreenHeight);
367         //}
368         //else
369         //{
370         //    //Initialize framebuffer
371         //    FrameBuffer::getSingleton().dispose();
372            // FrameBuffer::getSingleton().initialize(m_config->windowWidth,  m_config->windowHeight);
373         //}
374
375
376     }       
377
378     //Get Video Interface Size
379     m_vi->calcSize(m_graphicsInfo);    
380     m_openGLMgr.calcViewScale(m_vi->getWidth(), m_vi->getHeight());
381     OpenGLManager::getSingleton().setForceDisableCulling( ROMDetector::getSingleton().getDisableFaceCulling() );
382
383     //Render Scene
384     OpenGLManager::getSingleton().beginRendering();        
385     OpenGLManager::getSingleton().setTextureing2D(true);        
386     glEnable(GL_DEPTH_TEST);                        
387     {    
388         //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
389         m_rsp.reset();
390         m_rdp.reset();
391         m_openGLMgr.setCullMode(false, true);
392         m_displayListParser->processDisplayList();
393     }
394
395         //Clear Screen?
396     m_numDListProcessed++;
397
398     //glFlush();    
399 //    OpenGLManager::getSingleton().endRendering();
400         OpenGLManager::getSingleton().setDrawFlag();
401     //Take screenshot?
402 }
403
404 //-----------------------------------------------------------------------------
405 // Update Screen
406 //-----------------------------------------------------------------------------
407 void GraphicsPlugin::drawScreen()
408 {
409     OpenGLManager::getSingleton().endRendering();
410 }
411
412 void GraphicsPlugin::setDrawScreenSignal()
413 {
414     m_rdp.signalUpdate();
415 }
416
417 //-----------------------------------------------------------------------------
418 // Video Interface Status Changed
419 //-----------------------------------------------------------------------------
420 void GraphicsPlugin::viStatusChanged()
421 {
422     //Get new VI Size
423     m_vi->calcSize( m_graphicsInfo );
424
425     //Re Calculate Scale
426     m_openGLMgr.calcViewScale(m_vi->getWidth(), m_vi->getHeight());
427 }
428
429 //-----------------------------------------------------------------------------
430 // Toggle Fullscreen
431 //-----------------------------------------------------------------------------
432 void GraphicsPlugin::toggleFullscreen()
433 {
434     if ( m_initialized ) 
435     {   
436         CoreVideo_ToggleFullScreen();
437     }
438 }
439
440 //-----------------------------------------------------------------------------
441 // Take Screenshot
442 //-----------------------------------------------------------------------------
443 void GraphicsPlugin::takeScreenshot(void *dest, int *width, int *height, int front)
444 {
445     *width = m_config->windowWidth;
446     *height = m_config->windowHeight;
447     if (dest)
448     {
449 #ifndef HAVE_GLES
450         if (front)
451             glReadBuffer(GL_FRONT);
452         else
453             glReadBuffer(GL_BACK);
454 #endif
455         glReadPixels(0, 0, *width, *height, GL_RGB, GL_UNSIGNED_BYTE, dest);
456     }
457 }
458
459 //-----------------------------------------------------------------------------
460 // Update Configuration
461 //-----------------------------------------------------------------------------
462 void GraphicsPlugin::updateConfig()
463 {
464     m_updateConfig = true;
465
466     //For project 64, Give config dialog time to close before continueing
467 #ifdef WIN32
468     Sleep(300); 
469 #endif
470     //Resize Window
471     _setWindowMode(m_config->windowWidth, m_config->windowHeight);  
472
473     //Reinitialize OpenGL
474     OpenGLManager::getSingleton().resize(m_config->windowWidth, m_config->windowHeight, m_config->fullscreenBitDepth, m_config->fullscreenRefreshRate);        
475 }
476
477 //-----------------------------------------------------------------------------
478 // Set Window Mode
479 //-----------------------------------------------------------------------------
480 void GraphicsPlugin::_setWindowMode(int width, int height)
481 {
482     if ( m_initialized ) 
483     {
484         //TODO: is this function needed?
485         //m_windowMgr->resizeWindow(width, height);            
486     }    
487 }
488
489 //-----------------------------------------------------------------------------
490 // Set Texture Cache Size
491 //-----------------------------------------------------------------------------
492 void GraphicsPlugin::_setTextureCacheSize(int sizeInBytes)
493 {
494
495 }