[retro-gtk] retro-core: Implement RETRO_ENVIRONMENT_SET_HW_RENDER



commit 71d106405ea69f3b8e55c6650b22fcf2c98845ee
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Fri Jan 31 22:49:15 2020 +0500

    retro-core: Implement RETRO_ENVIRONMENT_SET_HW_RENDER
    
    Use RetroGLRenderer to support hardware rendering for OpenGL.

 retro-runner/retro-core-private.h |  2 +
 retro-runner/retro-core.c         |  5 +++
 retro-runner/retro-environment.c  | 80 +++++++++++++++++++++++++++++++++++++--
 3 files changed, 84 insertions(+), 3 deletions(-)
---
diff --git a/retro-runner/retro-core-private.h b/retro-runner/retro-core-private.h
index 435010b..34b2c33 100644
--- a/retro-runner/retro-core-private.h
+++ b/retro-runner/retro-core-private.h
@@ -14,6 +14,7 @@
 #include "retro-input-descriptor-private.h"
 #include "retro-module-private.h"
 #include "retro-pixel-format-private.h"
+#include "retro-renderer-private.h"
 #include "retro-rotation-private.h"
 #include "retro-variable-private.h"
 
@@ -47,6 +48,7 @@ struct _RetroCore
   gdouble sample_rate;
 
   RetroFramebuffer *framebuffer;
+  RetroRenderer *renderer;
   RetroKeyboardCallback keyboard_callback;
   RetroControllerState *default_controller;
   GHashTable *controllers;
diff --git a/retro-runner/retro-core.c b/retro-runner/retro-core.c
index 80f5d6a..4bb01d6 100644
--- a/retro-runner/retro-core.c
+++ b/retro-runner/retro-core.c
@@ -132,6 +132,7 @@ retro_core_finalize (GObject *object)
   g_free (self->libretro_path);
   g_free (self->content_directory);
   g_free (self->save_directory);
+  g_clear_object (&self->renderer);
 
   G_OBJECT_CLASS (retro_core_parent_class)->finalize (object);
 }
@@ -918,6 +919,8 @@ load_game (RetroCore     *self,
   get_system_av_info = retro_module_get_get_system_av_info (self->module);
   get_system_av_info (&info);
   retro_core_set_system_av_info (self, &info);
+  if (self->renderer)
+    retro_renderer_realize (self->renderer, info.geometry.max_width, info.geometry.max_height);
 
   return game_loaded;
 }
@@ -935,6 +938,8 @@ prepare (RetroCore *self) {
   get_system_av_info = retro_module_get_get_system_av_info (self->module);
   get_system_av_info (&info);
   retro_core_set_system_av_info (self, &info);
+  if (self->renderer)
+    retro_renderer_realize (self->renderer, info.geometry.max_width, info.geometry.max_height);
 
   return game_loaded;
 }
diff --git a/retro-runner/retro-environment.c b/retro-runner/retro-environment.c
index 409f351..ac22075 100644
--- a/retro-runner/retro-environment.c
+++ b/retro-runner/retro-environment.c
@@ -4,6 +4,8 @@
 
 #include <stdbool.h>
 #include "retro-input-private.h"
+#include "retro-gl-renderer-private.h"
+#include "retro-hw-render-callback-private.h"
 #include "retro-rumble-effect.h"
 
 #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000
@@ -303,6 +305,51 @@ get_variable_update (RetroCore *self,
   return TRUE;
 }
 
+static RetroProcAddress
+hw_rendering_callback_get_proc_address (const gchar *sym)
+{
+  RetroCore *self = retro_core_get_instance ();
+
+  return retro_renderer_get_proc_address (self->renderer, sym);
+}
+
+static guintptr
+hw_rendering_callback_get_current_framebuffer ()
+{
+  RetroCore *self = retro_core_get_instance ();
+
+  return retro_renderer_get_current_framebuffer (self->renderer);
+}
+
+static gboolean
+set_hw_render (RetroCore             *self,
+               RetroHWRenderCallback *callback)
+{
+  switch (callback->context_type) {
+  case RETRO_HW_CONTEXT_OPENGL:
+  case RETRO_HW_CONTEXT_OPENGL_CORE:
+  case RETRO_HW_CONTEXT_OPENGLES2:
+  case RETRO_HW_CONTEXT_OPENGLES3:
+  case RETRO_HW_CONTEXT_OPENGLES_VERSION:
+    self->renderer = retro_gl_renderer_new (self, callback);
+    break;
+
+  case RETRO_HW_CONTEXT_VULKAN:
+    g_critical ("Vulkan support isn't implemented");
+
+    return FALSE;
+  default:
+    g_critical ("Unknown context type: %d", callback->context_type);
+
+    return FALSE;
+  }
+
+  callback->get_current_framebuffer = hw_rendering_callback_get_current_framebuffer;
+  callback->get_proc_address = hw_rendering_callback_get_proc_address;
+
+  return TRUE;
+}
+
 static gboolean
 set_disk_control_interface (RetroCore                *self,
                             RetroDiskControlCallback *callback)
@@ -460,6 +507,9 @@ environment_core_command (RetroCore *self,
   case RETRO_ENVIRONMENT_SET_GEOMETRY:
     return set_geometry (self, (RetroGameGeometry *) data);
 
+  case RETRO_ENVIRONMENT_SET_HW_RENDER:
+    return set_hw_render (self, (RetroHWRenderCallback *) data);
+
   case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS:
     return set_input_descriptors (self, (RetroInputDescriptor *) data);
 
@@ -497,7 +547,6 @@ environment_core_command (RetroCore *self,
   case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK:
   case RETRO_ENVIRONMENT_SET_CONTROLLER_INFO:
   case RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK:
-  case RETRO_ENVIRONMENT_SET_HW_RENDER:
   case RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE:
   case RETRO_ENVIRONMENT_SET_MEMORY_MAPS:
   case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL:
@@ -536,8 +585,33 @@ video_refresh_cb (guint8 *data,
     return;
 
   retro_framebuffer_lock (self->framebuffer);
-  retro_framebuffer_set_data (self->framebuffer, self->pixel_format, pitch,
-                              width, height, self->aspect_ratio, data);
+
+  if (self->renderer) {
+    gint pixel_size;
+
+    if (data && data != RETRO_HW_FRAME_BUFFER_VALID) {
+      g_critical ("Video data must be NULL or RETRO_HW_FRAME_BUFFER_VALID if "
+                  "rendering to hardware.");
+
+      return;
+    }
+
+    if (!retro_pixel_format_to_gl (self->pixel_format, NULL, NULL, &pixel_size))
+      return;
+
+    pitch = width * pixel_size;
+
+    retro_framebuffer_set_data (self->framebuffer, self->pixel_format, pitch,
+                                width, height, self->aspect_ratio, NULL);
+
+    data = retro_framebuffer_get_pixels (self->framebuffer);
+
+    retro_renderer_snapshot (self->renderer, self->pixel_format, width, height, pitch, data);
+  }
+  else
+    retro_framebuffer_set_data (self->framebuffer, self->pixel_format, pitch,
+                                width, height, self->aspect_ratio, data);
+
   retro_framebuffer_unlock (self->framebuffer);
 
   if (!self->block_video_signal)


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