diff --git a/src/win32/OpenGL.cpp b/src/win32/OpenGL.cpp deleted file mode 100644 index abfe0892..00000000 --- a/src/win32/OpenGL.cpp +++ /dev/null @@ -1,764 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team -// Copyright (C) 2005-2006 VBA development team -// Copyright (C) 2007-2008 VBA-M development team -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef NO_OGL - -//OpenGL library -#pragma comment( lib, "opengl32.lib" ) - -// MFC -#include "stdafx.h" - -//GUI -#include "MainWnd.h" -#include "FullscreenSettings.h" - -// Internals -#include "../System.h" -#include "../agb/GBA.h" -#include "../Globals.h" -#include "../Util.h" -#include "../dmg/gbGlobals.h" -#include "..\memgzio.h" - -//Math -#include -#include - -// OpenGL -#include // main include file -#include -#include "glFont.h" -#include -typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); -extern int Init_2xSaI(u32); -extern void winlog(const char *,...); -extern int systemSpeed; - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#ifdef MMX -extern "C" bool cpu_mmx; -extern bool detectMMX(); -#endif - - -class OpenGLDisplay : public IDisplay { -private: - HDC hDC; - HGLRC hRC; - GLuint texture; - int width,height; - float size; - u8 *filterData; - RECT destRect; - bool failed; - GLFONT font; - int pitch; - GLuint displaylist; - u8 *data; - GLhandleARB v,f,p,t; - DWORD currentAdapter; - - void initializeMatrices( int w, int h ); - bool initializeTexture( int w, int h ); - void updateFiltering( int value ); - void setVSync( int interval = 1 ); - void calculateDestRect( int w, int h ); - void initializeFont(); - void renderlist(); - -public: - OpenGLDisplay(); - virtual ~OpenGLDisplay(); - virtual DISPLAY_TYPE getType() { return OPENGL; }; - - virtual void EnableOpenGL(); - virtual void DisableOpenGL(); - virtual bool initialize(); - virtual void cleanup(); - virtual void clear(); - virtual void render(); - - virtual bool changeRenderSize( int w, int h ); - virtual void resize( int w, int h ); - virtual void setOption( const char *, int ); - virtual bool selectFullScreenMode( VIDEO_MODE &mode ); -}; - -#include "gzglfont.h" -//Load GL font -void OpenGLDisplay::initializeFont() -{ - int ret; - z_stream strm; - char *buf = (char *)malloc(GZGLFONT_SIZE); - - /* allocate inflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, 16+MAX_WBITS); - if (ret != Z_OK) - return; - - strm.avail_in = sizeof(gzglfont); - strm.next_in = gzglfont; - strm.avail_out = GZGLFONT_SIZE; - strm.next_out = (Bytef *)buf; - ret = inflate(&strm, Z_NO_FLUSH); - if (ret==Z_STREAM_END) - { - glGenTextures( 1, &texture ); - glFontCreate(&font, (char *)buf, texture); - texture=0; - } - free(buf); - (void)inflateEnd(&strm); -} - -//OpenGL class constructor -OpenGLDisplay::OpenGLDisplay() -{ - hDC = NULL; - hRC = NULL; - texture = 0; - width = 0; - height = 0; - size = 0.0f; - failed = false; - filterData = NULL; - currentAdapter = 0; -} - -//OpenGL class destroyer -OpenGLDisplay::~OpenGLDisplay() -{ - cleanup(); -} - -//Set OpenGL PFD and contexts -void OpenGLDisplay::EnableOpenGL() -{ - PIXELFORMATDESCRIPTOR pfd; - // get the device context (DC) - hDC = GetDC( theApp.m_pMainWnd->GetSafeHwnd() ); - // set the pixel format for the DC - ZeroMemory( &pfd, sizeof( pfd ) ); - pfd.nSize = sizeof( pfd ); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; - pfd.cDepthBits = 16; - pfd.iLayerType = PFD_MAIN_PLANE; - SetPixelFormat (GetDC (theApp.m_pMainWnd->GetSafeHwnd()), ChoosePixelFormat ( GetDC (theApp.m_pMainWnd->GetSafeHwnd()), &pfd), &pfd); - wglMakeCurrent (GetDC (theApp.m_pMainWnd->GetSafeHwnd()), wglCreateContext(GetDC (theApp.m_pMainWnd->GetSafeHwnd()) ) ); -} -//Remove contexts -void OpenGLDisplay::DisableOpenGL() -{ - wglMakeCurrent( NULL, NULL ); - wglDeleteContext( hRC ); - ReleaseDC( theApp.m_pMainWnd->GetSafeHwnd(), hDC ); -} -//Remove resources used -void OpenGLDisplay::cleanup() -{ - if(texture != 0) { - glDeleteTextures(1, &texture); - texture = 0; - } - - if (displaylist) - { - glDeleteLists(displaylist, 1); - displaylist = 0; - } - - DisableOpenGL(); - if(filterData) { - free(filterData); - filterData = NULL; - } - width = 0; - height = 0; - size = 0.0f; - - DISPLAY_DEVICE dev; - ZeroMemory( &dev, sizeof(dev) ); - dev.cb = sizeof(dev); - EnumDisplayDevices( NULL, currentAdapter, &dev, 0 ); - // restore default video mode - ChangeDisplaySettingsEx( dev.DeviceName, NULL, NULL, 0, NULL ); -} - -//init renderer -bool OpenGLDisplay::initialize() -{ - switch( theApp.cartridgeType ) - { - case IMAGE_GBA: - theApp.sizeX = 240; - theApp.sizeY = 160; - break; - case IMAGE_GB: - if ( gbBorderOn ) - { - theApp.sizeX = 256; - theApp.sizeY = 224; - } - else - { - theApp.sizeX = 160; - theApp.sizeY = 144; - } - break; - } - - - switch(theApp.videoOption) - { - case VIDEO_1X: - theApp.surfaceSizeX = theApp.sizeX; - theApp.surfaceSizeY = theApp.sizeY; - break; - case VIDEO_2X: - theApp.surfaceSizeX = theApp.sizeX * 2; - theApp.surfaceSizeY = theApp.sizeY * 2; - break; - case VIDEO_3X: - theApp.surfaceSizeX = theApp.sizeX * 3; - theApp.surfaceSizeY = theApp.sizeY * 3; - break; - case VIDEO_4X: - theApp.surfaceSizeX = theApp.sizeX * 4; - theApp.surfaceSizeY = theApp.sizeY * 4; - break; - case VIDEO_320x240: - case VIDEO_640x480: - case VIDEO_800x600: - case VIDEO_1024x768: - case VIDEO_1280x960: - case VIDEO_OTHER: - { - if( theApp.fullScreenStretch ) { - theApp.surfaceSizeX = theApp.fsWidth; - theApp.surfaceSizeY = theApp.fsHeight; - } else { - float scaleX = (float)theApp.fsWidth / (float)theApp.sizeX; - float scaleY = (float)theApp.fsHeight / (float)theApp.sizeY; - float min = ( scaleX < scaleY ) ? scaleX : scaleY; - if( theApp.fsMaxScale ) - min = ( min > (float)theApp.fsMaxScale ) ? (float)theApp.fsMaxScale : min; - theApp.surfaceSizeX = (int)((float)theApp.sizeX * min); - theApp.surfaceSizeY = (int)((float)theApp.sizeY * min); - } - } - break; - } - - theApp.rect.left = 0; - theApp.rect.top = 0; - theApp.rect.right = theApp.sizeX; - theApp.rect.bottom = theApp.sizeY; - - theApp.dest.left = 0; - theApp.dest.top = 0; - theApp.dest.right = theApp.surfaceSizeX; - theApp.dest.bottom = theApp.surfaceSizeY; - - DWORD style = WS_POPUP | WS_VISIBLE; - DWORD styleEx = 0; - - if( theApp.videoOption <= VIDEO_4X ) - style |= WS_OVERLAPPEDWINDOW; - else - styleEx = 0; - - if( theApp.videoOption <= VIDEO_4X ) - AdjustWindowRectEx( &theApp.dest, style, TRUE, styleEx ); - else - AdjustWindowRectEx( &theApp.dest, style, FALSE, styleEx ); - - int winSizeX = theApp.dest.right - theApp.dest.left; - int winSizeY = theApp.dest.bottom - theApp.dest.top; - int x = 0, y = 0; - - if( theApp.videoOption <= VIDEO_4X ) { - x = theApp.windowPositionX; - y = theApp.windowPositionY; - } else { - winSizeX = theApp.fsWidth; - winSizeY = theApp.fsHeight; - } - - // Create a window - MainWnd *pWnd = new MainWnd; - theApp.m_pMainWnd = pWnd; - - pWnd->CreateEx( - styleEx, - theApp.wndClass, - "VisualBoyAdvance", - style, - x,y,winSizeX,winSizeY, - NULL, - 0 ); - - if (!(HWND)*pWnd) { - winlog("Error creating Window %08x\n", GetLastError()); - return FALSE; - } - - theApp.updateMenuBar(); - - theApp.adjustDestRect(); - theApp.mode320Available = FALSE; - theApp.mode640Available = FALSE; - theApp.mode800Available = FALSE; - theApp.mode1024Available = FALSE; - theApp.mode1280Available = FALSE; - - - currentAdapter = theApp.fsAdapter; - DISPLAY_DEVICE dev; - ZeroMemory( &dev, sizeof(dev) ); - dev.cb = sizeof(dev); - EnumDisplayDevices( NULL, currentAdapter, &dev, 0 ); - if( theApp.videoOption >= VIDEO_320x240 ) { - // enter full screen mode - DEVMODE mode; - ZeroMemory( &mode, sizeof(mode) ); - mode.dmSize = sizeof(mode); - mode.dmBitsPerPel = theApp.fsColorDepth; - mode.dmPelsWidth = theApp.fsWidth; - mode.dmPelsHeight = theApp.fsHeight; - mode.dmDisplayFrequency = theApp.fsFrequency; - mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; - LONG ret = ChangeDisplaySettingsEx( dev.DeviceName, &mode, NULL, CDS_FULLSCREEN, NULL ); - if( ret != DISP_CHANGE_SUCCESSFUL ) { - systemMessage( 0, "Can not change display mode!" ); - failed = true; - } - } else { - // restore default mode - ChangeDisplaySettingsEx( dev.DeviceName, NULL, NULL, 0, NULL ); - } - - EnableOpenGL(); - initializeFont(); - glPushAttrib( GL_ENABLE_BIT ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_CULL_FACE ); - glEnable( GL_TEXTURE_2D ); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - initializeMatrices( theApp.surfaceSizeX, theApp.surfaceSizeY ); - - setVSync( theApp.vsync ); - -#ifdef MMX - if(!theApp.disableMMX) - cpu_mmx = theApp.detectMMX(); - else - cpu_mmx = 0; -#endif - - systemRedShift = 3; - systemGreenShift = 11; - systemBlueShift = 19; - systemColorDepth = 32; - theApp.fsColorDepth = 32; - - Init_2xSaI(32); - - utilUpdateSystemColorMaps(); - theApp.updateFilter(); - theApp.updateIFB(); - pitch = theApp.filterWidth * (systemColorDepth>>3) + 4; - data = pix + ( theApp.sizeX + 1 ) * 4; - renderlist(); - - if(failed) - return false; - - return true; -} - -//clear colour buffer -void OpenGLDisplay::clear() -{ - glClearColor(0.0,0.0,0.0,1.0); - glClear( GL_COLOR_BUFFER_BIT ); -} - -//dlist -void OpenGLDisplay::renderlist() -{ - displaylist = glGenLists(1); //set the cube list to Generate a List - glNewList(displaylist,GL_COMPILE); //compile the new list - glBegin( GL_QUADS ); - - glTexCoord2f( 0.0f, 0.0f ); - glVertex3i( 0, 0, 0 ); - - glTexCoord2f( (float)(width) / size, 0.0f ); - glVertex3i( theApp.surfaceSizeX, 0, 0 ); - - glTexCoord2f( (float)(width) / size, (float)(height) / size ); - glVertex3i( theApp.surfaceSizeX, theApp.surfaceSizeY, 0 ); - - glTexCoord2f( 0.0f, (float)(height) / size ); - glVertex3i( 0, theApp.surfaceSizeY, 0 ); - glEnd(); - glEndList(); -} - -//main render func -void OpenGLDisplay::render() -{ - clear(); - - pitch = theApp.filterWidth * (systemColorDepth>>3) + 4; - data = pix + ( theApp.sizeX + 1 ) * 4; - - // apply pixel filter - if(theApp.filterFunction) { - data = filterData; - theApp.filterFunction( - pix + pitch, - pitch, - (u8*)theApp.delta, - (u8*)filterData, - width * 4 , - theApp.filterWidth, - theApp.filterHeight); - } - - // Texturemap complete texture to surface - // so we have free scaling and antialiasing - - if( theApp.filterFunction ) { - glPixelStorei( GL_UNPACK_ROW_LENGTH, width); - } else { - glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 ); - } - glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,data ); - - - glCallList(displaylist); - - - if( theApp.showSpeed ) { // && ( theApp.videoOption > VIDEO_4X ) ) { - char buffer[30]; - if( theApp.showSpeed == 1 ) { - sprintf( buffer, "%3d%%", systemSpeed ); - } else { - sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames ); - } - glFontBegin(&font); - glPushMatrix(); - float fontscale = (float)theApp.surfaceSizeX / 100.0f; - glScalef(fontscale, fontscale, fontscale); - glColor4f(1.0f, 0.25f, 0.25f, 1.0f); - glFontTextOut(buffer, (theApp.surfaceSizeX-(strlen(buffer)*11))/(fontscale*2), (theApp.surfaceSizeY-20)/fontscale, 0); - glPopMatrix(); - glFontEnd(); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glBindTexture( GL_TEXTURE_2D, texture ); - } - if( theApp.screenMessage ) { - if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage ) { - glFontBegin(&font); - glPushMatrix(); - - float fontscale = (float)theApp.surfaceSizeX / 100.0f; - glScalef(fontscale, fontscale, fontscale); - glColor4f(1.0f, 0.25f, 0.25f, 1.0f); - glFontTextOut((char *)((const char *)theApp.screenMessageBuffer), (theApp.surfaceSizeX-(theApp.screenMessageBuffer.GetLength()*11))/(fontscale*2), (theApp.surfaceSizeY-40)/fontscale, 0); - glPopMatrix(); - glFontEnd(); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glBindTexture( GL_TEXTURE_2D, texture ); - } else { - theApp.screenMessage = false; - } - } - - glFlush(); - SwapBuffers( hDC ); - // since OpenGL draws on the back buffer, - // we have to swap it to the front buffer to see the content - -} - -//resize screen -void OpenGLDisplay::resize( int w, int h ) -{ - initializeMatrices( w, h ); - /* Display lists are not mutable, so we have to do this*/ - if (displaylist) - { - glDeleteLists(displaylist, 1); - displaylist = 0; - renderlist(); - } -} - -//update filtering methods -void OpenGLDisplay::updateFiltering( int value ) -{ - switch( value ) - { - case 0: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - break; - case 1: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - break; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); -} - -//init projection matrixes and viewports -void OpenGLDisplay::initializeMatrices( int w, int h ) -{ - if( theApp.fullScreenStretch ) { - glViewport( 0, 0, w, h ); - } else { - calculateDestRect( w, h ); - glViewport( - destRect.left, - destRect.top, - destRect.right - destRect.left, - destRect.bottom - destRect.top ); - } - - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( - /* left */ 1.0f, - /* right */ (GLdouble)(w - 1), - /* bottom */ (GLdouble)(h - 1), - /* top */ 1.0f, - 0.0f, - 1.0f ); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - if (displaylist) - { - glDeleteLists(displaylist, 1); - displaylist = 0; - renderlist(); - } -} - -//init font texture -bool OpenGLDisplay::initializeTexture( int w, int h ) -{ - // size = 2^n - // w = 24 > size = 256 = 2^8 - // w = 255 > size = 256 = 2^8 - // w = 256 > size = 512 = 2^9 - // w = 300 > size = 512 = 2^9 - // OpenGL textures have to be square and a power of 2 - // We could use methods that allow tex's to not be powers of two - // but that requires extra OGL extensions - - float n1 = log10( (float)w ) / log10( 2.0f ); - float n2 = log10( (float)h ) / log10( 2.0f ); - float n = ( n1 > n2 ) ? n1 : n2; - - if( ((float)((int)n)) != n ) { - // round up - n = ((float)((int)n)) + 1.0f; - } - - size = pow( 2.0f, n ); - - glGenTextures( 1, &texture ); - glBindTexture( GL_TEXTURE_2D, texture ); - updateFiltering( theApp.glFilter ); - - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA, - (GLsizei)size, - (GLsizei)size, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - NULL ); - - width = w; - height = h; - - //return ( glGetError() == GL_NO_ERROR) ? true : false; - // Workaround: We usually get GL_INVALID_VALUE, but somehow it works nevertheless - // In consequence, we must not treat it as an error or else the app behaves as if an error occured. - // This in the end results in theApp->input not being created = no input when switching from D3D to OGL - return true; -} - -//turn vsync on or off -void OpenGLDisplay::setVSync( int interval ) -{ - const char *extensions = (const char *)glGetString( GL_EXTENSIONS ); - - if( strstr( extensions, "WGL_EXT_swap_control" ) == 0 ) { - winlog( "Error: WGL_EXT_swap_control extension not supported on your computer.\n" ); - return; - } else { - PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = NULL; - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" ); - if( wglSwapIntervalEXT ) { - wglSwapIntervalEXT( interval ); - } - } -} - -//change render size for fonts and filter data -bool OpenGLDisplay::changeRenderSize( int w, int h ) -{ - if( (width != w) || (height != h) ) { - if( texture != 0 ) { - glDeleteTextures( 1, &texture ); - texture = 0; - } - - if( !initializeTexture( w, h ) ) { - failed = true; - return false; - } - if (filterData) - free(filterData); - filterData = (u8 *)malloc(4*w*h); - } - if (displaylist) - { - glDeleteLists(displaylist, 1); - displaylist = 0; - renderlist(); - } - return true; -} - -//calculate RECTs -void OpenGLDisplay::calculateDestRect( int w, int h ) -{ - float scaleX = (float)w / (float)width; - float scaleY = (float)h / (float)height; - float min = (scaleX < scaleY) ? scaleX : scaleY; - if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) { - min = (float)theApp.fsMaxScale; - } - destRect.left = 0; - destRect.top = 0; - destRect.right = (LONG)(width * min); - destRect.bottom = (LONG)(height * min); - if( destRect.right != w ) { - LONG diff = (w - destRect.right) / 2; - destRect.left += diff; - destRect.right += diff; - } - if( destRect.bottom != h ) { - LONG diff = (h - destRect.bottom) / 2; - destRect.top += diff; - destRect.bottom += diff; - } - if (displaylist) - { - glDeleteLists(displaylist, 1); - displaylist = 0; - renderlist(); - } -} - -//config options -void OpenGLDisplay::setOption( const char *option, int value ) -{ - if( !_tcscmp( option, _T("vsync") ) ) { - setVSync( value ); - } - - if( !_tcscmp( option, _T("glFilter") ) ) { - updateFiltering( value ); - } - - if( !_tcscmp( option, _T("maxScale") ) ) { - initializeMatrices( theApp.dest.right, theApp.dest.bottom ); - } - - if( !_tcscmp( option, _T("fullScreenStretch") ) ) { - initializeMatrices( theApp.dest.right, theApp.dest.bottom ); - } -} - -//set fullscreen mode -bool OpenGLDisplay::selectFullScreenMode( VIDEO_MODE &mode ) -{ - FullscreenSettings dlg; - dlg.setAPI( this->getType() ); - INT_PTR ret = dlg.DoModal(); - if( ret == IDOK ) { - mode.adapter = dlg.m_device; - switch( dlg.m_colorDepth ) - { - case 30: - // TODO: support - return false; - break; - case 24: - mode.bitDepth = 32; - break; - case 16: - case 15: - mode.bitDepth = 16; - break; - } - mode.width = dlg.m_width; - mode.height = dlg.m_height; - mode.frequency = dlg.m_refreshRate; - return true; - } else { - return false; - } -} - - -IDisplay *newOpenGLDisplay() -{ - return new OpenGLDisplay(); -} - -#endif // #ifndef NO_OGL