Index: [thread] [date] [subject] [author]
  From: Aki M Laukkanen <amlaukka@cc.helsinki.fi>
  To  : ggi-develop@eskimo.com
  Date: Sun, 20 Jun 1999 18:39:42 +0300 (EET DST)

RFC: Integration of HERMES with LibGGI

Hello, being bored on sunday afternoon I decided to try to integrate
HERMES to LibGGI. HERMES is a pixel format conversion library and
you can find more about it at:

http://hermes.terminal.at/

The following patch replaces the default ggiCrossBlit() implementation
when it thinks that the conversion could be done with HERMES. This is
the very first working version and I've only tested the conversion from
8bit memory target to 24bit X target. I did some benchmarks but forgot
to save the results from the LibGGI only implementation so I can't give
you exact results. There was some speed gain as expected since the 
HERMES routines are in optimized assembly. Comments?

PS. I only included the minimal patch and you need to rerun
automake/autoconf to build the source. Building with HERMES is enabled
by specifying a new configure option "--with-hermes[=DIR]".

diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/acconfig.h libggi-HERMES/acconfig.h
--- libggi-2.0b2.1/acconfig.h	Sun May  9 03:16:23 1999
+++ libggi-HERMES/acconfig.h	Fri Jun 18 20:31:53 1999
@@ -13,6 +13,9 @@
 /* Define to use run-time debugging */
 #undef DEBUG
 
+/* Define when compiling with HERMES */
+#undef USE_HERMES
+
 /* Define if you have the <ncurses.h> header file.  */
 #undef HAVE_NCURSES_H
 
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/config.h.in libggi-HERMES/config.h.in
--- libggi-2.0b2.1/config.h.in	Sun May  9 03:17:12 1999
+++ libggi-HERMES/config.h.in	Fri Jun 18 20:35:30 1999
@@ -64,6 +64,9 @@
 /* Define to use run-time debugging */
 #undef DEBUG
 
+/* Define when compiling with HERMES */
+#undef USE_HERMES
+
 /* Define if you have the <ncurses.h> header file.  */
 #undef HAVE_NCURSES_H
 
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/configure.in libggi-HERMES/configure.in
--- libggi-2.0b2.1/configure.in	Fri May 14 21:59:24 1999
+++ libggi-HERMES/configure.in	Fri Jun 18 20:38:00 1999
@@ -21,7 +21,11 @@
 use_debug="yes"
 
 use_threads="no"
+
+use_hermes="no"
+
 THREADLIBS=""
+HERMESLIBS=""
 
 sublib_libs=""
 dynload_libs="-lgii -lgg"
@@ -156,6 +160,16 @@
 [  --disable-debug         don't build with run-time debugging (speed freaks)],
 use_debug=$enableval)
 
+AC_ARG_WITH(hermes,
+[  --with-hermes[=DIR]     use the HERMES pixel format conversion library],
+use_hermes="yes"
+if test $withval != "yes"; then
+  CFLAGS="$CFLAGS -I$withval/include"
+  CPPFLAGS="$CPPFLAGS -I$withval/include"
+  LDFLAGS="$LDFLAGS -L$withval/lib"
+fi)
+
+
 GGI_EXTRA_PATHS
 
 
@@ -294,6 +308,23 @@
   fi
 fi
 
