File 0002-Port-sdl-display-to-SDL2.patch of Package gegl

From c07813452c658f1f441b104fbe836380a6ddd18d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
Date: Sun, 4 Aug 2019 01:22:01 +0200
Subject: [PATCH 2/3] Port sdl-display to SDL2

The SDL2 Video API is split into several orthogonal parts, see
https://wiki.libsdl.org/MigrationGuide#Video.

Fixes half of #184
---
 operations/common/display.c        |   1 +
 operations/external/Makefile.am    |   6 +
 operations/external/sdl2-display.c | 209 +++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+)
 create mode 100644 operations/external/sdl2-display.c

diff --git a/operations/common/display.c b/operations/common/display.c
index 826ae4caa..9e06f1eb5 100644
--- a/operations/common/display.c
+++ b/operations/common/display.c
@@ -60,6 +60,7 @@ set_display_handler (GeglOperation *operation)
   GeglOp   *self = GEGL_OP (operation);
   const gchar *known_handlers[] = {"gegl-gtk3:display", 
                                    "gegl-gtk2:display",
+                                   "gegl:sdl2-display",
                                    "gegl:sdl-display"};
   char *handler = NULL;
   gchar **operations = NULL;
diff --git a/operations/external/Makefile.am b/operations/external/Makefile.am
index 498ffb062..719698401 100644
--- a/operations/external/Makefile.am
+++ b/operations/external/Makefile.am
@@ -81,6 +81,12 @@ exr_save_la_LIBADD = $(op_libs) $(OPENEXR_LIBS)
 exr_save_la_CXXFLAGS = $(AM_CFLAGS) $(OPENEXR_CFLAGS)
 endif
 
+if HAVE_SDL2
+ops += sdl2-display.la
+sdl2_display_la_LIBADD = $(op_libs) $(SDL2_LIBS)
+sdl2_display_la_CFLAGS = $(AM_CFLAGS) $(SDL2_CFLAGS)
+endif
+
 if HAVE_SDL
 ops += sdl-display.la
 sdl_display_la_LIBADD = $(op_libs) $(SDL_LIBS)
