libtriple/framebuffer: use DirectFB acceleration

Use a hack, almost as ugly as the original Coolstream code ;),
to accelerate drawing of boxes and blitting with DirectFB functions.
This commit is contained in:
Stefan Seyfried
2010-08-20 00:48:25 +02:00
parent 000fbfe74b
commit 9fc1d89563
4 changed files with 137 additions and 6 deletions

View File

@@ -21,11 +21,12 @@ static const char * FILENAME = "init_td.cpp";
static bool initialized = false; static bool initialized = false;
/* the super interface */ /* the super interface */
static IDirectFB *dfb; IDirectFB *dfb;
/* the primary surface */ /* the primary surface */
static IDirectFBSurface *primary; static IDirectFBSurface *primary;
static IDirectFBSurface *dest; IDirectFBSurface *dfbdest;
static IDirectFBDisplayLayer *layer; static IDirectFBDisplayLayer *layer;
int gfxfd = -1;
#define DFBCHECK(x...) \ #define DFBCHECK(x...) \
err = x; \ err = x; \
@@ -74,13 +75,13 @@ static void dfb_init()
primary->GetPixelFormat(primary, &pixelformat); primary->GetPixelFormat(primary, &pixelformat);
primary->GetSize(primary, &SW, &SH); primary->GetSize(primary, &SW, &SH);
primary->Clear(primary, 0, 0, 0, 0); primary->Clear(primary, 0, 0, 0, 0);
primary->GetSubSurface(primary, NULL, &dest); primary->GetSubSurface(primary, NULL, &dfbdest);
dest->Clear(dest, 0, 0, 0, 0); dfbdest->Clear(dfbdest, 0, 0, 0, 0);
} }
static void dfb_deinit() static void dfb_deinit()
{ {
dest->Release(dest); dfbdest->Release(dfbdest);
primary->Release(primary); primary->Release(primary);
layer->Release(layer); layer->Release(layer);
dfb->Release(dfb); dfb->Release(dfb);
@@ -119,6 +120,9 @@ void init_td_api()
if (setpgid(0, pid)) if (setpgid(0, pid))
perror("setpgid"); perror("setpgid");
rc_init(); rc_init();
gfxfd = open("/dev/stb/tdgfx", O_RDWR);
if (gfxfd < 0)
perror("open /dev/stb/tdgfx");
} }
initialized = true; initialized = true;
fprintf(stderr, "%s:%s end\n", FILENAME, __FUNCTION__); fprintf(stderr, "%s:%s end\n", FILENAME, __FUNCTION__);
@@ -129,5 +133,8 @@ void shutdown_td_api()
fprintf(stderr, "%s:%s, initialized = %d\n", FILENAME, __FUNCTION__, (int)initialized); fprintf(stderr, "%s:%s, initialized = %d\n", FILENAME, __FUNCTION__, (int)initialized);
if (initialized) if (initialized)
dfb_deinit(); dfb_deinit();
if (gfxfd > -1)
close(gfxfd);
gfxfd = -1;
initialized = false; initialized = false;
} }

View File

@@ -50,7 +50,8 @@ libneutrino_driver_a_SOURCES += \
lcdd.cpp lcdd.cpp
INCLUDES += \ INCLUDES += \
-I$(top_srcdir)/lib/libtriple -I$(top_srcdir)/lib/libtriple \
@DIRECTFB_CFLAGS@
endif endif
libneutrino_driver_netfile_a_SOURCES = netfile.cpp libneutrino_driver_netfile_a_SOURCES = netfile.cpp

View File

