From b04b1d7f8c1faec98c4cd808a991b859f31a203f Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 8 Feb 2017 23:53:54 +0100 Subject: [PATCH] fb_accel: add TripleDragon framebuffer code --- src/driver/Makefile.am | 1 + src/driver/fb_accel.h | 21 +++++ src/driver/fb_accel_td.cpp | 176 +++++++++++++++++++++++++++++++++++++ src/driver/fb_generic.cpp | 3 + 4 files changed, 201 insertions(+) create mode 100644 src/driver/fb_accel_td.cpp diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am index cb2a5ef11..393a5bf8e 100644 --- a/src/driver/Makefile.am +++ b/src/driver/Makefile.am @@ -59,6 +59,7 @@ endif if BOXTYPE_TRIPLE libneutrino_driver_a_SOURCES += \ + fb_accel_td.cpp \ newclock.cpp \ lcdd.cpp endif diff --git a/src/driver/fb_accel.h b/src/driver/fb_accel.h index 148c9f591..d67dc75d0 100644 --- a/src/driver/fb_accel.h +++ b/src/driver/fb_accel.h @@ -150,4 +150,25 @@ class CFbAccelGLFB fb_pixel_t * getBackBufferPointer() const; }; +class CFbAccelTD + : public CFbAccel +{ + private: + fb_pixel_t lastcol; + void setColor(fb_pixel_t col); + fb_pixel_t *backbuffer; + public: + CFbAccelTD(); + ~CFbAccelTD(); + 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 paintHLineRel(int x, int dx, int y, const fb_pixel_t col) { paintLine(x, y, x + dx, y, col); }; + void paintVLineRel(int x, int y, int dy, const fb_pixel_t col) { paintLine(x, y, x, y + dy, 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); + void waitForIdle(const char *func = NULL); +}; + #endif diff --git a/src/driver/fb_accel_td.cpp b/src/driver/fb_accel_td.cpp new file mode 100644 index 000000000..7cddcfa3c --- /dev/null +++ b/src/driver/fb_accel_td.cpp @@ -0,0 +1,176 @@ +/* + Framebuffer acceleration hardware abstraction functions. + The hardware dependent framebuffer acceleration functions for the + TripleDragon are represented in this class using DirectFB. + + License: GPL + + (C) 2017 Stefan Seyfried + + 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 + +#define LOGTAG "[fb_accel_td] " + +#include +#include +extern IDirectFB *dfb; +extern IDirectFBSurface *dfbdest; +extern int gfxfd; +void CFbAccelTD::waitForIdle(const char *) +{ +#if 0 + struct timeval ts, te; + gettimeofday(&ts, NULL); +#endif + /* does not work: DFBResult r = dfb->WaitForSync(dfb); */ + ioctl(gfxfd, STB04GFX_ENGINE_SYNC); +#if 0 + gettimeofday(&te, NULL); + printf("STB04GFX_ENGINE_SYNC took %lld us\n", (te.tv_sec * 1000000LL + te.tv_usec) - (ts.tv_sec * 1000000LL + ts.tv_usec)); +#endif +} + +CFbAccelTD::CFbAccelTD() +{ + fb_name = "TripleDragon framebuffer"; + lastcol = 0xffffffff; + lbb = lfb; /* the memory area to draw to... */ +}; + +CFbAccelTD::~CFbAccelTD() +{ + if (lfb) + munmap(lfb, available); + if (fd > -1) + close(fd); +} + +void CFbAccelTD::setColor(fb_pixel_t col) +{ + if (col == lastcol) + return; + char *c = (char *)&col; + dfbdest->SetColor(dfbdest, c[1], c[2], c[3], c[0]); + lastcol = col; +} + +void CFbAccelTD::paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col) +{ + setColor(col); + dfbdest->FillRectangle(dfbdest, x, y, dx, dy); +} + +void CFbAccelTD::paintPixel(const int x, const int y, const fb_pixel_t col) +{ + setColor(col); + dfbdest->DrawLine(dfbdest, x, y, x, y); +} + +void CFbAccelTD::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col) +{ + setColor(col); + dfbdest->DrawLine(dfbdest, xa, ya, xb, yb); +} + +void CFbAccelTD::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) +{ + DFBRectangle src; + DFBResult err; + IDirectFBSurface *surf; + DFBSurfaceDescription dsc; + + src.x = xp; + src.y = yp; + src.w = width - xp; + src.h = height - yp; + + dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PREALLOCATED); + dsc.caps = DSCAPS_NONE; + dsc.width = width; + dsc.height = height; + dsc.preallocated[0].data = fbbuff; + dsc.preallocated[0].pitch = width * sizeof(fb_pixel_t); + err = dfb->CreateSurface(dfb, &dsc, &surf); + /* TODO: maybe we should not die if this fails? */ + if (err != DFB_OK) { + fprintf(stderr, LOGTAG "blit2FB: "); + DirectFBErrorFatal("dfb->CreateSurface(dfb, &dsc, &surf)", err); + } + + if (transp) + { + surf->SetSrcColorKey(surf, 0, 0, 0); + dfbdest->SetBlittingFlags(dfbdest, DSBLIT_SRC_COLORKEY); + } + else + dfbdest->SetBlittingFlags(dfbdest, DSBLIT_BLEND_ALPHACHANNEL); + + dfbdest->Blit(dfbdest, surf, &src, xoff, yoff); + surf->Release(surf); + return; +} + +void CFbAccelTD::init(const char *) +{ + 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... */ + available = fix.smem_len; + stride = fix.line_length; + xRes = screeninfo.xres; + yRes = screeninfo.yres; + bpp = screeninfo.bits_per_pixel; + + return; +} + +/* wrong name... */ +int CFbAccelTD::setMode(unsigned int, unsigned int, unsigned int) +{ + 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; +} diff --git a/src/driver/fb_generic.cpp b/src/driver/fb_generic.cpp index 1ded80c78..3453fee1e 100644 --- a/src/driver/fb_generic.cpp +++ b/src/driver/fb_generic.cpp @@ -133,6 +133,9 @@ CFrameBuffer* CFrameBuffer::getInstance() #endif #if HAVE_GENERIC_HARDWARE frameBuffer = new CFbAccelGLFB(); +#endif +#if HAVE_TRIPLEDRAGON + frameBuffer = new CFbAccelTD(); #endif if (!frameBuffer) frameBuffer = new CFrameBuffer();