diff --git a/src/driver/fbaccel.cpp b/src/driver/fbaccel.cpp index cab2efc34..29b0a0b2b 100644 --- a/src/driver/fbaccel.cpp +++ b/src/driver/fbaccel.cpp @@ -59,6 +59,7 @@ extern GLFramebuffer *glfb; #endif #include +#include #include #if HAVE_COOL_HARDWARE || HAVE_TRIPLEDRAGON @@ -67,6 +68,15 @@ extern GLFramebuffer *glfb; #define NEED_BLIT_THREAD 1 #endif +#ifdef BOXMODEL_APOLLO +#ifndef FB_HW_ACCELERATION +#define FB_HW_ACCELERATION +#endif +#endif +#if defined(FB_HW_ACCELERATION) && defined(USE_NEVIS_GXA) +#error +#endif + /* note that it is *not* enough to just change those values */ #define DEFAULT_XRES 1280 #define DEFAULT_YRES 720 @@ -1127,3 +1137,178 @@ int CFbAccel::setMode(void) (void) si; return 0; } + +#if HAVE_COOL_HARDWARE + +void CFbAccel::paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col) +{ + +#if defined(FB_HW_ACCELERATION) + fb_fillrect fillrect; + fillrect.dx = x; + fillrect.dy = y; + fillrect.width = 1; + fillrect.height = dy; + fillrect.color = col; + fillrect.rop = ROP_COPY; + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); +#elif defined(USE_NEVIS_GXA) + /* draw a single vertical line from point x/y with hight dx */ + 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; + + _write_gxa(gxa_base, GXA_FG_COLOR_REG, (unsigned int) col); /* setup the drawing color */ + _write_gxa(gxa_base, GXA_LINE_CONTROL_REG, 0x00000404); /* X is major axis, skip last pixel */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y + dy)); /* end point */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* start point */ +#else /* USE_NEVIS_GXA */ + uint8_t * pos = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + + for(int count=0;count= 10) { + fb_fillrect fillrect; + fillrect.dx = x; + fillrect.dy = y; + fillrect.width = dx; + fillrect.height = 1; + fillrect.color = col; + fillrect.rop = ROP_COPY; + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); + return; + } +#endif +#if defined(USE_NEVIS_GXA) + /* draw a single horizontal line from point x/y with width dx */ + 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; + + _write_gxa(gxa_base, GXA_FG_COLOR_REG, (unsigned int) col); /* setup the drawing color */ + _write_gxa(gxa_base, GXA_LINE_CONTROL_REG, 0x00000404); /* X is major axis, skip last pixel */ + _write_gxa(gxa_base, cmd, GXA_POINT(x + dx, y)); /* end point */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* start point */ +#else /* USE_NEVIS_GXA */ + uint8_t * pos = ((uint8_t *)fb->getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + fb->stride * y; + + fb_pixel_t * dest = (fb_pixel_t *)pos; + for (int i = 0; i < dx; i++) + *(dest++) = col; +#endif /* USE_NEVIS_GXA */ +} + +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 (dx == 0 || dy == 0) { + dprintf(DEBUG_NORMAL, "[CFbAccel] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __FUNCTION__, __LINE__, radius, x, y, x+dx, y+dy); + return; + } + + bool corner_tl = !!(type & CORNER_TOP_LEFT); + bool corner_tr = !!(type & CORNER_TOP_RIGHT); + bool corner_bl = !!(type & CORNER_BOTTOM_LEFT); + bool corner_br = !!(type & CORNER_BOTTOM_RIGHT); + +#if defined(FB_HW_ACCELERATION) + fb_fillrect fillrect; + fillrect.color = col; + fillrect.rop = ROP_COPY; +#elif defined(USE_NEVIS_GXA) + if (!fb_no_check) + OpenThreads::ScopedLock 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 */ +#endif + + if (type && radius) { + radius = fb->limitRadius(dx, dy, radius); + + int line = 0; + while (line < dy) { + int ofl, ofr; + if (fb->calcCorners(NULL, &ofl, &ofr, dy, line, radius, + corner_tl, corner_tr, corner_bl, corner_br)) { + //printf("3: x %d y %d dx %d dy %d rad %d line %d\n", x, y, dx, dy, radius, line); +#if defined(FB_HW_ACCELERATION) || defined(USE_NEVIS_GXA) + int rect_height_mult = ((type & CORNER_TOP) && (type & CORNER_BOTTOM)) ? 2 : 1; +#if defined(FB_HW_ACCELERATION) + fillrect.dx = x; + fillrect.dy = y + line; + fillrect.width = dx; + fillrect.height = dy - (radius * rect_height_mult); + + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); +#elif defined(USE_NEVIS_GXA) + _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 */ +#endif + line += dy - (radius * rect_height_mult); + continue; +#endif + } + + if (dx-ofr-ofl < 1) { + if (dx-ofr-ofl == 0){ + dprintf(DEBUG_INFO, "[CFbAccel] [%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, "[CFbAccel] [%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; + } +#ifdef USE_NEVIS_GXA + _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 */ +#else + paintHLineRelInternal(x+ofl, dx-ofl-ofr, y+line, col); +#endif + line++; + } + } else { +#if defined(FB_HW_ACCELERATION) + /* 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(fb->fd, FBIO_FILL_RECT, &fillrect); + return; + } +#endif +#if defined(USE_NEVIS_GXA) + _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 */ +#else + int swidth = fb->stride / sizeof(fb_pixel_t); + fb_pixel_t *fbp = fb->getFrameBufferPointer() + (swidth * y); + int line = 0; + while (line < dy) { + for (int pos = x; pos < x + dx; pos++) + *(fbp + pos) = col; + + fbp += swidth; + line++; + } +#endif + } +#ifdef USE_NEVIS_GXA + _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(); +#endif +} +#endif diff --git a/src/driver/fbaccel.h b/src/driver/fbaccel.h index 965df48c9..6dfd40467 100644 --- a/src/driver/fbaccel.h +++ b/src/driver/fbaccel.h @@ -89,6 +89,12 @@ class CFbAccel #ifdef USE_NEVIS_GXA void setupGXA(void); #endif + +#if HAVE_COOL_HARDWARE + void paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col); + void paintHLineRelInternal(int x, int dx, int y, 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, int type); +#endif }; #endif diff --git a/src/driver/framebuffer_ng.cpp b/src/driver/framebuffer_ng.cpp index 96dbbc206..608adfe90 100644 --- a/src/driver/framebuffer_ng.cpp +++ b/src/driver/framebuffer_ng.cpp @@ -119,7 +119,7 @@ static const int q_circle[541] = { 147, 144, 140, 136, 132, 128, 124, 120, 115, 111, 105, 101, 95, 89, 83, 77, 69, 61, 52, 40, 23}; -static inline bool calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius, +bool CFrameBuffer::calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius, const bool& tl, const bool& tr, const bool& bl, const bool& br) { /* just a multiplicator for all math to reduce rounding errors */ @@ -155,7 +155,7 @@ static inline bool calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, cons return ret; } -static inline int limitRadius(const int& dx, const int& dy, const int& radius) +int CFrameBuffer::limitRadius(const int& dx, const int& dy, const int& radius) { int m = std::min(dx, dy); if (radius > m) @@ -630,6 +630,12 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int if (!getActive()) return; +#if HAVE_COOL_HARDWARE + checkFbArea(x, y, dx, dy, true); + accel->paintBoxRel(x, y, dx, dy, col, radius, type); + checkFbArea(x, y, dx, dy, false); +#else + bool corner_tl = !!(type & CORNER_TOP_LEFT); bool corner_tr = !!(type & CORNER_TOP_RIGHT); bool corner_bl = !!(type & CORNER_BOTTOM_LEFT); @@ -670,6 +676,7 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int } checkFbArea(x, y, dx, dy, false); accel->mark(x, y, x+dx, y+dy); +#endif } void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col) @@ -692,22 +699,50 @@ void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t co void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col) { +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintVLineRelInternal(x, ya, yb-ya, col); +#else paintLine(x, ya, x, yb, col); +#endif } void CFrameBuffer::paintVLineRel(int x, int y, int dy, const fb_pixel_t col) { +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintVLineRelInternal(x, y, dy, col); +#else paintLine(x, y, x, y + dy, col); +#endif } void CFrameBuffer::paintHLine(int xa, int xb, int y, const fb_pixel_t col) { +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintHLineRelInternal(xa, xb-xa, y, col); +#else paintLine(xa, y, xb, y, col); +#endif } void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col) { +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintHLineRelInternal(x, dx, y, col); +#else paintLine(x, y, x + dx, y, col); +#endif } void CFrameBuffer::setIconBasePath(const std::string & iconPath) @@ -1384,3 +1419,15 @@ void CFrameBuffer::stopFrame() { videoDecoder->StopPicture(); } + +#if HAVE_COOL_HARDWARE +void CFrameBuffer::paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col) +{ + accel->paintVLineRelInternal(x, y, dy, col); +} + +void CFrameBuffer::paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col) +{ + accel->paintHLineRelInternal(x, dx, y, col); +} +#endif diff --git a/src/driver/framebuffer_ng.h b/src/driver/framebuffer_ng.h index 9ae02af58..edc27812b 100644 --- a/src/driver/framebuffer_ng.h +++ b/src/driver/framebuffer_ng.h @@ -312,6 +312,14 @@ class CFrameBuffer void doPaintMuteIcon(bool mode) { do_paint_mute_icon = mode; } /* blit() is unnecessary, but here to avoid patches to the neutrino code */ void blit(void) {} + bool calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius, + const bool& tl, const bool& tr, const bool& bl, const bool& br); + int limitRadius(const int& dx, const int& dy, const int& radius); + +#if HAVE_COOL_HARDWARE + void paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col); + void paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col); +#endif }; #endif