Merge remote-tracking branch 'tuxbox/pu/fb-modules'

only compile tested ;-)
This commit is contained in:
Stefan Seyfried
2017-02-12 21:29:10 +01:00
45 changed files with 859 additions and 157 deletions

View File

@@ -46,9 +46,15 @@ libneutrino_driver_a_SOURCES = \
volume.cpp
if BOXTYPE_COOL
if BOXMODEL_CS_HD2
libneutrino_driver_a_SOURCES += \
fb_accel_cs.cpp \
fb_accel_cs_hd2.cpp \
vfd.cpp
else
libneutrino_driver_a_SOURCES += \
fb_accel_cs_hd1.cpp \
vfd.cpp
endif
endif
if BOXTYPE_TRIPLE

View File

@@ -55,14 +55,14 @@ void COSDFader::StartFadeIn()
fadeIn = true;
fadeOut = false;
fadeValue = 100;
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
frameBuffer->setBlendMode(CNXTFB_BLEND_MODE_UNIFORM_ALPHA); // Global alpha multiplied with pixel alpha
#else
frameBuffer->setBlendMode(2); // Global alpha multiplied with pixel alpha
#endif
frameBuffer->setBlendLevel(fadeValue);
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || (HAVE_COOL_HARDWARE && defined(BOXMODEL_APOLLO))
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || (HAVE_COOL_HARDWARE && defined(BOXMODEL_CS_HD2))
usleep(60000);
#endif
fadeTimer = g_RCInput->addTimer( FADE_TIME, false );
@@ -79,7 +79,7 @@ bool COSDFader::StartFadeOut()
if ((!fadeOut) && g_settings.widget_fade) {
fadeOut = true;
fadeTimer = g_RCInput->addTimer( FADE_TIME, false );
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
frameBuffer->setBlendMode(CNXTFB_BLEND_MODE_UNIFORM_ALPHA); // Global alpha multiplied with pixel alpha
#else
frameBuffer->setBlendMode(2); // Global alpha multiplied with pixel alpha
@@ -93,12 +93,12 @@ void COSDFader::StopFade()
{
if ( fadeIn || fadeOut ) {
g_RCInput->killTimer(fadeTimer);
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
frameBuffer->setBlendMode(CNXTFB_BLEND_MODE_PER_PIXEL); // Global alpha multiplied with pixel alpha
#else
frameBuffer->setBlendMode(1); // Global alpha multiplied with pixel alpha
#endif
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || (HAVE_COOL_HARDWARE && defined(BOXMODEL_APOLLO))
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || (HAVE_COOL_HARDWARE && defined(BOXMODEL_CS_HD2))
usleep(60000);
#endif
fadeIn = fadeOut = false;
@@ -124,12 +124,12 @@ bool COSDFader::FadeDone()
fadeValue = max_alpha;
g_RCInput->killTimer (fadeTimer);
fadeIn = false;
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
frameBuffer->setBlendMode(CNXTFB_BLEND_MODE_PER_PIXEL); // Global alpha multiplied with pixel alpha
#else
frameBuffer->setBlendMode(1); // Global alpha multiplied with pixel alpha
#endif
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || (HAVE_COOL_HARDWARE && defined(BOXMODEL_APOLLO))
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || (HAVE_COOL_HARDWARE && defined(BOXMODEL_CS_HD2))
usleep(60000);
#endif
} else

View File

@@ -32,10 +32,6 @@
#if HAVE_SPARK_HARDWARE
#define PARTIAL_BLIT 1
#endif
#if HAVE_COOL_HARDWARE
/* not needed -- if you don't want acceleration, don't call CFbAccel ;) */
#define USE_NEVIS_GXA 1
#endif
class CFbAccel
: public CFrameBuffer
@@ -82,7 +78,7 @@ class CFbAccelSTi
void setBlendLevel(int);
};
class CFbAccelCS
class CFbAccelCSHD1
: public CFbAccel
{
private:
@@ -90,24 +86,47 @@ class CFbAccelCS
int devmem_fd; /* to access the GXA register we use /dev/mem */
unsigned int smem_start; /* as aquired from the fbdev, the framebuffers physical start address */
volatile uint8_t *gxa_base; /* base address for the GXA's register access */
void add_gxa_sync_marker(void);
void setupGXA(void);
void setColor(fb_pixel_t col);
void run(void);
fb_pixel_t *backbuffer;
public:
CFbAccelCS();
~CFbAccelCS();
CFbAccelCSHD1();
~CFbAccelCSHD1();
void init(const char * const);
int setMode(unsigned int xRes, unsigned int yRes, unsigned int bpp);
void paintPixel(int x, int y, const fb_pixel_t col);
void paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col);
void paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col);
void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp);
inline void paintHLineRel(int x, int dx, int y, const fb_pixel_t col) { paintLine(x, y, x+dx, y, col); };
inline void paintVLineRel(int x, int y, int dy, const fb_pixel_t col) { paintLine(x, y, x, y+dy, col); };
void paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius = 0, int type = CORNER_ALL);
void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp = 0, uint32_t yp = 0, bool transp = false);
void blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff);
void waitForIdle(const char *func = NULL);
fb_pixel_t * getBackBufferPointer() const;
void setBlendMode(uint8_t);
void setBlendLevel(int);
void add_gxa_sync_marker(void);
void setupGXA(void);
};
class CFbAccelCSHD2
: public CFbAccel
{
private:
fb_pixel_t *backbuffer;
public:
CFbAccelCSHD2();
// ~CFbAccelCSHD2();
int setMode(unsigned int xRes, unsigned int yRes, unsigned int bpp);
void paintHLineRel(int x, int dx, int y, const fb_pixel_t col);
void paintVLineRel(int x, int y, int dy, const fb_pixel_t col);
void paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius = 0, int type = CORNER_ALL);
void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp = 0, uint32_t yp = 0, bool transp = false);
void blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff);
void setBlendMode(uint8_t);
void setBlendLevel(int);
};
class CFbAccelGLFB

