fbaccel: implement partial blitting for SPARK

Blit only the parts of the screen that have changed. First
tests show better performance and no obvious errors. Might
still contain some bugs, you have been warned :-)
This commit is contained in:
Stefan Seyfried
2015-02-08 21:47:20 +01:00
parent 5fa8552fa6
commit d1573a510e
3 changed files with 51 additions and 8 deletions

View File

@@ -39,6 +39,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <memory.h> #include <memory.h>
#include <math.h> #include <math.h>
#include <limits.h>
#include <linux/kd.h> #include <linux/kd.h>
@@ -261,6 +262,11 @@ CFbAccel::CFbAccel(CFrameBuffer *_fb)
bpafd = -1; bpafd = -1;
return; return;
} }
#ifdef PARTIAL_BLIT
to_blit.xs = to_blit.ys = INT_MAX;
to_blit.xe = to_blit.ye = 0;
last_xres = 0;
#endif
#endif #endif
#ifdef USE_NEVIS_GXA #ifdef USE_NEVIS_GXA
@@ -460,10 +466,10 @@ void CFbAccel::paintRect(const int x, const int y, const int dx, const int dy, c
bltData.srcMemBase = STMFBGP_FRAMEBUFFER; bltData.srcMemBase = STMFBGP_FRAMEBUFFER;
bltData.colour = col; bltData.colour = col;
mark(xx, yy, bltData.dst_right, bltData.dst_bottom);
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
if (ioctl(fb->fd, STMFBIO_BLT, &bltData ) < 0) if (ioctl(fb->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,fb->stride); fprintf(stderr, "blitRect FBIO_BLIT: %m x:%d y:%d w:%d h:%d s:%d\n", xx,yy,width,height,fb->stride);
// update_dirty(xx, yy, bltData.dst_right, bltData.dst_bottom);
#else #else
int line = 0; int line = 0;
int swidth = fb->stride / sizeof(fb_pixel_t); int swidth = fb->stride / sizeof(fb_pixel_t);
@@ -601,6 +607,7 @@ void CFbAccel::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col)
paintPixel(x, y, col); paintPixel(x, y, col);
} }
} }
mark(xa, ya, xb, yb);
blit(); blit();
#endif #endif
} }
@@ -669,6 +676,7 @@ void CFbAccel::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t x
blt_data.srcMemSize = mem_sz; blt_data.srcMemSize = mem_sz;
blt_data.dstMemSize = fb->stride * fb->yRes + lbb_off; blt_data.dstMemSize = fb->stride * fb->yRes + lbb_off;
mark(x, y, blt_data.dst_right, blt_data.dst_bottom);
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex); OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
ioctl(fb->fd, STMFBIO_SYNC_BLITTER); ioctl(fb->fd, STMFBIO_SYNC_BLITTER);
if (fbbuff != backbuffer) if (fbbuff != backbuffer)
@@ -678,7 +686,6 @@ void CFbAccel::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t x
if (ioctl(fb->fd, STMFBIO_BLT_EXTERN, &blt_data) < 0) if (ioctl(fb->fd, STMFBIO_BLT_EXTERN, &blt_data) < 0)
perror("CFbAccel blit2FB STMFBIO_BLT_EXTERN"); perror("CFbAccel blit2FB STMFBIO_BLT_EXTERN");
//update_dirty(x, y, blt_data.dst_right, blt_data.dst_bottom);
return; return;
#else #else
fb_pixel_t *data = (fb_pixel_t *) fbbuff; fb_pixel_t *data = (fb_pixel_t *) fbbuff;
@@ -820,6 +827,7 @@ void CFbAccel::_blit()
printf("%s %ld\n", __func__, now - last); printf("%s %ld\n", __func__, now - last);
last = now; last = now;
#endif #endif
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
#ifdef PARTIAL_BLIT #ifdef PARTIAL_BLIT
if (to_blit.xs == INT_MAX) if (to_blit.xs == INT_MAX)
return; return;
@@ -862,12 +870,12 @@ void CFbAccel::_blit()
last_xres = s.xres; last_xres = s.xres;
bltData.src_left = 0; bltData.src_left = 0;
bltData.src_top = 0; bltData.src_top = 0;
bltData.src_right = xRes; bltData.src_right = fb->xRes;
bltData.src_bottom = yRes; bltData.src_bottom = fb->yRes;
} }
double xFactor = (double)s.xres/(double)xRes; double xFactor = (double)s.xres/(double)fb->xRes;
double yFactor = (double)s.yres/(double)yRes; double yFactor = (double)s.yres/(double)fb->yRes;
int desXa = xFactor * bltData.src_left; int desXa = xFactor * bltData.src_left;
int desYa = yFactor * bltData.src_top; int desYa = yFactor * bltData.src_top;
@@ -897,7 +905,6 @@ void CFbAccel::_blit()
printf("CFbAccel::blit: values out of range desXb:%d desYb:%d\n", printf("CFbAccel::blit: values out of range desXb:%d desYb:%d\n",
bltData.dst_right, bltData.dst_bottom); bltData.dst_right, bltData.dst_bottom);
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
if(ioctl(fb->fd, STMFBIO_SYNC_BLITTER) < 0) if(ioctl(fb->fd, STMFBIO_SYNC_BLITTER) < 0)
perror("CFbAccel::blit ioctl STMFBIO_SYNC_BLITTER 1"); perror("CFbAccel::blit ioctl STMFBIO_SYNC_BLITTER 1");
msync(lbb, fb->xRes * 4 * fb->yRes, MS_SYNC); msync(lbb, fb->xRes * 4 * fb->yRes, MS_SYNC);
@@ -952,7 +959,23 @@ void CFbAccel::_blit()
#ifdef PARTIAL_BLIT #ifdef PARTIAL_BLIT
void CFbAccel::mark(int xs, int ys, int xe, int ye) void CFbAccel::mark(int xs, int ys, int xe, int ye)
{ {
update_dirty(xs, ys, xe, ye); OpenThreads::ScopedLock<OpenThreads::Mutex> 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)fb->xRes)
to_blit.xe = fb->xRes - 1;
else
to_blit.xe = xe;
}
if (ye > to_blit.ye) {
if (ye >= (int)fb->xRes)
to_blit.ye = fb->yRes - 1;
else
to_blit.ye = ye;
}
} }
#else #else
void CFbAccel::mark(int, int, int, int) void CFbAccel::mark(int, int, int, int)

