mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 13:57:57 -07:00
839df31347
This branch is the final step of fully supporting both OpenGL and OpenGL ES in the same binary. This of course only applies to EGL and won't work for GLX/AGL/WGL since they don't really support GL ES. The changes here actually aren't too terrible, basically change every #ifdef USE_GLES to a runtime check. This adds a DetectMode() function to the EGL context backend. EGL will iterate through each of the configs and check for GL, GLES3_KHR, and GLES2 bits After that it'll change the mode from _DETECT to whichever one is the best supported. After that point we'll just create a context with the mode that was detected
156 lines
4.4 KiB
C++
156 lines
4.4 KiB
C++
// Copyright 2013 Dolphin Emulator Project
|
|
// Licensed under GPLv2
|
|
// Refer to the license.txt file included.
|
|
|
|
#include "Globals.h"
|
|
#include "VideoConfig.h"
|
|
#include "IniFile.h"
|
|
#include "Core.h"
|
|
#include "VideoBackend.h"
|
|
#include "ConfigManager.h"
|
|
|
|
#include "Render.h"
|
|
|
|
#include "GLUtil.h"
|
|
|
|
GLWindow GLWin;
|
|
cInterfaceBase *GLInterface;
|
|
|
|
namespace OGL
|
|
{
|
|
|
|
// Draw messages on top of the screen
|
|
unsigned int VideoBackend::PeekMessages()
|
|
{
|
|
return GLInterface->PeekMessages();
|
|
}
|
|
|
|
// Show the current FPS
|
|
void VideoBackend::UpdateFPSDisplay(const char *text)
|
|
{
|
|
char temp[100];
|
|
snprintf(temp, sizeof temp, "%s | %s | %s", scm_rev_str, GetDisplayName().c_str(), text);
|
|
return GLInterface->UpdateFPSDisplay(temp);
|
|
}
|
|
|
|
}
|
|
void InitInterface()
|
|
{
|
|
#if defined(USE_EGL) && USE_EGL
|
|
GLInterface = new cInterfaceEGL;
|
|
#elif defined(__APPLE__)
|
|
GLInterface = new cInterfaceAGL;
|
|
#elif defined(_WIN32)
|
|
GLInterface = new cInterfaceWGL;
|
|
#elif defined(HAVE_X11) && HAVE_X11
|
|
GLInterface = new cInterfaceGLX;
|
|
#endif
|
|
}
|
|
|
|
GLuint OpenGL_CompileProgram ( const char* vertexShader, const char* fragmentShader )
|
|
{
|
|
// generate objects
|
|
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
|
GLuint programID = glCreateProgram();
|
|
|
|
// compile vertex shader
|
|
glShaderSource(vertexShaderID, 1, &vertexShader, NULL);
|
|
glCompileShader(vertexShaderID);
|
|
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
|
GLint Result = GL_FALSE;
|
|
char stringBuffer[1024];
|
|
GLsizei stringBufferUsage = 0;
|
|
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result);
|
|
glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer);
|
|
if(Result && stringBufferUsage) {
|
|
ERROR_LOG(VIDEO, "GLSL vertex shader warnings:\n%s%s", stringBuffer, vertexShader);
|
|
} else if(!Result) {
|
|
ERROR_LOG(VIDEO, "GLSL vertex shader error:\n%s%s", stringBuffer, vertexShader);
|
|
} else {
|
|
DEBUG_LOG(VIDEO, "GLSL vertex shader compiled:\n%s", vertexShader);
|
|
}
|
|
bool shader_errors = !Result;
|
|
#endif
|
|
|
|
// compile fragment shader
|
|
glShaderSource(fragmentShaderID, 1, &fragmentShader, NULL);
|
|
glCompileShader(fragmentShaderID);
|
|
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
|
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &Result);
|
|
glGetShaderInfoLog(fragmentShaderID, 1024, &stringBufferUsage, stringBuffer);
|
|
if(Result && stringBufferUsage) {
|
|
ERROR_LOG(VIDEO, "GLSL fragment shader warnings:\n%s%s", stringBuffer, fragmentShader);
|
|
} else if(!Result) {
|
|
ERROR_LOG(VIDEO, "GLSL fragment shader error:\n%s%s", stringBuffer, fragmentShader);
|
|
} else {
|
|
DEBUG_LOG(VIDEO, "GLSL fragment shader compiled:\n%s", fragmentShader);
|
|
}
|
|
shader_errors |= !Result;
|
|
#endif
|
|
|
|
// link them
|
|
glAttachShader(programID, vertexShaderID);
|
|
glAttachShader(programID, fragmentShaderID);
|
|
glLinkProgram(programID);
|
|
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
|
glGetProgramiv(programID, GL_LINK_STATUS, &Result);
|
|
glGetProgramInfoLog(programID, 1024, &stringBufferUsage, stringBuffer);
|
|
if(Result && stringBufferUsage) {
|
|
ERROR_LOG(VIDEO, "GLSL linker warnings:\n%s%s%s", stringBuffer, vertexShader, fragmentShader);
|
|
} else if(!Result && !shader_errors) {
|
|
ERROR_LOG(VIDEO, "GLSL linker error:\n%s%s%s", stringBuffer, vertexShader, fragmentShader);
|
|
}
|
|
#endif
|
|
|
|
// cleanup
|
|
glDeleteShader(vertexShaderID);
|
|
glDeleteShader(fragmentShaderID);
|
|
|
|
return programID;
|
|
}
|
|
|
|
|
|
GLuint OpenGL_ReportGLError(const char *function, const char *file, int line)
|
|
{
|
|
GLint err = glGetError();
|
|
if (err != GL_NO_ERROR)
|
|
{
|
|
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL error 0x%x\n",
|
|
file, line, function, err);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
|
|
{
|
|
unsigned int fbo_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
if (fbo_status != GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
const char *error = "unknown error";
|
|
switch (fbo_status)
|
|
{
|
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
|
error = "INCOMPLETE_ATTACHMENT";
|
|
break;
|
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
|
error = "INCOMPLETE_MISSING_ATTACHMENT";
|
|
break;
|
|
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
|
error = "INCOMPLETE_DRAW_BUFFER";
|
|
break;
|
|
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
|
|
error = "INCOMPLETE_READ_BUFFER";
|
|
break;
|
|
case GL_FRAMEBUFFER_UNSUPPORTED:
|
|
error = "UNSUPPORTED";
|
|
break;
|
|
}
|
|
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL FBO error - %s\n",
|
|
file, line, function, error);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|