diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am
index bb7bf09df..3d1c9b216 100644
--- a/src/driver/Makefile.am
+++ b/src/driver/Makefile.am
@@ -26,6 +26,7 @@ libneutrino_driver_a_SOURCES = \
audioplay.cpp \
colorgradient.cpp \
fade.cpp \
+ fb_accel.cpp \
fb_window.cpp \
fb_generic.cpp \
file.cpp \
@@ -55,4 +56,10 @@ libneutrino_driver_a_SOURCES += \
lcdd.cpp
endif
+#if BOXTYPE_SPARK
+#libneutrino_driver_a_SOURCES += \
+# fb_accel_sti.cpp \
+# simple_display.cpp
+#endif
+
libneutrino_driver_netfile_a_SOURCES = netfile.cpp
diff --git a/src/driver/fb_accel.cpp b/src/driver/fb_accel.cpp
new file mode 100644
index 000000000..d8391ab34
--- /dev/null
+++ b/src/driver/fb_accel.cpp
@@ -0,0 +1,97 @@
+/*
+ Framebuffer acceleration hardware abstraction functions.
+ The infrastructure for hardware dependent framebuffer acceleration
+ functions are implemented in this class, hardware specific stuff
+ is in derived classes.
+
+ (C) 2017 Stefan Seyfried
+
+ 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
+
+CFbAccel::CFbAccel()
+{
+};
+
+CFbAccel::~CFbAccel()
+{
+};
+
+void CFbAccel::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;
+
+ checkFbArea(x, y, dx, dy, true);
+
+ if (!type || !radius)
+ {
+ paintRect(x, y, dx, dy, col);
+ checkFbArea(x, y, dx, dy, false);
+ return;
+ }
+
+ setCornerFlags(type);
+ /* limit the radius */
+ radius = limitRadius(dx, dy, radius);
+ if (radius < 1) /* dx or dy = 0... */
+ radius = 1; /* avoid div by zero below */
+
+ int line = 0;
+ while (line < dy) {
+ int ofl, ofr;
+ if (calcCorners(NULL, &ofl, &ofr, dy, line, radius, type)) {
+ int height = dy - ((corner_tl || corner_tr)?radius: 0 ) - ((corner_bl || corner_br) ? radius : 0);
+ paintRect(x, y + line, dx, height, col);
+ line += height;
+ continue;
+ }
+ if (dx - ofr - ofl < 1) {
+ //printf("FB-NG::%s:%d x %d y %d dx %d dy %d l %d r %d\n", __func__, __LINE__, x,y,dx,dy, ofl, ofr);
+ line++;
+ continue;
+ }
+ paintLine(x + ofl, y + line, x + dx - ofr, y + line, col);
+ line++;
+ }
+ checkFbArea(x, y, dx, dy, false);
+ mark(x, y, x+dx, y+dy);
+}
+
+void CFbAccel::paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col)
+{
+ int line = 0;
+ int swidth = stride / sizeof(fb_pixel_t);
+ fb_pixel_t *fbp = getFrameBufferPointer() + (swidth * y);
+ int pos;
+ while (line < dy)
+ {
+ for (pos = x; pos < x + dx; pos++)
+ *(fbp + pos) = col;
+ fbp += swidth;
+ line++;
+ }
+ mark(x, y, x+dx, y+dy);
+ blit();
+}
diff --git a/src/driver/fb_accel.h b/src/driver/fb_accel.h
new file mode 100644
index 000000000..af73b76ef
--- /dev/null
+++ b/src/driver/fb_accel.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2007-2013 Stefan Seyfried
+
+ 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 .
+
+ private functions for the fbaccel class (only used in CFrameBuffer)
+*/
+
+
+#ifndef __fbaccel__
+#define __fbaccel__
+#include
+#include
+#include
+#include
+#include
+#include "fb_generic.h"
+
+#if HAVE_SPARK_HARDWARE
+#define PARTIAL_BLIT 1
+#endif
+
+class CFbAccel
+ : public CFrameBuffer
+{
+ public:
+ CFbAccel();
+ ~CFbAccel();
+ void paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type);
+ virtual void paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col);
+};
+
+class CFbAccelSTi
+ : public OpenThreads::Thread, public CFbAccel
+{
+ private:
+ void run(void);
+ void blit(void);
+ void _blit(void);
+ bool blit_thread;
+ bool blit_pending;
+ OpenThreads::Condition blit_cond;
+ OpenThreads::Mutex blit_mutex;
+ fb_pixel_t *backbuffer;
+#ifdef PARTIAL_BLIT
+ struct {
+ int xs;
+ int ys;
+ int xe;
+ int ye;
+ } to_blit;
+ uint32_t last_xres;
+#endif
+ public:
+ CFbAccelSTi();
+ ~CFbAccelSTi();
+ void init(const char * const);
+ int setMode(unsigned int xRes, unsigned int yRes, unsigned int bpp);
+ void paintRect(const int x, const int y, const int dx, const int dy, 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);
+ void waitForIdle(const char *func = NULL);
+ void mark(int x, int y, int dx, int dy);
+ fb_pixel_t * getBackBufferPointer() const;
+ void setBlendMode(uint8_t);
+ void setBlendLevel(int);
+};
+
+#endif
diff --git a/src/driver/fb_accel_sti.cpp b/src/driver/fb_accel_sti.cpp
new file mode 100644
index 000000000..446fc3828
--- /dev/null
+++ b/src/driver/fb_accel_sti.cpp
@@ -0,0 +1,655 @@
+/*
+ Framebuffer acceleration hardware abstraction functions.
+ The hardware dependent framebuffer acceleration functions for STi chips
+ are represented in this class.
+
+ (C) 2017 Stefan Seyfried
+
+ 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
+
+#include
+#include
+
+#include
+#include
+
+/* note that it is *not* enough to just change those values */
+#define DEFAULT_XRES 1280
+#define DEFAULT_YRES 720
+#define DEFAULT_BPP 32
+
+#define LOGTAG "[fb_accel_sti] "
+static int bpafd = -1;
+static size_t lbb_sz = 1920 * 1080; /* offset from fb start in 'pixels' */
+static size_t lbb_off = lbb_sz * sizeof(fb_pixel_t); /* same in bytes */
+static int backbuf_sz = 0;
+
+void CFbAccelSTi::waitForIdle(const char *)
+{
+#if 0 /* blits too often and does not seem to be necessary */
+ blit_mutex.lock();
+ if (blit_pending)
+ {
+ blit_mutex.unlock();
+ _blit();
+ return;
+ }
+ blit_mutex.unlock();
+#endif
+ OpenThreads::ScopedLock m_lock(mutex);
+ ioctl(fd, STMFBIO_SYNC_BLITTER);
+}
+
+CFbAccelSTi::CFbAccelSTi()
+{
+ fb_name = "STx7xxx framebuffer";
+}
+
+void CFbAccelSTi::init(const char * const)
+{
+ blit_thread = false;
+ 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);
+
+ lbb = lfb; /* the memory area to draw to... */
+ if (available < 12*1024*1024)
+ {
+ /* for old installations that did not upgrade their module config
+ * it will still work good enough to display the message below */
+ fprintf(stderr, "[neutrino] WARNING: not enough framebuffer memory available!\n");
+ fprintf(stderr, "[neutrino] I need at least 12MB.\n");
+ FILE *f = fopen("/tmp/infobar.txt", "w");
+ if (f) {
+ fprintf(f, "NOT ENOUGH FRAMEBUFFER MEMORY!");
+ fclose(f);
+ }
+ lbb_sz = 0;
+ lbb_off = 0;
+ }
+ lbb = lfb + lbb_sz;
+ bpafd = open("/dev/bpamem0", O_RDWR | O_CLOEXEC);
+ if (bpafd < 0)
+ {
+ fprintf(stderr, "[neutrino] FB: cannot open /dev/bpamem0: %m\n");
+ return;
+ }
+ backbuf_sz = 1280 * 720 * sizeof(fb_pixel_t);
+ BPAMemAllocMemData bpa_data;
+ bpa_data.bpa_part = (char *)"LMI_VID";
+ bpa_data.mem_size = backbuf_sz;
+ int res;
+ res = ioctl(bpafd, BPAMEMIO_ALLOCMEM, &bpa_data);
+ if (res)
+ {
+ fprintf(stderr, "[neutrino] FB: cannot allocate from bpamem: %m\n");
+ fprintf(stderr, "backbuf_sz: %d\n", backbuf_sz);
+ close(bpafd);
+ bpafd = -1;
+ return;
+ }
+ close(bpafd);
+
+ char bpa_mem_device[30];
+ sprintf(bpa_mem_device, "/dev/bpamem%d", bpa_data.device_num);
+ bpafd = open(bpa_mem_device, O_RDWR | O_CLOEXEC);
+ if (bpafd < 0)
+ {
+ fprintf(stderr, "[neutrino] FB: cannot open secondary %s: %m\n", bpa_mem_device);
+ return;
+ }
+
+ backbuffer = (fb_pixel_t *)mmap(0, bpa_data.mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, bpafd, 0);
+ if (backbuffer == MAP_FAILED)
+ {
+ fprintf(stderr, "[neutrino] FB: cannot map from bpamem: %m\n");
+ ioctl(bpafd, BPAMEMIO_FREEMEM);
+ close(bpafd);
+ bpafd = -1;
+ return;
+ }
+#ifdef PARTIAL_BLIT
+ to_blit.xs = to_blit.ys = INT_MAX;
+ to_blit.xe = to_blit.ye = 0;
+ last_xres = 0;
+#endif
+
+ /* start the autoblit-thread (run() function) */
+ OpenThreads::Thread::start();
+};
+
+CFbAccelSTi::~CFbAccelSTi()
+{
+ if (blit_thread)
+ {
+ blit_thread = false;
+ blit(); /* wakes up the thread */
+ OpenThreads::Thread::join();
+ }
+ if (backbuffer)
+ {
+ fprintf(stderr, LOGTAG "unmap backbuffer\n");
+ munmap(backbuffer, backbuf_sz);
+ }
+ if (bpafd != -1)
+ {
+ fprintf(stderr, LOGTAG "BPAMEMIO_FREEMEM\n");
+ ioctl(bpafd, BPAMEMIO_FREEMEM);
+ close(bpafd);
+ }
+ if (lfb)
+ munmap(lfb, available);
+ if (fd > -1)
+ close(fd);
+}
+
+void CFbAccelSTi::paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col)
+{
+ if (dx <= 0 || dy <= 0)
+ return;
+
+ // The STM blitter introduces considerable overhead probably not worth for single lines. --martii
+ if (dx == 1) {
+ waitForIdle();
+ fb_pixel_t *fbs = getFrameBufferPointer() + (DEFAULT_XRES * y) + x;
+ fb_pixel_t *fbe = fbs + DEFAULT_XRES * dy;
+ while (fbs < fbe) {
+ *fbs = col;
+ fbs += DEFAULT_XRES;
+ }
+ mark(x , y, x + 1, y + dy);
+ return;
+ }
+ if (dy == 1) {
+ waitForIdle();
+ fb_pixel_t *fbs = getFrameBufferPointer() + (DEFAULT_XRES * y) + x;
+ fb_pixel_t *fbe = fbs + dx;
+ while (fbs < fbe)
+ *fbs++ = col;
+ mark(x , y, x + dx, y + 1);
+ return;
+ }
+
+ /* function has const parameters, so copy them here... */
+ int width = dx;
+ int height = dy;
+ int xx = x;
+ int yy = y;
+ /* maybe we should just return instead of fixing this up... */
+ if (x < 0) {
+ fprintf(stderr, "[neutrino] fb::%s: x < 0 (%d)\n", __func__, x);
+ width += x;
+ if (width <= 0)
+ return;
+ xx = 0;
+ }
+
+ if (y < 0) {
+ fprintf(stderr, "[neutrino] fb::%s: y < 0 (%d)\n", __func__, y);
+ height += y;
+ if (height <= 0)
+ return;
+ yy = 0;
+ }
+
+ int right = xx + width;
+ int bottom = yy + height;
+
+ if (right > (int)xRes) {
+ if (xx >= (int)xRes) {
+ fprintf(stderr, "[neutrino] fb::%s: x >= xRes (%d > %d)\n", __func__, xx, xRes);
+ return;
+ }
+ fprintf(stderr, "[neutrino] fb::%s: x+w > xRes! (%d+%d > %d)\n", __func__, xx, width, xRes);
+ right = xRes;
+ }
+ if (bottom > (int)yRes) {
+ if (yy >= (int)yRes) {
+ fprintf(stderr, "[neutrino] fb::%s: y >= yRes (%d > %d)\n", __func__, yy, yRes);
+ return;
+ }
+ fprintf(stderr, "[neutrino] fb::%s: y+h > yRes! (%d+%d > %d)\n", __func__, yy, height, yRes);
+ bottom = yRes;
+ }
+
+ STMFBIO_BLT_DATA bltData;
+ memset(&bltData, 0, sizeof(STMFBIO_BLT_DATA));
+
+ bltData.operation = BLT_OP_FILL;
+ bltData.dstOffset = lbb_off;
+ bltData.dstPitch = stride;
+
+ bltData.dst_left = xx;
+ bltData.dst_top = yy;
+ bltData.dst_right = right;
+ bltData.dst_bottom = bottom;
+
+ bltData.dstFormat = SURF_ARGB8888;
+ bltData.srcFormat = SURF_ARGB8888;
+ bltData.dstMemBase = STMFBGP_FRAMEBUFFER;
+ bltData.srcMemBase = STMFBGP_FRAMEBUFFER;
+ bltData.colour = col;
+
+ mark(xx, yy, bltData.dst_right, bltData.dst_bottom);
+ OpenThreads::ScopedLock m_lock(mutex);
+ if (ioctl(fd, STMFBIO_BLT, &bltData ) < 0)
+ fprintf(stderr, "blitRect FBIO_BLIT: %m x:%d y:%d w:%d h:%d s:%d\n", xx,yy,width,height,stride);
+ blit();
+}
+
+void CFbAccelSTi::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp)
+{
+ int x, y, dw, dh;
+ x = xoff;
+ y = yoff;
+ dw = width - xp;
+ dh = height - yp;
+
+ size_t mem_sz = width * height * sizeof(fb_pixel_t);
+ unsigned long ulFlags = 0;
+ if (!transp) /* transp == false (default): use transparency from source alphachannel */
+ ulFlags = BLT_OP_FLAGS_BLEND_SRC_ALPHA|BLT_OP_FLAGS_BLEND_DST_MEMORY; // we need alpha blending
+
+ STMFBIO_BLT_EXTERN_DATA blt_data;
+ memset(&blt_data, 0, sizeof(STMFBIO_BLT_EXTERN_DATA));
+ blt_data.operation = BLT_OP_COPY;
+ blt_data.ulFlags = ulFlags;
+ blt_data.srcOffset = 0;
+ blt_data.srcPitch = width * 4;
+ blt_data.dstOffset = lbb_off;
+ blt_data.dstPitch = stride;
+ blt_data.src_left = xp;
+ blt_data.src_top = yp;
+ blt_data.src_right = width;
+ blt_data.src_bottom = height;
+ blt_data.dst_left = x;
+ blt_data.dst_top = y;
+ blt_data.dst_right = x + dw;
+ blt_data.dst_bottom = y + dh;
+ blt_data.srcFormat = SURF_ARGB8888;
+ blt_data.dstFormat = SURF_ARGB8888;
+ blt_data.srcMemBase = (char *)backbuffer;
+ blt_data.dstMemBase = (char *)lfb;
+ blt_data.srcMemSize = mem_sz;
+ blt_data.dstMemSize = stride * yRes + lbb_off;
+
+ mark(x, y, blt_data.dst_right, blt_data.dst_bottom);
+ OpenThreads::ScopedLock m_lock(mutex);
+ ioctl(fd, STMFBIO_SYNC_BLITTER);
+ if (fbbuff != backbuffer)
+ memmove(backbuffer, fbbuff, mem_sz);
+ // icons are so small that they will still be in cache
+ msync(backbuffer, backbuf_sz, MS_SYNC);
+
+ if (ioctl(fd, STMFBIO_BLT_EXTERN, &blt_data) < 0)
+ perror(LOGTAG "blit2FB STMFBIO_BLT_EXTERN");
+ return;
+}
+
+#define BLIT_INTERVAL_MIN 40
+#define BLIT_INTERVAL_MAX 250
+void CFbAccelSTi::run()
+{
+ printf(LOGTAG "::run start\n");
+ time_t last_blit = 0;
+ blit_pending = false;
+ blit_thread = true;
+ blit_mutex.lock();
+ set_threadname("stifb::autoblit");
+ while (blit_thread) {
+ blit_cond.wait(&blit_mutex, blit_pending ? BLIT_INTERVAL_MIN : BLIT_INTERVAL_MAX);
+ time_t now = time_monotonic_ms();
+ if (now - last_blit < BLIT_INTERVAL_MIN)
+ {
+ blit_pending = true;
+ //printf(LOGTAG "::run: skipped, time %ld\n", now - last_blit);
+ }
+ else
+ {
+ blit_pending = false;
+ blit_mutex.unlock();
+ _blit();
+ blit_mutex.lock();
+ last_blit = now;
+ }
+ }
+ blit_mutex.unlock();
+ printf(LOGTAG "::run end\n");
+}
+
+void CFbAccelSTi::blit()
+{
+ //printf(LOGTAG "::blit\n");
+ blit_mutex.lock();
+ blit_cond.signal();
+ blit_mutex.unlock();
+}
+
+void CFbAccelSTi::_blit()
+{
+#if 0
+ static time_t last = 0;
+ time_t now = time_monotonic_ms();
+ printf("%s %ld\n", __func__, now - last);
+ last = now;
+#endif
+ OpenThreads::ScopedLock m_lock(mutex);
+#ifdef PARTIAL_BLIT
+ if (to_blit.xs == INT_MAX)
+ return;
+
+ int srcXa = to_blit.xs;
+ int srcYa = to_blit.ys;
+ int srcXb = to_blit.xe;
+ int srcYb = to_blit.ye;
+#else
+ const int srcXa = 0;
+ const int srcYa = 0;
+ int srcXb = xRes;
+ int srcYb = yRes;
+#endif
+ STMFBIO_BLT_DATA bltData;
+ memset(&bltData, 0, sizeof(STMFBIO_BLT_DATA));
+
+ bltData.operation = BLT_OP_COPY;
+ //bltData.ulFlags = BLT_OP_FLAGS_BLEND_SRC_ALPHA | BLT_OP_FLAGS_BLEND_DST_MEMORY; // we need alpha blending
+ // src
+ bltData.srcOffset = lbb_off;
+ bltData.srcPitch = stride;
+
+ bltData.src_left = srcXa;
+ bltData.src_top = srcYa;
+ bltData.src_right = srcXb;
+ bltData.src_bottom = srcYb;
+
+ bltData.srcFormat = SURF_BGRA8888;
+ bltData.srcMemBase = STMFBGP_FRAMEBUFFER;
+
+ /* calculate dst/blit factor */
+ fb_var_screeninfo s;
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &s) == -1)
+ perror("CFbAccel ");
+
+#ifdef PARTIAL_BLIT
+ if (s.xres != last_xres) /* fb resolution has changed -> clear artifacts */
+ {
+ last_xres = s.xres;
+ bltData.src_left = 0;
+ bltData.src_top = 0;
+ bltData.src_right = xRes;
+ bltData.src_bottom = yRes;
+ }
+
+ double xFactor = (double)s.xres/(double)xRes;
+ double yFactor = (double)s.yres/(double)yRes;
+
+ int desXa = xFactor * bltData.src_left;
+ int desYa = yFactor * bltData.src_top;
+ int desXb = xFactor * bltData.src_right;
+ int desYb = yFactor * bltData.src_bottom;
+#else
+ const int desXa = 0;
+ const int desYa = 0;
+ int desXb = s.xres;
+ int desYb = s.yres;
+#endif
+
+ /* dst */
+ bltData.dstOffset = 0;
+ bltData.dstPitch = s.xres * 4;
+
+ bltData.dst_left = desXa;
+ bltData.dst_top = desYa;
+ bltData.dst_right = desXb;
+ bltData.dst_bottom = desYb;
+
+ bltData.dstFormat = SURF_BGRA8888;
+ bltData.dstMemBase = STMFBGP_FRAMEBUFFER;
+
+ //printf("CFbAccelSTi::blit: sx:%d sy:%d sxe:%d sye: %d dx:%d dy:%d dxe:%d dye:%d\n", srcXa, srcYa, srcXb, srcYb, desXa, desYa, desXb, desYb);
+ if ((bltData.dst_right > s.xres) || (bltData.dst_bottom > s.yres))
+ printf(LOGTAG "blit: values out of range desXb:%d desYb:%d\n",
+ bltData.dst_right, bltData.dst_bottom);
+
+ if(ioctl(fd, STMFBIO_SYNC_BLITTER) < 0)
+ perror(LOGTAG "blit ioctl STMFBIO_SYNC_BLITTER 1");
+ msync(lbb, xRes * 4 * yRes, MS_SYNC);
+ if (ioctl(fd, STMFBIO_BLT, &bltData ) < 0)
+ perror(LOGTAG "STMFBIO_BLT");
+ if(ioctl(fd, STMFBIO_SYNC_BLITTER) < 0)
+ perror(LOGTAG "blit ioctl STMFBIO_SYNC_BLITTER 2");
+
+#ifdef PARTIAL_BLIT
+ to_blit.xs = to_blit.ys = INT_MAX;
+ to_blit.xe = to_blit.ye = 0;
+#endif
+}
+
+/* not really used yet */
+#ifdef PARTIAL_BLIT
+void CFbAccelSTi::mark(int xs, int ys, int xe, int ye)
+{
+ OpenThreads::ScopedLock m_lock(mutex);
+ if (xs < to_blit.xs)
+ to_blit.xs = xs;
+ if (ys < to_blit.ys)
+ to_blit.ys = ys;
+ if (xe > to_blit.xe) {
+ if (xe >= (int)xRes)
+ to_blit.xe = xRes - 1;
+ else
+ to_blit.xe = xe;
+ }
+ if (ye > to_blit.ye) {
+ if (ye >= (int)xRes)
+ to_blit.ye = yRes - 1;
+ else
+ to_blit.ye = ye;
+ }
+#if 0
+ /* debug code that kills neutrino right away if the blit area is invalid
+ * only enable this for creating a coredump for debugging */
+ fb_var_screeninfo s;
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &s) == -1)
+ perror("CFbAccel ");
+ if ((xe > s.xres) || (ye > s.yres)) {
+ fprintf(stderr, LOGTAG "mark: values out of range xe:%d ye:%d\n", xe, ye);
+ int *kill = NULL;
+ *kill = 1; /* oh my */
+ }
+#endif
+}
+#else
+void CFbAccelSTi::mark(int, int, int, int)
+{
+}
+#endif
+
+/* wrong name... */
+int CFbAccelSTi::setMode(unsigned int, unsigned int, unsigned int)
+{
+ /* it's all fake... :-) */
+ xRes = screeninfo.xres = screeninfo.xres_virtual = DEFAULT_XRES;
+ yRes = screeninfo.yres = screeninfo.yres_virtual = DEFAULT_YRES;
+ bpp = screeninfo.bits_per_pixel = DEFAULT_BPP;
+ stride = screeninfo.xres * screeninfo.bits_per_pixel / 8;
+ return 0;
+}
+
+fb_pixel_t *CFbAccelSTi::getBackBufferPointer() const
+{
+ return backbuffer;
+}
+
+/* original interfaceL: 1 == pixel alpha, 2 == global alpha premultiplied */
+void CFbAccelSTi::setBlendMode(uint8_t mode)
+{
+ /* mode = 1 => reset to no extra transparency */
+ if (mode == 1)
+ setBlendLevel(0);
+}
+
+/* level = 100 -> transparent, level = 0 -> nontransperent */
+void CFbAccelSTi::setBlendLevel(int level)
+{
+ struct stmfbio_var_screeninfo_ex v;
+ memset(&v, 0, sizeof(v));
+ /* set to 0 already...
+ v.layerid = 0;
+ v.activate = STMFBIO_ACTIVATE_IMMEDIATE; // == 0
+ v.premultiplied_alpha = 0;
+ */
+ v.caps = STMFBIO_VAR_CAPS_OPACITY | STMFBIO_VAR_CAPS_PREMULTIPLIED;
+ v.opacity = 0xff - (level * 0xff / 100);
+ if (ioctl(fd, STMFBIO_SET_VAR_SCREENINFO_EX, &v) < 0)
+ perror(LOGTAG "setBlendLevel STMFBIO");
+}
+
+#if 0
+/* this is not accelerated... */
+void CFbAccelSTi::paintPixel(const int x, const int y, const fb_pixel_t col)
+{
+ fb_pixel_t *pos = getFrameBufferPointer();
+ pos += (stride / sizeof(fb_pixel_t)) * y;
+ pos += x;
+ *pos = col;
+}
+
+/* unused, because horizontal and vertical line are not acceleratedn in paintRect anyway
+ * and everything else is identical to fb_generic code */
+void CFbAccelSTi::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col)
+{
+ int dx = abs (xa - xb);
+ int dy = abs (ya - yb);
+ if (dy == 0) /* horizontal line */
+ {
+ /* paintRect actually is 1 pixel short to the right,
+ * but that's bug-compatibility with the GXA code */
+ paintRect(xa, ya, xb - xa, 1, col);
+ return;
+ }
+ if (dx == 0) /* vertical line */
+ {
+ paintRect(xa, ya, 1, yb - ya, col);
+ return;
+ }
+ int x;
+ int y;
+ int End;
+ int step;
+
+ if (dx > dy)
+ {
+ int p = 2 * dy - dx;
+ int twoDy = 2 * dy;
+ int twoDyDx = 2 * (dy-dx);
+
+ if (xa > xb)
+ {
+ x = xb;
+ y = yb;
+ End = xa;
+ step = ya < yb ? -1 : 1;
+ }
+ else
+ {
+ x = xa;
+ y = ya;
+ End = xb;
+ step = yb < ya ? -1 : 1;
+ }
+
+ paintPixel(x, y, col);
+
+ while (x < End)
+ {
+ x++;
+ if (p < 0)
+ p += twoDy;
+ else
+ {
+ y += step;
+ p += twoDyDx;
+ }
+ paintPixel(x, y, col);
+ }
+ }
+ else
+ {
+ int p = 2 * dx - dy;
+ int twoDx = 2 * dx;
+ int twoDxDy = 2 * (dx-dy);
+
+ if (ya > yb)
+ {
+ x = xb;
+ y = yb;
+ End = ya;
+ step = xa < xb ? -1 : 1;
+ }
+ else
+ {
+ x = xa;
+ y = ya;
+ End = yb;
+ step = xb < xa ? -1 : 1;
+ }
+
+ paintPixel(x, y, col);
+
+ while (y < End)
+ {
+ y++;
+ if (p < 0)
+ p += twoDx;
+ else
+ {
+ x += step;
+ p += twoDxDy;
+ }
+ paintPixel(x, y, col);
+ }
+ }
+ mark(xa, ya, xb, yb);
+ blit();
+}
+#endif
diff --git a/src/driver/fb_generic.cpp b/src/driver/fb_generic.cpp
index 69066e7bc..5607aef16 100644
--- a/src/driver/fb_generic.cpp
+++ b/src/driver/fb_generic.cpp
@@ -30,7 +30,8 @@
#include
#endif
-#include
+#include
+#include
#include
#include
@@ -118,8 +119,12 @@ CFrameBuffer* CFrameBuffer::getInstance()
{
static CFrameBuffer* frameBuffer = NULL;
- if(!frameBuffer) {
- frameBuffer = new CFrameBuffer();
+ if (!frameBuffer) {
+#if HAVE_SPARK_HARDWARE
+ frameBuffer = new CFbAccelSTi();
+#endif
+ if (!frameBuffer)
+ frameBuffer = new CFrameBuffer();
printf("[neutrino] %s Instance created\n", frameBuffer->fb_name);
}
return frameBuffer;
@@ -715,6 +720,7 @@ void CFrameBuffer::paintVLineRel(int x, int y, int dy, const fb_pixel_t col)
return;
paintVLineRelInternal(x, y, dy, col);
+ mark(x, y, x, y + dy);
}
void CFrameBuffer::paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col)
@@ -731,6 +737,7 @@ void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col)
return;
paintHLineRelInternal(x, dx, y, col);
+ mark(x, y, x + dx, y);
}
void CFrameBuffer::setIconBasePath(const std::string & iconPath)
@@ -1245,6 +1252,7 @@ void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t co
paintPixel (x, y, col);
}
}
+ mark(xa, ya, xb, yb);
}
#if 0
//never used
@@ -1533,6 +1541,7 @@ void CFrameBuffer::RestoreScreen(int x, int y, int dx, int dy, fb_pixel_t * cons
fbpos += stride;
bkpos += dx;
}
+ mark(x, y, x + dx, y + dy);
checkFbArea(x, y, dx, dy, false);
}
#if 0