diff --git a/src/driver/framebuffer.cpp b/src/driver/framebuffer.cpp index 1046929c8..862b2a373 100644 --- a/src/driver/framebuffer.cpp +++ b/src/driver/framebuffer.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -660,6 +661,114 @@ void CFrameBuffer::paletteSet(struct fb_cmap *map) } } +void CFrameBuffer::paintHLineRelInternal2Buf(const int& x, const int& dx, const int& y, const int& box_dx, const fb_pixel_t& col, fb_pixel_t* buf) +{ + uint8_t * pos = ((uint8_t *)buf) + x * sizeof(fb_pixel_t) + box_dx * sizeof(fb_pixel_t) * y; + fb_pixel_t * dest = (fb_pixel_t *)pos; + for (int i = 0; i < dx; i++) + *(dest++) = col; +} + +fb_pixel_t* CFrameBuffer::paintBoxRel2Buf(const int dx, const int dy, const fb_pixel_t col, fb_pixel_t* buf/* = NULL*/, int radius/* = 0*/, int type/* = CORNER_ALL*/) +{ + if (!getActive()) + return buf; + if (dx == 0 || dy == 0) { + dprintf(DEBUG_INFO, "[%s - %d]: radius %d, dx %d dy %d\n", __func__, __LINE__, radius, dx, dy); + return buf; + } + + fb_pixel_t* pixBuf = buf; + if (pixBuf == NULL) { + pixBuf = (fb_pixel_t*) cs_malloc_uncached(dx*dy*sizeof(fb_pixel_t)); + if (pixBuf == NULL) { + dprintf(DEBUG_NORMAL, "[%s #%d] Error cs_malloc_uncached\n", __func__, __LINE__); + return NULL; + } + } + memset((void*)pixBuf, '\0', dx*dy*sizeof(fb_pixel_t)); + + if (type && radius) { + setCornerFlags(type); + radius = limitRadius(dx, dy, radius); + + int line = 0; + while (line < dy) { + int ofl, ofr; + calcCorners(NULL, &ofl, &ofr, dy, line, radius, type); + if (dx-ofr-ofl < 1) { + if (dx-ofr-ofl == 0) { + dprintf(DEBUG_INFO, "[%s - %d]: radius %d, end x %d y %d\n", __func__, __LINE__, radius, dx-ofr-ofl, line); + } + else { + dprintf(DEBUG_INFO, "[%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; + } + paintHLineRelInternal2Buf(ofl, dx-ofl-ofr, line, dx, col, pixBuf); + line++; + } + } else { + fb_pixel_t *bp = pixBuf; + int line = 0; + while (line < dy) { + for (int pos = 0; pos < dx; pos++) + *(bp + pos) = col; + bp += dx; + line++; + } + } + return pixBuf; +} + +fb_pixel_t* CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int dy, + const fb_pixel_t /*col*/, gradientData_t *gradientData, + int radius, int type) +{ +#define MASK 0xFFFFFFFF + + fb_pixel_t* boxBuf = paintBoxRel2Buf(dx, dy, MASK, NULL, radius, type); + fb_pixel_t *bp = boxBuf; + fb_pixel_t *gra = gradientData->gradientBuf; + gradientData->boxBuf = boxBuf; + + if (gradientData->direction == gradientVertical) { + // vertical + for (int pos = 0; pos < dx; pos++) { + for(int count = 0; count < dy; count++) { + if (*(bp + pos) == MASK) + *(bp + pos) = (fb_pixel_t)(*(gra + count)); + bp += dx; + } + bp = boxBuf; + } + } else { + // horizontal + for (int line = 0; line < dy; line++) { + for (int pos = 0; pos < dx; pos++) { + if (*(bp + pos) == MASK) + *(bp + pos) = (fb_pixel_t)(*(gra + pos)); + } + bp += dx; + } + } + + if ((gradientData->mode & pbrg_noPaint) == pbrg_noPaint) + return boxBuf; + +// blit2FB(boxBuf, dx, dy, x, y); + blitBox2FB(boxBuf, dx, dy, x, y); + + if ((gradientData->mode & pbrg_noFree) == pbrg_noFree) + return boxBuf; + + cs_free_uncached(boxBuf); + + return NULL; +} + void CFrameBuffer::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) */ @@ -1826,6 +1935,30 @@ void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32 } } +void CFrameBuffer::blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff) +{ + checkFbArea(xoff, yoff, width, height, true); + + uint32_t swidth = stride / sizeof(fb_pixel_t); + fb_pixel_t *fbp = getFrameBufferPointer() + (swidth * yoff); + fb_pixel_t* data = (fb_pixel_t*)boxBuf; + + uint32_t line = 0; + while (line < height) { + fb_pixel_t *pixpos = &data[line * width]; + for (uint32_t pos = xoff; pos < xoff + width; pos++) { + //don't paint backgroundcolor (*pixpos = 0x00000000) + if (*pixpos) + *(fbp + pos) = *pixpos; + pixpos++; + } + fbp += swidth; + line++; + } + + checkFbArea(xoff, yoff, width, height, false); +} + 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 *fbbuff = NULL; diff --git a/src/driver/framebuffer.h b/src/driver/framebuffer.h index f2432ac86..5fdacb8b7 100644 --- a/src/driver/framebuffer.h +++ b/src/driver/framebuffer.h @@ -40,6 +40,14 @@ typedef struct fb_var_screeninfo t_fb_var_screeninfo; +typedef struct gradientData_t +{ + fb_pixel_t* gradientBuf; + fb_pixel_t* boxBuf; + bool direction; + int mode; +} gradientData_struct_t; + #define CORNER_TOP_LEFT 0x1 #define CORNER_TOP_RIGHT 0x2 #define CORNER_TOP 0x3 @@ -131,6 +139,7 @@ class CFrameBuffer void paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col); void paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col); + inline void paintHLineRelInternal2Buf(const int& x, const int& dx, const int& y, const int& box_dx, const fb_pixel_t& col, fb_pixel_t* buf); void paintShortHLineRelInternal(const int& x, const int& dx, const int& y, const fb_pixel_t& col); int limitRadius(const int& dx, const int& dy, int& radius); void setCornerFlags(const int& type); @@ -139,6 +148,18 @@ class CFrameBuffer bool calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius, const int& type); public: + + enum { + gradientHorizontal, + gradientVertical + }; + + enum { + pbrg_noOption = 0x00, + pbrg_noPaint = 0x01, + pbrg_noFree = 0x02 + }; + fb_pixel_t realcolor[256]; ~CFrameBuffer(); @@ -184,6 +205,9 @@ class CFrameBuffer }; void paintPixel(int x, int y, const fb_pixel_t col); + fb_pixel_t* paintBoxRel2Buf(const int dx, const int dy, const fb_pixel_t col, fb_pixel_t* buf = NULL, int radius = 0, int type = CORNER_ALL); + fb_pixel_t* paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, gradientData_t *gradientData, int radius = 0, int type = CORNER_ALL); + void paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius = 0, int type = CORNER_ALL); inline void paintBox(int xa, int ya, int xb, int yb, const fb_pixel_t col) { paintBoxRel(xa, ya, xb - xa, yb - ya, col); } inline void paintBox(int xa, int ya, int xb, int yb, const fb_pixel_t col, int radius, int type) { paintBoxRel(xa, ya, xb - xa, yb - ya, col, radius, type); } @@ -245,7 +269,7 @@ class CFrameBuffer void* convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y); void displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb = true, int transp = 0xFF); void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp = 0, uint32_t yp = 0, bool transp = false); - bool blitToPrimary(unsigned int * data, int dx, int dy, int sw, int sh); + void blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff); enum {