[retro-gtk/wip/aplazas/gl-display] Add RetroGLDisplay



commit 7b1f7e8263006a8021befc37081c46b87763ff3e
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Sun Oct 15 09:36:05 2017 +0200

    Add RetroGLDisplay

 meson.build                              |    3 +
 retro-gtk/meson.build                    |   11 +
 retro-gtk/retro-core-view.c              |   31 +-
 retro-gtk/retro-gl-display-fragment.glsl |    6 +
 retro-gtk/retro-gl-display-vertex.glsl   |    6 +
 retro-gtk/retro-gl-display.c             |  460 ++++++++++++++++++++++++++++++
 retro-gtk/retro-gl-display.h             |   36 +++
 retro-gtk/retro-gtk-0.14.deps            |    1 +
 retro-gtk/retro-gtk.gresource.xml        |    7 +
 9 files changed, 546 insertions(+), 15 deletions(-)
---
diff --git a/meson.build b/meson.build
index 5f560f7..d0f936d 100644
--- a/meson.build
+++ b/meson.build
@@ -3,6 +3,7 @@ project('retro-gtk','c',
   meson_version: '>= 0.43.0',
 )
 
+cc = meson.get_compiler('c')
 gnome = import('gnome')
 
 prefix = get_option('prefix')
@@ -15,12 +16,14 @@ srcinc = include_directories('retro-gtk')
 glib_version = '>= 2.50'
 gtk_version = '>= 3.22'
 
+epoxy = dependency ('epoxy')
 gio = dependency ('gio-2.0', version: glib_version)
 glib = dependency ('glib-2.0', version: glib_version)
 gmodule = dependency ('gmodule-2.0', version: glib_version)
 gobject = dependency ('gobject-2.0', version: glib_version)
 gtk = dependency ('gtk+-3.0', version: gtk_version)
 libpulse_simple = dependency ('libpulse-simple')
+m = cc.find_library('m', required : false)
 
 config_h = configuration_data()
 config_h.set_quoted ('RETRO_PLUGIN_PATH', ':'.join ([libretrodir, libdir]))
diff --git a/retro-gtk/meson.build b/retro-gtk/meson.build
index 7b86739..1a2f733 100644
--- a/retro-gtk/meson.build
+++ b/retro-gtk/meson.build
@@ -2,7 +2,15 @@ api_version = '0.14'
 
 retro_gtk_module = 'retro-gtk-' + api_version
 
