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 --- src/libnsfb.c | 17 ++++++ src/plot/generic.c | 10 ++-- src/surface/linux.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++--- src/surface/surface.c | 25 +++++++-- 4 files changed, 182 insertions(+), 19 deletions(-) (limited to 'src') 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; } -- cgit v1.2.3