Slightly improved OpenGL error handling on Windows

This commit is contained in:
Henrik Rydgard 2013-03-10 23:08:57 +01:00
parent f5bb835dcb
commit 94e485e695
9 changed files with 116 additions and 84 deletions

View File

@ -21,7 +21,6 @@
#include <string>
#include "../Globals.h"
class PMixer
{
public:
@ -30,8 +29,6 @@ public:
virtual int Mix(short *stereoout, int numSamples) {memset(stereoout,0,numSamples*2*sizeof(short)); return numSamples;}
};
class Host
{
public:
@ -44,7 +41,7 @@ public:
virtual void SetDebugMode(bool mode) { }
virtual void InitGL() = 0;
virtual bool InitGL(std::string *error_string) = 0;
virtual void BeginFrame() {}
virtual void ShutdownGL() = 0;

View File

@ -2,6 +2,7 @@
#include "base/threadutil.h"
#include "Log.h"
#include "StringUtil.h"
#include "../Globals.h"
#include "EmuThread.h"
#include "../Core/MemMap.h"
@ -53,18 +54,25 @@ char *GetCurrentFilename()
return fileToStart;
}
DWORD TheThread(LPVOID x)
{
DWORD TheThread(LPVOID x) {
setCurrentThreadName("EmuThread");
g_State.bEmuThreadStarted = true;
CoreParameter coreParameter;
host->UpdateUI();
host->InitGL();
std::string error_string;
if (!host->InitGL(&error_string)) {
std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str());
MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR);
ERROR_LOG(BOOT, full_error.c_str());
goto shutdown;
}
INFO_LOG(BOOT, "Starting up hardware.");
CoreParameter coreParameter;
coreParameter.fileToStart = fileToStart;
coreParameter.enableSound = true;
coreParameter.gpuCore = GPU_GLES;
@ -81,7 +89,7 @@ DWORD TheThread(LPVOID x)
coreParameter.startPaused = !g_Config.bAutoRun;
coreParameter.useMediaEngine = false;
std::string error_string;
error_string = "";
if (!PSP_Init(coreParameter, &error_string))
{
ERROR_LOG(BOOT, "Error loading: %s", error_string.c_str());

View File

@ -30,37 +30,32 @@ void setVSync(int interval=1)
wglSwapIntervalEXT(interval);
}
void GL_Resized() // Resize And Initialize The GL Window
{
// Resize And Initialize The GL Window
void GL_Resized() {
if (!hWnd)
return;
RECT rc;
GetWindowRect(hWnd,&rc);
xres=rc.right-rc.left; //account for border :P
yres=rc.bottom-rc.top;
xres = rc.right - rc.left; //account for border :P
yres = rc.bottom - rc.top;
//swidth=width; // Set Scissor Width To Window Width
//sheight=height; // Set Scissor Height To Window Height
if (yres==0) // Prevent A Divide By Zero By
{
yres=1; // Making Height Equal One
}
if (yres == 0)
yres = 1;
glstate.viewport.set(0, 0, xres, yres);
glstate.viewport.restore();
}
void GL_SwapBuffers()
{
void GL_SwapBuffers() {
SwapBuffers(hDC);
}
void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenum type,
GLuint id, GLenum severity, const char *msg)
{
GLuint id, GLenum severity, const char *msg) {
char sourceStr[32];
const char *sourceFmt = "UNDEFINED(0x%04X)";
switch(source)
{
switch(source) {
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;
@ -72,8 +67,7 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu
char typeStr[32];
const char *typeFmt = "UNDEFINED(0x%04X)";
switch(type)
{
switch(type) {
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;
@ -98,8 +92,7 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu
}
void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar *message, GLvoid *userParam)
{
GLsizei length, const GLchar *message, GLvoid *userParam) {
(void)length;
FILE *outFile = (FILE*)userParam;
char finalMessage[256];
@ -107,15 +100,13 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity,
ERROR_LOG(HLE, "GL: %s", finalMessage);
}
bool GL_Init(HWND window)
{
bool GL_Init(HWND window, std::string *error_message) {
*error_message = "ok";
hWnd = window;
GLuint PixelFormat; // Holds The Results After Searching For A Match
GLuint PixelFormat;
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
hInstance = GetModuleHandle(NULL);
static const PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
@ -127,65 +118,68 @@ bool GL_Init(HWND window)
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
0, 0, 0 // Layer Masks Ignored
};
if (!(hDC = GetDC(hWnd))) // Did We Get A Device Context?
{
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
hDC = GetDC(hWnd);
if (!hDC) {
*error_message = "Failed to get a device context.";
return false; // Return FALSE
}
if (!(PixelFormat = ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
// Did Windows Find A Matching Pixel Format?
if (!(PixelFormat = ChoosePixelFormat(hDC,&pfd)))
{
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
*error_message = "Can't Find A Suitable PixelFormat.";
return false;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
// Are We Able To Set The Pixel Format?
if (!SetPixelFormat(hDC,PixelFormat,&pfd)) {
*error_message = "Can't Set The PixelFormat.";
return false;
}
if (!(hRC = wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
// Are We Able To Get A Rendering Context?
if (!(hRC = wglCreateContext(hDC))) {
*error_message = "Can't Create A GL Rendering Context.";
return false;
}
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
// 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.";
return false;
}
glewInit();
// Alright, now for the modernity.
int attribs[] =
{
static const int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_FLAGS_ARB, enableGLDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
0
};
HGLRC m_hrc;
if(wglewIsSupported("WGL_ARB_create_context") == 1)
{
HGLRC m_hrc;
if(wglewIsSupported("WGL_ARB_create_context") == 1) {
m_hrc = wglCreateContextAttribsARB(hDC,0, attribs);
wglMakeCurrent(NULL,NULL);
wglDeleteContext(hRC);
wglMakeCurrent(hDC, m_hrc);
}
else
{ //It's not possible to make a GL 3.x context. Use the old style context (GL 2.1 and before)
} else {
// We can't make a GL 3.x context. Use an old style context (GL 2.1 and before)
m_hrc = hRC;
}
@ -197,43 +191,41 @@ bool GL_Init(HWND window)
glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);
if (!m_hrc) return false;
if (!m_hrc) {
*error_message = "No m_hrc";
return false;
}
hRC = m_hrc;
glstate.Initialize();
setVSync(0);
if (enableGLDebug && glewIsSupported("GL_ARB_debug_output"))
{
if (enableGLDebug && glewIsSupported("GL_ARB_debug_output")) {
glDebugMessageCallbackARB((GLDEBUGPROCARB)&DebugCallbackARB, 0); // print debug output to stderr
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
GL_Resized(); // Set Up Our Perspective GL Screen
return true; // Success
}
void GL_Shutdown()
{
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
void GL_Shutdown() {
if (hRC) {
// Are We Able To Release The DC And RC Contexts?
if (!wglMakeCurrent(NULL,NULL)) {
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
// Are We Able To Delete The RC?
if (!wglDeleteContext(hRC)) {
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
hRC = NULL;
}
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
if (hDC && !ReleaseDC(hWnd,hDC)) {
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
hDC = NULL;
}
hWnd = NULL;
}

View File

@ -5,7 +5,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
bool GL_Init(HWND window);
bool GL_Init(HWND window, std::string *error_message);
void GL_Shutdown();
void GL_Resized();
void GL_SwapBuffers();

View File

@ -1,3 +1,20 @@
// Copyright (c) 2012- PPSSPP Project.
// 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, version 2.0 or later versions.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Core/Core.h"
#include "Core/Config.h"
#include "EmuThread.h"
@ -26,9 +43,9 @@ int MyMix(short *buffer, int numSamples, int bits, int rate, int channels)
}
}
void WindowsHost::InitGL()
bool WindowsHost::InitGL(std::string *error_message)
{
GL_Init(MainWindow::GetDisplayHWND());
return GL_Init(MainWindow::GetDisplayHWND(), error_message);
}
void WindowsHost::ShutdownGL()

View File

@ -1,3 +1,20 @@
// Copyright (c) 2012- PPSSPP Project.
// 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, version 2.0 or later versions.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../Core/Host.h"
#include "InputDevice.h"
#include <list>
@ -19,7 +36,7 @@ public:
void AddSymbol(std::string name, u32 addr, u32 size, int type);
void InitGL();
bool InitGL(std::string *error_message);
void BeginFrame();
void ShutdownGL();

View File

@ -99,7 +99,7 @@ public:
virtual void SetDebugMode(bool mode) { }
virtual void InitGL() {}
virtual bool InitGL(std::string *error_message) {}
virtual void BeginFrame() {}
virtual void ShutdownGL() {}

View File

@ -137,7 +137,9 @@ int main(int argc, const char* argv[])
HeadlessHost *headlessHost = useGraphics ? new HEADLESSHOST_CLASS() : new HeadlessHost();
host = headlessHost;
host->InitGL();
std::string error_string;
host->InitGL(&error_string);
LogManager::Init();
LogManager *logman = LogManager::GetInstance();
@ -176,7 +178,6 @@ int main(int argc, const char* argv[])
g_Config.flashDirectory = g_Config.memCardDirectory+"/flash/";
#endif
std::string error_string;
if (!PSP_Init(coreParameter, &error_string)) {
fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str());

View File

@ -33,7 +33,7 @@ public:
virtual void SetDebugMode(bool mode) { }
virtual void InitGL() {}
virtual bool InitGL(std::string *error_message) {return true;}
virtual void BeginFrame() {}
virtual void ShutdownGL() {}