video_core: Make the OpenGL renderer work on GL 2.0+ and GLES 2.0+

This commit is contained in:
Emmanuel Gil Peyrot 2014-11-19 14:56:54 +00:00
parent 8885c118ff
commit 6e95f273cc
4 changed files with 61 additions and 30 deletions

View file

@ -10,7 +10,7 @@
namespace ShaderUtil { namespace ShaderUtil {
GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) { GLuint LoadShaders(const char* glsl_header, const char* vertex_shader, const char* fragment_shader) {
// Create the shaders // Create the shaders
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER); GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
@ -22,7 +22,8 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
// Compile Vertex Shader // Compile Vertex Shader
LOG_DEBUG(Render_OpenGL, "Compiling vertex shader..."); LOG_DEBUG(Render_OpenGL, "Compiling vertex shader...");
glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr); const char* vertex_source[2] = {glsl_header, vertex_shader};
glShaderSource(vertex_shader_id, 2, vertex_source, nullptr);
glCompileShader(vertex_shader_id); glCompileShader(vertex_shader_id);
// Check Vertex Shader // Check Vertex Shader
@ -42,7 +43,8 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
// Compile Fragment Shader // Compile Fragment Shader
LOG_DEBUG(Render_OpenGL, "Compiling fragment shader..."); LOG_DEBUG(Render_OpenGL, "Compiling fragment shader...");
glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr); const char* fragment_source[2] = {glsl_header, fragment_shader};
glShaderSource(fragment_shader_id, 2, fragment_source, nullptr);
glCompileShader(fragment_shader_id); glCompileShader(fragment_shader_id);
// Check Fragment Shader // Check Fragment Shader

View file

@ -8,6 +8,6 @@
namespace ShaderUtil { namespace ShaderUtil {
GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path); GLuint LoadShaders(const char* glsl_header, const char* vertex_shader, const char* fragment_shader);
} }

View file

@ -7,38 +7,40 @@
namespace GLShaders { namespace GLShaders {
const char g_vertex_shader[] = R"( const char g_vertex_shader[] = R"(
#version 150 core #if GL_ES && __VERSION__ >= 300 || !GL_ES && __VERSION__ >= 130
#define attribute in
#define varying out
#endif
in vec2 vert_position; attribute mediump vec2 vert_position;
in vec2 vert_tex_coord; attribute mediump vec2 vert_tex_coord;
out vec2 frag_tex_coord; varying mediump vec2 frag_tex_coord;
// This is a truncated 3x3 matrix for 2D transformations: uniform mat3 modelview_matrix;
// The upper-left 2x2 submatrix performs scaling/rotation/mirroring.
// The third column performs translation.
// The third row could be used for projection, which we don't need in 2D. It hence is assumed to
// implicitly be [0, 0, 1]
uniform mat3x2 modelview_matrix;
void main() { void main() {
// Multiply input position by the rotscale part of the matrix and then manually translate by gl_Position = vec4(modelview_matrix * vec3(vert_position, 1.0), 1.0);
// the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
// to `vec3(vert_position.xy, 1.0)`
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
frag_tex_coord = vert_tex_coord; frag_tex_coord = vert_tex_coord;
} }
)"; )";
const char g_fragment_shader[] = R"( const char g_fragment_shader[] = R"(
#version 150 core #if GL_ES && __VERSION__ >= 300 || !GL_ES && __VERSION__ >= 130
#define varying in
#endif
in vec2 frag_tex_coord; varying mediump vec2 frag_tex_coord;
out vec4 color;
#if GL_ES && __VERSION__ >= 300
out mediump vec4 color;
#else
#define color gl_FragColor
#endif
uniform sampler2D color_texture; uniform sampler2D color_texture;
void main() { void main() {
color = texture(color_texture, frag_tex_coord); color = texture2D(color_texture, frag_tex_coord);
} }
)"; )";

View file

@ -34,12 +34,12 @@ struct ScreenRectVertex {
* The projection part of the matrix is trivial, hence these operations are represented * The projection part of the matrix is trivial, hence these operations are represented
* by a 3x2 matrix. * by a 3x2 matrix.
*/ */
static std::array<GLfloat, 3*2> MakeOrthographicMatrix(const float width, const float height) { static std::array<GLfloat, 3*3> MakeOrthographicMatrix(const float width, const float height) {
std::array<GLfloat, 3*2> matrix; std::array<GLfloat, 3*3> matrix;
matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; matrix[0] = 2.f / width; matrix[3] = 0.f; matrix[6] = -1.f;
matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; matrix[1] = 0.f; matrix[4] = -2.f / height; matrix[7] = 1.f;
// Last matrix row is implicitly assumed to be [0, 0, 1]. matrix[2] = 0.f; matrix[5] = 0.f; matrix[8] = 1.f;
return matrix; return matrix;
} }
@ -131,11 +131,38 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
* Initializes the OpenGL state and creates persistent objects. * Initializes the OpenGL state and creates persistent objects.
*/ */
void RendererOpenGL::InitOpenGLObjects() { void RendererOpenGL::InitOpenGLObjects() {
std::string glsl_header;
// Select the right GLSL version for our context
int version = epoxy_gl_version();
if (epoxy_is_desktop_gl()) {
if (version == 20)
glsl_header = "#version 110\n";
else if (version == 21)
glsl_header = "#version 120\n";
else if (version == 30)
glsl_header = "#version 130\n";
else if (version == 31)
glsl_header = "#version 140\n";
else if (version == 32)
glsl_header = "#version 150\n";
else
glsl_header = "#version " + std::to_string(version * 10) + "\n";
// Desktop OpenGL doesnt support precision qualifiers.
glsl_header += "#define mediump\n";
} else {
if (version == 20)
glsl_header = "#version 100\n";
else
glsl_header = "#version " + std::to_string(version * 10) + " es\n";
}
glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
// Link shaders and get variable locations // Link shaders and get variable locations
program_id = ShaderUtil::LoadShaders(GLShaders::g_vertex_shader, GLShaders::g_fragment_shader); program_id = ShaderUtil::LoadShaders(glsl_header.c_str(), GLShaders::g_vertex_shader, GLShaders::g_fragment_shader);
uniform_modelview_matrix = glGetUniformLocation(program_id, "modelview_matrix"); uniform_modelview_matrix = glGetUniformLocation(program_id, "modelview_matrix");
uniform_color_texture = glGetUniformLocation(program_id, "color_texture"); uniform_color_texture = glGetUniformLocation(program_id, "color_texture");
attrib_position = glGetAttribLocation(program_id, "vert_position"); attrib_position = glGetAttribLocation(program_id, "vert_position");
@ -201,8 +228,8 @@ void RendererOpenGL::DrawScreens() {
glUseProgram(program_id); glUseProgram(program_id);
// Set projection matrix // Set projection matrix
std::array<GLfloat, 3*2> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height); std::array<GLfloat, 3*3> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height);
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); glUniformMatrix3fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
// Bind texture in Texture Unit 0 // Bind texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);