dolphin/Source/Core/Common/GL/GLUtil.cpp
Lioncash f295182833 VideoBackends: Simplify initialization and deinitialization of resources
Approximately three or four times now, the issue of pointers being
in an inconsistent state been an issue in the video backend renderers
with regards to tripping up other developers.

Global (ugh) resources are put into a unique_ptr and will always have a
well-defined state of being - null or not null
2015-12-20 22:40:37 -05:00

141 lines
4.3 KiB
C++

// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <memory>
#include "Common/Assert.h"
#include "Common/GL/GLInterfaceBase.h"
#include "Common/GL/GLUtil.h"
#include "Common/Logging/Log.h"
std::unique_ptr<cInterfaceBase> GLInterface;
static GLuint attributelessVAO = 0;
static GLuint attributelessVBO = 0;
void InitInterface()
{
GLInterface = HostGL_CreateGLInterface();
}
GLuint OpenGL_CompileProgram(const std::string& vertexShader, const std::string& fragmentShader)
{
// generate objects
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLuint programID = glCreateProgram();
// compile vertex shader
const char* shader = vertexShader.c_str();
glShaderSource(vertexShaderID, 1, &shader, nullptr);
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.c_str());
}
else if (!Result)
{
ERROR_LOG(VIDEO, "GLSL vertex shader error:\n%s%s", stringBuffer, vertexShader.c_str());
}
else
{
DEBUG_LOG(VIDEO, "GLSL vertex shader compiled:\n%s", vertexShader.c_str());
}
bool shader_errors = !Result;
#endif
// compile fragment shader
shader = fragmentShader.c_str();
glShaderSource(fragmentShaderID, 1, &shader, nullptr);
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.c_str());
}
else if (!Result)
{
ERROR_LOG(VIDEO, "GLSL fragment shader error:\n%s%s", stringBuffer, fragmentShader.c_str());
}
else
{
DEBUG_LOG(VIDEO, "GLSL fragment shader compiled:\n%s", fragmentShader.c_str());
}
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.c_str(), fragmentShader.c_str());
}
else if (!Result && !shader_errors)
{
ERROR_LOG(VIDEO, "GLSL linker error:\n%s%s%s", stringBuffer, vertexShader.c_str(), fragmentShader.c_str());
}
#endif
// cleanup
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
return programID;
}
void OpenGL_CreateAttributelessVAO()
{
glGenVertexArrays(1, &attributelessVAO);
_dbg_assert_msg_(VIDEO, attributelessVAO != 0, "Attributeless VAO should have been created successfully.")
// In a compatibility context, we require a valid, bound array buffer.
glGenBuffers(1, &attributelessVBO);
_dbg_assert_msg_(VIDEO, attributelessVBO != 0, "Attributeless VBO should have been created successfully.")
// Initialize the buffer with nothing. 16 floats is an arbitrary size that may work around driver issues.
glBindBuffer(GL_ARRAY_BUFFER, attributelessVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, nullptr, GL_STATIC_DRAW);
// We must also define vertex attribute 0.
glBindVertexArray(attributelessVAO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
}
void OpenGL_BindAttributelessVAO()
{
_dbg_assert_msg_(VIDEO, attributelessVAO != 0, "Attributeless VAO should have already been created.")
glBindVertexArray(attributelessVAO);
}
void OpenGL_DeleteAttributelessVAO()
{
_dbg_assert_msg_(VIDEO, attributelessVAO != 0, "Attributeless VAO should have already been created.")
if (attributelessVAO != 0)
{
glDeleteVertexArrays(1, &attributelessVAO);
glDeleteBuffers(1, &attributelessVBO);
attributelessVAO = 0;
attributelessVBO = 0;
}
}