diff --git a/operations/external/sdl2-display.c b/operations/external/sdl2-display.c
new file mode 100644
index 000000000..a3bab50a5
--- /dev/null
+++ b/operations/external/sdl2-display.c
@@ -0,0 +1,209 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * Copyright 2019 Stefan Brüns <stefan.bruens@rwth-aachen.de>
+ *
+ * Based on sdl-display.c:
+ * Copyright 2006 Øyvind Kolås <pippin@gimp.org>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+
+#ifdef GEGL_PROPERTIES
+
+property_string (window_title, _("Window title"), "window_title")
+    description (_("Title to be given to output window"))
+#else
+
+#define GEGL_OP_SINK
+#define GEGL_OP_NAME sdl2_display
+#define GEGL_OP_C_SOURCE sdl2-display.c
+
+#include "gegl-op.h"
+#include <SDL.h>
+
+typedef struct {
+  SDL_Window   *window;
+  SDL_Renderer *renderer;
+  SDL_Texture  *texture;
+  SDL_Surface  *screen;
+  gint         width;
+  gint         height;
+} SDLState;
+
+static void
+init_sdl (void)
+{
+  static int inited = 0;
+
+  if (!inited)
+    {
+      inited = 1;
+
+      if (SDL_Init (SDL_INIT_VIDEO) < 0)
+        {
+          fprintf (stderr, "Unable to init SDL: %s\n", SDL_GetError ());
+          return;
+        }
+      atexit (SDL_Quit);
+    }
+}
+
+static gboolean idle (gpointer data)
+{
+  SDL_Event event;
+  while (SDL_PollEvent  (&event))
+    {
+      switch (event.type)
+        {
+          case SDL_QUIT:
+            exit (0);
+        }
+    }
+  return TRUE;
+}
+
+static guint handle = 0;
+
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *input,
+         const GeglRectangle *result,
+         gint                 level)
+{
+  GeglProperties   *o = GEGL_PROPERTIES (operation);
+  SDLState     *state = NULL;
+
+  if(!o->user_data)
+      o->user_data = g_new0 (SDLState, 1);
+  state = o->user_data;
+
+  init_sdl ();
+
+  if (!handle)
+    handle = g_timeout_add (500, idle, NULL);
+
+  if (!state->window ||
+       state->width  != result->width ||
+       state->height != result->height)
+    {
+
+      if (state->window)
+        {
+          SDL_SetWindowSize (state->window,
+                  result->width, result->height);
+        }
+        else
+        {
+          if (SDL_CreateWindowAndRenderer (result->width,
+                  result->height, 0,
+                  &state->window, &state->renderer))
+            {
+              fprintf (stderr, "Unable to create window: %s\n",
+                       SDL_GetError ());
+              return -1;
+            }
+        }
+
+      SDL_FreeSurface (state->screen);
+      state->screen = SDL_CreateRGBSurfaceWithFormat (0,
+              result->width, result->height, 32, SDL_PIXELFORMAT_RGBA32);
+      if (!state->screen)
+        {
+          fprintf (stderr, "Unable to create surface: %s\n",
+                   SDL_GetError ());
+          return -1;
+        }
+
+      if (state->texture)
+        SDL_DestroyTexture (state->texture);
+      state->texture = SDL_CreateTextureFromSurface (state->renderer, state->screen);
+      if (!state->texture)
+        {
+          fprintf (stderr, "Unable to create texture: %s\n",
+                   SDL_GetError ());
+          return -1;
+        }
+
+      state->width  = result->width ;
+      state->height = result->height;
+    }
+
+  /*
+   * There seems to be a valid faster path to the SDL desired display format
+   * in B'G'R'A, perhaps babl should have been able to figure this out ito?
+   *
+   */
+  gegl_buffer_get (input,
+       NULL,
+       1.0,
+       babl_format_new (babl_model ("R'G'B'A"),
+                        babl_type ("u8"),
+                        babl_component ("B'"),
+                        babl_component ("G'"),
+                        babl_component ("R'"),
+                        babl_component ("A"),
+                        NULL),
+       state->screen->pixels, GEGL_AUTO_ROWSTRIDE,
+       GEGL_ABYSS_NONE);
+
+  SDL_UpdateTexture (state->texture, NULL, state->screen->pixels, state->screen->pitch);
+
+  SDL_RenderClear (state->renderer);
+  SDL_RenderCopy (state->renderer, state->texture, NULL, NULL);
+  SDL_RenderPresent (state->renderer);
+  SDL_SetWindowTitle (state->window, o->window_title);
+
+  return  TRUE;
+}
+
+static void
+finalize (GObject *object)
+{
+  GeglProperties *o = GEGL_PROPERTIES (object);
+
+  g_clear_pointer (&o->user_data, g_free);
+
+  G_OBJECT_CLASS (gegl_op_parent_class)->finalize (object);
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+  GObjectClass           *object_class;
+  GeglOperationClass     *operation_class;
+  GeglOperationSinkClass *sink_class;
+
+  object_class    = G_OBJECT_CLASS (klass);
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  sink_class      = GEGL_OPERATION_SINK_CLASS (klass);
+
+  object_class->finalize = finalize;
+
+  sink_class->process = process;
+  sink_class->needs_full = TRUE;
+
+  gegl_operation_class_set_keys (operation_class,
+    "name",         "gegl:sdl2-display",
+    "title",        _("SDL2 Display"),
+    "categories",   "display",
+    "description",
+        _("Displays the input buffer in an SDL2 window (restricted to one"
+          " display op/process, due to SDL2 implementation issues)."),
+        NULL);
+}
+#endif
-- 
2.22.0