+retro_gtk_resources = gnome.compile_resources(
+  'retro_gtk_resources',
+  'retro-gtk.gresource.xml',
+  c_name: 'retro_gtk',
+  source_dir: '.',
+)
+
 retro_gtk_sources = [
+  retro_gtk_resources[0],
   'retro-cairo-display.c',
   'retro-controller.c',
   'retro-controller-codes.c',
@@ -14,6 +22,7 @@ retro_gtk_sources = [
   'retro-core-view-controller.c',
   'retro-environment.c',
   'retro-game-info.c',
+  'retro-gl-display.c',
   'retro-input.c',
   'retro-input-descriptor.c',
   'retro-keyboard-key.c',
@@ -80,12 +89,14 @@ retro_gtk_c_args = [
 ]
 
 retro_gtk_deps = [
+  epoxy,
   gio,
   glib,
   gmodule,
   gobject,
   gtk,
   libpulse_simple,
+  m,
 ]
 
 retro_gtk_lib = shared_library(
diff --git a/retro-gtk/retro-core-view.c b/retro-gtk/retro-core-view.c
index 3f3f9c2..6aa2cf3 100644
--- a/retro-gtk/retro-core-view.c
+++ b/retro-gtk/retro-core-view.c
@@ -4,6 +4,7 @@
 
 #include <linux/input-event-codes.h>
 #include "retro-cairo-display.h"
+#include "retro-gl-display.h"
 #include "retro-controller-codes.h"
 #include "retro-core-view-controller.h"
 #include "retro-pa-player.h"
@@ -31,7 +32,7 @@ struct _RetroCoreView
 {
   GtkEventBox parent_instance;
   RetroCore *core;
-  RetroCairoDisplay *display;
+  RetroGLDisplay *display;
   GBinding *pixbuf_binding;
   GBinding *sensitive_binding;
   GdkPixbuf *pixbuf;
@@ -247,11 +248,11 @@ retro_core_view_on_button_press_event (GtkWidget      *source,
   else {
     set_input_pressed (self->mouse_button_state, event->button);
     self->pointer_is_on_display =
-      retro_cairo_display_get_coordinates_on_display (self->display,
-                                                      event->x,
-                                                      event->y,
-                                                      &self->pointer_x,
-                                                      &self->pointer_y);
+      retro_gl_display_get_coordinates_on_display (self->display,
+                                                   event->x,
+                                                   event->y,
+                                                   &self->pointer_x,
+                                                   &self->pointer_y);
   }
 
   return FALSE;
@@ -312,11 +313,11 @@ retro_core_view_on_motion_notify_event (GtkWidget      *source,
   }
   else {
     self->pointer_is_on_display =
-      retro_cairo_display_get_coordinates_on_display (self->display,
-                                                      event->x,
-                                                      event->y,
-                                                      &self->pointer_x,
-                                                      &self->pointer_y);
+      retro_gl_display_get_coordinates_on_display (self->display,
+                                                   event->x,
+                                                   event->y,
+                                                   &self->pointer_x,
+                                                   &self->pointer_y);
 
   }
 
@@ -488,7 +489,7 @@ retro_core_view_init (RetroCoreView *self)
 {
   g_object_set ((GtkWidget*) self, "can-focus", TRUE, NULL);
 
-  self->display = g_object_ref_sink (retro_cairo_display_new ());
+  self->display = g_object_ref_sink (retro_gl_display_new ());
   gtk_widget_set_visible (GTK_WIDGET (self->display), TRUE);
   g_object_set (GTK_WIDGET (self->display), "can-focus", FALSE, NULL);
   gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->display));
@@ -537,13 +538,13 @@ retro_core_view_set_core (RetroCoreView *self,
 
   if (self->core != NULL) {
     g_clear_object (&self->core);
-    retro_cairo_display_set_core (self->display, NULL);
+    retro_gl_display_set_core (self->display, NULL);
     retro_pa_player_set_core (self->audio_player, NULL);
   }
 
   if (core != NULL) {
     self->core = g_object_ref (core);
-    retro_cairo_display_set_core (self->display, core);
+    retro_gl_display_set_core (self->display, core);
     retro_pa_player_set_core (self->audio_player, core);
   }
 }
@@ -595,7 +596,7 @@ retro_core_view_set_filter (RetroCoreView    *self,
 {
   g_return_if_fail (RETRO_IS_CORE_VIEW (self));
 
-  retro_cairo_display_set_filter (self->display, filter);
+  retro_gl_display_set_filter (self->display, filter);
 }
 
 /**
diff --git a/retro-gtk/retro-gl-display-fragment.glsl b/retro-gtk/retro-gl-display-fragment.glsl
new file mode 100644
index 0000000..f70065a
--- /dev/null
+++ b/retro-gtk/retro-gl-display-fragment.glsl
@@ -0,0 +1,6 @@
+#version 400
+
+out vec4 frag_colour;
+void main() {
+  frag_colour = vec4(0.5, 0.0, 0.5, 1.0);
+}
diff --git a/retro-gtk/retro-gl-display-vertex.glsl b/retro-gtk/retro-gl-display-vertex.glsl
new file mode 100644
index 0000000..d2107ad
--- /dev/null
+++ b/retro-gtk/retro-gl-display-vertex.glsl
@@ -0,0 +1,6 @@
+#version 400
+
+in vec3 vp;
+void main() {
+  gl_Position = vec4(vp, 1.0);
+}
diff --git a/retro-gtk/retro-gl-display.c b/retro-gtk/retro-gl-display.c
new file mode 100644
index 0000000..2b25f25
--- /dev/null
+++ b/retro-gtk/retro-gl-display.c
@@ -0,0 +1,460 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include "retro-gl-display.h"
+
+#include <epoxy/gl.h>
+#include <math.h>
+#include "retro-pixdata.h"
+
+struct _RetroGLDisplay
+{
+  GtkGLArea parent_instance;
+  RetroCore *core;
+  GdkPixbuf *pixbuf;
+  RetroVideoFilter filter;
+  gfloat aspect_ratio;
+  gulong on_video_output_id;
+
+  GLuint shader_program;
+  GLuint framebuffer;
+};
+
+G_DEFINE_TYPE (RetroGLDisplay, retro_gl_display, GTK_TYPE_GL_AREA)
+
+enum {
+  PROP_PIXBUF = 1,
+  N_PROPS,
+};
+
+static GParamSpec *properties [N_PROPS];
+
+#define GLAREA_ERROR (glarea_error_quark ())
+
+typedef enum {
+  GLAREA_ERROR_SHADER_COMPILATION,
+  GLAREA_ERROR_SHADER_LINK
+} GlareaError;
+
+G_DEFINE_QUARK (glarea-error, glarea_error)
+
+/* Private */
+
+static void
+retro_gl_display_get_video_box (RetroGLDisplay *self,
+                                gdouble        *width,
+                                gdouble        *height,
+                                gdouble        *x,
+                                gdouble        *y)
+{
+  gdouble w;
+  gdouble h;
+  gdouble display_ratio;
+  gdouble allocated_ratio;
+
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (width != NULL);
+  g_return_if_fail (height != NULL);
+  g_return_if_fail (x != NULL);
+  g_return_if_fail (y != NULL);
+
+  w = (gdouble) gtk_widget_get_allocated_width (GTK_WIDGET (self));
+  h = (gdouble) gtk_widget_get_allocated_height (GTK_WIDGET (self));
+
+  // Set the size of the display.
+  display_ratio = (gdouble) self->aspect_ratio;
+  allocated_ratio = w / h;
+
+  // If the screen is wider than the video…
+  if (allocated_ratio > display_ratio) {
+    *height = h;
+    *width = (gdouble) (h * display_ratio);
+  }
+  else {
+    *width = w;
+    *height = (gdouble) (w / display_ratio);
+  }
+
+  // Set the position of the display.
+  *x = (w - *width) / 2;
+  *y = (h - *height) / 2;
+}
+
+static void
+retro_gl_display_realize (RetroGLDisplay *self)
+{
+  GLuint vertex_shader;
+  GLuint fragment_shader;
+  GLuint shader_program;
+  GBytes *shader_source_bytes;
+  const gchar *shader_source;
+
+  gtk_gl_area_make_current (GTK_GL_AREA (self));
+
+  // Prepare the vertex shader
+  shader_source_bytes = g_resources_lookup_data ("/org/gnome/Retro/retro-gl-display-vertex.glsl", 0, NULL);
+  shader_source = g_bytes_get_data (shader_source_bytes, NULL);
+  vertex_shader = glCreateShader (GL_VERTEX_SHADER);
+  glShaderSource (vertex_shader, 1, &shader_source, NULL);
+  glCompileShader (vertex_shader);
+  g_bytes_unref (shader_source_bytes);
+
+  // Prepare the fragment shader
+  shader_source_bytes = g_resources_lookup_data ("/org/gnome/Retro/retro-gl-display-fragment.glsl", 0, NULL);
+  shader_source = g_bytes_get_data (shader_source_bytes, NULL);
+  fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
+  glShaderSource (fragment_shader, 1, &shader_source, NULL);
+  glCompileShader (fragment_shader);
+  g_bytes_unref (shader_source_bytes);
+
+  // Prepare the shader program
+  shader_program = glCreateProgram();
+  glAttachShader (shader_program, vertex_shader);
+  glAttachShader (shader_program, fragment_shader);
+  glLinkProgram (shader_program);
+
+  self->shader_program = shader_program;
+}
+
+static void
+retro_gl_display_unrealize (RetroGLDisplay *self)
+{
+  gtk_gl_area_make_current (GTK_GL_AREA (self));
+
+  glDeleteFramebuffers (1, &self->framebuffer);
+  glDeleteProgram (self->shader_program);
+}
+
+static gboolean
+retro_gl_display_render (RetroGLDisplay *self)
+{
+  gdouble w = 0.0;
+  gdouble h = 0.0;
+  gdouble x = 0.0;
+  gdouble y = 0.0;
+  GLenum filter;
+
+  g_return_val_if_fail (self != NULL, FALSE);
+
+  retro_gl_display_get_video_box (self, &w, &h, &x, &y);
+
+  switch (self->filter) {
+  case RETRO_VIDEO_FILTER_SHARP:
+    filter = GL_NEAREST;
+
+    break;
+  default:
+  case RETRO_VIDEO_FILTER_SMOOTH:
+    filter = GL_LINEAR;
+
+    break;
+  }
+
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glUseProgram (self->shader_program);
+
+  glBindFramebuffer (GL_READ_FRAMEBUFFER, self->framebuffer);
+  glBlitFramebuffer (0, 0,
+                     gdk_pixbuf_get_width (self->pixbuf),
+                     gdk_pixbuf_get_height (self->pixbuf),
+                     (GLint) x, (GLint) (y + h), (GLint) (x + w), (GLint) y,
+                     GL_COLOR_BUFFER_BIT,
+                     filter);
+  glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
+
+  return FALSE;
+}
+
+static void
+retro_gl_display_finalize (GObject *object)
+{
+  RetroGLDisplay *self = (RetroGLDisplay *) object;
+
+  if (self->core != NULL)
+    g_object_unref (self->core);
+  if (self->pixbuf != NULL)
+    g_object_unref (self->pixbuf);
+
+  G_OBJECT_CLASS (retro_gl_display_parent_class)->finalize (object);
+}
+
+static void
+retro_gl_display_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  RetroGLDisplay *self = RETRO_GL_DISPLAY (object);
+
+  switch (prop_id) {
+  case PROP_PIXBUF:
+    g_value_set_object (value, retro_gl_display_get_pixbuf (self));
+
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+
+    break;
+  }
+}
+
+static void
+retro_gl_display_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  RetroGLDisplay *self = RETRO_GL_DISPLAY (object);
+
+  switch (prop_id) {
+  case PROP_PIXBUF:
+    retro_gl_display_set_pixbuf (self, g_value_get_object (value));
+
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+
+    break;
+  }
+}
+
+static void
+retro_gl_display_class_init (RetroGLDisplayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = retro_gl_display_finalize;
+  object_class->get_property = retro_gl_display_get_property;
+  object_class->set_property = retro_gl_display_set_property;
+
+  properties[PROP_PIXBUF] =
+    g_param_spec_object ("pixbuf",
+                         "Pixbuf",
+                         "The displayed pixbuf",
+                         gdk_pixbuf_get_type (),
+                         G_PARAM_READWRITE |
+                         G_PARAM_STATIC_NAME |
+                         G_PARAM_STATIC_NICK |
+                         G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PIXBUF, properties[PROP_PIXBUF]);
+}
+
+static void
+queue_draw (GObject    *sender,
+            GParamSpec *pspec,
+            gpointer    self)
+{
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+retro_gl_display_init (RetroGLDisplay *self)
+{
+  g_signal_connect_object (G_OBJECT (self),
+                           "realize",
+                           (GCallback) retro_gl_display_realize,
+                           GTK_WIDGET (self),
+                           0);
+
+  g_signal_connect_object (G_OBJECT (self),
+                           "unrealize",
+                           (GCallback) retro_gl_display_unrealize,
+                           GTK_WIDGET (self),
+                           0);
+
+  g_signal_connect_object (G_OBJECT (self),
+                           "render",
+                           (GCallback) retro_gl_display_render,
+                           GTK_WIDGET (self),
+                           0);
+
+  self->filter = RETRO_VIDEO_FILTER_SMOOTH;
+
+  g_signal_connect_object (G_OBJECT (self),
+                           "notify::sensitive",
+                           (GCallback) queue_draw,
+                           GTK_WIDGET (self),
+                           0);
+
+  g_signal_connect_object (G_OBJECT (self),
+                           "notify::pixbuf",
+                           (GCallback) queue_draw,
+                           GTK_WIDGET (self),
+                           0);
+}
+
+static void
+retro_gl_display_on_video_output (RetroCore    *sender,
+                                  RetroPixdata *pixdata,
+                                  gpointer      user_data)
+{
+  RetroGLDisplay *self = RETRO_GL_DISPLAY (user_data);
+
+  GdkPixbuf *pixbuf;
+
+  g_return_if_fail (self != NULL);
+
+  self->aspect_ratio = retro_pixdata_get_aspect_ratio (pixdata);
+  pixbuf = retro_pixdata_to_pixbuf (pixdata);
+  retro_gl_display_set_pixbuf (self, pixbuf);
+
+  if (pixbuf != NULL)
+    g_object_unref (pixbuf);
+}
+
+/* Public */
+
+/**
+ * retro_gl_display_set_core:
+ * @self: a #RetroGLDisplay
+ * @core: (nullable): a #RetroCore, or %NULL
+ *
+ * Sets @core as the #RetroCore displayed by @self.
+ */
+void
+retro_gl_display_set_core (RetroGLDisplay *self,
+                           RetroCore      *core)
+{
+  g_return_if_fail (self != NULL);
+
+  if (self->core == core)
+    return;
+
+  if (self->core != NULL) {
+    g_signal_handler_disconnect (G_OBJECT (self->core), self->on_video_output_id);
+    g_clear_object (&self->core);
+  }
+
+  if (core != NULL) {
+    self->core = g_object_ref (core);
+    self->on_video_output_id = g_signal_connect_object (core, "video-output", (GCallback) 
retro_gl_display_on_video_output, self, 0);
+  }
+}
+
+/**
+ * retro_gl_display_get_pixbuf:
+ * @self: a #RetroGLDisplay
+ *
+ * Gets the currently displayed video frame.
+ *
+ * Returns: (transfer none): a #GdkPixbuf
+ */
+GdkPixbuf *
+retro_gl_display_get_pixbuf (RetroGLDisplay *self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+
+  return self->pixbuf;
+}
+
+/**
+ * retro_gl_display_set_pixbuf:
+ * @self: a #RetroGLDisplay
+ * @pixbuf: a #GdkPixbuf
+ *
+ * Sets @pixbuf as the currently displayed video frame.
+ */
+void
+retro_gl_display_set_pixbuf (RetroGLDisplay *self,
+                             GdkPixbuf      *pixbuf)
+{
+  g_return_if_fail (self != NULL);
+
+  if (self->pixbuf == pixbuf)
+    return;
+
+  g_clear_object (&self->pixbuf);
+
+  if (pixbuf != NULL) {
+    self->pixbuf = g_object_ref (pixbuf);
+
+    GLuint tex = 0;
+    glGenTextures (1, &tex);
+    glBindTexture (GL_TEXTURE_2D, tex);
+
+    glTexImage2D (GL_TEXTURE_2D,
+                  0,
+                  GL_RGB,
+                  gdk_pixbuf_get_width (self->pixbuf),
+                  gdk_pixbuf_get_height (self->pixbuf),
+                  0,
+                  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
+                  gdk_pixbuf_get_pixels (self->pixbuf));
+
+    glGenFramebuffers(1, &self->framebuffer);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, self->framebuffer);
+    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                           GL_TEXTURE_2D, tex, 0);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PIXBUF]);
+}
+
+/**
+ * retro_gl_display_set_filter:
+ * @self: a #RetroGLDisplay
+ * @filter: a #RetroVideoFilter
+ *
+ * Sets the video filter to use to render the core's video on @self.
+ */
+void
+retro_gl_display_set_filter (RetroGLDisplay   *self,
+                             RetroVideoFilter  filter)
+{
+  g_return_if_fail (self != NULL);
+
+  self->filter = filter;
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+/**
+ * retro_gl_display_get_coordinates_on_display:
+ * @self: a #RetroGLDisplay
+ * @widget_x: the abscissa on @self
+ * @widget_y: the ordinate on @self
+ * @display_x: return location for a the abscissa on the core's video display
+ * @display_y: return location for a the ordinate on the core's video display
+ *
+ * Gets coordinates on the core's video output from coordinates on @self, and
+ * whether the point is inside the core's video display.
+ *
+ * Returns: whether the coordinates are on the core's video display
+ */
+gboolean
+retro_gl_display_get_coordinates_on_display (RetroGLDisplay *self,
+                                             gdouble         widget_x,
+                                             gdouble         widget_y,
+                                             gdouble        *display_x,
+                                             gdouble        *display_y)
+{
+  gdouble w = 0.0;
+  gdouble h = 0.0;
+  gdouble x = 0.0;
+  gdouble y = 0.0;
+
+  g_return_val_if_fail (self != NULL, FALSE);
+  g_return_val_if_fail (display_x != NULL, FALSE);
+  g_return_val_if_fail (display_y != NULL, FALSE);
+
+  retro_gl_display_get_video_box (self, &w, &h, &x, &y);
+
+  // Return coordinates as a [-1.0, 1.0] scale, (0.0, 0.0) is the center.
+  *display_x = ((widget_x - x) * 2.0 - w) / w;
+  *display_y = ((widget_y - y) * 2.0 - h) / h;
+
+  return (-1.0 <= *display_x) && (*display_x <= 1.0) &&
+         (-1.0 <= *display_y) && (*display_y <= 1.0);
+}
+
+/**
+ * retro_gl_display_new:
+ *
+ * Creates a new #RetroGLDisplay.
+ *
+ * Returns: (transfer full): a new #RetroGLDisplay
+ */
+RetroGLDisplay *
+retro_gl_display_new (void)
+{
+  return g_object_new (RETRO_TYPE_GL_DISPLAY, NULL);
+}
diff --git a/retro-gtk/retro-gl-display.h b/retro-gtk/retro-gl-display.h
new file mode 100644
index 0000000..2a0b1c7
--- /dev/null
+++ b/retro-gtk/retro-gl-display.h
@@ -0,0 +1,36 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#ifndef RETRO_GL_DISPLAY_H
+#define RETRO_GL_DISPLAY_H
+
+#if !defined(__RETRO_GTK_INSIDE__) && !defined(RETRO_GTK_COMPILATION)
+# error "Only <retro-gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+#include "retro-core.h"
+#include "retro-video-filter.h"
+
+G_BEGIN_DECLS
+
+#define RETRO_TYPE_GL_DISPLAY (retro_gl_display_get_type())
+
+G_DECLARE_FINAL_TYPE (RetroGLDisplay, retro_gl_display, RETRO, GL_DISPLAY, GtkGLArea)
+
+RetroGLDisplay *retro_gl_display_new (void);
+GdkPixbuf *retro_gl_display_get_pixbuf (RetroGLDisplay *self);
+void retro_gl_display_set_pixbuf (RetroGLDisplay *self,
+                                  GdkPixbuf      *pixbuf);
+void retro_gl_display_set_core (RetroGLDisplay *self,
+                                RetroCore      *core);
+void retro_gl_display_set_filter (RetroGLDisplay   *self,
+                                  RetroVideoFilter  filter);
+gboolean retro_gl_display_get_coordinates_on_display (RetroGLDisplay *self,
+                                                      gdouble         widget_x,
+                                                      gdouble         widget_y,
+                                                      gdouble        *display_x,
+                                                      gdouble        *display_y);
+
+G_END_DECLS
+
+#endif /* RETRO_GL_DISPLAY_H */
diff --git a/retro-gtk/retro-gtk-0.14.deps b/retro-gtk/retro-gtk-0.14.deps
index ec2cb16..2fc8f4c 100644
--- a/retro-gtk/retro-gtk-0.14.deps
+++ b/retro-gtk/retro-gtk-0.14.deps
@@ -1,5 +1,6 @@
 
 cairo
+epoxy
 gio-2.0
 glib-2.0
 gmodule-2.0
diff --git a/retro-gtk/retro-gtk.gresource.xml b/retro-gtk/retro-gtk.gresource.xml
new file mode 100644
index 0000000..e9a9c5f
--- /dev/null
+++ b/retro-gtk/retro-gtk.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/Retro">
+    <file>retro-gl-display-fragment.glsl</file>
+    <file>retro-gl-display-vertex.glsl</file>
+  </gresource>
+</gresources>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]