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-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-06-30 00:47:09 +00:00
|
|
|
#pragma optimize("", off)
|
|
|
|
|
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;
|
|
|
|
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);
|
|
|
|
ERROR_LOG(HLE, "GL: %s", finalMessage);
|
|
|
|
}
|
|
|
|
|
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-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
|
|
|
|
32, // Select Our Color Depth
|
|
|
|
0, 0, 0, 0, 0, 0, // Color Bits Ignored
|
|
|
|
0, // No Alpha Buffer
|
|
|
|
0, // Shift Bit Ignored
|
|
|
|
0, // No Accumulation Buffer
|
2013-03-10 22:08:57 +00:00
|
|
|
0, 0, 0, 0, // Accumulation Bits Ignored
|
2012-11-01 15:19:01 +00:00
|
|
|
16, // 16Bit Z-Buffer (Depth Buffer)
|
|
|
|
0, // No Stencil Buffer
|
|
|
|
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
|
|
|
// Did Windows Find A Matching Pixel Format?
|
|
|
|
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
|
|
|
// Are We Able To Set The Pixel Format?
|
|
|
|
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
|
|
|
// Are We Able To Get A Rendering Context?
|
|
|
|
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
|
|
|
// Try To Activate The Rendering Context
|
|
|
|
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-03-17 13:46:39 +00:00
|
|
|
if (!m_hrc) {
|
|
|
|
*error_message = "No m_hrc";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hRC = m_hrc;
|
|
|
|
|
2013-01-26 20:22:49 +00:00
|
|
|
//Checking GL version
|
|
|
|
const char *GLVersionString = (const char *)glGetString(GL_VERSION);
|
|
|
|
|
|
|
|
//Or better yet, use the GL3 way to get the version number
|
|
|
|
int OpenGLVersion[2];
|
|
|
|
glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
|
|
|
|
glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);
|
|
|
|
|
2012-11-24 14:19:29 +00:00
|
|
|
glstate.Initialize();
|
2013-07-07 08:58:21 +00:00
|
|
|
CheckGLExtensions();
|
2013-08-24 09:53:54 +00:00
|
|
|
if( wglSwapIntervalEXT )
|
|
|
|
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)) {
|
2012-11-01 15:19:01 +00:00
|
|
|
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
|
|
|
}
|
|
|
|
|
2013-03-10 22:08:57 +00:00
|
|
|
// Are We Able To Delete The RC?
|
|
|
|
if (!wglDeleteContext(hRC)) {
|
2012-11-01 15:19:01 +00:00
|
|
|
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
|
|
|
}
|
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) {
|
|
|
|
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
|
|
|
}
|
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
|
|
|
}
|