diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2018-02-20 10:13:24 +0800 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2018-04-12 14:22:33 +0800 |
commit | c368ccb16b1e996846f47a7c640250a380401e01 (patch) | |
tree | 215191c65fac87ffd971842b8f6020f5cabbe237 | |
parent | 0a58169a7838f74332e74393c4b87f40840e0b41 (diff) | |
download | fbterm-c368ccb16b1e996846f47a7c640250a380401e01.tar.gz fbterm-c368ccb16b1e996846f47a7c640250a380401e01.zip |
Add a shared-memory framebuffer output method
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/fbconfig.cpp | 4 | ||||
-rw-r--r-- | src/fbshm.cpp | 157 | ||||
-rw-r--r-- | src/fbshm.h | 39 | ||||
-rw-r--r-- | src/screen.cpp | 17 |
5 files changed, 215 insertions, 4 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e99f752..d942176 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,7 @@ bin_PROGRAMS = fbterm fbterm_SOURCES = fbconfig.cpp fbconfig.h fbio.cpp fbio.h fbshell.cpp fbshell.h fbshellman.cpp fbshellman.h fbterm.cpp \ fbterm.h font.cpp font.h input.cpp input.h input_key.h mouse.cpp mouse.h screen.cpp screen.h improxy.cpp improxy.h \ - screen_render.cpp fbdev.cpp fbdev.h vesadev.cpp vesadev.h vbe.h + screen_render.cpp fbdev.cpp fbdev.h fbshm.cpp fbshm.h vesadev.cpp vesadev.h vbe.h EXTRA_fbterm_SOURCES = signalfd.h fbterm_CXXFLAGS = -fno-exceptions -fno-rtti -I$(top_srcdir)/src/lib @FT2_CFLAGS@ @FC_CFLAGS@ diff --git a/src/fbconfig.cpp b/src/fbconfig.cpp index 14240b6..f1985d0 100644 --- a/src/fbconfig.cpp +++ b/src/fbconfig.cpp @@ -237,6 +237,7 @@ bool Config::parseArgs(s32 argc, s8 **argv) { "font-width", required_argument, 0, 2 }, { "font-height", required_argument, 0, 4 }, { "ambiguous-wide", no_argument, 0, 'a' }, + { "shared-mem", required_argument, 0, 'm' }, #ifdef ENABLE_VESA { "vesa-mode", required_argument, 0, 3 }, #endif @@ -244,7 +245,7 @@ bool Config::parseArgs(s32 argc, s8 **argv) }; s32 index; - while ((index = getopt_long(argc, argv, "Vvhn:s:f:b:e:r:i:a", options, 0)) != -1) { + while ((index = getopt_long(argc, argv, "Vvhn:s:f:b:e:r:i:m:a", options, 0)) != -1) { switch (index) { case 'V': printf("FbTerm version " VERSION "\n"); @@ -269,6 +270,7 @@ bool Config::parseArgs(s32 argc, s8 **argv) " -r, --screen-rotate=NUM specify orientation of screen display\n" " -a, --ambiguous-wide treat ambiguous width characters as wide\n" " -i, --input-method=TEXT specify input method program\n" + " -m, --shared-mem=DESC use shared-memory framebuffer DESC\n" " --cursor-shape=NUM specify default cursor shape\n" " --cursor-interval=NUM specify cursor flash interval\n" #ifdef ENABLE_VESA diff --git a/src/fbshm.cpp b/src/fbshm.cpp new file mode 100644 index 0000000..48d0c38 --- /dev/null +++ b/src/fbshm.cpp @@ -0,0 +1,157 @@ +/* + * Copyright © 2018 IBM Corporation + * This file is part of FbTerm. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/mman.h> +#include "fbconfig.h" +#include "fbshm.h" + +int FbShm::parse_shm_desc(const char *desc, char **file, + int *rows, int *cols, int *bpp) +{ + char *str, *sep, *endp; + unsigned long tmp; + + str = strdup(desc); + + /* <file>:<cols>x<rows>@<bpp> */ + + /* file */ + sep = strchr(str, ':'); + if (!sep) + goto err_free; + + *file = str; + *sep = '\0'; + + /* cols */ + str = sep + 1; + sep = strchr(str, 'x'); + if (!sep) { + fprintf(stderr, "can't parse shm descriptor %s: no geom\n", + desc); + goto err_free; + } + *sep = '\0'; + + tmp = strtoul(str, &endp, 10); + if (endp != sep) { + fprintf(stderr, + "can't parse shm descriptor %s: invalid cols %s\n", + desc, str); + goto err_free; + } + + *cols = (int)(tmp & 0xffffffff); + + /* rows */ + str = sep + 1; + sep = strchr(str, '@'); + if (!sep) { + fprintf(stderr, "can't parse shm descriptor %s: no geom\n", + desc); + goto err_free; + } + *sep = '\0'; + + tmp = strtoul(str, &endp, 10); + if (endp != sep) { + fprintf(stderr, + "can't parse shm descriptor %s: invalid rows %s\n", + desc, str); + goto err_free; + } + + *rows = (int)(tmp & 0xffffffff); + + /* bpp */ + tmp = strtoul(sep + 1, &endp, 10); + if (*endp != '\0' || endp == str) { + fprintf(stderr, + "can't parse shm descriptor %s: invalid bpp\n", + desc); + goto err_free; + } + + *bpp = (int)(tmp & 0xff); + + printf("%s: rows %d, cols %d, bpp %d\n", *file, *rows, *cols, *bpp); + + return 0; + +err_free: + free(str); + return -1; +} + +FbShm *FbShm::initFbShm() +{ + int rows, cols, bpp; + s8 *file, desc[4096]; + int fd; + + Config::instance()->getOption("shared-mem", desc, sizeof(desc)); + + if (!strlen(desc)) + return 0; + + if (parse_shm_desc(desc, &file, &rows, &cols, &bpp)) + return 0; + + fd = open(file, O_RDWR); + if (fd < 0) { + fprintf(stderr, "can't open frame buffer shm %s: %m\n", file); + free(file); + return 0; + } + + free(file); + + return new FbShm(fd, rows, cols, bpp); +} + +FbShm::FbShm(int fd, int rows, int cols, int bpp) +{ + mWidth = cols; + mHeight = rows; + mBitsPerPixel = bpp; + mBytesPerLine = cols * (bpp >> 3); + mFD = fd; + + + mVMemBase = (u8 *)mmap(0, mHeight * mBytesPerLine, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +} + +FbShm::~FbShm() +{ + munmap(mVMemBase, mHeight * mBytesPerLine); + close(mFD); +} + +const s8 *FbShm::drvId() +{ + return "shm"; +} + diff --git a/src/fbshm.h b/src/fbshm.h new file mode 100644 index 0000000..3b85726 --- /dev/null +++ b/src/fbshm.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2018 IBM Corporation + * This file is part of FbTerm. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef FBSHM_H +#define FBSHM_H + +#include "screen.h" + +class FbShm : public Screen { +private: + friend class Screen; + static FbShm *initFbShm(); + static int parse_shm_desc(const char *desc, char **file, + int *rows, int *cols, int *bpp); + int mFD; + + FbShm(int fd, int rows, int cols, int bpp); + ~FbShm(); + + virtual const s8 *drvId(); +}; +#endif diff --git a/src/screen.cpp b/src/screen.cpp index 4da2453..fee1f05 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -26,6 +26,7 @@ #include "fbshellman.h" #include "fbconfig.h" #include "fbdev.h" +#include "fbshm.h" #include "config.h" #ifdef ENABLE_VESA #include "vesadev.h" @@ -45,6 +46,7 @@ DEFINE_INSTANCE(Screen) Screen *Screen::createInstance() { + if (!Font::instance() || !FW(1) || !FH(1)) { fprintf(stderr, "init font error!\n"); return 0; @@ -52,6 +54,9 @@ Screen *Screen::createInstance() Screen *pScreen = 0; + s8 shm_info[2]; + Config::instance()->getOption("shared-mem", shm_info, sizeof(shm_info)); + #ifdef ENABLE_VESA s8 buf[16]; Config::instance()->getOption("vesa-mode", buf, sizeof(buf)); @@ -63,10 +68,18 @@ Screen *Screen::createInstance() u32 mode = 0; Config::instance()->getOption("vesa-mode", mode); - if (!mode) pScreen = FbDev::initFbDev(); + if (!mode) { + if (strlen(shm_info)) + pScreen = FbShm::initFbShm(); + else + pScreen = FbDev::initFbDev(); + } if (!pScreen) pScreen = VesaDev::initVesaDev(mode); #else - pScreen = FbDev::initFbDev(); + if (strlen(shm_info)) + pScreen = FbShm::initFbShm(); + else + pScreen = FbDev::initFbDev(); #endif if (!pScreen) return 0; |