gegl/0002-Port-sdl-display-to-SDL2.patch

264 lines
7.5 KiB
Diff

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