GTK+: Modernize OpenGL code.

Requires OpenGL 2.0 or above. Everything is core-compatible now.
This commit is contained in:
Brandon Wright 2018-10-27 18:13:51 -05:00
parent b84a8fbd5b
commit 09498e72e0
4 changed files with 116 additions and 64 deletions

View File

@ -11,6 +11,36 @@
#include "gtk_shader_parameters.h"
#include "shaders/shader_helpers.h"
static const char *stock_vertex_shader =
"#version 130\n"
"in vec2 in_position;\n"
"in vec2 in_texcoord;\n"
"out vec2 texcoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4 (in_position, 0.0, 1.0);\n"
" texcoord = in_texcoord;\n"
"}\n";
static const char *stock_fragment_shader =
"#version 130\n"
"uniform sampler2D texmap;\n"
"out vec4 fragcolor;\n"
"in vec2 texcoord;\n"
"void main()\n"
"{\n"
" fragcolor = texture2D(texmap, texcoord);\n"
"}\n";
static GLfloat coords[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
static void S9xViewportCallback (int src_width, int src_height,
int viewport_x, int viewport_y,
int viewport_width, int viewport_height,
@ -37,7 +67,7 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
{
uint8 *final_buffer = NULL;
int final_pitch;
void *pboMemory = NULL;
void *pbo_map = NULL;
int x, y, w, h;
GtkAllocation allocation;
@ -56,6 +86,7 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
allocation.height *= gdk_scale_factor;
#endif
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texmap);
GLint filter = Settings.BilinearFilter ? GL_LINEAR : GL_NEAREST;
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
@ -65,7 +96,6 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
glClear (GL_COLOR_BUFFER_BIT);
glEnable (GL_TEXTURE_2D);
if (config->scale_method > 0)
{
@ -95,8 +125,10 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
final_buffer += (final_pitch * yoffset);
}
x = width; y = height;
w = allocation.width; h = allocation.height;
x = width;
y = height;
w = allocation.width;
h = allocation.height;
S9xApplyAspect (x, y, w, h);
glViewport (x, allocation.height - y - h, w, h);
@ -114,11 +146,11 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
width * height * 2,
NULL,
GL_STREAM_DRAW);
pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
for (int y = 0; y < height; y++)
{
memcpy ((uint8 *) pboMemory + (width * y * 2),
memcpy ((uint8 *) pbo_map + (width * y * 2),
final_buffer + (y * final_pitch),
width * image_bpp);
}
@ -145,12 +177,12 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
width * height * 4,
NULL,
GL_STREAM_DRAW);
pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
/* Pixel swizzling in software */
S9xSetEndianess (ENDIAN_NORMAL);
S9xConvert (final_buffer,
pboMemory,
pbo_map,
final_pitch,
width * 4,
width,
@ -187,11 +219,6 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
final_buffer);
}
texcoords[1] = (float) (height) / texture_height;
texcoords[2] = (float) (width) / texture_width;
texcoords[3] = texcoords[1];
texcoords[4] = texcoords[2];
if (using_glsl_shaders)
{
glsl_shader->render (texmap, width, height, x, allocation.height - y - h, w, h, S9xViewportCallback);
@ -199,7 +226,15 @@ void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
return;
}
glDrawArrays (GL_QUADS, 0, 4);
glUseProgram (stock_program);
glBindBuffer (GL_ARRAY_BUFFER, coord_buffer);
glEnableVertexAttribArray (0);
glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (0));
glEnableVertexAttribArray (1);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (32));
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray (1);
glDisableVertexAttribArray (0);
swap_buffers ();
}
@ -332,26 +367,41 @@ int S9xOpenGLDisplayDriver::opengl_defaults ()
npot = true;
}
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
stock_program = glCreateProgram ();
vertices[0] = 0.0f;
vertices[1] = 0.0f;
vertices[2] = 1.0f;
vertices[3] = 0.0f;
vertices[4] = 1.0f;
vertices[5] = 1.0f;
vertices[6] = 0.0f;
vertices[7] = 1.0f;
GLuint vertex_shader = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vertex_shader, 1, (const GLchar **) &stock_vertex_shader, NULL);
glCompileShader (vertex_shader);
glAttachShader (stock_program, vertex_shader);
glVertexPointer (2, GL_FLOAT, 0, vertices);
GLuint fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fragment_shader, 1, (const GLchar **) &stock_fragment_shader, NULL);
glCompileShader (fragment_shader);
glAttachShader (stock_program, fragment_shader);
texcoords[0] = 0.0f;
texcoords[5] = 0.0f;
texcoords[6] = 0.0f;
texcoords[7] = 0.0f;
glBindAttribLocation (stock_program, 0, "in_position");
glBindAttribLocation (stock_program, 1, "in_texcoord");
glTexCoordPointer (2, GL_FLOAT, 0, texcoords);
glLinkProgram (stock_program);
glUseProgram (stock_program);
glDeleteShader (vertex_shader);
glDeleteShader (fragment_shader);
GLint texture_uniform = glGetUniformLocation (stock_program, "texmap");
glUniform1i (texture_uniform, 0);
if (core)
{
GLuint vao;
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
}
glGenBuffers (1, &coord_buffer);
glBindBuffer (GL_ARRAY_BUFFER, coord_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 16, coords, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
if (config->use_pbos)
{
@ -393,25 +443,7 @@ int S9xOpenGLDisplayDriver::opengl_defaults ()
NULL);
}
glEnable (GL_DITHER);
glDisable (GL_POLYGON_SMOOTH);
glShadeModel (GL_FLAT);
glPolygonMode (GL_FRONT, GL_FILL);
glEnable (GL_CULL_FACE);
glCullFace (GL_BACK);
glClearColor (0.0, 0.0, 0.0, 0.0);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
glDisable (GL_TEXTURE_2D);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0.0, 1.0, 0.0, 1.0, -1, 1);
return 1;
}
@ -456,12 +488,22 @@ int S9xOpenGLDisplayDriver::create_context ()
context->make_current ();
if (epoxy_gl_version () < 20)
int version = epoxy_gl_version ();
if (version < 20)
{
printf ("OpenGL version is only %d. Need 20.\n", epoxy_gl_version ());
return 0;
printf ("OpenGL version is only %d.%d. Need 2.0.\n"
"Trying to run anyway.",
version / 10,
version % 10);
}
int profile_mask = 0;
glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &profile_mask);
if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT)
core = true;
else
core = false;
return 1;
}

