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-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"
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-03-17 13:46:39 +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-03-10 22:08:57 +00:00
if ( ! ( PixelFormat = ChoosePixelFormat ( hDC , & pfd ) ) )
2012-11-01 15:19:01 +00:00
{
2013-03-10 22:08:57 +00:00
* error_message = " Can't Find A Suitable PixelFormat. " ;
2012-11-01 15:19:01 +00:00
return false ;
}
2013-03-10 22:08:57 +00:00
if ( ! SetPixelFormat ( hDC , PixelFormat , & pfd ) ) {
* 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 ) ) ) {
* error_message = " Can't Create A GL Rendering Context. " ;
2012-11-01 15:19:01 +00:00
return false ;
}
2013-03-10 22:08:57 +00:00
if ( ! wglMakeCurrent ( hDC , hRC ) ) {
* error_message = " Can't activate the GL Rendering Context. " ;
return false ;
}
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
// Alright, now for the modernity.
2013-03-10 22:08:57 +00:00
static const int attribs [ ] = {
2013-01-26 20:22:49 +00:00
WGL_CONTEXT_MAJOR_VERSION_ARB , 3 ,
WGL_CONTEXT_MINOR_VERSION_ARB , 1 ,
WGL_CONTEXT_FLAGS_ARB , enableGLDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0 ,
0
} ;
2013-03-10 22:08:57 +00:00
HGLRC m_hrc ;
if ( wglewIsSupported ( " WGL_ARB_create_context " ) = = 1 ) {
2013-03-17 13:46:39 +00:00
m_hrc = wglCreateContextAttribsARB ( hDC , 0 , attribs ) ;
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
std : : string renderer = ( const char * ) glGetString ( GL_RENDERER ) ;
if ( renderer = = " GDI Generic " ) {
// Windows XP, no OpenGL driver installed.
* error_message = " PPSSPP requires working OpenGL drivers, version 2.0 or higher. \r \n Please install the latest drivers for your graphics card (GPU). \r \n See ppsspp.org/faq.html for more information. " ;
return false ;
}
/*
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
2013-09-11 19:35:04 +00:00
CheckGLExtensions ( ) ;
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
2012-11-17 16:46:05 +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 ) {
// Are We Able To Release The DC And RC Contexts?
if ( ! wglMakeCurrent ( NULL , NULL ) ) {
2013-08-26 17:00:16 +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-03-10 22:08:57 +00:00
// Are We Able To Delete The RC?
if ( ! wglDeleteContext ( hRC ) ) {
2013-08-26 17:00:16 +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-08-26 17:00:16 +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
}