@@ -149,6 +149,27 @@ void CFrameBuffer::waitForIdle(void)
} }
#endif /* USE_NEVIS_GXA */ #endif /* USE_NEVIS_GXA */
#if HAVE_TRIPLEDRAGON
#include <directfb.h>
#include <tdgfx/stb04gfx.h>
extern IDirectFB *dfb;
extern IDirectFBSurface *dfbdest;
extern int gfxfd;
void CFrameBuffer::waitForIdle(void)
{
#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
}
#endif
/*******************************************************************************/ /*******************************************************************************/
static uint8_t * virtual_fb = NULL; static uint8_t * virtual_fb = NULL;
@@ -632,9 +653,14 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int
int corner_bl = (type & CORNER_BOTTOM_LEFT) ? 1 : 0; int corner_bl = (type & CORNER_BOTTOM_LEFT) ? 1 : 0;
int corner_br = (type & CORNER_BOTTOM_RIGHT) ? 1 : 0; int corner_br = (type & CORNER_BOTTOM_RIGHT) ? 1 : 0;
#if HAVE_TRIPLEDRAGON
char *c = (char *)&col;
dfbdest->SetColor(dfbdest, c[1], c[2], c[3], c[0]);
#else
#ifndef USE_NEVIS_GXA #ifndef USE_NEVIS_GXA
int swidth = stride / sizeof(fb_pixel_t); int swidth = stride / sizeof(fb_pixel_t);
fb_pixel_t *fbp = getFrameBufferPointer() + (swidth * y); fb_pixel_t *fbp = getFrameBufferPointer() + (swidth * y);
#endif
#endif #endif
/* this table contains the x coordinates for a quarter circle (the bottom right quarter) with fixed /* this table contains the x coordinates for a quarter circle (the bottom right quarter) with fixed
@@ -720,6 +746,16 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int
ofl = corner_bl ? ofs : 0; ofl = corner_bl ? ofs : 0;
ofr = corner_br ? ofs : 0; ofr = corner_br ? ofs : 0;
} }
#if HAVE_TRIPLEDRAGON
else
{
int height = dy - ((corner_tl|corner_tr) + (corner_bl|corner_br)) * radius;
dfbdest->FillRectangle(dfbdest, x, y + line, dx, height);
line += height;
continue;
}
dfbdest->DrawLine(dfbdest, x + ofl, y + line, x + dx - ofr - 1, y + line);
#else
#ifdef USE_NEVIS_GXA #ifdef USE_NEVIS_GXA
_write_gxa(gxa_base, cmd, GXA_POINT(x + dx - ofr, y + line)); /* endig point */ _write_gxa(gxa_base, cmd, GXA_POINT(x + dx - ofr, y + line)); /* endig point */
_write_gxa(gxa_base, cmd, GXA_POINT(x + ofl, y + line)); /* start point */ _write_gxa(gxa_base, cmd, GXA_POINT(x + ofl, y + line)); /* start point */
@@ -729,12 +765,14 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int
*(fbp + pos) = col; *(fbp + pos) = col;
} }
fbp += swidth; fbp += swidth;
#endif
#endif #endif
line++; line++;
} }
} }
else else
{ {
#if !HAVE_TRIPLEDRAGON
while (line < dy) while (line < dy)
{ {
#ifdef USE_NEVIS_GXA #ifdef USE_NEVIS_GXA
@@ -749,6 +787,9 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int
#endif #endif
line++; line++;
} }
#else
dfbdest->FillRectangle(dfbdest, x, y + line, dx, dy - line);
#endif
} }
#ifdef USE_NEVIS_GXA #ifdef USE_NEVIS_GXA
/* the GXA seems to do asynchronous rendering, so we add a sync marker /* the GXA seems to do asynchronous rendering, so we add a sync marker
@@ -757,6 +798,7 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int
#endif #endif
} }
#if !HAVE_TRIPLEDRAGON
void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col) void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col)
{ {
if (!getActive()) if (!getActive())
@@ -850,6 +892,43 @@ void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col)
*(dest++) = col; *(dest++) = col;
#endif /* USE_NEVIS_GXA */ #endif /* USE_NEVIS_GXA */
} }
#else /* TRIPLEDRAGON */
void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col)
{
paintLine(x, y, x, y, col);
}
void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col)
{
if (!getActive())
return;
char *c = (char *)&col;
dfbdest->SetColor(dfbdest, c[1], c[2], c[3], c[0]);
dfbdest->DrawLine(dfbdest, xa, ya, xb, yb);
return;
}
void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col)
{
paintLine(x, ya, x, yb, col);
}
void CFrameBuffer::paintVLineRel(int x, int y, int dy, const fb_pixel_t col)
{
paintLine(x, y, x, y + dy, col);
}
void CFrameBuffer::paintHLine(int xa, int xb, int y, const fb_pixel_t col)
{
paintLine(xa, y, xb, y, col);
}
void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col)
{
paintLine(x, y, x + dx, y, col);
}
#endif /* TRIPLEDRAGON */
void CFrameBuffer::setIconBasePath(const std::string & iconPath) void CFrameBuffer::setIconBasePath(const std::string & iconPath)
{ {
@@ -1127,6 +1206,7 @@ void CFrameBuffer::loadPal(const std::string & filename, const unsigned char off
close(lfd); close(lfd);
} }
#if !HAVE_TRIPLEDRAGON
void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col) void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col)
{ {
if (!getActive()) if (!getActive())
@@ -1142,6 +1222,7 @@ void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col)
*pos = col; *pos = col;
#endif #endif
} }
#endif
void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const int dy, const int px, const fb_pixel_t col, const int rad) void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const int dy, const int px, const fb_pixel_t col, const int rad)
{ {
@@ -1204,6 +1285,7 @@ void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const
} }
#if !HAVE_TRIPLEDRAGON
void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col) void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col)
{ {
if (!getActive()) if (!getActive())
@@ -1291,6 +1373,7 @@ void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t co
} }
} }
} }
#endif
void CFrameBuffer::setBackgroundColor(const fb_pixel_t color) void CFrameBuffer::setBackgroundColor(const fb_pixel_t color)
{ {
@@ -1677,6 +1760,7 @@ void * CFrameBuffer::convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, uns
return int_convertRGB2FB(rgbbuff, x, y, 0, true); return int_convertRGB2FB(rgbbuff, x, y, 0, true);
} }
#if !HAVE_TRIPLEDRAGON
void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) void CFrameBuffer::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; int xc, yc;
@@ -1729,6 +1813,41 @@ void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32
} }
#endif #endif
} }
#else
void CFrameBuffer::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, "CFrameBuffer::blit2FB: ");
DirectFBErrorFatal("dfb->CreateSurface(dfb, &dsc, &surf)", err);
}
if (transp)
surf->SetSrcColorKey(surf, 0, 0, 0);
dfbdest->SetBlittingFlags(dfbdest, DSBLIT_SRC_COLORKEY);
dfbdest->Blit(dfbdest, surf, &src, xoff, yoff);
surf->Release(surf);
return;
}
#endif
void CFrameBuffer::displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb, int transp) void CFrameBuffer::displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb, int transp)
{ {

View File

@@ -214,8 +214,12 @@ class CFrameBuffer
#ifdef USE_NEVIS_GXA #ifdef USE_NEVIS_GXA
void add_gxa_sync_marker(void); void add_gxa_sync_marker(void);
void waitForIdle(void); void waitForIdle(void);
#else
#if HAVE_TRIPLEDRAGON
void waitForIdle(void);
#else #else
inline void waitForIdle(void) {}; inline void waitForIdle(void) {};
#endif
#endif #endif
void* convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp = 0xFF); void* convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp = 0xFF);
void* convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y); void* convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y);