View File

@ -42,13 +42,14 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
int create_context ();
void resize ();
GLuint stock_program;
GLuint coord_buffer;
GLint texture_width;
GLint texture_height;
GLfloat vertices[8];
GLfloat texcoords[8];
GLuint texmap;
GLuint pbo;
bool core;
bool npot;
bool using_pbos;
bool initialized;

View File

@ -91,7 +91,9 @@ bool GTKGLXContext::attach (GtkWidget *widget)
bool GTKGLXContext::create_context ()
{
int context_attribs[] = {
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
None
};
@ -142,13 +144,9 @@ void GTKGLXContext::make_current ()
void GTKGLXContext::swap_interval (int frames)
{
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
if (!extensions)
return;
if (strstr (extensions, "EXT_swap_control"))
if (epoxy_has_glx_extension (display, screen, "GLX_EXT_swap_control"))
glXSwapIntervalEXT (display, xid, frames);
else if (strstr (extensions, "SGI_swap_control"))
else if (epoxy_has_glx_extension (display, screen, "GLX_SGI_swap_control"))
glXSwapIntervalSGI (frames);
}

View File

@ -110,7 +110,14 @@ bool WaylandEGLContext::create_context ()
EGL_NONE
};
EGLint context_attribs[] = {
EGLint core_context_attribs[] = {
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
EGL_CONTEXT_MAJOR_VERSION, 3,
EGL_CONTEXT_MINOR_VERSION, 3,
EGL_NONE
};
EGLint compatibility_context_attribs[] = {
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
EGL_NONE
};
@ -144,12 +151,16 @@ bool WaylandEGLContext::create_context ()
return false;
}
egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, context_attribs);
egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, core_context_attribs);
if (!egl_context)
{
egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, compatibility_context_attribs);
if (!egl_context)
{
printf ("Couldn't create context.\n");
return false;
}
}
wl_surface_set_buffer_scale (child, scale);
gdk_window_invalidate_rect (gdk_window, NULL, FALSE);