diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index e982e3746..f6b47f407 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp @@ -10,7 +10,7 @@ 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 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 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); // Check Vertex Shader @@ -42,7 +43,8 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) { // Compile 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); // Check Fragment Shader diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index caa6ae8fe..b43cc8e6b 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h @@ -8,6 +8,6 @@ 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); } diff --git a/src/video_core/renderer_opengl/gl_shaders.h b/src/video_core/renderer_opengl/gl_shaders.h index 746a37afe..6ae0db943 100644 --- a/src/video_core/renderer_opengl/gl_shaders.h +++ b/src/video_core/renderer_opengl/gl_shaders.h @@ -7,38 +7,40 @@ namespace GLShaders { 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; -in vec2 vert_tex_coord; -out vec2 frag_tex_coord; +attribute mediump vec2 vert_position; +attribute mediump vec2 vert_tex_coord; +varying mediump vec2 frag_tex_coord; -// This is a truncated 3x3 matrix for 2D transformations: -// 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; +uniform mat3 modelview_matrix; void main() { - // Multiply input position by the rotscale part of the matrix and then manually translate by - // 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); + gl_Position = vec4(modelview_matrix * vec3(vert_position, 1.0), 1.0); frag_tex_coord = vert_tex_coord; } )"; 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; -out vec4 color; +varying mediump vec2 frag_tex_coord; + +#if GL_ES && __VERSION__ >= 300 +out mediump vec4 color; +#else +#define color gl_FragColor +#endif uniform sampler2D color_texture; void main() { - color = texture(color_texture, frag_tex_coord); + color = texture2D(color_texture, frag_tex_coord); } )"; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index c181ba63e..5e144943f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -34,12 +34,12 @@ struct ScreenRectVertex { * The projection part of the matrix is trivial, hence these operations are represented * by a 3x2 matrix. */ -static std::array MakeOrthographicMatrix(const float width, const float height) { - std::array matrix; +static std::array MakeOrthographicMatrix(const float width, const float height) { + std::array matrix; - matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; - matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; - // Last matrix row is implicitly assumed to be [0, 0, 1]. + matrix[0] = 2.f / width; matrix[3] = 0.f; matrix[6] = -1.f; + matrix[1] = 0.f; matrix[4] = -2.f / height; matrix[7] = 1.f; + matrix[2] = 0.f; matrix[5] = 0.f; matrix[8] = 1.f; return matrix; } @@ -131,11 +131,38 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& * Initializes the OpenGL state and creates persistent objects. */ 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 doesn’t 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); glDisable(GL_DEPTH_TEST); // 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_color_texture = glGetUniformLocation(program_id, "color_texture"); attrib_position = glGetAttribLocation(program_id, "vert_position"); @@ -201,8 +228,8 @@ void RendererOpenGL::DrawScreens() { glUseProgram(program_id); // Set projection matrix - std::array ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height); - glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); + std::array ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height); + glUniformMatrix3fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); // Bind texture in Texture Unit 0 glActiveTexture(GL_TEXTURE0);