diff options
author | Vincent Sanders <vince@netsurf-browser.org> | 2012-03-22 16:55:36 +0000 |
---|---|---|
committer | Vincent Sanders <vince@netsurf-browser.org> | 2012-03-22 16:55:36 +0000 |
commit | 51d8264eb1e8f705635cd0af2c0e9dddaf855711 (patch) | |
tree | 25bdda51e22072965b65545fabea1cf957f6d303 /src/surface | |
parent | 4875d9f650071c8cd6d2976ea6f88f18bc8cc10b (diff) | |
download | libnsfb-51d8264eb1e8f705635cd0af2c0e9dddaf855711.tar.gz libnsfb-51d8264eb1e8f705635cd0af2c0e9dddaf855711.tar.bz2 |
basic fixes for linux framebuffer surface
svn path=/trunk/libnsfb/; revision=13550
Diffstat (limited to 'src/surface')
-rw-r--r-- | src/surface/linux.c | 149 | ||||
-rw-r--r-- | src/surface/surface.c | 25 |
2 files changed, 160 insertions, 14 deletions
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; } |