2018-11-16 00:42:29 +01:00
|
|
|
/*****************************************************************************\
|
|
|
|
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
|
|
|
This file is licensed under the Snes9x License.
|
|
|
|
For further information, consult the LICENSE file in the root directory.
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
2018-10-22 01:03:35 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
#include "gtk_s9x.h"
|
2018-10-26 22:49:56 +02:00
|
|
|
#include "gtk_wayland_egl_context.h"
|
2018-10-22 01:03:35 +02:00
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
WaylandEGLContext::WaylandEGLContext()
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
egl_display = NULL;
|
|
|
|
egl_surface = NULL;
|
|
|
|
egl_context = NULL;
|
|
|
|
egl_config = NULL;
|
|
|
|
egl_window = NULL;
|
2023-03-06 01:30:46 +01:00
|
|
|
x = 0;
|
|
|
|
y = 0;
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
WaylandEGLContext::~WaylandEGLContext()
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
|
|
|
if (egl_context)
|
2019-03-02 22:25:59 +01:00
|
|
|
eglDestroyContext(egl_display, egl_context);
|
2018-10-22 01:03:35 +02:00
|
|
|
|
|
|
|
if (egl_surface)
|
2019-03-02 22:25:59 +01:00
|
|
|
eglDestroySurface(egl_display, egl_surface);
|
2018-10-22 01:03:35 +02:00
|
|
|
|
|
|
|
if (egl_window)
|
2019-03-02 22:25:59 +01:00
|
|
|
wl_egl_window_destroy(egl_window);
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
bool WaylandEGLContext::attach(GtkWidget *widget)
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
GdkWindow *window = gtk_widget_get_window(widget);
|
2018-10-22 01:03:35 +02:00
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
if (!GDK_IS_WAYLAND_WINDOW(window))
|
2018-10-22 01:03:35 +02:00
|
|
|
return false;
|
|
|
|
|
2023-03-06 01:30:46 +01:00
|
|
|
wayland_surface = std::make_unique<WaylandSurface>();
|
|
|
|
wayland_surface->attach(widget);
|
2022-01-31 04:23:33 +01:00
|
|
|
|
2018-10-22 01:03:35 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
bool WaylandEGLContext::create_context()
|
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
|
|
|
|
};
|
|
|
|
|
2018-10-28 01:13:51 +02:00
|
|
|
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;
|
|
|
|
|
2023-03-06 01:30:46 +01:00
|
|
|
egl_display = eglGetDisplay((EGLNativeDisplayType)wayland_surface->display);
|
2019-03-02 22:25:59 +01:00
|
|
|
eglInitialize(egl_display, NULL, NULL);
|
2018-10-22 01:03:35 +02:00
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
if (!eglChooseConfig(egl_display, surface_attribs, &egl_config, 1, &num_configs))
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
printf("Couldn't find matching config.\n");
|
2018-10-22 01:03:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-03-02 22:25:59 +01:00
|
|
|
eglBindAPI(EGL_OPENGL_API);
|
2018-10-22 01:03:35 +02:00
|
|
|
|
2023-03-06 01:30:46 +01:00
|
|
|
std::tie(width, height) = wayland_surface->get_size();
|
|
|
|
egl_window = wl_egl_window_create(wayland_surface->child, width, height);
|
2018-10-22 01:03:35 +02:00
|
|
|
if (!egl_window)
|
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
printf("Couldn't create window.\n");
|
2018-10-22 01:03:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
egl_surface = eglCreateWindowSurface(egl_display, egl_config, (EGLNativeWindowType)egl_window, NULL);
|
2018-10-22 01:03:35 +02:00
|
|
|
if (!egl_surface)
|
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
printf("Couldn't create surface.\n");
|
2018-10-22 01:03:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, core_context_attribs);
|
2018-10-22 01:03:35 +02:00
|
|
|
if (!egl_context)
|
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, compatibility_context_attribs);
|
2018-10-28 01:13:51 +02:00
|
|
|
if (!egl_context)
|
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
printf("Couldn't create context.\n");
|
2018-10-28 01:13:51 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
void WaylandEGLContext::resize()
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2023-03-06 01:30:46 +01:00
|
|
|
wayland_surface->resize();
|
|
|
|
|
|
|
|
std::tie(width, height) = wayland_surface->get_size();
|
|
|
|
wl_egl_window_resize(egl_window, width, height, 0, 0);
|
2018-10-22 01:03:35 +02:00
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
make_current();
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
void WaylandEGLContext::swap_buffers()
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
eglSwapBuffers(egl_display, egl_surface);
|
2023-03-06 01:30:46 +01:00
|
|
|
wl_surface_commit(wayland_surface->child);
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
bool WaylandEGLContext::ready()
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
return true;
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
void WaylandEGLContext::make_current()
|
2018-10-22 01:03:35 +02:00
|
|
|
{
|
2019-03-02 22:25:59 +01:00
|
|
|
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
|
2018-10-22 01:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:25:59 +01:00
|
|
|
void WaylandEGLContext::swap_interval(int frames)
|
|
|
|
{
|
|
|
|
eglSwapInterval(egl_display, frames);
|
|
|
|
}
|