View File

@@ -36,6 +36,10 @@
#include <OpenThreads/Thread> #include <OpenThreads/Thread>
#include <OpenThreads/Condition> #include <OpenThreads/Condition>
#if HAVE_SPARK_HARDWARE
#define PARTIAL_BLIT 1
#endif
class CFrameBuffer; class CFrameBuffer;
class CFbAccel class CFbAccel
: public OpenThreads::Thread : public OpenThreads::Thread
@@ -57,6 +61,16 @@ class CFbAccel
bool blit_pending; bool blit_pending;
OpenThreads::Condition blit_cond; OpenThreads::Condition blit_cond;
OpenThreads::Mutex blit_mutex; OpenThreads::Mutex blit_mutex;
#ifdef PARTIAL_BLIT
OpenThreads::Mutex to_blit_mutex;
struct {
int xs;
int ys;
int xe;
int ye;
} to_blit;
uint32_t last_xres;
#endif
public: public:
fb_pixel_t *backbuffer; fb_pixel_t *backbuffer;
fb_pixel_t *lbb; fb_pixel_t *lbb;

View File

@@ -670,6 +670,7 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int
line++; line++;
} }
checkFbArea(x, y, dx, dy, false); checkFbArea(x, y, dx, dy, false);
accel->mark(x, y, x+dx, y+dy);
} }
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)
@@ -783,6 +784,7 @@ bool CFrameBuffer::paintIcon8(const std::string & filename, const int x, const i
d += stride; d += stride;
} }
close(lfd); close(lfd);
accel->mark(x, y, x + width, y + height);
accel->blit(); accel->blit();
return true; return true;
} }
@@ -1073,6 +1075,7 @@ void CFrameBuffer::paintBackgroundBoxRel(int x, int y, int dx, int dy)
bkpos += BACKGROUNDIMAGEWIDTH; bkpos += BACKGROUNDIMAGEWIDTH;
} }
checkFbArea(x, y, dx, dy, false); checkFbArea(x, y, dx, dy, false);
accel->mark(x, y, x + dx, y + dy);
} }
} }
@@ -1088,6 +1091,7 @@ void CFrameBuffer::paintBackground()
for (int i = 0; i < 576; i++) for (int i = 0; i < 576; i++)
memmove(((uint8_t *)getFrameBufferPointer()) + i * stride, (background + i * BACKGROUNDIMAGEWIDTH), BACKGROUNDIMAGEWIDTH * sizeof(fb_pixel_t)); memmove(((uint8_t *)getFrameBufferPointer()) + i * stride, (background + i * BACKGROUNDIMAGEWIDTH), BACKGROUNDIMAGEWIDTH * sizeof(fb_pixel_t));
checkFbArea(0, 0, xRes, yRes, false); checkFbArea(0, 0, xRes, yRes, false);
accel->mark(0, 0, xRes, yRes);
accel->blit(); accel->blit();
} }
else else
@@ -1138,6 +1142,7 @@ void CFrameBuffer::RestoreScreen(int x, int y, int dx, int dy, fb_pixel_t * cons
fbpos += stride; fbpos += stride;
bkpos += dx; bkpos += dx;
} }
accel->mark(x, y, x + dx, y + dy);
accel->blit(); accel->blit();
checkFbArea(x, y, dx, dy, false); checkFbArea(x, y, dx, dy, false);
} }
@@ -1238,6 +1243,7 @@ void CFrameBuffer::blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t
fbp += swidth; fbp += swidth;
line++; line++;
} }
accel->mark(xoff, yoff, xoff + width, xoff + height);
checkFbArea(xoff, yoff, width, height, false); checkFbArea(xoff, yoff, width, height, false);
} }