[retro-gtk] retro-gtk: Refactor video format conversion
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk] retro-gtk: Refactor video format conversion
- Date: Wed, 8 Feb 2017 14:58:23 +0000 (UTC)
commit 00e8d562b2e0e98882cb704874a71ee7f91c9ca9
Author: Adrien Plazas <kekun plazas laposte net>
Date: Wed Feb 8 09:48:51 2017 +0100
retro-gtk: Refactor video format conversion
Completely refactor video-converter.c to make it more readable,
maintainable and hopefully slightly faster.
https://bugzilla.gnome.org/show_bug.cgi?id=777489
retro-gobject/video.vala | 2 +-
retro-gtk/Makefile.am | 3 +-
retro-gtk/video/cairo-display.vala | 6 +-
retro-gtk/video/retro-video-converter.c | 161 +++++++++++++++++++++++++++++++
retro-gtk/video/video-converter.c | 150 ----------------------------
retro-gtk/video/video-converter.h | 22 ----
6 files changed, 166 insertions(+), 178 deletions(-)
---
diff --git a/retro-gobject/video.vala b/retro-gobject/video.vala
index a6da3cb..2366e9b 100644
--- a/retro-gobject/video.vala
+++ b/retro-gobject/video.vala
@@ -23,7 +23,7 @@ public enum PixelFormat {
* This pixel format is default for compatibility concerns only.
* If a 15/16-bit pixel format is desired, consider using RGB565.
*/
- ORGB1555,
+ XRGB1555,
/**
* XRGB8888, native endian. X bits are ignored.
diff --git a/retro-gtk/Makefile.am b/retro-gtk/Makefile.am
index e4d9eac..a592d7e 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -37,8 +37,7 @@ libretro_gtk_la_SOURCES = \
input/virtual-gamepad.vala \
\
video/cairo-display.vala \
- video/video-converter.c \
- video/video-converter.h \
+ video/retro-video-converter.c \
$(NULL)
libretro_gtk_la_LDFLAGS =
diff --git a/retro-gtk/video/cairo-display.vala b/retro-gtk/video/cairo-display.vala
index c8a7843..a8608cc 100644
--- a/retro-gtk/video/cairo-display.vala
+++ b/retro-gtk/video/cairo-display.vala
@@ -15,8 +15,8 @@ public class RetroGtk.CairoDisplay : Gtk.DrawingArea {
notify["pixbuf"].connect (queue_draw);
}
- [CCode (cname = "video_to_pixbuf", cheader_filename="video-converter.h")]
- static extern Gdk.Pixbuf video_to_pixbuf ([CCode (array_length = false)] uint8[] data, uint width,
uint height, size_t pitch, Retro.PixelFormat pixel_format);
+ [CCode (cname = "gdk_pixbuf_new_from_video")]
+ static extern Gdk.Pixbuf gdk_pixbuf_new_from_video ([CCode (array_length = false)] uint8[] data, uint
width, uint height, size_t pitch, Retro.PixelFormat pixel_format);
public void set_core (Retro.Core core) {
if (this.core != null)
@@ -28,7 +28,7 @@ public class RetroGtk.CairoDisplay : Gtk.DrawingArea {
private void on_video_output (uint8[] data, uint width, uint height, size_t pitch, Retro.PixelFormat
pixel_format, float aspect_ratio) {
this.aspect_ratio = aspect_ratio;
- pixbuf = video_to_pixbuf (data, width, height, pitch, pixel_format);
+ pixbuf = gdk_pixbuf_new_from_video (data, width, height, pitch, pixel_format);
}
public void show_video () {
diff --git a/retro-gtk/video/retro-video-converter.c b/retro-gtk/video/retro-video-converter.c
new file mode 100644
index 0000000..ebb7a31
--- /dev/null
+++ b/retro-gtk/video/retro-video-converter.c
@@ -0,0 +1,161 @@
+// This file is part of RetroGtk. License: GPLv3
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <retro-gobject.h>
+
+typedef struct _xrgb1555 xrgb1555;
+struct _xrgb1555 {
+ guint16 b: 5;
+ guint16 g: 5;
+ guint16 r: 5;
+ guint16 x: 1;
+};
+
+typedef struct _xrgb8888 xrgb8888;
+struct _xrgb8888 {
+ guint32 b: 8;
+ guint32 g: 8;
+ guint32 r: 8;
+ guint32 x: 8;
+};
+
+typedef struct _rgb565 rgb565;
+struct _rgb565 {
+ guint16 b: 5;
+ guint16 g: 6;
+ guint16 r: 5;
+};
+
+typedef struct _rgba8888 rgba8888;
+struct _rgba8888 {
+ guint32 a: 8;
+ guint32 b: 8;
+ guint32 g: 8;
+ guint32 r: 8;
+};
+
+typedef rgba8888 (*GetRGBA8888) (const gpointer pixel);
+
+static rgba8888
+rgba8888_from_xrgb1555 (const gpointer data)
+{
+ xrgb1555 pixel = *(const xrgb1555 *) data;
+
+ return (rgba8888) { pixel.r << 3 | pixel.r >> 2, pixel.g << 3 | pixel.g >> 2, pixel.b << 3 | pixel.b >> 2,
0xff };
+}
+
+static rgba8888
+rgba8888_from_xrgb8888 (const gpointer data)
+{
+ xrgb8888 pixel = *(const xrgb8888 *) data;
+
+ return (rgba8888) { pixel.r, pixel.g, pixel.b, 0xff };
+}
+
+static rgba8888
+rgba8888_from_rgb565 (const gpointer data)
+{
+ rgb565 pixel = *(const rgb565 *) data;
+
+ return (rgba8888) { pixel.r << 3 | pixel.r >> 2, pixel.g << 2 | pixel.g >> 4, pixel.b << 3 | pixel.b >> 2,
0xff };
+}
+
+static gboolean
+get_interface_for_pixel_format (gint pixel_format,
+ GetRGBA8888 *get_pixel,
+ gsize *pixel_size)
+{
+ switch (pixel_format) {
+ case RETRO_PIXEL_FORMAT_XRGB1555:
+ *get_pixel = rgba8888_from_xrgb1555;
+ *pixel_size = sizeof (xrgb1555);
+
+ return TRUE;
+ case RETRO_PIXEL_FORMAT_XRGB8888:
+ *get_pixel = rgba8888_from_xrgb8888;
+ *pixel_size = sizeof (rgba8888);
+
+ return TRUE;
+ case RETRO_PIXEL_FORMAT_RGB565:
+ *get_pixel = rgba8888_from_rgb565;
+ *pixel_size = sizeof (rgb565);
+
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ * The destination buffer must be at least 'height * width * sizeof (rgba8888)' bytes long.
+ */
+static void
+rgba8888_from_video (const gpointer src,
+ rgba8888 *dst,
+ size_t pixel_size,
+ guint width,
+ guint height,
+ gsize pitch,
+ GetRGBA8888 get_pixel)
+{
+ gsize row, src_row, dst_row, col, src_col;
+
+ for (row = 0 ; row < height ; row++) {
+ src_row = row * pitch;
+ dst_row = row * width;
+
+ for (col = 0 ; col < width ; col++) {
+ src_col = col * pixel_size;
+
+ dst[dst_row + col] = get_pixel (src_row + src_col + src);
+ }
+ }
+}
+
+static rgba8888 *
+new_rgba8888_from_video (const gpointer src,
+ guint width,
+ guint height,
+ gsize pitch,
+ gint pixel_format)
+{
+ GetRGBA8888 get_pixel;
+ gsize pixel_size;
+ rgba8888 *dst;
+
+ if (!get_interface_for_pixel_format (pixel_format, &get_pixel, &pixel_size))
+ return NULL;
+
+ dst = g_new (rgba8888, height * width);
+ rgba8888_from_video (src, dst, pixel_size, width, height, pitch, get_pixel);
+
+ return dst;
+}
+
+static void
+pixels_free (guchar *pixels, gpointer data) {
+ g_free (pixels);
+}
+
+GdkPixbuf *
+gdk_pixbuf_new_from_video (const gpointer src,
+ guint width,
+ guint height,
+ gsize pitch,
+ gint pixel_format)
+{
+ rgba8888 *dst;
+
+ dst = new_rgba8888_from_video (src, width, height, pitch, pixel_format);
+ if (dst == NULL)
+ return NULL;
+
+ GdkColorspace colorspace = GDK_COLORSPACE_RGB;
+ gboolean has_alpha = TRUE;
+ gint bits_per_sample = 8;
+ gint rowstride = width * sizeof (rgba8888);
+
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data ((guchar *) dst, colorspace, has_alpha, bits_per_sample, width,
height, rowstride, pixels_free, NULL);
+
+ return pb;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]