mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
f295182833
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
141 lines
4.3 KiB
C++
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;
|
|
}
|
|
}
|