mirror of https://github.com/snes9xgit/snes9x.git
GTK: Add EGL WSI for OpenGL.
This commit is contained in:
parent
e543702e24
commit
55723df0a6
|
@ -1,8 +1,13 @@
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
#include <gdk/gdkwayland.h>
|
||||||
|
#endif
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -26,6 +31,7 @@ static void S9xViewportCallback (int src_width, int src_height,
|
||||||
*out_y = src_height + viewport_y;
|
*out_y = src_height + viewport_y;
|
||||||
*out_width = viewport_width;
|
*out_width = viewport_width;
|
||||||
*out_height = viewport_height;
|
*out_height = viewport_height;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,9 +665,19 @@ S9xOpenGLDisplayDriver::refresh (int width, int height)
|
||||||
void
|
void
|
||||||
S9xOpenGLDisplayDriver::resize_window (int width, int height)
|
S9xOpenGLDisplayDriver::resize_window (int width, int height)
|
||||||
{
|
{
|
||||||
gdk_window_destroy (gdk_window);
|
|
||||||
|
if (!using_egl)
|
||||||
|
gdk_window_destroy (gdk_window);
|
||||||
|
|
||||||
create_window (width, height);
|
create_window (width, height);
|
||||||
glXMakeCurrent (display, xwindow, glx_context);
|
|
||||||
|
if (using_egl)
|
||||||
|
eglMakeCurrent (egl_display, egl_surface, egl_surface, egl_context);
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
else
|
||||||
|
glXMakeCurrent (display, xwindow, glx_context);
|
||||||
|
#endif
|
||||||
|
|
||||||
swap_control (config->sync_to_vblank);
|
swap_control (config->sync_to_vblank);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -670,73 +686,169 @@ S9xOpenGLDisplayDriver::resize_window (int width, int height)
|
||||||
void
|
void
|
||||||
S9xOpenGLDisplayDriver::create_window (int width, int height)
|
S9xOpenGLDisplayDriver::create_window (int width, int height)
|
||||||
{
|
{
|
||||||
GdkWindowAttr window_attr;
|
if (using_egl)
|
||||||
memset (&window_attr, 0, sizeof (GdkWindowAttr));
|
{
|
||||||
window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
|
egl_surface = NULL;
|
||||||
window_attr.width = width;
|
gdk_window = gtk_widget_get_window (drawing_area);
|
||||||
window_attr.height = height;
|
|
||||||
window_attr.x = 0;
|
|
||||||
window_attr.y = 0;
|
|
||||||
window_attr.wclass = GDK_INPUT_OUTPUT;
|
|
||||||
window_attr.window_type = GDK_WINDOW_CHILD;
|
|
||||||
window_attr.visual = gdk_x11_screen_lookup_visual (gtk_widget_get_screen (drawing_area), vi->visualid);
|
|
||||||
|
|
||||||
gdk_window = gdk_window_new (gtk_widget_get_window (drawing_area),
|
#ifdef GDK_WINDOWING_X11
|
||||||
&window_attr,
|
if (GDK_IS_X11_WINDOW (gdk_window))
|
||||||
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
|
{
|
||||||
gdk_window_set_user_data (gdk_window, (gpointer) drawing_area);
|
xwindow = GDK_COMPAT_WINDOW_XID (gdk_window);
|
||||||
|
egl_surface = eglCreateWindowSurface (egl_display, egl_config, xwindow, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
if (GDK_IS_WAYLAND_WINDOW (gdk_window))
|
||||||
|
{
|
||||||
|
struct wl_surface *surface;
|
||||||
|
surface = gdk_wayland_window_get_wl_surface (gdk_window);
|
||||||
|
egl_surface = eglCreatePlatformWindowSurface (egl_display, egl_config, surface, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GdkWindowAttr window_attr;
|
||||||
|
memset (&window_attr, 0, sizeof (GdkWindowAttr));
|
||||||
|
window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
|
||||||
|
window_attr.width = width;
|
||||||
|
window_attr.height = height;
|
||||||
|
window_attr.x = 0;
|
||||||
|
window_attr.y = 0;
|
||||||
|
window_attr.wclass = GDK_INPUT_OUTPUT;
|
||||||
|
window_attr.window_type = GDK_WINDOW_CHILD;
|
||||||
|
window_attr.visual = gdk_x11_screen_lookup_visual (gtk_widget_get_screen (drawing_area), vi->visualid);
|
||||||
|
|
||||||
gdk_window_show (gdk_window);
|
gdk_window = gdk_window_new (gtk_widget_get_window (drawing_area),
|
||||||
xwindow = GDK_COMPAT_WINDOW_XID (gdk_window);
|
&window_attr,
|
||||||
|
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
|
||||||
|
gdk_window_set_user_data (gdk_window, (gpointer) drawing_area);
|
||||||
|
|
||||||
|
gdk_window_show (gdk_window);
|
||||||
|
xwindow = GDK_COMPAT_WINDOW_XID (gdk_window);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
output_window_width = width;
|
output_window_width = width;
|
||||||
output_window_height = height;
|
output_window_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
S9xOpenGLDisplayDriver::init_glx (void)
|
S9xOpenGLDisplayDriver::init_gl (void)
|
||||||
{
|
{
|
||||||
int glx_attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
|
using_egl = 0;
|
||||||
|
if (epoxy_has_egl ())
|
||||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
||||||
|
|
||||||
vi = glXChooseVisual (display, DefaultScreen (display), glx_attribs);
|
|
||||||
|
|
||||||
if (!vi)
|
|
||||||
{
|
{
|
||||||
fprintf (stderr, _("Couldn't find an adequate OpenGL visual.\n"));
|
printf ("Using EGL context\n");
|
||||||
return 0;
|
|
||||||
|
using_egl = 1;
|
||||||
|
EGLint num_configs;
|
||||||
|
EGLint const egl_attribs[] = { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE };
|
||||||
|
|
||||||
|
egl_display = NULL;
|
||||||
|
GdkDisplay *d = gdk_display_get_default ();
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
if (GDK_IS_X11_DISPLAY (d))
|
||||||
|
{
|
||||||
|
display = GDK_DISPLAY_XDISPLAY (d);
|
||||||
|
egl_display = eglGetDisplay (display);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
if (GDK_IS_WAYLAND_DISPLAY (d))
|
||||||
|
{
|
||||||
|
struct wl_display *wl_d = gdk_wayland_display_get_wl_display (d);
|
||||||
|
egl_display = eglGetPlatformDisplay (EGL_PLATFORM_WAYLAND_KHR, wl_d, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!egl_display)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
eglInitialize (egl_display, NULL, NULL);
|
||||||
|
eglChooseConfig (egl_display, egl_attribs, &egl_config, 1, &num_configs);
|
||||||
|
eglBindAPI (EGL_OPENGL_API);
|
||||||
|
|
||||||
|
if (num_configs < 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, _("Couldn't find any appropriate EGL configs.\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_window (1, 1);
|
||||||
|
if (!egl_surface)
|
||||||
|
{
|
||||||
|
fprintf (stderr, _("Couldn't create an EGL surface.\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, NULL);
|
||||||
|
|
||||||
|
if (!egl_context)
|
||||||
|
{
|
||||||
|
fprintf (stderr, _("Couldn't create an EGL context.\n"));
|
||||||
|
eglDestroySurface (egl_display, egl_surface);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglMakeCurrent (egl_display, egl_surface, egl_surface, egl_context))
|
||||||
|
{
|
||||||
|
fprintf (stderr, _("Couldn't make current EGL context.\n"));
|
||||||
|
eglDestroyContext (egl_display, egl_context);
|
||||||
|
eglDestroySurface (egl_display, egl_surface);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
xcolormap = XCreateColormap (display,
|
else /* GLX */
|
||||||
GDK_COMPAT_WINDOW_XID (gtk_widget_get_window (drawing_area)),
|
|
||||||
vi->visual,
|
|
||||||
AllocNone);
|
|
||||||
|
|
||||||
create_window (1, 1);
|
|
||||||
gdk_window_hide (gdk_window);
|
|
||||||
|
|
||||||
glx_context = glXCreateContext (display, vi, 0, 1);
|
|
||||||
|
|
||||||
if (!glx_context)
|
|
||||||
{
|
{
|
||||||
XFreeColormap (display, xcolormap);
|
printf ("Using GLX context\n");
|
||||||
gdk_window_destroy (gdk_window);
|
|
||||||
|
|
||||||
fprintf (stderr, _("Couldn't create an OpenGL context.\n"));
|
int glx_attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
|
||||||
return 0;
|
|
||||||
}
|
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
|
|
||||||
if (!glXMakeCurrent (display, xwindow, glx_context))
|
vi = glXChooseVisual (display, DefaultScreen (display), glx_attribs);
|
||||||
{
|
|
||||||
XFreeColormap (display, xcolormap);
|
if (!vi)
|
||||||
g_object_unref (gdk_window);
|
{
|
||||||
gdk_window_destroy (gdk_window);
|
fprintf (stderr, _("Couldn't find an adequate OpenGL visual.\n"));
|
||||||
|
return 0;
|
||||||
fprintf (stderr, "glXMakeCurrent failed.\n");
|
}
|
||||||
return 0;
|
|
||||||
|
xcolormap = XCreateColormap (display,
|
||||||
|
GDK_COMPAT_WINDOW_XID (gtk_widget_get_window (drawing_area)),
|
||||||
|
vi->visual,
|
||||||
|
AllocNone);
|
||||||
|
|
||||||
|
create_window (1, 1);
|
||||||
|
gdk_window_hide (gdk_window);
|
||||||
|
|
||||||
|
glx_context = glXCreateContext (display, vi, 0, 1);
|
||||||
|
|
||||||
|
if (!glx_context)
|
||||||
|
{
|
||||||
|
XFreeColormap (display, xcolormap);
|
||||||
|
gdk_window_destroy (gdk_window);
|
||||||
|
|
||||||
|
fprintf (stderr, _("Couldn't create an OpenGL context.\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glXMakeCurrent (display, xwindow, glx_context))
|
||||||
|
{
|
||||||
|
XFreeColormap (display, xcolormap);
|
||||||
|
g_object_unref (gdk_window);
|
||||||
|
gdk_window_destroy (gdk_window);
|
||||||
|
|
||||||
|
fprintf (stderr, "glXMakeCurrent failed.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -746,7 +858,7 @@ S9xOpenGLDisplayDriver::init (void)
|
||||||
{
|
{
|
||||||
initialized = 0;
|
initialized = 0;
|
||||||
|
|
||||||
if (!init_glx ())
|
if (!init_gl ())
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -778,16 +890,26 @@ void
|
||||||
S9xOpenGLDisplayDriver::swap_control (int enable)
|
S9xOpenGLDisplayDriver::swap_control (int enable)
|
||||||
{
|
{
|
||||||
enable = enable ? 1 : 0;
|
enable = enable ? 1 : 0;
|
||||||
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
|
|
||||||
|
|
||||||
if (strstr (extensions, "EXT_swap_control"))
|
if (using_egl)
|
||||||
{
|
{
|
||||||
glXSwapIntervalEXT (display, xwindow, enable);
|
eglSwapInterval (egl_display, enable);
|
||||||
}
|
}
|
||||||
else if (strstr (extensions, "SGI_swap_control"))
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
else
|
||||||
{
|
{
|
||||||
glXSwapIntervalSGI (enable);
|
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
|
||||||
|
|
||||||
|
if (strstr (extensions, "EXT_swap_control"))
|
||||||
|
{
|
||||||
|
glXSwapIntervalEXT (display, xwindow, enable);
|
||||||
|
}
|
||||||
|
else if (strstr (extensions, "SGI_swap_control"))
|
||||||
|
{
|
||||||
|
glXSwapIntervalSGI (enable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -815,12 +937,16 @@ S9xOpenGLDisplayDriver::get_current_buffer (void)
|
||||||
void
|
void
|
||||||
S9xOpenGLDisplayDriver::gl_swap (void)
|
S9xOpenGLDisplayDriver::gl_swap (void)
|
||||||
{
|
{
|
||||||
glXSwapBuffers (display, xwindow);
|
if (using_egl)
|
||||||
|
eglSwapBuffers (egl_display, egl_surface);
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
else
|
||||||
|
glXSwapBuffers (display, xwindow);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (config->sync_every_frame)
|
if (config->sync_every_frame)
|
||||||
{
|
{
|
||||||
usleep (0);
|
usleep (0);
|
||||||
glXWaitX ();
|
|
||||||
glFinish ();
|
glFinish ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,13 +992,21 @@ S9xOpenGLDisplayDriver::deinit (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteTextures (1, &texmap);
|
glDeleteTextures (1, &texmap);
|
||||||
glXDestroyContext (display, glx_context);
|
|
||||||
|
|
||||||
gdk_window_destroy (gdk_window);
|
|
||||||
|
|
||||||
XFree (vi);
|
|
||||||
XFreeColormap (display, xcolormap);
|
|
||||||
|
|
||||||
|
if (using_egl)
|
||||||
|
{
|
||||||
|
eglDestroyContext (egl_display, egl_context);
|
||||||
|
eglDestroySurface (egl_display, egl_surface);
|
||||||
|
}
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glXDestroyContext (display, glx_context);
|
||||||
|
gdk_window_destroy (gdk_window);
|
||||||
|
XFree (vi);
|
||||||
|
XFreeColormap (display, xcolormap);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,18 +1019,18 @@ S9xOpenGLDisplayDriver::reconfigure (int width, int height)
|
||||||
int
|
int
|
||||||
S9xOpenGLDisplayDriver::query_availability (void)
|
S9xOpenGLDisplayDriver::query_availability (void)
|
||||||
{
|
{
|
||||||
int errorBase, eventBase;
|
if (epoxy_has_egl ())
|
||||||
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
return 1;
|
||||||
|
|
||||||
if (!display)
|
#ifdef GDK_WINDOWING_X11
|
||||||
return 0;
|
Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
|
|
||||||
if (glXQueryExtension (display, &errorBase, &eventBase) == False)
|
if (epoxy_has_glx (dpy))
|
||||||
{
|
return 1;
|
||||||
if (gui_config->hw_accel == HWA_OPENGL)
|
#endif
|
||||||
gui_config->hw_accel = HWA_NONE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
if (gui_config->hw_accel == HWA_OPENGL)
|
||||||
|
gui_config->hw_accel = HWA_NONE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
#include "gtk_display_driver.h"
|
#include "gtk_display_driver.h"
|
||||||
|
|
||||||
#include <epoxy/gl.h>
|
#include <epoxy/gl.h>
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
#include <epoxy/glx.h>
|
#include <epoxy/glx.h>
|
||||||
|
#endif
|
||||||
|
#include <epoxy/egl.h>
|
||||||
|
|
||||||
#include "shaders/glsl.h"
|
#include "shaders/glsl.h"
|
||||||
|
|
||||||
|
@ -50,7 +53,7 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
||||||
int shaders_available (void);
|
int shaders_available (void);
|
||||||
int load_shaders (const char *);
|
int load_shaders (const char *);
|
||||||
void update_texture_size (int width, int height);
|
void update_texture_size (int width, int height);
|
||||||
int init_glx (void);
|
int init_gl (void);
|
||||||
void create_window (int width, int height);
|
void create_window (int width, int height);
|
||||||
void resize_window (int width, int height);
|
void resize_window (int width, int height);
|
||||||
|
|
||||||
|
@ -72,14 +75,23 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
||||||
int using_glsl_shaders;
|
int using_glsl_shaders;
|
||||||
GLSLShader *glsl_shader;
|
GLSLShader *glsl_shader;
|
||||||
|
|
||||||
|
GdkWindow *gdk_window;
|
||||||
|
int output_window_width;
|
||||||
|
int output_window_height;
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
Display *display;
|
Display *display;
|
||||||
Window xwindow;
|
Window xwindow;
|
||||||
Colormap xcolormap;
|
Colormap xcolormap;
|
||||||
XVisualInfo *vi;
|
XVisualInfo *vi;
|
||||||
GdkWindow *gdk_window;
|
|
||||||
GLXContext glx_context;
|
GLXContext glx_context;
|
||||||
int output_window_width;
|
#endif
|
||||||
int output_window_height;
|
|
||||||
|
bool using_egl;
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
EGLContext egl_context;
|
||||||
|
EGLConfig egl_config;
|
||||||
|
EGLSurface egl_surface;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __GTK_DISPLAY_DRIVER_OPENGL_H */
|
#endif /* __GTK_DISPLAY_DRIVER_OPENGL_H */
|
||||||
|
|
Loading…
Reference in New Issue