summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2011-11-21 08:44:10 +0000
committerVincent Sanders <vince@netsurf-browser.org>2011-11-21 08:44:10 +0000
commit2dd32c7adb7116f1ad9ab2632d9fcf57a31e9fa2 (patch)
tree3528ebeb39ee0aadaf7faf0259b583b26172ed5c
parent81ad700162a2fa639a69c1c6e3969ed8f7b3f63b (diff)
downloadlibnsfb-2dd32c7adb7116f1ad9ab2632d9fcf57a31e9fa2.tar.gz
libnsfb-2dd32c7adb7116f1ad9ab2632d9fcf57a31e9fa2.tar.bz2
Improve API to allow for RAM surfaces instead of direct blitting
Improve and update tests Fix RAM surface Fix VNC surface svn path=/trunk/libnsfb/; revision=13158
-rw-r--r--Makefile8
-rw-r--r--include/frontend.h47
-rw-r--r--include/libnsfb.h94
-rw-r--r--include/libnsfb_event.h26
-rw-r--r--include/libnsfb_plot.h2
-rw-r--r--include/nsfb.h28
-rw-r--r--include/surface.h61
-rw-r--r--src/Makefile2
-rw-r--r--src/cursor.c18
-rw-r--r--src/dump.c56
-rw-r--r--src/libnsfb.c91
-rw-r--r--src/plot/api.c43
-rw-r--r--src/plot/generic.c530
-rw-r--r--src/surface/Makefile6
-rw-r--r--src/surface/able.c12
-rw-r--r--src/surface/linux.c14
-rw-r--r--src/surface/ram.c71
-rw-r--r--src/surface/sdl.c201
-rw-r--r--src/surface/surface.c139
-rw-r--r--src/surface/vnc.c536
-rw-r--r--src/surface/x.c45
-rw-r--r--test/Makefile2
-rw-r--r--test/bezier.c55
-rw-r--r--test/bitmap.c168
-rw-r--r--test/frontend.c52
-rw-r--r--test/path.c59
-rw-r--r--test/plottest.c106
-rw-r--r--test/polygon.c55
-rw-r--r--test/polystar.c56
-rw-r--r--test/polystar2.c56
-rwxr-xr-xtest/runtest.sh17
31 files changed, 1965 insertions, 691 deletions
diff --git a/Makefile b/Makefile
index 4239425..db12d1c 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ CFLAGS := -g -std=c99 -D_BSD_SOURCE -I$(CURDIR)/include/ \
NSFB_XCB_PKG_NAMES := xcb xcb-icccm xcb-image xcb-keysyms
+$(eval $(call pkg_config_package_available,NSFB_VNC_AVAILABLE,libvncserver))
$(eval $(call pkg_config_package_available,NSFB_SDL_AVAILABLE,sdl))
$(eval $(call pkg_config_package_available,NSFB_XCB_AVAILABLE,$(NSFB_XCB_PKG_NAMES)))
@@ -43,6 +44,13 @@ ifeq ($(NSFB_XCB_AVAILABLE),yes)
REQUIRED_PKGS := $(REQUIRED_PKGS) $(NSFB_XCB_PKG_NAMES)
endif
+ifeq ($(NSFB_VNC_AVAILABLE),yes)
+ $(eval $(call pkg_config_package_add_flags,libvncserver,CFLAGS))
+ $(eval $(call pkg_config_package_add_flags,libvncserver,TESTCFLAGS,TESTLDFLAGS))
+
+ REQUIRED_PKGS := $(REQUIRED_PKGS) libvncserver
+endif
+
TESTLDFLAGS := -Wl,--whole-archive -l$(COMPONENT) -Wl,--no-whole-archive $(TESTLDFLAGS)
include build/makefiles/Makefile.top
diff --git a/include/frontend.h b/include/frontend.h
deleted file mode 100644
index fba407f..0000000
--- a/include/frontend.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* libnsfb framebuffer frontend support */
-
-#include "libnsfb.h"
-#include "libnsfb_plot.h"
-#include "nsfb.h"
-
-/* frontend default options */
-typedef int (nsfb_fendfn_defaults_t)(nsfb_t *nsfb);
-/* frontend init */
-typedef int (nsfb_fendfn_init_t)(nsfb_t *nsfb);
-/* frontend finalise */
-typedef int (nsfb_fendfn_fini_t)(nsfb_t *nsfb);
-/* frontend set geometry */
-typedef int (nsfb_fendfn_geometry_t)(nsfb_t *nsfb, int width, int height, int bpp);
-/* frontend input */
-typedef bool (nsfb_fendfn_input_t)(nsfb_t *nsfb, nsfb_event_t *event, int timeout);
-/* frontend area claim */
-typedef int (nsfb_fendfn_claim_t)(nsfb_t *nsfb, nsfb_bbox_t *box);
-/* frontend area update */
-typedef int (nsfb_fendfn_update_t)(nsfb_t *nsfb, nsfb_bbox_t *box);
-/* frontend cursor display */
-typedef int (nsfb_fendfn_cursor_t)(nsfb_t *nsfb, struct nsfb_cursor_s *cursor);
-
-typedef struct nsfb_frontend_rtns_s {
- nsfb_fendfn_defaults_t *defaults;
- nsfb_fendfn_init_t *initialise;
- nsfb_fendfn_fini_t *finalise;
- nsfb_fendfn_geometry_t *geometry;
- nsfb_fendfn_input_t *input;
- nsfb_fendfn_claim_t *claim;
- nsfb_fendfn_update_t *update;
- nsfb_fendfn_cursor_t *cursor;
-} nsfb_frontend_rtns_t;
-
-void _nsfb_register_frontend(const enum nsfb_frontend_e type, const nsfb_frontend_rtns_t *rtns, const char *name);
-
-
-/* macro which adds a builtin command with no argument limits */
-#define NSFB_FRONTEND_DEF(__name, __type, __rtns) \
- static void __name##_register_frontend(void) __attribute__((constructor)); \
- void __name##_register_frontend(void) { \
- _nsfb_register_frontend(__type, __rtns, #__name); \
- }
-
-/* Obtain routines for a frontend */
-nsfb_frontend_rtns_t *nsfb_frontend_get_rtns(enum nsfb_frontend_e type);
-
diff --git a/include/libnsfb.h b/include/libnsfb.h
index 3f4a4e7..330c476 100644
--- a/include/libnsfb.h
+++ b/include/libnsfb.h
@@ -31,46 +31,60 @@ typedef struct nsfb_bbox_s {
int y1;
} nsfb_bbox_t;
-/** The type of frontend for a framebuffer context. */
-enum nsfb_frontend_e {
- NSFB_FRONTEND_NONE = 0, /**< Empty frontend. */
- NSFB_FRONTEND_SDL, /**< SDL frontend */
- NSFB_FRONTEND_LINUX, /**< Linux frontend */
- NSFB_FRONTEND_VNC, /**< VNC frontend */
- NSFB_FRONTEND_ABLE, /**< ABLE frontend */
- NSFB_FRONTEND_RAM, /**< RAM frontend */
- NSFB_FRONTEND_X /**< X windows frontend */
+/** The type of framebuffer surface. */
+enum nsfb_type_e {
+ NSFB_SURFACE_NONE = 0, /**< No surface */
+ NSFB_SURFACE_RAM, /**< RAM surface */
+ NSFB_SURFACE_SDL, /**< SDL surface */
+ NSFB_SURFACE_LINUX, /**< Linux framebuffer surface */
+ NSFB_SURFACE_VNC, /**< VNC surface */
+ NSFB_SURFACE_ABLE, /**< ABLE framebuffer surface */
+ NSFB_SURFACE_X /**< X windows surface */
};
-/** Initialise nsfb context.
- *
- * This initialises a framebuffer context.
- *
- * @param frontend The type of frontend to create a context for.
+enum nsfb_format_e {
+ NSFB_FMT_ANY = 0, /* No specific format - use surface default */
+ NSFB_FMT_XBGR8888, /* 32bpp Blue Green Red */
+ NSFB_FMT_XRGB8888, /* 32bpp Red Green Blue */
+ NSFB_FMT_ABGR8888, /* 32bpp Alpga Blue Green Red */
+ NSFB_FMT_ARGB8888, /* 32bpp Alpga Red Green Blue */
+ NSFB_FMT_RGB888, /* 24 bpp Alpga Red Green Blue */
+ NSFB_FMT_ARGB1555, /* 16 bpp 555 */
+ NSFB_FMT_RGB565, /* 16 bpp 565 */
+ NSFB_FMT_I8, /* 8bpp indexed */
+ NSFB_FMT_I4, /* 4bpp indexed */
+ NSFB_FMT_I1, /* black and white */
+};
+
+/** Select frontend type from a name.
+ *
+ * @param name The name to select a frontend.
+ * @return The surface type or NSFB_SURFACE_NONE if frontend with specified
+ * name was not available
*/
-nsfb_t *nsfb_init(enum nsfb_frontend_e frontend);
+enum nsfb_type_e nsfb_type_from_name(const char *name);
-/** Finalise nsfb.
+/** Create a nsfb context.
*
- * This shuts down and releases all resources associated with an nsfb context.
+ * This creates a framebuffer surface context.
*
- * @param nsfb The context returned from ::nsfb_init tofinalise
+ * @param surface_type The type of surface to create a context for.
*/
-int nsfb_finalise(nsfb_t *nsfb);
+nsfb_t *nsfb_new(const enum nsfb_type_e surface_type);
-/** Initialise selected frontend.
+/** Initialise selected surface context.
*
* @param nsfb The context returned from ::nsfb_init
*/
-int nsfb_init_frontend(nsfb_t *nsfb);
+int nsfb_init(nsfb_t *nsfb);
-/** Select frontend type from a name.
- *
- * @param name The name to select a frontend.
- * @return The frontend type or NSFB_FRONTEND_NONE if frontend with specified
- * name was not available
+/** Free nsfb context.
+ *
+ * This shuts down and releases all resources associated with an nsfb context.
+ *
+ * @param nsfb The context returned from ::nsfb_new to free
*/
-enum nsfb_frontend_e nsfb_frontend_from_name(const char *name);
+int nsfb_free(nsfb_t *nsfb);
/** Claim an area of screen to be redrawn.
*
@@ -86,7 +100,7 @@ int nsfb_claim(nsfb_t *nsfb, nsfb_bbox_t *box);
/** Update an area of screen which has been redrawn.
*
* Informs the nsfb library that an area of screen has been directly
- * updated by the user program. Some frontends only show the update on
+ * updated by the user program. Some surfaces only show the update on
* notification. The area updated does not neccisarrily have to
* corelate with a previous ::nsfb_claim bounding box, however if the
* redrawn area is larger than the claimed area pointer plotting
@@ -100,9 +114,9 @@ int nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box);
*
* @param width a variable to store the framebuffer width in or NULL
* @param height a variable to store the framebuffer height in or NULL
- * @param bpp a variable to store the framebuffer bpp in or NULL
+ * @param format a variable to store the framebuffer format in or NULL
*/
-int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp);
+int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, enum nsfb_format_e *format);
/** Alter the geometry of a framebuffer context
*
@@ -111,10 +125,24 @@ int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp);
* @param height The new display height.
* @param bpp The new display depth.
*/
-int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, int bpp);
+int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format);
-/** Obtain the framebuffer memory base and stride.
+/** Obtain the buffer memory base and stride.
+ *
+ * @param nsfb The context to read.
*/
-int nsfb_get_framebuffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen);
+int nsfb_get_buffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen);
+
+/** Dump the surface to fd in PPM format
+ */
+bool nsfb_dump(nsfb_t *nsfb, int fd);
+
#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/include/libnsfb_event.h b/include/libnsfb_event.h
index ea2b2bf..6944654 100644
--- a/include/libnsfb_event.h
+++ b/include/libnsfb_event.h
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * This is the exported interface for the libnsfb graphics library.
+ */
+
+#ifndef _LIBNSFB_EVENT_H
+#define _LIBNSFB_EVENT_H 1
+
enum nsfb_event_type_e {
NSFB_EVENT_NONE,
NSFB_EVENT_CONTROL,
@@ -13,6 +26,7 @@ enum nsfb_key_code_e {
NSFB_KEY_UNKNOWN = 0,
NSFB_KEY_BACKSPACE = 8,
NSFB_KEY_TAB = 9,
+ NSFB_KEY_LF = 10,
NSFB_KEY_CLEAR = 12,
NSFB_KEY_RETURN = 13,
NSFB_KEY_PAUSE = 19,
@@ -166,7 +180,8 @@ enum nsfb_key_code_e {
enum nsfb_control_e {
NSFB_CONTROL_NONE,
- NSFB_CONTROL_QUIT,
+ NSFB_CONTROL_TIMEOUT, /* timeout event */
+ NSFB_CONTROL_QUIT, /* surface handler quit event */
};
struct nsfb_event_s {
@@ -193,3 +208,12 @@ struct nsfb_event_s {
* @return If the /a event structure is updated true else false.
*/
bool nsfb_event(nsfb_t *nsfb, nsfb_event_t *event, int timeout);
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/include/libnsfb_plot.h b/include/libnsfb_plot.h
index 931243d..b3f86d1 100644
--- a/include/libnsfb_plot.h
+++ b/include/libnsfb_plot.h
@@ -148,7 +148,7 @@ bool nsfb_plot_path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_pl
*
* Copy an area of the display.
*/
-bool nsfb_plot_copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox);
+bool nsfb_plot_copy(nsfb_t *srcfb, nsfb_bbox_t *srcbox, nsfb_t *dstfb, nsfb_bbox_t *dstbox);
/** Plot bitmap.
*/
diff --git a/include/nsfb.h b/include/nsfb.h
index 7b28fcb..9b1619c 100644
--- a/include/nsfb.h
+++ b/include/nsfb.h
@@ -1,3 +1,13 @@
+/*
+ * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * This is the internal interface for the libnsfb graphics library.
+ */
+
#ifndef _NSFB_H
#define _NSFB_H 1
@@ -9,10 +19,13 @@
struct nsfb_s {
int width; /**< Visible width. */
int height; /**< Visible height. */
- int bpp; /**< Bits per pixel. */
+
+ int bpp;
+
+ enum nsfb_format_e format; /**< Framebuffer format */
int refresh; /**< Desired refresh rate for physical displays. */
- char *output_dev; /**> Path to output device for frontends that require it. */
+ char *output_dev; /**> Path to output device for surfaces that require it. */
uint8_t *ptr; /**< Base of video memory. */
int linelen; /**< length of a video line. */
@@ -20,8 +33,8 @@ struct nsfb_s {
nsfb_colour_t palette[256]; /**< palette for index modes */
nsfb_cursor_t *cursor; /**< cursor */
- struct nsfb_frontend_rtns_s *frontend_rtns; /**< frontend routines. */
- void *frontend_priv; /**< frontend opaque data. */
+ struct nsfb_surface_rtns_s *surface_rtns; /**< surface routines. */
+ void *surface_priv; /**< surface opaque data. */
nsfb_bbox_t clip; /**< current clipping rectangle for plotters */
struct nsfb_plotter_fns_s *plotter_fns; /**< Plotter methods */
@@ -29,3 +42,10 @@ struct nsfb_s {
#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/include/surface.h b/include/surface.h
new file mode 100644
index 0000000..d0c6c5a
--- /dev/null
+++ b/include/surface.h
@@ -0,0 +1,61 @@
+/* libnsfb framebuffer surface support */
+
+#include "libnsfb.h"
+#include "libnsfb_plot.h"
+#include "nsfb.h"
+
+/* surface default options */
+typedef int (nsfb_fendfn_defaults_t)(nsfb_t *nsfb);
+
+/* surface init */
+typedef int (nsfb_fendfn_init_t)(nsfb_t *nsfb);
+
+/* surface finalise */
+typedef int (nsfb_fendfn_fini_t)(nsfb_t *nsfb);
+
+/* surface set geometry */
+typedef int (nsfb_fendfn_geometry_t)(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format);
+
+/* surface input */
+typedef bool (nsfb_fendfn_input_t)(nsfb_t *nsfb, nsfb_event_t *event, int timeout);
+
+/* surface area claim */
+typedef int (nsfb_fendfn_claim_t)(nsfb_t *nsfb, nsfb_bbox_t *box);
+
+/* surface area update */
+typedef int (nsfb_fendfn_update_t)(nsfb_t *nsfb, nsfb_bbox_t *box);
+
+/* surface cursor display */
+typedef int (nsfb_fendfn_cursor_t)(nsfb_t *nsfb, struct nsfb_cursor_s *cursor);
+
+typedef struct nsfb_surface_rtns_s {
+ nsfb_fendfn_defaults_t *defaults;
+ nsfb_fendfn_init_t *initialise;
+ nsfb_fendfn_fini_t *finalise;
+ nsfb_fendfn_geometry_t *geometry;
+ nsfb_fendfn_input_t *input;
+ nsfb_fendfn_claim_t *claim;
+ nsfb_fendfn_update_t *update;
+ nsfb_fendfn_cursor_t *cursor;
+} nsfb_surface_rtns_t;
+
+void _nsfb_register_surface(const enum nsfb_type_e type, const nsfb_surface_rtns_t *rtns, const char *name);
+
+
+/* macro which adds a builtin command with no argument limits */
+#define NSFB_SURFACE_DEF(__name, __type, __rtns) \
+ static void __name##_register_surface(void) __attribute__((constructor)); \
+ void __name##_register_surface(void) { \
+ _nsfb_register_surface(__type, __rtns, #__name); \
+ }
+
+/** Obtain routines for a surface
+ *
+ * Obtain a vlist of methods for a surface type.
+ *
+ * @param type The surface type.
+ * @return A vtable of routines which teh caller must deallocate or
+ * NULL on error
+ */
+nsfb_surface_rtns_t *nsfb_surface_get_rtns(enum nsfb_type_e type);
+
diff --git a/src/Makefile b/src/Makefile
index 24f412f..90cde9b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,4 +1,4 @@
# Sources
-DIR_SOURCES := libnsfb.c cursor.c
+DIR_SOURCES := libnsfb.c dump.c cursor.c
include build/makefiles/Makefile.subdir
diff --git a/src/cursor.c b/src/cursor.c
index f1a3b58..bd9f04b 100644
--- a/src/cursor.c
+++ b/src/cursor.c
@@ -1,3 +1,15 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@kyllikki.org>
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/** \file
+ * cursor (implementation).
+ */
+
#include <stdbool.h>
#include <stdlib.h>
@@ -8,7 +20,7 @@
#include "nsfb.h"
#include "cursor.h"
#include "plot.h"
-#include "frontend.h"
+#include "surface.h"
bool nsfb_cursor_init(nsfb_t *nsfb)
{
@@ -36,7 +48,7 @@ bool nsfb_cursor_set(nsfb_t *nsfb, const nsfb_colour_t *pixel, int bmp_width, in
nsfb->cursor->loc.x1 = nsfb->cursor->loc.x0 + nsfb->cursor->bmp_width;
nsfb->cursor->loc.y1 = nsfb->cursor->loc.y0 + nsfb->cursor->bmp_height;
- return nsfb->frontend_rtns->cursor(nsfb, nsfb->cursor);
+ return nsfb->surface_rtns->cursor(nsfb, nsfb->cursor);
}
bool nsfb_cursor_loc_set(nsfb_t *nsfb, const nsfb_bbox_t *loc)
@@ -48,7 +60,7 @@ bool nsfb_cursor_loc_set(nsfb_t *nsfb, const nsfb_bbox_t *loc)
nsfb->cursor->loc.x1 = nsfb->cursor->loc.x0 + nsfb->cursor->bmp_width;
nsfb->cursor->loc.y1 = nsfb->cursor->loc.y0 + nsfb->cursor->bmp_height;
- return nsfb->frontend_rtns->cursor(nsfb, nsfb->cursor);
+ return nsfb->surface_rtns->cursor(nsfb, nsfb->cursor);
}
bool nsfb_cursor_loc_get(nsfb_t *nsfb, nsfb_bbox_t *loc)
diff --git a/src/dump.c b/src/dump.c
new file mode 100644
index 0000000..ed56a00
--- /dev/null
+++ b/src/dump.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "libnsfb.h"
+#include "libnsfb_plot.h"
+#include "libnsfb_event.h"
+#include "nsfb.h"
+#include "surface.h"
+
+/* exported interface documented in libnsfb.h */
+bool
+nsfb_dump(nsfb_t *nsfb, int fd)
+{
+ FILE *outf;
+ int x;
+ int y;
+
+ outf = fdopen(dup(fd), "w");
+ if (outf == NULL) {
+ return false;
+ }
+
+ fprintf(outf,"P3\n#libnsfb buffer dump\n%d %d\n255\n",
+ nsfb->width, nsfb->height);
+ for (y=0; y < nsfb->height; y++) {
+ for (x=0; x < nsfb->width; x++) {
+ fprintf(outf,"%d %d %d ",
+ *(nsfb->ptr + (((nsfb->width * y) + x) * 4) + 2),
+ *(nsfb->ptr + (((nsfb->width * y) + x) * 4) + 1),
+ *(nsfb->ptr + (((nsfb->width * y) + x) * 4) + 0));
+
+ }
+ fprintf(outf,"\n");
+ }
+
+ fclose(outf);
+
+ return true;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/libnsfb.c b/src/libnsfb.c
index 405df2c..21661cd 100644
--- a/src/libnsfb.c
+++ b/src/libnsfb.c
@@ -14,60 +14,70 @@
#include "libnsfb_plot.h"
#include "libnsfb_event.h"
#include "nsfb.h"
-#include "frontend.h"
+#include "surface.h"
-/* documented in libnsfb.h */
+/* exported interface documented in libnsfb.h */
nsfb_t*
-nsfb_init(const enum nsfb_frontend_e frontend_type)
+nsfb_new(const enum nsfb_type_e surface_type)
{
nsfb_t *newfb;
newfb = calloc(1, sizeof(nsfb_t));
if (newfb == NULL)
return NULL;
- /* obtain frontend routines */
- newfb->frontend_rtns = nsfb_frontend_get_rtns(frontend_type);
- if (newfb->frontend_rtns == NULL) {
+ /* obtain surface routines */
+ newfb->surface_rtns = nsfb_surface_get_rtns(surface_type);
+ if (newfb->surface_rtns == NULL) {
free(newfb);
return NULL;
}
- newfb->frontend_rtns->defaults(newfb);
+ newfb->surface_rtns->defaults(newfb);
return newfb;
}
-int nsfb_finalise(nsfb_t *nsfb)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_init(nsfb_t *nsfb)
{
- int ret;
- ret = nsfb->frontend_rtns->finalise(nsfb);
- free(nsfb);
- return ret;
+ return nsfb->surface_rtns->initialise(nsfb);
}
-
-int
-nsfb_init_frontend(nsfb_t *nsfb)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_free(nsfb_t *nsfb)
{
- return nsfb->frontend_rtns->initialise(nsfb);
+ int ret;
+ ret = nsfb->surface_rtns->finalise(nsfb);
+ free(nsfb);
+ return ret;
}
-bool nsfb_event(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
+/* exported interface documented in libnsfb.h */
+bool
+nsfb_event(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
{
- return nsfb->frontend_rtns->input(nsfb, event, timeout);
+ return nsfb->surface_rtns->input(nsfb, event, timeout);
}
-int nsfb_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
{
- return nsfb->frontend_rtns->claim(nsfb, box);
+ return nsfb->surface_rtns->claim(nsfb, box);
}
-int nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
- return nsfb->frontend_rtns->update(nsfb, box);
+ return nsfb->surface_rtns->update(nsfb, box);
}
-int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
if (width <= 0)
width = nsfb->width;
@@ -75,13 +85,15 @@ int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
if (height <= 0)
height = nsfb->height;
- if ((bpp != 32) && (bpp != 16) && (bpp != 8))
- bpp = nsfb->bpp;
+ if (format == NSFB_FMT_ANY)
+ format = nsfb->format;
- return nsfb->frontend_rtns->geometry(nsfb, width, height, bpp);
+ return nsfb->surface_rtns->geometry(nsfb, width, height, format);
}
-int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, enum nsfb_format_e *format)
{
if (width != NULL)
*width = nsfb->width;
@@ -89,15 +101,30 @@ int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp)
if (height != NULL)
*height = nsfb->height;
- if (bpp != NULL)
- *bpp = nsfb->bpp;
+ if (format != NULL)
+ *format = nsfb->format;
return 0;
}
-int nsfb_get_framebuffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen)
+/* exported interface documented in libnsfb.h */
+int
+nsfb_get_buffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen)
{
- *ptr = nsfb->ptr;
- *linelen = nsfb->linelen;
+ if (ptr != NULL) {
+ *ptr = nsfb->ptr;
+ }
+ if (linelen != NULL) {
+ *linelen = nsfb->linelen;
+ }
return 0;
}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
+
diff --git a/src/plot/api.c b/src/plot/api.c
index f5c16f3..77559cb 100644
--- a/src/plot/api.c
+++ b/src/plot/api.c
@@ -126,9 +126,41 @@ bool nsfb_plot_ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c)
return nsfb->plotter_fns->ellipse_fill(nsfb, ellipse, c);
}
-bool nsfb_plot_copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
+/* copy an area of surface from one location to another.
+ *
+ * @warning This implementation is woefully incomplete!
+ */
+bool
+nsfb_plot_copy(nsfb_t *srcfb,
+ nsfb_bbox_t *srcbox,
+ nsfb_t *dstfb,
+ nsfb_bbox_t *dstbox)
{
- return nsfb->plotter_fns->copy(nsfb, srcbox, dstbox);
+ bool trans = false;
+ nsfb_colour_t srccol;
+
+ if (srcfb == dstfb) {
+ return dstfb->plotter_fns->copy(srcfb, srcbox, dstbox);
+ }
+
+ if (srcfb->format == NSFB_FMT_ABGR8888) {
+ trans = true;
+ }
+
+ if ((srcfb->width == 1) && (srcfb->height == 1)) {
+ srccol = *(nsfb_colour_t *)(srcfb->ptr);
+
+ /* check for completely transparent */
+ if ((srccol & 0xff000000) == 0)
+ return true;
+
+ /* completely opaque pixels can be replaced with fill */
+ if ((srccol & 0xff000000) == 0xff)
+ return dstfb->plotter_fns->fill(dstfb, dstbox, srccol);
+ }
+
+ return dstfb->plotter_fns->bitmap(dstfb, dstbox, (const nsfb_colour_t *)srcfb->ptr, srcfb->width, srcfb->height, (srcfb->linelen * 8) / srcfb->bpp, trans);
+
}
bool nsfb_plot_bitmap(nsfb_t *nsfb, const nsfb_bbox_t *loc, const nsfb_colour_t *pixel, int bmp_width, int bmp_height, int bmp_stride, bool alpha)
@@ -172,3 +204,10 @@ bool nsfb_plot_path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_pl
{
return nsfb->plotter_fns->path(nsfb, pathc, pathop, pen);
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/plot/generic.c b/src/plot/generic.c
index 01a8587..63845e4 100644
--- a/src/plot/generic.c
+++ b/src/plot/generic.c
@@ -22,7 +22,7 @@
#include "nsfb.h"
#include "plot.h"
-#include "frontend.h"
+#include "surface.h"
extern const nsfb_plotter_fns_t _nsfb_1bpp_plotters;
extern const nsfb_plotter_fns_t _nsfb_8bpp_plotters;
@@ -97,20 +97,20 @@ static bool clg(nsfb_t *nsfb, nsfb_colour_t c)
* evenness of the total.
*/
static bool establish_crossing_value(int x, int y, int x0, int y0,
- int x1, int y1)
+ int x1, int y1)
{
- bool v1 = (x == x0 && y == y0); /* whether we're crossing 1st vertex */
- bool v2 = (x == x1 && y == y1); /* whether we're crossing 2nd vertex */
+ bool v1 = (x == x0 && y == y0); /* whether we're crossing 1st vertex */
+ bool v2 = (x == x1 && y == y1); /* whether we're crossing 2nd vertex */
- if ((v1 && (y0 < y1)) || (v2 && (y1 < y0))) {
- /* crossing top vertex */
- return true;
- } else if (!v1 && !v2) {
- /* Intersection with current y level is not at a vertex.
- * Normal crossing. */
- return true;
- }
- return false;
+ if ((v1 && (y0 < y1)) || (v2 && (y1 < y0))) {
+ /* crossing top vertex */
+ return true;
+ } else if (!v1 && !v2) {
+ /* Intersection with current y level is not at a vertex.
+ * Normal crossing. */
+ return true;
+ }
+ return false;
}
@@ -127,125 +127,125 @@ static bool establish_crossing_value(int x, int y, int x0, int y0,
*/
static bool find_span(const int *p, int n, int x, int y, int *x0, int *x1)
{
- int i;
- int p_x0, p_y0;
- int p_x1, p_y1;
- int x0_min, x1_min;
- int x_new;
- unsigned int x0c, x1c; /* counters for crossings at span end points */
- bool crossing_value;
- bool found_span_start = false;
-
- x0_min = x1_min = INT_MIN;
- x0c = x1c = 0;
- *x0 = *x1 = INT_MAX;
-
- /* search row for next span, returning it if one exists */
- do {
- /* reset endpoint info, if valid span endpoints not found */
- if (!found_span_start)
- *x0 = INT_MAX;
- *x1 = INT_MAX;
-
- /* search all lines in polygon */
- for (i = 0; i < n; i = i + 2) {
- /* get line endpoints */
- if (i != n - 2) {
- /* not the last line */
- p_x0 = p[i]; p_y0 = p[i + 1];
- p_x1 = p[i + 2]; p_y1 = p[i + 3];
- } else {
- /* last line; 2nd endpoint is first vertex */
- p_x0 = p[i]; p_y0 = p[i + 1];
- p_x1 = p[0]; p_y1 = p[1];
- }
- /* ignore horizontal lines */
- if (p_y0 == p_y1)
- continue;
-
- /* ignore lines that don't cross this y level */
- if ((y < p_y0 && y < p_y1) || (y > p_y0 && y > p_y1))
- continue;
-
- if (p_x0 == p_x1) {
- /* vertical line, x is constant */
- x_new = p_x0;
- } else {
- /* find crossing (intersection of this line and
- * current y level) */
- int num = (y - p_y0) * (p_x1 - p_x0);
- int den = (p_y1 - p_y0);
-
- /* To round to nearest (rather than down)
- * half the denominator is either added to
- * or subtracted from the numerator,
- * depending on whether the numerator and
- * denominator have the same sign. */
- num = ((num < 0) == (den < 0)) ?
- num + (den / 2) :
- num - (den / 2);
- x_new = p_x0 + num / den;
- }
-
- /* ignore crossings before current x */
- if (x_new < x ||
- (!found_span_start && x_new < x0_min) ||
- (found_span_start && x_new < x1_min))
- continue;
-
- crossing_value = establish_crossing_value(x_new, y,
- p_x0, p_y0, p_x1, p_y1);
-
-
- /* set nearest intersections as filled area endpoints */
- if (!found_span_start &&
- x_new < *x0 && crossing_value) {
- /* nearer than first endpoint */
- *x1 = *x0;
- x1c = x0c;
- *x0 = x_new;
- x0c = 1;
- } else if (!found_span_start &&
- x_new == *x0 && crossing_value) {
- /* same as first endpoint */
- x0c++;
- } else if (x_new < *x1 && crossing_value) {
- /* nearer than second endpoint */
- *x1 = x_new;
- x1c = 1;
- } else if (x_new == *x1 && crossing_value) {
- /* same as second endpoint */
- x1c++;
- }
- }
- /* check whether the span endpoints have been found */
- if (!found_span_start && x0c % 2 == 1) {
- /* valid fill start found */
- found_span_start = true;
-
- }
- if (x1c % 2 == 1) {
- /* valid fill endpoint found */
- if (!found_span_start) {
- /* not got a start yet; use this as start */
- found_span_start = true;
- x0c = x1c;
- *x0 = *x1;
- } else {
- /* got valid end of span */
- return true;
- }
- }
- /* if current positions aren't valid endpoints, set new
- * minimums after current positions */
- if (!found_span_start)
- x0_min = *x0 + 1;
- x1_min = *x1 + 1;
-
- } while (*x1 != INT_MAX);
-
- /* no spans found */
- return false;
+ int i;
+ int p_x0, p_y0;
+ int p_x1, p_y1;
+ int x0_min, x1_min;
+ int x_new;
+ unsigned int x0c, x1c; /* counters for crossings at span end points */
+ bool crossing_value;
+ bool found_span_start = false;
+
+ x0_min = x1_min = INT_MIN;
+ x0c = x1c = 0;
+ *x0 = *x1 = INT_MAX;
+
+ /* search row for next span, returning it if one exists */
+ do {
+ /* reset endpoint info, if valid span endpoints not found */
+ if (!found_span_start)
+ *x0 = INT_MAX;
+ *x1 = INT_MAX;
+
+ /* search all lines in polygon */
+ for (i = 0; i < n; i = i + 2) {
+ /* get line endpoints */
+ if (i != n - 2) {
+ /* not the last line */
+ p_x0 = p[i]; p_y0 = p[i + 1];
+ p_x1 = p[i + 2]; p_y1 = p[i + 3];
+ } else {
+ /* last line; 2nd endpoint is first vertex */
+ p_x0 = p[i]; p_y0 = p[i + 1];
+ p_x1 = p[0]; p_y1 = p[1];
+ }
+ /* ignore horizontal lines */
+ if (p_y0 == p_y1)
+ continue;
+
+ /* ignore lines that don't cross this y level */
+ if ((y < p_y0 && y < p_y1) || (y > p_y0 && y > p_y1))
+ continue;
+
+ if (p_x0 == p_x1) {
+ /* vertical line, x is constant */
+ x_new = p_x0;
+ } else {
+ /* find crossing (intersection of this line and
+ * current y level) */
+ int num = (y - p_y0) * (p_x1 - p_x0);
+ int den = (p_y1 - p_y0);
+
+ /* To round to nearest (rather than down)
+ * half the denominator is either added to
+ * or subtracted from the numerator,
+ * depending on whether the numerator and
+ * denominator have the same sign. */
+ num = ((num < 0) == (den < 0)) ?
+ num + (den / 2) :
+ num - (den / 2);
+ x_new = p_x0 + num / den;
+ }
+
+ /* ignore crossings before current x */
+ if (x_new < x ||
+ (!found_span_start && x_new < x0_min) ||
+ (found_span_start && x_new < x1_min))
+ continue;
+
+ crossing_value = establish_crossing_value(x_new, y,
+ p_x0, p_y0, p_x1, p_y1);
+
+
+ /* set nearest intersections as filled area endpoints */
+ if (!found_span_start &&
+ x_new < *x0 && crossing_value) {
+ /* nearer than first endpoint */
+ *x1 = *x0;
+ x1c = x0c;
+ *x0 = x_new;
+ x0c = 1;
+ } else if (!found_span_start &&
+ x_new == *x0 && crossing_value) {
+ /* same as first endpoint */
+ x0c++;
+ } else if (x_new < *x1 && crossing_value) {
+ /* nearer than second endpoint */
+ *x1 = x_new;
+ x1c = 1;
+ } else if (x_new == *x1 && crossing_value) {
+ /* same as second endpoint */
+ x1c++;
+ }
+ }
+ /* check whether the span endpoints have been found */
+ if (!found_span_start && x0c % 2 == 1) {
+ /* valid fill start found */
+ found_span_start = true;
+
+ }
+ if (x1c % 2 == 1) {
+ /* valid fill endpoint found */
+ if (!found_span_start) {
+ /* not got a start yet; use this as start */
+ found_span_start = true;
+ x0c = x1c;
+ *x0 = *x1;
+ } else {
+ /* got valid end of span */
+ return true;
+ }
+ }
+ /* if current positions aren't valid endpoints, set new
+ * minimums after current positions */
+ if (!found_span_start)
+ x0_min = *x0 + 1;
+ x1_min = *x1 + 1;
+
+ } while (*x1 != INT_MAX);
+
+ /* no spans found */
+ return false;
}
@@ -260,87 +260,87 @@ static bool find_span(const int *p, int n, int x, int y, int *x0, int *x1)
*/
static bool polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t c)
{
- int poly_x0, poly_y0; /* Bounding box top left corner */
- int poly_x1, poly_y1; /* Bounding box bottom right corner */
- int i, j; /* indexes */
- int x0, x1; /* filled span extents */
- int y; /* current y coordinate */
- int y_max; /* bottom of plot area */
- nsfb_bbox_t fline;
- nsfb_plot_pen_t pen;
-
- /* find no. of vertex values */
- int v = n * 2;
-
- /* Can't plot polygons with 2 or fewer vertices */
- if (n <= 2)
- return true;
+ int poly_x0, poly_y0; /* Bounding box top left corner */
+ int poly_x1, poly_y1; /* Bounding box bottom right corner */
+ int i, j; /* indexes */
+ int x0, x1; /* filled span extents */
+ int y; /* current y coordinate */
+ int y_max; /* bottom of plot area */
+ nsfb_bbox_t fline;
+ nsfb_plot_pen_t pen;
- pen.stroke_colour = c;
-
- /* Find polygon bounding box */
- poly_x0 = poly_x1 = *p;
- poly_y0 = poly_y1 = p[1];
- for (i = 2; i < v; i = i + 2) {
- j = i + 1;
- if (p[i] < poly_x0)
- poly_x0 = p[i];
- else if (p[i] > poly_x1)
- poly_x1 = p[i];
- if (p[j] < poly_y0)
- poly_y0 = p[j];
- else if (p[j] > poly_y1)
- poly_y1 = p[j];
- }
+ /* find no. of vertex values */
+ int v = n * 2;
- /* Don't try to plot it if it's outside the clip rectangle */
- if (nsfb->clip.y1 < poly_y0 ||
- nsfb->clip.y0 > poly_y1 ||
- nsfb->clip.x1 < poly_x0 ||
- nsfb->clip.x0 > poly_x1)
- return true;
+ /* Can't plot polygons with 2 or fewer vertices */
+ if (n <= 2)
+ return true;
- /* Find the top of the important area */
- if (poly_y0 > nsfb->clip.y0)
- y = poly_y0;
- else
- y = nsfb->clip.y0;
-
- /* Find the bottom of the important area */
- if (poly_y1 < nsfb->clip.y1)
- y_max = poly_y1;
- else
- y_max = nsfb->clip.y1;
-
- for (; y < y_max; y++) {
- x1 = poly_x0 - 1;
- /* For each row */
- while (find_span(p, v, x1 + 1, y, &x0, &x1)) {
- /* don't draw anything outside clip region */
- if (x1 < nsfb->clip.x0)
- continue;
- else if (x0 < nsfb->clip.x0)
- x0 = nsfb->clip.x0;
- if (x0 > nsfb->clip.x1)
- break;
- else if (x1 > nsfb->clip.x1)
- x1 = nsfb->clip.x1;
-
- fline.x0 = x0;
- fline.y0 = y;
- fline.x1 = x1;
- fline.y1 = y;
-
- /* draw this filled span on current row */
- nsfb->plotter_fns->line(nsfb, 1, &fline, &pen);
-
- /* don't look for more spans if already at end of clip
- * region or polygon */
- if (x1 == nsfb->clip.x1 || x1 == poly_x1)
- break;
- }
- }
+ pen.stroke_colour = c;
+
+ /* Find polygon bounding box */
+ poly_x0 = poly_x1 = *p;
+ poly_y0 = poly_y1 = p[1];
+ for (i = 2; i < v; i = i + 2) {
+ j = i + 1;
+ if (p[i] < poly_x0)
+ poly_x0 = p[i];
+ else if (p[i] > poly_x1)
+ poly_x1 = p[i];
+ if (p[j] < poly_y0)
+ poly_y0 = p[j];
+ else if (p[j] > poly_y1)
+ poly_y1 = p[j];
+ }
+
+ /* Don't try to plot it if it's outside the clip rectangle */
+ if (nsfb->clip.y1 < poly_y0 ||
+ nsfb->clip.y0 > poly_y1 ||
+ nsfb->clip.x1 < poly_x0 ||
+ nsfb->clip.x0 > poly_x1)
return true;
+
+ /* Find the top of the important area */
+ if (poly_y0 > nsfb->clip.y0)
+ y = poly_y0;
+ else
+ y = nsfb->clip.y0;
+
+ /* Find the bottom of the important area */
+ if (poly_y1 < nsfb->clip.y1)
+ y_max = poly_y1;
+ else
+ y_max = nsfb->clip.y1;
+
+ for (; y < y_max; y++) {
+ x1 = poly_x0 - 1;
+ /* For each row */
+ while (find_span(p, v, x1 + 1, y, &x0, &x1)) {
+ /* don't draw anything outside clip region */
+ if (x1 < nsfb->clip.x0)
+ continue;
+ else if (x0 < nsfb->clip.x0)
+ x0 = nsfb->clip.x0;
+ if (x0 > nsfb->clip.x1)
+ break;
+ else if (x1 > nsfb->clip.x1)
+ x1 = nsfb->clip.x1;
+
+ fline.x0 = x0;
+ fline.y0 = y;
+ fline.x1 = x1;
+ fline.y1 = y;
+
+ /* draw this filled span on current row */
+ nsfb->plotter_fns->line(nsfb, 1, &fline, &pen);
+
+ /* don't look for more spans if already at end of clip
+ * region or polygon */
+ if (x1 == nsfb->clip.x1 || x1 == poly_x1)
+ break;
+ }
+ }
+ return true;
}
static bool
@@ -354,9 +354,9 @@ rectangle(nsfb_t *nsfb, nsfb_bbox_t *rect,
pen.stroke_colour = c;
pen.stroke_width = line_width;
if (dotted || dashed) {
- pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
} else {
- pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
}
side[0] = *rect;
@@ -543,7 +543,7 @@ static bool ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c)
-/* copy an area of screen from one location to another.
+/* copy an area of surface from one location to another.
*
* @warning This implementation is woefully incomplete!
*/
@@ -563,7 +563,7 @@ copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
nsfb_plot_add_rect(srcbox, dstbox, &allbox);
- nsfb->frontend_rtns->claim(nsfb, &allbox);
+ nsfb->surface_rtns->claim(nsfb, &allbox);
srcptr = (nsfb->ptr +
(srcy * nsfb->linelen) +
@@ -595,21 +595,23 @@ copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
}
}
- nsfb->frontend_rtns->update(nsfb, dstbox);
+ nsfb->surface_rtns->update(nsfb, dstbox);
return true;
}
+
+
static bool arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2, nsfb_colour_t c)
{
- nsfb=nsfb;
- x = x;
- y = y;
- radius = radius;
- c = c;
- angle1=angle1;
- angle2=angle2;
- return true;
+ nsfb=nsfb;
+ x = x;
+ y = y;
+ radius = radius;
+ c = c;
+ angle1=angle1;
+ angle2=angle2;
+ return true;
}
#define N_SEG 30
@@ -654,14 +656,14 @@ cubic_points(unsigned int pointc,
point[cur_point].y = y;
if ((point[cur_point].x != point[cur_point - 1].x) ||
(point[cur_point].y != point[cur_point - 1].y))
- cur_point++;
+ cur_point++;
}
point[cur_point].x = curve->x1;
point[cur_point].y = curve->y1;
if ((point[cur_point].x != point[cur_point - 1].x) ||
(point[cur_point].y != point[cur_point - 1].y))
- cur_point++;
+ cur_point++;
return cur_point;
}
@@ -711,14 +713,14 @@ quadratic_points(unsigned int pointc,
point[cur_point].y = y;
if ((point[cur_point].x != point[cur_point - 1].x) ||
(point[cur_point].y != point[cur_point - 1].y))
- cur_point++;
+ cur_point++;
}
point[cur_point].x = curve->x1;
point[cur_point].y = curve->y1;
if ((point[cur_point].x != point[cur_point - 1].x) ||
(point[cur_point].y != point[cur_point - 1].y))
- cur_point++;
+ cur_point++;
return cur_point;
}
@@ -854,34 +856,57 @@ bool select_plotters(nsfb_t *nsfb)
{
const nsfb_plotter_fns_t *table = NULL;
- switch (nsfb->bpp) {
- /* case 1:
- table = &_nsfb_1bpp_plotters;
- break;
- */
- case 8:
- table = &_nsfb_8bpp_plotters;
- break;
-
- case 16:
- table = &_nsfb_16bpp_plotters;
- break;
-
- /*
- case 24:
- table = &_nsfb_24bpp_plotters;
- break;
- */
- case 32:
- table = &_nsfb_32bpp_plotters;
- break;
+ switch (nsfb->format) {
+ case NSFB_FMT_XBGR8888: /* 32bpp Blue Green Red */
+ case NSFB_FMT_ABGR8888: /* 32bpp Alpga Blue Green Red */
+ table = &_nsfb_32bpp_plotters;
+ nsfb->bpp = 32;
+ break;
+
+ case NSFB_FMT_XRGB8888: /* 32bpp Red Green Blue */
+ case NSFB_FMT_ARGB8888: /* 32bpp Alpga Red Green Blue */
+ table = &_nsfb_32bpp_plotters;
+ nsfb->bpp = 32;
+ break;
+
+
+ case NSFB_FMT_RGB888: /* 24 bpp Alpga Red Green Blue */
+#ifdef ENABLE_24_BPP
+ table = &_nsfb_24bpp_plotters;
+ nsfb->bpp = 24;
+ break;
+#else
+ return false;
+#endif
+
+ case NSFB_FMT_ARGB1555: /* 16 bpp 555 */
+ case NSFB_FMT_RGB565: /* 16 bpp 565 */
+ table = &_nsfb_16bpp_plotters;
+ nsfb->bpp = 16;
+ break;
+
+ case NSFB_FMT_I8: /* 8bpp indexed */
+ table = &_nsfb_8bpp_plotters;
+ nsfb->bpp = 8;
+ break;
+
+ case NSFB_FMT_I1: /* black and white */
+#ifdef ENABLE_1_BPP
+ table = &_nsfb_1bpp_plotters;
+ nsfb->bpp = 1
+ break;
+#else
+ return false;
+#endif
+
+ case NSFB_FMT_ANY: /* No specific format - use surface default */
default:
- return false;
+ return false;
}
if (nsfb->plotter_fns != NULL)
- free(nsfb->plotter_fns);
+ free(nsfb->plotter_fns);
nsfb->plotter_fns = calloc(1, sizeof(nsfb_plotter_fns_t));
memcpy(nsfb->plotter_fns, table, sizeof(nsfb_plotter_fns_t));
@@ -909,3 +934,10 @@ bool select_plotters(nsfb_t *nsfb)
return true;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/Makefile b/src/surface/Makefile
index 6eddcb6..21547a5 100644
--- a/src/surface/Makefile
+++ b/src/surface/Makefile
@@ -1,5 +1,5 @@
# Sources
-DIR_SOURCES := surface.c vnc.c able.c ram.c linux.c
+DIR_SOURCES := surface.c able.c ram.c linux.c
ifeq ($(NSFB_SDL_AVAILABLE),yes)
DIR_SOURCES := $(DIR_SOURCES) sdl.c
@@ -9,4 +9,8 @@ ifeq ($(NSFB_XCB_AVAILABLE),yes)
DIR_SOURCES := $(DIR_SOURCES) x.c
endif
+ifeq ($(NSFB_VNC_AVAILABLE),yes)
+ DIR_SOURCES := $(DIR_SOURCES) vnc.c
+endif
+
include build/makefiles/Makefile.subdir
diff --git a/src/surface/able.c b/src/surface/able.c
index d7b9226..dd4c340 100644
--- a/src/surface/able.c
+++ b/src/surface/able.c
@@ -13,18 +13,18 @@
#include "libnsfb_plot.h"
#include "libnsfb_event.h"
#include "nsfb.h"
-#include "frontend.h"
+#include "surface.h"
#define UNUSED(x) ((x) = (x))
-static int able_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+static int able_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
- if (nsfb->frontend_priv != NULL)
+ if (nsfb->surface_priv != NULL)
return -1; /* if were already initialised fail */
nsfb->width = width;
nsfb->height = height;
- nsfb->bpp = bpp;
+ nsfb->format = format;
return 0;
}
@@ -49,11 +49,11 @@ static bool able_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
return false;
}
-const nsfb_frontend_rtns_t able_rtns = {
+const nsfb_surface_rtns_t able_rtns = {
.initialise = able_initialise,
.finalise = able_finalise,
.input = able_input,
.geometry = able_set_geometry,
};
-NSFB_FRONTEND_DEF(able, NSFB_FRONTEND_ABLE, &able_rtns)
+NSFB_SURFACE_DEF(able, NSFB_SURFACE_ABLE, &able_rtns)
diff --git a/src/surface/linux.c b/src/surface/linux.c
index 3394f85..8c9ffec 100644
--- a/src/surface/linux.c
+++ b/src/surface/linux.c
@@ -16,20 +16,20 @@
#include "nsfb.h"
#include "plot.h"
-#include "frontend.h"
+#include "surface.h"
#include "cursor.h"
#define UNUSED(x) ((x) = (x))
-static int linux_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+static int linux_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
- if (nsfb->frontend_priv != NULL)
+ if (nsfb->surface_priv != NULL)
return -1; /* if we are already initialised fail */
nsfb->width = width;
nsfb->height = height;
- nsfb->bpp = bpp;
+ nsfb->format = format;
/* select default sw plotters for bpp */
select_plotters(nsfb);
@@ -39,7 +39,7 @@ static int linux_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
static int linux_initialise(nsfb_t *nsfb)
{
- if (nsfb->frontend_priv != NULL)
+ if (nsfb->surface_priv != NULL)
return -1;
/* sanity checked depth. */
@@ -122,7 +122,7 @@ static int linux_update(nsfb_t *nsfb, nsfb_bbox_t *box)
return 0;
}
-const nsfb_frontend_rtns_t linux_rtns = {
+const nsfb_surface_rtns_t linux_rtns = {
.initialise = linux_initialise,
.finalise = linux_finalise,
.input = linux_input,
@@ -132,4 +132,4 @@ const nsfb_frontend_rtns_t linux_rtns = {
.geometry = linux_set_geometry,
};
-NSFB_FRONTEND_DEF(linux, NSFB_FRONTEND_LINUX, &linux_rtns)
+NSFB_SURFACE_DEF(linux, NSFB_SURFACE_LINUX, &linux_rtns)
diff --git a/src/surface/ram.c b/src/surface/ram.c
index 0948a5d..4deabda 100644
--- a/src/surface/ram.c
+++ b/src/surface/ram.c
@@ -8,36 +8,77 @@
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include "libnsfb.h"
#include "libnsfb_plot.h"
#include "libnsfb_event.h"
+
#include "nsfb.h"
-#include "frontend.h"
+#include "surface.h"
+#include "plot.h"
#define UNUSED(x) ((x) = (x))
-static int ram_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+static int ram_defaults(nsfb_t *nsfb)
{
- if (nsfb->frontend_priv != NULL)
- return -1; /* if were already initialised fail */
+ nsfb->width = 0;
+ nsfb->height = 0;
+ nsfb->format = NSFB_FMT_ABGR8888;
- nsfb->width = width;
- nsfb->height = height;
- nsfb->bpp = bpp;
+ /* select default sw plotters for bpp */
+ select_plotters(nsfb);
return 0;
}
+
static int ram_initialise(nsfb_t *nsfb)
{
- UNUSED(nsfb);
+ size_t size = (nsfb->width * nsfb->height * nsfb->bpp) / 8;
+
+ nsfb->ptr = realloc(nsfb->ptr, size);
+ nsfb->linelen = (nsfb->width * nsfb->bpp) / 8;
+
+ return 0;
+}
+
+static int ram_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
+{
+ int startsize;
+ int endsize;
+
+ startsize = (nsfb->width * nsfb->height * nsfb->bpp) / 8;
+
+ if (width > 0) {
+ nsfb->width = width;
+ }
+
+ if (height > 0) {
+ nsfb->height = height;
+ }
+
+ if (format != NSFB_FMT_ANY) {
+ nsfb->format = format;
+ }
+
+ /* select soft plotters appropriate for format */
+ select_plotters(nsfb);
+
+ endsize = (nsfb->width * nsfb->height * nsfb->bpp) / 8;
+ if ((nsfb->ptr != NULL) && (startsize != endsize)) {
+ nsfb->ptr = realloc(nsfb->ptr, endsize);
+ }
+ nsfb->linelen = (nsfb->width * nsfb->bpp) / 8;
+
return 0;
}
+
static int ram_finalise(nsfb_t *nsfb)
{
- UNUSED(nsfb);
+ free(nsfb->ptr);
+
return 0;
}
@@ -49,11 +90,19 @@ static bool ram_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
return false;
}
-const nsfb_frontend_rtns_t ram_rtns = {
+const nsfb_surface_rtns_t ram_rtns = {
+ .defaults = ram_defaults,
.initialise = ram_initialise,
.finalise = ram_finalise,
.input = ram_input,
.geometry = ram_set_geometry,
};
-NSFB_FRONTEND_DEF(ram, NSFB_FRONTEND_RAM, &ram_rtns)
+NSFB_SURFACE_DEF(ram, NSFB_SURFACE_RAM, &ram_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/sdl.c b/src/surface/sdl.c
index f0f48af..2a905f5 100644
--- a/src/surface/sdl.c
+++ b/src/surface/sdl.c
@@ -16,7 +16,7 @@
#include "libnsfb_plot_util.h"
#include "nsfb.h"
-#include "frontend.h"
+#include "surface.h"
#include "plot.h"
#include "cursor.h"
@@ -350,7 +350,7 @@ enum nsfb_key_code_e sdl_nsfb_map[] = {
static void
set_palette(nsfb_t *nsfb)
{
- SDL_Surface *sdl_screen = nsfb->frontend_priv;
+ SDL_Surface *sdl_screen = nsfb->surface_priv;
SDL_Color palette[256];
int rloop, gloop, bloop;
int loop = 0;
@@ -363,8 +363,8 @@ set_palette(nsfb_t *nsfb)
palette[loop].g = (gloop << 5) | (gloop << 2) | (gloop >> 1);
palette[loop].b = (bloop << 6) | (bloop << 4) | (bloop << 2) | (bloop);
nsfb->palette[loop] = palette[loop].r |
- palette[loop].g << 8 |
- palette[loop].b << 16;
+ palette[loop].g << 8 |
+ palette[loop].b << 16;
loop++;
}
}
@@ -380,7 +380,7 @@ sdlcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
{
SDL_Rect src;
SDL_Rect dst;
- SDL_Surface *sdl_screen = nsfb->frontend_priv;
+ SDL_Surface *sdl_screen = nsfb->surface_priv;
nsfb_bbox_t allbox;
struct nsfb_cursor_s *cursor = nsfb->cursor;
@@ -416,16 +416,16 @@ sdlcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
}
-static int sdl_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+static int sdl_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
- if (nsfb->frontend_priv != NULL)
- return -1; /* if were already initialised fail */
+ if (nsfb->surface_priv != NULL)
+ return -1; /* fail if surface already initialised */
nsfb->width = width;
nsfb->height = height;
- nsfb->bpp = bpp;
+ nsfb->format = format;
- /* select default sw plotters for bpp */
+ /* select default sw plotters for format */
select_plotters(nsfb);
nsfb->plotter_fns->copy = sdlcopy;
@@ -437,7 +437,7 @@ static int sdl_initialise(nsfb_t *nsfb)
{
SDL_Surface *sdl_screen;
- if (nsfb->frontend_priv != NULL)
+ if (nsfb->surface_priv != NULL)
return -1;
/* sanity checked depth. */
@@ -449,7 +449,6 @@ static int sdl_initialise(nsfb_t *nsfb)
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
return -1;
}
- atexit(SDL_Quit);
sdl_screen = SDL_SetVideoMode(nsfb->width,
nsfb->height,
@@ -461,7 +460,7 @@ static int sdl_initialise(nsfb_t *nsfb)
return -1;
}
- nsfb->frontend_priv = sdl_screen;
+ nsfb->surface_priv = sdl_screen;
if (nsfb->bpp == 8)
set_palette(nsfb);
@@ -478,6 +477,7 @@ static int sdl_initialise(nsfb_t *nsfb)
static int sdl_finalise(nsfb_t *nsfb)
{
nsfb=nsfb;
+ SDL_Quit();
return 0;
}
@@ -518,92 +518,98 @@ static bool sdl_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
SDL_RemoveTimer(tid);
}
} else {
- got_event = SDL_WaitEvent(&sdlevent);
+ got_event = SDL_WaitEvent(&sdlevent);
}
}
/* Do nothing if there was no event */
- if (got_event == 0)
+ if (got_event == 0) {
return false;
+ }
event->type = NSFB_EVENT_NONE;
switch (sdlevent.type) {
- case SDL_KEYDOWN:
- event->type = NSFB_EVENT_KEY_DOWN;
- event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym];
- break;
-
- case SDL_KEYUP:
- event->type = NSFB_EVENT_KEY_UP;
- event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym];
- break;
-
- case SDL_MOUSEBUTTONDOWN:
- event->type = NSFB_EVENT_KEY_DOWN;
-
- switch (sdlevent.button.button) {
-
- case SDL_BUTTON_LEFT:
- event->value.keycode = NSFB_KEY_MOUSE_1;
- break;
-
- case SDL_BUTTON_MIDDLE:
- event->value.keycode = NSFB_KEY_MOUSE_2;
- break;
-
- case SDL_BUTTON_RIGHT:
- event->value.keycode = NSFB_KEY_MOUSE_3;
- break;
-
- case SDL_BUTTON_WHEELUP:
- event->value.keycode = NSFB_KEY_MOUSE_4;
- break;
-
- case SDL_BUTTON_WHEELDOWN:
- event->value.keycode = NSFB_KEY_MOUSE_5;
- break;
- }
- break;
-
- case SDL_MOUSEBUTTONUP:
- event->type = NSFB_EVENT_KEY_UP;
-
- switch (sdlevent.button.button) {
-
- case SDL_BUTTON_LEFT:
- event->value.keycode = NSFB_KEY_MOUSE_1;
- break;
-
- case SDL_BUTTON_MIDDLE:
- event->value.keycode = NSFB_KEY_MOUSE_2;
- break;
-
- case SDL_BUTTON_RIGHT:
- event->value.keycode = NSFB_KEY_MOUSE_3;
- break;
-
- case SDL_BUTTON_WHEELUP:
- event->value.keycode = NSFB_KEY_MOUSE_4;
- break;
-
- case SDL_BUTTON_WHEELDOWN:
- event->value.keycode = NSFB_KEY_MOUSE_5;
- break;
- }
- break;
-
- case SDL_MOUSEMOTION:
- event->type = NSFB_EVENT_MOVE_ABSOLUTE;
- event->value.vector.x = sdlevent.motion.x;
- event->value.vector.y = sdlevent.motion.y;
- event->value.vector.z = 0;
- break;
-
- case SDL_QUIT:
- event->type = NSFB_EVENT_CONTROL;
- event->value.controlcode = NSFB_CONTROL_QUIT;
- break;
+ case SDL_KEYDOWN:
+ event->type = NSFB_EVENT_KEY_DOWN;
+ event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym];
+ break;
+
+ case SDL_KEYUP:
+ event->type = NSFB_EVENT_KEY_UP;
+ event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym];
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ event->type = NSFB_EVENT_KEY_DOWN;
+
+ switch (sdlevent.button.button) {
+
+ case SDL_BUTTON_LEFT:
+ event->value.keycode = NSFB_KEY_MOUSE_1;
+ break;
+
+ case SDL_BUTTON_MIDDLE:
+ event->value.keycode = NSFB_KEY_MOUSE_2;
+ break;
+
+ case SDL_BUTTON_RIGHT:
+ event->value.keycode = NSFB_KEY_MOUSE_3;
+ break;
+
+ case SDL_BUTTON_WHEELUP:
+ event->value.keycode = NSFB_KEY_MOUSE_4;
+ break;
+
+ case SDL_BUTTON_WHEELDOWN:
+ event->value.keycode = NSFB_KEY_MOUSE_5;
+ break;
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ event->type = NSFB_EVENT_KEY_UP;
+
+ switch (sdlevent.button.button) {
+
+ case SDL_BUTTON_LEFT:
+ event->value.keycode = NSFB_KEY_MOUSE_1;
+ break;
+
+ case SDL_BUTTON_MIDDLE:
+ event->value.keycode = NSFB_KEY_MOUSE_2;
+ break;
+
+ case SDL_BUTTON_RIGHT:
+ event->value.keycode = NSFB_KEY_MOUSE_3;
+ break;
+
+ case SDL_BUTTON_WHEELUP:
+ event->value.keycode = NSFB_KEY_MOUSE_4;
+ break;
+
+ case SDL_BUTTON_WHEELDOWN:
+ event->value.keycode = NSFB_KEY_MOUSE_5;
+ break;
+ }
+ break;
+
+ case SDL_MOUSEMOTION:
+ event->type = NSFB_EVENT_MOVE_ABSOLUTE;
+ event->value.vector.x = sdlevent.motion.x;
+ event->value.vector.y = sdlevent.motion.y;
+ event->value.vector.z = 0;
+ break;
+
+ case SDL_QUIT:
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_QUIT;
+ break;
+
+ case SDL_USEREVENT:
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_TIMEOUT;
+ break;
}
@@ -625,7 +631,7 @@ static int sdl_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
static int
sdl_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
{
- SDL_Surface *sdl_screen = nsfb->frontend_priv;
+ SDL_Surface *sdl_screen = nsfb->surface_priv;
nsfb_bbox_t redraw;
nsfb_bbox_t fbarea;
@@ -659,7 +665,7 @@ sdl_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
static int sdl_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
- SDL_Surface *sdl_screen = nsfb->frontend_priv;
+ SDL_Surface *sdl_screen = nsfb->surface_priv;
struct nsfb_cursor_s *cursor = nsfb->cursor;
if ((cursor != NULL) &&
@@ -676,7 +682,7 @@ static int sdl_update(nsfb_t *nsfb, nsfb_bbox_t *box)
return 0;
}
-const nsfb_frontend_rtns_t sdl_rtns = {
+const nsfb_surface_rtns_t sdl_rtns = {
.initialise = sdl_initialise,
.finalise = sdl_finalise,
.input = sdl_input,
@@ -686,4 +692,11 @@ const nsfb_frontend_rtns_t sdl_rtns = {
.geometry = sdl_set_geometry,
};
-NSFB_FRONTEND_DEF(sdl, NSFB_FRONTEND_SDL, &sdl_rtns)
+NSFB_SURFACE_DEF(sdl, NSFB_SURFACE_SDL, &sdl_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/surface.c b/src/surface/surface.c
index 6fa65a8..b2cf769 100644
--- a/src/surface/surface.c
+++ b/src/surface/surface.c
@@ -12,40 +12,41 @@
#include <stdlib.h>
#include <string.h>
-#include "frontend.h"
+#include "surface.h"
#include "plot.h"
-#define MAX_FRONTENDS 16
+#define MAX_SURFACES 16
-struct nsfb_frontend_s {
- enum nsfb_frontend_e type;
- const nsfb_frontend_rtns_t *rtns;
+struct nsfb_surface_s {
+ enum nsfb_type_e type;
+ const nsfb_surface_rtns_t *rtns;
const char *name;
};
-static struct nsfb_frontend_s frontends[MAX_FRONTENDS];
-static int frontend_count = 0;
+static struct nsfb_surface_s surfaces[MAX_SURFACES];
+static int surface_count = 0;
-/* internal routine which lets frontends register their presence at runtime */
-void _nsfb_register_frontend(const enum nsfb_frontend_e type,
- const nsfb_frontend_rtns_t *rtns,
+/* internal routine which lets surfaces register their presence at runtime */
+void _nsfb_register_surface(const enum nsfb_type_e type,
+ const nsfb_surface_rtns_t *rtns,
const char *name)
{
- if (frontend_count >= MAX_FRONTENDS)
- return; /* no space for additional frontends */
+ if (surface_count >= MAX_SURFACES)
+ return; /* no space for additional surfaces */
- frontends[frontend_count].type = type;
- frontends[frontend_count].rtns = rtns;
- frontends[frontend_count].name = name;
- frontend_count++;
+ surfaces[surface_count].type = type;
+ surfaces[surface_count].rtns = rtns;
+ surfaces[surface_count].name = name;
+ surface_count++;
}
-/* default frontend implementations */
-static int frontend_defaults(nsfb_t *nsfb)
+/* default surface implementations */
+
+static int surface_defaults(nsfb_t *nsfb)
{
nsfb->width = 800;
nsfb->height = 600;
- nsfb->bpp = 32;
+ nsfb->format = NSFB_FMT_XRGB8888;
/* select default sw plotters for bpp */
select_plotters(nsfb);
@@ -53,75 +54,93 @@ static int frontend_defaults(nsfb_t *nsfb)
return 0;
}
-static int frontend_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
+static int surface_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
{
nsfb=nsfb;
box=box;
return 0;
}
-static int frontend_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+static int surface_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
nsfb=nsfb;
box=box;
return 0;
}
-static int frontend_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
+static int surface_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
{
nsfb=nsfb;
cursor=cursor;
return 0;
}
-nsfb_frontend_rtns_t *nsfb_frontend_get_rtns(enum nsfb_frontend_e type)
+/* exported interface documented in surface.h */
+nsfb_surface_rtns_t *
+nsfb_surface_get_rtns(enum nsfb_type_e type)
{
int fend_loop;
- nsfb_frontend_rtns_t *rtns = NULL;
-
- for (fend_loop = 0; fend_loop < frontend_count; fend_loop++) {
- if (frontends[fend_loop].type == type) {
- rtns = malloc(sizeof(nsfb_frontend_rtns_t));
- memcpy(rtns,
- frontends[fend_loop].rtns,
- sizeof(nsfb_frontend_rtns_t));
-
- /* frontend must have an initialisor, finaliser and input method */
- if ((rtns->initialise == NULL) ||
- (rtns->finalise == NULL) ||
- (rtns->input == NULL) ) {
- free(rtns);
- rtns = NULL;
- } else {
- /* The rest may be empty but to avoid the null check every time
- * provide default implementations.
- */
- if (rtns->defaults == NULL)
- rtns->defaults = frontend_defaults;
-
- if (rtns->claim == NULL)
- rtns->claim = frontend_claim;
-
- if (rtns->update == NULL)
- rtns->update = frontend_update;
-
- if (rtns->cursor == NULL)
- rtns->cursor = frontend_cursor;
- }
-
+ nsfb_surface_rtns_t *rtns = NULL;
+
+ for (fend_loop = 0; fend_loop < surface_count; fend_loop++) {
+ /* surface type must match and have a initialisor, finaliser
+ * and input method
+ */
+ if ((surfaces[fend_loop].type == type) &&
+ (surfaces[fend_loop].rtns->initialise != NULL) &&
+ (surfaces[fend_loop].rtns->finalise != NULL) &&
+ (surfaces[fend_loop].rtns->input != NULL) ) {
+
+ rtns = malloc(sizeof(nsfb_surface_rtns_t));
+ if (rtns == NULL) {
+ continue;
+ }
+
+ memcpy(rtns,
+ surfaces[fend_loop].rtns,
+ sizeof(nsfb_surface_rtns_t));
+
+ /* The rest may be empty but to avoid the null check every time
+ * provide default implementations.
+ */
+ if (rtns->defaults == NULL) {
+ rtns->defaults = surface_defaults;
+ }
+
+ if (rtns->claim == NULL) {
+ rtns->claim = surface_claim;
+ }
+
+ if (rtns->update == NULL) {
+ rtns->update = surface_update;
+ }
+
+ if (rtns->cursor == NULL) {
+ rtns->cursor = surface_cursor;
+ }
+
break;
}
}
return rtns;
}
-enum nsfb_frontend_e nsfb_frontend_from_name(const char *name)
+/* exported interface defined in libnsfb.h */
+enum nsfb_type_e
+nsfb_type_from_name(const char *name)
{
int fend_loop;
- for (fend_loop = 0; fend_loop < frontend_count; fend_loop++) {
- if (strcmp(frontends[fend_loop].name, name) == 0)
- return frontends[fend_loop].type;
+ for (fend_loop = 0; fend_loop < surface_count; fend_loop++) {
+ if (strcmp(surfaces[fend_loop].name, name) == 0)
+ return surfaces[fend_loop].type;
}
- return NSFB_FRONTEND_NONE;
+ return NSFB_SURFACE_NONE;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/vnc.c b/src/surface/vnc.c
index eb6d6ff..eb32560 100644
--- a/src/surface/vnc.c
+++ b/src/surface/vnc.c
@@ -9,51 +9,559 @@
#include <stdbool.h>
#include <stdio.h>
+#include <rfb/rfb.h>
+#include <rfb/keysym.h>
+
#include "libnsfb.h"
#include "libnsfb_event.h"
#include "libnsfb_plot.h"
+
#include "nsfb.h"
-#include "frontend.h"
+#include "surface.h"
+#include "plot.h"
+#include "cursor.h"
#define UNUSED(x) ((x) = (x))
-static int vnc_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+static nsfb_event_t *gevent;
+
+/* vnc special set codes */
+static enum nsfb_key_code_e vnc_nsfb_map[256] = {
+ NSFB_KEY_UNKNOWN, /* 0x00 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_BACKSPACE, /* 0x08 */
+ NSFB_KEY_TAB,
+ NSFB_KEY_LF,
+ NSFB_KEY_CLEAR,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_RETURN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x10 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_RETURN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x18 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_ESCAPE,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_COMPOSE, /* 0x20 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x28 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x30 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x38 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x40 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x48 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_HOME, /* 0x50 */
+ NSFB_KEY_LEFT,
+ NSFB_KEY_UP,
+ NSFB_KEY_RIGHT,
+ NSFB_KEY_DOWN,
+ NSFB_KEY_PAGEUP,
+ NSFB_KEY_PAGEDOWN,
+ NSFB_KEY_END,
+ NSFB_KEY_HOME, /* 0x58 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x60 */
+ NSFB_KEY_PRINT,
+ NSFB_KEY_HELP,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNDO,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_MENU,
+ NSFB_KEY_UNKNOWN, /* 0x68 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_BREAK,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x70 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x78 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_MODE,
+ NSFB_KEY_NUMLOCK,
+ NSFB_KEY_UNKNOWN, /* 0x80 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x88 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_KP_ENTER,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x90 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0x98 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xA0 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xA8 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_KP_MULTIPLY,
+ NSFB_KEY_KP_PLUS,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_KP_MINUS,
+ NSFB_KEY_KP_PERIOD,
+ NSFB_KEY_KP_DIVIDE,
+ NSFB_KEY_KP0, /* 0xB0 */
+ NSFB_KEY_KP1,
+ NSFB_KEY_KP2,
+ NSFB_KEY_KP3,
+ NSFB_KEY_KP4,
+ NSFB_KEY_KP5,
+ NSFB_KEY_KP6,
+ NSFB_KEY_KP7,
+ NSFB_KEY_KP8, /* 0xB8 */
+ NSFB_KEY_KP9,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_KP_EQUALS,
+ NSFB_KEY_F1,
+ NSFB_KEY_F2,
+ NSFB_KEY_F3, /* 0xC0 */
+ NSFB_KEY_F4,
+ NSFB_KEY_F5,
+ NSFB_KEY_F6,
+ NSFB_KEY_F7,
+ NSFB_KEY_F8,
+ NSFB_KEY_F9,
+ NSFB_KEY_F10,
+ NSFB_KEY_F11, /* 0xC8 */
+ NSFB_KEY_F12,
+ NSFB_KEY_F13,
+ NSFB_KEY_F14,
+ NSFB_KEY_F15,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xD0 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xD8 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xE0 */
+ NSFB_KEY_LSHIFT,
+ NSFB_KEY_RSHIFT,
+ NSFB_KEY_LCTRL,
+ NSFB_KEY_RCTRL,
+ NSFB_KEY_CAPSLOCK,
+ NSFB_KEY_SCROLLOCK,
+ NSFB_KEY_LMETA,
+ NSFB_KEY_RMETA, /* 0xE8 */
+ NSFB_KEY_LALT,
+ NSFB_KEY_RALT,
+ NSFB_KEY_LSUPER,
+ NSFB_KEY_RSUPER,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xF0 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN, /* 0xF8 */
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_UNKNOWN,
+ NSFB_KEY_DELETE,
+};
+
+
+static void vnc_doptr(int buttonMask,int x,int y,rfbClientPtr cl)
+{
+ static int prevbuttonMask = 0;
+
+ UNUSED(cl);
+
+ if (prevbuttonMask != buttonMask) {
+ /* button click */
+ if (((prevbuttonMask ^ buttonMask) & 0x01) == 0x01) {
+ if ((buttonMask & 0x01) == 0x01) {
+ gevent->type = NSFB_EVENT_KEY_DOWN;
+ } else {
+ gevent->type = NSFB_EVENT_KEY_UP;
+ }
+ gevent->value.keycode = NSFB_KEY_MOUSE_1;
+ } else if (((prevbuttonMask ^ buttonMask) & 0x02) == 0x02) {
+ if ((buttonMask & 0x01) == 0x01) {
+ gevent->type = NSFB_EVENT_KEY_DOWN;
+ } else {
+ gevent->type = NSFB_EVENT_KEY_UP;
+ }
+ gevent->value.keycode = NSFB_KEY_MOUSE_2;
+ } else if (((prevbuttonMask ^ buttonMask) & 0x04) == 0x04) {
+ if ((buttonMask & 0x01) == 0x01) {
+ gevent->type = NSFB_EVENT_KEY_DOWN;
+ } else {
+ gevent->type = NSFB_EVENT_KEY_UP;
+ }
+ gevent->value.keycode = NSFB_KEY_MOUSE_3;
+ } else if (((prevbuttonMask ^ buttonMask) & 0x08) == 0x08) {
+ if ((buttonMask & 0x01) == 0x01) {
+ gevent->type = NSFB_EVENT_KEY_DOWN;
+ } else {
+ gevent->type = NSFB_EVENT_KEY_UP;
+ }
+ gevent->value.keycode = NSFB_KEY_MOUSE_4;
+ } else if (((prevbuttonMask ^ buttonMask) & 0x10) == 0x10) {
+ if ((buttonMask & 0x01) == 0x01) {
+ gevent->type = NSFB_EVENT_KEY_DOWN;
+ } else {
+ gevent->type = NSFB_EVENT_KEY_UP;
+ }
+ gevent->value.keycode = NSFB_KEY_MOUSE_5;
+ }
+ prevbuttonMask = buttonMask;
+ } else {
+ gevent->type = NSFB_EVENT_MOVE_ABSOLUTE;
+ gevent->value.vector.x = x;
+ gevent->value.vector.y = y;
+ gevent->value.vector.z = 0;
+ }
+
+}
+
+
+static void vnc_dokey(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+{
+ enum nsfb_key_code_e keycode = NSFB_KEY_UNKNOWN;
+
+ UNUSED(cl);
+
+ if ((key >= XK_space) && (key <= XK_asciitilde)) {
+ /* ascii codes line up */
+ keycode = key;
+ } else if ((key & 0xff00) == 0xff00) {
+ /* bottom 8bits of keysyms in this range map via table */
+ keycode = vnc_nsfb_map[(key & 0xff)];
+ }
+
+ if (down == 0) {
+ /* key up */
+ gevent->type = NSFB_EVENT_KEY_UP;
+ } else {
+ /* key down */
+ gevent->type = NSFB_EVENT_KEY_DOWN;
+ }
+ gevent->value.keycode = keycode;
+
+}
+
+
+static int vnc_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
- if (nsfb->frontend_priv != NULL)
- return -1; /* if were already initialised fail */
+ if (nsfb->surface_priv != NULL)
+ return -1; /* fail if surface already initialised */
+
+ if (width > 0) {
+ nsfb->width = width;
+ }
+
+ if (height > 0) {
+ nsfb->height = height;
+ }
+
+ if (format != NSFB_FMT_ANY) {
+ nsfb->format = format;
+ }
- nsfb->width = width;
- nsfb->height = height;
- nsfb->bpp = bpp;
+ /* select soft plotters appropriate for format */
+ select_plotters(nsfb);
return 0;
}
static int vnc_initialise(nsfb_t *nsfb)
{
- UNUSED(nsfb);
+ rfbScreenInfoPtr vncscreen;
+ int argc = 0;
+ char **argv = NULL;
+
+ if (nsfb->surface_priv != NULL)
+ return -1; /* fail if surface already initialised */
+
+ /* sanity checked depth. */
+ if (nsfb->bpp != 32)
+ return -1;
+
+ /* create vnc screen with 8bits per sample, three samples per
+ * pixel and 4 bytes per pixel. */
+ vncscreen = rfbGetScreen(&argc, argv,
+ nsfb->width, nsfb->height,
+ 8, 3, (nsfb->bpp / 8));
+
+ if (vncscreen == NULL) {
+ /* Note libvncserver does not check its own allocations/error
+ * paths so the faliure mode of the rfbGetScreen is to segfault.
+ */
+ return -1;
+ }
+
+ vncscreen->frameBuffer = malloc(nsfb->width * nsfb->height * (nsfb->bpp / 8));
+
+ if (vncscreen->frameBuffer == NULL) {
+ rfbScreenCleanup(vncscreen);
+ return -1;
+ }
+
+
+ switch (nsfb->bpp) {
+ case 8:
+ break;
+
+ case 16:
+ vncscreen->serverFormat.trueColour=TRUE;
+ vncscreen->serverFormat.redShift = 11;
+ vncscreen->serverFormat.greenShift = 5;
+ vncscreen->serverFormat.blueShift = 0;
+ vncscreen->serverFormat.redMax = 31;
+ vncscreen->serverFormat.greenMax = 63;
+ vncscreen->serverFormat.blueMax = 31;
+ break;
+
+ case 32:
+ vncscreen->serverFormat.trueColour=TRUE;
+ vncscreen->serverFormat.redShift = 16;
+ vncscreen->serverFormat.greenShift = 8;
+ vncscreen->serverFormat.blueShift = 0;
+ break;
+ }
+
+ vncscreen->alwaysShared = TRUE;
+ vncscreen->autoPort = 1;
+ vncscreen->ptrAddEvent = vnc_doptr;
+ vncscreen->kbdAddEvent = vnc_dokey;
+
+ rfbInitServer(vncscreen);
+
+ /* keep parameters */
+ nsfb->surface_priv = vncscreen;
+ nsfb->ptr = (uint8_t *)vncscreen->frameBuffer;
+ nsfb->linelen = (nsfb->width * nsfb->bpp) / 8;
+
return 0;
}
static int vnc_finalise(nsfb_t *nsfb)
{
- UNUSED(nsfb);
+ rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
+
+ if (vncscreen != NULL) {
+ rfbScreenCleanup(vncscreen);
+ }
+
+ return 0;
+}
+
+
+static int vnc_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+ rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
+
+ rfbMarkRectAsModified(vncscreen, box->x0, box->y0, box->x1, box->y1);
+
return 0;
}
+
static bool vnc_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
{
- UNUSED(nsfb);
- UNUSED(event);
- UNUSED(timeout);
+ rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
+ int ret;
+
+ if (vncscreen != NULL) {
+
+ gevent = event; /* blergh - have to use global state to pass data */
+
+ /* set default to timeout */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_TIMEOUT;
+
+ ret = rfbProcessEvents(vncscreen, timeout * 1000);
+ return true;
+ }
+
return false;
}
-const nsfb_frontend_rtns_t vnc_rtns = {
+static int
+vnc_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
+{
+ rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
+ rfbCursorPtr vnccursor = calloc(1,sizeof(rfbCursor));
+ int rwidth; /* rounded width */
+ int row;
+ int col;
+ const nsfb_colour_t *pixel;
+ uint8_t bit;
+
+ rwidth = (cursor->bmp_width + 7) / 8;
+
+ vnccursor->cleanup = 1; /* rfb lib will free this allocation */
+ vnccursor->width = cursor->bmp_width;
+ vnccursor->height = cursor->bmp_height;
+ vnccursor->foreRed = vnccursor->foreGreen = vnccursor->foreBlue = 0xffff;
+
+ vnccursor->source = calloc(rwidth, vnccursor->height);
+ vnccursor->cleanupSource = 1; /* rfb lib will free this allocation */
+ vnccursor->mask = calloc(rwidth, vnccursor->height);
+ vnccursor->cleanupMask = 1; /* rfb lib will free this allocation */
+
+ for (row = 0, pixel = cursor->pixel; row < vnccursor->height; row++) {
+ for (col = 0, bit = 0x80;
+ col < vnccursor->width;
+ col++, bit = (bit & 1)? 0x80 : bit>>1, pixel++) {
+
+ /* pixel luminance more than 50% */
+ if ((((((*pixel) & 0xff) * 77) +
+ ((((*pixel) & 0xff00) >> 8) * 151) +
+ ((((*pixel) & 0xff0000) >> 16) * 28)) / 256) > 128) {
+
+ vnccursor->source[row * rwidth + col/8] |= bit;
+ }
+ if (((*pixel) & 0xff000000) != 0) {
+ vnccursor->mask[row * rwidth + col/8] |= bit;
+ }
+ }
+ }
+
+ rfbSetCursor(vncscreen, vnccursor);
+ return true;
+}
+
+const nsfb_surface_rtns_t vnc_rtns = {
.initialise = vnc_initialise,
.finalise = vnc_finalise,
.input = vnc_input,
+ .update = vnc_update,
+ .cursor = vnc_cursor,
.geometry = vnc_set_geometry,
};
-NSFB_FRONTEND_DEF(vnc, NSFB_FRONTEND_VNC, &vnc_rtns)
+NSFB_SURFACE_DEF(vnc, NSFB_SURFACE_VNC, &vnc_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/x.c b/src/surface/x.c
index a8c06ee..ccefacf 100644
--- a/src/surface/x.c
+++ b/src/surface/x.c
@@ -29,7 +29,7 @@
#include "libnsfb_plot_util.h"
#include "nsfb.h"
-#include "frontend.h"
+#include "surface.h"
#include "plot.h"
#include "cursor.h"
@@ -390,7 +390,7 @@ xkeysym_to_nsfbkeycode(xcb_keysym_t ks)
static void
set_palette(nsfb_t *nsfb)
{
- X_Surface *x_screen = nsfb->frontend_priv;
+ X_Surface *x_screen = nsfb->surface_priv;
X_Color palette[256];
int rloop, gloop, bloop;
int loop = 0;
@@ -469,7 +469,7 @@ update_and_redraw_pixmap(xstate_t *xstate, int x, int y, int width, int height)
static bool
xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
{
- xstate_t *xstate = nsfb->frontend_priv;
+ xstate_t *xstate = nsfb->surface_priv;
nsfb_bbox_t allbox;
struct nsfb_cursor_s *cursor = nsfb->cursor;
uint8_t *srcptr;
@@ -564,16 +564,17 @@ xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
}
-static int x_set_geometry(nsfb_t *nsfb, int width, int height, int bpp)
+static int
+x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
- if (nsfb->frontend_priv != NULL)
+ if (nsfb->surface_priv != NULL)
return -1; /* if were already initialised fail */
nsfb->width = width;
nsfb->height = height;
- nsfb->bpp = bpp;
+ nsfb->format = format;
- /* select default sw plotters for bpp */
+ /* select default sw plotters for format */
select_plotters(nsfb);
nsfb->plotter_fns->copy = xcopy;
@@ -588,6 +589,7 @@ find_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp)
const xcb_setup_t *setup = xcb_get_setup(c);
xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
+
for(; fmt != fmtend; ++fmt) {
if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) {
return fmt;
@@ -756,7 +758,7 @@ static int x_initialise(nsfb_t *nsfb)
uint32_t mask;
uint32_t values[3];
xcb_size_hints_t *hints;
- xstate_t *xstate = nsfb->frontend_priv;
+ xstate_t *xstate = nsfb->surface_priv;
xcb_cursor_t blank_cursor;
if (xstate != NULL)
@@ -801,7 +803,7 @@ static int x_initialise(nsfb_t *nsfb)
}
/* ensure plotting information is stored */
- nsfb->frontend_priv = xstate;
+ nsfb->surface_priv = xstate;
nsfb->ptr = xstate->image->data;
nsfb->linelen = xstate->image->stride;
@@ -867,7 +869,7 @@ static int x_initialise(nsfb_t *nsfb)
static int x_finalise(nsfb_t *nsfb)
{
- xstate_t *xstate = nsfb->frontend_priv;
+ xstate_t *xstate = nsfb->surface_priv;
if (xstate == NULL)
return 0;
@@ -890,7 +892,7 @@ static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
xcb_button_press_event_t *ebp;
xcb_key_press_event_t *ekp;
xcb_key_press_event_t *ekr;
- xstate_t *xstate = nsfb->frontend_priv;
+ xstate_t *xstate = nsfb->surface_priv;
if (xstate == NULL)
return false;
@@ -916,8 +918,10 @@ static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
retval = select(confd + 1, &rfds, NULL, NULL, &tv);
if (retval == 0) {
- return false; /* timeout, nothing happened */
-
+ /* timeout, nothing happened */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_TIMEOUT;
+ return true;
}
}
e = xcb_wait_for_event(xstate->connection);
@@ -1051,7 +1055,7 @@ static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
static int
x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
{
- xstate_t *xstate = nsfb->frontend_priv;
+ xstate_t *xstate = nsfb->surface_priv;
nsfb_bbox_t redraw;
nsfb_bbox_t fbarea;
@@ -1083,7 +1087,7 @@ x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
- xstate_t *xstate = nsfb->frontend_priv;
+ xstate_t *xstate = nsfb->surface_priv;
struct nsfb_cursor_s *cursor = nsfb->cursor;
if ((cursor != NULL) &&
@@ -1096,7 +1100,7 @@ static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
return 0;
}
-const nsfb_frontend_rtns_t x_rtns = {
+const nsfb_surface_rtns_t x_rtns = {
.initialise = x_initialise,
.finalise = x_finalise,
.input = x_input,
@@ -1106,4 +1110,11 @@ const nsfb_frontend_rtns_t x_rtns = {
.geometry = x_set_geometry,
};
-NSFB_FRONTEND_DEF(x, NSFB_FRONTEND_X, &x_rtns)
+NSFB_SURFACE_DEF(x, NSFB_SURFACE_X, &x_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/Makefile b/test/Makefile
index b2320e3..7f2d40e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := plottest:plottest.c;nsglobe.c frontend:frontend.c bezier:bezier.c path:path.c polygon:polygon.c polystar:polystar.c polystar2:polystar2.c
+DIR_TEST_ITEMS := plottest:plottest.c bitmap:bitmap.c;nsglobe.c frontend:frontend.c bezier:bezier.c path:path.c polygon:polygon.c polystar:polystar.c polystar2:polystar2.c
include build/makefiles/Makefile.subdir
diff --git a/test/bezier.c b/test/bezier.c
index d686349..630c4a8 100644
--- a/test/bezier.c
+++ b/test/bezier.c
@@ -13,8 +13,12 @@
int main(int argc, char **argv)
{
+ const char *fename;
+ enum nsfb_type_e fetype;
nsfb_t *nsfb;
nsfb_event_t event;
+ int waitloop = 3;
+
nsfb_bbox_t box;
nsfb_bbox_t box2;
uint8_t *fbptr;
@@ -24,25 +28,35 @@ int main(int argc, char **argv)
int loop;
nsfb_plot_pen_t pen;
- UNUSED(argc);
- UNUSED(argv);
+ if (argc < 2) {
+ fename="sdl";
+ } else {
+ fename = argv[1];
+ }
- nsfb = nsfb_init(NSFB_FRONTEND_SDL);
- if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n");
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
return 2;
}
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
+ }
+
/* get the geometry of the whole screen */
box.x0 = box.y0 = 0;
nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
- nsfb_get_framebuffer(nsfb, &fbptr, &fbstride);
+ nsfb_get_buffer(nsfb, &fbptr, &fbstride);
/* claim the whole screen for update */
nsfb_claim(nsfb, &box);
@@ -115,8 +129,29 @@ int main(int argc, char **argv)
nsfb_update(nsfb, &box);
- while (event.type != NSFB_EVENT_CONTROL)
- nsfb_event(nsfb, &event, -1);
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
+
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/bitmap.c b/test/bitmap.c
new file mode 100644
index 0000000..b14f2f6
--- /dev/null
+++ b/test/bitmap.c
@@ -0,0 +1,168 @@
+/* libnsfb plotter test program */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "libnsfb.h"
+#include "libnsfb_plot.h"
+#include "libnsfb_event.h"
+
+#define UNUSED(x) ((x) = (x))
+
+extern const struct {
+ unsigned int width;
+ unsigned int height;
+ unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
+ unsigned char pixel_data[132 * 135 * 4 + 1];
+} nsglobe;
+
+static bool
+dump(nsfb_t *nsfb, const char *filename)
+{
+ int fd;
+
+ if (filename == NULL)
+ return false;
+
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
+ if (fd < 0)
+ return false;
+
+ nsfb_dump(nsfb, fd);
+
+ close(fd);
+
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ const char *fename;
+ enum nsfb_type_e fetype;
+ nsfb_t *nsfb;
+ nsfb_t *bmp;
+ nsfb_event_t event;
+ int waitloop = 3;
+
+ nsfb_bbox_t box;
+ nsfb_bbox_t box2;
+ nsfb_bbox_t box3;
+ uint8_t *fbptr;
+ int fbstride;
+ const char *dumpfile = NULL;
+
+ if (argc < 2) {
+ fename="sdl";
+ } else {
+ fename = argv[1];
+ if (argc >= 3) {
+ dumpfile = argv[2];
+ }
+ }
+
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
+ return 1;
+ }
+
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
+ return 2;
+ }
+
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
+ }
+
+
+ bmp = nsfb_new(NSFB_SURFACE_RAM);
+ nsfb_set_geometry(bmp, nsglobe.width, nsglobe.height, NSFB_FMT_ABGR8888);
+ nsfb_init(bmp);
+ nsfb_get_buffer(bmp, &fbptr, &fbstride);
+
+ memcpy(fbptr, nsglobe.pixel_data, nsglobe.width * nsglobe.height * 4);
+
+ /* get the geometry of the whole screen */
+ box.x0 = box.y0 = 0;
+ nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
+
+ /* claim the whole screen for update */
+ nsfb_claim(nsfb, &box);
+
+ nsfb_plot_clg(nsfb, 0xffffffff);
+
+ box3.x0 = 0;
+ box3.y0 = 0;
+ box3.x1 = 132;
+ box3.y1 = 135;
+
+ nsfb_plot_copy(bmp, &box3, nsfb, &box3);
+
+ box3.x0 = 132;
+ box3.y0 = 135;
+ box3.x1 = box3.x0 + 264;
+ box3.y1 = box3.y0 + 135;
+
+ nsfb_plot_copy(bmp, &box3, nsfb, &box3);
+
+ box3.x0 = 396;
+ box3.y0 = 270;
+ box3.x1 = box3.x0 + 264;
+ box3.y1 = box3.y0 + 270;
+
+ nsfb_plot_copy(bmp, &box3, nsfb, &box3);
+
+ box2.x0 = 64;
+ box2.y0 = 64;
+ box2.x1 = 128;
+ box2.y1 = 128;
+
+ box3.x0 = 270;
+ box3.y0 = 270;
+ box3.x1 = box3.x0 + 64;
+ box3.y1 = box3.y0 + 64;
+
+ nsfb_plot_copy(nsfb, &box2, nsfb, &box3);
+
+ nsfb_update(nsfb, &box);
+
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
+
+ dump(nsfb, dumpfile);
+
+ nsfb_free(bmp);
+
+ nsfb_free(nsfb);
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/frontend.c b/test/frontend.c
index 3d72229..5cf0651 100644
--- a/test/frontend.c
+++ b/test/frontend.c
@@ -4,12 +4,16 @@
#include <unistd.h>
#include "libnsfb.h"
+#include "libnsfb_event.h"
int main(int argc, char **argv)
{
nsfb_t *nsfb;
const char *fename;
- enum nsfb_frontend_e fetype;
+ enum nsfb_type_e fetype;
+ nsfb_event_t event;
+
+ int waitloop = 3;
if (argc < 2) {
fename="sdl";
@@ -17,32 +21,52 @@ int main(int argc, char **argv)
fename = argv[1];
}
- fetype = nsfb_frontend_from_name(fename);
- if (fetype == NSFB_FRONTEND_NONE) {
- fprintf(stderr, "Unable to initialise nsfb with %s frontend\n", fename);
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- nsfb = nsfb_init(fetype);
+ nsfb = nsfb_new(fetype);
if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with %s frontend\n", fename);
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
return 2;
}
- if (nsfb_set_geometry(nsfb, 0, 0, 32) == -1) {
- fprintf(stderr, "Unable to set geometry\n");
- nsfb_finalise(nsfb);
+ if (nsfb_set_geometry(nsfb, 0, 0, NSFB_FMT_ANY) == -1) {
+ fprintf(stderr, "Unable to set surface geometry\n");
+ nsfb_free(nsfb);
return 3;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
- nsfb_finalise(nsfb);
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
return 4;
}
- sleep(2);
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
- nsfb_finalise(nsfb);
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/path.c b/test/path.c
index 16a8ce2..7f1c6d1 100644
--- a/test/path.c
+++ b/test/path.c
@@ -39,7 +39,12 @@ static int fill_shape(nsfb_plot_pathop_t *path, int xoff, int yoff)
int main(int argc, char **argv)
{
+ const char *fename;
+ enum nsfb_type_e fetype;
nsfb_t *nsfb;
+
+ int waitloop = 3;
+
nsfb_event_t event;
nsfb_bbox_t box;
uint8_t *fbptr;
@@ -47,25 +52,35 @@ int main(int argc, char **argv)
nsfb_plot_pen_t pen;
nsfb_plot_pathop_t path[20];
- UNUSED(argc);
- UNUSED(argv);
+ if (argc < 2) {
+ fename="sdl";
+ } else {
+ fename = argv[1];
+ }
- nsfb = nsfb_init(NSFB_FRONTEND_SDL);
- if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n");
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
return 2;
}
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
+ }
+
/* get the geometry of the whole screen */
box.x0 = box.y0 = 0;
nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
- nsfb_get_framebuffer(nsfb, &fbptr, &fbstride);
+ nsfb_get_buffer(nsfb, &fbptr, &fbstride);
/* claim the whole screen for update */
nsfb_claim(nsfb, &box);
@@ -87,11 +102,31 @@ int main(int argc, char **argv)
nsfb_plot_path(nsfb, fill_shape(path, 100, 350), path, &pen);
-
nsfb_update(nsfb, &box);
-
- while (event.type != NSFB_EVENT_CONTROL)
- nsfb_event(nsfb, &event, -1);
+
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
+
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/plottest.c b/test/plottest.c
index 74134c4..a4cde36 100644
--- a/test/plottest.c
+++ b/test/plottest.c
@@ -1,8 +1,12 @@
-/* libnsfb plotetr test program */
+/* libnsfb plotter test program */
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include "libnsfb.h"
#include "libnsfb_plot.h"
@@ -10,13 +14,6 @@
#define UNUSED(x) ((x) = (x))
-extern const struct {
- unsigned int width;
- unsigned int height;
- unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
- unsigned char pixel_data[132 * 135 * 4 + 1];
-} nsglobe;
-
const struct {
unsigned int w;
unsigned int h;
@@ -67,11 +64,34 @@ const struct {
}
};
+
+static bool
+dump(nsfb_t *nsfb, const char *filename)
+{
+ int fd;
+
+ if (filename == NULL)
+ return false;
+
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
+ if (fd < 0)
+ return false;
+
+ nsfb_dump(nsfb, fd);
+
+ close(fd);
+
+ return true;
+}
+
int main(int argc, char **argv)
{
+ const char *fename;
+ enum nsfb_type_e fetype;
nsfb_t *nsfb;
- int bpp;
nsfb_event_t event;
+ int waitloop = 3;
+
nsfb_bbox_t box;
nsfb_bbox_t box2;
nsfb_bbox_t box3;
@@ -80,37 +100,40 @@ int main(int argc, char **argv)
int p[] = { 300,300, 350,350, 400,300, 450,250, 400,200};
int loop;
nsfb_plot_pen_t pen;
+ const char *dumpfile = NULL;
if (argc < 2) {
- bpp = 32;
+ fename="sdl";
} else {
- bpp = atoi(argv[1]);
- if (bpp == 0)
- bpp = 32;
+ fename = argv[1];
+ if (argc >= 3) {
+ dumpfile = argv[2];
+ }
}
- nsfb = nsfb_init(NSFB_FRONTEND_SDL);
- if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n");
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- if (nsfb_set_geometry(nsfb, 0, 0, bpp) == -1) {
- fprintf(stderr, "Unable to set geometry\n");
- nsfb_finalise(nsfb);
- return 3;
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
+ return 2;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
- return 2;
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
}
/* get the geometry of the whole screen */
box.x0 = box.y0 = 0;
nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
- nsfb_get_framebuffer(nsfb, &fbptr, &fbstride);
+ nsfb_get_buffer(nsfb, &fbptr, &fbstride);
/* claim the whole screen for update */
nsfb_claim(nsfb, &box);
@@ -219,14 +242,7 @@ int main(int argc, char **argv)
box3.x1 = 700;
box3.y1 = 300;
- nsfb_plot_copy(nsfb, &box2, &box3);
-
- box3.x0 = 50;
- box3.x1 = 200;
- box3.y0 = 300;
- box3.y1 = 500;
-
- nsfb_plot_bitmap(nsfb, &box3, (nsfb_colour_t *)nsglobe.pixel_data, nsglobe.width, nsglobe.height, nsglobe.width, true);
+ nsfb_plot_copy(nsfb, &box2, nsfb, &box3);
/* test glyph plotting */
for (loop = 100; loop < 200; loop+= Mglyph1.w) {
@@ -270,9 +286,31 @@ int main(int argc, char **argv)
nsfb_update(nsfb, &box2);
}
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
- while (event.type != NSFB_EVENT_CONTROL)
- nsfb_event(nsfb, &event, -1);
+ dump(nsfb, dumpfile);
+
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/polygon.c b/test/polygon.c
index cd7efd8..e91846f 100644
--- a/test/polygon.c
+++ b/test/polygon.c
@@ -14,8 +14,12 @@
int main(int argc, char **argv)
{
+ const char *fename;
+ enum nsfb_type_e fetype;
nsfb_t *nsfb;
nsfb_event_t event;
+ int waitloop = 3;
+
nsfb_bbox_t box;
uint8_t *fbptr;
int fbstride;
@@ -26,25 +30,35 @@ int main(int argc, char **argv)
int loop;
// nsfb_plot_pen_t pen;
- UNUSED(argc);
- UNUSED(argv);
+ if (argc < 2) {
+ fename="sdl";
+ } else {
+ fename = argv[1];
+ }
- nsfb = nsfb_init(NSFB_FRONTEND_SDL);
- if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n");
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
return 2;
}
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
+ }
+
/* get the geometry of the whole screen */
box.x0 = box.y0 = 0;
nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
- nsfb_get_framebuffer(nsfb, &fbptr, &fbstride);
+ nsfb_get_buffer(nsfb, &fbptr, &fbstride);
/* claim the whole screen for update */
nsfb_claim(nsfb, &box);
@@ -72,8 +86,29 @@ int main(int argc, char **argv)
nsfb_update(nsfb, &box);
- while (event.type != NSFB_EVENT_CONTROL)
- nsfb_event(nsfb, &event, -1);
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
+
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/polystar.c b/test/polystar.c
index 6963cfb..c71ba41 100644
--- a/test/polystar.c
+++ b/test/polystar.c
@@ -24,7 +24,12 @@ static void sleepMilli(long ms)
int main(int argc, char **argv)
{
+ const char *fename;
+ enum nsfb_type_e fetype;
nsfb_t *nsfb;
+
+ int waitloop = 3;
+
nsfb_event_t event;
nsfb_bbox_t box;
uint8_t *fbptr;
@@ -38,25 +43,35 @@ int main(int argc, char **argv)
double rotate;
- UNUSED(argc);
- UNUSED(argv);
+ if (argc < 2) {
+ fename="sdl";
+ } else {
+ fename = argv[1];
+ }
- nsfb = nsfb_init(NSFB_FRONTEND_SDL);
- if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n");
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
return 2;
}
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
+ }
+
/* get the geometry of the whole screen */
box.x0 = box.y0 = 0;
nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
- nsfb_get_framebuffer(nsfb, &fbptr, &fbstride);
+ nsfb_get_buffer(nsfb, &fbptr, &fbstride);
pen.stroke_colour = 0xff000000;
@@ -99,8 +114,29 @@ int main(int argc, char **argv)
sleepMilli(100);
}
- while (event.type != NSFB_EVENT_CONTROL)
- nsfb_event(nsfb, &event, -1);
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
+
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/polystar2.c b/test/polystar2.c
index 479a45b..afff5a0 100644
--- a/test/polystar2.c
+++ b/test/polystar2.c
@@ -25,7 +25,12 @@ static void sleepMilli(long ms)
int main(int argc, char **argv)
{
+ const char *fename;
+ enum nsfb_type_e fetype;
nsfb_t *nsfb;
+
+ int waitloop = 3;
+
nsfb_event_t event;
nsfb_bbox_t box;
uint8_t *fbptr;
@@ -38,24 +43,34 @@ int main(int argc, char **argv)
int counter;
int colour;
- UNUSED(argc);
- UNUSED(argv);
+ if (argc < 2) {
+ fename="sdl";
+ } else {
+ fename = argv[1];
+ }
- nsfb = nsfb_init(NSFB_FRONTEND_SDL);
- if (nsfb == NULL) {
- fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n");
+ fetype = nsfb_type_from_name(fename);
+ if (fetype == NSFB_SURFACE_NONE) {
+ fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename);
return 1;
}
- if (nsfb_init_frontend(nsfb) == -1) {
- fprintf(stderr, "Unable to initialise nsfb frontend\n");
+ nsfb = nsfb_new(fetype);
+ if (nsfb == NULL) {
+ fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename);
return 2;
}
+ if (nsfb_init(nsfb) == -1) {
+ fprintf(stderr, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return 4;
+ }
+
/* get the geometry of the whole screen */
box.x0 = box.y0 = 0;
nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL);
- nsfb_get_framebuffer(nsfb, &fbptr, &fbstride);
+ nsfb_get_buffer(nsfb, &fbptr, &fbstride);
radius = (box.x1 / 3);
sides = 5;
@@ -92,8 +107,29 @@ int main(int argc, char **argv)
sleepMilli(400);
}
- while (event.type != NSFB_EVENT_CONTROL)
- nsfb_event(nsfb, &event, -1);
+ /* wait for quit event or timeout */
+ while (waitloop > 0) {
+ if (nsfb_event(nsfb, &event, 1000) == false) {
+ break;
+ }
+ if (event.type == NSFB_EVENT_CONTROL) {
+ if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) {
+ /* timeout */
+ waitloop--;
+ } else if (event.value.controlcode == NSFB_CONTROL_QUIT) {
+ break;
+ }
+ }
+ }
+
+ nsfb_free(nsfb);
return 0;
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/runtest.sh b/test/runtest.sh
index f2eb0a4..5d131ab 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -2,11 +2,14 @@
TEST_PATH=$1
-${TEST_PATH}/test_frontend
-${TEST_PATH}/test_plottest
-${TEST_PATH}/test_bezier
-${TEST_PATH}/test_path
-${TEST_PATH}/test_polygon
-${TEST_PATH}/test_polystar
-${TEST_PATH}/test_polystar2
+TEST_FRONTEND=x
+
+${TEST_PATH}/test_frontend ${TEST_FRONTEND}
+${TEST_PATH}/test_plottest ${TEST_FRONTEND}
+${TEST_PATH}/test_bitmap ${TEST_FRONTEND}
+${TEST_PATH}/test_bezier ${TEST_FRONTEND}
+${TEST_PATH}/test_path ${TEST_FRONTEND}
+${TEST_PATH}/test_polygon ${TEST_FRONTEND}
+${TEST_PATH}/test_polystar ${TEST_FRONTEND}
+${TEST_PATH}/test_polystar2 ${TEST_FRONTEND}