snes9x/gtk/src/gtk_wayland_egl_context.cpp

201 lines
5.3 KiB
C++
Raw Normal View History

2018-10-22 01:03:35 +02:00
#include <stdio.h>
#include <string.h>
#include "gtk_wayland_egl_context.h"
2018-10-22 01:03:35 +02:00
static void wl_global (void *data,
struct wl_registry *wl_registry,
uint32_t name,
const char *interface,
uint32_t version)
{
struct WaylandEGLContext *wl = (struct WaylandEGLContext *) data;
2018-10-22 01:03:35 +02:00
if (!strcmp (interface, "wl_compositor"))
wl->compositor = (struct wl_compositor *) wl_registry_bind (wl_registry, name, &wl_compositor_interface, 3);
2018-10-22 01:03:35 +02:00
else if (!strcmp (interface, "wl_subcompositor"))
wl->subcompositor = (struct wl_subcompositor *) wl_registry_bind (wl_registry, name, &wl_subcompositor_interface, 1);
}
static void wl_global_remove (void *data,
struct wl_registry *wl_registry,
uint32_t name)
{
}
static const struct wl_registry_listener wl_registry_listener = {
wl_global,
wl_global_remove
};
WaylandEGLContext::WaylandEGLContext ()
2018-10-22 01:03:35 +02:00
{
display = NULL;
registry = NULL;
compositor = NULL;
subcompositor = NULL;
parent = NULL;
child = NULL;
2018-10-22 01:49:13 +02:00
region = NULL;
2018-10-22 01:03:35 +02:00
subsurface = NULL;
egl_display = NULL;
egl_surface = NULL;
egl_context = NULL;
egl_config = NULL;
egl_window = NULL;
}
WaylandEGLContext::~WaylandEGLContext ()
2018-10-22 01:03:35 +02:00
{
if (subsurface)
wl_subsurface_destroy (subsurface);
if (region)
wl_region_destroy (region);
if (child)
wl_surface_destroy (child);
if (egl_context)
eglDestroyContext (egl_display, egl_context);
if (egl_surface)
eglDestroySurface (egl_display, egl_surface);
if (egl_window)
wl_egl_window_destroy (egl_window);
}
bool WaylandEGLContext::attach (GtkWidget *widget)
2018-10-22 01:03:35 +02:00
{
GdkWindow *window = gtk_widget_get_window (widget);
2018-10-22 01:03:35 +02:00
if (!GDK_IS_WAYLAND_WINDOW (window))
return false;
gdk_window = window;
gdk_window_get_geometry (gdk_window, &x, &y, &width, &height);
2018-10-22 01:03:35 +02:00
display = gdk_wayland_display_get_wl_display (gdk_window_get_display (gdk_window));
parent = gdk_wayland_window_get_wl_surface (gdk_window);
registry = wl_display_get_registry (display);
wl_registry_add_listener (registry, &wl_registry_listener, this);
wl_display_roundtrip (display);
if (!compositor || !subcompositor)
return false;
child = wl_compositor_create_surface (compositor);
region = wl_compositor_create_region (compositor);
subsurface = wl_subcompositor_get_subsurface (subcompositor, child, parent);
wl_surface_set_input_region (child, region);
wl_subsurface_set_desync (subsurface);
wl_subsurface_set_position (subsurface, x, y);
return true;
}
bool WaylandEGLContext::create_context ()
2018-10-22 01:03:35 +02:00
{
int scale = gdk_window_get_scale_factor (gdk_window);
gdk_window_get_geometry (gdk_window, &x, &y, &width, &height);
2018-10-22 01:03:35 +02:00
EGLint surface_attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_RED_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_NONE
};
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[] = {
2018-10-22 01:03:35 +02:00
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
EGL_NONE
};
EGLint num_configs = 0;
if (!subsurface)
return false;
egl_display = eglGetDisplay ((EGLNativeDisplayType) display);
eglInitialize (egl_display, NULL, NULL);
if (!eglChooseConfig (egl_display, surface_attribs, &egl_config, 1, &num_configs))
{
printf ("Couldn't find matching config.\n");
return false;
}
eglBindAPI (EGL_OPENGL_API);
egl_window = wl_egl_window_create (child, width * scale, height * scale);
if (!egl_window)
{
printf ("Couldn't create window.\n");
return false;
}
egl_surface = eglCreateWindowSurface (egl_display, egl_config, (EGLNativeWindowType) egl_window, NULL);
if (!egl_surface)
{
printf ("Couldn't create surface.\n");
return false;
}
egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, core_context_attribs);
2018-10-22 01:03:35 +02:00
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;
}
2018-10-22 01:03:35 +02:00
}
wl_surface_set_buffer_scale (child, scale);
gdk_window_invalidate_rect (gdk_window, NULL, FALSE);
2018-10-22 01:03:35 +02:00
return true;
}
void WaylandEGLContext::resize ()
2018-10-22 01:03:35 +02:00
{
int scale;
2018-10-22 01:03:35 +02:00
gdk_window_get_geometry (gdk_window, &x, &y, &width, &height);
2018-10-22 01:03:35 +02:00
scale = gdk_window_get_scale_factor (gdk_window);
wl_egl_window_resize (egl_window, width * scale, height * scale, 0, 0);
2018-10-22 01:03:35 +02:00
wl_subsurface_set_position (subsurface, x, y);
make_current ();
}
void WaylandEGLContext::swap_buffers ()
2018-10-22 01:03:35 +02:00
{
eglSwapBuffers (egl_display, egl_surface);
wl_surface_commit (child);
}
void WaylandEGLContext::make_current ()
2018-10-22 01:03:35 +02:00
{
eglMakeCurrent (egl_display, egl_surface, egl_surface, egl_context);
}
void WaylandEGLContext::swap_interval (int frames)
2018-10-22 01:03:35 +02:00
{
eglSwapInterval (egl_display, frames);
}