View File

@@ -0,0 +1,374 @@
/*
Framebuffer acceleration hardware abstraction functions.
The hardware dependent acceleration functions for coolstream GXA chips
are represented in this class.
(C) 2017 Stefan Seyfried
Derived from old neutrino-hd framebuffer code
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 <http://www.gnu.org/licenses/>.
*/
#include "fb_accel_cs_hdx_inc.h"
/*******************************************************************************/
#define GXA_POINT(x, y) (((y) & 0x0FFF) << 16) | ((x) & 0x0FFF)
#define GXA_SRC_BMP_SEL(x) (x << 8)
#define GXA_DST_BMP_SEL(x) (x << 5)
#define GXA_PARAM_COUNT(x) (x << 2)
#define GXA_CMD_REG 0x001C
#define GXA_FG_COLOR_REG 0x0020
#define GXA_BG_COLOR_REG 0x0024
#define GXA_LINE_CONTROL_REG 0x0038
#define GXA_BMP1_TYPE_REG 0x0048
#define GXA_BMP1_ADDR_REG 0x004C
#define GXA_BMP2_TYPE_REG 0x0050
#define GXA_BMP2_ADDR_REG 0x0054
#define GXA_BMP3_TYPE_REG 0x0058
#define GXA_BMP3_ADDR_REG 0x005C
#define GXA_BMP4_TYPE_REG 0x0060
#define GXA_BMP4_ADDR_REG 0x0064
#define GXA_BMP5_TYPE_REG 0x0068
#define GXA_BMP5_ADDR_REG 0x006C
#define GXA_BMP6_TYPE_REG 0x0070
#define GXA_BMP7_TYPE_REG 0x0078
#define GXA_DEPTH_REG 0x00F4
#define GXA_CONTENT_ID_REG 0x0144
#define GXA_BLT_CONTROL_REG 0x0034
#define GXA_CMD_BLT 0x00010800
#define GXA_CMD_NOT_ALPHA 0x00011000
#define GXA_CMD_NOT_TEXT 0x00018000
#define GXA_CMD_QMARK 0x00001000
#define GXA_BLEND_CFG_REG 0x003C
#define GXA_CFG_REG 0x0030
#define GXA_CFG2_REG 0x00FC
#define LOGTAG "[fb_accel_cs_hd1] "
/*
static unsigned int _read_gxa(volatile unsigned char *base_addr, unsigned int offset)
{
return *(volatile unsigned int *)(base_addr + offset);
}
*/
static unsigned int _mark = 0;
static void _write_gxa(volatile unsigned char *base_addr, unsigned int offset, unsigned int value)
{
while ((*(volatile unsigned int *)(base_addr + GXA_DEPTH_REG)) & 0x40000000) {};
*(volatile unsigned int *)(base_addr + offset) = value;
}
/* this adds a tagged marker into the GXA queue. Once this comes out
of the other end of the queue, all commands before it are finished */
void CFbAccelCSHD1::add_gxa_sync_marker(void)
{
unsigned int cmd = GXA_CMD_QMARK | GXA_PARAM_COUNT(1);
// TODO: locking?
_mark++;
_mark &= 0x0000001F; /* bit 0x20 crashes the kernel, if set */
_write_gxa(gxa_base, cmd, _mark);
//fprintf(stderr, "%s: wrote %02x\n", __FUNCTION__, _mark);
}
/* wait until the current marker comes out of the GXA command queue */
void CFbAccelCSHD1::waitForIdle(const char *func)
{
unsigned int cfg, count = 0;
do {
cfg = *(volatile unsigned int *)(gxa_base + GXA_CMD_REG);
cfg >>= 24; /* the token is stored in bits 31...24 */
if (cfg == _mark)
break;
/* usleep is too coarse, because of CONFIG_HZ=100 in kernel
so use sched_yield to at least give other threads a chance to run */
sched_yield();
//fprintf(stderr, "%s: read %02x, expected %02x\n", __FUNCTION__, cfg, _mark);
} while(++count < 8192); /* don't deadlock here if there is an error */
if (count > 2048) /* more than 2000 are unlikely, even for large BMP6 blits */
fprintf(stderr, LOGTAG "waitForIdle: count is big (%d) [%s]!\n", count, func?func:"");
}
CFbAccelCSHD1::CFbAccelCSHD1()
{
fb_name = "Coolstream HD1 framebuffer";
}
void CFbAccelCSHD1::init(const char * const)
{
fprintf(stderr, ">FBACCEL::INIT\n");
CFrameBuffer::init();
if (lfb == NULL) {
printf(LOGTAG "CFrameBuffer::init() failed.\n");
return; /* too bad... */
}
available = fix.smem_len;
printf(LOGTAG "%dk video mem\n", available / 1024);
memset(lfb, 0, available);
lastcol = 0xffffffff;
lbb = lfb; /* the memory area to draw to... */
/* Open /dev/mem for HW-register access */
devmem_fd = open("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC);
if (devmem_fd < 0) {
perror("CFbAccel open /dev/mem");
goto error;
}
/* mmap the GXA's base address */
gxa_base = (volatile unsigned char*)mmap(0, 0x00040000, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, 0xE0600000);
if (gxa_base == (void *)-1) {
perror("CFbAccel mmap /dev/mem");
goto error;
}
setupGXA();
error:
/* TODO: what to do here? does this really happen? */
;
};
CFbAccelCSHD1::~CFbAccelCSHD1()
{
if (gxa_base != MAP_FAILED)
munmap((void *)gxa_base, 0x40000);
if (devmem_fd != -1)
close(devmem_fd);
}
void CFbAccelCSHD1::setColor(fb_pixel_t col)
{
if (col == lastcol)
return;
_write_gxa(gxa_base, GXA_FG_COLOR_REG, (unsigned int)col); /* setup the drawing color */
lastcol = col;
}
void CFbAccelCSHD1::paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
unsigned int cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_CMD_NOT_ALPHA |
GXA_SRC_BMP_SEL(6) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2);
_write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int)col); /* setup the drawing color */
_write_gxa(gxa_base, GXA_BMP6_TYPE_REG, (3 << 16) | (1 << 27)); /* 3 == 32bpp, 1<<27 == fill */
_write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* destination pos */
_write_gxa(gxa_base, cmd, GXA_POINT(dx, dy)); /* destination size */
_write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int)backgroundColor);
/* the GXA seems to do asynchronous rendering, so we add a sync marker
to which the fontrenderer code can synchronize */
add_gxa_sync_marker();
}
void CFbAccelCSHD1::paintPixel(const int x, const int y, const fb_pixel_t col)
{
paintLine(x, y, x + 1, y, col);
}
void CFbAccelCSHD1::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col)
{
if (!getActive())
return;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
/* draw a single vertical line from point xa/ya to xb/yb */
unsigned int cmd = GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(2) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2) | GXA_CMD_NOT_ALPHA;
setColor(col);
_write_gxa(gxa_base, GXA_LINE_CONTROL_REG, 0x00000404); /* X is major axis, skip last pixel */
_write_gxa(gxa_base, cmd, GXA_POINT(xb, yb)); /* end point */
_write_gxa(gxa_base, cmd, GXA_POINT(xa, ya)); /* start point */
}
void CFbAccelCSHD1::paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type)
{
/* draw a filled rectangle (with additional round corners) */
if (!getActive())
return;
if (dx == 0 || dy == 0) {
dprintf(DEBUG_DEBUG, "[CFbAccelCSHD1] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __func__, __LINE__, radius, x, y, x+dx, y+dy);
return;
}
if (radius < 0)
dprintf(DEBUG_NORMAL, "[CFbAccelCSHD1] [%s - %d]: WARNING! radius < 0 [%d] FIXME\n", __func__, __LINE__, radius);
checkFbArea(x, y, dx, dy, true);
if (!fb_no_check)
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
/* solid fill with background color */
unsigned int cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(7) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2) | GXA_CMD_NOT_ALPHA;
_write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int) col); /* setup the drawing color */
if (type && radius) {
setCornerFlags(type);
radius = limitRadius(dx, dy, radius);
int line = 0;
while (line < dy) {
int ofl, ofr;
if (calcCorners(NULL, &ofl, &ofr, dy, line, radius, type)) {
int rect_height_mult = ((type & CORNER_TOP) && (type & CORNER_BOTTOM)) ? 2 : 1;
_write_gxa(gxa_base, GXA_BLT_CONTROL_REG, 0);
_write_gxa(gxa_base, cmd, GXA_POINT(x, y + line)); /* destination x/y */
_write_gxa(gxa_base, cmd, GXA_POINT(dx, dy - (radius * rect_height_mult))); /* width/height */
line += dy - (radius * rect_height_mult);
continue;
}
if (dx-ofr-ofl < 1) {
if (dx-ofr-ofl == 0){
dprintf(DEBUG_INFO, "[CFbAccelCSHD1] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __func__, __LINE__, radius, x, y, x+dx-ofr-ofl, y+line);
}else{
dprintf(DEBUG_INFO, "[CFbAccelCSHD1] [%s - %04d]: Calculated width: %d\n (radius %d, dx %d, offsetLeft %d, offsetRight %d).\n Width can not be less than 0, abort.\n",
__func__, __LINE__, dx-ofr-ofl, radius, dx, ofl, ofr);
}
line++;
continue;
}
_write_gxa(gxa_base, GXA_BLT_CONTROL_REG, 0);
_write_gxa(gxa_base, cmd, GXA_POINT(x + ofl, y + line)); /* destination x/y */
_write_gxa(gxa_base, cmd, GXA_POINT(dx-ofl-ofr, 1)); /* width/height */
line++;
}
} else {
_write_gxa(gxa_base, GXA_BLT_CONTROL_REG, 0);
_write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* destination x/y */
_write_gxa(gxa_base, cmd, GXA_POINT(dx, dy)); /* width/height */
}
_write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int) backgroundColor); //FIXME needed ?
/* the GXA seems to do asynchronous rendering, so we add a sync marker
* to which the fontrenderer code can synchronize
*/
add_gxa_sync_marker();
checkFbArea(x, y, dx, dy, false);
}
void CFbAccelCSHD1::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp)
{
int xc, yc;
xc = (width > xRes) ? xRes : width;
yc = (height > yRes) ? yRes : height;
u32 cmd;
void *uKva;
uKva = cs_phys_addr(fbbuff);
if (uKva != NULL) {
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(1) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(3);
_write_gxa(gxa_base, GXA_BMP1_TYPE_REG, (3 << 16) | width);
_write_gxa(gxa_base, GXA_BMP1_ADDR_REG, (unsigned int)uKva);
_write_gxa(gxa_base, cmd, GXA_POINT(xoff, yoff)); /* destination pos */
_write_gxa(gxa_base, cmd, GXA_POINT(xc, yc)); /* source width, FIXME real or adjusted xc, yc ? */
_write_gxa(gxa_base, cmd, GXA_POINT(xp, yp)); /* source pos */
return;
}
CFrameBuffer::blit2FB(fbbuff, width, height, xoff, yoff, xp, yp, transp);
}
void CFbAccelCSHD1::blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff)
{
if(width <1 || height <1 || !boxBuf )
return;
uint32_t xc = (width > xRes) ? (uint32_t)xRes : width;
uint32_t yc = (height > yRes) ? (uint32_t)yRes : height;
void* uKva = cs_phys_addr((void*)boxBuf);
if(uKva != NULL) {
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
u32 cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(1) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(3);
_write_gxa(gxa_base, GXA_BMP1_TYPE_REG, (3 << 16) | width);
_write_gxa(gxa_base, GXA_BMP1_ADDR_REG, (unsigned int) uKva);
_write_gxa(gxa_base, cmd, GXA_POINT(xoff, yoff));
_write_gxa(gxa_base, cmd, GXA_POINT(xc, yc));
_write_gxa(gxa_base, cmd, GXA_POINT(0, 0));
add_gxa_sync_marker();
return;
}
CFrameBuffer::blitBox2FB(boxBuf, width, height, xoff, yoff);
}
void CFbAccelCSHD1::setupGXA()
{
// We (re)store the GXA regs here in case DFB override them and was not
// able to restore them.
_write_gxa(gxa_base, GXA_BMP2_TYPE_REG, (3 << 16) | (unsigned int)screeninfo.xres);
_write_gxa(gxa_base, GXA_BMP2_ADDR_REG, (unsigned int) fix.smem_start);
_write_gxa(gxa_base, GXA_BLEND_CFG_REG, 0x00089064);
// TODO check mono-flip, bit 8
_write_gxa(gxa_base, GXA_CFG_REG, 0x100 | (1 << 12) | (1 << 29));
_write_gxa(gxa_base, GXA_CFG2_REG, 0x1FF);
_write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int)backgroundColor);
_write_gxa(gxa_base, GXA_BMP7_TYPE_REG, (3 << 16) | (unsigned int)screeninfo.xres | (1 << 27));
add_gxa_sync_marker();
}
/* wrong name... */
int CFbAccelCSHD1::setMode(unsigned int, unsigned int, unsigned int)
{
fb_fix_screeninfo _fix;
if (ioctl(fd, FBIOGET_FSCREENINFO, &_fix) < 0) {
perror("FBIOGET_FSCREENINFO");
return -1;
}
stride = _fix.line_length;
if (ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0)
printf("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 + stride / sizeof(fb_pixel_t) * 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 * CFbAccelCSHD1::getBackBufferPointer() const
{
return backbuffer;
}
void CFbAccelCSHD1::setBlendMode(uint8_t mode)
{
if (ioctl(fd, FBIO_SETBLENDMODE, mode))
printf("FBIO_SETBLENDMODE failed.\n");
}
void CFbAccelCSHD1::setBlendLevel(int level)
{
unsigned char value = 0xFF;
if (level >= 0 && level <= 100)
value = convertSetupAlpha2Alpha(level);
if (ioctl(fd, FBIO_SETOPACITY, value))
printf("FBIO_SETOPACITY failed.\n");
}

View File

@@ -0,0 +1,230 @@
/*
Framebuffer acceleration hardware abstraction functions.
The hardware dependent acceleration functions for coolstream hd2 graphic chips
are represented in this class.
(C) 2017 M. Liebmann
Derived from old neutrino-hd framebuffer code
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 <http://www.gnu.org/licenses/>.
*/
#include "fb_accel_cs_hdx_inc.h"
#define LOGTAG "[fb_accel_cs_hd2] "
CFbAccelCSHD2::CFbAccelCSHD2()
{
fb_name = "Coolstream HD2 framebuffer";
}
/*
CFbAccelCSHD2::~CFbAccelCSHD2()
{
}
*/
void CFbAccelCSHD2::paintHLineRel(int x, int dx, int y, const fb_pixel_t col)
{
if (!getActive())
return;
if (dx >= 10) {
fb_fillrect fillrect;
fillrect.dx = x;
fillrect.dy = y;
fillrect.width = dx;
fillrect.height = 1;
fillrect.color = col;
fillrect.rop = ROP_COPY;
ioctl(fd, FBIO_FILL_RECT, &fillrect);
return;
}
CFrameBuffer::paintHLineRelInternal(x, dx, y, col);
}
void CFbAccelCSHD2::paintVLineRel(int x, int y, int dy, const fb_pixel_t col)
{
if (!getActive())
return;
fb_fillrect fillrect;
fillrect.dx = x;
fillrect.dy = y;
fillrect.width = 1;
fillrect.height = dy;
fillrect.color = col;
fillrect.rop = ROP_COPY;
ioctl(fd, FBIO_FILL_RECT, &fillrect);
}
void CFbAccelCSHD2::paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type)
{
if (!getActive())
return;
if (dx == 0 || dy == 0) {
dprintf(DEBUG_DEBUG, "[CFbAccelCSHD2] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __func__, __LINE__, radius, x, y, x+dx, y+dy);
return;
}
if (radius < 0)
dprintf(DEBUG_NORMAL, "[CFbAccelCSHD2] [%s - %d]: WARNING! radius < 0 [%d] FIXME\n", __func__, __LINE__, radius);
checkFbArea(x, y, dx, dy, true);
fb_fillrect fillrect;
fillrect.color = col;
fillrect.rop = ROP_COPY;
if (type && radius) {
setCornerFlags(type);
radius = limitRadius(dx, dy, radius);
int line = 0;
while (line < dy) {
int ofl, ofr;
if (calcCorners(NULL, &ofl, &ofr, dy, line, radius, type)) {
int rect_height_mult = ((type & CORNER_TOP) && (type & CORNER_BOTTOM)) ? 2 : 1;
fillrect.dx = x;
fillrect.dy = y + line;
fillrect.width = dx;
fillrect.height = dy - (radius * rect_height_mult);
ioctl(fd, FBIO_FILL_RECT, &fillrect);
line += dy - (radius * rect_height_mult);
continue;
}
if (dx-ofr-ofl < 1) {
if (dx-ofr-ofl == 0){
dprintf(DEBUG_INFO, "[CFbAccelCSHD2] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __func__, __LINE__, radius, x, y, x+dx-ofr-ofl, y+line);
}else{
dprintf(DEBUG_INFO, "[CFbAccelCSHD2] [%s - %04d]: Calculated width: %d\n (radius %d, dx %d, offsetLeft %d, offsetRight %d).\n Width can not be less than 0, abort.\n",
__func__, __LINE__, dx-ofr-ofl, radius, dx, ofl, ofr);
}
line++;
continue;
}
paintHLineRel(x+ofl, dx-ofl-ofr, y+line, col);
line++;
}
} else {
/* FIXME small size faster to do by software */
if (dx > 10 || dy > 10) {
fillrect.dx = x;
fillrect.dy = y;
fillrect.width = dx;
fillrect.height = dy;
ioctl(fd, FBIO_FILL_RECT, &fillrect);
checkFbArea(x, y, dx, dy, false);
return;
}
int line = 0;
while (line < dy) {
CFrameBuffer::paintHLineRelInternal(x, dx, y+line, col);
line++;
}
}
checkFbArea(x, y, dx, dy, false);
}
void CFbAccelCSHD2::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp)
{
int xc, yc;
xc = (width > xRes) ? xRes : width;
yc = (height > yRes) ? yRes : height;
if(!(width%4)) {
fb_image image;
image.dx = xoff;
image.dy = yoff;
image.width = xc;
image.height = yc;
image.cmap.len = 0;
image.depth = 32;
image.data = (const char*)fbbuff;
ioctl(fd, FBIO_IMAGE_BLT, &image);
return;
}
CFrameBuffer::blit2FB(fbbuff, width, height, xoff, yoff, xp, yp, transp);
}
void CFbAccelCSHD2::blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff)
{
if(width <1 || height <1 || !boxBuf )
return;
uint32_t xc = (width > xRes) ? (uint32_t)xRes : width;
uint32_t yc = (height > yRes) ? (uint32_t)yRes : height;
if (!(width%4)) {
fb_image image;
image.dx = xoff;
image.dy = yoff;
image.width = xc;
image.height = yc;
image.cmap.len = 0;
image.depth = 32;
image.data = (const char*)boxBuf;
ioctl(fd, FBIO_IMAGE_BLT, &image);
return;
}
CFrameBuffer::blitBox2FB(boxBuf, width, height, xoff, yoff);
}
int CFbAccelCSHD2::setMode(unsigned int, unsigned int, unsigned int)
{
fb_fix_screeninfo _fix;
if (ioctl(fd, FBIOGET_FSCREENINFO, &_fix) < 0) {
perror("FBIOGET_FSCREENINFO");
return -1;
}
stride = _fix.line_length;
if (ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0)
printf("screen unblanking failed\n");
xRes = screeninfo.xres;
yRes = screeninfo.yres;
bpp = screeninfo.bits_per_pixel;
printf(LOGTAG "%dx%dx%d line length %d. using hd2 graphics accelerator.\n", xRes, yRes, bpp, stride);
int needmem = stride * yRes * 2;
if (available >= needmem)
{
backbuffer = lfb + stride / sizeof(fb_pixel_t) * 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 */
}
void CFbAccelCSHD2::setBlendMode(uint8_t mode)
{
if (ioctl(fd, FBIO_SETBLENDMODE, mode))
printf("FBIO_SETBLENDMODE failed.\n");
}
void CFbAccelCSHD2::setBlendLevel(int level)
{
unsigned char value = 0xFF;
if (level >= 0 && level <= 100)
value = convertSetupAlpha2Alpha(level);
if (ioctl(fd, FBIO_SETOPACITY, value))
printf("FBIO_SETOPACITY failed.\n");
if (level == 100) // TODO: sucks.
usleep(20000);
}

View File

@@ -0,0 +1,38 @@
/*
Framebuffer acceleration hardware abstraction functions.
The hardware dependent acceleration functions for coolstream hdx graphic chips
are represented in this class.
(C) 2017 M. Liebmann
(C) 2017 Thilo Graf 'dbt'
Derived from old neutrino-hd framebuffer code
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 <http://www.gnu.org/licenses/>.
*/
#include <driver/fb_generic.h>
#include <driver/fb_accel.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <gui/color.h>
#include <system/debug.h>
#include <cs_api.h>
#include <cnxtfb.h>

View File

@@ -126,7 +126,12 @@ CFrameBuffer* CFrameBuffer::getInstance()
frameBuffer = new CFbAccelSTi();
#endif
#if HAVE_COOL_HARDWARE
frameBuffer = new CFbAccelCS();
#ifdef BOXMODEL_CS_HD1
frameBuffer = new CFbAccelCSHD1();
#endif
#ifdef BOXMODEL_CS_HD2
frameBuffer = new CFbAccelCSHD2();
#endif
#endif
#if HAVE_GENERIC_HARDWARE
frameBuffer = new CFbAccelGLFB();
@@ -347,7 +352,7 @@ int CFrameBuffer::setMode(unsigned int /*nxRes*/, unsigned int /*nyRes*/, unsign
}
return 0;
}
#if 0
#if 0
//never used
void CFrameBuffer::setTransparency( int /*tr*/ )
{
@@ -361,7 +366,7 @@ void CFrameBuffer::setBlendLevel(int /*level*/)
{
}
#if 0
#if 0
//never used
void CFrameBuffer::setAlphaFade(int in, int num, int tr)
{
@@ -507,7 +512,7 @@ fb_pixel_t* CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, co
int w_align;
int offs_align;
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
if (_dx%4 != 0) {
w_align = GetWidth4FB_HW_ACC(x, _dx, true);
if (w_align < _dx)
@@ -1190,7 +1195,7 @@ void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t co
}
mark(xa, ya, xb, yb);
}
#if 0
#if 0
//never used
void CFrameBuffer::setBackgroundColor(const fb_pixel_t color)
{
@@ -1538,9 +1543,9 @@ void * CFrameBuffer::int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x,
if (alpha) {
for(i = 0; i < count ; i++)
fbbuff[i] = ((rgbbuff[i*4+3] << 24) & 0xFF000000) |
((rgbbuff[i*4] << 16) & 0x00FF0000) |
((rgbbuff[i*4+1] << 8) & 0x0000FF00) |
fbbuff[i] = ((rgbbuff[i*4+3] << 24) & 0xFF000000) |
((rgbbuff[i*4] << 16) & 0x00FF0000) |
((rgbbuff[i*4+1] << 8) & 0x0000FF00) |
((rgbbuff[i*4+2]) & 0x000000FF);
} else {
switch (m_transparent) {

View File

@@ -122,6 +122,7 @@ class CFrameBuffer : public sigc::trackable
int kd_mode;
struct vt_mode vt_mode;
bool active;
bool fb_no_check;
static void switch_signal (int);
fb_fix_screeninfo fix;
bool locked;
@@ -175,14 +176,18 @@ class CFrameBuffer : public sigc::trackable
virtual fb_pixel_t * getBackBufferPointer() const; // pointer to backbuffer
virtual unsigned int getStride() const; // size of a single line in the framebuffer (in bytes)
unsigned int getScreenWidth(bool real = false);
unsigned int getScreenHeight(bool real = false);
unsigned int getScreenHeight(bool real = false);
unsigned int getScreenWidthRel(bool force_small = false);
unsigned int getScreenHeightRel(bool force_small = false);
unsigned int getScreenX();
unsigned int getScreenY();
bool getActive() const; // is framebuffer active?
void setActive(bool enable); // is framebuffer active?
#ifdef BOXMODEL_CS_HD1
virtual void setupGXA() {};
virtual void add_gxa_sync_marker() {};
#endif
void setTransparency( int tr = 0 );
virtual void setBlendMode(uint8_t mode = 1);
@@ -223,7 +228,7 @@ class CFrameBuffer : public sigc::trackable
void getIconSize(const char * const filename, int* width, int *height);
/* h is the height of the target "window", if != 0 the icon gets centered in that window */
bool paintIcon (const std::string & filename, const int x, const int y,
bool paintIcon (const std::string & filename, const int x, const int y,
const int h = 0, const unsigned char offset = 1, bool paint = true, bool paintBg = false, const fb_pixel_t colBg = 0);
bool paintIcon8(const std::string & filename, const int x, const int y, const unsigned char offset = 0);
void loadPal (const std::string & filename, const unsigned char offset = 0, const unsigned char endidx = 255);
@@ -266,7 +271,7 @@ class CFrameBuffer : public sigc::trackable
virtual void mark(int x, int y, int dx, int dy);
enum
enum
{
TM_EMPTY = 0,
TM_NONE = 1,
@@ -296,7 +301,6 @@ class CFrameBuffer : public sigc::trackable
typedef std::vector<fb_area_t> v_fbarea_t;
typedef v_fbarea_t::iterator fbarea_iterator_t;
v_fbarea_t v_fbarea;
bool fb_no_check;
bool do_paint_mute_icon;
bool _checkFbArea(int _x, int _y, int _dx, int _dy, bool prev);

View File

@@ -63,7 +63,7 @@ extern CPictureViewer * g_PicViewer;
#define BACKGROUNDIMAGEWIDTH 720
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
#ifndef FB_HW_ACCELERATION
#define FB_HW_ACCELERATION
#endif
@@ -582,7 +582,7 @@ void CFrameBuffer::setBlendLevel(int level)
if (ioctl(fd, FBIO_SETOPACITY, value))
printf("FBIO_SETOPACITY failed.\n");
#ifndef BOXMODEL_APOLLO
#ifndef BOXMODEL_CS_HD2
if(level == 100) // TODO: sucks.
usleep(20000);
#endif
@@ -735,7 +735,7 @@ fb_pixel_t* CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, co
int w_align;
int offs_align;
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
if (_dx%4 != 0) {
w_align = GetWidth4FB_HW_ACC(x, _dx, true);
if (w_align < _dx)

View File

@@ -142,7 +142,7 @@ void CNeutrinoFonts::SetupNeutrinoFonts(bool initRenderClass/*=true*/)
if (initRenderClass) {
if (g_fontRenderer != NULL)
delete g_fontRenderer;
g_fontRenderer = new FBFontRenderClass(72 * g_settings.screen_xres / 100, 72 * g_settings.screen_yres / 100);
g_fontRenderer = new FBFontRenderClass(72 * g_settings.font_scaling_x / 100, 72 * g_settings.font_scaling_y / 100);
old_fontDescr.size_offset = fontDescr.size_offset;
old_fontDescr.filename = fontDescr.filename;

View File

@@ -856,7 +856,7 @@ bool CPictureViewer::checkfreemem(size_t bufsize)
{
struct sysinfo info;
sysinfo( &info );
if(bufsize + 4096 > (size_t)info.freeram + (size_t)info.freeswap){
if(bufsize*2 + 4096 > (size_t)info.freeram + (size_t)info.freeswap){
dprintf(DEBUG_NORMAL, "[CPictureViewer] [%s - %d] Error: Out of memory\n", __func__, __LINE__);
return false;
}

View File

@@ -39,7 +39,7 @@
#include <string>
#include <vector>
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
#ifdef HAVE_COOLSTREAM_CS_IR_GENERIC_H
#include <cs_ir_generic.h>
#endif

View File

@@ -78,7 +78,7 @@ bool CScreenShot::GetData()
bool res = false;
mutex.lock();
#ifdef USE_NEVIS_GXA
#ifdef BOXMODEL_CS_HD1
CFrameBuffer::getInstance()->setActive(false);
#endif
if (videoDecoder->getBlank())
@@ -87,7 +87,7 @@ bool CScreenShot::GetData()
res = videoDecoder->GetScreenImage(pixel_data, xres, yres, get_video, get_osd, scale_to_video);
#endif
#ifdef USE_NEVIS_GXA
#ifdef BOXMODEL_CS_HD1
/* sort of hack. GXA used to transfer/convert live image to RGB,
* so setup GXA back */
CFrameBuffer::getInstance()->setupGXA();
@@ -216,7 +216,7 @@ bool CScreenShot::SavePng()
png_set_compression_level(png_ptr, Z_BEST_SPEED);
png_set_bgr(png_ptr);
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
png_set_invert_alpha(png_ptr);
#endif
png_write_info(png_ptr, info_ptr);

View File

@@ -71,7 +71,7 @@ CVFD::CVFD()
has_led_segment = false;
}
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
if (fd >= 0) {
int ret = ioctl(fd, IOC_FP_GET_DISPLAY_CAPS, &caps);
if (ret < 0) {
@@ -372,7 +372,7 @@ void CVFD::showTime(bool force)
ShowText(timestr);
} else if (support_numbers && has_led_segment) {
ShowNumber((t->tm_hour*100) + t->tm_min);
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
ioctl(fd, IOC_FP_SET_COLON, 0x01);
#endif
}
@@ -564,7 +564,7 @@ void CVFD::setMode(const MODES m, const char * const title)
if(fd < 0) return;
// Clear colon in display if it is still there
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
if (support_numbers && has_led_segment)
ioctl(fd, IOC_FP_SET_COLON, 0x00);
#endif
@@ -819,7 +819,7 @@ void CVFD::ShowNumber(int number)
if (number < 0)
return;
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
int ret = ioctl(fd, IOC_FP_SET_NUMBER, number);
if(ret < 0) {
support_numbers = false;

View File

@@ -76,7 +76,7 @@ class CVFD
private:
#ifdef BOXMODEL_APOLLO
#ifdef BOXMODEL_CS_HD2
fp_display_caps_t caps;
#endif
MODES mode;