1 /******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
5 * Copyright (C) 2009 Jon Ring
6 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
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.
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.
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 *****************************************************************************/
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"
40 #include <SDL_opengles.h>
43 //FrameBuffer framebuffer01;
44 //FrameBuffer framebuffer02;
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
49 GraphicsPlugin::GraphicsPlugin()
50 : m_openGLMgr( OpenGLManager::getSingleton() )
53 m_initialized = false;
54 m_updateConfig = false;
58 //-----------------------------------------------------------------------------
60 //-----------------------------------------------------------------------------
61 GraphicsPlugin::~GraphicsPlugin()
66 //-----------------------------------------------------------------------------
68 //-----------------------------------------------------------------------------
69 bool GraphicsPlugin::initialize(GFX_INFO* graphicsInfo)
71 //Initialize video output
72 if (CoreVideo_Init() != M64ERR_SUCCESS)
74 Logger::getSingleton().printMsg("Could not initialize video.", M64MSG_ERROR);
78 //Save pointer to graphics info
79 m_graphicsInfo = graphicsInfo;
81 m_numDListProcessed = 0;
83 //Detect what rom it is
84 m_romDetector = &ROMDetector::getSingleton();
85 m_romDetector->initialize( m_graphicsInfo->HEADER );
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);
91 if (m_config->multiSampling > 0)
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);
101 CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 16);
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)
108 Logger::getSingleton().printMsg("Could not set video attributes.", M64MSG_ERROR);
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)
115 Logger::getSingleton().printMsg("Could not set video mode.", M64MSG_ERROR);
119 CoreVideo_SetCaption("Arachnoid");
121 //Initialize Video Interface
123 m_vi->calcSize(m_graphicsInfo);
126 m_memory = new Memory();
127 if ( !m_memory->initialize(m_graphicsInfo->RDRAM, m_graphicsInfo->DMEM) )
132 m_displayListParser = new DisplayListParser();
133 m_displayListParser->initialize(&m_rsp, &m_rdp, &m_gbi, m_memory);
136 if ( !m_openGLMgr.initialize(m_config->startFullscreen, m_config->fullscreenWidth, m_config->fullscreenHeight, m_config->fullscreenBitDepth, m_config->fullscreenRefreshRate, true, false) )
138 Logger::getSingleton().printMsg("Unable to initialize OpenGL", M64MSG_ERROR);
143 m_openGLMgr.calcViewScale(m_vi->getWidth(), m_vi->getHeight());
145 //Initialize Fog Manager
146 m_fogManager = new FogManager();
147 m_fogManager->initialize();
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 );
156 //Initialize OpenGL Renderer
157 if ( !OpenGLRenderer::getSingleton().initialize(&m_rsp, &m_rdp, &m_textureCache, m_vi, m_fogManager) )
159 Logger::getSingleton().printMsg("Unable to initialize OpenGL Renderer", M64MSG_ERROR);
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);
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);
176 //Initialize framebuffer
177 //framebuffer01.initialize(width, height);
178 // framebuffer02.initialize(width, height);
180 m_initialized = true;
184 //-----------------------------------------------------------------------------
186 //-----------------------------------------------------------------------------
187 void GraphicsPlugin::dispose()
189 //Dispose of Textures
190 m_textureCache.dispose();
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; }
203 //framebuffer01.dispose();
204 // framebuffer02.dispose();
205 m_openGLMgr.dispose();
211 SDL_Quit(); // *SEB* *TODO* Close Subsystem only?
217 m_initialized = false;
220 void renderMotionBlur()
224 glDisable(GL_DEPTH_TEST);
225 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
227 glColor4f(1, 1, 1, 0.9f); //Alpha blending
229 // framebuffer01.render2();
231 glColor4f(1, 1, 1, 1.0f); //Alpha blending
232 glEnable(GL_DEPTH_TEST);
238 bool animate(int frameRate)
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))
245 lastTime = currentTime;
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;
257 if( elapsedTime > (1.0f / frameRate) )
259 lastTime = currentTime;
273 //glDisable(GL_CULL_FACE);
274 glMatrixMode(GL_MODELVIEW);
276 // glRotatef(dt, 0, 1, 0);
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);
294 void renderRedBox(float x, float y, float z, float width, float height, float length)
298 glRotatef(dt, 1,1,1);
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);
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);
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);
336 //-----------------------------------------------------------------------------
337 // ProcessDisplayList
338 //-----------------------------------------------------------------------------
339 void GraphicsPlugin::processDisplayList()
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) )
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);
353 if ( m_updateConfig )
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;
362 //if ( OpenGLManager::getSingleton().getFullscreen() )
364 // //Initialize framebuffer
365 // FrameBuffer::getSingleton().dispose();
366 // FrameBuffer::getSingleton().initialize(m_config->fullscreenWidth, m_config->fullscreenHeight);
370 // //Initialize framebuffer
371 // FrameBuffer::getSingleton().dispose();
372 // FrameBuffer::getSingleton().initialize(m_config->windowWidth, m_config->windowHeight);
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() );
384 OpenGLManager::getSingleton().beginRendering();
385 OpenGLManager::getSingleton().setTextureing2D(true);
386 glEnable(GL_DEPTH_TEST);
388 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
391 m_openGLMgr.setCullMode(false, true);
392 m_displayListParser->processDisplayList();
396 m_numDListProcessed++;
399 // OpenGLManager::getSingleton().endRendering();
400 OpenGLManager::getSingleton().setDrawFlag();
404 //-----------------------------------------------------------------------------
406 //-----------------------------------------------------------------------------
407 void GraphicsPlugin::drawScreen()
409 OpenGLManager::getSingleton().endRendering();
412 void GraphicsPlugin::setDrawScreenSignal()
414 m_rdp.signalUpdate();
417 //-----------------------------------------------------------------------------
418 // Video Interface Status Changed
419 //-----------------------------------------------------------------------------
420 void GraphicsPlugin::viStatusChanged()
423 m_vi->calcSize( m_graphicsInfo );
426 m_openGLMgr.calcViewScale(m_vi->getWidth(), m_vi->getHeight());
429 //-----------------------------------------------------------------------------
431 //-----------------------------------------------------------------------------
432 void GraphicsPlugin::toggleFullscreen()
436 CoreVideo_ToggleFullScreen();
440 //-----------------------------------------------------------------------------
442 //-----------------------------------------------------------------------------
443 void GraphicsPlugin::takeScreenshot(void *dest, int *width, int *height, int front)
445 *width = m_config->windowWidth;
446 *height = m_config->windowHeight;
451 glReadBuffer(GL_FRONT);
453 glReadBuffer(GL_BACK);
455 glReadPixels(0, 0, *width, *height, GL_RGB, GL_UNSIGNED_BYTE, dest);
459 //-----------------------------------------------------------------------------
460 // Update Configuration
461 //-----------------------------------------------------------------------------
462 void GraphicsPlugin::updateConfig()
464 m_updateConfig = true;
466 //For project 64, Give config dialog time to close before continueing
471 _setWindowMode(m_config->windowWidth, m_config->windowHeight);
473 //Reinitialize OpenGL
474 OpenGLManager::getSingleton().resize(m_config->windowWidth, m_config->windowHeight, m_config->fullscreenBitDepth, m_config->fullscreenRefreshRate);
477 //-----------------------------------------------------------------------------
479 //-----------------------------------------------------------------------------
480 void GraphicsPlugin::_setWindowMode(int width, int height)
484 //TODO: is this function needed?
485 //m_windowMgr->resizeWindow(width, height);
489 //-----------------------------------------------------------------------------
490 // Set Texture Cache Size
491 //-----------------------------------------------------------------------------
492 void GraphicsPlugin::_setTextureCacheSize(int sizeInBytes)