2012-11-01 15:19:01 +00:00
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
2013-10-15 10:15:29 +00:00
# include "util/text/utf8.h"
2013-07-29 04:01:49 +00:00
# include "Common/CommonWindows.h"
# include "native/gfx_es2/gl_state.h"
# include "native/gfx/gl_common.h"
2013-09-11 19:35:04 +00:00
# include "util/text/utf8.h"
2013-01-26 20:22:49 +00:00
# include "GL/gl.h"
# include "GL/wglew.h"
2013-10-16 18:25:47 +00:00
# include "util/text/utf8.h"
# include "i18n/i18n.h"
2012-11-01 15:19:01 +00:00
2013-07-29 04:01:49 +00:00
# include "Windows/OpenGLBase.h"
2012-11-01 15:19:01 +00:00
2013-06-16 21:45:06 +00:00
static HDC hDC ; // Private GDI Device Context
static HGLRC hRC ; // Permanent Rendering Context
static HWND hWnd ; // Holds Our Window Handle
2013-10-15 12:59:41 +00:00
2012-11-01 15:19:01 +00:00
static int xres , yres ;
2013-01-26 20:22:49 +00:00
// TODO: Make config?
static bool enableGLDebug = false ;
2013-03-10 22:08:57 +00:00
void GL_Resized ( ) {
2012-11-17 16:46:05 +00:00
if ( ! hWnd )
return ;
2012-11-01 15:19:01 +00:00
RECT rc ;
2013-09-11 19:35:04 +00:00
GetWindowRect ( hWnd , & rc ) ;
2013-03-10 22:08:57 +00:00
xres = rc . right - rc . left ; //account for border :P
yres = rc . bottom - rc . top ;
2012-11-01 15:19:01 +00:00
2013-03-10 22:08:57 +00:00
if ( yres = = 0 )
yres = 1 ;
2013-01-06 22:23:36 +00:00
glstate . viewport . set ( 0 , 0 , xres , yres ) ;
glstate . viewport . restore ( ) ;
2012-11-01 15:19:01 +00:00
}
2013-03-10 22:08:57 +00:00
void GL_SwapBuffers ( ) {
2012-11-01 15:19:01 +00:00
SwapBuffers ( hDC ) ;
}
2013-01-26 20:22:49 +00:00
void FormatDebugOutputARB ( char outStr [ ] , size_t outStrSize , GLenum source , GLenum type ,
2013-03-10 22:08:57 +00:00
GLuint id , GLenum severity , const char * msg ) {
2013-01-26 20:22:49 +00:00
char sourceStr [ 32 ] ;
const char * sourceFmt = " UNDEFINED(0x%04X) " ;
2013-03-10 22:08:57 +00:00
switch ( source ) {
2013-01-26 20:22:49 +00:00
case GL_DEBUG_SOURCE_API_ARB : sourceFmt = " API " ; break ;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB : sourceFmt = " WINDOW_SYSTEM " ; break ;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB : sourceFmt = " SHADER_COMPILER " ; break ;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB : sourceFmt = " THIRD_PARTY " ; break ;
case GL_DEBUG_SOURCE_APPLICATION_ARB : sourceFmt = " APPLICATION " ; break ;
case GL_DEBUG_SOURCE_OTHER_ARB : sourceFmt = " OTHER " ; break ;
}
_snprintf ( sourceStr , 32 , sourceFmt , source ) ;
char typeStr [ 32 ] ;
const char * typeFmt = " UNDEFINED(0x%04X) " ;
2013-03-10 22:08:57 +00:00
switch ( type ) {
2013-01-26 20:22:49 +00:00
case GL_DEBUG_TYPE_ERROR_ARB : typeFmt = " ERROR " ; break ;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB : typeFmt = " DEPRECATED_BEHAVIOR " ; break ;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB : typeFmt = " UNDEFINED_BEHAVIOR " ; break ;
case GL_DEBUG_TYPE_PORTABILITY_ARB : typeFmt = " PORTABILITY " ; break ;
case GL_DEBUG_TYPE_PERFORMANCE_ARB : typeFmt = " PERFORMANCE " ; break ;
case GL_DEBUG_TYPE_OTHER_ARB : typeFmt = " OTHER " ; break ;
}
_snprintf ( typeStr , 32 , typeFmt , type ) ;
char severityStr [ 32 ] ;
const char * severityFmt = " UNDEFINED " ;
switch ( severity )
{
case GL_DEBUG_SEVERITY_HIGH_ARB : severityFmt = " HIGH " ; break ;
case GL_DEBUG_SEVERITY_MEDIUM_ARB : severityFmt = " MEDIUM " ; break ;
case GL_DEBUG_SEVERITY_LOW_ARB : severityFmt = " LOW " ; break ;
}
_snprintf ( severityStr , 32 , severityFmt , severity ) ;
_snprintf ( outStr , outStrSize , " OpenGL: %s [source=%s type=%s severity=%s id=%d] " , msg , sourceStr , typeStr , severityStr , id ) ;
}
void DebugCallbackARB ( GLenum source , GLenum type , GLuint id , GLenum severity ,
2013-03-10 22:08:57 +00:00
GLsizei length , const GLchar * message , GLvoid * userParam ) {
2013-01-26 20:22:49 +00:00
( void ) length ;
FILE * outFile = ( FILE * ) userParam ;
char finalMessage [ 256 ] ;
FormatDebugOutputARB ( finalMessage , 256 , source , type , id , severity , message ) ;
2013-09-07 20:31:14 +00:00
ERROR_LOG ( G3D , " GL: %s " , finalMessage ) ;
2013-01-26 20:22:49 +00:00
}
2013-03-10 22:08:57 +00:00
bool GL_Init ( HWND window , std : : string * error_message ) {
* error_message = " ok " ;
2012-11-01 15:19:01 +00:00
hWnd = window ;
2013-03-10 22:08:57 +00:00
GLuint PixelFormat ;
2012-11-01 15:19:01 +00:00
2013-08-27 14:23:46 +00:00
// TODO: Change to use WGL_ARB_pixel_format instead
2013-03-10 22:08:57 +00:00
static const PIXELFORMATDESCRIPTOR pfd = {
2012-11-01 15:19:01 +00:00
sizeof ( PIXELFORMATDESCRIPTOR ) , // Size Of This Pixel Format Descriptor
1 , // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER , // Must Support Double Buffering
PFD_TYPE_RGBA , // Request An RGBA Format
2013-08-27 14:23:46 +00:00
24 , // Select Our Color Depth
2012-11-01 15:19:01 +00:00
0 , 0 , 0 , 0 , 0 , 0 , // Color Bits Ignored
2013-08-27 14:23:46 +00:00
8 , // No Alpha Buffer
2012-11-01 15:19:01 +00:00
0 , // Shift Bit Ignored
0 , // No Accumulation Buffer
2013-03-10 22:08:57 +00:00
0 , 0 , 0 , 0 , // Accumulation Bits Ignored
2013-09-04 09:31:59 +00:00
16 , // At least a 16Bit Z-Buffer (Depth Buffer)
8 , // 8-bit Stencil Buffer
2012-11-01 15:19:01 +00:00
0 , // No Auxiliary Buffer
2013-03-10 22:08:57 +00:00
PFD_MAIN_PLANE , // Main Drawing Layer
2012-11-01 15:19:01 +00:00
0 , // Reserved
2013-03-10 22:08:57 +00:00
0 , 0 , 0 // Layer Masks Ignored
2012-11-01 15:19:01 +00:00
} ;
2013-03-10 22:08:57 +00:00
hDC = GetDC ( hWnd ) ;
if ( ! hDC ) {
* error_message = " Failed to get a device context. " ;
2012-11-01 15:19:01 +00:00
return false ; // Return FALSE
}
2013-10-15 10:15:29 +00:00
if ( ! ( PixelFormat = ChoosePixelFormat ( hDC , & pfd ) ) ) {
2013-10-16 18:25:47 +00:00
* error_message = " Can't find a suitable PixelFormat. " ;
2012-11-01 15:19:01 +00:00
return false ;
}
2013-10-15 10:15:29 +00:00
if ( ! SetPixelFormat ( hDC , PixelFormat , & pfd ) ) {
2013-10-16 18:25:47 +00:00
* error_message = " Can't set the PixelFormat. " ;
2012-11-01 15:19:01 +00:00
return false ;
}
2013-03-10 22:08:57 +00:00
if ( ! ( hRC = wglCreateContext ( hDC ) ) ) {
2013-10-16 18:25:47 +00:00
* error_message = " Can't create a GL rendering context. " ;
2012-11-01 15:19:01 +00:00
return false ;
2013-10-15 12:59:41 +00:00
}
2012-11-01 15:19:01 +00:00
2013-10-15 10:15:29 +00:00
if ( ! wglMakeCurrent ( hDC , hRC ) ) {
2013-10-16 18:25:47 +00:00
* error_message = " Can't activate the GL rendering context. " ;
2013-03-10 22:08:57 +00:00
return false ;
}
2013-10-15 10:15:29 +00:00
// Check for really old OpenGL drivers and refuse to run really early in some cases.
// TODO: Also either tell the user to give up or point the user to the right websites. Here's some collected
// information about a system that will not work:
// GL_VERSION GL_VENDOR GL_RENDERER
// "1.4.0 - Build 8.14.10.2364" "intel" intel Pineview Platform
2013-10-16 18:25:47 +00:00
I18NCategory * err = GetI18NCategory ( " Error " ) ;
std : : string glVersion = ( const char * ) glGetString ( GL_VERSION ) ;
std : : string glRenderer = ( const char * ) glGetString ( GL_RENDERER ) ;
2013-10-16 19:05:50 +00:00
const std : : string openGL_1 = " 1. " ;
2013-10-16 18:25:47 +00:00
2013-10-16 19:05:50 +00:00
if ( glRenderer = = " GDI Generic " | | glVersion . substr ( 0 , openGL_1 . size ( ) ) = = openGL_1 ) {
2013-10-16 18:30:55 +00:00
const char * defaultError = " Insufficient OpenGL driver support detected! \n \n "
" Your GPU reports that it does not support OpenGL 2.0, which is currently required for PPSSPP to run. \n \n "
" Please check that your GPU is compatible with OpenGL 2.0.If it is, you need to find and install new graphics drivers from your GPU vendor's website. \n \n "
2014-03-24 23:31:33 +00:00
" Visit the forums at http://forums.ppsspp.org for more information. \n \n " ;
2013-10-16 18:30:55 +00:00
2014-03-24 23:43:52 +00:00
std : : wstring versionDetected = ConvertUTF8ToWString ( glVersion + " \n \n " ) ;
2013-10-16 18:30:55 +00:00
std : : wstring error = ConvertUTF8ToWString ( err - > T ( " InsufficientOpenGLDriver " , defaultError ) ) ;
std : : wstring title = ConvertUTF8ToWString ( err - > T ( " OpenGLDriverError " , " OpenGL driver error " ) ) ;
2014-03-24 23:43:52 +00:00
std : : wstring combined = versionDetected + error ;
2013-10-16 18:25:47 +00:00
2014-03-24 23:43:52 +00:00
MessageBox ( hWnd , combined . c_str ( ) , title . c_str ( ) , MB_ICONERROR ) ;
2014-03-24 23:31:33 +00:00
// Avoid further error messages. Let's just bail, it's safe, and we can't continue.
ExitProcess ( 0 ) ;
2013-10-15 10:15:29 +00:00
}
2013-03-10 22:08:57 +00:00
if ( GLEW_OK ! = glewInit ( ) ) {
* error_message = " Failed to initialize GLEW. " ;
2012-11-01 15:19:01 +00:00
return false ;
}
2013-01-26 20:22:49 +00:00
2014-04-01 09:02:27 +00:00
CheckGLExtensions ( ) ;
int contextFlags = enableGLDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0 ;
// Alright, now for the modernity. First try a 4.4, then 4.3, context, if that fails try 3.3.
// I can't seem to find a way that lets you simply request the newest version available.
const int attribs44 [ ] = {
WGL_CONTEXT_MAJOR_VERSION_ARB , 4 ,
WGL_CONTEXT_MINOR_VERSION_ARB , 4 ,
WGL_CONTEXT_FLAGS_ARB , contextFlags ,
WGL_CONTEXT_PROFILE_MASK_ARB , WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ,
0
} ;
const int attribs43 [ ] = {
WGL_CONTEXT_MAJOR_VERSION_ARB , 4 ,
WGL_CONTEXT_MINOR_VERSION_ARB , 3 ,
WGL_CONTEXT_FLAGS_ARB , contextFlags ,
WGL_CONTEXT_PROFILE_MASK_ARB , WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ,
0
} ;
const int attribs33 [ ] = {
2013-01-26 20:22:49 +00:00
WGL_CONTEXT_MAJOR_VERSION_ARB , 3 ,
2014-04-01 09:02:27 +00:00
WGL_CONTEXT_MINOR_VERSION_ARB , 3 ,
WGL_CONTEXT_FLAGS_ARB , contextFlags ,
WGL_CONTEXT_PROFILE_MASK_ARB , WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ,
2013-01-26 20:22:49 +00:00
0
} ;
2013-03-10 22:08:57 +00:00
HGLRC m_hrc ;
if ( wglewIsSupported ( " WGL_ARB_create_context " ) = = 1 ) {
2014-04-01 09:02:27 +00:00
m_hrc = wglCreateContextAttribsARB ( hDC , 0 , attribs44 ) ;
if ( ! m_hrc )
m_hrc = wglCreateContextAttribsARB ( hDC , 0 , attribs43 ) ;
if ( ! m_hrc )
m_hrc = wglCreateContextAttribsARB ( hDC , 0 , attribs33 ) ;
2013-03-17 13:46:39 +00:00
if ( ! m_hrc ) {
// Fall back
m_hrc = hRC ;
} else {
// Switch to the new ARB context.
wglMakeCurrent ( NULL , NULL ) ;
wglDeleteContext ( hRC ) ;
wglMakeCurrent ( hDC , m_hrc ) ;
}
2013-03-10 22:08:57 +00:00
} else {
// We can't make a GL 3.x context. Use an old style context (GL 2.1 and before)
2013-01-26 20:22:49 +00:00
m_hrc = hRC ;
}
2013-10-08 19:50:43 +00:00
if ( GLEW_OK ! = glewInit ( ) ) {
* error_message = " Failed to re-initialize GLEW. " ;
return false ;
}
2013-03-17 13:46:39 +00:00
if ( ! m_hrc ) {
* error_message = " No m_hrc " ;
return false ;
}
hRC = m_hrc ;
2013-09-11 19:35:04 +00:00
/*
MessageBox ( 0 , ConvertUTF8ToWString ( ( const char * ) glGetString ( GL_VERSION ) ) . c_str ( ) , 0 , 0 ) ;
MessageBox ( 0 , ConvertUTF8ToWString ( ( const char * ) glGetString ( GL_VENDOR ) ) . c_str ( ) , 0 , 0 ) ;
MessageBox ( 0 , ConvertUTF8ToWString ( ( const char * ) glGetString ( GL_RENDERER ) ) . c_str ( ) , 0 , 0 ) ;
MessageBox ( 0 , ConvertUTF8ToWString ( ( const char * ) glGetString ( GL_SHADING_LANGUAGE_VERSION ) ) . c_str ( ) , 0 , 0 ) ;
*/
2013-01-26 20:22:49 +00:00
2012-11-24 14:19:29 +00:00
glstate . Initialize ( ) ;
2013-09-11 19:35:04 +00:00
if ( wglSwapIntervalEXT )
2013-08-24 09:53:54 +00:00
wglSwapIntervalEXT ( 0 ) ;
2013-03-10 22:08:57 +00:00
if ( enableGLDebug & & glewIsSupported ( " GL_ARB_debug_output " ) ) {
2013-01-26 20:22:49 +00:00
glDebugMessageCallbackARB ( ( GLDEBUGPROCARB ) & DebugCallbackARB , 0 ) ; // print debug output to stderr
glEnable ( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ) ;
}
2012-11-01 15:19:01 +00:00
2013-10-16 18:30:55 +00:00
GL_Resized ( ) ; // Set up our perspective GL screen
2012-11-01 15:19:01 +00:00
return true ; // Success
}
2013-03-10 22:08:57 +00:00
void GL_Shutdown ( ) {
if ( hRC ) {
2013-10-16 18:25:47 +00:00
// Are we able to release the DC and RC contexts?
2013-03-10 22:08:57 +00:00
if ( ! wglMakeCurrent ( NULL , NULL ) ) {
2013-10-16 18:25:47 +00:00
MessageBox ( NULL , L " Release of DC and RC failed. " , L " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
2012-11-01 15:19:01 +00:00
}
2013-10-16 18:25:47 +00:00
// Are we able to delete the RC?
2013-03-10 22:08:57 +00:00
if ( ! wglDeleteContext ( hRC ) ) {
2013-10-16 18:25:47 +00:00
MessageBox ( NULL , L " Release rendering context failed. " , L " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
2012-11-01 15:19:01 +00:00
}
2013-03-10 22:08:57 +00:00
hRC = NULL ;
2012-11-01 15:19:01 +00:00
}
2013-03-10 22:08:57 +00:00
if ( hDC & & ! ReleaseDC ( hWnd , hDC ) ) {
2013-06-30 00:47:09 +00:00
DWORD err = GetLastError ( ) ;
if ( err ! = ERROR_DC_NOT_FOUND ) {
2013-10-16 18:25:47 +00:00
MessageBox ( NULL , L " Release device context failed. " , L " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
2013-06-30 00:47:09 +00:00
}
2013-03-10 22:08:57 +00:00
hDC = NULL ;
2012-11-01 15:19:01 +00:00
}
2012-11-17 16:46:05 +00:00
hWnd = NULL ;
2012-11-01 15:19:01 +00:00
}