diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am index 298e9274d..ac05d73fd 100644 --- a/src/driver/Makefile.am +++ b/src/driver/Makefile.am @@ -85,6 +85,7 @@ endif if BOXTYPE_ARMBOX libneutrino_driver_a_SOURCES += \ fb_accel.cpp \ + fb_accel_arm.cpp \ simple_display.cpp endif if USE_STB_HAL diff --git a/src/driver/fb_accel.h b/src/driver/fb_accel.h index 6343056f9..d293b062e 100644 --- a/src/driver/fb_accel.h +++ b/src/driver/fb_accel.h @@ -209,4 +209,19 @@ class CFbAccelTD void setBlendLevel(int); }; +class CFbAccelARM + : public CFbAccel +{ + private: + fb_pixel_t *backbuffer; + public: + CFbAccelARM(); + ~CFbAccelARM(); + fb_pixel_t * getBackBufferPointer() const; + int setMode(unsigned int xRes, unsigned int yRes, unsigned int bpp); + int scale2Res(int size); + bool fullHdAvailable(); + void setOsdResolutions(); +}; + #endif diff --git a/src/driver/fb_accel_arm.cpp b/src/driver/fb_accel_arm.cpp new file mode 100644 index 000000000..ff35791b3 --- /dev/null +++ b/src/driver/fb_accel_arm.cpp @@ -0,0 +1,221 @@ +/* + Framebuffer acceleration hardware abstraction functions. + The hardware dependent acceleration functions for bcm graphic chips + are represented in this class. + + (C) 2017 TangoCash + Derived from old neutrino-hd framebuffer code / e2 sources + + License: GPL + + 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, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define LOGTAG "[fb_accel_arm] " + +#define FBIO_ACCEL 0x23 + +static unsigned int displaylist[1024]; +static int ptr; +static bool supportblendingflags = true; + +#define P(x, y) do { displaylist[ptr++] = x; displaylist[ptr++] = y; } while (0) +#define C(x) P(x, 0) + +static int fb_fd = -1; +static int exec_list(void); + +static int exec_list(void) +{ + int ret; + struct + { + void *ptr; + int len; + } l; + + if (fb_fd < 0) return -1; + + l.ptr = displaylist; + l.len = ptr; + ret = ioctl(fb_fd, FBIO_ACCEL, &l); + ptr = 0; + return ret; +} + +CFbAccelARM::CFbAccelARM() +{ + fb_name = "armbox framebuffer"; + fb_fd = open("/dev/fb0", O_RDWR); + if (fb_fd < 0) + { + printf(LOGTAG "[bcm] /dev/fb0 %m"); + } + if (exec_list()) + { + printf(LOGTAG "[bcm] interface not available - %m"); + close(fb_fd); + fb_fd = -1; + } + /* now test for blending flags support */ + P(0x80, 0); + if (exec_list()) + { + supportblendingflags = false; + } +#ifdef FORCE_NO_BLENDING_ACCELERATION + /* hardware doesn't allow us to detect whether the opcode is working */ + supportblendingflags = false; +#endif +} + +CFbAccelARM::~CFbAccelARM() +{ + if (fb_fd >= 0) + { + close(fb_fd); + fb_fd = -1; + } +} + +void CFbAccelARM::setOsdResolutions() +{ + osd_resolution_t res; + osd_resolutions.clear(); + res.xRes = 1280; + res.yRes = 720; + res.bpp = 32; + res.mode = OSDMODE_720; + osd_resolutions.push_back(res); + if (fullHdAvailable()) { + res.xRes = 1920; + res.yRes = 1080; + res.bpp = 32; + res.mode = OSDMODE_1080; + osd_resolutions.push_back(res); + } +} + +int CFbAccelARM::setMode(unsigned int nxRes, unsigned int nyRes, unsigned int nbpp) +{ + if (!available&&!active) + return -1; + + if (osd_resolutions.empty()) + setOsdResolutions(); + + unsigned int nxRes_ = nxRes; + unsigned int nyRes_ = nyRes; + unsigned int nbpp_ = nbpp; + if (!fullHdAvailable()) { + nxRes_ = 1280; + nyRes_ = 720; + nbpp_ = 32; + } + screeninfo.xres=nxRes_; + screeninfo.yres=nyRes_; + screeninfo.xres_virtual=nxRes_; + screeninfo.yres_virtual=nyRes_*2; + screeninfo.height=0; + screeninfo.width=0; + screeninfo.xoffset=screeninfo.yoffset=0; + screeninfo.bits_per_pixel=nbpp_; + + if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0) + perror(LOGTAG "FBIOPUT_VSCREENINFO"); + + printf(LOGTAG "SetMode: %dbits, red %d:%d green %d:%d blue %d:%d transp %d:%d\n", + screeninfo.bits_per_pixel, screeninfo.red.length, screeninfo.red.offset, screeninfo.green.length, screeninfo.green.offset, screeninfo.blue.length, screeninfo.blue.offset, screeninfo.transp.length, screeninfo.transp.offset); + if ((screeninfo.xres != nxRes_) || + (screeninfo.yres != nyRes_) || + (screeninfo.bits_per_pixel != nbpp_)) { + printf(LOGTAG "SetMode failed: wanted: %dx%dx%d, got %dx%dx%d\n", + nxRes_, nyRes_, nbpp_, + screeninfo.xres, screeninfo.yres, screeninfo.bits_per_pixel); + return -1; + } + + fb_fix_screeninfo _fix; + + if (ioctl(fd, FBIOGET_FSCREENINFO, &_fix) < 0) { + perror(LOGTAG "FBIOGET_FSCREENINFO"); + return -1; + } + stride = _fix.line_length; + swidth = stride / sizeof(fb_pixel_t); + if (ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) + printf(LOGTAG "screen unblanking failed\n"); + xRes = screeninfo.xres; + yRes = screeninfo.yres; + bpp = screeninfo.bits_per_pixel; + printf(LOGTAG "%dx%dx%d line length %d. using %s graphics accelerator.\n", xRes, yRes, bpp, stride, _fix.id); + + int needmem = stride * yRes * 2; + if (available >= needmem) + { + backbuffer = lfb + swidth * yRes; + return 0; + } + fprintf(stderr, LOGTAG "not enough FB memory (have %d, need %d)\n", available, needmem); + backbuffer = lfb; /* will not work well, but avoid crashes */ + return 0; /* dont fail because of this */ +} + +fb_pixel_t * CFbAccelARM::getBackBufferPointer() const +{ + return backbuffer; +} + +int CFbAccelARM::scale2Res(int size) +{ + /* + The historic resolution 1280x720 is default for some values/sizes. + So let's scale these values to other resolutions. + */ + +#ifdef ENABLE_CHANGE_OSD_RESOLUTION + if (screeninfo.xres == 1920) + size += size/2; +#endif + + return size; +} + +bool CFbAccelARM::fullHdAvailable() +{ +#ifdef ENABLE_CHANGE_OSD_RESOLUTION + return true; +#endif + return false; +} diff --git a/src/driver/fb_accel_arm.h b/src/driver/fb_accel_arm.h new file mode 100644 index 000000000..5fa950d51 --- /dev/null +++ b/src/driver/fb_accel_arm.h @@ -0,0 +1,45 @@ +/* + Framebuffer acceleration hardware abstraction functions. + The common functions for bcm graphic chips + are represented in this class. + + (C) 2017 M. Liebmann + (C) 2017 Thilo Graf 'dbt' + (C) 2017 TangoCash + Derived from old neutrino-hd framebuffer code / e2 sources + + License: GPL + + 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, see . +*/ + +#ifndef FB_ACCEL_ARM_H +#define FB_ACCEL_ARM_H + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +//extern cVideo * videoDecoder; + +#endif // FB_ACCEL_ARM_H diff --git a/src/driver/fb_generic.cpp b/src/driver/fb_generic.cpp index 6d6409ff4..9c706c0eb 100644 --- a/src/driver/fb_generic.cpp +++ b/src/driver/fb_generic.cpp @@ -138,6 +138,9 @@ CFrameBuffer* CFrameBuffer::getInstance() #endif #if HAVE_TRIPLEDRAGON frameBuffer = new CFbAccelTD(); +#endif +#if HAVE_ARM_HARDWARE + frameBuffer = new CFbAccelARM(); #endif if (!frameBuffer) frameBuffer = new CFrameBuffer();