From 6e4437255b603b5b25360481507099dd9b92f942 Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 6 Sep 2013 12:29:06 +1000 Subject: GDISP revamp - stage 1 New low level driver interface: Only Win32 ported currently Significant reduction in GDISP stack usage Improved performance particularly for native streaming drivers New circle, ellipse, arc routines (draw and fill) that are significantly more efficient and don't overdraw New arc draw algorithm that measures angles correctly. New arc fill algorithm for that actually works without overdrawing or gaps. Much more to come... --- src/gdisp/gdisp.c | 2135 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 1611 insertions(+), 524 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 22773908..1aecd26c 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -19,438 +19,1526 @@ /* Include the low level driver information */ #include "gdisp/lld/gdisp_lld.h" +#if !GDISP_HARDWARE_STREAM && !GDISP_HARDWARE_DRAWPIXEL + #error "GDISP Driver: Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be defined" +#endif + +#if 1 + #undef INLINE + #define INLINE inline +#else + #undef INLINE + #define INLINE +#endif + /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ -#if GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC - static gfxMutex gdispMutex; +#define GC ((GDISPDriver *)GDISP) +GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; + +#if GDISP_NEED_MULTITHREAD + #define MUTEX_INIT() gfxMutexInit(&GC->mutex) + #define MUTEX_ENTER() gfxMutexEnter(&GC->mutex) + #define MUTEX_EXIT() gfxMutexExit(&GC->mutex) +#else + #define MUTEX_INIT() + #define MUTEX_ENTER() + #define MUTEX_EXIT() #endif -#if GDISP_NEED_ASYNC - #define GDISP_THREAD_STACK_SIZE 256 /* Just a number - not yet a reflection of actual use */ - #define GDISP_QUEUE_SIZE 8 /* We only allow a short queue */ +#if GDISP_HARDWARE_STREAM_END + #define STREAM_CLEAR() if ((GC->flags & GDISP_FLG_INSTREAM)) { \ + gdisp_lld_stream_end(); \ + GC->flags &= ~GDISP_FLG_INSTREAM; \ + } +#else + #define STREAM_CLEAR() GC->flags &= ~GDISP_FLG_INSTREAM +#endif - static gfxQueue gdispQueue; - static gfxMutex gdispMsgsMutex; - static gfxSem gdispMsgsSem; - static gdisp_lld_msg_t gdispMsgs[GDISP_QUEUE_SIZE]; - static DECLARE_THREAD_STACK(waGDISPThread, GDISP_THREAD_STACK_SIZE); +#define NEED_CLIPPING (!GDISP_HARDWARE_CLIP && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) + +/*==========================================================================*/ +/* Internal functions. */ +/*==========================================================================*/ + +// drawpixel_clip() +// Parameters: x,y +// Alters: cx, cy (if using streaming) +#if GDISP_HARDWARE_DRAWPIXEL + // Best is hardware accelerated pixel draw + #if NEED_CLIPPING + static INLINE void drawpixel_clip(void) { + if (GC->p.x >= GC->clipx0 && GC->p.x < GC->clipx1 && GC->p.y >= GC->clipy0 && GC->p.y < GC->clipy1) + gdisp_lld_draw_pixel(); + } + #else + #define drawpixel_clip() gdisp_lld_draw_pixel() + #endif +#else + // Worst is streaming + static INLINE void drawpixel_clip(void) { + #if NEED_CLIPPING + if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1 || GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) + return; + #endif + + GC->cx = GC->cy = 1; + gdisp_lld_stream_start(); + gdisp_lld_stream_color(); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(); + #endif + } #endif -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ +// fillarea() +// Parameters: x,y cx,cy and color +// Alters: nothing +// Note: This is not clipped +#if GDISP_HARDWARE_FILLS + // Best is hardware accelerated area fill + #define fillarea() gdisp_lld_fill_area() +#elif GDISP_HARDWARE_STREAM + // Next best is hardware streaming + static INLINE void fillarea(void) { + uint32_t area; + + area = (uint32_t)GC->p.cx * GC->p.cy; + + gdisp_lld_stream_start(); + for(; area; area--) + gdisp_lld_stream_color(); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(gc); + #endif + } +#else + // Worst is drawing pixels + static INLINE void fillarea(void) { + coord_t x0, y0, x1, y1; + + x0 = GC->p.x; + y0 = GC->p.y; + x1 = GC->p.x + GC->p.cx; + y1 = GC->p.y + GC->p.cy; + for(; GC->p.y < y1; GC->p.y++, GC->p.x = x0) + for(; GC->p.x < x1; GC->p.x++) + gdisp_lld_draw_pixel(); + GC->p.y = y0; + } +#endif -#if GDISP_NEED_ASYNC - static DECLARE_THREAD_FUNCTION(GDISPThreadHandler, arg) { - (void)arg; - gdisp_lld_msg_t *pmsg; +#if NEED_CLIPPING + #define TEST_CLIP_AREA(x,y,cx,cy) \ + if ((x) < GC->clipx0) { (cx) -= GC->clipx0 - (x); (x) = GC->clipx0; } \ + if ((y) < GC->clipy0) { (cy) -= GC->clipy0 - (y); (y) = GC->clipy0; } \ + if ((x) + (cx) > GC->clipx1) (cx) = GC->clipx1 - (x); \ + if ((y) + (cy) > GC->clipy1) (cy) = GC->clipy1 - (y); \ + if ((cx) > 0 && (cy) > 0) +#else + #define TEST_CLIP_AREA(x,y,cx,cy) +#endif - while(1) { - /* Wait for msg with work to do. */ - pmsg = (gdisp_lld_msg_t *)gfxQueueGet(&gdispQueue, TIME_INFINITE); +// Parameters: x,y and x1 +// Alters: x,y x1,y1 cx,cy +static void hline_clip(void) { + // Swap the points if necessary so it always goes from x to x1 + if (GC->p.x1 < GC->p.x) { + GC->p.cx = GC->p.x; GC->p.x = GC->p.x1; GC->p.x1 = GC->p.cx; + } + + // Clipping + #if NEED_CLIPPING + if (GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) return; + if (GC->p.x < GC->clipx0) GC->p.x = GC->clipx0; + if (GC->p.x1 >= GC->clipx1) GC->p.x1 = GC->clipx1 - 1; + if (GC->p.x1 < GC->p.x) return; + #endif - /* OK - we need to obtain the mutex in case a synchronous operation is occurring */ - gfxMutexEnter(&gdispMutex); + // This is an optimization for the point case. It is only worthwhile however if we + // have hardware fills or if we support both hardware pixel drawing and hardware streaming + #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM) + // Is this a point + if (GC->p.x == GC->p.x1) { + #if GDISP_HARDWARE_DRAWPIXEL + // Best is hardware accelerated pixel draw + gdisp_lld_draw_pixel(); + #else + // Worst is streaming + GC->p.cx = GC->p.cy = 1; + gdisp_lld_stream_start(); + gdisp_lld_stream_color(); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(); + #endif + #endif + return; + } + #endif + + #if GDISP_HARDWARE_FILLS + // Best is hardware accelerated area fill + GC->p.cx = GC->p.x1 - GC->p.x + 1; + GC->p.cy = 1; + gdisp_lld_fill_area(); + #elif GDISP_HARDWARE_STREAM + // Next best is streaming + GC->p.cx = GC->p.x1 - GC->p.x; + gdisp_lld_stream_start(); + do { gdisp_lld_stream_color(); } while(GC->p.cx--); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(); + #endif + #else + // Worst is drawing pixels + for(; GC->p.x <= GC->p.x1; GC->p.x++) + gdisp_lld_draw_pixel(); + #endif +} - gdisp_lld_msg_dispatch(pmsg); +// Parameters: x,y and y1 +// Alters: x,y x1,y1 cx,cy +static void vline_clip(void) { + // Swap the points if necessary so it always goes from y to y1 + if (GC->p.y1 < GC->p.y) { + GC->p.cy = GC->p.y; GC->p.y = GC->p.y1; GC->p.y1 = GC->p.cy; + } - /* Mark the message as free */ - pmsg->action = GDISP_LLD_MSG_NOP; + // Clipping + #if NEED_CLIPPING + if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1) return; + if (GC->p.y < GC->clipy0) GC->p.y = GC->clipy0; + if (GC->p.y1 >= GC->clipy1) GC->p.y1 = GC->clipy1 - 1; + if (GC->p.y1 < GC->p.y) return; + #endif - gfxMutexExit(&gdispMutex); + // This is an optimization for the point case. It is only worthwhile however if we + // have hardware fills or if we support both hardware pixel drawing and hardware streaming + #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM) + // Is this a point + if (GC->p.y == GC->p.y1) { + #if GDISP_HARDWARE_DRAWPIXEL + // Best is hardware accelerated pixel draw + gdisp_lld_draw_pixel(); + #else + // Worst is streaming + GC->p.cx = GC->p.cy = 1; + gdisp_lld_stream_start(); + gdisp_lld_stream_color(); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(); + #endif + #endif + return; } - return 0; + #endif + + #if GDISP_HARDWARE_FILLS + // Best is hardware accelerated area fill + GC->p.cy = GC->p.y1 - GC->p.y + 1; + GC->p.cx = 1; + gdisp_lld_fill_area(); + #elif GDISP_HARDWARE_STREAM + // Next best is streaming + GC->p.cy = GC->p.y1 - GC->p.y; + gdisp_lld_stream_start(); + do { gdisp_lld_stream_color(); } while(GC->p.cy--); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(); + #endif + #else + // Worst is drawing pixels + for(; GC->p.y <= GC->p.y1; GC->p.y++) + gdisp_lld_draw_pixel(); + #endif +} + +// Parameters: x,y and x1,y1 +// Alters: x,y x1,y1 cx,cy +static void line_clip(void) { + int16_t dy, dx; + int16_t addx, addy; + int16_t P, diff, i; + + // Is this a horizontal line (or a point) + if (GC->p.y == GC->p.y1) { + hline_clip(); + return; } - static gdisp_lld_msg_t *gdispAllocMsg(gdisp_msgaction_t action) { - gdisp_lld_msg_t *p; + // Is this a vertical line (or a point) + if (GC->p.x == GC->p.x1) { + vline_clip(); + return; + } - while(1) { /* To be sure, to be sure */ + // Not horizontal or vertical - /* Wait for a slot */ - gfxSemWait(&gdispMsgsSem, TIME_INFINITE); + // Use Bresenham's line drawing algorithm. + // This should be replaced with fixed point slope based line drawing + // which is more efficient on modern processors as it branches less. + // When clipping is needed, all the clipping could also be done up front + // instead of on each pixel. - /* Find the slot */ - gfxMutexEnter(&gdispMsgsMutex); - for(p=gdispMsgs; p < &gdispMsgs[GDISP_QUEUE_SIZE]; p++) { - if (p->action == GDISP_LLD_MSG_NOP) { - /* Allocate it */ - p->action = action; - gfxMutexExit(&gdispMsgsMutex); - return p; - } - } - gfxMutexExit(&gdispMsgsMutex); + if (GC->p.x1 >= GC->p.x) { + dx = GC->p.x1 - GC->p.x; + addx = 1; + } else { + dx = GC->p.x - GC->p.x1; + addx = -1; + } + if (GC->p.y1 >= GC->p.y) { + dy = GC->p.y1 - GC->p.y; + addy = 1; + } else { + dy = GC->p.y - GC->p.y1; + addy = -1; + } - /* Oops - none found, try again */ - gfxSemSignal(&gdispMsgsSem); + if (dx >= dy) { + dy <<= 1; + P = dy - dx; + diff = P - dx; + + for(i=0; i<=dx; ++i) { + drawpixel_clip(); + if (P < 0) { + P += dy; + GC->p.x += addx; + } else { + P += diff; + GC->p.x += addx; + GC->p.y += addy; + } + } + } else { + dx <<= 1; + P = dx - dy; + diff = P - dy; + + for(i=0; i<=dy; ++i) { + drawpixel_clip(); + if (P < 0) { + P += dx; + GC->p.y += addy; + } else { + P += diff; + GC->p.x += addx; + GC->p.y += addy; + } } } -#endif +} /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ /* Our module initialiser */ -#if GDISP_NEED_MULTITHREAD - void _gdispInit(void) { - /* Initialise Mutex */ - gfxMutexInit(&gdispMutex); - - /* Initialise driver */ - gfxMutexEnter(&gdispMutex); - gdisp_lld_init(); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ASYNC - void _gdispInit(void) { - unsigned i; - gfxThreadHandle hth; - - /* Mark all the Messages as free */ - for(i=0; i < GDISP_QUEUE_SIZE; i++) - gdispMsgs[i].action = GDISP_LLD_MSG_NOP; - - /* Initialise our Queue, Mutex's and Counting Semaphore. - * A Mutex is required as well as the Queue and Thread because some calls have to be synchronous. - * Synchronous calls get handled by the calling thread, asynchronous by our worker thread. - */ - gfxQueueInit(&gdispQueue); - gfxMutexInit(&gdispMutex); - gfxMutexInit(&gdispMsgsMutex); - gfxSemInit(&gdispMsgsSem, GDISP_QUEUE_SIZE, GDISP_QUEUE_SIZE); - - hth = gfxThreadCreate(waGDISPThread, sizeof(waGDISPThread), NORMAL_PRIORITY, GDISPThreadHandler, NULL); - if (hth) gfxThreadClose(hth); - - /* Initialise driver - synchronous */ - gfxMutexEnter(&gdispMutex); - gdisp_lld_init(); - gfxMutexExit(&gdispMutex); - } -#else - void _gdispInit(void) { - gdisp_lld_init(); - } -#endif +void _gdispInit(void) { + MUTEX_INIT(); + + /* Initialise driver */ + MUTEX_ENTER(); + gdisp_lld_init(); + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + #if GDISP_HARDWARE_CLIP + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + gdisp_lld_set_clip(); + #else + GC->clipx0 = 0; + GC->clipy0 = 0; + GC->clipx1 = GC->g.Width; + GC->clipy1 = GC->g.Height; + #endif + #endif + MUTEX_EXIT(); +} -#if GDISP_NEED_MULTITHREAD - bool_t gdispIsBusy(void) { - return FALSE; - } -#elif GDISP_NEED_ASYNC - bool_t gdispIsBusy(void) { - return !gfxQueueIsEmpty(&gdispQueue); - } -#endif +void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) { + MUTEX_ENTER(); -#if GDISP_NEED_MULTITHREAD - void gdispClear(color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_clear(color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ASYNC - void gdispClear(color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_CLEAR); - p->clear.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); - } -#endif + #if NEED_CLIPPING + // Test if the area is valid - if not then exit + if (x < GC->clipx0 || x+cx >= GC->clipx1 || y < GC->clipy0 || y+cy >= GC->clipy1) { + MUTEX_EXIT(); + return; + } + #endif -#if GDISP_NEED_MULTITHREAD - void gdispDrawPixel(coord_t x, coord_t y, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_draw_pixel(x, y, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ASYNC - void gdispDrawPixel(coord_t x, coord_t y, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWPIXEL); - p->drawpixel.x = x; - p->drawpixel.y = y; - p->drawpixel.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); - } -#endif + GC->flags |= GDISP_FLG_INSTREAM; + + #if GDISP_HARDWARE_STREAM + // Best is hardware streaming + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + gdisp_lld_stream_start(); + #else + // Worst - save the parameters and use pixel drawing + + // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position + GC->p.x1 = GC->p.x = x; + GC->p.y1 = GC->p.y = y; + GC->p.x2 = GC->p.x + GC->p.cx; + GC->p.x2 = GC->p.x + GC->p.cx; + #endif + + // Don't release the mutex as gdispStreamEnd() will do that. +} + +void gdispStreamColor(color_t color) { + // Don't touch the mutex as we should already own it + + // Ignore this call if we are not streaming + if (!(GC->flags & GDISP_FLG_INSTREAM)) + return; + + #if GDISP_HARDWARE_STREAM + // Best is hardware streaming + GC->p.color = color; + gdisp_lld_stream_color(); + #else + // Worst is using pixel drawing + GC->p.color = color; + gdisp_lld_draw_pixel(); + + // Just wrap at end-of-line and end-of-buffer + if (++GC->p.x >= GC->p.x2) { + GC->p.x = GC->p.x1; + if (++GC->p.y >= GC->p.x2) + GC->p.y = GC->p.y1; + } + #endif +} + +void gdispStreamEnd(void) { + // Only release the mutex and end the stream if we are actually streaming. + if (!(GC->flags & GDISP_FLG_INSTREAM)) + return; + + #if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(); + #endif + GC->flags &= ~GDISP_FLG_INSTREAM; + MUTEX_EXIT(); +} + +void gdispDrawPixel(coord_t x, coord_t y, color_t color) { + MUTEX_ENTER(); + GC->p.x = x; + GC->p.y = y; + GC->p.color = color; + drawpixel_clip(); + MUTEX_EXIT(); +} -#if GDISP_NEED_MULTITHREAD - void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_draw_line(x0, y0, x1, y1, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ASYNC - void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWLINE); - p->drawline.x0 = x0; - p->drawline.y0 = y0; - p->drawline.x1 = x1; - p->drawline.y1 = y1; - p->drawline.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); - } -#endif +void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { + MUTEX_ENTER(); + GC->p.x = x0; + GC->p.y = y0; + GC->p.x1 = x1; + GC->p.y1 = y1; + GC->p.color = color; + line_clip(); + MUTEX_EXIT(); +} -#if GDISP_NEED_MULTITHREAD - void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_fill_area(x, y, cx, cy, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ASYNC - void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLAREA); - p->fillarea.x = x; - p->fillarea.y = y; - p->fillarea.cx = cx; - p->fillarea.cy = cy; - p->fillarea.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +void gdispClear(color_t color) { + // Note - clear() ignores the clipping area. It clears the screen. + MUTEX_ENTER(); + + #if GDISP_HARDWARE_CLEARS + // Best is hardware accelerated clear + GC->p.color = color; + gdisp_lld_clear(); + #elif GDISP_HARDWARE_FILLS + // Next best is hardware accelerated area fill + GC->p.x = GC->p.y = 0; + GC->p.cx = GC->g.Width; + GC->p.cy = GC->g.Height; + GC->p.color = color; + gdisp_lld_fill_area(); + #elif GDISP_HARDWARE_STREAM + // Next best is streaming + uint32_t area; + + GC->p.x = GC->p.y = 0; + GC->p.cx = GC->g.Width; + GC->p.cy = GC->g.Height; + GC->p.color = color; + area = (uint32_t)GC->p.cx * GC->p.cy; + + gdisp_lld_stream_start(); + for(; area; area--) + gdisp_lld_stream_color(); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(gc); + #endif + #else + // Worst is drawing pixels + GC->p.color = color; + for(GC->p.y = 0; GC->p.y < GC->g.Height; GC->p.y++) + for(GC->p.x = 0; GC->p.x < GC->g.Width; GC->p.x++) + gdisp_lld_draw_pixel(); + #endif + MUTEX_EXIT(); +} + +void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + MUTEX_ENTER(); + TEST_CLIP_AREA(x,y,cx,cy) { + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + GC->p.color = color; + fillarea(); } -#endif + MUTEX_EXIT(); +} -#if GDISP_NEED_MULTITHREAD - void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_blit_area_ex(x, y, cx, cy, srcx, srcy, srccx, buffer); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ASYNC - void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_BLITAREA); - p->blitarea.x = x; - p->blitarea.y = y; - p->blitarea.cx = cx; - p->blitarea.cy = cy; - p->blitarea.srcx = srcx; - p->blitarea.srcy = srcy; - p->blitarea.srccx = srccx; - p->blitarea.buffer = buffer; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); - } -#endif +void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + MUTEX_ENTER(); + + #if NEED_CLIPPING + // This is a different cliping to fillarea() as it needs to take into account srcx,srcy + if (x < GC->clipx0) { cx -= GC->clipx0 - x; srcx += GC->clipx0 - x; x = GC->clipx0; } + if (y < GC->clipy0) { cy -= GC->clipy0 - y; srcy += GC->clipy0 - x; y = GC->clipy0; } + if (x+cx > GC->clipx1) cx = GC->clipx1 - x; + if (y+cy > GC->clipy1) cy = GC->clipy1 - y; + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0) { MUTEX_EXIT(); return; } + #endif + + #if GDISP_HARDWARE_BITFILLS + // Best is hardware bitfills + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + GC->p.x1 = srcx; + GC->p.y1 = srcy; + GC->p.x2 = srccx; + GC->p.ptr = (void *)buffer; + gdisp_lld_blit_area_ex(); + #elif GDISP_HARDWARE_STREAM + // Next best is hardware streaming + + // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap + buffer += srcy*srccx+srcx; + srcx = x + cx; + srcy = y + cy; + srccx -= cx; + + gdisp_lld_stream_start(gc); + for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { + for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) { + GC->p.color = *buffer++; + gdisp_lld_stream_color(); + } + } + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(gc); + #endif + #else + // Worst is drawing pixels + + // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap + buffer += srcy*srccx+srcx; + srcx = x + cx; + srcy = y + cy; + srccx -= cx; + + for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { + for(GC->p.x=x; GC->p.x < srcx; GC->p.x++) { + GC->p.color = *buffer++; + gdisp_lld_draw_pixel(); + } + } + #endif + MUTEX_EXIT(); +} -#if (GDISP_NEED_CLIP && GDISP_NEED_MULTITHREAD) - void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_set_clip(x, y, cx, cy); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_CLIP && GDISP_NEED_ASYNC +#if GDISP_NEED_CLIP void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_SETCLIP); - p->setclip.x = x; - p->setclip.y = y; - p->setclip.cx = cx; - p->setclip.cy = cy; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + MUTEX_ENTER(); + #if GDISP_HARDWARE_CLIP + // Best is using hardware clipping + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + gdisp_lld_set_clip(); + #else + // Worst is using software clipping + if (x < 0) { cx += x; x = 0; } + if (y < 0) { cy += y; y = 0; } + if (cx <= 0 || cy <= 0 || x >= GC->g.Width || y >= GC->g.Height) { MUTEX_EXIT(); return; } + GC->clipx0 = x; + GC->clipy0 = y; + GC->clipx1 = x+cx; if (GC->clipx1 > GC->g.Width) GC->clipx1 = GC->g.Width; + GC->clipy1 = y+cy; if (GC->clipy1 > GC->g.Height) GC->clipy1 = GC->g.Height; + #endif + MUTEX_EXIT(); } #endif -#if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) +#if GDISP_NEED_CIRCLE void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_draw_circle(x, y, radius, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_CIRCLE && GDISP_NEED_ASYNC - void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWCIRCLE); - p->drawcircle.x = x; - p->drawcircle.y = y; - p->drawcircle.radius = radius; - p->drawcircle.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + coord_t a, b, P; + + MUTEX_ENTER(); + + // Calculate intermediates + a = 1; + b = radius; + P = 4 - radius; + GC->p.color = color; + + // Away we go using Bresenham's circle algorithm + // Optimized to prevent double drawing + GC->p.x = x; GC->p.y = y + b; drawpixel_clip(); + GC->p.x = x; GC->p.y = y - b; drawpixel_clip(); + GC->p.x = x + b; GC->p.y = y; drawpixel_clip(); + GC->p.x = x - b; GC->p.y = y; drawpixel_clip(); + do { + GC->p.x = x + a; GC->p.y = y + b; drawpixel_clip(); + GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); + GC->p.x = x + b; GC->p.y = y + a; drawpixel_clip(); + GC->p.x = x - b; GC->p.y = y + a; drawpixel_clip(); + GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); + GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); + GC->p.x = x + b; GC->p.y = y - a; drawpixel_clip(); + GC->p.x = x - b; GC->p.y = y - a; drawpixel_clip(); + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a < b); + GC->p.x = x + a; GC->p.y = y + b; drawpixel_clip(); + GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); + GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); + GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); + MUTEX_EXIT(); } #endif - -#if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) - void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_fill_circle(x, y, radius, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_CIRCLE && GDISP_NEED_ASYNC + +#if GDISP_NEED_CIRCLE void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLCIRCLE); - p->fillcircle.x = x; - p->fillcircle.y = y; - p->fillcircle.radius = radius; - p->fillcircle.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + coord_t a, b, P; + + MUTEX_ENTER(); + + // Calculate intermediates + a = 1; + b = radius; + P = 4 - radius; + GC->p.color = color; + + // Away we go using Bresenham's circle algorithm + // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value + GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + GC->p.y = y+b; GC->p.x = x; drawpixel_clip(); + GC->p.y = y-b; GC->p.x = x; drawpixel_clip(); + do { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + if (P < 0) { + P += 3 + 2*a++; + } else { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); + P += 5 + 2*(a++ - b--); + } + } while(a < b); + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + MUTEX_EXIT(); } #endif -#if (GDISP_NEED_ELLIPSE && GDISP_NEED_MULTITHREAD) - void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_draw_ellipse(x, y, a, b, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ELLIPSE && GDISP_NEED_ASYNC +#if GDISP_NEED_ELLIPSE void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWELLIPSE); - p->drawellipse.x = x; - p->drawellipse.y = y; - p->drawellipse.a = a; - p->drawellipse.b = b; - p->drawellipse.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + coord_t dx, dy; + int32_t a2, b2; + int32_t err, e2; + + MUTEX_ENTER(); + + // Calculate intermediates + dx = 0; + dy = b; + a2 = a*a; + b2 = b*b; + err = b2-(2*b-1)*a2; + GC->p.color = color; + + // Away we go using Bresenham's ellipse algorithm + do { + GC->p.x = x + dx; GC->p.y = y + dy; drawpixel_clip(); + GC->p.x = x - dx; GC->p.y = y + dy; drawpixel_clip(); + GC->p.x = x - dx; GC->p.y = y - dy; drawpixel_clip(); + GC->p.x = x + dx; GC->p.y = y - dy; drawpixel_clip(); + + e2 = 2*err; + if(e2 < (2*dx+1)*b2) { + dx++; + err += (2*dx+1)*b2; + } + if(e2 > -(2*dy-1)*a2) { + dy--; + err -= (2*dy-1)*a2; + } + } while(dy >= 0); + MUTEX_EXIT(); } #endif -#if (GDISP_NEED_ELLIPSE && GDISP_NEED_MULTITHREAD) - void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_fill_ellipse(x, y, a, b, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ELLIPSE && GDISP_NEED_ASYNC +#if GDISP_NEED_ELLIPSE void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLELLIPSE); - p->fillellipse.x = x; - p->fillellipse.y = y; - p->fillellipse.a = a; - p->fillellipse.b = b; - p->fillellipse.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + coord_t dx, dy; + int32_t a2, b2; + int32_t err, e2; + + MUTEX_ENTER(); + + // Calculate intermediates + dx = 0; + dy = b; + a2 = a*a; + b2 = b*b; + err = b2-(2*b-1)*a2; + GC->p.color = color; + + // Away we go using Bresenham's ellipse algorithm + // This is optimized to prevent overdrawing by drawing a line only when a y is about to change value + do { + e2 = 2*err; + if(e2 < (2*dx+1)*b2) { + dx++; + err += (2*dx+1)*b2; + } + if(e2 > -(2*dy-1)*a2) { + GC->p.y = y + dy; GC->p.x = x - dx; GC->p.x1 = x + dx; hline_clip(); + if (y) { GC->p.y = y - dy; GC->p.x = x - dx; GC->p.x1 = x + dx; hline_clip(); } + dy--; + err -= (2*dy-1)*a2; + } + } while(dy >= 0); + MUTEX_EXIT(); } #endif -#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) - void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_draw_arc(x, y, radius, start, end, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC +#if GDISP_NEED_ARC + #if !GMISC_NEED_FIXEDTRIG && !GMISC_NEED_FASTTRIG + #include + #endif + void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWARC); - p->drawarc.x = x; - p->drawarc.y = y; - p->drawarc.radius = radius; - p->drawarc.start = start; - p->drawarc.end = end; - p->drawarc.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + coord_t a, b, P, sedge, eedge; + uint8_t full, sbit, ebit, tbit; + + // Normalize the angles + if (start < 0) + start -= (start/360-1)*360; + else if (start >= 360) + start %= 360; + if (end < 0) + end -= (end/360-1)*360; + else if (end >= 360) + end %= 360; + + sbit = 1<<(start/45); + ebit = 1<<(end/45); + full = 0; + if (start == end) { + full = 0xFF; + } else if (end < start) { + for(tbit=sbit<<1; tbit; tbit<<=1) full |= tbit; + for(tbit=ebit>>1; tbit; tbit>>=1) full |= tbit; + } else if (sbit < 0x80) { + for(tbit=sbit<<1; tbit < ebit; tbit<<=1) full |= tbit; + } + + MUTEX_ENTER(); + GC->p.color = color; + + if (full) { + // Draw full sectors + // Optimized to prevent double drawing + a = 1; + b = radius; + P = 4 - radius; + if (full & 0x60) { GC->p.y = y+b; GC->p.x = x; drawpixel_clip(); } + if (full & 0x06) { GC->p.y = y-b; GC->p.x = x; drawpixel_clip(); } + if (full & 0x81) { GC->p.y = y; GC->p.x = x+b; drawpixel_clip(); } + if (full & 0x18) { GC->p.y = y; GC->p.x = x-b; drawpixel_clip(); } + do { + if (full & 0x01) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } + if (full & 0x02) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (full & 0x04) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (full & 0x08) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } + if (full & 0x10) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } + if (full & 0x20) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if (full & 0x40) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (full & 0x80) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a < b); + if (full & 0xC0) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (full & 0x0C) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (full & 0x03) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (full & 0x30) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if (full == 0xFF) + return; + } + + #if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG + sedge = NONFIXED(radius * ((sbit & 0x99) ? ffsin(start) : ffcos(start)) + FIXED0_5); + eedge = NONFIXED(radius * ((ebit & 0x99) ? ffsin(end) : ffcos(end)) + FIXED0_5); + #elif GFX_USE_GMISC && GMISC_NEED_FASTTRIG + sedge = round(radius * ((sbit & 0x99) ? fsin(start) : fcos(start))); + eedge = round(radius * ((ebit & 0x99) ? fsin(end) : fcos(end))); + #else + sedge = round(radius * ((sbit & 0x99) ? sin(start*M_PI/180) : cos(start*M_PI/180))); + eedge = round(radius * ((ebit & 0x99) ? sin(end*M_PI/180) : cos(end*M_PI/180))); + #endif + if (sbit & 0xB4) sedge = -sedge; + if (ebit & 0xB4) eedge = -eedge; + + if (sbit != ebit) { + // Draw start and end sectors + // Optimized to prevent double drawing + a = 1; + b = radius; + P = 4 - radius; + if ((sbit & 0x20) || (ebit & 0x40)) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } + if ((sbit & 0x02) || (ebit & 0x04)) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } + if ((sbit & 0x80) || (ebit & 0x01)) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } + if ((sbit & 0x08) || (ebit & 0x10)) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + do { + if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } + if (((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } + if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } + if (((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a < b); + if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge) || ((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) + { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge) || ((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) + { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge) || ((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) + { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge) || ((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) + { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + } else if (end < start) { + // Draw start/end sector where it is a non-internal angle + // Optimized to prevent double drawing + a = 1; + b = radius; + P = 4 - radius; + if (sbit & 0x60) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } + if (sbit & 0x06) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } + if (sbit & 0x81) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } + if (sbit & 0x18) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + do { + if ((sbit & 0x01) && (a >= sedge || a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } + if ((sbit & 0x02) && (a <= sedge || a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if ((sbit & 0x04) && (a >= sedge || a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if ((sbit & 0x08) && (a <= sedge || a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } + if ((sbit & 0x10) && (a >= sedge || a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } + if ((sbit & 0x20) && (a <= sedge || a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if ((sbit & 0x40) && (a >= sedge || a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if ((sbit & 0x80) && (a <= sedge || a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a < b); + if (((sbit & 0x04) && (a >= sedge || a <= eedge)) || ((sbit & 0x08) && (a <= sedge || a >= eedge))) + { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x40) && (a >= sedge || a <= eedge)) || ((sbit & 0x80) && (a <= sedge || a >= eedge))) + { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x01) && (a >= sedge || a <= eedge)) || ((sbit & 0x02) && (a <= sedge || a >= eedge))) + { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x10) && (a >= sedge || a <= eedge)) || ((sbit & 0x20) && (a <= sedge || a >= eedge))) + { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + } else { + // Draw start/end sector where it is a internal angle + // Optimized to prevent double drawing + a = 1; + b = radius; + P = 4 - radius; + if (((sbit & 0x20) && !eedge) || ((sbit & 0x40) && !sedge)) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x02) && !eedge) || ((sbit & 0x04) && !sedge)) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x80) && !eedge) || ((sbit & 0x01) && !sedge)) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } + if (((sbit & 0x08) && !eedge) || ((sbit & 0x10) && !sedge)) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + do { + if (((sbit & 0x01) && a >= sedge && a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } + if (((sbit & 0x02) && a <= sedge && a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x04) && a >= sedge && a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x08) && a <= sedge && a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } + if (((sbit & 0x10) && a >= sedge && a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } + if (((sbit & 0x20) && a <= sedge && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x40) && a >= sedge && a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x80) && a <= sedge && a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a < b); + if (((sbit & 0x04) && a >= sedge && a <= eedge) || ((sbit & 0x08) && a <= sedge && a >= eedge)) + { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x40) && a >= sedge && a <= eedge) || ((sbit & 0x80) && a <= sedge && a >= eedge)) + { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + if (((sbit & 0x01) && a >= sedge && a <= eedge) || ((sbit & 0x02) && a <= sedge && a >= eedge)) + { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + if (((sbit & 0x10) && a >= sedge && a <= eedge) || ((sbit & 0x20) && a <= sedge && a >= eedge)) + { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + } + MUTEX_EXIT(); } #endif -#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) - void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_fill_arc(x, y, radius, start, end, color); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC +#if GDISP_NEED_ARC void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLARC); - p->fillarc.x = x; - p->fillarc.y = y; - p->fillarc.radius = radius; - p->fillarc.start = start; - p->fillarc.end = end; - p->fillarc.color = color; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + coord_t a, b, P; + coord_t sy, ey; + fixed sxa, sxb, sxd, exa, exb, exd; + uint8_t qtr; + + MUTEX_ENTER(); + + // Do the trig to get the formulas for the start and end lines. + sxa = exa = FIXED(x)+FIXED0_5; + #if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG + sxb = radius*ffcos(start); sy = -NONFIXED(radius*ffsin(start) + FIXED0_5); + exb = radius*ffcos(end); ey = -NONFIXED(radius*ffsin(end) + FIXED0_5); + #elif GFX_USE_GMISC && GMISC_NEED_FASTTRIG + sxb = FP2FIXED(radius*fcos(start)); sy = -round(radius*fsin(start)); + exb = FP2FIXED(radius*fcos(end)); ey = -round(radius*fsin(end)); + #else + sxb = FP2FIXED(radius*cos(start*M_PI/180)); sy = -round(radius*sin(start*M_PI/180)); + exb = FP2FIXED(radius*cos(end*M_PI/180)); ey = -round(radius*sin(end*M_PI/180)); + #endif + sxd = sy ? sxb/sy : sxb; + exd = ey ? exb/ey : exb; + + // Calculate which quarters and which direction we are traveling + qtr = 0; + if (sxb > 0) qtr |= 0x01; // S1=0001(1), S2=0000(0), S3=0010(2), S4=0011(3) + if (sy > 0) qtr |= 0x02; + if (exb > 0) qtr |= 0x04; // E1=0100(4), E2=0000(0), E3=1000(8), E4=1100(12) + if (ey > 0) qtr |= 0x08; + if (sy > ey) qtr |= 0x10; // order of start and end lines + + // Calculate intermediates + a = 1; + b = radius; + P = 4 - radius; + GC->p.color = color; + sxb += sxa; + exb += exa; + + // Away we go using Bresenham's circle algorithm + // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value + + switch(qtr) { + case 0: // S2E2 sy <= ey + case 1: // S1E2 sy <= ey + if (ey && sy) { + GC->p.x = x; GC->p.x1 = x; // E2S + sxa -= sxd; exa -= exd; + } else if (sy) { + GC->p.x = x-b; GC->p.x1 = x; // C2S + sxa -= sxd; + } else if (ey) { + GC->p.x = x; GC->p.x1 = x+b; // E2C + exa -= exd; + } else { + GC->p.x = x-b; GC->p.x1 = x+b; // C2C + } + GC->p.y = y; + hline_clip(); + do { + if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + sxa -= sxd; exa -= exd; + } else if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + sxa -= sxd; + } else if (qtr & 1) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + if (-b >= ey) { + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = NONFIXED(sxb); hline_clip(); // E2S + sxb += sxd; exb += exd; + } else if (-b >= sy) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + sxb += sxd; + } else if (qtr & 1) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + } else if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + } else if (qtr & 1) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + break; + + case 2: // S3E2 sy <= ey + case 3: // S4E2 sy <= ey + case 6: // S3E1 sy <= ey + case 7: // S4E1 sy <= ey + case 18: // S3E2 sy > ey + case 19: // S4E2 sy > ey + case 22: // S3E1 sy > ey + case 23: // S4E1 sy > ey + GC->p.y = y; GC->p.x = x; GC->p.x1 = x+b; hline_clip(); // SE2C + sxa += sxd; exa -= exd; + do { + if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + exa -= exd; + } else if (!(qtr & 4)) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + sxa += sxd; + } else if (!(qtr & 1)) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + if (-b >= ey) { + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + exb += exd; + } else if (!(qtr & 4)) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + if (b <= sy) { + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + sxb -= sxd; + } else if (!(qtr & 1)) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + } else if (!(qtr & 4)) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+a; hline_clip(); // S2C + } else if (!(qtr & 1)) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+a; hline_clip(); // C2C + } + break; + + case 4: // S2E1 sy <= ey + case 5: // S1E1 sy <= ey + GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + do { + if (-a >= ey) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + sxa -= sxd; exa -= exd; + } else if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + sxa -= sxd; + } else if (qtr & 1) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + if (P < 0) { + P += 3 + 2*a++; + } else { + if (-b >= ey) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + sxb += sxd; exb += exd; + } else if (-b >= sy) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + sxb += sxd; + } else if (qtr & 1) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (-a >= ey) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + } else if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + } else if (qtr & 1) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + break; + + case 8: // S2E3 sy <= ey + case 9: // S1E3 sy <= ey + case 12: // S2E4 sy <= ey + case 13: // S1E4 sy <= ey + case 24: // S2E3 sy > ey + case 25: // S1E3 sy > ey + case 28: // S2E3 sy > ey + case 29: // S1E3 sy > ey + GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x; hline_clip(); // C2SE + sxa -= sxd; exa += exd; + do { + if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + sxa -= sxd; + } else if (qtr & 1) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + exa += exd; + } else if (qtr & 4) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + if (-b >= sy) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + sxb += sxd; + } else if (qtr & 1) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + if (b <= ey) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + exb -= exd; + } else if (qtr & 4) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + } else if (qtr & 1) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + } else if (qtr & 4) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+a; hline_clip(); // C2C + } + break; + + case 10: // S3E3 sy <= ey + case 14: // S3E4 sy <= ey + GC->p.y = y; GC->p.x = x; drawpixel_clip(); // S2E + sxa += sxd; exa += exd; + do { + if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + sxa += sxd; exa += exd; + } else if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + exa += exd; + } else if (qtr & 4) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + if (b <= sy) { + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = NONFIXED(exb); hline_clip(); // S2E + sxb -= sxd; exb -= exd; + } else if (b <= ey) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + exb -= exd; + } else if (qtr & 4) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + } else if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + } else if (qtr & 4) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + break; + + case 11: // S4E3 sy <= ey + case 15: // S4E4 sy <= ey + GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + do { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + if (a <= sy) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + sxa += sxd; exa += exd; + } else if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + exa += exd; + } else if (qtr & 4) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + if (b <= sy) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + sxb -= sxd; exb -= exd; + } else if (b <= ey) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + exb -= exd; + } else if (qtr & 4) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + if (a <= sy) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + } else if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + } else if (qtr & 4) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + break; + + case 16: // S2E2 sy > ey + case 20: // S2E1 sy > ey + GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + sxa -= sxd; exa -= exd; + do { + if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + sxa -= sxd; exa -= exd; + } else if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + exa -= exd; + } else if (!(qtr & 4)){ + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + if (P < 0) { + P += 3 + 2*a++; + } else { + if (-b >= sy) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + sxb += sxd; exb += exd; + } else if (-b >= ey) { + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + exb += exd; + } else if (!(qtr & 4)){ + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (-a >= sy) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + } else if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + } else if (!(qtr & 4)){ + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + break; + + case 17: // S1E2 sy > ey + case 21: // S1E1 sy > ey + if (sy) { + GC->p.x = x; GC->p.x1 = x; // E2S + sxa -= sxd; exa -= exd; + } else { + GC->p.x = x; GC->p.x1 = x+b; // E2C + exa -= exd; + } + GC->p.y = y; + hline_clip(); + do { + if (-a >= sy) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + sxa -= sxd; exa -= exd; + } else if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + exa -= exd; + } else if (!(qtr & 4)) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + if (-b >= sy) { + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = NONFIXED(sxb); hline_clip(); // E2S + sxb += sxd; exb += exd; + } else if (-b >= ey) { + GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + exb += exd; + } else if (!(qtr & 4)) { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (-a >= sy) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + } else if (-a >= ey) { + GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + } else if (!(qtr & 4)) { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + break; + + case 26: // S3E3 sy > ey + case 27: // S4E3 sy > ey + GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + do { + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + sxa += sxd; exa += exd; + } else if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + sxa += sxd; + } else if (!(qtr & 1)) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + if (b <= ey) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + sxb -= sxd; exb -= exd; + } else if (b <= sy) { + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + sxb -= sxd; + } else if (!(qtr & 1)) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + if (a <= ey) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + } else if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + } else if (!(qtr & 4)) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + break; + + case 30: // S3E4 sy > ey + case 31: // S4E4 sy > ey + do { + if (a <= ey) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + sxa += sxd; exa += exd; + } else if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + sxa += sxd; + } else if (!(qtr & 1)) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + if (P < 0) { + P += 3 + 2*a++; + } else { + if (b <= ey) { + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = NONFIXED(exb); hline_clip(); // S2E + sxb -= sxd; exb -= exd; + } else if (b <= sy) { + GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + sxb -= sxd; + } else if (!(qtr & 1)) { + GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + } + P += 5 + 2*(a++ - b--); + } + } while(a < b); + if (a <= ey) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + } else if (a <= sy) { + GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + } else if (!(qtr & 4)) { + GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + } + break; + } + + MUTEX_EXIT(); } + #endif #if GDISP_NEED_ARC -void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { - if (2*radius > cx || 2*radius > cy) { - gdispDrawBox(x, y, cx, cy, color); - return; + void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { + if (2*radius > cx || 2*radius > cy) { + gdispDrawBox(x, y, cx, cy, color); + return; + } + gdispDrawArc(x+radius, y+radius, radius, 90, 180, color); + gdispDrawLine(x+radius+1, y, x+cx-2-radius, y, color); + gdispDrawArc(x+cx-1-radius, y+radius, radius, 0, 90, color); + gdispDrawLine(x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color); + gdispDrawArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); + gdispDrawLine(x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color); + gdispDrawArc(x+radius, y+cy-1-radius, radius, 180, 270, color); + gdispDrawLine(x, y+radius+1, x, y+cy-2-radius, color); } - gdispDrawArc(x+radius, y+radius, radius, 90, 180, color); - gdispDrawLine(x+radius+1, y, x+cx-2-radius, y, color); - gdispDrawArc(x+cx-1-radius, y+radius, radius, 0, 90, color); - gdispDrawLine(x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color); - gdispDrawArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); - gdispDrawLine(x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color); - gdispDrawArc(x+radius, y+cy-1-radius, radius, 180, 270, color); - gdispDrawLine(x, y+radius+1, x, y+cy-2-radius, color); -} #endif #if GDISP_NEED_ARC -void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { - coord_t radius2; + void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { + coord_t radius2; - radius2 = radius*2; - if (radius2 > cx || radius2 > cy) { - gdispFillArea(x, y, cx, cy, color); - return; + radius2 = radius*2; + if (radius2 > cx || radius2 > cy) { + gdispFillArea(x, y, cx, cy, color); + return; + } + gdispFillArc(x+radius, y+radius, radius, 90, 180, color); + gdispFillArea(x+radius+1, y, cx-radius2, radius, color); + gdispFillArc(x+cx-1-radius, y+radius, radius, 0, 90, color); + gdispFillArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); + gdispFillArea(x+radius+1, y+cy-radius, cx-radius2, radius, color); + gdispFillArc(x+radius, y+cy-1-radius, radius, 180, 270, color); + gdispFillArea(x, y+radius, cx, cy-radius2, color); } - gdispFillArc(x+radius, y+radius, radius, 90, 180, color); - gdispFillArea(x+radius+1, y, cx-radius2, radius, color); - gdispFillArc(x+cx-1-radius, y+radius, radius, 0, 90, color); - gdispFillArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); - gdispFillArea(x+radius+1, y+cy-radius, cx-radius2, radius, color); - gdispFillArc(x+radius, y+cy-1-radius, radius, 180, 270, color); - gdispFillArea(x, y+radius, cx, cy-radius2, color); -} #endif -#if (GDISP_NEED_PIXELREAD && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC)) +#if GDISP_NEED_PIXELREAD color_t gdispGetPixelColor(coord_t x, coord_t y) { color_t c; /* Always synchronous as it must return a value */ - gfxMutexEnter(&gdispMutex); - c = gdisp_lld_get_pixel_color(x, y); - gfxMutexExit(&gdispMutex); + MUTEX_ENTER(); + GC->p.x = x; + GC->p.y = y; + c = gdisp_lld_get_pixel_color(); + MUTEX_EXIT(); return c; } #endif -#if (GDISP_NEED_SCROLL && GDISP_NEED_MULTITHREAD) - void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_vertical_scroll(x, y, cx, cy, lines, bgcolor); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_SCROLL && GDISP_NEED_ASYNC +#if GDISP_NEED_SCROLL void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_VERTICALSCROLL); - p->verticalscroll.x = x; - p->verticalscroll.y = y; - p->verticalscroll.cx = cx; - p->verticalscroll.cy = cy; - p->verticalscroll.lines = lines; - p->verticalscroll.bgcolor = bgcolor; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + MUTEX_ENTER(); + #if NEED_CLIPPING + if (x < GC->clipx0) { cx -= GC->clipx0 - x; x = GC->clipx0; } + if (y < GC->clipy0) { cy -= GC->clipy0 - y; y = GC->clipy0; } + if (cx <= 0 || cy <= 0 || x >= GC->clipx1 || y >= GC->clipy1) { MUTEX_EXIT(); return; } + if (x+cx > GC->clipx1) cx = GC->clipx1 - x; + if (y+cy > GC->clipy1) cy = GC->clipy1 - y; + #endif + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + GC->p.y1 = lines; + GC->p.color = bgcolor; + gdisp_lld_vertical_scroll(); + MUTEX_EXIT(); } #endif -#if (GDISP_NEED_CONTROL && GDISP_NEED_MULTITHREAD) - void gdispControl(unsigned what, void *value) { - gfxMutexEnter(&gdispMutex); - gdisp_lld_control(what, value); - gfxMutexExit(&gdispMutex); - } -#elif GDISP_NEED_CONTROL && GDISP_NEED_ASYNC - void gdispControl(unsigned what, void *value) { - gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_CONTROL); - p->control.what = what; - p->control.value = value; - gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); - } +#if GDISP_NEED_CONTROL + #if GDISP_HARDWARE_CONTROL + void gdispControl(unsigned what, void *value) { + MUTEX_ENTER(); + GC->p.x = what; + GC->p.ptr = value; + gdisp_lld_control(); + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + if (what == GDISP_CONTROL_ORIENTATION) { + #if GDISP_HARDWARE_CLIP + // Best is hardware clipping + GC->p.x = 0; + GC->p.y = 0; + GC->p.cx = GC->g.Width; + GC->p.cy = GC->g.Height; + gdisp_lld_set_clip(); + #else + // Worst is software clipping + GC->clipx0 = 0; + GC->clipy0 = 0; + GC->clipx1 = GC->g.Width; + GC->clipy1 = GC->g.Height; + #endif + } + #endif + MUTEX_EXIT(); + } + #else + void gdispControl(unsigned what, void *value) { + (void)what; + (void)value; + /* Ignore everything */ + } + #endif #endif -#if (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC) && GDISP_NEED_QUERY - void *gdispQuery(unsigned what) { - void *res; +#if GDISP_NEED_QUERY + #if GDISP_HARDWARE_QUERY + void *gdispQuery(unsigned what) { + void *res; - gfxMutexEnter(&gdispMutex); - res = gdisp_lld_query(what); - gfxMutexExit(&gdispMutex); - return res; - } + MUTEX_ENTER(); + GC->p.x = (coord_t)what; + res = gdisp_lld_query(); + MUTEX_EXIT(); + return res; + } + #else + void *gdispQuery(unsigned what) { + (void) what; + return (void *)-1; + } + #endif #endif /*===========================================================================*/ @@ -458,29 +1546,30 @@ void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t r /*===========================================================================*/ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - /* No mutex required as we only call high level functions which have their own mutex */ - coord_t x1, y1; - - x1 = x+cx-1; - y1 = y+cy-1; - - if (cx > 2) { - if (cy >= 1) { - gdispDrawLine(x, y, x1, y, color); - if (cy >= 2) { - gdispDrawLine(x, y1, x1, y1, color); - if (cy > 2) { - gdispDrawLine(x, y+1, x, y1-1, color); - gdispDrawLine(x1, y+1, x1, y1-1, color); - } + if (cx <= 0 || cy <= 0) return; + cx = x+cx-1; cy = y+cy-1; // cx, cy are now the end point. + + MUTEX_ENTER(); + + GC->p.color = color; + + if (cx - x > 2) { + GC->p.x = x; GC->p.y = y; GC->p.x1 = cx; hline_clip(); + if (y != cy) { + GC->p.x = x; GC->p.y = cy; GC->p.x1 = cx; hline_clip(); + if (cy - y > 2) { + y++; cy--; + GC->p.x = x; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); } } - } else if (cx == 2) { - gdispDrawLine(x, y, x, y1, color); - gdispDrawLine(x1, y, x1, y1, color); - } else if (cx == 1) { - gdispDrawLine(x, y, x, y1, color); + } else { + GC->p.x = x; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + if (x != cx) { + GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + } } + MUTEX_EXIT(); } #if GDISP_NEED_CONVEX_POLYGON @@ -488,9 +1577,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { const point *epnt, *p; epnt = &pntarray[cnt-1]; - for(p = pntarray; p < epnt; p++) - gdispDrawLine(tx+p->x, ty+p->y, tx+p[1].x, ty+p[1].y, color); - gdispDrawLine(tx+p->x, ty+p->y, tx+pntarray->x, ty+pntarray->y, color); + + MUTEX_ENTER(); + GC->p.color = color; + for(p = pntarray; p < epnt; p++) { + GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+p[1].x; GC->p.y1=ty+p[1].y; line_clip(); + } + GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+pntarray->x; GC->p.y1=ty+pntarray->y; line_clip(); + MUTEX_EXIT(); } void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { @@ -510,21 +1604,21 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { y = rpnt->y; /* Work out the slopes of the two attached line segs */ - lpnt = rpnt <= pntarray ? epnts : rpnt-1; - while (lpnt->y == y) { + for (lpnt = rpnt <= pntarray ? epnts : rpnt-1; lpnt->y == y; cnt--) { + if (!cnt) return; lx = FIXED(lpnt->x); lpnt = lpnt <= pntarray ? epnts : lpnt-1; - if (!cnt--) return; } - rpnt = rpnt >= epnts ? pntarray : rpnt+1; - while (rpnt->y == y) { - rx = rpnt->x<<16; + for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { + if (!cnt) return; + rx = FIXED(rpnt->x); rpnt = rpnt >= epnts ? pntarray : rpnt+1; - if (!cnt--) return; } lk = (FIXED(lpnt->x) - lx) / (lpnt->y - y); rk = (FIXED(rpnt->x) - rx) / (rpnt->y - y); + MUTEX_ENTER(); + GC->p.color = color; while(1) { /* Determine our boundary */ ymax = rpnt->y < lpnt->y ? rpnt->y : lpnt->y; @@ -539,38 +1633,40 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { * of pixels. */ if (lxc < rxc) { - if (rxc - lxc == 1) - gdispDrawPixel(tx+lxc, ty+y, color); - else - gdispDrawLine(tx+lxc, ty+y, tx+rxc-1, ty+y, color); + GC->p.x=tx+lxc; GC->p.y=ty+y; GC->p.x1=tx+rxc-1; hline_clip(); } else if (lxc > rxc) { - if (lxc - rxc == 1) - gdispDrawPixel(tx+rxc, ty+y, color); - else - gdispDrawLine(tx+rxc, ty+y, tx+lxc-1, ty+y, color); + GC->p.x=tx+rxc; GC->p.y=ty+y; GC->p.x1=tx+lxc-1; hline_clip(); } lx += lk; rx += rk; } - if (!cnt--) return; + if (!cnt) { + MUTEX_EXIT(); + return; + } + cnt--; /* Replace the appropriate point */ if (ymax == lpnt->y) { - lpnt = lpnt <= pntarray ? epnts : lpnt-1; - while (lpnt->y == y) { + for (lpnt = lpnt <= pntarray ? epnts : lpnt-1; lpnt->y == y; cnt--) { + if (!cnt) { + MUTEX_EXIT(); + return; + } lx = FIXED(lpnt->x); lpnt = lpnt <= pntarray ? epnts : lpnt-1; - if (!cnt--) return; } lk = (FIXED(lpnt->x) - lx) / (lpnt->y - y); } else { - rpnt = rpnt >= epnts ? pntarray : rpnt+1; - while (rpnt->y == y) { + for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { + if (!cnt) { + MUTEX_EXIT(); + return; + } rx = FIXED(rpnt->x); rpnt = rpnt >= epnts ? pntarray : rpnt+1; - if (!cnt--) return; } rk = (FIXED(rpnt->x) - rx) / (rpnt->y - y); } @@ -582,146 +1678,130 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { #include "mcufont.h" #if GDISP_NEED_ANTIALIAS && GDISP_NEED_PIXELREAD - static void text_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { + static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { + if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return; if (alpha == 255) { - if (count == 1) - gdispDrawPixel(x, y, ((color_t *)state)[0]); - else - gdispFillArea(x, y, count, 1, ((color_t *)state)[0]); + GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; GC->p.color = GC->t.color; + hline_clip(); } else { - while (count--) { - gdispDrawPixel(x, y, gdispBlendColor(((color_t *)state)[0], gdispGetPixelColor(x, y), alpha)); - x++; + for (; count; count--, x++) { + GC->p.x = x; GC->p.y = y; + GC->p.color = gdispBlendColor(GC->t.color, gdisp_lld_get_pixel_color(), alpha); + drawpixel_clip(); } } } #else - static void text_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { + static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { + (void) state; + if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return; if (alpha > 0x80) { // A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased - if (count == 1) - gdispDrawPixel(x, y, ((color_t *)state)[0]); - else - gdispFillArea(x, y, count, 1, ((color_t *)state)[0]); + GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; GC->p.color = GC->t.color; + hline_clip(); } } #endif - void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { - /* No mutex required as we only call high level functions which have their own mutex */ - mf_render_character(font, x, y, c, text_draw_char_callback, &color); - } - #if GDISP_NEED_ANTIALIAS - static void text_fill_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { + static void fillcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { + (void) state; + if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return; if (alpha == 255) { - if (count == 1) - gdispDrawPixel(x, y, ((color_t *)state)[0]); - else - gdispFillArea(x, y, count, 1, ((color_t *)state)[0]); + GC->p.color = GC->t.color; } else { - while (count--) { - gdispDrawPixel(x, y, gdispBlendColor(((color_t *)state)[0], ((color_t *)state)[1], alpha)); - x++; - } + GC->p.color = gdispBlendColor(GC->t.color, GC->t.bgcolor, alpha); } + GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; + hline_clip(); } #else - #define text_fill_char_callback text_draw_char_callback + #define fillcharline drawcharline #endif - void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { - /* No mutex required as we only call high level functions which have their own mutex */ - color_t state[2]; - - state[0] = color; - state[1] = bgcolor; - - gdispFillArea(x, y, mf_character_width(font, c) + font->baseline_x, font->height, bgcolor); - mf_render_character(font, x, y, c, text_fill_char_callback, state); + /* Callback to render characters. */ + static uint8_t drawcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { + (void) state; + return mf_render_character(GC->t.font, x, y, ch, drawcharline, 0); } - typedef struct - { - font_t font; - color_t color; - coord_t x, y; - coord_t cx, cy; - } gdispDrawString_state_t; - /* Callback to render characters. */ - static uint8_t gdispDrawString_callback(int16_t x, int16_t y, mf_char character, void *state) - { - gdispDrawString_state_t *s = state; - uint8_t w; - - w = mf_character_width(s->font, character); - if (x >= s->x && x+w < s->x + s->cx && y >= s->y && y+s->font->height <= s->y + s->cy) - mf_render_character(s->font, x, y, character, text_draw_char_callback, &s->color); - return w; + static uint8_t fillcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { + (void) state; + return mf_render_character(GC->t.font, x, y, ch, fillcharline, 0); } - void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color) { - /* No mutex required as we only call high level functions which have their own mutex */ - gdispDrawString_state_t state; - - state.font = font; - state.color = color; - state.x = x; - state.y = y; - state.cx = GDISP.Width - x; - state.cy = GDISP.Height - y; - - x += font->baseline_x; - mf_render_aligned(font, x, y, MF_ALIGN_LEFT, str, 0, gdispDrawString_callback, &state); - } - - typedef struct - { - font_t font; - color_t color[2]; - coord_t x, y; - coord_t cx, cy; - } gdispFillString_state_t; + void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { + MUTEX_ENTER(); + GC->t.font = font; + GC->t.clipx0 = x; + GC->t.clipy0 = y; + GC->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x; + GC->t.clipy1 = y + font->height; + GC->t.color = color; + mf_render_character(font, x, y, c, drawcharline, 0); + MUTEX_EXIT(); + } - /* Callback to render characters. */ - static uint8_t gdispFillString_callback(int16_t x, int16_t y, mf_char character, void *state) - { - gdispFillString_state_t *s = state; - uint8_t w; + void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { + MUTEX_ENTER(); + GC->p.cx = mf_character_width(font, c) + font->baseline_x; + GC->p.cy = font->height; + GC->t.font = font; + GC->t.clipx0 = GC->p.x = x; + GC->t.clipy0 = GC->p.y = y; + GC->t.clipx1 = GC->p.x+GC->p.cx; + GC->t.clipy1 = GC->p.y+GC->p.cy; + GC->t.color = color; + GC->t.bgcolor = GC->p.color = bgcolor; + + TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { + fillarea(); + mf_render_character(font, x, y, c, fillcharline, 0); + } + MUTEX_EXIT(); + } - w = mf_character_width(s->font, character); - if (x >= s->x && x+w < s->x + s->cx && y >= s->y && y+s->font->height <= s->y + s->cy) - mf_render_character(s->font, x, y, character, text_fill_char_callback, s->color); - return w; + void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color) { + MUTEX_ENTER(); + GC->t.font = font; + GC->t.clipx0 = x; + GC->t.clipy0 = y; + GC->t.clipx1 = x + mf_get_string_width(font, str, 0, 0); + GC->t.clipy1 = y + font->height; + GC->t.color = color; + + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, 0); + MUTEX_EXIT(); } void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { - /* No mutex required as we only call high level functions which have their own mutex */ - gdispFillString_state_t state; - - state.font = font; - state.color[0] = color; - state.color[1] = bgcolor; - state.x = x; - state.y = y; - state.cx = mf_get_string_width(font, str, 0, 0); - state.cy = font->height; - - gdispFillArea(x, y, state.cx, state.cy, bgcolor); - mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, gdispFillString_callback, &state); + MUTEX_ENTER(); + GC->p.cx = mf_get_string_width(font, str, 0, 0); + GC->p.cy = font->height; + GC->t.font = font; + GC->t.clipx0 = GC->p.x = x; + GC->t.clipy0 = GC->p.y = y; + GC->t.clipx1 = GC->p.x+GC->p.cx; + GC->t.clipy1 = GC->p.y+GC->p.cy; + GC->t.color = color; + GC->t.bgcolor = GC->p.color = bgcolor; + + TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { + fillarea(); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, 0); + } + MUTEX_EXIT(); } void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { - /* No mutex required as we only call high level functions which have their own mutex */ - gdispDrawString_state_t state; - - state.font = font; - state.color = color; - state.x = x; - state.y = y; - state.cx = cx; - state.cy = cy; - + MUTEX_ENTER(); + GC->t.font = font; + GC->t.clipx0 = x; + GC->t.clipy0 = y; + GC->t.clipx1 = x+cx; + GC->t.clipy1 = y+cy; + GC->t.color = color; + /* Select the anchor position */ switch(justify) { case justifyCenter: @@ -736,39 +1816,45 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } y += (cy+1 - font->height)/2; - mf_render_aligned(font, x, y, justify, str, 0, gdispDrawString_callback, &state); + mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, 0); + MUTEX_EXIT(); } void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { - /* No mutex required as we only call high level functions which have their own mutex */ - gdispFillString_state_t state; - - state.font = font; - state.color[0] = color; - state.color[1] = bgcolor; - state.x = x; - state.y = y; - state.cx = cx; - state.cy = cy; - - gdispFillArea(x, y, cx, cy, bgcolor); - - /* Select the anchor position */ - switch(justify) { - case justifyCenter: - x += (cx + 1) / 2; - break; - case justifyRight: - x += cx; - break; - default: // justifyLeft - x += font->baseline_x; - break; + MUTEX_ENTER(); + GC->p.cx = cx; + GC->p.cy = cy; + GC->t.font = font; + GC->t.clipx0 = GC->p.x = x; + GC->t.clipy0 = GC->p.y = y; + GC->t.clipx1 = x+cx; + GC->t.clipy1 = y+cy; + GC->t.color = color; + GC->t.bgcolor = GC->p.color = bgcolor; + + TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { + + // background fill + fillarea(); + + /* Select the anchor position */ + switch(justify) { + case justifyCenter: + x += (cx + 1) / 2; + break; + case justifyRight: + x += cx; + break; + default: // justifyLeft + x += font->baseline_x; + break; + } + y += (cy+1 - font->height)/2; + + /* Render */ + mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, 0); } - y += (cy+1 - font->height)/2; - - /* Render */ - mf_render_aligned(font, x, y, justify, str, 0, gdispFillString_callback, &state); + MUTEX_EXIT(); } coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) { @@ -831,5 +1917,6 @@ color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha) } #endif + #endif /* GFX_USE_GDISP */ /** @} */ -- cgit v1.2.3 From 01a6d6ff95d72e6e9107d8c3e386c2bd2ce5c28d Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 18 Sep 2013 23:36:35 +1000 Subject: Fix some compiler warnings --- src/gdisp/mcufont/mf_kerning.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gdisp') diff --git a/src/gdisp/mcufont/mf_kerning.c b/src/gdisp/mcufont/mf_kerning.c index 4118b78e..0ef35363 100644 --- a/src/gdisp/mcufont/mf_kerning.c +++ b/src/gdisp/mcufont/mf_kerning.c @@ -25,6 +25,7 @@ static void fit_leftedge(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { struct kerning_state_s *s = state; + (void)count; if (alpha > 7) { @@ -64,7 +65,7 @@ static bool do_kerning(mf_char c) return true; } -static int16_t min16(int16_t a, int16_t b) { return (a < b) ? a : b; } +//static int16_t min16(int16_t a, int16_t b) { return (a < b) ? a : b; } static int16_t max16(int16_t a, int16_t b) { return (a > b) ? a : b; } static int16_t avg16(int16_t a, int16_t b) { return (a + b) / 2; } -- cgit v1.2.3 From b25ac5e667d98f2915831a74707f6ec198a4498b Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 18 Sep 2013 23:46:37 +1000 Subject: Scrolling emulation when not supported by hardware Start of new multiple display support GDISP performance optimisations Documentation updates Win32 driver updates --- src/gdisp/gdisp.c | 461 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 326 insertions(+), 135 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 1aecd26c..25c2621d 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -50,7 +50,7 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #if GDISP_HARDWARE_STREAM_END #define STREAM_CLEAR() if ((GC->flags & GDISP_FLG_INSTREAM)) { \ - gdisp_lld_stream_end(); \ + gdisp_lld_stream_end(GC); \ GC->flags &= ~GDISP_FLG_INSTREAM; \ } #else @@ -71,10 +71,10 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #if NEED_CLIPPING static INLINE void drawpixel_clip(void) { if (GC->p.x >= GC->clipx0 && GC->p.x < GC->clipx1 && GC->p.y >= GC->clipy0 && GC->p.y < GC->clipy1) - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); } #else - #define drawpixel_clip() gdisp_lld_draw_pixel() + #define drawpixel_clip() gdisp_lld_draw_pixel(GC) #endif #else // Worst is streaming @@ -85,10 +85,10 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #endif GC->cx = GC->cy = 1; - gdisp_lld_stream_start(); - gdisp_lld_stream_color(); + gdisp_lld_stream_start(GC); + gdisp_lld_stream_color(GC); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(); + gdisp_lld_stream_end(GC); #endif } #endif @@ -99,7 +99,7 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; // Note: This is not clipped #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - #define fillarea() gdisp_lld_fill_area() + #define fillarea() gdisp_lld_fill_area(GC) #elif GDISP_HARDWARE_STREAM // Next best is hardware streaming static INLINE void fillarea(void) { @@ -107,11 +107,11 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; area = (uint32_t)GC->p.cx * GC->p.cy; - gdisp_lld_stream_start(); + gdisp_lld_stream_start(GC); for(; area; area--) - gdisp_lld_stream_color(); + gdisp_lld_stream_color(GC); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(gc); + gdisp_lld_stream_end(GC); #endif } #else @@ -125,7 +125,7 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; y1 = GC->p.y + GC->p.cy; for(; GC->p.y < y1; GC->p.y++, GC->p.x = x0) for(; GC->p.x < x1; GC->p.x++) - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); GC->p.y = y0; } #endif @@ -164,14 +164,14 @@ static void hline_clip(void) { if (GC->p.x == GC->p.x1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); #else // Worst is streaming GC->p.cx = GC->p.cy = 1; - gdisp_lld_stream_start(); - gdisp_lld_stream_color(); + gdisp_lld_stream_start(GC); + gdisp_lld_stream_color(GC); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(); + gdisp_lld_stream_end(GC); #endif #endif return; @@ -182,19 +182,19 @@ static void hline_clip(void) { // Best is hardware accelerated area fill GC->p.cx = GC->p.x1 - GC->p.x + 1; GC->p.cy = 1; - gdisp_lld_fill_area(); + gdisp_lld_fill_area(GC); #elif GDISP_HARDWARE_STREAM // Next best is streaming GC->p.cx = GC->p.x1 - GC->p.x; - gdisp_lld_stream_start(); - do { gdisp_lld_stream_color(); } while(GC->p.cx--); + gdisp_lld_stream_start(GC); + do { gdisp_lld_stream_color(GC); } while(GC->p.cx--); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(); + gdisp_lld_stream_end(GC); #endif #else // Worst is drawing pixels for(; GC->p.x <= GC->p.x1; GC->p.x++) - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); #endif } @@ -221,14 +221,14 @@ static void vline_clip(void) { if (GC->p.y == GC->p.y1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); #else // Worst is streaming GC->p.cx = GC->p.cy = 1; - gdisp_lld_stream_start(); - gdisp_lld_stream_color(); + gdisp_lld_stream_start(GC); + gdisp_lld_stream_color(GC); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(); + gdisp_lld_stream_end(GC); #endif #endif return; @@ -239,19 +239,19 @@ static void vline_clip(void) { // Best is hardware accelerated area fill GC->p.cy = GC->p.y1 - GC->p.y + 1; GC->p.cx = 1; - gdisp_lld_fill_area(); + gdisp_lld_fill_area(GC); #elif GDISP_HARDWARE_STREAM // Next best is streaming GC->p.cy = GC->p.y1 - GC->p.y; - gdisp_lld_stream_start(); - do { gdisp_lld_stream_color(); } while(GC->p.cy--); + gdisp_lld_stream_start(GC); + do { gdisp_lld_stream_color(GC); } while(GC->p.cy--); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(); + gdisp_lld_stream_end(GC); #endif #else // Worst is drawing pixels for(; GC->p.y <= GC->p.y1; GC->p.y++) - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); #endif } @@ -342,14 +342,15 @@ void _gdispInit(void) { /* Initialise driver */ MUTEX_ENTER(); - gdisp_lld_init(); + GC->flags = 0; + gdisp_lld_init(GC); #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP #if GDISP_HARDWARE_CLIP GC->p.x = x; GC->p.y = y; GC->p.cx = cx; GC->p.cy = cy; - gdisp_lld_set_clip(); + gdisp_lld_set_clip(GC); #else GC->clipx0 = 0; GC->clipy0 = 0; @@ -360,75 +361,140 @@ void _gdispInit(void) { MUTEX_EXIT(); } -void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) { - MUTEX_ENTER(); +#if GDISP_NEED_STREAMING + void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) { + MUTEX_ENTER(); - #if NEED_CLIPPING - // Test if the area is valid - if not then exit - if (x < GC->clipx0 || x+cx >= GC->clipx1 || y < GC->clipy0 || y+cy >= GC->clipy1) { - MUTEX_EXIT(); - return; - } - #endif + #if NEED_CLIPPING + // Test if the area is valid - if not then exit + if (x < GC->clipx0 || x+cx >= GC->clipx1 || y < GC->clipy0 || y+cy >= GC->clipy1) { + MUTEX_EXIT(); + return; + } + #endif - GC->flags |= GDISP_FLG_INSTREAM; + GC->flags |= GDISP_FLG_INSTREAM; - #if GDISP_HARDWARE_STREAM - // Best is hardware streaming - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_stream_start(); - #else - // Worst - save the parameters and use pixel drawing + #if GDISP_HARDWARE_STREAM + // Best is hardware streaming + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + gdisp_lld_stream_start(GC); + #else + // Worst - save the parameters and use pixel drawing + + // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position, cx = bufpos + GC->p.x1 = GC->p.x = x; + GC->p.y1 = GC->p.y = y; + GC->p.x2 = x + cx; + GC->p.y2 = y + cy; + GC->p.cx = 0; + #endif - // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position - GC->p.x1 = GC->p.x = x; - GC->p.y1 = GC->p.y = y; - GC->p.x2 = GC->p.x + GC->p.cx; - GC->p.x2 = GC->p.x + GC->p.cx; - #endif + // Don't release the mutex as gdispStreamEnd() will do that. + } - // Don't release the mutex as gdispStreamEnd() will do that. -} + void gdispStreamColor(color_t color) { + #if !GDISP_HARDWARE_STREAM && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS + coord_t pos, sx1, sy1, sx2; + #endif -void gdispStreamColor(color_t color) { - // Don't touch the mutex as we should already own it + // Don't touch the mutex as we should already own it - // Ignore this call if we are not streaming - if (!(GC->flags & GDISP_FLG_INSTREAM)) - return; + // Ignore this call if we are not streaming + if (!(GC->flags & GDISP_FLG_INSTREAM)) + return; - #if GDISP_HARDWARE_STREAM - // Best is hardware streaming - GC->p.color = color; - gdisp_lld_stream_color(); - #else - // Worst is using pixel drawing - GC->p.color = color; - gdisp_lld_draw_pixel(); + #if GDISP_HARDWARE_STREAM + // Best is hardware streaming + GC->p.color = color; + gdisp_lld_stream_color(GC); + #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS + GC->linebuf[GC->p.cx++] = color; + if (GC->p.cx >= GDISP_LINEBUF_SIZE) { + pos = GC->p.cx; + sx1 = GC->p.x1; + sy1 = GC->p.y1; + sx2 = GC->p.x2; + GC->p.x -= pos; + GC->p.cx = pos; + GC->p.cy = 1; + GC->p.x1 = 0; + GC->p.y1 = 0; + GC->p.x2 = pos; + GC->p.ptr = (void *)GC->linebuf; + gdisp_lld_blit_area(GC); + GC->p.x1 = sx1; + GC->p.y1 = sy1; + GC->p.x2 = sx2; + GC->p.x += pos; + GC->p.cx = 0; + } - // Just wrap at end-of-line and end-of-buffer - if (++GC->p.x >= GC->p.x2) { - GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.x2) - GC->p.y = GC->p.y1; - } - #endif -} + // Just wrap at end-of-line and end-of-buffer + if (++GC->p.x >= GC->p.x2) { + if (GC->p.cx) { + pos = GC->p.cx; + sx1 = GC->p.x1; + sy1 = GC->p.y1; + sx2 = GC->p.x2; + GC->p.x -= pos; + GC->p.cx = pos; + GC->p.cy = 1; + GC->p.x1 = 0; + GC->p.y1 = 0; + GC->p.x2 = pos; + GC->p.ptr = (void *)GC->linebuf; + gdisp_lld_blit_area(GC); + GC->p.x1 = sx1; + GC->p.y1 = sy1; + GC->p.x2 = sx2; + GC->p.cx = 0; + } + GC->p.x = GC->p.x1; + if (++GC->p.y >= GC->p.x2) + GC->p.y = GC->p.y1; + } + #else + // Worst is using pixel drawing + GC->p.color = color; + gdisp_lld_draw_pixel(GC); + + // Just wrap at end-of-line and end-of-buffer + if (++GC->p.x >= GC->p.x2) { + GC->p.x = GC->p.x1; + if (++GC->p.y >= GC->p.x2) + GC->p.y = GC->p.y1; + } + #endif + } -void gdispStreamEnd(void) { - // Only release the mutex and end the stream if we are actually streaming. - if (!(GC->flags & GDISP_FLG_INSTREAM)) - return; + void gdispStreamEnd(void) { + // Only release the mutex and end the stream if we are actually streaming. + if (!(GC->flags & GDISP_FLG_INSTREAM)) + return; - #if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(); - #endif - GC->flags &= ~GDISP_FLG_INSTREAM; - MUTEX_EXIT(); -} + #if GDISP_HARDWARE_STREAM + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(GC); + #endif + #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS + if (GC->p.cx) { + GC->p.x -= GC->p.cx; + GC->p.cy = 1; + GC->p.x1 = 0; + GC->p.y1 = 0; + GC->p.x2 = GC->p.cx; + GC->p.ptr = (void *)GC->linebuf; + gdisp_lld_blit_area(GC); + } + #endif + GC->flags &= ~GDISP_FLG_INSTREAM; + MUTEX_EXIT(); + } +#endif void gdispDrawPixel(coord_t x, coord_t y, color_t color) { MUTEX_ENTER(); @@ -457,14 +523,14 @@ void gdispClear(color_t color) { #if GDISP_HARDWARE_CLEARS // Best is hardware accelerated clear GC->p.color = color; - gdisp_lld_clear(); + gdisp_lld_clear(GC); #elif GDISP_HARDWARE_FILLS // Next best is hardware accelerated area fill GC->p.x = GC->p.y = 0; GC->p.cx = GC->g.Width; GC->p.cy = GC->g.Height; GC->p.color = color; - gdisp_lld_fill_area(); + gdisp_lld_fill_area(GC); #elif GDISP_HARDWARE_STREAM // Next best is streaming uint32_t area; @@ -475,18 +541,18 @@ void gdispClear(color_t color) { GC->p.color = color; area = (uint32_t)GC->p.cx * GC->p.cy; - gdisp_lld_stream_start(); + gdisp_lld_stream_start(GC); for(; area; area--) - gdisp_lld_stream_color(); + gdisp_lld_stream_color(GC); #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(gc); + gdisp_lld_stream_end(GC); #endif #else // Worst is drawing pixels GC->p.color = color; for(GC->p.y = 0; GC->p.y < GC->g.Height; GC->p.y++) for(GC->p.x = 0; GC->p.x < GC->g.Width; GC->p.x++) - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); #endif MUTEX_EXIT(); } @@ -527,7 +593,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.y1 = srcy; GC->p.x2 = srccx; GC->p.ptr = (void *)buffer; - gdisp_lld_blit_area_ex(); + gdisp_lld_blit_area(GC); #elif GDISP_HARDWARE_STREAM // Next best is hardware streaming @@ -537,15 +603,15 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - gdisp_lld_stream_start(gc); + gdisp_lld_stream_start(GC); for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) { GC->p.color = *buffer++; - gdisp_lld_stream_color(); + gdisp_lld_stream_color(GC); } } #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(gc); + gdisp_lld_stream_end(GC); #endif #else // Worst is drawing pixels @@ -559,7 +625,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { for(GC->p.x=x; GC->p.x < srcx; GC->p.x++) { GC->p.color = *buffer++; - gdisp_lld_draw_pixel(); + gdisp_lld_draw_pixel(GC); } } #endif @@ -575,7 +641,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.y = y; GC->p.cx = cx; GC->p.cy = cy; - gdisp_lld_set_clip(); + gdisp_lld_set_clip(GC); #else // Worst is using software clipping if (x < 0) { cx += x; x = 0; } @@ -1456,9 +1522,26 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, /* Always synchronous as it must return a value */ MUTEX_ENTER(); - GC->p.x = x; - GC->p.y = y; - c = gdisp_lld_get_pixel_color(); + #if GDISP_HARDWARE_PIXELREAD + // Best is direct pixel read + GC->p.x = x; + GC->p.y = y; + c = gdisp_lld_get_pixel_color(GC); + #elif GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ + // Next best is hardware streaming + GC->p.x = x; + GC->p.y = y; + GC->p.cx = 1; + GC->p.cy = 1; + gdisp_lld_stream_start(GC); + c = gdisp_lld_stream_read(GC); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(GC); + #endif + #else + // Worst is "not possible" + #error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display" + #endif MUTEX_EXIT(); return c; @@ -1467,21 +1550,127 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #if GDISP_NEED_SCROLL void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { + coord_t abslines; + #if !GDISP_HARDWARE_SCROLL + coord_t fy, dy, ix, fx, i, j; + #endif + MUTEX_ENTER(); #if NEED_CLIPPING if (x < GC->clipx0) { cx -= GC->clipx0 - x; x = GC->clipx0; } if (y < GC->clipy0) { cy -= GC->clipy0 - y; y = GC->clipy0; } - if (cx <= 0 || cy <= 0 || x >= GC->clipx1 || y >= GC->clipy1) { MUTEX_EXIT(); return; } + if (!lines || cx <= 0 || cy <= 0 || x >= GC->clipx1 || y >= GC->clipy1) { MUTEX_EXIT(); return; } if (x+cx > GC->clipx1) cx = GC->clipx1 - x; if (y+cy > GC->clipy1) cy = GC->clipy1 - y; #endif + + abslines = lines < 0 ? -lines : lines; + if (abslines >= cy) { + abslines = cy; + cy = 0; + } else { + #if GDISP_HARDWARE_SCROLL + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; + GC->p.y1 = lines; + GC->p.color = bgcolor; + gdisp_lld_vertical_scroll(GC); + cy -= abslines; + #elif GDISP_LINEBUF_SIZE == 0 + #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support and GDISP_LINEBUF_SIZE is zero." + #else + cy -= abslines; + if (lines < 0) { + fy = y+cx-1; + dy = -1; + } else { + fy = y; + dy = 1; + } + // Move the screen - one line at a time + for(i = 0; i < cy; i++, fy += dy) { + + // Handle where the buffer is smaller than a line + for(ix=0; ix < cx; ix += GDISP_LINEBUF_SIZE) { + + // Calculate the data we can move in one operation + fx = cx - ix; + if (fx > GDISP_LINEBUF_SIZE) + fx = GDISP_LINEBUF_SIZE; + + // Read one line of data from the screen + #if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ + // Best is hardware streaming + GC->p.x = x+ix; + GC->p.y = fy+lines; + GC->p.cx = fx; + GC->p.cy = 1; + gdisp_lld_stream_start(GC); + for(j=0; j < fx; j++) + GC->linebuf[j] = gdisp_lld_stream_read(GC); + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(GC); + #endif + #elif GDISP_HARDWARE_PIXELREAD + // Next best is single pixel reads + for(j=0; j < fx; j++) { + GC->p.x = x+ix+j; + GC->p.y = fy+lines; + GC->linebuf[j] = gdisp_lld_get_pixel_color(GC); + } + #else + // Worst is "not possible" + #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support for scrolling or reading pixels." + #endif + + // Write that line to the new location + #if GDISP_HARDWARE_BITFILLS + // Best is hardware bitfills + GC->p.x = x+ix; + GC->p.y = fy; + GC->p.cx = fx; + GC->p.cy = 1; + GC->p.x1 = 0; + GC->p.y1 = 0; + GC->p.x2 = fx; + GC->p.ptr = (void *)GC->linebuf; + gdisp_lld_blit_area(GC); + #elif GDISP_HARDWARE_STREAM + // Next best is hardware streaming + GC->p.x = x+ix; + GC->p.y = fy; + GC->p.cx = fx; + GC->p.cy = 1; + gdisp_lld_stream_start(GC); + for(j = 0; j < fx; j++) { + GC->p.color = GC->linebuf[j]; + gdisp_lld_stream_color(GC); + } + #if GDISP_HARDWARE_STREAM_END + gdisp_lld_stream_end(GC); + #endif + #else + // Worst is drawing pixels + GC->p.y = fy; + for(GC->p.x = x+ix, j = 0; j < fx; GC->p.x++, j++) { + GC->p.color = GC->linebuf[j]; + gdisp_lld_draw_pixel(GC); + } + #endif + } + } + #endif + } + + /* fill the remaining gap */ GC->p.x = x; - GC->p.y = y; + GC->p.y = lines > 0 ? (y+cy) : y; GC->p.cx = cx; - GC->p.cy = cy; - GC->p.y1 = lines; + GC->p.cy = abslines; GC->p.color = bgcolor; - gdisp_lld_vertical_scroll(); + fillarea(); MUTEX_EXIT(); } #endif @@ -1492,7 +1681,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, MUTEX_ENTER(); GC->p.x = what; GC->p.ptr = value; - gdisp_lld_control(); + gdisp_lld_control(GC); #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION if (what == GDISP_CONTROL_ORIENTATION) { #if GDISP_HARDWARE_CLIP @@ -1501,7 +1690,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.y = 0; GC->p.cx = GC->g.Width; GC->p.cy = GC->g.Height; - gdisp_lld_set_clip(); + gdisp_lld_set_clip(GC); #else // Worst is software clipping GC->clipx0 = 0; @@ -1529,7 +1718,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, MUTEX_ENTER(); GC->p.x = (coord_t)what; - res = gdisp_lld_query(); + res = gdisp_lld_query(GC); MUTEX_EXIT(); return res; } @@ -1677,42 +1866,46 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { #if GDISP_NEED_TEXT #include "mcufont.h" - #if GDISP_NEED_ANTIALIAS && GDISP_NEED_PIXELREAD + #if GDISP_NEED_ANTIALIAS && GDISP_HARDWARE_PIXELREAD static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return; + #define GD ((GDISPDriver *)state) + if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { - GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; GC->p.color = GC->t.color; + GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; hline_clip(); } else { for (; count; count--, x++) { - GC->p.x = x; GC->p.y = y; - GC->p.color = gdispBlendColor(GC->t.color, gdisp_lld_get_pixel_color(), alpha); + GD->p.x = x; GD->p.y = y; + GD->p.color = gdispBlendColor(GD->t.color, gdisp_lld_get_pixel_color(GD), alpha); drawpixel_clip(); } } + #undef GD } #else static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - (void) state; - if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return; + #define GD ((GDISPDriver *)state) + if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha > 0x80) { // A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased - GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; GC->p.color = GC->t.color; + GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; hline_clip(); } + #undef GD } #endif #if GDISP_NEED_ANTIALIAS static void fillcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - (void) state; - if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return; + #define GD ((GDISPDriver *)state) + if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { - GC->p.color = GC->t.color; + GD->p.color = GD->t.color; } else { - GC->p.color = gdispBlendColor(GC->t.color, GC->t.bgcolor, alpha); + GD->p.color = gdispBlendColor(GD->t.color, GD->t.bgcolor, alpha); } - GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; + GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; hline_clip(); + #undef GD } #else #define fillcharline drawcharline @@ -1720,14 +1913,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { /* Callback to render characters. */ static uint8_t drawcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { - (void) state; - return mf_render_character(GC->t.font, x, y, ch, drawcharline, 0); + return mf_render_character(GC->t.font, x, y, ch, drawcharline, state); } /* Callback to render characters. */ static uint8_t fillcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { - (void) state; - return mf_render_character(GC->t.font, x, y, ch, fillcharline, 0); + return mf_render_character(GC->t.font, x, y, ch, fillcharline, state); } void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { @@ -1738,7 +1929,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GC->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x; GC->t.clipy1 = y + font->height; GC->t.color = color; - mf_render_character(font, x, y, c, drawcharline, 0); + mf_render_character(font, x, y, c, drawcharline, GC); MUTEX_EXIT(); } @@ -1756,7 +1947,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { fillarea(); - mf_render_character(font, x, y, c, fillcharline, 0); + mf_render_character(font, x, y, c, fillcharline, GC); } MUTEX_EXIT(); } @@ -1770,7 +1961,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GC->t.clipy1 = y + font->height; GC->t.color = color; - mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, 0); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, GC); MUTEX_EXIT(); } @@ -1788,7 +1979,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { fillarea(); - mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, 0); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, GC); } MUTEX_EXIT(); } @@ -1816,7 +2007,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } y += (cy+1 - font->height)/2; - mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, 0); + mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, GC); MUTEX_EXIT(); } @@ -1852,7 +2043,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { y += (cy+1 - font->height)/2; /* Render */ - mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, 0); + mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, GC); } MUTEX_EXIT(); } -- cgit v1.2.3 From 973e34089e33f06cfd9ed560db968870e22c2b8a Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 24 Sep 2013 16:10:15 +1000 Subject: GDISP streaming bug fixes Win32 bitmap support Win32 Rotation is back to front. Need to check touch and other drivers. --- src/gdisp/gdisp.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 25c2621d..8ec2c998 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -367,7 +367,7 @@ void _gdispInit(void) { #if NEED_CLIPPING // Test if the area is valid - if not then exit - if (x < GC->clipx0 || x+cx >= GC->clipx1 || y < GC->clipy0 || y+cy >= GC->clipy1) { + if (x < GC->clipx0 || x+cx > GC->clipx1 || y < GC->clipy0 || y+cy > GC->clipy1) { MUTEX_EXIT(); return; } @@ -398,7 +398,7 @@ void _gdispInit(void) { void gdispStreamColor(color_t color) { #if !GDISP_HARDWARE_STREAM && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - coord_t pos, sx1, sy1, sx2; + coord_t sx1, sy1, sx2; #endif // Don't touch the mutex as we should already own it @@ -413,48 +413,45 @@ void _gdispInit(void) { gdisp_lld_stream_color(GC); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS GC->linebuf[GC->p.cx++] = color; + GC->p.x++; if (GC->p.cx >= GDISP_LINEBUF_SIZE) { - pos = GC->p.cx; sx1 = GC->p.x1; sy1 = GC->p.y1; - sx2 = GC->p.x2; - GC->p.x -= pos; - GC->p.cx = pos; + //sx2 = GC->p.x2; + GC->p.x -= GC->p.cx; GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; - GC->p.x2 = pos; + //GC->p.x2 = GC->p.cx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); GC->p.x1 = sx1; GC->p.y1 = sy1; - GC->p.x2 = sx2; - GC->p.x += pos; + //GC->p.x2 = sx2; + GC->p.x += GC->p.cx; GC->p.cx = 0; } // Just wrap at end-of-line and end-of-buffer - if (++GC->p.x >= GC->p.x2) { + if (GC->p.x >= GC->p.x2) { if (GC->p.cx) { - pos = GC->p.cx; sx1 = GC->p.x1; sy1 = GC->p.y1; - sx2 = GC->p.x2; - GC->p.x -= pos; - GC->p.cx = pos; + //sx2 = GC->p.x2; + GC->p.x -= GC->p.cx; GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; - GC->p.x2 = pos; + //GC->p.x2 = GC->p.cx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); GC->p.x1 = sx1; GC->p.y1 = sy1; - GC->p.x2 = sx2; + //GC->p.x2 = sx2; GC->p.cx = 0; } GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.x2) + if (++GC->p.y >= GC->p.y2) GC->p.y = GC->p.y1; } #else @@ -465,13 +462,13 @@ void _gdispInit(void) { // Just wrap at end-of-line and end-of-buffer if (++GC->p.x >= GC->p.x2) { GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.x2) + if (++GC->p.y >= GC->p.y2) GC->p.y = GC->p.y1; } #endif } - void gdispStreamEnd(void) { + void gdispStreamStop(void) { // Only release the mutex and end the stream if we are actually streaming. if (!(GC->flags & GDISP_FLG_INSTREAM)) return; @@ -486,7 +483,7 @@ void _gdispInit(void) { GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; - GC->p.x2 = GC->p.cx; + //GC->p.x2 = GC->p.cx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); } -- cgit v1.2.3 From 30154560b6f588c42032bce94152676c3756124e Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 25 Sep 2013 17:17:05 +1000 Subject: Rename a macro and fix some bugs --- src/gdisp/gdisp.c | 65 +++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 35 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 8ec2c998..2e423764 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -48,9 +48,9 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #define MUTEX_EXIT() #endif -#if GDISP_HARDWARE_STREAM_END +#if GDISP_HARDWARE_STREAM_STOP #define STREAM_CLEAR() if ((GC->flags & GDISP_FLG_INSTREAM)) { \ - gdisp_lld_stream_end(GC); \ + gdisp_lld_stream_stop(GC); \ GC->flags &= ~GDISP_FLG_INSTREAM; \ } #else @@ -84,11 +84,11 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; return; #endif - GC->cx = GC->cy = 1; + GC->p.cx = GC->p.cy = 1; gdisp_lld_stream_start(GC); gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif } #endif @@ -110,8 +110,8 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; gdisp_lld_stream_start(GC); for(; area; area--) gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif } #else @@ -170,8 +170,8 @@ static void hline_clip(void) { GC->p.cx = GC->p.cy = 1; gdisp_lld_stream_start(GC); gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #endif return; @@ -186,10 +186,11 @@ static void hline_clip(void) { #elif GDISP_HARDWARE_STREAM // Next best is streaming GC->p.cx = GC->p.x1 - GC->p.x; + GC->p.cy = 1; gdisp_lld_stream_start(GC); do { gdisp_lld_stream_color(GC); } while(GC->p.cx--); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #else // Worst is drawing pixels @@ -227,8 +228,8 @@ static void vline_clip(void) { GC->p.cx = GC->p.cy = 1; gdisp_lld_stream_start(GC); gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #endif return; @@ -243,10 +244,11 @@ static void vline_clip(void) { #elif GDISP_HARDWARE_STREAM // Next best is streaming GC->p.cy = GC->p.y1 - GC->p.y; + GC->p.cx = 1; gdisp_lld_stream_start(GC); do { gdisp_lld_stream_color(GC); } while(GC->p.cy--); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #else // Worst is drawing pixels @@ -398,7 +400,7 @@ void _gdispInit(void) { void gdispStreamColor(color_t color) { #if !GDISP_HARDWARE_STREAM && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - coord_t sx1, sy1, sx2; + coord_t sx1, sy1; #endif // Don't touch the mutex as we should already own it @@ -417,17 +419,14 @@ void _gdispInit(void) { if (GC->p.cx >= GDISP_LINEBUF_SIZE) { sx1 = GC->p.x1; sy1 = GC->p.y1; - //sx2 = GC->p.x2; GC->p.x -= GC->p.cx; GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; - //GC->p.x2 = GC->p.cx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); GC->p.x1 = sx1; GC->p.y1 = sy1; - //GC->p.x2 = sx2; GC->p.x += GC->p.cx; GC->p.cx = 0; } @@ -437,17 +436,14 @@ void _gdispInit(void) { if (GC->p.cx) { sx1 = GC->p.x1; sy1 = GC->p.y1; - //sx2 = GC->p.x2; GC->p.x -= GC->p.cx; GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; - //GC->p.x2 = GC->p.cx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); GC->p.x1 = sx1; GC->p.y1 = sy1; - //GC->p.x2 = sx2; GC->p.cx = 0; } GC->p.x = GC->p.x1; @@ -474,8 +470,8 @@ void _gdispInit(void) { return; #if GDISP_HARDWARE_STREAM - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS if (GC->p.cx) { @@ -483,7 +479,6 @@ void _gdispInit(void) { GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; - //GC->p.x2 = GC->p.cx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); } @@ -541,8 +536,8 @@ void gdispClear(color_t color) { gdisp_lld_stream_start(GC); for(; area; area--) gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #else // Worst is drawing pixels @@ -607,8 +602,8 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, gdisp_lld_stream_color(GC); } } - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #else // Worst is drawing pixels @@ -1532,8 +1527,8 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.cy = 1; gdisp_lld_stream_start(GC); c = gdisp_lld_stream_read(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #else // Worst is "not possible" @@ -1607,8 +1602,8 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, gdisp_lld_stream_start(GC); for(j=0; j < fx; j++) GC->linebuf[j] = gdisp_lld_stream_read(GC); - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #elif GDISP_HARDWARE_PIXELREAD // Next best is single pixel reads @@ -1645,8 +1640,8 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.color = GC->linebuf[j]; gdisp_lld_stream_color(GC); } - #if GDISP_HARDWARE_STREAM_END - gdisp_lld_stream_end(GC); + #if GDISP_HARDWARE_STREAM_STOP + gdisp_lld_stream_stop(GC); #endif #else // Worst is drawing pixels -- cgit v1.2.3 From 9c55df546763b9fd4912d3fbb36af1e2990969ba Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 27 Sep 2013 01:35:29 +1000 Subject: Fix compiler warning in image code --- src/gdisp/image.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/gdisp') diff --git a/src/gdisp/image.c b/src/gdisp/image.c index 89f42ee1..1e9ac3d6 100644 --- a/src/gdisp/image.c +++ b/src/gdisp/image.c @@ -16,6 +16,8 @@ #if GFX_USE_GDISP && GDISP_NEED_IMAGE +#include + /* The structure defining the routines for image drawing */ typedef struct gdispImageHandlers { gdispImageError (*open)(gdispImage *img); /* The open function */ -- cgit v1.2.3 From 548eb3c981772ec4be1211352867f2edcdc24423 Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 27 Sep 2013 01:37:32 +1000 Subject: GDISP Streaming bug fixes and new optimisation method --- src/gdisp/gdisp.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 11 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 2e423764..828e5aa9 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -185,7 +185,7 @@ static void hline_clip(void) { gdisp_lld_fill_area(GC); #elif GDISP_HARDWARE_STREAM // Next best is streaming - GC->p.cx = GC->p.x1 - GC->p.x; + GC->p.cx = GC->p.x1 - GC->p.x + 1; GC->p.cy = 1; gdisp_lld_stream_start(GC); do { gdisp_lld_stream_color(GC); } while(GC->p.cx--); @@ -243,7 +243,7 @@ static void vline_clip(void) { gdisp_lld_fill_area(GC); #elif GDISP_HARDWARE_STREAM // Next best is streaming - GC->p.cy = GC->p.y1 - GC->p.y; + GC->p.cy = GC->p.y1 - GC->p.y + 1; GC->p.cx = 1; gdisp_lld_stream_start(GC); do { gdisp_lld_stream_color(GC); } while(GC->p.cy--); @@ -392,7 +392,10 @@ void _gdispInit(void) { GC->p.y1 = GC->p.y = y; GC->p.x2 = x + cx; GC->p.y2 = y + cy; - GC->p.cx = 0; + #if (GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS) || GDISP_HARDWARE_FILLS + GC->p.cx = 0; + GC->p.cy = 1; + #endif #endif // Don't release the mutex as gdispStreamEnd() will do that. @@ -415,12 +418,9 @@ void _gdispInit(void) { gdisp_lld_stream_color(GC); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS GC->linebuf[GC->p.cx++] = color; - GC->p.x++; if (GC->p.cx >= GDISP_LINEBUF_SIZE) { sx1 = GC->p.x1; sy1 = GC->p.y1; - GC->p.x -= GC->p.cx; - GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; GC->p.ptr = (void *)GC->linebuf; @@ -432,12 +432,10 @@ void _gdispInit(void) { } // Just wrap at end-of-line and end-of-buffer - if (GC->p.x >= GC->p.x2) { + if (GC->p.x+GC->p.cx >= GC->p.x2) { if (GC->p.cx) { sx1 = GC->p.x1; sy1 = GC->p.y1; - GC->p.x -= GC->p.cx; - GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; GC->p.ptr = (void *)GC->linebuf; @@ -450,6 +448,33 @@ void _gdispInit(void) { if (++GC->p.y >= GC->p.y2) GC->p.y = GC->p.y1; } + #elif GDISP_HARDWARE_FILLS + // Only slightly better than drawing pixels is to look for runs and use fill area + if (!GC->p.cx || GC->p.color == color) { + GC->p.cx++; + GC->p.color = color; + } else { + if (GC->p.cx == 1) + gdisp_lld_draw_pixel(GC); + else + gdisp_lld_fill_area(GC); + GC->p.x += GC->p.cx; + GC->p.color = color; + GC->p.cx = 1; + } + // Just wrap at end-of-line and end-of-buffer + if (GC->p.x+GC->p.cx >= GC->p.x2) { + if (GC->p.cx) { + if (GC->p.cx == 1) + gdisp_lld_draw_pixel(GC); + else + gdisp_lld_fill_area(GC); + GC->p.cx = 0; + } + GC->p.x = GC->p.x1; + if (++GC->p.y >= GC->p.y2) + GC->p.y = GC->p.y1; + } #else // Worst is using pixel drawing GC->p.color = color; @@ -475,13 +500,18 @@ void _gdispInit(void) { #endif #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS if (GC->p.cx) { - GC->p.x -= GC->p.cx; - GC->p.cy = 1; GC->p.x1 = 0; GC->p.y1 = 0; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); } + #elif GDISP_HARDWARE_FILLS + if (GC->p.cx) { + if (GC->p.cx == 1) + gdisp_lld_draw_pixel(GC); + else + gdisp_lld_fill_area(GC); + } #endif GC->flags &= ~GDISP_FLG_INSTREAM; MUTEX_EXIT(); @@ -595,6 +625,10 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; + GC->p.x = x; + GC->p.y = y; + GC->p.cx = cx; + GC->p.cy = cy; gdisp_lld_stream_start(GC); for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) { @@ -605,6 +639,31 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #if GDISP_HARDWARE_STREAM_STOP gdisp_lld_stream_stop(GC); #endif + #elif GDISP_HARDWARE_FILLS + // Only slightly better than drawing pixels is to look for runs and use fill area + + // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap + buffer += srcy*srccx+srcx; + srcx = x + cx; + srcy = y + cy; + srccx -= cx; + + GC->p.cy = 1; + for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { + for(GC->p.x=x; GC->p.x < srcx; GC->p.x += GC->p.cx) { + GC->p.cx=1; + GC->p.color = *buffer++; + while(GC->p.x+GC->p.cx < srcx && *buffer == GC->p.color) { + GC->p.cx++; + buffer++; + } + if (GC->p.cx == 1) { + gdisp_lld_draw_pixel(GC); + } else { + gdisp_lld_fill_area(GC); + } + } + } #else // Worst is drawing pixels -- cgit v1.2.3 From 6499da5be310f8f3ef8f2d11dfcfb662499c8c17 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 30 Sep 2013 00:05:07 +1000 Subject: SSD1289 streaming driver (untested) X streaming driver (untested) Nokia6610 fixes Read pixel streaming support for low level driver. --- src/gdisp/gdisp.c | 139 +++++++++++++++++++++--------------------------------- 1 file changed, 53 insertions(+), 86 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 828e5aa9..a135462d 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -19,8 +19,8 @@ /* Include the low level driver information */ #include "gdisp/lld/gdisp_lld.h" -#if !GDISP_HARDWARE_STREAM && !GDISP_HARDWARE_DRAWPIXEL - #error "GDISP Driver: Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be defined" +#if !GDISP_HARDWARE_STREAM_WRITE && !GDISP_HARDWARE_DRAWPIXEL + #error "GDISP Driver: Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be defined" #endif #if 1 @@ -48,15 +48,6 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #define MUTEX_EXIT() #endif -#if GDISP_HARDWARE_STREAM_STOP - #define STREAM_CLEAR() if ((GC->flags & GDISP_FLG_INSTREAM)) { \ - gdisp_lld_stream_stop(GC); \ - GC->flags &= ~GDISP_FLG_INSTREAM; \ - } -#else - #define STREAM_CLEAR() GC->flags &= ~GDISP_FLG_INSTREAM -#endif - #define NEED_CLIPPING (!GDISP_HARDWARE_CLIP && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) /*==========================================================================*/ @@ -85,11 +76,9 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #endif GC->p.cx = GC->p.cy = 1; - gdisp_lld_stream_start(GC); - gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_start(GC); + gdisp_lld_write_color(GC); + gdisp_lld_write_stop(GC); } #endif @@ -100,19 +89,17 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill #define fillarea() gdisp_lld_fill_area(GC) -#elif GDISP_HARDWARE_STREAM +#elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming static INLINE void fillarea(void) { uint32_t area; area = (uint32_t)GC->p.cx * GC->p.cy; - gdisp_lld_stream_start(GC); + gdisp_lld_write_start(GC); for(; area; area--) - gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_color(GC); + gdisp_lld_write_stop(GC); } #else // Worst is drawing pixels @@ -159,7 +146,7 @@ static void hline_clip(void) { // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming - #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM) + #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) // Is this a point if (GC->p.x == GC->p.x1) { #if GDISP_HARDWARE_DRAWPIXEL @@ -168,11 +155,9 @@ static void hline_clip(void) { #else // Worst is streaming GC->p.cx = GC->p.cy = 1; - gdisp_lld_stream_start(GC); - gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_start(GC); + gdisp_lld_write_color(GC); + gdisp_lld_write_stop(GC); #endif return; } @@ -183,15 +168,13 @@ static void hline_clip(void) { GC->p.cx = GC->p.x1 - GC->p.x + 1; GC->p.cy = 1; gdisp_lld_fill_area(GC); - #elif GDISP_HARDWARE_STREAM + #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming GC->p.cx = GC->p.x1 - GC->p.x + 1; GC->p.cy = 1; - gdisp_lld_stream_start(GC); - do { gdisp_lld_stream_color(GC); } while(GC->p.cx--); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_start(GC); + do { gdisp_lld_write_color(GC); } while(GC->p.cx--); + gdisp_lld_write_stop(GC); #else // Worst is drawing pixels for(; GC->p.x <= GC->p.x1; GC->p.x++) @@ -217,7 +200,7 @@ static void vline_clip(void) { // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming - #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM) + #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) // Is this a point if (GC->p.y == GC->p.y1) { #if GDISP_HARDWARE_DRAWPIXEL @@ -226,11 +209,9 @@ static void vline_clip(void) { #else // Worst is streaming GC->p.cx = GC->p.cy = 1; - gdisp_lld_stream_start(GC); - gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_start(GC); + gdisp_lld_write_color(GC); + gdisp_lld_write_stop(GC); #endif return; } @@ -241,15 +222,13 @@ static void vline_clip(void) { GC->p.cy = GC->p.y1 - GC->p.y + 1; GC->p.cx = 1; gdisp_lld_fill_area(GC); - #elif GDISP_HARDWARE_STREAM + #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming GC->p.cy = GC->p.y1 - GC->p.y + 1; GC->p.cx = 1; - gdisp_lld_stream_start(GC); - do { gdisp_lld_stream_color(GC); } while(GC->p.cy--); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_start(GC); + do { gdisp_lld_write_color(GC); } while(GC->p.cy--); + gdisp_lld_write_stop(GC); #else // Worst is drawing pixels for(; GC->p.y <= GC->p.y1; GC->p.y++) @@ -377,13 +356,13 @@ void _gdispInit(void) { GC->flags |= GDISP_FLG_INSTREAM; - #if GDISP_HARDWARE_STREAM + #if GDISP_HARDWARE_STREAM_WRITE // Best is hardware streaming GC->p.x = x; GC->p.y = y; GC->p.cx = cx; GC->p.cy = cy; - gdisp_lld_stream_start(GC); + gdisp_lld_write_start(GC); #else // Worst - save the parameters and use pixel drawing @@ -402,7 +381,7 @@ void _gdispInit(void) { } void gdispStreamColor(color_t color) { - #if !GDISP_HARDWARE_STREAM && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS + #if !GDISP_HARDWARE_STREAM_WRITE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS coord_t sx1, sy1; #endif @@ -412,10 +391,10 @@ void _gdispInit(void) { if (!(GC->flags & GDISP_FLG_INSTREAM)) return; - #if GDISP_HARDWARE_STREAM + #if GDISP_HARDWARE_STREAM_WRITE // Best is hardware streaming GC->p.color = color; - gdisp_lld_stream_color(GC); + gdisp_lld_write_color(GC); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS GC->linebuf[GC->p.cx++] = color; if (GC->p.cx >= GDISP_LINEBUF_SIZE) { @@ -494,10 +473,8 @@ void _gdispInit(void) { if (!(GC->flags & GDISP_FLG_INSTREAM)) return; - #if GDISP_HARDWARE_STREAM - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + #if GDISP_HARDWARE_STREAM_WRITE + gdisp_lld_write_stop(GC); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS if (GC->p.cx) { GC->p.x1 = 0; @@ -553,7 +530,7 @@ void gdispClear(color_t color) { GC->p.cy = GC->g.Height; GC->p.color = color; gdisp_lld_fill_area(GC); - #elif GDISP_HARDWARE_STREAM + #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming uint32_t area; @@ -563,12 +540,10 @@ void gdispClear(color_t color) { GC->p.color = color; area = (uint32_t)GC->p.cx * GC->p.cy; - gdisp_lld_stream_start(GC); + gdisp_lld_write_start(GC); for(; area; area--) - gdisp_lld_stream_color(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_color(GC); + gdisp_lld_write_stop(GC); #else // Worst is drawing pixels GC->p.color = color; @@ -616,7 +591,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.x2 = srccx; GC->p.ptr = (void *)buffer; gdisp_lld_blit_area(GC); - #elif GDISP_HARDWARE_STREAM + #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap @@ -629,16 +604,14 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.y = y; GC->p.cx = cx; GC->p.cy = cy; - gdisp_lld_stream_start(GC); + gdisp_lld_write_start(GC); for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) { GC->p.color = *buffer++; - gdisp_lld_stream_color(GC); + gdisp_lld_write_color(GC); } } - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_stop(GC); #elif GDISP_HARDWARE_FILLS // Only slightly better than drawing pixels is to look for runs and use fill area @@ -1578,17 +1551,15 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.x = x; GC->p.y = y; c = gdisp_lld_get_pixel_color(GC); - #elif GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ + #elif GDISP_HARDWARE_STREAM_READ // Next best is hardware streaming GC->p.x = x; GC->p.y = y; GC->p.cx = 1; GC->p.cy = 1; - gdisp_lld_stream_start(GC); - c = gdisp_lld_stream_read(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_read_start(GC); + c = gdisp_lld_read_color(GC); + gdisp_lld_read_stop(GC); #else // Worst is "not possible" #error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display" @@ -1634,7 +1605,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #else cy -= abslines; if (lines < 0) { - fy = y+cx-1; + fy = y+cy-1; dy = -1; } else { fy = y; @@ -1652,18 +1623,16 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, fx = GDISP_LINEBUF_SIZE; // Read one line of data from the screen - #if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ + #if GDISP_HARDWARE_STREAM_READ // Best is hardware streaming GC->p.x = x+ix; GC->p.y = fy+lines; GC->p.cx = fx; GC->p.cy = 1; - gdisp_lld_stream_start(GC); + gdisp_lld_read_start(GC); for(j=0; j < fx; j++) - GC->linebuf[j] = gdisp_lld_stream_read(GC); - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + GC->linebuf[j] = gdisp_lld_read_color(GC); + gdisp_lld_read_stop(GC); #elif GDISP_HARDWARE_PIXELREAD // Next best is single pixel reads for(j=0; j < fx; j++) { @@ -1688,20 +1657,18 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.x2 = fx; GC->p.ptr = (void *)GC->linebuf; gdisp_lld_blit_area(GC); - #elif GDISP_HARDWARE_STREAM + #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming GC->p.x = x+ix; GC->p.y = fy; GC->p.cx = fx; GC->p.cy = 1; - gdisp_lld_stream_start(GC); + gdisp_lld_write_start(GC); for(j = 0; j < fx; j++) { GC->p.color = GC->linebuf[j]; - gdisp_lld_stream_color(GC); + gdisp_lld_write_color(GC); } - #if GDISP_HARDWARE_STREAM_STOP - gdisp_lld_stream_stop(GC); - #endif + gdisp_lld_write_stop(GC); #else // Worst is drawing pixels GC->p.y = fy; -- cgit v1.2.3 From 884db04e8c13d9258c6aea10248e42615e10ab83 Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 2 Oct 2013 16:29:02 +1000 Subject: New optimisation method for some streaming drivers. It should improve speed by about 30% for those controllers that support it. --- src/gdisp/gdisp.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 2 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index a135462d..756d5c1d 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -54,6 +54,17 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; /* Internal functions. */ /*==========================================================================*/ +#if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + static INLINE void setglobalwindow(void) { + coord_t x, y; + x = GC->p.x; y = GC->p.y; + GC->p.cx = GC->g.Width; GC->p.cy = GC->g.Height; + gdisp_lld_write_start(GC); + GC->p.x = x; GC->p.y = y; + GC->flags |= GDISP_FLG_SCRSTREAM; + } +#endif + // drawpixel_clip() // Parameters: x,y // Alters: cx, cy (if using streaming) @@ -67,6 +78,18 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; #else #define drawpixel_clip() gdisp_lld_draw_pixel(GC) #endif +#elif GDISP_HARDWARE_STREAM_POS + // Next best is cursor based streaming + static INLINE void drawpixel_clip(void) { + #if NEED_CLIPPING + if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1 || GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) + return; + #endif + if (!(GC->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(); + gdisp_lld_write_pos(GC); + gdisp_lld_write_color(GC); + } #else // Worst is streaming static INLINE void drawpixel_clip(void) { @@ -86,6 +109,8 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; // Parameters: x,y cx,cy and color // Alters: nothing // Note: This is not clipped +// Resets the streaming area +// if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill #define fillarea() gdisp_lld_fill_area(GC) @@ -96,7 +121,17 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; area = (uint32_t)GC->p.cx * GC->p.cy; + #if GDISP_HARDWARE_STREAM_POS + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif + gdisp_lld_write_start(GC); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(GC); + #endif for(; area; area--) gdisp_lld_write_color(GC); gdisp_lld_write_stop(GC); @@ -130,6 +165,8 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; // Parameters: x,y and x1 // Alters: x,y x1,y1 cx,cy +// Assumes the window covers the screen and a write_stop() will occur later +// if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. static void hline_clip(void) { // Swap the points if necessary so it always goes from x to x1 if (GC->p.x1 < GC->p.x) { @@ -152,6 +189,12 @@ static void hline_clip(void) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw gdisp_lld_draw_pixel(GC); + #elif GDISP_HARDWARE_STREAM_POS + // Next best is cursor based streaming + if (!(GC->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(); + gdisp_lld_write_pos(GC); + gdisp_lld_write_color(GC); #else // Worst is streaming GC->p.cx = GC->p.cy = 1; @@ -168,6 +211,12 @@ static void hline_clip(void) { GC->p.cx = GC->p.x1 - GC->p.x + 1; GC->p.cy = 1; gdisp_lld_fill_area(GC); + #elif GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + // Next best is cursor based streaming + if (!(GC->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(); + gdisp_lld_write_pos(GC); + do { gdisp_lld_write_color(GC); } while(GC->p.cx--); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming GC->p.cx = GC->p.x1 - GC->p.x + 1; @@ -200,12 +249,18 @@ static void vline_clip(void) { // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming - #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) + #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) || (GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE) // Is this a point if (GC->p.y == GC->p.y1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw gdisp_lld_draw_pixel(GC); + #elif GDISP_HARDWARE_STREAM_POS + // Next best is cursor based streaming + if (!(GC->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(); + gdisp_lld_write_pos(GC); + gdisp_lld_write_color(GC); #else // Worst is streaming GC->p.cx = GC->p.cy = 1; @@ -224,9 +279,18 @@ static void vline_clip(void) { gdisp_lld_fill_area(GC); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming + #if GDISP_HARDWARE_STREAM_POS + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif GC->p.cy = GC->p.y1 - GC->p.y + 1; GC->p.cx = 1; gdisp_lld_write_start(GC); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(GC); + #endif do { gdisp_lld_write_color(GC); } while(GC->p.cy--); gdisp_lld_write_stop(GC); #else @@ -363,6 +427,9 @@ void _gdispInit(void) { GC->p.cx = cx; GC->p.cy = cy; gdisp_lld_write_start(GC); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(GC); + #endif #else // Worst - save the parameters and use pixel drawing @@ -501,6 +568,12 @@ void gdispDrawPixel(coord_t x, coord_t y, color_t color) { GC->p.y = y; GC->p.color = color; drawpixel_clip(); + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -512,6 +585,12 @@ void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color GC->p.y1 = y1; GC->p.color = color; line_clip(); + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -541,6 +620,9 @@ void gdispClear(color_t color) { area = (uint32_t)GC->p.cx * GC->p.cy; gdisp_lld_write_start(GC); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(GC); + #endif for(; area; area--) gdisp_lld_write_color(GC); gdisp_lld_write_stop(GC); @@ -605,6 +687,9 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.cx = cx; GC->p.cy = cy; gdisp_lld_write_start(GC); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(GC); + #endif for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) { GC->p.color = *buffer++; @@ -716,6 +801,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } #endif @@ -750,6 +842,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, } while(a < b); GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } #endif @@ -787,6 +886,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, err -= (2*dy-1)*a2; } } while(dy >= 0); + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } #endif @@ -822,6 +928,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, err -= (2*dy-1)*a2; } } while(dy >= 0); + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } #endif @@ -888,8 +1001,16 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, if (full & 0x0C) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } if (full & 0x03) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } if (full & 0x30) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (full == 0xFF) + if (full == 0xFF) { + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif + MUTEX_EXIT; return; + } } #if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG @@ -1002,6 +1123,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, if (((sbit & 0x10) && a >= sedge && a <= eedge) || ((sbit & 0x20) && a <= sedge && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } } + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } #endif @@ -1499,6 +1627,12 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, break; } + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -1664,6 +1798,9 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, GC->p.cx = fx; GC->p.cy = 1; gdisp_lld_write_start(GC); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(GC); + #endif for(j = 0; j < fx; j++) { GC->p.color = GC->linebuf[j]; gdisp_lld_write_color(GC); @@ -1776,6 +1913,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); } } + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -1791,6 +1935,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+p[1].x; GC->p.y1=ty+p[1].y; line_clip(); } GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+pntarray->x; GC->p.y1=ty+pntarray->y; line_clip(); + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -1850,6 +2001,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } if (!cnt) { + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); return; } @@ -1859,6 +2016,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { if (ymax == lpnt->y) { for (lpnt = lpnt <= pntarray ? epnts : lpnt-1; lpnt->y == y; cnt--) { if (!cnt) { + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); return; } @@ -1869,6 +2032,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } else { for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { if (!cnt) { + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); return; } @@ -1948,6 +2117,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GC->t.clipy1 = y + font->height; GC->t.color = color; mf_render_character(font, x, y, c, drawcharline, GC); + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -1967,6 +2142,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { fillarea(); mf_render_character(font, x, y, c, fillcharline, GC); } + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -1980,6 +2161,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GC->t.color = color; mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, GC); + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -1999,6 +2186,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { fillarea(); mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, GC); } + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -2026,6 +2220,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { y += (cy+1 - font->height)/2; mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, GC); + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } @@ -2063,6 +2264,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { /* Render */ mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, GC); } + + #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + if ((GC->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(GC); + GC->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif MUTEX_EXIT(); } -- cgit v1.2.3 From d22bc07e7adf459b2b83fcd0e5bd6475c18e1e9a Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 12 Oct 2013 13:24:40 +1000 Subject: Multiple displays across one or more controllers is now fully supported. Only the Win32 driver supports this so far. Other drivers are currently broken due to API changes and will be fixed. --- src/gdisp/gdisp.c | 1773 +++++++++++++++++++++++++++-------------------------- 1 file changed, 910 insertions(+), 863 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 756d5c1d..41f2f0f9 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -31,81 +31,92 @@ #define INLINE #endif +// Number of milliseconds for the startup logo - 0 means disabled. +#define GDISP_STARTUP_LOGO_TIMEOUT 1000 + /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ -#define GC ((GDISPDriver *)GDISP) -GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; +// The controller array, the display array and the default display +#if GDISP_TOTAL_CONTROLLERS > 1 + typedef const struct GDISPVMT const VMTEL[1]; + extern VMTEL GDISP_CONTROLLER_LIST; + static const struct GDISPVMT const * ControllerList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; + static const unsigned DisplayCountList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS}; +#endif +static GDisplay GDisplayArray[GDISP_TOTAL_DISPLAYS]; +GDisplay *GDISP = GDisplayArray; #if GDISP_NEED_MULTITHREAD - #define MUTEX_INIT() gfxMutexInit(&GC->mutex) - #define MUTEX_ENTER() gfxMutexEnter(&GC->mutex) - #define MUTEX_EXIT() gfxMutexExit(&GC->mutex) + #define MUTEX_INIT(g) gfxMutexInit(&(g)->mutex) + #define MUTEX_ENTER(g) gfxMutexEnter(&(g)->mutex) + #define MUTEX_EXIT(g) gfxMutexExit(&(g)->mutex) #else - #define MUTEX_INIT() - #define MUTEX_ENTER() - #define MUTEX_EXIT() + #define MUTEX_INIT(g) + #define MUTEX_ENTER(g) + #define MUTEX_EXIT(g) #endif #define NEED_CLIPPING (!GDISP_HARDWARE_CLIP && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) + /*==========================================================================*/ /* Internal functions. */ /*==========================================================================*/ #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - static INLINE void setglobalwindow(void) { + static INLINE void setglobalwindow(GDisplay *g) { coord_t x, y; - x = GC->p.x; y = GC->p.y; - GC->p.cx = GC->g.Width; GC->p.cy = GC->g.Height; - gdisp_lld_write_start(GC); - GC->p.x = x; GC->p.y = y; - GC->flags |= GDISP_FLG_SCRSTREAM; + x = g->p.x; y = g->p.y; + g->p.cx = g->g.Width; g->p.cy = g->g.Height; + gdisp_lld_write_start(g); + g->p.x = x; g->p.y = y; + g->flags |= GDISP_FLG_SCRSTREAM; } #endif -// drawpixel_clip() +// drawpixel_clip(g) // Parameters: x,y // Alters: cx, cy (if using streaming) #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw #if NEED_CLIPPING - static INLINE void drawpixel_clip(void) { - if (GC->p.x >= GC->clipx0 && GC->p.x < GC->clipx1 && GC->p.y >= GC->clipy0 && GC->p.y < GC->clipy1) - gdisp_lld_draw_pixel(GC); + static INLINE void drawpixel_clip(GDisplay *g) { + if (g->p.x >= g->clipx0 && g->p.x < g->clipx1 && g->p.y >= g->clipy0 && g->p.y < g->clipy1) + gdisp_lld_draw_pixel(g); } #else - #define drawpixel_clip() gdisp_lld_draw_pixel(GC) + #define drawpixel_clip(g) gdisp_lld_draw_pixel(g) #endif #elif GDISP_HARDWARE_STREAM_POS // Next best is cursor based streaming - static INLINE void drawpixel_clip(void) { + static INLINE void drawpixel_clip(GDisplay *g) { #if NEED_CLIPPING - if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1 || GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; #endif - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - gdisp_lld_write_color(GC); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); } #else // Worst is streaming - static INLINE void drawpixel_clip(void) { + static INLINE void drawpixel_clip(GDisplay *g) { #if NEED_CLIPPING - if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1 || GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; #endif - GC->p.cx = GC->p.cy = 1; - gdisp_lld_write_start(GC); - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); } #endif -// fillarea() +// fillarea(g) // Parameters: x,y cx,cy and color // Alters: nothing // Note: This is not clipped @@ -113,94 +124,94 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; // if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - #define fillarea() gdisp_lld_fill_area(GC) + #define fillarea(g) gdisp_lld_fill_area(g) #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming - static INLINE void fillarea(void) { + static INLINE void fillarea(GDisplay *g) { uint32_t area; - area = (uint32_t)GC->p.cx * GC->p.cy; + area = (uint32_t)g->p.cx * g->p.cy; #if GDISP_HARDWARE_STREAM_POS - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - gdisp_lld_write_start(GC); + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif for(; area; area--) - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); } #else // Worst is drawing pixels - static INLINE void fillarea(void) { + static INLINE void fillarea(GDisplay *g) { coord_t x0, y0, x1, y1; - x0 = GC->p.x; - y0 = GC->p.y; - x1 = GC->p.x + GC->p.cx; - y1 = GC->p.y + GC->p.cy; - for(; GC->p.y < y1; GC->p.y++, GC->p.x = x0) - for(; GC->p.x < x1; GC->p.x++) - gdisp_lld_draw_pixel(GC); - GC->p.y = y0; + x0 = g->p.x; + y0 = g->p.y; + x1 = g->p.x + g->p.cx; + y1 = g->p.y + g->p.cy; + for(; g->p.y < y1; g->p.y++, g->p.x = x0) + for(; g->p.x < x1; g->p.x++) + gdisp_lld_draw_pixel(g); + g->p.y = y0; } #endif #if NEED_CLIPPING - #define TEST_CLIP_AREA(x,y,cx,cy) \ - if ((x) < GC->clipx0) { (cx) -= GC->clipx0 - (x); (x) = GC->clipx0; } \ - if ((y) < GC->clipy0) { (cy) -= GC->clipy0 - (y); (y) = GC->clipy0; } \ - if ((x) + (cx) > GC->clipx1) (cx) = GC->clipx1 - (x); \ - if ((y) + (cy) > GC->clipy1) (cy) = GC->clipy1 - (y); \ - if ((cx) > 0 && (cy) > 0) + #define TEST_CLIP_AREA(g) \ + if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; } \ + if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; } \ + if ((g)->p.x + (g)->p.cx > (g)->clipx1) (g)->p.cx = (g)->clipx1 - (g)->p.x; \ + if ((g)->p.y + (g)->p.cy > (g)->clipy1) (g)->p.cy = (g)->clipy1 - (g)->p.y; \ + if ((g)->p.cx > 0 && (g)->p.cy > 0) #else - #define TEST_CLIP_AREA(x,y,cx,cy) + #define TEST_CLIP_AREA(g) #endif // Parameters: x,y and x1 // Alters: x,y x1,y1 cx,cy // Assumes the window covers the screen and a write_stop() will occur later // if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. -static void hline_clip(void) { +static void hline_clip(GDisplay *g) { // Swap the points if necessary so it always goes from x to x1 - if (GC->p.x1 < GC->p.x) { - GC->p.cx = GC->p.x; GC->p.x = GC->p.x1; GC->p.x1 = GC->p.cx; + if (g->p.x1 < g->p.x) { + g->p.cx = g->p.x; g->p.x = g->p.x1; g->p.x1 = g->p.cx; } // Clipping #if NEED_CLIPPING - if (GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) return; - if (GC->p.x < GC->clipx0) GC->p.x = GC->clipx0; - if (GC->p.x1 >= GC->clipx1) GC->p.x1 = GC->clipx1 - 1; - if (GC->p.x1 < GC->p.x) return; + if (g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; + if (g->p.x < g->clipx0) g->p.x = g->clipx0; + if (g->p.x1 >= g->clipx1) g->p.x1 = g->clipx1 - 1; + if (g->p.x1 < g->p.x) return; #endif // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) // Is this a point - if (GC->p.x == GC->p.x1) { + if (g->p.x == g->p.x1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(GC); + gdisp_lld_draw_pixel(g); #elif GDISP_HARDWARE_STREAM_POS // Next best is cursor based streaming - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - gdisp_lld_write_color(GC); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); #else // Worst is streaming - GC->p.cx = GC->p.cy = 1; - gdisp_lld_write_start(GC); - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); #endif return; } @@ -208,65 +219,65 @@ static void hline_clip(void) { #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - GC->p.cx = GC->p.x1 - GC->p.x + 1; - GC->p.cy = 1; - gdisp_lld_fill_area(GC); + g->p.cx = g->p.x1 - g->p.x + 1; + g->p.cy = 1; + gdisp_lld_fill_area(g); #elif GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE // Next best is cursor based streaming - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - do { gdisp_lld_write_color(GC); } while(GC->p.cx--); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + do { gdisp_lld_write_color(g); } while(g->p.cx--); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming - GC->p.cx = GC->p.x1 - GC->p.x + 1; - GC->p.cy = 1; - gdisp_lld_write_start(GC); - do { gdisp_lld_write_color(GC); } while(GC->p.cx--); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.x1 - g->p.x + 1; + g->p.cy = 1; + gdisp_lld_write_start(g); + do { gdisp_lld_write_color(g); } while(g->p.cx--); + gdisp_lld_write_stop(g); #else // Worst is drawing pixels - for(; GC->p.x <= GC->p.x1; GC->p.x++) - gdisp_lld_draw_pixel(GC); + for(; g->p.x <= g->p.x1; g->p.x++) + gdisp_lld_draw_pixel(g); #endif } // Parameters: x,y and y1 // Alters: x,y x1,y1 cx,cy -static void vline_clip(void) { +static void vline_clip(GDisplay *g) { // Swap the points if necessary so it always goes from y to y1 - if (GC->p.y1 < GC->p.y) { - GC->p.cy = GC->p.y; GC->p.y = GC->p.y1; GC->p.y1 = GC->p.cy; + if (g->p.y1 < g->p.y) { + g->p.cy = g->p.y; g->p.y = g->p.y1; g->p.y1 = g->p.cy; } // Clipping #if NEED_CLIPPING - if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1) return; - if (GC->p.y < GC->clipy0) GC->p.y = GC->clipy0; - if (GC->p.y1 >= GC->clipy1) GC->p.y1 = GC->clipy1 - 1; - if (GC->p.y1 < GC->p.y) return; + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1) return; + if (g->p.y < g->clipy0) g->p.y = g->clipy0; + if (g->p.y1 >= g->clipy1) g->p.y1 = g->clipy1 - 1; + if (g->p.y1 < g->p.y) return; #endif // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) || (GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE) // Is this a point - if (GC->p.y == GC->p.y1) { + if (g->p.y == g->p.y1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(GC); + gdisp_lld_draw_pixel(g); #elif GDISP_HARDWARE_STREAM_POS // Next best is cursor based streaming - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - gdisp_lld_write_color(GC); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); #else // Worst is streaming - GC->p.cx = GC->p.cy = 1; - gdisp_lld_write_start(GC); - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); #endif return; } @@ -274,48 +285,48 @@ static void vline_clip(void) { #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - GC->p.cy = GC->p.y1 - GC->p.y + 1; - GC->p.cx = 1; - gdisp_lld_fill_area(GC); + g->p.cy = g->p.y1 - g->p.y + 1; + g->p.cx = 1; + gdisp_lld_fill_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming #if GDISP_HARDWARE_STREAM_POS - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - GC->p.cy = GC->p.y1 - GC->p.y + 1; - GC->p.cx = 1; - gdisp_lld_write_start(GC); + g->p.cy = g->p.y1 - g->p.y + 1; + g->p.cx = 1; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif - do { gdisp_lld_write_color(GC); } while(GC->p.cy--); - gdisp_lld_write_stop(GC); + do { gdisp_lld_write_color(g); } while(g->p.cy--); + gdisp_lld_write_stop(g); #else // Worst is drawing pixels - for(; GC->p.y <= GC->p.y1; GC->p.y++) - gdisp_lld_draw_pixel(GC); + for(; g->p.y <= g->p.y1; g->p.y++) + gdisp_lld_draw_pixel(g); #endif } // Parameters: x,y and x1,y1 // Alters: x,y x1,y1 cx,cy -static void line_clip(void) { +static void line_clip(GDisplay *g) { int16_t dy, dx; int16_t addx, addy; int16_t P, diff, i; // Is this a horizontal line (or a point) - if (GC->p.y == GC->p.y1) { - hline_clip(); + if (g->p.y == g->p.y1) { + hline_clip(g); return; } // Is this a vertical line (or a point) - if (GC->p.x == GC->p.x1) { - vline_clip(); + if (g->p.x == g->p.x1) { + vline_clip(g); return; } @@ -327,18 +338,18 @@ static void line_clip(void) { // When clipping is needed, all the clipping could also be done up front // instead of on each pixel. - if (GC->p.x1 >= GC->p.x) { - dx = GC->p.x1 - GC->p.x; + if (g->p.x1 >= g->p.x) { + dx = g->p.x1 - g->p.x; addx = 1; } else { - dx = GC->p.x - GC->p.x1; + dx = g->p.x - g->p.x1; addx = -1; } - if (GC->p.y1 >= GC->p.y) { - dy = GC->p.y1 - GC->p.y; + if (g->p.y1 >= g->p.y) { + dy = g->p.y1 - g->p.y; addy = 1; } else { - dy = GC->p.y - GC->p.y1; + dy = g->p.y - g->p.y1; addy = -1; } @@ -348,14 +359,14 @@ static void line_clip(void) { diff = P - dx; for(i=0; i<=dx; ++i) { - drawpixel_clip(); + drawpixel_clip(g); if (P < 0) { P += dy; - GC->p.x += addx; + g->p.x += addx; } else { P += diff; - GC->p.x += addx; - GC->p.y += addy; + g->p.x += addx; + g->p.y += addy; } } } else { @@ -364,90 +375,126 @@ static void line_clip(void) { diff = P - dy; for(i=0; i<=dy; ++i) { - drawpixel_clip(); + drawpixel_clip(g); if (P < 0) { P += dx; - GC->p.y += addy; + g->p.y += addy; } else { P += diff; - GC->p.x += addx; - GC->p.y += addy; + g->p.x += addx; + g->p.y += addy; } } } } +#if GDISP_STARTUP_LOGO_TIMEOUT > 0 + static void StatupLogoDisplay(GDisplay *g) { + gdispGClear(g, Black); + gdispGFillArea(g, g->g.Width/4, g->g.Height/4, g->g.Width/2, g->g.Height/2, Blue); + } +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ /* Our module initialiser */ void _gdispInit(void) { - MUTEX_INIT(); + GDisplay *g; + unsigned i; + #if GDISP_TOTAL_CONTROLLERS > 1 + unsigned j; + #endif + /* Initialise driver */ - MUTEX_ENTER(); - GC->flags = 0; - gdisp_lld_init(GC); - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - #if GDISP_HARDWARE_CLIP - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_set_clip(GC); - #else - GC->clipx0 = 0; - GC->clipy0 = 0; - GC->clipx1 = GC->g.Width; - GC->clipy1 = GC->g.Height; - #endif + #if GDISP_TOTAL_CONTROLLERS > 1 + for(g = GDisplayArray, j=0; j < GDISP_TOTAL_CONTROLLERS; j++) + for(i = 0; i < DisplayCountList[j]; g++, i++) { + g->vmt = ControllerList[j]; + #else + for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) { + #endif + MUTEX_INIT(g); + MUTEX_ENTER(g); + g->flags = 0; + gdisp_lld_init(g, i); + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + #if GDISP_HARDWARE_CLIP + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_set_clip(g); + #else + g->clipx0 = 0; + g->clipy0 = 0; + g->clipx1 = g->g.Width; + g->clipy1 = g->g.Height; + #endif + #endif + MUTEX_EXIT(g); + #if GDISP_STARTUP_LOGO_TIMEOUT > 0 + StatupLogoDisplay(g); + #else + gdispGClear(g, Black); + #endif + } + #if GDISP_STARTUP_LOGO_TIMEOUT > 0 + gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); + for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) + gdispGClear(g, Black); #endif - MUTEX_EXIT(); +} + +void gdispSetDisplay(unsigned display) { + if (display < GDISP_TOTAL_DISPLAYS) + GDISP = &GDisplayArray[display]; } #if GDISP_NEED_STREAMING - void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) { - MUTEX_ENTER(); + void gdispGStreamStart(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { + MUTEX_ENTER(g); #if NEED_CLIPPING // Test if the area is valid - if not then exit - if (x < GC->clipx0 || x+cx > GC->clipx1 || y < GC->clipy0 || y+cy > GC->clipy1) { - MUTEX_EXIT(); + if (x < g->clipx0 || x+cx > g->clipx1 || y < g->clipy0 || y+cy > g->clipy1) { + MUTEX_EXIT(g); return; } #endif - GC->flags |= GDISP_FLG_INSTREAM; + g->flags |= GDISP_FLG_INSTREAM; #if GDISP_HARDWARE_STREAM_WRITE // Best is hardware streaming - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_write_start(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif #else // Worst - save the parameters and use pixel drawing // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position, cx = bufpos - GC->p.x1 = GC->p.x = x; - GC->p.y1 = GC->p.y = y; - GC->p.x2 = x + cx; - GC->p.y2 = y + cy; + g->p.x1 = g->p.x = x; + g->p.y1 = g->p.y = y; + g->p.x2 = x + cx; + g->p.y2 = y + cy; #if (GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS) || GDISP_HARDWARE_FILLS - GC->p.cx = 0; - GC->p.cy = 1; + g->p.cx = 0; + g->p.cy = 1; #endif #endif // Don't release the mutex as gdispStreamEnd() will do that. } - void gdispStreamColor(color_t color) { + void gdispGStreamColor(GDisplay *g, color_t color) { #if !GDISP_HARDWARE_STREAM_WRITE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS coord_t sx1, sy1; #endif @@ -455,224 +502,224 @@ void _gdispInit(void) { // Don't touch the mutex as we should already own it // Ignore this call if we are not streaming - if (!(GC->flags & GDISP_FLG_INSTREAM)) + if (!(g->flags & GDISP_FLG_INSTREAM)) return; #if GDISP_HARDWARE_STREAM_WRITE // Best is hardware streaming - GC->p.color = color; - gdisp_lld_write_color(GC); + g->p.color = color; + gdisp_lld_write_color(g); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - GC->linebuf[GC->p.cx++] = color; - if (GC->p.cx >= GDISP_LINEBUF_SIZE) { - sx1 = GC->p.x1; - sy1 = GC->p.y1; - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); - GC->p.x1 = sx1; - GC->p.y1 = sy1; - GC->p.x += GC->p.cx; - GC->p.cx = 0; + g->linebuf[g->p.cx++] = color; + if (g->p.cx >= GDISP_LINEBUF_SIZE) { + sx1 = g->p.x1; + sy1 = g->p.y1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + g->p.x1 = sx1; + g->p.y1 = sy1; + g->p.x += g->p.cx; + g->p.cx = 0; } // Just wrap at end-of-line and end-of-buffer - if (GC->p.x+GC->p.cx >= GC->p.x2) { - if (GC->p.cx) { - sx1 = GC->p.x1; - sy1 = GC->p.y1; - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); - GC->p.x1 = sx1; - GC->p.y1 = sy1; - GC->p.cx = 0; + if (g->p.x+g->p.cx >= g->p.x2) { + if (g->p.cx) { + sx1 = g->p.x1; + sy1 = g->p.y1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + g->p.x1 = sx1; + g->p.y1 = sy1; + g->p.cx = 0; } - GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.y2) - GC->p.y = GC->p.y1; + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } #elif GDISP_HARDWARE_FILLS // Only slightly better than drawing pixels is to look for runs and use fill area - if (!GC->p.cx || GC->p.color == color) { - GC->p.cx++; - GC->p.color = color; + if (!g->p.cx || g->p.color == color) { + g->p.cx++; + g->p.color = color; } else { - if (GC->p.cx == 1) - gdisp_lld_draw_pixel(GC); + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); else - gdisp_lld_fill_area(GC); - GC->p.x += GC->p.cx; - GC->p.color = color; - GC->p.cx = 1; + gdisp_lld_fill_area(g); + g->p.x += g->p.cx; + g->p.color = color; + g->p.cx = 1; } // Just wrap at end-of-line and end-of-buffer - if (GC->p.x+GC->p.cx >= GC->p.x2) { - if (GC->p.cx) { - if (GC->p.cx == 1) - gdisp_lld_draw_pixel(GC); + if (g->p.x+g->p.cx >= g->p.x2) { + if (g->p.cx) { + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); else - gdisp_lld_fill_area(GC); - GC->p.cx = 0; + gdisp_lld_fill_area(g); + g->p.cx = 0; } - GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.y2) - GC->p.y = GC->p.y1; + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } #else // Worst is using pixel drawing - GC->p.color = color; - gdisp_lld_draw_pixel(GC); + g->p.color = color; + gdisp_lld_draw_pixel(g); // Just wrap at end-of-line and end-of-buffer - if (++GC->p.x >= GC->p.x2) { - GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.y2) - GC->p.y = GC->p.y1; + if (++g->p.x >= g->p.x2) { + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } #endif } - void gdispStreamStop(void) { + void gdispGStreamStop(GDisplay *g) { // Only release the mutex and end the stream if we are actually streaming. - if (!(GC->flags & GDISP_FLG_INSTREAM)) + if (!(g->flags & GDISP_FLG_INSTREAM)) return; #if GDISP_HARDWARE_STREAM_WRITE - gdisp_lld_write_stop(GC); + gdisp_lld_write_stop(g); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - if (GC->p.cx) { - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); + if (g->p.cx) { + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); } #elif GDISP_HARDWARE_FILLS - if (GC->p.cx) { - if (GC->p.cx == 1) - gdisp_lld_draw_pixel(GC); + if (g->p.cx) { + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); else - gdisp_lld_fill_area(GC); + gdisp_lld_fill_area(g); } #endif - GC->flags &= ~GDISP_FLG_INSTREAM; - MUTEX_EXIT(); + g->flags &= ~GDISP_FLG_INSTREAM; + MUTEX_EXIT(g); } #endif -void gdispDrawPixel(coord_t x, coord_t y, color_t color) { - MUTEX_ENTER(); - GC->p.x = x; - GC->p.y = y; - GC->p.color = color; - drawpixel_clip(); +void gdispGDrawPixel(GDisplay *g, coord_t x, coord_t y, color_t color) { + MUTEX_ENTER(g); + g->p.x = x; + g->p.y = y; + g->p.color = color; + drawpixel_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - MUTEX_ENTER(); - GC->p.x = x0; - GC->p.y = y0; - GC->p.x1 = x1; - GC->p.y1 = y1; - GC->p.color = color; - line_clip(); +void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { + MUTEX_ENTER(g); + g->p.x = x0; + g->p.y = y0; + g->p.x1 = x1; + g->p.y1 = y1; + g->p.color = color; + line_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispClear(color_t color) { +void gdispGClear(GDisplay *g, color_t color) { // Note - clear() ignores the clipping area. It clears the screen. - MUTEX_ENTER(); + MUTEX_ENTER(g); #if GDISP_HARDWARE_CLEARS // Best is hardware accelerated clear - GC->p.color = color; - gdisp_lld_clear(GC); + g->p.color = color; + gdisp_lld_clear(g); #elif GDISP_HARDWARE_FILLS // Next best is hardware accelerated area fill - GC->p.x = GC->p.y = 0; - GC->p.cx = GC->g.Width; - GC->p.cy = GC->g.Height; - GC->p.color = color; - gdisp_lld_fill_area(GC); + g->p.x = g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + g->p.color = color; + gdisp_lld_fill_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming uint32_t area; - GC->p.x = GC->p.y = 0; - GC->p.cx = GC->g.Width; - GC->p.cy = GC->g.Height; - GC->p.color = color; - area = (uint32_t)GC->p.cx * GC->p.cy; + g->p.x = g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + g->p.color = color; + area = (uint32_t)g->p.cx * g->p.cy; - gdisp_lld_write_start(GC); + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif for(; area; area--) - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); #else // Worst is drawing pixels - GC->p.color = color; - for(GC->p.y = 0; GC->p.y < GC->g.Height; GC->p.y++) - for(GC->p.x = 0; GC->p.x < GC->g.Width; GC->p.x++) - gdisp_lld_draw_pixel(GC); + g->p.color = color; + for(g->p.y = 0; g->p.y < g->g.Height; g->p.y++) + for(g->p.x = 0; g->p.x < g->g.Width; g->p.x++) + gdisp_lld_draw_pixel(g); #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - MUTEX_ENTER(); - TEST_CLIP_AREA(x,y,cx,cy) { - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - GC->p.color = color; - fillarea(); +void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + MUTEX_ENTER(g); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.color = color; + TEST_CLIP_AREA(g) { + fillarea(g); } - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { - MUTEX_ENTER(); +void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + MUTEX_ENTER(g); #if NEED_CLIPPING - // This is a different cliping to fillarea() as it needs to take into account srcx,srcy - if (x < GC->clipx0) { cx -= GC->clipx0 - x; srcx += GC->clipx0 - x; x = GC->clipx0; } - if (y < GC->clipy0) { cy -= GC->clipy0 - y; srcy += GC->clipy0 - x; y = GC->clipy0; } - if (x+cx > GC->clipx1) cx = GC->clipx1 - x; - if (y+cy > GC->clipy1) cy = GC->clipy1 - y; + // This is a different cliping to fillarea(g) as it needs to take into account srcx,srcy + if (x < g->clipx0) { cx -= g->clipx0 - x; srcx += g->clipx0 - x; x = g->clipx0; } + if (y < g->clipy0) { cy -= g->clipy0 - y; srcy += g->clipy0 - x; y = g->clipy0; } + if (x+cx > g->clipx1) cx = g->clipx1 - x; + if (y+cy > g->clipy1) cy = g->clipy1 - y; if (srcx+cx > srccx) cx = srccx - srcx; - if (cx <= 0 || cy <= 0) { MUTEX_EXIT(); return; } + if (cx <= 0 || cy <= 0) { MUTEX_EXIT(g); return; } #endif #if GDISP_HARDWARE_BITFILLS // Best is hardware bitfills - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - GC->p.x1 = srcx; - GC->p.y1 = srcy; - GC->p.x2 = srccx; - GC->p.ptr = (void *)buffer; - gdisp_lld_blit_area(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.x1 = srcx; + g->p.y1 = srcy; + g->p.x2 = srccx; + g->p.ptr = (void *)buffer; + gdisp_lld_blit_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming @@ -682,21 +729,21 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_write_start(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif - for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { - for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) { - GC->p.color = *buffer++; - gdisp_lld_write_color(GC); + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x = x; g->p.x < srcx; g->p.x++) { + g->p.color = *buffer++; + gdisp_lld_write_color(g); } } - gdisp_lld_write_stop(GC); + gdisp_lld_write_stop(g); #elif GDISP_HARDWARE_FILLS // Only slightly better than drawing pixels is to look for runs and use fill area @@ -706,19 +753,19 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - GC->p.cy = 1; - for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { - for(GC->p.x=x; GC->p.x < srcx; GC->p.x += GC->p.cx) { - GC->p.cx=1; - GC->p.color = *buffer++; - while(GC->p.x+GC->p.cx < srcx && *buffer == GC->p.color) { - GC->p.cx++; + g->p.cy = 1; + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x=x; g->p.x < srcx; g->p.x += g->p.cx) { + g->p.cx=1; + g->p.color = *buffer++; + while(g->p.x+g->p.cx < srcx && *buffer == g->p.color) { + g->p.cx++; buffer++; } - if (GC->p.cx == 1) { - gdisp_lld_draw_pixel(GC); + if (g->p.cx == 1) { + gdisp_lld_draw_pixel(g); } else { - gdisp_lld_fill_area(GC); + gdisp_lld_fill_area(g); } } } @@ -731,135 +778,135 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) { - for(GC->p.x=x; GC->p.x < srcx; GC->p.x++) { - GC->p.color = *buffer++; - gdisp_lld_draw_pixel(GC); + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x=x; g->p.x < srcx; g->p.x++) { + g->p.color = *buffer++; + gdisp_lld_draw_pixel(g); } } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #if GDISP_NEED_CLIP - void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { - MUTEX_ENTER(); + void gdispGSetClip(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { + MUTEX_ENTER(g); #if GDISP_HARDWARE_CLIP // Best is using hardware clipping - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_set_clip(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_set_clip(g); #else // Worst is using software clipping if (x < 0) { cx += x; x = 0; } if (y < 0) { cy += y; y = 0; } - if (cx <= 0 || cy <= 0 || x >= GC->g.Width || y >= GC->g.Height) { MUTEX_EXIT(); return; } - GC->clipx0 = x; - GC->clipy0 = y; - GC->clipx1 = x+cx; if (GC->clipx1 > GC->g.Width) GC->clipx1 = GC->g.Width; - GC->clipy1 = y+cy; if (GC->clipy1 > GC->g.Height) GC->clipy1 = GC->g.Height; + if (cx <= 0 || cy <= 0 || x >= g->g.Width || y >= g->g.Height) { MUTEX_EXIT(g); return; } + g->clipx0 = x; + g->clipy0 = y; + g->clipx1 = x+cx; if (g->clipx1 > g->g.Width) g->clipx1 = g->g.Width; + g->clipy1 = y+cy; if (g->clipy1 > g->g.Height) g->clipy1 = g->g.Height; #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_CIRCLE - void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) { + void gdispGDrawCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color) { coord_t a, b, P; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates a = 1; b = radius; P = 4 - radius; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's circle algorithm // Optimized to prevent double drawing - GC->p.x = x; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x + b; GC->p.y = y; drawpixel_clip(); - GC->p.x = x - b; GC->p.y = y; drawpixel_clip(); + g->p.x = x; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x + b; g->p.y = y; drawpixel_clip(g); + g->p.x = x - b; g->p.y = y; drawpixel_clip(g); do { - GC->p.x = x + a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x + b; GC->p.y = y + a; drawpixel_clip(); - GC->p.x = x - b; GC->p.y = y + a; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x + b; GC->p.y = y - a; drawpixel_clip(); - GC->p.x = x - b; GC->p.y = y - a; drawpixel_clip(); + g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x + b; g->p.y = y + a; drawpixel_clip(g); + g->p.x = x - b; g->p.y = y + a; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x + b; g->p.y = y - a; drawpixel_clip(g); + g->p.x = x - b; g->p.y = y - a; drawpixel_clip(g); if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); - GC->p.x = x + a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); + g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_CIRCLE - void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) { + void gdispGFillCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color) { coord_t a, b, P; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates a = 1; b = radius; P = 4 - radius; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's circle algorithm // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); - GC->p.y = y+b; GC->p.x = x; drawpixel_clip(); - GC->p.y = y-b; GC->p.x = x; drawpixel_clip(); + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + g->p.y = y+b; g->p.x = x; drawpixel_clip(g); + g->p.y = y-b; g->p.x = x; drawpixel_clip(g); do { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); if (P < 0) { P += 3 + 2*a++; } else { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); P += 5 + 2*(a++ - b--); } } while(a < b); - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ELLIPSE - void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { + void gdispGDrawEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { coord_t dx, dy; int32_t a2, b2; int32_t err, e2; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates dx = 0; @@ -867,14 +914,14 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a2 = a*a; b2 = b*b; err = b2-(2*b-1)*a2; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's ellipse algorithm do { - GC->p.x = x + dx; GC->p.y = y + dy; drawpixel_clip(); - GC->p.x = x - dx; GC->p.y = y + dy; drawpixel_clip(); - GC->p.x = x - dx; GC->p.y = y - dy; drawpixel_clip(); - GC->p.x = x + dx; GC->p.y = y - dy; drawpixel_clip(); + g->p.x = x + dx; g->p.y = y + dy; drawpixel_clip(g); + g->p.x = x - dx; g->p.y = y + dy; drawpixel_clip(g); + g->p.x = x - dx; g->p.y = y - dy; drawpixel_clip(g); + g->p.x = x + dx; g->p.y = y - dy; drawpixel_clip(g); e2 = 2*err; if(e2 < (2*dx+1)*b2) { @@ -888,22 +935,22 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, } while(dy >= 0); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ELLIPSE - void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { + void gdispGFillEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { coord_t dx, dy; int32_t a2, b2; int32_t err, e2; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates dx = 0; @@ -911,7 +958,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a2 = a*a; b2 = b*b; err = b2-(2*b-1)*a2; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's ellipse algorithm // This is optimized to prevent overdrawing by drawing a line only when a y is about to change value @@ -922,20 +969,20 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, err += (2*dx+1)*b2; } if(e2 > -(2*dy-1)*a2) { - GC->p.y = y + dy; GC->p.x = x - dx; GC->p.x1 = x + dx; hline_clip(); - if (y) { GC->p.y = y - dy; GC->p.x = x - dx; GC->p.x1 = x + dx; hline_clip(); } + g->p.y = y + dy; g->p.x = x - dx; g->p.x1 = x + dx; hline_clip(g); + if (y) { g->p.y = y - dy; g->p.x = x - dx; g->p.x1 = x + dx; hline_clip(g); } dy--; err -= (2*dy-1)*a2; } } while(dy >= 0); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif @@ -944,7 +991,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #include #endif - void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { + void gdispGDrawArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { coord_t a, b, P, sedge, eedge; uint8_t full, sbit, ebit, tbit; @@ -970,8 +1017,8 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, for(tbit=sbit<<1; tbit < ebit; tbit<<=1) full |= tbit; } - MUTEX_ENTER(); - GC->p.color = color; + MUTEX_ENTER(g); + g->p.color = color; if (full) { // Draw full sectors @@ -979,33 +1026,33 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a = 1; b = radius; P = 4 - radius; - if (full & 0x60) { GC->p.y = y+b; GC->p.x = x; drawpixel_clip(); } - if (full & 0x06) { GC->p.y = y-b; GC->p.x = x; drawpixel_clip(); } - if (full & 0x81) { GC->p.y = y; GC->p.x = x+b; drawpixel_clip(); } - if (full & 0x18) { GC->p.y = y; GC->p.x = x-b; drawpixel_clip(); } + if (full & 0x60) { g->p.y = y+b; g->p.x = x; drawpixel_clip(g); } + if (full & 0x06) { g->p.y = y-b; g->p.x = x; drawpixel_clip(g); } + if (full & 0x81) { g->p.y = y; g->p.x = x+b; drawpixel_clip(g); } + if (full & 0x18) { g->p.y = y; g->p.x = x-b; drawpixel_clip(g); } do { - if (full & 0x01) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if (full & 0x02) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x04) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x08) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if (full & 0x10) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if (full & 0x20) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (full & 0x40) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (full & 0x80) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (full & 0x01) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if (full & 0x02) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x04) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x08) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if (full & 0x10) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if (full & 0x20) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if (full & 0x40) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (full & 0x80) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); - if (full & 0xC0) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (full & 0x0C) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x03) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x30) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if (full & 0xC0) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (full & 0x0C) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x03) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x30) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } if (full == 0xFF) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif MUTEX_EXIT; @@ -1032,116 +1079,116 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a = 1; b = radius; P = 4 - radius; - if ((sbit & 0x20) || (ebit & 0x40)) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } - if ((sbit & 0x02) || (ebit & 0x04)) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } - if ((sbit & 0x80) || (ebit & 0x01)) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } - if ((sbit & 0x08) || (ebit & 0x10)) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + if ((sbit & 0x20) || (ebit & 0x40)) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } + if ((sbit & 0x02) || (ebit & 0x04)) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } + if ((sbit & 0x80) || (ebit & 0x01)) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } + if ((sbit & 0x08) || (ebit & 0x10)) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } do { - if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if (((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if (((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge) || ((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge) || ((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge) || ((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge) || ((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } else if (end < start) { // Draw start/end sector where it is a non-internal angle // Optimized to prevent double drawing a = 1; b = radius; P = 4 - radius; - if (sbit & 0x60) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } - if (sbit & 0x06) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } - if (sbit & 0x81) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } - if (sbit & 0x18) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + if (sbit & 0x60) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } + if (sbit & 0x06) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } + if (sbit & 0x81) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } + if (sbit & 0x18) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } do { - if ((sbit & 0x01) && (a >= sedge || a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if ((sbit & 0x02) && (a <= sedge || a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if ((sbit & 0x04) && (a >= sedge || a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if ((sbit & 0x08) && (a <= sedge || a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if ((sbit & 0x10) && (a >= sedge || a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if ((sbit & 0x20) && (a <= sedge || a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if ((sbit & 0x40) && (a >= sedge || a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if ((sbit & 0x80) && (a <= sedge || a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if ((sbit & 0x01) && (a >= sedge || a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if ((sbit & 0x02) && (a <= sedge || a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if ((sbit & 0x04) && (a >= sedge || a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if ((sbit & 0x08) && (a <= sedge || a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if ((sbit & 0x10) && (a >= sedge || a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if ((sbit & 0x20) && (a <= sedge || a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if ((sbit & 0x40) && (a >= sedge || a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if ((sbit & 0x80) && (a <= sedge || a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); if (((sbit & 0x04) && (a >= sedge || a <= eedge)) || ((sbit & 0x08) && (a <= sedge || a >= eedge))) - { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x40) && (a >= sedge || a <= eedge)) || ((sbit & 0x80) && (a <= sedge || a >= eedge))) - { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } if (((sbit & 0x01) && (a >= sedge || a <= eedge)) || ((sbit & 0x02) && (a <= sedge || a >= eedge))) - { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x10) && (a >= sedge || a <= eedge)) || ((sbit & 0x20) && (a <= sedge || a >= eedge))) - { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } else { // Draw start/end sector where it is a internal angle // Optimized to prevent double drawing a = 1; b = radius; P = 4 - radius; - if (((sbit & 0x20) && !eedge) || ((sbit & 0x40) && !sedge)) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x02) && !eedge) || ((sbit & 0x04) && !sedge)) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x80) && !eedge) || ((sbit & 0x01) && !sedge)) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } - if (((sbit & 0x08) && !eedge) || ((sbit & 0x10) && !sedge)) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + if (((sbit & 0x20) && !eedge) || ((sbit & 0x40) && !sedge)) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x02) && !eedge) || ((sbit & 0x04) && !sedge)) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x80) && !eedge) || ((sbit & 0x01) && !sedge)) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } + if (((sbit & 0x08) && !eedge) || ((sbit & 0x10) && !sedge)) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } do { - if (((sbit & 0x01) && a >= sedge && a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x02) && a <= sedge && a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x04) && a >= sedge && a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x08) && a <= sedge && a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x10) && a >= sedge && a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if (((sbit & 0x20) && a <= sedge && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x40) && a >= sedge && a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x80) && a <= sedge && a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (((sbit & 0x01) && a >= sedge && a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x02) && a <= sedge && a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x04) && a >= sedge && a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x08) && a <= sedge && a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x10) && a >= sedge && a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if (((sbit & 0x20) && a <= sedge && a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x40) && a >= sedge && a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x80) && a <= sedge && a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); if (((sbit & 0x04) && a >= sedge && a <= eedge) || ((sbit & 0x08) && a <= sedge && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x40) && a >= sedge && a <= eedge) || ((sbit & 0x80) && a <= sedge && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } if (((sbit & 0x01) && a >= sedge && a <= eedge) || ((sbit & 0x02) && a <= sedge && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x10) && a >= sedge && a <= eedge) || ((sbit & 0x20) && a <= sedge && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ARC - void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { + void gdispGFillArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { coord_t a, b, P; coord_t sy, ey; fixed sxa, sxb, sxd, exa, exb, exd; uint8_t qtr; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Do the trig to get the formulas for the start and end lines. sxa = exa = FIXED(x)+FIXED0_5; @@ -1170,7 +1217,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a = 1; b = radius; P = 4 - radius; - GC->p.color = color; + g->p.color = color; sxb += sxa; exb += exa; @@ -1181,50 +1228,50 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 0: // S2E2 sy <= ey case 1: // S1E2 sy <= ey if (ey && sy) { - GC->p.x = x; GC->p.x1 = x; // E2S + g->p.x = x; g->p.x1 = x; // E2S sxa -= sxd; exa -= exd; } else if (sy) { - GC->p.x = x-b; GC->p.x1 = x; // C2S + g->p.x = x-b; g->p.x1 = x; // C2S sxa -= sxd; } else if (ey) { - GC->p.x = x; GC->p.x1 = x+b; // E2C + g->p.x = x; g->p.x1 = x+b; // E2C exa -= exd; } else { - GC->p.x = x-b; GC->p.x1 = x+b; // C2C + g->p.x = x-b; g->p.x1 = x+b; // C2C } - GC->p.y = y; - hline_clip(); + g->p.y = y; + hline_clip(g); do { if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S sxa -= sxd; exa -= exd; } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S sxa -= sxd; } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = NONFIXED(sxb); hline_clip(); // E2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = NONFIXED(sxb); hline_clip(g); // E2S sxb += sxd; exb += exd; } else if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S sxb += sxd; } else if (qtr & 1) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; @@ -1236,92 +1283,92 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 19: // S4E2 sy > ey case 22: // S3E1 sy > ey case 23: // S4E1 sy > ey - GC->p.y = y; GC->p.x = x; GC->p.x1 = x+b; hline_clip(); // SE2C + g->p.y = y; g->p.x = x; g->p.x1 = x+b; hline_clip(g); // SE2C sxa += sxd; exa -= exd; do { if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C exa -= exd; } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C exb += exd; } else if (!(qtr & 4)) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; } else if (!(qtr & 1)) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+a; hline_clip(g); // S2C } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+a; hline_clip(g); // C2C } break; case 4: // S2E1 sy <= ey case 5: // S1E1 sy <= ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C do { if (-a >= ey) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C sxa -= sxd; exa -= exd; } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S sxa -= sxd; } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (P < 0) { P += 3 + 2*a++; } else { if (-b >= ey) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C sxb += sxd; exb += exd; } else if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S sxb += sxd; } else if (qtr & 1) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= ey) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C break; case 8: // S2E3 sy <= ey @@ -1332,261 +1379,261 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 25: // S1E3 sy > ey case 28: // S2E3 sy > ey case 29: // S1E3 sy > ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x; hline_clip(); // C2SE + g->p.y = y; g->p.x = x-b; g->p.x1 = x; hline_clip(g); // C2SE sxa -= sxd; exa += exd; do { if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S sxa -= sxd; } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E exa += exd; } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S sxb += sxd; } else if (qtr & 1) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E exb -= exd; } else if (qtr & 4) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+a; hline_clip(g); // C2C } break; case 10: // S3E3 sy <= ey case 14: // S3E4 sy <= ey - GC->p.y = y; GC->p.x = x; drawpixel_clip(); // S2E + g->p.y = y; g->p.x = x; drawpixel_clip(g); // S2E sxa += sxd; exa += exd; do { if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g); // S2E sxa += sxd; exa += exd; } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E exa += exd; } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = NONFIXED(exb); hline_clip(); // S2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = NONFIXED(exb); hline_clip(g); // S2E sxb -= sxd; exb -= exd; } else if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E exb -= exd; } else if (qtr & 4) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g); // S2E } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; case 11: // S4E3 sy <= ey case 15: // S4E4 sy <= ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C do { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= sy) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; exa += exd; } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E exa += exd; } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C if (b <= sy) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; exb -= exd; } else if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E exb -= exd; } else if (qtr & 4) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= sy) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; case 16: // S2E2 sy > ey case 20: // S2E1 sy > ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C sxa -= sxd; exa -= exd; do { if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C sxa -= sxd; exa -= exd; } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C exa -= exd; } else if (!(qtr & 4)){ - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (P < 0) { P += 3 + 2*a++; } else { if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C sxb += sxd; exb += exd; } else if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C exb += exd; } else if (!(qtr & 4)){ - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (!(qtr & 4)){ - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C break; case 17: // S1E2 sy > ey case 21: // S1E1 sy > ey if (sy) { - GC->p.x = x; GC->p.x1 = x; // E2S + g->p.x = x; g->p.x1 = x; // E2S sxa -= sxd; exa -= exd; } else { - GC->p.x = x; GC->p.x1 = x+b; // E2C + g->p.x = x; g->p.x1 = x+b; // E2C exa -= exd; } - GC->p.y = y; - hline_clip(); + g->p.y = y; + hline_clip(g); do { if (-a >= sy) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S sxa -= sxd; exa -= exd; } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C exa -= exd; } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= sy) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = NONFIXED(sxb); hline_clip(); // E2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = NONFIXED(sxb); hline_clip(g); // E2S sxb += sxd; exb += exd; } else if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C exb += exd; } else if (!(qtr & 4)) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= sy) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; case 26: // S3E3 sy > ey case 27: // S4E3 sy > ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C do { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; exa += exd; } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; exb -= exd; } else if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; } else if (!(qtr & 1)) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (!(qtr & 4)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; @@ -1594,52 +1641,52 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 31: // S4E4 sy > ey do { if (a <= ey) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g); // S2E sxa += sxd; exa += exd; } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (b <= ey) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = NONFIXED(exb); hline_clip(); // S2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = NONFIXED(exb); hline_clip(g); // S2E sxb -= sxd; exb -= exd; } else if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; } else if (!(qtr & 1)) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (a <= ey) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (!(qtr & 4)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ARC - void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { + void gdispGDrawRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { if (2*radius > cx || 2*radius > cy) { gdispDrawBox(x, y, cx, cy, color); return; @@ -1656,7 +1703,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #endif #if GDISP_NEED_ARC - void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { + void gdispGFillRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { coord_t radius2; radius2 = radius*2; @@ -1675,49 +1722,49 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #endif #if GDISP_NEED_PIXELREAD - color_t gdispGetPixelColor(coord_t x, coord_t y) { + color_t gdispGGetPixelColor(GDisplay *g, coord_t x, coord_t y) { color_t c; /* Always synchronous as it must return a value */ - MUTEX_ENTER(); + MUTEX_ENTER(g); #if GDISP_HARDWARE_PIXELREAD // Best is direct pixel read - GC->p.x = x; - GC->p.y = y; - c = gdisp_lld_get_pixel_color(GC); + g->p.x = x; + g->p.y = y; + c = gdisp_lld_get_pixel_color(g); #elif GDISP_HARDWARE_STREAM_READ // Next best is hardware streaming - GC->p.x = x; - GC->p.y = y; - GC->p.cx = 1; - GC->p.cy = 1; - gdisp_lld_read_start(GC); - c = gdisp_lld_read_color(GC); - gdisp_lld_read_stop(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = 1; + g->p.cy = 1; + gdisp_lld_read_start(g); + c = gdisp_lld_read_color(g); + gdisp_lld_read_stop(g); #else // Worst is "not possible" #error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display" #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return c; } #endif #if GDISP_NEED_SCROLL - void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { + void gdispGVerticalScroll(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { coord_t abslines; #if !GDISP_HARDWARE_SCROLL coord_t fy, dy, ix, fx, i, j; #endif - MUTEX_ENTER(); + MUTEX_ENTER(g); #if NEED_CLIPPING - if (x < GC->clipx0) { cx -= GC->clipx0 - x; x = GC->clipx0; } - if (y < GC->clipy0) { cy -= GC->clipy0 - y; y = GC->clipy0; } - if (!lines || cx <= 0 || cy <= 0 || x >= GC->clipx1 || y >= GC->clipy1) { MUTEX_EXIT(); return; } - if (x+cx > GC->clipx1) cx = GC->clipx1 - x; - if (y+cy > GC->clipy1) cy = GC->clipy1 - y; + if (x < g->clipx0) { cx -= g->clipx0 - x; x = g->clipx0; } + if (y < g->clipy0) { cy -= g->clipy0 - y; y = g->clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= g->clipx1 || y >= g->clipy1) { MUTEX_EXIT(g); return; } + if (x+cx > g->clipx1) cx = g->clipx1 - x; + if (y+cy > g->clipy1) cy = g->clipy1 - y; #endif abslines = lines < 0 ? -lines : lines; @@ -1726,13 +1773,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, cy = 0; } else { #if GDISP_HARDWARE_SCROLL - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - GC->p.y1 = lines; - GC->p.color = bgcolor; - gdisp_lld_vertical_scroll(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.y1 = lines; + g->p.color = bgcolor; + gdisp_lld_vertical_scroll(g); cy -= abslines; #elif GDISP_LINEBUF_SIZE == 0 #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support and GDISP_LINEBUF_SIZE is zero." @@ -1759,20 +1806,20 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, // Read one line of data from the screen #if GDISP_HARDWARE_STREAM_READ // Best is hardware streaming - GC->p.x = x+ix; - GC->p.y = fy+lines; - GC->p.cx = fx; - GC->p.cy = 1; - gdisp_lld_read_start(GC); + g->p.x = x+ix; + g->p.y = fy+lines; + g->p.cx = fx; + g->p.cy = 1; + gdisp_lld_read_start(g); for(j=0; j < fx; j++) - GC->linebuf[j] = gdisp_lld_read_color(GC); - gdisp_lld_read_stop(GC); + g->linebuf[j] = gdisp_lld_read_color(g); + gdisp_lld_read_stop(g); #elif GDISP_HARDWARE_PIXELREAD // Next best is single pixel reads for(j=0; j < fx; j++) { - GC->p.x = x+ix+j; - GC->p.y = fy+lines; - GC->linebuf[j] = gdisp_lld_get_pixel_color(GC); + g->p.x = x+ix+j; + g->p.y = fy+lines; + g->linebuf[j] = gdisp_lld_get_pixel_color(g); } #else // Worst is "not possible" @@ -1782,36 +1829,36 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, // Write that line to the new location #if GDISP_HARDWARE_BITFILLS // Best is hardware bitfills - GC->p.x = x+ix; - GC->p.y = fy; - GC->p.cx = fx; - GC->p.cy = 1; - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.x2 = fx; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); + g->p.x = x+ix; + g->p.y = fy; + g->p.cx = fx; + g->p.cy = 1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.x2 = fx; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming - GC->p.x = x+ix; - GC->p.y = fy; - GC->p.cx = fx; - GC->p.cy = 1; - gdisp_lld_write_start(GC); + g->p.x = x+ix; + g->p.y = fy; + g->p.cx = fx; + g->p.cy = 1; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif for(j = 0; j < fx; j++) { - GC->p.color = GC->linebuf[j]; - gdisp_lld_write_color(GC); + g->p.color = g->linebuf[j]; + gdisp_lld_write_color(g); } - gdisp_lld_write_stop(GC); + gdisp_lld_write_stop(g); #else // Worst is drawing pixels - GC->p.y = fy; - for(GC->p.x = x+ix, j = 0; j < fx; GC->p.x++, j++) { - GC->p.color = GC->linebuf[j]; - gdisp_lld_draw_pixel(GC); + g->p.y = fy; + for(g->p.x = x+ix, j = 0; j < fx; g->p.x++, j++) { + g->p.color = g->linebuf[j]; + gdisp_lld_draw_pixel(g); } #endif } @@ -1820,45 +1867,45 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, } /* fill the remaining gap */ - GC->p.x = x; - GC->p.y = lines > 0 ? (y+cy) : y; - GC->p.cx = cx; - GC->p.cy = abslines; - GC->p.color = bgcolor; - fillarea(); - MUTEX_EXIT(); + g->p.x = x; + g->p.y = lines > 0 ? (y+cy) : y; + g->p.cx = cx; + g->p.cy = abslines; + g->p.color = bgcolor; + fillarea(g); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_CONTROL #if GDISP_HARDWARE_CONTROL - void gdispControl(unsigned what, void *value) { - MUTEX_ENTER(); - GC->p.x = what; - GC->p.ptr = value; - gdisp_lld_control(GC); + void gdispGControl(GDisplay *g, unsigned what, void *value) { + MUTEX_ENTER(g); + g->p.x = what; + g->p.ptr = value; + gdisp_lld_control(g); #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION if (what == GDISP_CONTROL_ORIENTATION) { #if GDISP_HARDWARE_CLIP // Best is hardware clipping - GC->p.x = 0; - GC->p.y = 0; - GC->p.cx = GC->g.Width; - GC->p.cy = GC->g.Height; - gdisp_lld_set_clip(GC); + g->p.x = 0; + g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + gdisp_lld_set_clip(g); #else // Worst is software clipping - GC->clipx0 = 0; - GC->clipy0 = 0; - GC->clipx1 = GC->g.Width; - GC->clipy1 = GC->g.Height; + g->clipx0 = 0; + g->clipy0 = 0; + g->clipx1 = g->g.Width; + g->clipy1 = g->g.Height; #endif } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #else - void gdispControl(unsigned what, void *value) { + void gdispGControl(GDisplay *g, unsigned what, void *value) { (void)what; (void)value; /* Ignore everything */ @@ -1868,17 +1915,17 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #if GDISP_NEED_QUERY #if GDISP_HARDWARE_QUERY - void *gdispQuery(unsigned what) { + void *gdispGQuery(GDisplay *g, unsigned what) { void *res; - MUTEX_ENTER(); - GC->p.x = (coord_t)what; - res = gdisp_lld_query(GC); - MUTEX_EXIT(); + MUTEX_ENTER(g); + g->p.x = (coord_t)what; + res = gdisp_lld_query(g); + MUTEX_EXIT(g); return res; } #else - void *gdispQuery(unsigned what) { + void *gdispGQuery(GDisplay *g, unsigned what) { (void) what; return (void *)-1; } @@ -1889,63 +1936,63 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, /* High Level Driver Routines. */ /*===========================================================================*/ -void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { +void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { if (cx <= 0 || cy <= 0) return; cx = x+cx-1; cy = y+cy-1; // cx, cy are now the end point. - MUTEX_ENTER(); + MUTEX_ENTER(g); - GC->p.color = color; + g->p.color = color; if (cx - x > 2) { - GC->p.x = x; GC->p.y = y; GC->p.x1 = cx; hline_clip(); + g->p.x = x; g->p.y = y; g->p.x1 = cx; hline_clip(g); if (y != cy) { - GC->p.x = x; GC->p.y = cy; GC->p.x1 = cx; hline_clip(); + g->p.x = x; g->p.y = cy; g->p.x1 = cx; hline_clip(g); if (cy - y > 2) { y++; cy--; - GC->p.x = x; GC->p.y = y; GC->p.y1 = cy; vline_clip(); - GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + g->p.x = x; g->p.y = y; g->p.y1 = cy; vline_clip(g); + g->p.x = cx; g->p.y = y; g->p.y1 = cy; vline_clip(g); } } } else { - GC->p.x = x; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + g->p.x = x; g->p.y = y; g->p.y1 = cy; vline_clip(g); if (x != cx) { - GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + g->p.x = cx; g->p.y = y; g->p.y1 = cy; vline_clip(g); } } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #if GDISP_NEED_CONVEX_POLYGON - void gdispDrawPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { + void gdispGDrawPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { const point *epnt, *p; epnt = &pntarray[cnt-1]; - MUTEX_ENTER(); - GC->p.color = color; + MUTEX_ENTER(g); + g->p.color = color; for(p = pntarray; p < epnt; p++) { - GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+p[1].x; GC->p.y1=ty+p[1].y; line_clip(); + g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+p[1].x; g->p.y1=ty+p[1].y; line_clip(g); } - GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+pntarray->x; GC->p.y1=ty+pntarray->y; line_clip(); + g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+pntarray->x; g->p.y1=ty+pntarray->y; line_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { + void gdispGFillConvexPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { const point *lpnt, *rpnt, *epnts; fixed lx, rx, lk, rk; coord_t y, ymax, lxc, rxc; @@ -1975,8 +2022,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { lk = (FIXED(lpnt->x) - lx) / (lpnt->y - y); rk = (FIXED(rpnt->x) - rx) / (rpnt->y - y); - MUTEX_ENTER(); - GC->p.color = color; + MUTEX_ENTER(g); + g->p.color = color; while(1) { /* Determine our boundary */ ymax = rpnt->y < lpnt->y ? rpnt->y : lpnt->y; @@ -1991,9 +2038,9 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { * of pixels. */ if (lxc < rxc) { - GC->p.x=tx+lxc; GC->p.y=ty+y; GC->p.x1=tx+rxc-1; hline_clip(); + g->p.x=tx+lxc; g->p.y=ty+y; g->p.x1=tx+rxc-1; hline_clip(g); } else if (lxc > rxc) { - GC->p.x=tx+rxc; GC->p.y=ty+y; GC->p.x1=tx+lxc-1; hline_clip(); + g->p.x=tx+rxc; g->p.y=ty+y; g->p.x1=tx+lxc-1; hline_clip(g); } lx += lk; @@ -2002,12 +2049,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { if (!cnt) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return; } cnt--; @@ -2017,12 +2064,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { for (lpnt = lpnt <= pntarray ? epnts : lpnt-1; lpnt->y == y; cnt--) { if (!cnt) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return; } lx = FIXED(lpnt->x); @@ -2033,12 +2080,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { if (!cnt) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return; } rx = FIXED(rpnt->x); @@ -2055,27 +2102,27 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { #if GDISP_NEED_ANTIALIAS && GDISP_HARDWARE_PIXELREAD static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - #define GD ((GDISPDriver *)state) + #define GD ((GDisplay *)state) if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; - hline_clip(); + hline_clip(g); } else { for (; count; count--, x++) { GD->p.x = x; GD->p.y = y; GD->p.color = gdispBlendColor(GD->t.color, gdisp_lld_get_pixel_color(GD), alpha); - drawpixel_clip(); + drawpixel_clip(g); } } #undef GD } #else static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - #define GD ((GDISPDriver *)state) + #define GD ((GDisplay *)state) if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha > 0x80) { // A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; - hline_clip(); + hline_clip(g); } #undef GD } @@ -2083,7 +2130,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { #if GDISP_NEED_ANTIALIAS static void fillcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - #define GD ((GDISPDriver *)state) + #define GD ((GDisplay *)state) if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { GD->p.color = GD->t.color; @@ -2091,7 +2138,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GD->p.color = gdispBlendColor(GD->t.color, GD->t.bgcolor, alpha); } GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; - hline_clip(); + hline_clip(g); #undef GD } #else @@ -2100,110 +2147,110 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { /* Callback to render characters. */ static uint8_t drawcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { - return mf_render_character(GC->t.font, x, y, ch, drawcharline, state); + return mf_render_character(g->t.font, x, y, ch, drawcharline, state); } /* Callback to render characters. */ static uint8_t fillcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { - return mf_render_character(GC->t.font, x, y, ch, fillcharline, state); + return mf_render_character(g->t.font, x, y, ch, fillcharline, state); } - void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { - MUTEX_ENTER(); - GC->t.font = font; - GC->t.clipx0 = x; - GC->t.clipy0 = y; - GC->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x; - GC->t.clipy1 = y + font->height; - GC->t.color = color; - mf_render_character(font, x, y, c, drawcharline, GC); + void gdispGDrawChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { + MUTEX_ENTER(g); + g->t.font = font; + g->t.clipx0 = x; + g->t.clipy0 = y; + g->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x; + g->t.clipy1 = y + font->height; + g->t.color = color; + mf_render_character(font, x, y, c, drawcharline, g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { - MUTEX_ENTER(); - GC->p.cx = mf_character_width(font, c) + font->baseline_x; - GC->p.cy = font->height; - GC->t.font = font; - GC->t.clipx0 = GC->p.x = x; - GC->t.clipy0 = GC->p.y = y; - GC->t.clipx1 = GC->p.x+GC->p.cx; - GC->t.clipy1 = GC->p.y+GC->p.cy; - GC->t.color = color; - GC->t.bgcolor = GC->p.color = bgcolor; - - TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { - fillarea(); - mf_render_character(font, x, y, c, fillcharline, GC); + void gdispGFillChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { + MUTEX_ENTER(g); + g->p.cx = mf_character_width(font, c) + font->baseline_x; + g->p.cy = font->height; + g->t.font = font; + g->t.clipx0 = g->p.x = x; + g->t.clipy0 = g->p.y = y; + g->t.clipx1 = g->p.x+g->p.cx; + g->t.clipy1 = g->p.y+g->p.cy; + g->t.color = color; + g->t.bgcolor = g->p.color = bgcolor; + + TEST_CLIP_AREA(g) { + fillarea(g); + mf_render_character(font, x, y, c, fillcharline, g); } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color) { - MUTEX_ENTER(); - GC->t.font = font; - GC->t.clipx0 = x; - GC->t.clipy0 = y; - GC->t.clipx1 = x + mf_get_string_width(font, str, 0, 0); - GC->t.clipy1 = y + font->height; - GC->t.color = color; + void gdispGDrawString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color) { + MUTEX_ENTER(g); + g->t.font = font; + g->t.clipx0 = x; + g->t.clipy0 = y; + g->t.clipx1 = x + mf_get_string_width(font, str, 0, 0); + g->t.clipy1 = y + font->height; + g->t.color = color; - mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, GC); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { - MUTEX_ENTER(); - GC->p.cx = mf_get_string_width(font, str, 0, 0); - GC->p.cy = font->height; - GC->t.font = font; - GC->t.clipx0 = GC->p.x = x; - GC->t.clipy0 = GC->p.y = y; - GC->t.clipx1 = GC->p.x+GC->p.cx; - GC->t.clipy1 = GC->p.y+GC->p.cy; - GC->t.color = color; - GC->t.bgcolor = GC->p.color = bgcolor; - - TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { - fillarea(); - mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, GC); + void gdispGFillString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { + MUTEX_ENTER(g); + g->p.cx = mf_get_string_width(font, str, 0, 0); + g->p.cy = font->height; + g->t.font = font; + g->t.clipx0 = g->p.x = x; + g->t.clipy0 = g->p.y = y; + g->t.clipx1 = g->p.x+g->p.cx; + g->t.clipy1 = g->p.y+g->p.cy; + g->t.color = color; + g->t.bgcolor = g->p.color = bgcolor; + + TEST_CLIP_AREA(g) { + fillarea(g); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, g); } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { - MUTEX_ENTER(); - GC->t.font = font; - GC->t.clipx0 = x; - GC->t.clipy0 = y; - GC->t.clipx1 = x+cx; - GC->t.clipy1 = y+cy; - GC->t.color = color; + void gdispGDrawStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { + MUTEX_ENTER(g); + g->t.font = font; + g->t.clipx0 = x; + g->t.clipy0 = y; + g->t.clipx1 = x+cx; + g->t.clipy1 = y+cy; + g->t.color = color; /* Select the anchor position */ switch(justify) { @@ -2219,33 +2266,33 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } y += (cy+1 - font->height)/2; - mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, GC); + mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { - MUTEX_ENTER(); - GC->p.cx = cx; - GC->p.cy = cy; - GC->t.font = font; - GC->t.clipx0 = GC->p.x = x; - GC->t.clipy0 = GC->p.y = y; - GC->t.clipx1 = x+cx; - GC->t.clipy1 = y+cy; - GC->t.color = color; - GC->t.bgcolor = GC->p.color = bgcolor; + void gdispGFillStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { + MUTEX_ENTER(g); + g->p.cx = cx; + g->p.cy = cy; + g->t.font = font; + g->t.clipx0 = g->p.x = x; + g->t.clipy0 = g->p.y = y; + g->t.clipx1 = x+cx; + g->t.clipy1 = y+cy; + g->t.color = color; + g->t.bgcolor = g->p.color = bgcolor; - TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { + TEST_CLIP_AREA(g) { // background fill - fillarea(); + fillarea(g); /* Select the anchor position */ switch(justify) { @@ -2262,16 +2309,16 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { y += (cy+1 - font->height)/2; /* Render */ - mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, GC); + mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, g); } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) { -- cgit v1.2.3 From ea4af865f11cd18ac1b3d33fb9951f7527a42ab7 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 14 Oct 2013 08:55:15 +1000 Subject: Compile time fix to text rendering. Updated gdisp Get/Set Display routines to a more logical API. --- src/gdisp/gdisp.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 41f2f0f9..ca0411e3 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -448,9 +448,14 @@ void _gdispInit(void) { #endif } -void gdispSetDisplay(unsigned display) { - if (display < GDISP_TOTAL_DISPLAYS) - GDISP = &GDisplayArray[display]; +GDisplay *gdispGetDisplay(unsigned display) { + if (display >= GDISP_TOTAL_DISPLAYS) + return 0; + return &GDisplayArray[display]; +} + +void gdispSetDisplay(GDisplay *g) { + if (g) GDISP = g; } #if GDISP_NEED_STREAMING @@ -2106,12 +2111,12 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; - hline_clip(g); + hline_clip(GD); } else { for (; count; count--, x++) { GD->p.x = x; GD->p.y = y; GD->p.color = gdispBlendColor(GD->t.color, gdisp_lld_get_pixel_color(GD), alpha); - drawpixel_clip(g); + drawpixel_clip(GD); } } #undef GD @@ -2122,7 +2127,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha > 0x80) { // A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; - hline_clip(g); + hline_clip(GD); } #undef GD } @@ -2138,7 +2143,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co GD->p.color = gdispBlendColor(GD->t.color, GD->t.bgcolor, alpha); } GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; - hline_clip(g); + hline_clip(GD); #undef GD } #else @@ -2147,12 +2152,16 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co /* Callback to render characters. */ static uint8_t drawcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { - return mf_render_character(g->t.font, x, y, ch, drawcharline, state); + #define GD ((GDisplay *)state) + return mf_render_character(GD->t.font, x, y, ch, drawcharline, state); + #undef GD } /* Callback to render characters. */ static uint8_t fillcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { - return mf_render_character(g->t.font, x, y, ch, fillcharline, state); + #define GD ((GDisplay *)state) + return mf_render_character(GD->t.font, x, y, ch, fillcharline, state); + #undef GD } void gdispGDrawChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { -- cgit v1.2.3 From 86a57349128197f58cf3f103e9adf9c2c348d418 Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 16 Oct 2013 01:39:56 +1000 Subject: Multiple controller support can now auto-detect hardware capabilities at run-time. Specific hardware support can still be turned off or on via macros in gfxconf.h to improve efficiency. Multiple Display demo updated to match. --- src/gdisp/gdisp.c | 1388 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 886 insertions(+), 502 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index ca0411e3..ef388df5 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -19,10 +19,6 @@ /* Include the low level driver information */ #include "gdisp/lld/gdisp_lld.h" -#if !GDISP_HARDWARE_STREAM_WRITE && !GDISP_HARDWARE_DRAWPIXEL - #error "GDISP Driver: Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be defined" -#endif - #if 1 #undef INLINE #define INLINE inline @@ -34,6 +30,9 @@ // Number of milliseconds for the startup logo - 0 means disabled. #define GDISP_STARTUP_LOGO_TIMEOUT 1000 +// The color to clear the display on startup +#define GDISP_STARTUP_COLOR Black + /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ @@ -58,8 +57,27 @@ GDisplay *GDISP = GDisplayArray; #define MUTEX_EXIT(g) #endif -#define NEED_CLIPPING (!GDISP_HARDWARE_CLIP && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) +#define NEED_CLIPPING (GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) +#if !NEED_CLIPPING + #define TEST_CLIP_AREA(g) +#elif GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + #define TEST_CLIP_AREA(g) \ + if (!g->vmt->setclip) { \ + if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; } \ + if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; } \ + if ((g)->p.x + (g)->p.cx > (g)->clipx1) (g)->p.cx = (g)->clipx1 - (g)->p.x; \ + if ((g)->p.y + (g)->p.cy > (g)->clipy1) (g)->p.cy = (g)->clipy1 - (g)->p.y; \ + } \ + if ((g)->p.cx > 0 && (g)->p.cy > 0) +#else + #define TEST_CLIP_AREA(g) \ + if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; } \ + if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; } \ + if ((g)->p.x + (g)->p.cx > (g)->clipx1) (g)->p.cx = (g)->clipx1 - (g)->p.x; \ + if ((g)->p.y + (g)->p.cy > (g)->clipy1) (g)->p.cy = (g)->clipy1 - (g)->p.y; \ + if ((g)->p.cx > 0 && (g)->p.cy > 0) +#endif /*==========================================================================*/ /* Internal functions. */ @@ -76,103 +94,140 @@ GDisplay *GDISP = GDisplayArray; } #endif -// drawpixel_clip(g) +// drawpixel(g) // Parameters: x,y // Alters: cx, cy (if using streaming) -#if GDISP_HARDWARE_DRAWPIXEL +// Does not clip +static INLINE void drawpixel(GDisplay *g) { + // Best is hardware accelerated pixel draw - #if NEED_CLIPPING - static INLINE void drawpixel_clip(GDisplay *g) { - if (g->p.x >= g->clipx0 && g->p.x < g->clipx1 && g->p.y >= g->clipy0 && g->p.y < g->clipy1) - gdisp_lld_draw_pixel(g); + #if GDISP_HARDWARE_DRAWPIXEL + #if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + if (g->vmt->pixel) + #endif + { + gdisp_lld_draw_pixel(g); + return; } - #else - #define drawpixel_clip(g) gdisp_lld_draw_pixel(g) #endif -#elif GDISP_HARDWARE_STREAM_POS + // Next best is cursor based streaming - static INLINE void drawpixel_clip(GDisplay *g) { - #if NEED_CLIPPING - if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) - return; + #if GDISP_HARDWARE_DRAWPIXEL != TRUE && GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) #endif - if (!(g->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(g); - gdisp_lld_write_pos(g); - gdisp_lld_write_color(g); - } -#else - // Worst is streaming + { + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); + return; + } + #endif + + // Worst is general streaming + #if GDISP_HARDWARE_DRAWPIXEL != TRUE && GDISP_HARDWARE_STREAM_POS != TRUE && GDISP_HARDWARE_STREAM_WRITE + // The following test is unneeded because we are guaranteed to have streaming if we don't have drawpixel + //#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + // if (g->vmt->writestart) + //#endif + { + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); + return; + } + #endif +} + +// drawpixel_clip(g) +// Parameters: x,y +// Alters: cx, cy (if using streaming) +#if NEED_CLIPPING static INLINE void drawpixel_clip(GDisplay *g) { - #if NEED_CLIPPING + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (!g->vmt->setclip) + #endif + { if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; - #endif - - g->p.cx = g->p.cy = 1; - gdisp_lld_write_start(g); - gdisp_lld_write_color(g); - gdisp_lld_write_stop(g); + } + drawpixel(g); } +#else + #define drawpixel_clip(g) drawpixel(g) #endif // fillarea(g) // Parameters: x,y cx,cy and color // Alters: nothing // Note: This is not clipped -// Resets the streaming area -// if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. -#if GDISP_HARDWARE_FILLS - // Best is hardware accelerated area fill - #define fillarea(g) gdisp_lld_fill_area(g) -#elif GDISP_HARDWARE_STREAM_WRITE - // Next best is hardware streaming - static INLINE void fillarea(GDisplay *g) { - uint32_t area; +// Resets the streaming area if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. +static INLINE void fillarea(GDisplay *g) { - area = (uint32_t)g->p.cx * g->p.cy; - - #if GDISP_HARDWARE_STREAM_POS - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } + // Best is hardware accelerated area fill + #if GDISP_HARDWARE_FILLS + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) #endif + { + gdisp_lld_fill_area(g); + return; + } + #endif - gdisp_lld_write_start(g); - #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(g); + // Next best is hardware streaming + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) #endif - for(; area; area--) - gdisp_lld_write_color(g); - gdisp_lld_write_stop(g); - } -#else - // Worst is drawing pixels - static INLINE void fillarea(GDisplay *g) { - coord_t x0, y0, x1, y1; - - x0 = g->p.x; - y0 = g->p.y; - x1 = g->p.x + g->p.cx; - y1 = g->p.y + g->p.cy; - for(; g->p.y < y1; g->p.y++, g->p.x = x0) - for(; g->p.x < x1; g->p.x++) - gdisp_lld_draw_pixel(g); - g->p.y = y0; - } -#endif + { + uint32_t area; -#if NEED_CLIPPING - #define TEST_CLIP_AREA(g) \ - if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; } \ - if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; } \ - if ((g)->p.x + (g)->p.cx > (g)->clipx1) (g)->p.cx = (g)->clipx1 - (g)->p.x; \ - if ((g)->p.y + (g)->p.cy > (g)->clipy1) (g)->p.cy = (g)->clipy1 - (g)->p.y; \ - if ((g)->p.cx > 0 && (g)->p.cy > 0) -#else - #define TEST_CLIP_AREA(g) -#endif + #if GDISP_HARDWARE_STREAM_POS + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif + + area = (uint32_t)g->p.cx * g->p.cy; + gdisp_lld_write_start(g); + #if GDISP_HARDWARE_STREAM_POS + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) + #endif + gdisp_lld_write_pos(g); + #endif + for(; area; area--) + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); + return; + } + #endif + + // Worst is pixel drawing + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + coord_t x0, y0, x1, y1; + + x0 = g->p.x; + y0 = g->p.y; + x1 = g->p.x + g->p.cx; + y1 = g->p.y + g->p.cy; + for(; g->p.y < y1; g->p.y++, g->p.x = x0) + for(; g->p.x < x1; g->p.x++) + gdisp_lld_draw_pixel(g); + g->p.y = y0; + return; + } + #endif +} // Parameters: x,y and x1 // Alters: x,y x1,y1 cx,cy @@ -186,10 +241,15 @@ static void hline_clip(GDisplay *g) { // Clipping #if NEED_CLIPPING - if (g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; - if (g->p.x < g->clipx0) g->p.x = g->clipx0; - if (g->p.x1 >= g->clipx1) g->p.x1 = g->clipx1 - 1; - if (g->p.x1 < g->p.x) return; + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (!g->vmt->setclip) + #endif + { + if (g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; + if (g->p.x < g->clipx0) g->p.x = g->clipx0; + if (g->p.x1 >= g->clipx1) g->p.x1 = g->clipx1 - 1; + if (g->p.x1 < g->p.x) return; + } #endif // This is an optimization for the point case. It is only worthwhile however if we @@ -197,48 +257,64 @@ static void hline_clip(GDisplay *g) { #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) // Is this a point if (g->p.x == g->p.x1) { - #if GDISP_HARDWARE_DRAWPIXEL - // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(g); - #elif GDISP_HARDWARE_STREAM_POS - // Next best is cursor based streaming - if (!(g->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(g); - gdisp_lld_write_pos(g); - gdisp_lld_write_color(g); - #else - // Worst is streaming - g->p.cx = g->p.cy = 1; - gdisp_lld_write_start(g); - gdisp_lld_write_color(g); - gdisp_lld_write_stop(g); - #endif + drawpixel(g); return; } #endif + // Best is hardware accelerated area fill #if GDISP_HARDWARE_FILLS - // Best is hardware accelerated area fill - g->p.cx = g->p.x1 - g->p.x + 1; - g->p.cy = 1; - gdisp_lld_fill_area(g); - #elif GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - // Next best is cursor based streaming - if (!(g->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(g); - gdisp_lld_write_pos(g); - do { gdisp_lld_write_color(g); } while(g->p.cx--); - #elif GDISP_HARDWARE_STREAM_WRITE - // Next best is streaming - g->p.cx = g->p.x1 - g->p.x + 1; - g->p.cy = 1; - gdisp_lld_write_start(g); - do { gdisp_lld_write_color(g); } while(g->p.cx--); - gdisp_lld_write_stop(g); - #else - // Worst is drawing pixels - for(; g->p.x <= g->p.x1; g->p.x++) - gdisp_lld_draw_pixel(g); + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) + #endif + { + g->p.cx = g->p.x1 - g->p.x + 1; + g->p.cy = 1; + gdisp_lld_fill_area(g); + return; + } + #endif + + // Next best is cursor based streaming + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) + #endif + { + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + do { gdisp_lld_write_color(g); } while(g->p.cx--); + return; + } + #endif + + // Next best is streaming + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_POS != TRUE && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) + #endif + { + g->p.cx = g->p.x1 - g->p.x + 1; + g->p.cy = 1; + gdisp_lld_write_start(g); + do { gdisp_lld_write_color(g); } while(g->p.cx--); + gdisp_lld_write_stop(g); + return; + } + #endif + + // Worst is drawing pixels + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + for(; g->p.x <= g->p.x1; g->p.x++) + gdisp_lld_draw_pixel(g); + return; + } #endif } @@ -252,10 +328,15 @@ static void vline_clip(GDisplay *g) { // Clipping #if NEED_CLIPPING - if (g->p.x < g->clipx0 || g->p.x >= g->clipx1) return; - if (g->p.y < g->clipy0) g->p.y = g->clipy0; - if (g->p.y1 >= g->clipy1) g->p.y1 = g->clipy1 - 1; - if (g->p.y1 < g->p.y) return; + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (!g->vmt->setclip) + #endif + { + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1) return; + if (g->p.y < g->clipy0) g->p.y = g->clipy0; + if (g->p.y1 >= g->clipy1) g->p.y1 = g->clipy1 - 1; + if (g->p.y1 < g->p.y) return; + } #endif // This is an optimization for the point case. It is only worthwhile however if we @@ -263,51 +344,62 @@ static void vline_clip(GDisplay *g) { #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) || (GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE) // Is this a point if (g->p.y == g->p.y1) { - #if GDISP_HARDWARE_DRAWPIXEL - // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(g); - #elif GDISP_HARDWARE_STREAM_POS - // Next best is cursor based streaming - if (!(g->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(g); - gdisp_lld_write_pos(g); - gdisp_lld_write_color(g); - #else - // Worst is streaming - g->p.cx = g->p.cy = 1; - gdisp_lld_write_start(g); - gdisp_lld_write_color(g); - gdisp_lld_write_stop(g); - #endif + drawpixel(g); return; } #endif + // Best is hardware accelerated area fill #if GDISP_HARDWARE_FILLS - // Best is hardware accelerated area fill - g->p.cy = g->p.y1 - g->p.y + 1; - g->p.cx = 1; - gdisp_lld_fill_area(g); - #elif GDISP_HARDWARE_STREAM_WRITE - // Next best is streaming - #if GDISP_HARDWARE_STREAM_POS - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) #endif - g->p.cy = g->p.y1 - g->p.y + 1; - g->p.cx = 1; - gdisp_lld_write_start(g); - #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(g); + { + g->p.cy = g->p.y1 - g->p.y + 1; + g->p.cx = 1; + gdisp_lld_fill_area(g); + return; + } + #endif + + // Next best is streaming + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) #endif - do { gdisp_lld_write_color(g); } while(g->p.cy--); - gdisp_lld_write_stop(g); - #else - // Worst is drawing pixels - for(; g->p.y <= g->p.y1; g->p.y++) - gdisp_lld_draw_pixel(g); + { + #if GDISP_HARDWARE_STREAM_POS + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; + } + #endif + g->p.cy = g->p.y1 - g->p.y + 1; + g->p.cx = 1; + gdisp_lld_write_start(g); + #if GDISP_HARDWARE_STREAM_POS + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) + #endif + gdisp_lld_write_pos(g); + #endif + do { gdisp_lld_write_color(g); } while(g->p.cy--); + gdisp_lld_write_stop(g); + return; + } + #endif + + // Worst is drawing pixels + #if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + for(; g->p.y <= g->p.y1; g->p.y++) + gdisp_lld_draw_pixel(g); + return; + } #endif } @@ -390,7 +482,6 @@ static void line_clip(GDisplay *g) { #if GDISP_STARTUP_LOGO_TIMEOUT > 0 static void StatupLogoDisplay(GDisplay *g) { - gdispGClear(g, Black); gdispGFillArea(g, g->g.Width/4, g->g.Height/4, g->g.Width/2, g->g.Height/2, Blue); } #endif @@ -420,31 +511,47 @@ void _gdispInit(void) { MUTEX_ENTER(g); g->flags = 0; gdisp_lld_init(g, i); + + // Set the initial clipping region #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + + // Best is hardware clipping #if GDISP_HARDWARE_CLIP - g->p.x = x; - g->p.y = y; - g->p.cx = cx; - g->p.cy = cy; - gdisp_lld_set_clip(g); - #else - g->clipx0 = 0; - g->clipy0 = 0; - g->clipx1 = g->g.Width; - g->clipy1 = g->g.Height; + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (g->vmt->setclip) + #endif + { + g->p.x = 0; + g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + gdisp_lld_set_clip(g); + } + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + else + #endif + #endif + + // Worst is software clipping + #if GDISP_HARDWARE_CLIP != TRUE + { + g->clipx0 = 0; + g->clipy0 = 0; + g->clipx1 = g->g.Width; + g->clipy1 = g->g.Height; + } #endif #endif MUTEX_EXIT(g); + gdispGClear(g, GDISP_STARTUP_COLOR); #if GDISP_STARTUP_LOGO_TIMEOUT > 0 StatupLogoDisplay(g); - #else - gdispGClear(g, Black); #endif } #if GDISP_STARTUP_LOGO_TIMEOUT > 0 gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) - gdispGClear(g, Black); + gdispGClear(g, GDISP_STARTUP_COLOR); #endif } @@ -463,6 +570,9 @@ void gdispSetDisplay(GDisplay *g) { MUTEX_ENTER(g); #if NEED_CLIPPING + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (!g->vmt->setclip) + #endif // Test if the area is valid - if not then exit if (x < g->clipx0 || x+cx > g->clipx1 || y < g->clipy0 || y+cy > g->clipy1) { MUTEX_EXIT(g); @@ -472,28 +582,45 @@ void gdispSetDisplay(GDisplay *g) { g->flags |= GDISP_FLG_INSTREAM; + // Best is hardware streaming #if GDISP_HARDWARE_STREAM_WRITE - // Best is hardware streaming - g->p.x = x; - g->p.y = y; - g->p.cx = cx; - g->p.cy = cy; - gdisp_lld_write_start(g); - #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(g); - #endif - #else - // Worst - save the parameters and use pixel drawing - - // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position, cx = bufpos - g->p.x1 = g->p.x = x; - g->p.y1 = g->p.y = y; - g->p.x2 = x + cx; - g->p.y2 = y + cy; - #if (GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS) || GDISP_HARDWARE_FILLS - g->p.cx = 0; - g->p.cy = 1; + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) #endif + { + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_write_start(g); + #if GDISP_HARDWARE_STREAM_POS + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) + #endif + gdisp_lld_write_pos(g); + #endif + return; + } + #endif + + // Worst - save the parameters and use pixel drawing and/or area fills + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position, cx = bufpos + g->p.x1 = g->p.x = x; + g->p.y1 = g->p.y = y; + g->p.x2 = x + cx; + g->p.y2 = y + cy; + #if (GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS) || GDISP_HARDWARE_FILLS + g->p.cx = 0; + g->p.cy = 1; + #endif + return; + } #endif // Don't release the mutex as gdispStreamEnd() will do that. @@ -510,28 +637,26 @@ void gdispSetDisplay(GDisplay *g) { if (!(g->flags & GDISP_FLG_INSTREAM)) return; + // Best is hardware streaming #if GDISP_HARDWARE_STREAM_WRITE - // Best is hardware streaming - g->p.color = color; - gdisp_lld_write_color(g); - #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - g->linebuf[g->p.cx++] = color; - if (g->p.cx >= GDISP_LINEBUF_SIZE) { - sx1 = g->p.x1; - sy1 = g->p.y1; - g->p.x1 = 0; - g->p.y1 = 0; - g->p.ptr = (void *)g->linebuf; - gdisp_lld_blit_area(g); - g->p.x1 = sx1; - g->p.y1 = sy1; - g->p.x += g->p.cx; - g->p.cx = 0; + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) + #endif + { + g->p.color = color; + gdisp_lld_write_color(g); + return; } + #endif - // Just wrap at end-of-line and end-of-buffer - if (g->p.x+g->p.cx >= g->p.x2) { - if (g->p.cx) { + // Next best is to use bitfills with our line buffer + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS + #if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT + if (g->vmt->blit) + #endif + { + g->linebuf[g->p.cx++] = color; + if (g->p.cx >= GDISP_LINEBUF_SIZE) { sx1 = g->p.x1; sy1 = g->p.y1; g->p.x1 = 0; @@ -540,49 +665,83 @@ void gdispSetDisplay(GDisplay *g) { gdisp_lld_blit_area(g); g->p.x1 = sx1; g->p.y1 = sy1; + g->p.x += g->p.cx; g->p.cx = 0; } - g->p.x = g->p.x1; - if (++g->p.y >= g->p.y2) - g->p.y = g->p.y1; - } - #elif GDISP_HARDWARE_FILLS - // Only slightly better than drawing pixels is to look for runs and use fill area - if (!g->p.cx || g->p.color == color) { - g->p.cx++; - g->p.color = color; - } else { - if (g->p.cx == 1) - gdisp_lld_draw_pixel(g); - else - gdisp_lld_fill_area(g); - g->p.x += g->p.cx; - g->p.color = color; - g->p.cx = 1; + + // Just wrap at end-of-line and end-of-buffer + if (g->p.x+g->p.cx >= g->p.x2) { + if (g->p.cx) { + sx1 = g->p.x1; + sy1 = g->p.y1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + g->p.x1 = sx1; + g->p.y1 = sy1; + g->p.cx = 0; + } + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; + } } - // Just wrap at end-of-line and end-of-buffer - if (g->p.x+g->p.cx >= g->p.x2) { - if (g->p.cx) { + #endif + + // Only slightly better than drawing pixels is to look for runs and use fillarea + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS + // We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) + #endif + { + if (!g->p.cx || g->p.color == color) { + g->p.cx++; + g->p.color = color; + } else { if (g->p.cx == 1) gdisp_lld_draw_pixel(g); else gdisp_lld_fill_area(g); - g->p.cx = 0; + g->p.x += g->p.cx; + g->p.color = color; + g->p.cx = 1; + } + // Just wrap at end-of-line and end-of-buffer + if (g->p.x+g->p.cx >= g->p.x2) { + if (g->p.cx) { + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); + else + gdisp_lld_fill_area(g); + g->p.cx = 0; + } + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } - g->p.x = g->p.x1; - if (++g->p.y >= g->p.y2) - g->p.y = g->p.y1; + return; } - #else - // Worst is using pixel drawing - g->p.color = color; - gdisp_lld_draw_pixel(g); + #endif + + // Worst is using pixel drawing + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + g->p.color = color; + gdisp_lld_draw_pixel(g); - // Just wrap at end-of-line and end-of-buffer - if (++g->p.x >= g->p.x2) { - g->p.x = g->p.x1; - if (++g->p.y >= g->p.y2) - g->p.y = g->p.y1; + // Just wrap at end-of-line and end-of-buffer + if (++g->p.x >= g->p.x2) { + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; + } + return; } #endif } @@ -592,25 +751,54 @@ void gdispSetDisplay(GDisplay *g) { if (!(g->flags & GDISP_FLG_INSTREAM)) return; + // Clear the flag + g->flags &= ~GDISP_FLG_INSTREAM; + + // The cleanup below must match the streaming code above. + #if GDISP_HARDWARE_STREAM_WRITE - gdisp_lld_write_stop(g); - #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - if (g->p.cx) { - g->p.x1 = 0; - g->p.y1 = 0; - g->p.ptr = (void *)g->linebuf; - gdisp_lld_blit_area(g); + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) + #endif + { + gdisp_lld_write_stop(g); + MUTEX_EXIT(g); + return; } - #elif GDISP_HARDWARE_FILLS - if (g->p.cx) { - if (g->p.cx == 1) - gdisp_lld_draw_pixel(g); - else - gdisp_lld_fill_area(g); + #endif + + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS + #if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT + if (g->vmt->blit) + #endif + { + if (g->p.cx) { + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + } + MUTEX_EXIT(g); + return; + } + #endif + + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS + // We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) + #endif + { + if (g->p.cx) { + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); + else + gdisp_lld_fill_area(g); + } + MUTEX_EXIT(g); + return; } #endif - g->flags &= ~GDISP_FLG_INSTREAM; - MUTEX_EXIT(g); } #endif @@ -650,42 +838,79 @@ void gdispGClear(GDisplay *g, color_t color) { // Note - clear() ignores the clipping area. It clears the screen. MUTEX_ENTER(g); + // Best is hardware accelerated clear #if GDISP_HARDWARE_CLEARS - // Best is hardware accelerated clear - g->p.color = color; - gdisp_lld_clear(g); - #elif GDISP_HARDWARE_FILLS - // Next best is hardware accelerated area fill - g->p.x = g->p.y = 0; - g->p.cx = g->g.Width; - g->p.cy = g->g.Height; - g->p.color = color; - gdisp_lld_fill_area(g); - #elif GDISP_HARDWARE_STREAM_WRITE - // Next best is streaming - uint32_t area; - - g->p.x = g->p.y = 0; - g->p.cx = g->g.Width; - g->p.cy = g->g.Height; - g->p.color = color; - area = (uint32_t)g->p.cx * g->p.cy; + #if GDISP_HARDWARE_CLEARS == HARDWARE_AUTODETECT + if (g->vmt->clear) + #endif + { + g->p.color = color; + gdisp_lld_clear(g); + MUTEX_EXIT(g); + return; + } + #endif - gdisp_lld_write_start(g); - #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(g); + // Next best is hardware accelerated area fill + #if GDISP_HARDWARE_CLEARS != TRUE && GDISP_HARDWARE_FILLS + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) #endif - for(; area; area--) - gdisp_lld_write_color(g); - gdisp_lld_write_stop(g); - #else - // Worst is drawing pixels - g->p.color = color; - for(g->p.y = 0; g->p.y < g->g.Height; g->p.y++) - for(g->p.x = 0; g->p.x < g->g.Width; g->p.x++) - gdisp_lld_draw_pixel(g); + { + g->p.x = g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + g->p.color = color; + gdisp_lld_fill_area(g); + MUTEX_EXIT(g); + return; + } + #endif + + // Next best is streaming + #if GDISP_HARDWARE_CLEARS != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) + #endif + { + uint32_t area; + + g->p.x = g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + g->p.color = color; + area = (uint32_t)g->p.cx * g->p.cy; + + gdisp_lld_write_start(g); + #if GDISP_HARDWARE_STREAM_POS + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) + #endif + gdisp_lld_write_pos(g); + #endif + for(; area; area--) + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); + MUTEX_EXIT(g); + return; + } + #endif + + // Worst is drawing pixels + #if GDISP_HARDWARE_CLEARS != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + g->p.color = color; + for(g->p.y = 0; g->p.y < g->g.Height; g->p.y++) + for(g->p.x = 0; g->p.x < g->g.Width; g->p.x++) + gdisp_lld_draw_pixel(g); + MUTEX_EXIT(g); + return; + } #endif - MUTEX_EXIT(g); } void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { @@ -705,113 +930,166 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c MUTEX_ENTER(g); #if NEED_CLIPPING - // This is a different cliping to fillarea(g) as it needs to take into account srcx,srcy - if (x < g->clipx0) { cx -= g->clipx0 - x; srcx += g->clipx0 - x; x = g->clipx0; } - if (y < g->clipy0) { cy -= g->clipy0 - y; srcy += g->clipy0 - x; y = g->clipy0; } - if (x+cx > g->clipx1) cx = g->clipx1 - x; - if (y+cy > g->clipy1) cy = g->clipy1 - y; - if (srcx+cx > srccx) cx = srccx - srcx; - if (cx <= 0 || cy <= 0) { MUTEX_EXIT(g); return; } + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (!g->vmt->setclip) + #endif + { + // This is a different cliping to fillarea(g) as it needs to take into account srcx,srcy + if (x < g->clipx0) { cx -= g->clipx0 - x; srcx += g->clipx0 - x; x = g->clipx0; } + if (y < g->clipy0) { cy -= g->clipy0 - y; srcy += g->clipy0 - x; y = g->clipy0; } + if (x+cx > g->clipx1) cx = g->clipx1 - x; + if (y+cy > g->clipy1) cy = g->clipy1 - y; + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0) { MUTEX_EXIT(g); return; } + } #endif + // Best is hardware bitfills #if GDISP_HARDWARE_BITFILLS - // Best is hardware bitfills - g->p.x = x; - g->p.y = y; - g->p.cx = cx; - g->p.cy = cy; - g->p.x1 = srcx; - g->p.y1 = srcy; - g->p.x2 = srccx; - g->p.ptr = (void *)buffer; - gdisp_lld_blit_area(g); - #elif GDISP_HARDWARE_STREAM_WRITE - // Next best is hardware streaming - - // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap - buffer += srcy*srccx+srcx; - srcx = x + cx; - srcy = y + cy; - srccx -= cx; + #if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT + if (g->vmt->blit) + #endif + { + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.x1 = srcx; + g->p.y1 = srcy; + g->p.x2 = srccx; + g->p.ptr = (void *)buffer; + gdisp_lld_blit_area(g); + MUTEX_EXIT(g); + return; + } + #endif - g->p.x = x; - g->p.y = y; - g->p.cx = cx; - g->p.cy = cy; - gdisp_lld_write_start(g); - #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(g); + // Next best is hardware streaming + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) #endif - for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { - for(g->p.x = x; g->p.x < srcx; g->p.x++) { - g->p.color = *buffer++; - gdisp_lld_write_color(g); + { + // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap + buffer += srcy*srccx+srcx; + srcx = x + cx; + srcy = y + cy; + srccx -= cx; + + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_write_start(g); + #if GDISP_HARDWARE_STREAM_POS + #if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT + if (g->vmt->writepos) + #endif + gdisp_lld_write_pos(g); + #endif + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x = x; g->p.x < srcx; g->p.x++) { + g->p.color = *buffer++; + gdisp_lld_write_color(g); + } } + gdisp_lld_write_stop(g); + MUTEX_EXIT(g); + return; } - gdisp_lld_write_stop(g); - #elif GDISP_HARDWARE_FILLS - // Only slightly better than drawing pixels is to look for runs and use fill area - - // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap - buffer += srcy*srccx+srcx; - srcx = x + cx; - srcy = y + cy; - srccx -= cx; - - g->p.cy = 1; - for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { - for(g->p.x=x; g->p.x < srcx; g->p.x += g->p.cx) { - g->p.cx=1; - g->p.color = *buffer++; - while(g->p.x+g->p.cx < srcx && *buffer == g->p.color) { - g->p.cx++; - buffer++; - } - if (g->p.cx == 1) { - gdisp_lld_draw_pixel(g); - } else { - gdisp_lld_fill_area(g); + #endif + + // Only slightly better than drawing pixels is to look for runs and use fill area + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS + // We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) + #endif + { + // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap + buffer += srcy*srccx+srcx; + srcx = x + cx; + srcy = y + cy; + srccx -= cx; + + g->p.cy = 1; + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x=x; g->p.x < srcx; g->p.x += g->p.cx) { + g->p.cx=1; + g->p.color = *buffer++; + while(g->p.x+g->p.cx < srcx && *buffer == g->p.color) { + g->p.cx++; + buffer++; + } + if (g->p.cx == 1) { + gdisp_lld_draw_pixel(g); + } else { + gdisp_lld_fill_area(g); + } } } + MUTEX_EXIT(g); + return; } - #else - // Worst is drawing pixels - - // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap - buffer += srcy*srccx+srcx; - srcx = x + cx; - srcy = y + cy; - srccx -= cx; + #endif - for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { - for(g->p.x=x; g->p.x < srcx; g->p.x++) { - g->p.color = *buffer++; - gdisp_lld_draw_pixel(g); + // Worst is drawing pixels + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + // Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap + buffer += srcy*srccx+srcx; + srcx = x + cx; + srcy = y + cy; + srccx -= cx; + + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x=x; g->p.x < srcx; g->p.x++) { + g->p.color = *buffer++; + gdisp_lld_draw_pixel(g); + } } + MUTEX_EXIT(g); + return; } #endif - MUTEX_EXIT(g); } #if GDISP_NEED_CLIP void gdispGSetClip(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { MUTEX_ENTER(g); + + // Best is using hardware clipping #if GDISP_HARDWARE_CLIP - // Best is using hardware clipping - g->p.x = x; - g->p.y = y; - g->p.cx = cx; - g->p.cy = cy; - gdisp_lld_set_clip(g); - #else - // Worst is using software clipping - if (x < 0) { cx += x; x = 0; } - if (y < 0) { cy += y; y = 0; } - if (cx <= 0 || cy <= 0 || x >= g->g.Width || y >= g->g.Height) { MUTEX_EXIT(g); return; } - g->clipx0 = x; - g->clipy0 = y; - g->clipx1 = x+cx; if (g->clipx1 > g->g.Width) g->clipx1 = g->g.Width; - g->clipy1 = y+cy; if (g->clipy1 > g->g.Height) g->clipy1 = g->g.Height; + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (g->vmt->setclip) + #endif + { + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_set_clip(g); + } + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + else + #endif + #endif + + // Worst is using software clipping + #if GDISP_HARDWARE_CLIP != TRUE + { + if (x < 0) { cx += x; x = 0; } + if (y < 0) { cy += y; y = 0; } + if (cx <= 0 || cy <= 0 || x >= g->g.Width || y >= g->g.Height) { MUTEX_EXIT(g); return; } + g->clipx0 = x; + g->clipy0 = y; + g->clipx1 = x+cx; if (g->clipx1 > g->g.Width) g->clipx1 = g->g.Width; + g->clipy1 = y+cy; if (g->clipy1 > g->g.Height) g->clipy1 = g->g.Height; + } #endif MUTEX_EXIT(g); } @@ -1733,26 +2011,43 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c /* Always synchronous as it must return a value */ MUTEX_ENTER(g); #if GDISP_HARDWARE_PIXELREAD - // Best is direct pixel read - g->p.x = x; - g->p.y = y; - c = gdisp_lld_get_pixel_color(g); - #elif GDISP_HARDWARE_STREAM_READ - // Next best is hardware streaming - g->p.x = x; - g->p.y = y; - g->p.cx = 1; - g->p.cy = 1; - gdisp_lld_read_start(g); - c = gdisp_lld_read_color(g); - gdisp_lld_read_stop(g); - #else - // Worst is "not possible" - #error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display" + #if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT + if (g->vmt->get) + #endif + { + // Best is direct pixel read + g->p.x = x; + g->p.y = y; + c = gdisp_lld_get_pixel_color(g); + MUTEX_EXIT(g); + return c; + } + #endif + #if GDISP_HARDWARE_PIXELREAD != TRUE && GDISP_HARDWARE_STREAM_READ + #if GDISP_HARDWARE_STREAM_READ == HARDWARE_AUTODETECT + if (g->vmt->readcolor) + #endif + { + // Next best is hardware streaming + g->p.x = x; + g->p.y = y; + g->p.cx = 1; + g->p.cy = 1; + gdisp_lld_read_start(g); + c = gdisp_lld_read_color(g); + gdisp_lld_read_stop(g); + MUTEX_EXIT(g); + return c; + } + #endif + #if GDISP_HARDWARE_PIXELREAD != TRUE && GDISP_HARDWARE_STREAM_READ != TRUE + #if !GDISP_HARDWARE_PIXELREAD && !GDISP_HARDWARE_STREAM_READ + // Worst is "not possible" + #error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display" + #endif + MUTEX_EXIT(g); + return 0; #endif - MUTEX_EXIT(g); - - return c; } #endif @@ -1765,11 +2060,16 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c MUTEX_ENTER(g); #if NEED_CLIPPING - if (x < g->clipx0) { cx -= g->clipx0 - x; x = g->clipx0; } - if (y < g->clipy0) { cy -= g->clipy0 - y; y = g->clipy0; } - if (!lines || cx <= 0 || cy <= 0 || x >= g->clipx1 || y >= g->clipy1) { MUTEX_EXIT(g); return; } - if (x+cx > g->clipx1) cx = g->clipx1 - x; - if (y+cy > g->clipy1) cy = g->clipy1 - y; + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (!g->vmt->setclip) + #endif + { + if (x < g->clipx0) { cx -= g->clipx0 - x; x = g->clipx0; } + if (y < g->clipy0) { cy -= g->clipy0 - y; y = g->clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= g->clipx1 || y >= g->clipy1) { MUTEX_EXIT(g); return; } + if (x+cx > g->clipx1) cx = g->clipx1 - x; + if (y+cy > g->clipy1) cy = g->clipy1 - y; + } #endif abslines = lines < 0 ? -lines : lines; @@ -1777,95 +2077,159 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c abslines = cy; cy = 0; } else { + // Best is hardware scroll #if GDISP_HARDWARE_SCROLL - g->p.x = x; - g->p.y = y; - g->p.cx = cx; - g->p.cy = cy; - g->p.y1 = lines; - g->p.color = bgcolor; - gdisp_lld_vertical_scroll(g); - cy -= abslines; + #if GDISP_HARDWARE_SCROLL == HARDWARE_AUTODETECT + if (g->vmt->vscroll) + #endif + { + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.y1 = lines; + g->p.color = bgcolor; + gdisp_lld_vertical_scroll(g); + cy -= abslines; + } + #if GDISP_HARDWARE_SCROLL == HARDWARE_AUTODETECT + else + #endif #elif GDISP_LINEBUF_SIZE == 0 #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support and GDISP_LINEBUF_SIZE is zero." - #else - cy -= abslines; - if (lines < 0) { - fy = y+cy-1; - dy = -1; - } else { - fy = y; - dy = 1; - } - // Move the screen - one line at a time - for(i = 0; i < cy; i++, fy += dy) { - - // Handle where the buffer is smaller than a line - for(ix=0; ix < cx; ix += GDISP_LINEBUF_SIZE) { - - // Calculate the data we can move in one operation - fx = cx - ix; - if (fx > GDISP_LINEBUF_SIZE) - fx = GDISP_LINEBUF_SIZE; - - // Read one line of data from the screen - #if GDISP_HARDWARE_STREAM_READ - // Best is hardware streaming - g->p.x = x+ix; - g->p.y = fy+lines; - g->p.cx = fx; - g->p.cy = 1; - gdisp_lld_read_start(g); - for(j=0; j < fx; j++) - g->linebuf[j] = gdisp_lld_read_color(g); - gdisp_lld_read_stop(g); - #elif GDISP_HARDWARE_PIXELREAD - // Next best is single pixel reads - for(j=0; j < fx; j++) { - g->p.x = x+ix+j; - g->p.y = fy+lines; - g->linebuf[j] = gdisp_lld_get_pixel_color(g); - } - #else + #endif + + // Scroll Emulation + #if GDISP_HARDWARE_SCROLL != TRUE + { + cy -= abslines; + if (lines < 0) { + fy = y+cy-1; + dy = -1; + } else { + fy = y; + dy = 1; + } + // Move the screen - one line at a time + for(i = 0; i < cy; i++, fy += dy) { + + // Handle where the buffer is smaller than a line + for(ix=0; ix < cx; ix += GDISP_LINEBUF_SIZE) { + + // Calculate the data we can move in one operation + fx = cx - ix; + if (fx > GDISP_LINEBUF_SIZE) + fx = GDISP_LINEBUF_SIZE; + + // Read one line of data from the screen + + // Best line read is hardware streaming + #if GDISP_HARDWARE_STREAM_READ + #if GDISP_HARDWARE_STREAM_READ == HARDWARE_AUTODETECT + if (g->vmt->readstart) + #endif + { + g->p.x = x+ix; + g->p.y = fy+lines; + g->p.cx = fx; + g->p.cy = 1; + gdisp_lld_read_start(g); + for(j=0; j < fx; j++) + g->linebuf[j] = gdisp_lld_read_color(g); + gdisp_lld_read_stop(g); + } + #if GDISP_HARDWARE_STREAM_READ == HARDWARE_AUTODETECT + else + #endif + #endif + + // Next best line read is single pixel reads + #if GDISP_HARDWARE_STREAM_READ != TRUE && GDISP_HARDWARE_PIXELREAD + #if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT + if (g->vmt->get) + #endif + { + for(j=0; j < fx; j++) { + g->p.x = x+ix+j; + g->p.y = fy+lines; + g->linebuf[j] = gdisp_lld_get_pixel_color(g); + } + } + #if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT + else + // Worst is "not possible" + return; + #endif + #endif + // Worst is "not possible" - #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support for scrolling or reading pixels." - #endif + #if !GDISP_HARDWARE_STREAM_READ && !GDISP_HARDWARE_PIXELREAD + #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support for scrolling or reading pixels." + #endif - // Write that line to the new location - #if GDISP_HARDWARE_BITFILLS - // Best is hardware bitfills - g->p.x = x+ix; - g->p.y = fy; - g->p.cx = fx; - g->p.cy = 1; - g->p.x1 = 0; - g->p.y1 = 0; - g->p.x2 = fx; - g->p.ptr = (void *)g->linebuf; - gdisp_lld_blit_area(g); - #elif GDISP_HARDWARE_STREAM_WRITE - // Next best is hardware streaming - g->p.x = x+ix; - g->p.y = fy; - g->p.cx = fx; - g->p.cy = 1; - gdisp_lld_write_start(g); - #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(g); + // Write that line to the new location + + // Best line write is hardware bitfills + #if GDISP_HARDWARE_BITFILLS + #if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT + if (g->vmt->blit) + #endif + { + g->p.x = x+ix; + g->p.y = fy; + g->p.cx = fx; + g->p.cy = 1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.x2 = fx; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + } + #if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT + else + #endif #endif - for(j = 0; j < fx; j++) { - g->p.color = g->linebuf[j]; - gdisp_lld_write_color(g); - } - gdisp_lld_write_stop(g); - #else - // Worst is drawing pixels - g->p.y = fy; - for(g->p.x = x+ix, j = 0; j < fx; g->p.x++, j++) { - g->p.color = g->linebuf[j]; - gdisp_lld_draw_pixel(g); - } - #endif + + // Next best line write is hardware streaming + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + if (g->vmt->writestart) + #endif + { + g->p.x = x+ix; + g->p.y = fy; + g->p.cx = fx; + g->p.cy = 1; + gdisp_lld_write_start(g); + #if GDISP_HARDWARE_STREAM_POS + gdisp_lld_write_pos(g); + #endif + for(j = 0; j < fx; j++) { + g->p.color = g->linebuf[j]; + gdisp_lld_write_color(g); + } + gdisp_lld_write_stop(g); + } + #if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT + else + #endif + #endif + + // Worst line write is drawing pixels + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming + //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT + // if (g->vmt->pixel) + //#endif + { + g->p.y = fy; + for(g->p.x = x+ix, j = 0; j < fx; g->p.x++, j++) { + g->p.color = g->linebuf[j]; + gdisp_lld_draw_pixel(g); + } + } + #endif + } } } #endif @@ -1885,25 +2249,41 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c #if GDISP_NEED_CONTROL #if GDISP_HARDWARE_CONTROL void gdispGControl(GDisplay *g, unsigned what, void *value) { + #if GDISP_HARDWARE_CONTROL == HARDWARE_AUTODETECT + if (!g->vmt->control) + return; + #endif MUTEX_ENTER(g); g->p.x = what; g->p.ptr = value; gdisp_lld_control(g); #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION if (what == GDISP_CONTROL_ORIENTATION) { + // Best is hardware clipping #if GDISP_HARDWARE_CLIP - // Best is hardware clipping - g->p.x = 0; - g->p.y = 0; - g->p.cx = g->g.Width; - g->p.cy = g->g.Height; - gdisp_lld_set_clip(g); - #else - // Worst is software clipping - g->clipx0 = 0; - g->clipy0 = 0; - g->clipx1 = g->g.Width; - g->clipy1 = g->g.Height; + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + if (g->vmt->setclip) + #endif + { + g->p.x = 0; + g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + gdisp_lld_set_clip(g); + } + #if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT + else + #endif + #endif + + // Worst is software clipping + #if GDISP_HARDWARE_CLIP != TRUE + { + g->clipx0 = 0; + g->clipy0 = 0; + g->clipx1 = g->g.Width; + g->clipy1 = g->g.Height; + } #endif } #endif @@ -1923,6 +2303,10 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c void *gdispGQuery(GDisplay *g, unsigned what) { void *res; + #if GDISP_HARDWARE_QUERY == HARDWARE_AUTODETECT + if (!g->vmt->query) + return -1; + #endif MUTEX_ENTER(g); g->p.x = (coord_t)what; res = gdisp_lld_query(g); -- cgit v1.2.3 From 87a6af81f4edd9f638238d785aae716749a7fc13 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 19 Oct 2013 15:36:05 +1000 Subject: Change to gdisp low level driver API. Display number is now in the GDriver structure (It was required for a Nokia driver). --- src/gdisp/gdisp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index ef388df5..66cd59fd 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -493,9 +493,9 @@ static void line_clip(GDisplay *g) { /* Our module initialiser */ void _gdispInit(void) { GDisplay *g; - unsigned i; + uint16_t i; #if GDISP_TOTAL_CONTROLLERS > 1 - unsigned j; + uint16_t j; #endif @@ -504,13 +504,17 @@ void _gdispInit(void) { for(g = GDisplayArray, j=0; j < GDISP_TOTAL_CONTROLLERS; j++) for(i = 0; i < DisplayCountList[j]; g++, i++) { g->vmt = ControllerList[j]; + g->systemdisplay = j*GDISP_TOTAL_CONTROLLERS+i; + g->controllerdisplay = i; #else for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) { + g->systemdisplay = i; + g->controllerdisplay = i; #endif MUTEX_INIT(g); MUTEX_ENTER(g); g->flags = 0; - gdisp_lld_init(g, i); + gdisp_lld_init(g); // Set the initial clipping region #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP -- cgit v1.2.3 From 2bd47585698b5977ab873d63af4de4dc36f9ec5f Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 20 Oct 2013 21:58:52 +0200 Subject: compiler warnings --- src/gdisp/image_gif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gdisp') diff --git a/src/gdisp/image_gif.c b/src/gdisp/image_gif.c index 502fa3ad..d067bd0f 100644 --- a/src/gdisp/image_gif.c +++ b/src/gdisp/image_gif.c @@ -823,7 +823,7 @@ baddatacleanup: gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { gdispImagePrivate * priv; imgdecode * decode; - uint8_t * q; + uint8_t * q = 0; coord_t mx, my, fx, fy; uint16_t cnt, gcnt; uint8_t col; -- cgit v1.2.3 From 0b9db701a1d52c8a6d63ca692619b0dde47805d1 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 21 Oct 2013 13:34:55 +1000 Subject: Fix missing case in gdispStreamStop(). Add support for controllers that need flushing. Add both automatic and manual flushing (via the gdispFlush() method) --- src/gdisp/gdisp.c | 205 ++++++++++++++++++++++-------------------------------- 1 file changed, 84 insertions(+), 121 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 66cd59fd..172cddcc 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -94,6 +94,27 @@ GDisplay *GDISP = GDisplayArray; } #endif +#if GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH == HARDWARE_AUTODETECT + #define autoflush_stopdone(g) if (g->vmt->flush) gdisp_lld_flush(g) +#elif GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH + #define autoflush_stopdone(g) gdisp_lld_flush(g) +#else + #define autoflush_stopdone(g) +#endif + +#if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE + #define autoflush(g) \ + { \ + if ((g->flags & GDISP_FLG_SCRSTREAM)) { \ + gdisp_lld_write_stop(g); \ + g->flags &= ~GDISP_FLG_SCRSTREAM; \ + } + autoflush_stopdone(g); + } +#else + #define autoflush(g) autoflush_stopdone(g) +#endif + // drawpixel(g) // Parameters: x,y // Alters: cx, cy (if using streaming) @@ -551,11 +572,18 @@ void _gdispInit(void) { #if GDISP_STARTUP_LOGO_TIMEOUT > 0 StatupLogoDisplay(g); #endif + #if !GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH + gdispGFlush(g); + #endif } #if GDISP_STARTUP_LOGO_TIMEOUT > 0 gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); - for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) + for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) { gdispGClear(g, GDISP_STARTUP_COLOR); + #if !GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH + gdispGFlush(g); + #endif + } #endif } @@ -569,6 +597,21 @@ void gdispSetDisplay(GDisplay *g) { if (g) GDISP = g; } +void gdispGFlush(GDisplay *g) { + #if GDISP_HARDWARE_FLUSH + #if GDISP_HARDWARE_FLUSH == HARDWARE_AUTODETECT + if (g->vmt->flush) + #endif + { + MUTEX_ENTER(g); + gdisp_lld_flush(g); + MUTEX_EXIT(g); + } + #else + (void) g; + #endif +} + #if GDISP_NEED_STREAMING void gdispGStreamStart(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { MUTEX_ENTER(g); @@ -766,6 +809,7 @@ void gdispSetDisplay(GDisplay *g) { #endif { gdisp_lld_write_stop(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -782,6 +826,7 @@ void gdispSetDisplay(GDisplay *g) { g->p.ptr = (void *)g->linebuf; gdisp_lld_blit_area(g); } + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -799,10 +844,18 @@ void gdispSetDisplay(GDisplay *g) { else gdisp_lld_fill_area(g); } + autoflush_stopdone(g); MUTEX_EXIT(g); return; } #endif + + #if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS != TRUE + { + autoflush_stopdone(g); + MUTEX_EXIT(g); + } + #endif } #endif @@ -812,12 +865,7 @@ void gdispGDrawPixel(GDisplay *g, coord_t x, coord_t y, color_t color) { g->p.y = y; g->p.color = color; drawpixel_clip(g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -829,12 +877,7 @@ void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, g->p.y1 = y1; g->p.color = color; line_clip(g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -850,6 +893,7 @@ void gdispGClear(GDisplay *g, color_t color) { { g->p.color = color; gdisp_lld_clear(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -866,6 +910,7 @@ void gdispGClear(GDisplay *g, color_t color) { g->p.cy = g->g.Height; g->p.color = color; gdisp_lld_fill_area(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -895,6 +940,7 @@ void gdispGClear(GDisplay *g, color_t color) { for(; area; area--) gdisp_lld_write_color(g); gdisp_lld_write_stop(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -911,6 +957,7 @@ void gdispGClear(GDisplay *g, color_t color) { for(g->p.y = 0; g->p.y < g->g.Height; g->p.y++) for(g->p.x = 0; g->p.x < g->g.Width; g->p.x++) gdisp_lld_draw_pixel(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -927,6 +974,7 @@ void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c TEST_CLIP_AREA(g) { fillarea(g); } + autoflush_stopdone(g); MUTEX_EXIT(g); } @@ -963,6 +1011,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c g->p.x2 = srccx; g->p.ptr = (void *)buffer; gdisp_lld_blit_area(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -998,6 +1047,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } } gdisp_lld_write_stop(g); + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -1032,6 +1082,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } } } + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -1056,6 +1107,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c gdisp_lld_draw_pixel(g); } } + autoflush_stopdone(g); MUTEX_EXIT(g); return; } @@ -1136,12 +1188,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } #endif @@ -1177,12 +1224,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } #endif @@ -1221,12 +1263,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } } while(dy >= 0); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } #endif @@ -1263,12 +1300,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } } while(dy >= 0); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } #endif @@ -1336,12 +1368,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c if (full & 0x03) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (full & 0x30) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } if (full == 0xFF) { - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT; return; } @@ -1458,12 +1485,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } #endif @@ -1961,12 +1983,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c break; } - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2246,6 +2263,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c g->p.cy = abslines; g->p.color = bgcolor; fillarea(g); + autoflush_stopdone(g); MUTEX_EXIT(g); } #endif @@ -2354,12 +2372,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co } } - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2376,12 +2389,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co } g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+pntarray->x; g->p.y1=ty+pntarray->y; line_clip(g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2441,12 +2449,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co } if (!cnt) { - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); return; } @@ -2456,12 +2459,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co if (ymax == lpnt->y) { for (lpnt = lpnt <= pntarray ? epnts : lpnt-1; lpnt->y == y; cnt--) { if (!cnt) { - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); return; } @@ -2472,12 +2470,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co } else { for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { if (!cnt) { - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); return; } @@ -2561,12 +2554,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co g->t.clipy1 = y + font->height; g->t.color = color; mf_render_character(font, x, y, c, drawcharline, g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2586,12 +2574,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co fillarea(g); mf_render_character(font, x, y, c, fillcharline, g); } - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2605,12 +2588,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co g->t.color = color; mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2631,12 +2609,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, g); } - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2665,12 +2638,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, g); - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } @@ -2709,12 +2677,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, g); } - #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((g->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(g); - g->flags &= ~GDISP_FLG_SCRSTREAM; - } - #endif + autoflush(g); MUTEX_EXIT(g); } -- cgit v1.2.3 From 459fbf6781bca48471ea8dc1cfbbd2a0700ee2e1 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Mon, 21 Oct 2013 13:47:59 +0200 Subject: fixes --- src/gdisp/gdisp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 172cddcc..21c6e247 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -108,8 +108,8 @@ GDisplay *GDISP = GDisplayArray; if ((g->flags & GDISP_FLG_SCRSTREAM)) { \ gdisp_lld_write_stop(g); \ g->flags &= ~GDISP_FLG_SCRSTREAM; \ - } - autoflush_stopdone(g); + } \ + autoflush_stopdone(g); \ } #else #define autoflush(g) autoflush_stopdone(g) -- cgit v1.2.3 From 27b5383c1bcec9a8b45328bf051ee0624d0d1102 Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 22 Oct 2013 15:52:31 +1000 Subject: Fix typos in drivers --- src/gdisp/gdisp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 21c6e247..53882492 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -2313,6 +2313,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } #else void gdispGControl(GDisplay *g, unsigned what, void *value) { + (void)g; (void)what; (void)value; /* Ignore everything */ -- cgit v1.2.3 From 4a5506df0a36a61b13c01b0173523a2ce31b5fb9 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 24 Oct 2013 11:32:46 +1000 Subject: Fixes to GDISP for streaming drivers. Turn optimisation back on for SSD1289 driver --- src/gdisp/gdisp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 53882492..3d2e6e36 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -87,6 +87,7 @@ GDisplay *GDISP = GDisplayArray; static INLINE void setglobalwindow(GDisplay *g) { coord_t x, y; x = g->p.x; y = g->p.y; + g->p.x = g->p.y = 0; g->p.cx = g->g.Width; g->p.cy = g->g.Height; gdisp_lld_write_start(g); g->p.x = x; g->p.y = y; @@ -304,8 +305,9 @@ static void hline_clip(GDisplay *g) { { if (!(g->flags & GDISP_FLG_SCRSTREAM)) setglobalwindow(g); + g->p.cx = g->p.x1 - g->p.x + 1; gdisp_lld_write_pos(g); - do { gdisp_lld_write_color(g); } while(g->p.cx--); + do { gdisp_lld_write_color(g); } while(--g->p.cx); return; } #endif @@ -319,7 +321,7 @@ static void hline_clip(GDisplay *g) { g->p.cx = g->p.x1 - g->p.x + 1; g->p.cy = 1; gdisp_lld_write_start(g); - do { gdisp_lld_write_color(g); } while(g->p.cx--); + do { gdisp_lld_write_color(g); } while(--g->p.cx); gdisp_lld_write_stop(g); return; } @@ -404,7 +406,7 @@ static void vline_clip(GDisplay *g) { #endif gdisp_lld_write_pos(g); #endif - do { gdisp_lld_write_color(g); } while(g->p.cy--); + do { gdisp_lld_write_color(g); } while(--g->p.cy); gdisp_lld_write_stop(g); return; } -- cgit v1.2.3 From 452cfc1b1351e8070ed609d84cae0249411a236b Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 24 Oct 2013 12:57:20 +1000 Subject: Add GDISP_NEED_TIMERFLUSH to enable automatic display flushing on a timer. --- src/gdisp/gdisp.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 3d2e6e36..fdda1cff 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -44,6 +44,11 @@ static const struct GDISPVMT const * ControllerList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; static const unsigned DisplayCountList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS}; #endif + +#if GDISP_NEED_TIMERFLUSH + static GTimer FlushTimer; +#endif + static GDisplay GDisplayArray[GDISP_TOTAL_DISPLAYS]; GDisplay *GDISP = GDisplayArray; @@ -509,6 +514,16 @@ static void line_clip(GDisplay *g) { } #endif +#if GDISP_NEED_TIMERFLUSH + static void FlushTimerFn(void *param) { + GDisplay * g; + (void) param; + + for(g = GDisplayArray; g < &GDisplayArray[GDISP_TOTAL_DISPLAYS]; g++) + gdispGFlush(g); + } +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -521,7 +536,6 @@ void _gdispInit(void) { uint16_t j; #endif - /* Initialise driver */ #if GDISP_TOTAL_CONTROLLERS > 1 for(g = GDisplayArray, j=0; j < GDISP_TOTAL_CONTROLLERS; j++) @@ -587,6 +601,11 @@ void _gdispInit(void) { #endif } #endif + + #if GDISP_NEED_TIMERFLUSH + gtimerInit(&FlushTimer); + gtimerStart(&FlushTimer, FlushTimerFn, 0, TRUE, GDISP_NEED_TIMERFLUSH); + #endif } GDisplay *gdispGetDisplay(unsigned display) { -- cgit v1.2.3 From 21afd2b8f19d522fab6b78670bf1afcf11388cd5 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 24 Oct 2013 13:59:03 +1000 Subject: Created a crude auto-scaling logo (for startup) --- src/gdisp/gdisp.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index fdda1cff..263e882d 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -510,7 +510,41 @@ static void line_clip(GDisplay *g) { #if GDISP_STARTUP_LOGO_TIMEOUT > 0 static void StatupLogoDisplay(GDisplay *g) { - gdispGFillArea(g, g->g.Width/4, g->g.Height/4, g->g.Width/2, g->g.Height/2, Blue); + coord_t x, y, w; + const coord_t * p; + static const coord_t blks[] = { + // u + 2, 6, 1, 10, + 3, 11, 4, 1, + 6, 6, 1, 6, + // G + 8, 0, 1, 12, + 9, 0, 6, 1, + 9, 11, 6, 1, + 14, 6, 1, 5, + 12, 6, 2, 1, + // F + 16, 0, 1, 12, + 17, 0, 6, 1, + 17, 6, 3, 1, + // X + 22, 6, 7, 1, + 24, 0, 1, 6, + 22, 7, 1, 5, + 28, 0, 1, 6, + 26, 7, 1, 5, + }; + + // Get a starting position and a scale + // Work on a 8x16 grid for each char, 4 chars (uGFX) in 1 line, using half the screen + w = g->g.Width/(8*4*2); + if (!w) w = 1; + x = (g->g.Width - (8*4)*w)/2; + y = (g->g.Height - (16*1)*w)/2; + + // Simple but crude! + for(p = blks; p < blks+sizeof(blks)/sizeof(blks[0]); p+=4) + gdispGFillArea(g, x+p[0]*w, y+p[1]*w, p[2]*w, p[3]*w, Blue); } #endif -- cgit v1.2.3 From a28dce97d877160b10a3683fbf8ea578c8405417 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 24 Oct 2013 18:34:26 +1000 Subject: Add multiple display support to image decoding. --- src/gdisp/image.c | 17 +++++---- src/gdisp/image_bmp.c | 12 +++--- src/gdisp/image_gif.c | 98 ++++++++++++++++++++++++------------------------ src/gdisp/image_native.c | 6 +-- 4 files changed, 67 insertions(+), 66 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/image.c b/src/gdisp/image.c index 1e9ac3d6..62af0aeb 100644 --- a/src/gdisp/image.c +++ b/src/gdisp/image.c @@ -23,7 +23,8 @@ typedef struct gdispImageHandlers { gdispImageError (*open)(gdispImage *img); /* The open function */ void (*close)(gdispImage *img); /* The close function */ gdispImageError (*cache)(gdispImage *img); /* The cache function */ - gdispImageError (*draw)(gdispImage *img, + gdispImageError (*draw)(GDisplay *g, + gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy); /* The draw function */ @@ -33,27 +34,27 @@ typedef struct gdispImageHandlers { static gdispImageHandlers ImageHandlers[] = { #if GDISP_NEED_IMAGE_NATIVE { gdispImageOpen_NATIVE, gdispImageClose_NATIVE, - gdispImageCache_NATIVE, gdispImageDraw_NATIVE, gdispImageNext_NATIVE, + gdispImageCache_NATIVE, gdispGImageDraw_NATIVE, gdispImageNext_NATIVE, }, #endif #if GDISP_NEED_IMAGE_GIF { gdispImageOpen_GIF, gdispImageClose_GIF, - gdispImageCache_GIF, gdispImageDraw_GIF, gdispImageNext_GIF, + gdispImageCache_GIF, gdispGImageDraw_GIF, gdispImageNext_GIF, }, #endif #if GDISP_NEED_IMAGE_BMP { gdispImageOpen_BMP, gdispImageClose_BMP, - gdispImageCache_BMP, gdispImageDraw_BMP, gdispImageNext_BMP, + gdispImageCache_BMP, gdispGImageDraw_BMP, gdispImageNext_BMP, }, #endif #if GDISP_NEED_IMAGE_JPG { gdispImageOpen_JPG, gdispImageClose_JPG, - gdispImageCache_JPG, gdispImageDraw_JPG, gdispImageNext_JPG, + gdispImageCache_JPG, gdispGImageDraw_JPG, gdispImageNext_JPG, }, #endif #if GDISP_NEED_IMAGE_PNG { gdispImageOpen_PNG, gdispImageClose_PNG, - gdispImageCache_PNG, gdispImageDraw_PNG, gdispImageNext_PNG, + gdispImageCache_PNG, gdispGImageDraw_PNG, gdispImageNext_PNG, }, #endif }; @@ -205,9 +206,9 @@ gdispImageError gdispImageCache(gdispImage *img) { return img->fns->cache(img); } -gdispImageError gdispImageDraw(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispGImageDraw(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT; - return img->fns->draw(img, x, y, cx, cy, sx, sy); + return img->fns->draw(g, img, x, y, cx, cy, sx, sy); } delaytime_t gdispImageNext(gdispImage *img) { diff --git a/src/gdisp/image_bmp.c b/src/gdisp/image_bmp.c index e23d0fb1..158d6edc 100644 --- a/src/gdisp/image_bmp.c +++ b/src/gdisp/image_bmp.c @@ -828,7 +828,7 @@ gdispImageError gdispImageCache_BMP(gdispImage *img) { return GDISP_IMAGE_ERR_OK; } -gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { gdispImagePrivate * priv; coord_t mx, my; coord_t pos, len, st; @@ -842,7 +842,7 @@ gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_ /* Draw from the image cache - if it exists */ if (priv->frame0cache) { - gdispBlitAreaEx(x, y, cx, cy, sx, sy, img->width, priv->frame0cache); + gdispGBlitArea(g, x, y, cx, cy, sx, sy, img->width, priv->frame0cache); return GDISP_IMAGE_ERR_OK; } @@ -864,9 +864,9 @@ gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_ len = pos-st; if (mx+st+len > sx+cx) len = sx+cx-mx-st; if (len == 1) - gdispDrawPixel(x+mx+st-sx, y+my-sy, priv->buf[st]); + gdispGDrawPixel(g, x+mx+st-sx, y+my-sy, priv->buf[st]); else - gdispBlitAreaEx(x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf); + gdispGBlitArea(g, x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf); } mx += pos; } @@ -882,9 +882,9 @@ gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_ len = pos-st; if (mx+st+len > sx+cx) len = sx+cx-mx-st; if (len == 1) - gdispDrawPixel(x+mx+st-sx, y+my-sy, priv->buf[st]); + gdispGDrawPixel(g, x+mx+st-sx, y+my-sy, priv->buf[st]); else - gdispBlitAreaEx(x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf); + gdispGBlitArea(g, x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf); } mx += pos; } diff --git a/src/gdisp/image_gif.c b/src/gdisp/image_gif.c index d067bd0f..1ff72ff0 100644 --- a/src/gdisp/image_gif.c +++ b/src/gdisp/image_gif.c @@ -820,7 +820,7 @@ baddatacleanup: return GDISP_IMAGE_ERR_BADDATA; } -gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { gdispImagePrivate * priv; imgdecode * decode; uint8_t * q = 0; @@ -847,9 +847,9 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // The spec says to restore the backgound color (priv->bgcolor) but in practice if there is transparency // image decoders tend to assume that a restore to the transparent color is required instead if (((priv->dispose.flags & GIFL_TRANSPARENT) /*&& priv->dispose.paltrans == priv->bgcolor*/) || priv->bgcolor >= priv->palsize) - gdispFillArea(x+mx-sx, y+my-sy, fx-mx, fy-my, img->bgcolor); + gdispGFillArea(g, x+mx-sx, y+my-sy, fx-mx, fy-my, img->bgcolor); else - gdispFillArea(x+mx-sx, y+my-sy, fx-mx, fy-my, priv->palette[priv->bgcolor]); + gdispGFillArea(g, x+mx-sx, y+my-sy, fx-mx, fy-my, priv->palette[priv->bgcolor]); } } @@ -881,23 +881,23 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have a transparent pixel - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } continue; } priv->buf[gcnt++] = cache->palette[col]; if (gcnt >= BLIT_BUFFER_SIZE) { // We have run out of buffer - dump it to the display - gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); + gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; } } // We have finished the line - dump the buffer to the display switch(gcnt) { - case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; + case 0: break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; } } @@ -935,15 +935,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have a transparent pixel - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } continue; } priv->buf[gcnt++] = decode->palette[col]; if (gcnt >= BLIT_BUFFER_SIZE) { // We have run out of buffer - dump it to the display - gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); + gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; } continue; @@ -951,15 +951,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have finished the visible area - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } } // We have finished the line - dump the buffer to the display switch(gcnt) { - case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; + case 0: break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; } } // Every 8th row starting at row 4 @@ -981,15 +981,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have a transparent pixel - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } continue; } priv->buf[gcnt++] = decode->palette[col]; if (gcnt >= BLIT_BUFFER_SIZE) { // We have run out of buffer - dump it to the display - gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); + gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; } continue; @@ -997,15 +997,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have finished the visible area - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } } // We have finished the line - dump the buffer to the display switch(gcnt) { - case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; + case 0: break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; } } // Every 4th row starting at row 2 @@ -1027,15 +1027,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have a transparent pixel - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } continue; } priv->buf[gcnt++] = decode->palette[col]; if (gcnt >= BLIT_BUFFER_SIZE) { // We have run out of buffer - dump it to the display - gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); + gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; } continue; @@ -1043,15 +1043,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have finished the visible area - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } } // We have finished the line - dump the buffer to the display switch(gcnt) { - case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; + case 0: break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; } } // Every 2nd row starting at row 1 @@ -1073,15 +1073,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have a transparent pixel - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } continue; } priv->buf[gcnt++] = decode->palette[col]; if (gcnt >= BLIT_BUFFER_SIZE) { // We have run out of buffer - dump it to the display - gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); + gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; } continue; @@ -1089,15 +1089,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have finished the visible area - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } } // We have finished the line - dump the buffer to the display switch(gcnt) { - case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; + case 0: break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; } } } else { @@ -1120,15 +1120,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have a transparent pixel - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } continue; } priv->buf[gcnt++] = decode->palette[col]; if (gcnt >= BLIT_BUFFER_SIZE) { // We have run out of buffer - dump it to the display - gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); + gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; } continue; @@ -1136,15 +1136,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_ // We have finished the visible area - dump the buffer to the display switch(gcnt) { case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0; break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0; break; } } // We have finished the line - dump the buffer to the display switch(gcnt) { - case 0: break; - case 1: gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; - default: gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; + case 0: break; + case 1: gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); break; + default: gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); break; } } } diff --git a/src/gdisp/image_native.c b/src/gdisp/image_native.c index 24aed81f..72ae8b61 100644 --- a/src/gdisp/image_native.c +++ b/src/gdisp/image_native.c @@ -91,7 +91,7 @@ gdispImageError gdispImageCache_NATIVE(gdispImage *img) { return GDISP_IMAGE_ERR_OK; } -gdispImageError gdispImageDraw_NATIVE(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispImageGDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { coord_t mx, mcx; size_t pos, len; @@ -102,7 +102,7 @@ gdispImageError gdispImageDraw_NATIVE(gdispImage *img, coord_t x, coord_t y, coo /* Draw from the image cache - if it exists */ if (img->priv->frame0cache) { - gdispBlitAreaEx(x, y, cx, cy, sx, sy, img->width, img->priv->frame0cache); + gdispGBlitArea(g, x, y, cx, cy, sx, sy, img->width, img->priv->frame0cache); return GDISP_IMAGE_ERR_OK; } @@ -125,7 +125,7 @@ gdispImageError gdispImageDraw_NATIVE(gdispImage *img, coord_t x, coord_t y, coo return GDISP_IMAGE_ERR_BADDATA; /* Blit the chunk of data */ - gdispBlitAreaEx(mx, y, len, 1, 0, 0, len, img->priv->buf); + gdispGBlitArea(g, mx, y, len, 1, 0, 0, len, img->priv->buf); } /* Get the position for the start of the next line */ -- cgit v1.2.3 From 250adaf028848c0aa0dfa2029b722274cb7a6d6a Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 5 Nov 2013 13:45:19 +1000 Subject: Fixes to gdisp vertical scrolling. Also added improved optimisation for drivers without blit but with a fill routine. --- src/gdisp/gdisp.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 263e882d..b08fe627 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -1041,7 +1041,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c if (!g->vmt->setclip) #endif { - // This is a different cliping to fillarea(g) as it needs to take into account srcx,srcy + // This is a different clipping to fillarea(g) as it needs to take into account srcx,srcy if (x < g->clipx0) { cx -= g->clipx0 - x; srcx += g->clipx0 - x; x = g->clipx0; } if (y < g->clipy0) { cy -= g->clipy0 - y; srcy += g->clipy0 - x; y = g->clipy0; } if (x+cx > g->clipx1) cx = g->clipx1 - x; @@ -2130,7 +2130,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c #if GDISP_NEED_SCROLL void gdispGVerticalScroll(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { coord_t abslines; - #if !GDISP_HARDWARE_SCROLL + #if GDISP_HARDWARE_SCROLL != TRUE coord_t fy, dy, ix, fx, i, j; #endif @@ -2232,9 +2232,11 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } } #if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT - else + else { // Worst is "not possible" + MUTEX_EXIT(g); return; + } #endif #endif @@ -2291,8 +2293,40 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c #endif #endif + // Next best line write is drawing pixels in combination with filling + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS && GDISP_HARDWARE_DRAWPIXEL + // We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + if (g->vmt->fill) + #endif + { + g->p.y = fy; + g->p.cy = 1; + g->p.x = x+ix; + g->p.cx = 1; + for(j = 0; j < fx; ) { + g->p.color = g->linebuf[j]; + if (j + g->p.cx < fx && g->linebuf[j] == g->linebuf[j + g->p.cx]) + g->p.cx++; + else if (g->p.cx == 1) { + gdisp_lld_draw_pixel(g); + j++; + g->p.x++; + } else { + gdisp_lld_fill_area(g); + j += g->p.cx; + g->p.x += g->p.cx; + g->p.cx = 1; + } + } + } + #if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT + else + #endif + #endif + // Worst line write is drawing pixels - #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL + #if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_DRAWPIXEL // The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming //#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT // if (g->vmt->pixel) -- cgit v1.2.3 From daa4e8bbd78ebe4a84234de266006d1a23697657 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 9 Nov 2013 19:17:22 +1000 Subject: Add support for a portrait and landscape orientation modes. --- src/gdisp/gdisp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index b08fe627..7eade99c 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -2367,6 +2367,16 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c MUTEX_ENTER(g); g->p.x = what; g->p.ptr = value; + if (what == GDISP_CONTROL_ORIENTATION) { + switch ((orientation_t) value) { + case GDISP_ROTATE_LANDSCAPE: + g->p.ptr = g->g.Width >= g->g.Height ? GDISP_ROTATE_0 : GDISP_ROTATE_90; + break; + case GDISP_ROTATE_PORTRAIT: + g->p.ptr = g->g.Width >= g->g.Height ? GDISP_ROTATE_90 : GDISP_ROTATE_0; + break; + } + } gdisp_lld_control(g); #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION if (what == GDISP_CONTROL_ORIENTATION) { -- cgit v1.2.3 From 1f99d5c9fac79e3e9aa4ebff97b296b6dcb9c9a7 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 9 Nov 2013 19:18:59 +1000 Subject: Add support for a default application orientation. Also remove old unneeded GDISP_USE_CUSTOM_BOARD macro --- src/gdisp/gdisp.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 7eade99c..6964bfff 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -587,6 +587,15 @@ void _gdispInit(void) { g->flags = 0; gdisp_lld_init(g); + #if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL + g->p.x = GDISP_CONTROL_ORIENTATION; + g->p.ptr = GDISP_DEFAULT_ORIENTATION; + #if GDISP_HARDWARE_CONTROL == HARDWARE_AUTODETECT + if (g->vmt->control) + #endif + gdisp_lld_control(g); + #endif + // Set the initial clipping region #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP -- cgit v1.2.3 From 5cc1c5d67b339dc3cc623a6f3d10b9137d0929c8 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sun, 10 Nov 2013 21:33:28 +1000 Subject: Fix some compiler warnings. --- src/gdisp/gdisp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/gdisp') diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 6964bfff..2af30f15 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -589,7 +589,7 @@ void _gdispInit(void) { #if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL g->p.x = GDISP_CONTROL_ORIENTATION; - g->p.ptr = GDISP_DEFAULT_ORIENTATION; + g->p.ptr = (void *)GDISP_DEFAULT_ORIENTATION; #if GDISP_HARDWARE_CONTROL == HARDWARE_AUTODETECT if (g->vmt->control) #endif @@ -2379,10 +2379,12 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c if (what == GDISP_CONTROL_ORIENTATION) { switch ((orientation_t) value) { case GDISP_ROTATE_LANDSCAPE: - g->p.ptr = g->g.Width >= g->g.Height ? GDISP_ROTATE_0 : GDISP_ROTATE_90; + g->p.ptr = g->g.Width >= g->g.Height ? (void *)GDISP_ROTATE_0 : (void *)GDISP_ROTATE_90; break; case GDISP_ROTATE_PORTRAIT: - g->p.ptr = g->g.Width >= g->g.Height ? GDISP_ROTATE_90 : GDISP_ROTATE_0; + g->p.ptr = g->g.Width >= g->g.Height ? (void *)GDISP_ROTATE_90 : (void *)GDISP_ROTATE_0; + break; + default: break; } } -- cgit v1.2.3