+have_hermes="no"
+if test "x$use_hermes" != "xno"; then
+  AC_MSG_CHECKING(for HERMES library)
+  TMP_SAVE_LIBS=$LIBS
+  LIBS="$LIBS -lHermes"
+  AC_TRY_LINK([
+#include <Hermes/Hermes.h>
+],[
+Hermes_Init()
+],
+    have_hermes="yes"
+    AC_MSG_RESULT(yes),
+    use_hermes="no"
+    AC_MSG_RESULT(no)
+  LIBS=$TMP_SAVE_LIBS)
+fi
+
 if test "x$build_aa_target" != "xno"; then
   AC_CHECK_HEADER(aalib.h,
 	AC_CHECK_LIB(aa, aa_autoinit, foo=bar, build_aa_target="no"),
@@ -630,6 +661,7 @@
 
 AC_SUBST(DLLEXT)
 AC_SUBST(THREADLIBS)
+AC_SUBST(HERMESLIBS)
 AC_SUBST(sublib_libs)
 AC_SUBST(dynload_libs)
 
@@ -668,6 +700,11 @@
 
 if test "x$use_debug" = "xyes"; then
   AC_DEFINE(DEBUG)
+fi
+
+if test "x$use_hermes" = "xyes"; then
+  AC_DEFINE(USE_HERMES)
+  HERMESLIBS="-lHermes"
 fi
 
 AM_CONFIG_HEADER(config.h)
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/display/fbdev/fbdev.conf libggi-HERMES/display/fbdev/fbdev.conf
--- libggi-2.0b2.1/display/fbdev/fbdev.conf	Thu Jan  1 02:00:00 1970
+++ libggi-HERMES/display/fbdev/fbdev.conf	Sun Jun 20 17:48:06 1999
@@ -0,0 +1,10 @@
+# Mapping file for config-strings to accel libraries
+# config-name			library_name
+# ------------			--------------------------
+
+# Native drivers
+tgt-fbdev-mga-2164w		default/fbdev/mga/m2164w.so
+
+
+# KGIcon drivers
+tgt-fbdev-kgicon-generic	default/fbdev/kgi/genkgi.so
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/Makefile.am libggi-HERMES/ggi/Makefile.am
--- libggi-2.0b2.1/ggi/Makefile.am	Thu Apr  1 03:38:55 1999
+++ libggi-HERMES/ggi/Makefile.am	Sun Jun 20 16:48:38 1999
@@ -5,6 +5,6 @@
 libggi_la_SOURCES = db.c dl.c events.c gc.c init.c internal.c mode.c stubs.c \
 		visual.c unix.c
 libggi_la_LDFLAGS = ${extra_libraries} -version-info 2:0
-libggi_la_LIBADD = -lgii -lgg
+libggi_la_LIBADD = -lgii -lgg ${HERMESLIBS}
 
 EXTRA_DIST = EXPSYMS
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/dl.c libggi-HERMES/ggi/dl.c
--- libggi-2.0b2.1/ggi/dl.c	Thu Apr  1 18:22:10 1999
+++ libggi-HERMES/ggi/dl.c	Wed Jun 16 17:19:03 1999
@@ -119,7 +119,7 @@
 	const char *filename;
 	int err;
 
-	GGIDPRINT_LIBS("_ggiAddDL(%p, \"%s\", \"%s\", 0x%x) called\n",
+	fprintf(stderr, "_ggiAddDL(%p, \"%s\", \"%s\", 0x%x) called\n",
 		       vis, name, args ? args : "(null)", type);
 
 	if ((filename = ggMatchConfig(_ggiConfigHandle, name, NULL)) == NULL) {
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/init.c libggi-HERMES/ggi/init.c
--- libggi-2.0b2.1/ggi/init.c	Fri Mar 19 02:16:13 1999
+++ libggi-HERMES/ggi/init.c	Sun Jun 20 17:19:50 1999
@@ -35,6 +35,10 @@
 #include <ggi/internal/internal.h>
 #include <ggi/gg.h>
 
+#ifdef USE_HERMES
+#include <Hermes/Hermes.h>
+#endif /* USE_HERMES */
+
 /* Global variables */
 uint32                _ggiDebugState = 0;
 int                   _ggiDebugSync = 0;
@@ -72,6 +76,14 @@
 		return err;
 	}
 
+#ifdef USE_HERMES
+	err = Hermes_Init();
+	if (!err) {
+		fprintf(stderr, "LibGGI: unable to initialize HERMES\n");
+		return GGI_EUNKNOWN;
+	}
+#endif /* USE_HERMES */
+
 	if ((_ggiVisuals.mutex = ggLockCreate()) == NULL) {
 		fprintf(stderr, "LibGGI: unable to initialize core mutex.\n");
 		giiExit();
@@ -140,6 +152,9 @@
 	}
 
 	ggFreeConfig(_ggiConfigHandle);
+#ifdef USE_HERMES
+	Hermes_Done();
+#endif /* USE_HERMES */
 	giiExit();
 	_ggiLibIsUp = 0;
 
@@ -341,6 +356,22 @@
 			return NULL;
 		}
 	}
+
+#ifdef USE_HERMES
+	vis->conv_inst = Hermes_ConverterInstance(HERMES_CONVERT_NORMAL);
+	if (!vis->conv_inst) {
+		GGIDPRINT_CORE("Cannot get a HERMES converter instance\n");
+		ggiClose(vis);
+		return NULL;
+	}
+
+	vis->pal_inst = Hermes_PaletteInstance();
+	if (!vis->pal_inst) {
+		GGIDPRINT_CORE("Cannot get a HERMES palette instance\n");
+		ggiClose(vis);
+		return NULL;
+	}
+#endif /* USE_HERMES */
 	
 	return vis;
 }
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/internal.c libggi-HERMES/ggi/internal.c
--- libggi-2.0b2.1/ggi/internal.c	Mon May 17 10:39:46 1999
+++ libggi-HERMES/ggi/internal.c	Sun Jun 20 18:10:11 1999
@@ -27,6 +27,37 @@
 
 #include <ggi/internal/internal.h>
 
