From 51d8264eb1e8f705635cd0af2c0e9dddaf855711 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 22 Mar 2012 16:55:36 +0000 Subject: basic fixes for linux framebuffer surface svn path=/trunk/libnsfb/; revision=13550 --- Makefile | 2 +- include/libnsfb.h | 15 ++++- include/nsfb.h | 6 +- include/surface.h | 36 ++++++------ src/libnsfb.c | 17 ++++++ src/plot/generic.c | 10 ++-- src/surface/linux.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++--- src/surface/surface.c | 25 +++++++-- test/polystar.c | 2 + test/polystar2.c | 2 + test/runtest.sh | 2 +- 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 #include #include +#include #include "libnsfb.h" #include "libnsfb_plot.h" @@ -91,6 +92,22 @@ nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format return nsfb->surface_rtns->geometry(nsfb, width, height, 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 + * Copyright 2012 Vincent Sanders * * This file is part of libnsfb, http://www.netsurf-browser.org/ * Licenced under the MIT License, @@ -8,6 +8,18 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #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 #include 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 #include 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} -- cgit v1.2.3