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>
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -26,6 +31,7 @@ static void S9xViewportCallback (int src_width, int src_height,
|
|||
*out_y = src_height + viewport_y;
|
||||
*out_width = viewport_width;
|
||||
*out_height = viewport_height;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -659,9 +665,19 @@ S9xOpenGLDisplayDriver::refresh (int width, int height)
|
|||
void
|
||||
S9xOpenGLDisplayDriver::resize_window (int width, int height)
|
||||
{
|
||||
|
||||
if (!using_egl)
|
||||
gdk_window_destroy (gdk_window);
|
||||
|
||||
create_window (width, height);
|
||||
|
||||
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);
|
||||
|
||||
return;
|
||||
|
@ -670,6 +686,30 @@ S9xOpenGLDisplayDriver::resize_window (int width, int height)
|
|||
void
|
||||
S9xOpenGLDisplayDriver::create_window (int width, int height)
|
||||
{
|
||||
if (using_egl)
|
||||
{
|
||||
egl_surface = NULL;
|
||||
gdk_window = gtk_widget_get_window (drawing_area);
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_WINDOW (gdk_window))
|
||||
{
|
||||
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;
|
||||
|
@ -688,14 +728,85 @@ S9xOpenGLDisplayDriver::create_window (int width, int height)
|
|||
|
||||
gdk_window_show (gdk_window);
|
||||
xwindow = GDK_COMPAT_WINDOW_XID (gdk_window);
|
||||
}
|
||||
#endif
|
||||
|
||||
output_window_width = width;
|
||||
output_window_height = height;
|
||||
}
|
||||
|
||||
int
|
||||
S9xOpenGLDisplayDriver::init_glx (void)
|
||||
S9xOpenGLDisplayDriver::init_gl (void)
|
||||
{
|
||||
using_egl = 0;
|
||||
if (epoxy_has_egl ())
|
||||
{
|
||||
printf ("Using EGL context\n");
|
||||
|
||||
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
|
||||
else /* GLX */
|
||||
{
|
||||
printf ("Using GLX context\n");
|
||||
|
||||
int glx_attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
@ -708,7 +819,6 @@ S9xOpenGLDisplayDriver::init_glx (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
xcolormap = XCreateColormap (display,
|
||||
GDK_COMPAT_WINDOW_XID (gtk_widget_get_window (drawing_area)),
|
||||
vi->visual,
|
||||
|
@ -737,6 +847,8 @@ S9xOpenGLDisplayDriver::init_glx (void)
|
|||
fprintf (stderr, "glXMakeCurrent failed.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -746,7 +858,7 @@ S9xOpenGLDisplayDriver::init (void)
|
|||
{
|
||||
initialized = 0;
|
||||
|
||||
if (!init_glx ())
|
||||
if (!init_gl ())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -778,6 +890,14 @@ void
|
|||
S9xOpenGLDisplayDriver::swap_control (int enable)
|
||||
{
|
||||
enable = enable ? 1 : 0;
|
||||
|
||||
if (using_egl)
|
||||
{
|
||||
eglSwapInterval (egl_display, enable);
|
||||
}
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
else
|
||||
{
|
||||
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
|
||||
|
||||
if (strstr (extensions, "EXT_swap_control"))
|
||||
|
@ -788,6 +908,8 @@ S9xOpenGLDisplayDriver::swap_control (int enable)
|
|||
{
|
||||
glXSwapIntervalSGI (enable);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -815,12 +937,16 @@ S9xOpenGLDisplayDriver::get_current_buffer (void)
|
|||
void
|
||||
S9xOpenGLDisplayDriver::gl_swap (void)
|
||||
{
|
||||
if (using_egl)
|
||||
eglSwapBuffers (egl_display, egl_surface);
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
else
|
||||
glXSwapBuffers (display, xwindow);
|
||||
#endif
|
||||
|
||||
if (config->sync_every_frame)
|
||||
{
|
||||
usleep (0);
|
||||
glXWaitX ();
|
||||
glFinish ();
|
||||
}
|
||||
|
||||
|
@ -866,13 +992,21 @@ S9xOpenGLDisplayDriver::deinit (void)
|
|||
}
|
||||
|
||||
glDeleteTextures (1, &texmap);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -885,18 +1019,18 @@ S9xOpenGLDisplayDriver::reconfigure (int width, int height)
|
|||
int
|
||||
S9xOpenGLDisplayDriver::query_availability (void)
|
||||
{
|
||||
int errorBase, eventBase;
|
||||
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
if (epoxy_has_egl ())
|
||||
return 1;
|
||||
|
||||
if (!display)
|
||||
return 0;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
if (epoxy_has_glx (dpy))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if (glXQueryExtension (display, &errorBase, &eventBase) == False)
|
||||
{
|
||||
if (gui_config->hw_accel == HWA_OPENGL)
|
||||
gui_config->hw_accel = HWA_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
#include "gtk_display_driver.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <epoxy/glx.h>
|
||||
#endif
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
#include "shaders/glsl.h"
|
||||
|
||||
|
@ -50,7 +53,7 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
|||
int shaders_available (void);
|
||||
int load_shaders (const char *);
|
||||
void update_texture_size (int width, int height);
|
||||
int init_glx (void);
|
||||
int init_gl (void);
|
||||
void create_window (int width, int height);
|
||||
void resize_window (int width, int height);
|
||||
|
||||
|
@ -72,14 +75,23 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
|||
int using_glsl_shaders;
|
||||
GLSLShader *glsl_shader;
|
||||
|
||||
GdkWindow *gdk_window;
|
||||
int output_window_width;
|
||||
int output_window_height;
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
Display *display;
|
||||
Window xwindow;
|
||||
Colormap xcolormap;
|
||||
XVisualInfo *vi;
|
||||
GdkWindow *gdk_window;
|
||||
GLXContext glx_context;
|
||||
int output_window_width;
|
||||
int output_window_height;
|
||||
#endif
|
||||
|
||||
bool using_egl;
|
||||
EGLDisplay egl_display;
|
||||
EGLContext egl_context;
|
||||
EGLConfig egl_config;
|
||||
EGLSurface egl_surface;
|
||||
};
|
||||
|
||||
#endif /* __GTK_DISPLAY_DRIVER_OPENGL_H */
|
||||
|
|
Loading…
Reference in New Issue