+#ifdef USE_HERMES
+#include <Hermes/Hermes.h>
+
+void _ggi_set_hermes_palette(ggi_visual *vis)
+{
+	ggi_color *src;
+	int32 *iter;
+	int nocols;
+
+	nocols = 1 << GT_DEPTH(LIBGGI_GT(vis));
+
+	iter = Hermes_PaletteGet(vis->pal_inst);
+	if (!iter) 
+		return;
+
+	src = vis->palette;
+	if (!src)
+		return;
+
+	GGIDPRINT_COLOR("Setting HERMES palette: %d\n", nocols);
+
+	while (nocols--) {
+		*iter = (src->r & 0xff00) << 8;
+		*iter |= (src->g & 0xff00);
+		*iter++ |= src->b >> 8;
+		src++;
+	}
+	
+	Hermes_PaletteInvalidateCache(vis->pal_inst);
+}
+#endif /* USE_HERMES */
 
 int _ggi_mask2shift(uint32 mask)
 {
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/mode.c libggi-HERMES/ggi/mode.c
--- libggi-2.0b2.1/ggi/mode.c	Wed Feb 17 02:10:58 1999
+++ libggi-HERMES/ggi/mode.c	Sun Jun 20 17:40:53 1999
@@ -33,6 +33,9 @@
 
 #include <ggi/internal/internal.h>
 
+#ifdef USE_HERMES
+#include <Hermes/Hermes.h>
+#endif /* USE_HERMES */
 
 /* Static variables */
 static ggi_mode _ggiDefaultMode =
@@ -126,6 +129,41 @@
 		col.b = 0;
 		ggiSetGCForeground(vis, ggiMapColor(vis, &col));
 		ggiSetGCBackground(vis, ggiMapColor(vis, &col));
+
+#ifdef USE_HERMES
+		GGIDPRINT_CORE("ggiSetMode: Initializing HermesFormat\n");
+
+		memset(&vis->curformat, 0, sizeof (vis->curformat));
+
+		switch (GT_SCHEME(tm->graphtype)) {
+		case GT_PALETTE:
+		case GT_STATIC_PALETTE:
+			_ggi_set_hermes_palette(vis);
+			vis->curformat.indexed = 1;
+			break;
+		case GT_GREYSCALE: /* FIXME: must emulate with a fake palette */
+			vis->curformat.indexed = 1;
+			break;
+		case GT_TRUECOLOR:
+			vis->curformat.r = LIBGGI_PIXFMT(vis)->red_mask;
+			vis->curformat.g = LIBGGI_PIXFMT(vis)->green_mask;
+			vis->curformat.b = LIBGGI_PIXFMT(vis)->blue_mask;
+			vis->curformat.a = LIBGGI_PIXFMT(vis)->alpha_mask;
+			break;
+		case GT_TEXT:
+		default:
+			/* a flag to remind us not to touch these */
+			vis->curformat.indexed = 0x7f;
+			break;
+		}
+
+		vis->curformat.bits = LIBGGI_PIXFMT(vis)->size;
+
+		/* reverse endian and other flags */
+		if (LIBGGI_PIXFMT(vis)->flags)
+			vis->curformat.indexed = 0x7f;
+#endif /* USE_HERMES */
+
 		/* Clear frames to black */
 		for (i = 0; i < tm->frames; i++) {
 			GGIDPRINT_CORE("ggiSetMode: SetWriteFrame %d\n", i);
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/stubs.c libggi-HERMES/ggi/stubs.c
--- libggi-2.0b2.1/ggi/stubs.c	Fri May  7 00:40:45 1999
+++ libggi-HERMES/ggi/stubs.c	Sun Jun 20 17:27:59 1999
@@ -29,6 +29,10 @@
 
 #undef putc
 
+#ifdef USE_HERMES
+#include <Hermes/Hermes.h>
+#endif /* USE_HERMES */
+
 /************** Mode info ****************/
 
 int ggiSetFlags(ggi_visual *vis,ggi_flags flags)
@@ -102,7 +106,14 @@
 /* Palette, colors, etc...
  */
 int ggiSetPalette(ggi_visual *vis,int s,int len,ggi_color *cmap)
-{ return vis->opcolor->setpalvec(vis,s,len,cmap); }
+{ 
+	int err = vis->opcolor->setpalvec(vis,s,len,cmap); 
+#ifdef USE_HERMES
+	if (err >= 0)
+		_ggi_set_hermes_palette(vis);
+#endif /* USE_HERMES */	
+	return err;
+}
 
 int ggiGetPalette(ggi_visual *vis,int s,int len,ggi_color *cmap)
 { return vis->opcolor->getpalvec(vis,s,len,cmap); }
@@ -226,6 +237,22 @@
 	if (src == dst) {
 		return dst->opdraw->copybox(dst, sx, sy, w, h, dx, dy);
 	}
+
+#ifdef USE_HERMES
+	if (src->curformat.indexed != 0x7f && dst->curformat.indexed != 0x7f
+	    && src->r_frame && src->r_frame->layout == src->w_frame->layout 
+	    && dst->w_frame->buffer.plb.pixelformat->stdformat
+	    && Hermes_ConverterRequest(dst->conv_inst, &src->curformat, &dst->curformat)) {
+		if (src->curformat.indexed || dst->curformat.indexed)
+			Hermes_ConverterPalette(dst->conv_inst, src->pal_inst, dst->pal_inst);
+
+		if (Hermes_ConverterCopy(dst->conv_inst, LIBGGI_CURREAD(src), sx, sy,
+					 w, h, LIBGGI_FB_R_STRIDE(src), LIBGGI_CURWRITE(dst),
+					 dx, dy, w, h, LIBGGI_FB_W_STRIDE(dst)))
+		    return 0;
+	}
+#endif /* USE_HERMES */
+
 	/* Note: We use dst to map the request to, as it will normally be
 	   the "smarter" device. */
 	return dst->opdraw->crossblit(src, sx, sy, w, h, dst, dx, dy);
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/ggi/visual.c libggi-HERMES/ggi/visual.c
--- libggi-2.0b2.1/ggi/visual.c	Tue Mar 23 02:11:50 1999
+++ libggi-HERMES/ggi/visual.c	Sun Jun 20 17:20:15 1999
@@ -29,6 +29,10 @@
 
 #include <ggi/internal/internal.h>
 
+#ifdef USE_HERMES
+#include <Hermes/Hermes.h>
+#endif /* USE_HERMES */
+
 /*
 ******************************************************************************
  Default functions for op-structs
@@ -269,6 +273,14 @@
 	vis->palette = NULL;
 	vis->input = NULL;
 
+#ifdef USE_HERMES
+	vis->conv_inst = 0;
+	vis->pal_inst = 0;
+	vis->curformat.r = vis->curformat.g = vis->curformat.b = vis->curformat.a = 0;
+	vis->curformat.bits = 0;
+	vis->curformat.indexed = 0xff;
+#endif /* USE_HERMES */
+
 	_ggiZapMode(vis,~0);
 
 	return vis;
@@ -281,6 +293,10 @@
 		vis->input=NULL;
 	}
 	_ggiCloseDL(vis,~0);
+#ifdef USE_HERMES
+	Hermes_PaletteReturn(vis->pal_inst);
+	Hermes_ConverterReturn(vis->conv_inst);
+#endif /* USE_HERMES */
 	free(vis->opdisplay);
 	free(vis->opcolor);
 	free(vis->opdraw);
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/include/ggi/internal/internal.h libggi-HERMES/include/ggi/internal/internal.h
--- libggi-2.0b2.1/include/ggi/internal/internal.h	Thu Apr  1 18:24:27 1999
+++ libggi-HERMES/include/ggi/internal/internal.h	Sun Jun 20 16:26:40 1999
@@ -76,6 +76,9 @@
 void _ggi_build_palette(ggi_color *pal, int num);
 void _ggi_smart_match_palettes(ggi_color *pal, int size,
                                ggi_color *ref_pal, int ref_size);
+#ifdef USE_HERMES
+void _ggi_set_hermes_palette(ggi_visual *vis);
+#endif /* USE_HERMES */
 
 /* mode.c */
 void _ggiSetDefaultMode(const char *str);
diff -urN --exclude=Makefile.in --exclude=configure libggi-2.0b2.1/include/ggi/internal/structs.h libggi-HERMES/include/ggi/internal/structs.h
--- libggi-2.0b2.1/include/ggi/internal/structs.h	Thu Apr  1 18:30:29 1999
+++ libggi-HERMES/include/ggi/internal/structs.h	Sat Jun 19 14:50:58 1999
@@ -42,6 +42,12 @@
 
 #include <ggi/internal/dltypes.h>
 
+#ifdef USE_HERMES
+#include <ggi/internal/internal.h>
+
+#include <Hermes/Hermes.h>
+#endif /* USE_HERMES */
+
 #define GGI_VERSION_DLL	1
 
 /* Create a OP version number from the library and structure revisions
@@ -195,6 +201,11 @@
 	ggi_db_list 	 *app_dbs;	/* List of public DBs */
 	ggi_db_list	 *priv_dbs;	/* List of private DBs */
 	ggi_dlhandle_l	 *dlhandle;	/* Handles to dynamic libs */
+#ifdef USE_HERMES
+	HermesHandle	 conv_inst;	/* returned by Hermes_ConverterInstance() */
+	HermesHandle	 pal_inst;	/* returned by Hermes_PaletteInstance() */
+	HermesFormat	 curformat;	/* Current mode for HERMES */ 
+#endif /* USE_HERMES */
 
 	/* Extension stuff */
 	ggi_dlhandle_l	 *extlib;	/* Dynamic libs from extensions */


-- 
D.

Index: [thread] [date] [subject] [author]