summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2012-03-22 16:55:36 (GMT)
committer Vincent Sanders <vince@netsurf-browser.org>2012-03-22 16:55:36 (GMT)
commit51d8264eb1e8f705635cd0af2c0e9dddaf855711 (patch)
tree25bdda51e22072965b65545fabea1cf957f6d303
parent4875d9f650071c8cd6d2976ea6f88f18bc8cc10b (diff)
downloadlibnsfb-51d8264eb1e8f705635cd0af2c0e9dddaf855711.tar.gz
libnsfb-51d8264eb1e8f705635cd0af2c0e9dddaf855711.tar.bz2
basic fixes for linux framebuffer surface
svn path=/trunk/libnsfb/; revision=13550
-rw-r--r--Makefile2
-rw-r--r--include/libnsfb.h15
-rw-r--r--include/nsfb.h6
-rw-r--r--include/surface.h36
-rw-r--r--src/libnsfb.c17
-rw-r--r--src/plot/generic.c10
-rw-r--r--src/surface/linux.c149
-rw-r--r--src/surface/surface.c25
-rw-r--r--test/polystar.c2
-rw-r--r--test/polystar2.c2
-rwxr-xr-xtest/runtest.sh2
11 files changed, 223 insertions, 43 deletions
diff --git a/Makefile b/Makefile
index 9601727..da61c37 100644
--- a/Makefile
+++ b/Makefile
@@ -51,7 +51,7 @@ ifeq ($(NSFB_VNC_AVAILABLE),yes)
REQUIRED_PKGS := $(REQUIRED_PKGS) libvncserver
endif
-TESTLDFLAGS := -Wl,--whole-archive -l$(COMPONENT) -Wl,--no-whole-archive $(TESTLDFLAGS)
+TESTLDFLAGS := -lm -Wl,--whole-archive -l$(COMPONENT) -Wl,--no-whole-archive $(TESTLDFLAGS)
include build/makefiles/Makefile.top
diff --git a/include/libnsfb.h b/include/libnsfb.h
index 330c476..739617e 100644
--- a/include/libnsfb.h
+++ b/include/libnsfb.h
@@ -118,15 +118,26 @@ int nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box);
*/
int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, enum nsfb_format_e *format);
-/** Alter the geometry of a framebuffer context
+/** Alter the geometry of a surface
*
* @param nsfb The context to alter.
* @param width The new display width.
* @param height The new display height.
- * @param bpp The new display depth.
+ * @param format The desired surface format.
*/
int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format);
+/** Set parameters a surface
+ *
+ * Some surface types can take additional parameters for
+ * attributes. For example the linux surface uses this to allow the
+ * setting of a different output device
+ *
+ * @param nsfb The surface to alter.
+ * @param parameters The parameters for the surface.
+ */
+int nsfb_set_parameters(nsfb_t *nsfb, const char *parameters);
+
/** Obtain the buffer memory base and stride.
*
* @param nsfb The context to read.
diff --git a/include/nsfb.h b/include/nsfb.h
index 9b1619c..5caff9b 100644
--- a/include/nsfb.h
+++ b/include/nsfb.h
@@ -20,12 +20,10 @@ struct nsfb_s {
int width; /**< Visible width. */
int height; /**< Visible height. */
- int bpp;
+ char *parameters;
enum nsfb_format_e format; /**< Framebuffer format */
-
- int refresh; /**< Desired refresh rate for physical displays. */
- char *output_dev; /**> Path to output device for surfaces that require it. */
+ int bpp; /**< Bits per pixel - distinct from format */
uint8_t *ptr; /**< Base of video memory. */
int linelen; /**< length of a video line. */
diff --git a/include/surface.h b/include/surface.h
index d0c6c5a..efb84fb 100644
--- a/include/surface.h
+++ b/include/surface.h
@@ -5,38 +5,42 @@
#include "nsfb.h"
/* surface default options */
-typedef int (nsfb_fendfn_defaults_t)(nsfb_t *nsfb);
+typedef int (nsfb_surfacefn_defaults_t)(nsfb_t *nsfb);
/* surface init */
-typedef int (nsfb_fendfn_init_t)(nsfb_t *nsfb);
+typedef int (nsfb_surfacefn_init_t)(nsfb_t *nsfb);
/* surface finalise */
-typedef int (nsfb_fendfn_fini_t)(nsfb_t *nsfb);
+typedef int (nsfb_surfacefn_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);
+typedef int (nsfb_surfacefn_geometry_t)(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format);
+
+/* surface set parameters */
+typedef int (nsfb_surfacefn_parameters_t)(nsfb_t *nsfb, const char *parameters);
/* surface input */
-typedef bool (nsfb_fendfn_input_t)(nsfb_t *nsfb, nsfb_event_t *event, int timeout);
+typedef bool (nsfb_surfacefn_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);
+typedef int (nsfb_surfacefn_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);
+typedef int (nsfb_surfacefn_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 int (nsfb_surfacefn_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_surfacefn_defaults_t *defaults;
+ nsfb_surfacefn_init_t *initialise;
+ nsfb_surfacefn_fini_t *finalise;
+ nsfb_surfacefn_geometry_t *geometry;
+ nsfb_surfacefn_parameters_t *parameters;
+ nsfb_surfacefn_input_t *input;
+ nsfb_surfacefn_claim_t *claim;
+ nsfb_surfacefn_update_t *update;
+ nsfb_surfacefn_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);
diff --git a/src/libnsfb.c b/src/libnsfb.c
index 21661cd..6f14c99 100644
--- a/src/libnsfb.c
+++ b/src/libnsfb.c
@@ -9,6 +9,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "libnsfb.h"
#include "libnsfb_plot.h"
@@ -92,6 +93,22 @@ nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format
}
/* exported interface documented in libnsfb.h */
+int nsfb_set_parameters(nsfb_t *nsfb, const char *parameters)
+{
+ if ((parameters == NULL) || (*parameters == 0)) {
+ return -1;
+ }
+
+ if (nsfb->parameters != NULL) {
+ free(nsfb->parameters);
+ }
+
+ nsfb->parameters = strdup(parameters);
+
+ return nsfb->surface_rtns->parameters(nsfb, parameters);
+}
+
+/* exported interface documented in libnsfb.h */
int
nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, enum nsfb_format_e *format)
{
diff --git a/src/plot/generic.c b/src/plot/generic.c
index 63845e4..6a627ff 100644
--- a/src/plot/generic.c
+++ b/src/plot/generic.c
@@ -858,20 +858,20 @@ bool select_plotters(nsfb_t *nsfb)
switch (nsfb->format) {
- case NSFB_FMT_XBGR8888: /* 32bpp Blue Green Red */
- case NSFB_FMT_ABGR8888: /* 32bpp Alpga Blue Green Red */
+ case NSFB_FMT_XBGR8888: /* 32bpp Unused Blue Green Red */
+ case NSFB_FMT_ABGR8888: /* 32bpp Alpha 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 */
+ case NSFB_FMT_XRGB8888: /* 32bpp Unused Red Green Blue */
+ case NSFB_FMT_ARGB8888: /* 32bpp Alpha Red Green Blue */
table = &_nsfb_32bpp_plotters;
nsfb->bpp = 32;
break;
- case NSFB_FMT_RGB888: /* 24 bpp Alpga Red Green Blue */
+ case NSFB_FMT_RGB888: /* 24 bpp Alpha Red Green Blue */
#ifdef ENABLE_24_BPP
table = &_nsfb_24bpp_plotters;
nsfb->bpp = 24;
diff --git a/src/surface/linux.c b/src/surface/linux.c
index 8c9ffec..d524002 100644
--- a/src/surface/linux.c
+++ b/src/surface/linux.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2012 Vincent Sanders <vince@simtec.co.uk>
*
* This file is part of libnsfb, http://www.netsurf-browser.org/
* Licenced under the MIT License,
@@ -8,6 +8,18 @@
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include <linux/fb.h>
+
#include "libnsfb.h"
#include "libnsfb_event.h"
@@ -20,39 +32,153 @@
#include "cursor.h"
+
#define UNUSED(x) ((x) = (x))
+#define FB_NAME "/dev/fb0"
+
+struct lnx_priv {
+ struct fb_fix_screeninfo FixInfo;
+ struct fb_var_screeninfo VarInfo;
+ int fd;
+};
+
static int linux_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
- if (nsfb->surface_priv != NULL)
+ if (nsfb->surface_priv != NULL) {
return -1; /* if we are already initialised fail */
+ }
nsfb->width = width;
nsfb->height = height;
nsfb->format = format;
/* select default sw plotters for bpp */
- select_plotters(nsfb);
+ if (select_plotters(nsfb) != true) {
+ return -1;
+ }
return 0;
}
+static enum nsfb_format_e
+format_from_lstate(struct lnx_priv *lstate)
+{
+ enum nsfb_format_e fmt = NSFB_FMT_ANY;
+
+ switch(lstate->VarInfo.bits_per_pixel) {
+ case 32:
+ if (lstate->VarInfo.transp.length == 0)
+ fmt = NSFB_FMT_XBGR8888;
+ else
+ fmt = NSFB_FMT_ABGR8888;
+ break;
+
+ case 24:
+ fmt = NSFB_FMT_RGB888;
+ break;
+
+ case 16:
+ fmt = NSFB_FMT_RGB565;
+ break;
+
+ case 8:
+ fmt = NSFB_FMT_I8;
+ break;
+
+ case 1:
+ fmt = NSFB_FMT_RGB565;
+ break;
+
+ }
+
+
+ return fmt;
+}
+
static int linux_initialise(nsfb_t *nsfb)
{
+ int iFrameBufferSize;
+ struct lnx_priv *lstate;
+ enum nsfb_format_e lformat;
+
if (nsfb->surface_priv != NULL)
- return -1;
+ return -1;
- /* sanity checked depth. */
- if ((nsfb->bpp != 32) && (nsfb->bpp != 16) && (nsfb->bpp != 8))
- return -1;
+ lstate = calloc(1, sizeof(struct lnx_priv));
+ /* Open the framebuffer device in read write */
+ lstate->fd = open(FB_NAME, O_RDWR);
+ if (lstate->fd < 0) {
+ printf("Unable to open %s.\n", FB_NAME);
+ return -1;
+ }
+
+ /* Do Ioctl. Retrieve fixed screen info. */
+ if (ioctl(lstate->fd, FBIOGET_FSCREENINFO, &lstate->FixInfo) < 0) {
+ printf("get fixed screen info failed: %s\n",
+ strerror(errno));
+ close(lstate->fd);
+ free(lstate);
+ return -1;
+ }
+
+ /* Do Ioctl. Get the variable screen info. */
+ if (ioctl(lstate->fd, FBIOGET_VSCREENINFO, &lstate->VarInfo) < 0) {
+ printf("Unable to retrieve variable screen info: %s\n",
+ strerror(errno));
+ close(lstate->fd);
+ free(lstate);
+ return -1;
+ }
+
+ /* Calculate the size to mmap */
+ iFrameBufferSize = lstate->FixInfo.line_length * lstate->VarInfo.yres;
+
+ /* Now mmap the framebuffer. */
+ nsfb->ptr = mmap(NULL, iFrameBufferSize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, lstate->fd, 0);
+ if (nsfb->ptr == NULL) {
+ printf("mmap failed:\n");
+ close(lstate->fd);
+ free(lstate);
+ return -1;
+ }
+
+ nsfb->linelen = lstate->FixInfo.line_length;
+
+ nsfb->width = lstate->VarInfo.xres;
+ nsfb->height = lstate->VarInfo.yres;
+
+ lformat = format_from_lstate(lstate);
+
+ if (nsfb->format != lformat) {
+ nsfb->format = lformat;
+
+ /* select default sw plotters for format */
+ if (select_plotters(nsfb) != true) {
+ munmap(nsfb->ptr, 0);
+ close(lstate->fd);
+ free(lstate);
+ return -1;
+ }
+ }
+
+ nsfb->surface_priv = lstate;
return 0;
}
static int linux_finalise(nsfb_t *nsfb)
{
- UNUSED(nsfb);
+ struct lnx_priv *lstate = nsfb->surface_priv;
+
+ if (lstate != NULL) {
+ munmap(nsfb->ptr, 0);
+ close(lstate->fd);
+ free(lstate);
+ }
+
return 0;
}
@@ -133,3 +259,10 @@ const nsfb_surface_rtns_t linux_rtns = {
};
NSFB_SURFACE_DEF(linux, NSFB_SURFACE_LINUX, &linux_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/surface.c b/src/surface/surface.c
index b2cf769..f3127bd 100644
--- a/src/surface/surface.c
+++ b/src/surface/surface.c
@@ -17,6 +17,8 @@
#define MAX_SURFACES 16
+#define UNUSED(x) ((x) = (x))
+
struct nsfb_surface_s {
enum nsfb_type_e type;
const nsfb_surface_rtns_t *rtns;
@@ -56,22 +58,29 @@ static int surface_defaults(nsfb_t *nsfb)
static int surface_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
{
- nsfb=nsfb;
- box=box;
+ UNUSED(nsfb);
+ UNUSED(box);
return 0;
}
static int surface_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
- nsfb=nsfb;
- box=box;
+ UNUSED(nsfb);
+ UNUSED(box);
return 0;
}
static int surface_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
{
- nsfb=nsfb;
- cursor=cursor;
+ UNUSED(nsfb);
+ UNUSED(cursor);
+ return 0;
+}
+
+static int surface_parameters(nsfb_t *nsfb, const char *parameters)
+{
+ UNUSED(nsfb);
+ UNUSED(parameters);
return 0;
}
@@ -118,6 +127,10 @@ nsfb_surface_get_rtns(enum nsfb_type_e type)
if (rtns->cursor == NULL) {
rtns->cursor = surface_cursor;
}
+
+ if (rtns->parameters == NULL) {
+ rtns->parameters = surface_parameters;
+ }
break;
}
diff --git a/test/polystar.c b/test/polystar.c
index c71ba41..7ab6cdc 100644
--- a/test/polystar.c
+++ b/test/polystar.c
@@ -1,6 +1,8 @@
/* libnsfb ploygon plotter test program */
+#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199506L
+#endif
#include <stdio.h>
#include <stdbool.h>
diff --git a/test/polystar2.c b/test/polystar2.c
index afff5a0..164d429 100644
--- a/test/polystar2.c
+++ b/test/polystar2.c
@@ -1,6 +1,8 @@
/* libnsfb ploygon plotter test program */
+#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199506L
+#endif
#include <stdio.h>
#include <stdbool.h>
diff --git a/test/runtest.sh b/test/runtest.sh
index 5d131ab..2f484e6 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -2,7 +2,7 @@
TEST_PATH=$1
-TEST_FRONTEND=x
+TEST_FRONTEND=linux
${TEST_PATH}/test_frontend ${TEST_FRONTEND}
${TEST_PATH}/test_plottest ${TEST_FRONTEND}