diff --git a/demos/modules/gdisp/multiple_displays/gfxconf.h b/demos/modules/gdisp/multiple_displays/gfxconf.h index 60467f93..959f1d0b 100644 --- a/demos/modules/gdisp/multiple_displays/gfxconf.h +++ b/demos/modules/gdisp/multiple_displays/gfxconf.h @@ -46,16 +46,20 @@ #define GDISP_INCLUDE_FONT_UI2 TRUE -#define GDISP_TOTAL_DISPLAYS 2 - -/* Uncomment the following lines if you want to use multiple displays on - * different controllers. +/* You must either define GDISP_TOTAL_DISPLAYS or GDISP_DRIVER_LIST for multiple displays. + * You cannot define both! * - * Change the definitions to suit your hardware. - * Currently all controllers must use the same pixel format. + * Defining GDISP_TOTAL_DISPLAYS will create multiple instances of the one default driver. + * Defining GDISP_DRIVER_LIST allows you to specify multiple different drivers. * - * Remember that GDISP_TOTAL_DISPLAYS above must match the **Total** - * number of displays in your system across all controllers. + * Extra Notes for GDISP_DRIVER_LIST: + *----------------------------------- + * + * The same controller can appear more than once in the list. + * + * You must specify a GDISP_PIXELFORMAT that the application will work in. This + * is translated into each drivers internal pixel format by the driver. You the + * pixel format that is most common accross your drivers (for efficiency). * * Optionally, you can also specify hardware characteristics that are common to * all your controllers. This significantly improves code and speed efficiency @@ -72,9 +76,9 @@ * #define GDISP_HARDWARE_DRAWPIXEL TRUE * #define GDISP_HARDWARE_FILLS TRUE */ -//#define GDISP_TOTAL_CONTROLLERS 2 -//#define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_Win32 -//#define GDISP_CONTROLLER_DISPLAYS 1, 1 -//#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 +#define GDISP_TOTAL_DISPLAYS 2 + +//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32 +//#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 #endif /* _GFXCONF_H */ diff --git a/demos/modules/gdisp/multiple_displays/main.c b/demos/modules/gdisp/multiple_displays/main.c index 4e8a5a08..c4c37bed 100644 --- a/demos/modules/gdisp/multiple_displays/main.c +++ b/demos/modules/gdisp/multiple_displays/main.c @@ -46,7 +46,7 @@ #if USE_METHOD_1 int main(void) { coord_t width, height; - coord_t display, i, j; + coord_t display, i, j, cnt; font_t f; GDisplay *g; char buf[16]; @@ -58,7 +58,8 @@ f = gdispOpenFont("*"); /* Cycle through each display */ - for(display = 0; display < GDISP_TOTAL_DISPLAYS; display++) { + cnt = gdispGetDisplayCount(); + for(display = 0; display < cnt; display++) { // Get the specified display g = gdispGetDisplay(display); @@ -84,7 +85,7 @@ #else int main(void) { coord_t width, height; - coord_t display, i, j; + coord_t display, i, j, cnt; font_t f; char buf[16]; @@ -95,7 +96,8 @@ f = gdispOpenFont("*"); /* Cycle through each display */ - for(display = 0; display < GDISP_TOTAL_DISPLAYS; display++) { + cnt = gdispGetDisplayCount(); + for(display = 0; display < cnt; display++) { // Set the default display to the specified display gdispSetDisplay(gdispGetDisplay(display)); diff --git a/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c b/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c index 802f2822..e96ad3b2 100644 --- a/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c +++ b/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c @@ -205,20 +205,18 @@ static DECLARE_THREAD_FUNCTION(NetThread, param) { gfxHalt("GDISP: uGFXnet - Accept failed"); // Look for a display that isn't connected - for(disp = 0; disp < GDISP_TOTAL_DISPLAYS; disp++) { - if (!(g = gdispGetDisplay(disp))) - continue; - #if GDISP_TOTAL_CONTROLLERS > 1 - // Ignore displays for other controllers - if (g->vmt != &GDISPVMT_uGFXnet) - continue; - #endif + for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) { + // Ignore displays for other controllers + #ifdef GDISP_DRIVER_LIST + if (gvmt(g) != &GDISPVMT_uGFXnet) + continue; + #endif if (!(g->flags & GDISP_FLG_CONNECTED)) break; } // Was anything found? - if (disp >= GDISP_TOTAL_DISPLAYS) { + if (!g) { // No Just close the connection closesocket(clientfd); gfxHalt("GDISP: uGFXnet - Can't find display for connection"); @@ -275,21 +273,19 @@ static DECLARE_THREAD_FUNCTION(NetThread, param) { if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1) gfxHalt("GDISP: uGFXnet - Accept failed"); - // Look for a display that isn't connected - for(disp = 0; disp < GDISP_TOTAL_DISPLAYS; disp++) { - if (!(g = gdispGetDisplay(disp))) - continue; - #if GDISP_TOTAL_CONTROLLERS > 1 - // Ignore displays for other controllers - if (g->vmt != &GDISPVMT_uGFXnet) - continue; - #endif - if (!(g->flags & GDISP_FLG_CONNECTED)) - break; - } + // Look for a display that isn't connected + for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) { + // Ignore displays for other controllers + #ifdef GDISP_DRIVER_LIST + if (gvmt(g) != &GDISPVMT_uGFXnet) + continue; + #endif + if (!(g->flags & GDISP_FLG_CONNECTED)) + break; + } // Was anything found? - if (disp >= GDISP_TOTAL_DISPLAYS) { + if (!g) { // No Just close the connection closesocket(clientfd); //printf(New connection from %s on socket %d rejected as all displays are already connected\n", inet_ntoa(addr.sin_addr), clientfd); @@ -332,19 +328,17 @@ static DECLARE_THREAD_FUNCTION(NetThread, param) { // Handle data from a client // Look for a display that is connected and the socket descriptor matches - for(disp = 0; disp < GDISP_TOTAL_DISPLAYS; disp++) { - if (!(g = gdispGetDisplay(disp))) - continue; - #if GDISP_TOTAL_CONTROLLERS > 1 - // Ignore displays for other controllers - if (g->vmt != &GDISPVMT_uGFXnet) - continue; - #endif + for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) { + // Ignore displays for other controllers + #ifdef GDISP_DRIVER_LIST + if (gvmt(g) != &GDISPVMT_uGFXnet) + continue; + #endif priv = g->priv; if ((g->flags & GDISP_FLG_CONNECTED) && priv->netfd == i) break; - } - if (disp >= GDISP_TOTAL_DISPLAYS) + } + if (!g) gfxHalt("GDISP: uGFXnet - Got data from unrecognized connection"); if ((g->flags & GDISP_FLG_HAVEDATA)) { @@ -538,7 +532,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { // Make everything relative to the start of the line buffer = g->p.ptr; buffer += g->p.x2*g->p.y1; - + priv = g->priv; buf[0] = GNETCODE_BLIT; buf[1] = g->p.x; @@ -583,7 +577,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { // Now wait for a reply while(!(g->flags & GDISP_FLG_HAVEDATA) || priv->data[0] != GNETCODE_READ) gfxSleepMilliseconds(1); - + data = gdispNative2Color(priv->data[1]); g->flags &= ~GDISP_FLG_HAVEDATA; diff --git a/gfxconf.example.h b/gfxconf.example.h index 9b5ba477..205c79d3 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -108,8 +108,8 @@ //#define GDISP_TOTAL_DISPLAYS 1 -//#define GDISP_TOTAL_CONTROLLERS 1 -// #if GDISP_TOTAL_CONTROLLERS > 1 +//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32 +// #ifdef GDISP_DRIVER_LIST // // For code and speed optimization define as TRUE or FALSE if all controllers have the same capability // #define GDISP_HARDWARE_STREAM_WRITE FALSE // #define GDISP_HARDWARE_STREAM_READ FALSE @@ -124,8 +124,6 @@ // #define GDISP_HARDWARE_QUERY FALSE // #define GDISP_HARDWARE_CLIP FALSE -// #define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_Win32 -// #define GDISP_CONTROLLER_DISPLAYS 1, 1 // #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 // #endif diff --git a/src/gdisp/driver.h b/src/gdisp/driver.h index 3b77c568..10f9fd87 100644 --- a/src/gdisp/driver.h +++ b/src/gdisp/driver.h @@ -24,7 +24,7 @@ // Our special auto-detect hardware code which uses the VMT. #define HARDWARE_AUTODETECT 2 -#if GDISP_TOTAL_CONTROLLERS > 1 && !defined(GDISP_DRIVER_VMT) +#if defined(GDISP_DRIVER_LIST) && !defined(GDISP_DRIVER_VMT) // Multiple controllers the default is to hardware detect #define HARDWARE_DEFAULT HARDWARE_AUTODETECT #else @@ -40,7 +40,7 @@ * @brief The display hardware can benefit from being de-initialized when usage is complete. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note This is most useful for displays such as remote network displays. */ #ifndef GDISP_HARDWARE_DEINIT @@ -51,7 +51,7 @@ * @brief The display hardware can benefit from being flushed. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note Some controllers ** require ** the application to flush */ #ifndef GDISP_HARDWARE_FLUSH @@ -62,7 +62,7 @@ * @brief Hardware streaming writing is supported. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by each driver */ #ifndef GDISP_HARDWARE_STREAM_WRITE @@ -73,7 +73,7 @@ * @brief Hardware streaming reading of the display surface is supported. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * */ #ifndef GDISP_HARDWARE_STREAM_READ @@ -84,7 +84,7 @@ * @brief Hardware supports setting the cursor position within the stream window. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note This is used to optimise setting of individual pixels within a stream window. * It should therefore not be implemented unless it is cheaper than just setting * a new window. @@ -97,7 +97,7 @@ * @brief Hardware accelerated draw pixel. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver */ #ifndef GDISP_HARDWARE_DRAWPIXEL @@ -108,7 +108,7 @@ * @brief Hardware accelerated screen clears. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note This clears the entire display surface regardless of the clipping area currently set */ #ifndef GDISP_HARDWARE_CLEARS @@ -119,7 +119,7 @@ * @brief Hardware accelerated rectangular fills. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined */ #ifndef GDISP_HARDWARE_FILLS #define GDISP_HARDWARE_FILLS HARDWARE_DEFAULT @@ -129,7 +129,7 @@ * @brief Hardware accelerated fills from an image. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined */ #ifndef GDISP_HARDWARE_BITFILLS #define GDISP_HARDWARE_BITFILLS HARDWARE_DEFAULT @@ -139,7 +139,7 @@ * @brief Hardware accelerated scrolling. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined */ #ifndef GDISP_HARDWARE_SCROLL #define GDISP_HARDWARE_SCROLL HARDWARE_DEFAULT @@ -149,7 +149,7 @@ * @brief Reading back of pixel values. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined */ #ifndef GDISP_HARDWARE_PIXELREAD #define GDISP_HARDWARE_PIXELREAD HARDWARE_DEFAULT @@ -159,7 +159,7 @@ * @brief The driver supports one or more control commands. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined */ #ifndef GDISP_HARDWARE_CONTROL #define GDISP_HARDWARE_CONTROL HARDWARE_DEFAULT @@ -169,7 +169,7 @@ * @brief The driver supports a non-standard query. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined */ #ifndef GDISP_HARDWARE_QUERY #define GDISP_HARDWARE_QUERY HARDWARE_DEFAULT @@ -179,7 +179,7 @@ * @brief The driver supports a clipping in hardware. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * - * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined * @note If this is defined the driver must perform its own clipping on all calls to * the driver and respond appropriately if a parameter is outside the display area. * @note If this is not defined then the software ensures that all calls to the @@ -310,16 +310,16 @@ typedef struct GDISPVMT { } GDISPVMT; // Do we need function definitions or macro's (via the VMT) -#if GDISP_TOTAL_CONTROLLERS <= 1 || defined(GDISP_DRIVER_VMT) || defined(__DOXYGEN__) +#if !defined(GDISP_DRIVER_LIST) || defined(GDISP_DRIVER_VMT) || defined(__DOXYGEN__) #ifdef __cplusplus extern "C" { #endif // Should the driver routines should be static or not - #if GDISP_TOTAL_CONTROLLERS <= 1 - #define LLDSPEC + #if defined(GDISP_DRIVER_LIST) + #define LLDSPEC static #else - #define LLDSPEC static + #define LLDSPEC #endif /** @@ -611,7 +611,7 @@ typedef struct GDISPVMT { #endif // If we are not using multiple displays then hard-code the VMT name - #ifndef GDISP_CONTROLLER_LIST + #if !defined(GDISP_DRIVER_LIST) #undef GDISP_DRIVER_VMT #define GDISP_DRIVER_VMT GDISPVMT_OnlyOne #endif diff --git a/src/gdisp/gdisp_gdisp.c b/src/gdisp/gdisp_gdisp.c index a34788b2..0e5cacb5 100644 --- a/src/gdisp/gdisp_gdisp.c +++ b/src/gdisp/gdisp_gdisp.c @@ -566,45 +566,24 @@ static void line_clip(GDisplay *g) { void _gdispInit(void) { - // Both GDISP_CONTROLLER_LIST and GDISP_CONTROLLER_DISPLAYS are defined - create the required numbers of each controller - #if defined(GDISP_CONTROLLER_LIST) && defined(GDISP_CONTROLLER_DISPLAYS) - { - int i, cnt; - - extern GDriverVMTList GDISP_CONTROLLER_LIST; - static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; - static const unsigned dnlist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS}; - - for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++) { - for(cnt = dnlist[i]; cnt; cnt--) - gdriverRegister(dclist[i]); - } - } - - // Only GDISP_CONTROLLER_LIST is defined - create one of each controller - #elif defined(GDISP_CONTROLLER_LIST) + // GDISP_DRIVER_LIST is defined - create each driver instance + #if defined(GDISP_DRIVER_LIST) { int i; - extern GDriverVMTList GDISP_CONTROLLER_LIST; - static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; + extern GDriverVMTList GDISP_DRIVER_LIST; + static const struct GDriverVMT const * dclist[] = {GDISP_DRIVER_LIST}; - for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++) + for(i = 0; i < sizeof(dclist)/sizeof(dclist[0]); i++) gdriverRegister(dclist[i]); } - - // Only GDISP_TOTAL_DISPLAYS is defined - create the required number of the one controller #elif GDISP_TOTAL_DISPLAYS > 1 { - int cnt; + int i; - extern GDriverVMTList GDISPVMT_OnlyOne; - - for(cnt = 0; cnt < GDISP_TOTAL_DISPLAYS; cnt++) + for(i = 0; i < GDISP_TOTAL_DISPLAYS; i++) gdriverRegister(GDISPVMT_OnlyOne); } - - // One and only one display #else { extern GDriverVMTList GDISPVMT_OnlyOne; @@ -715,10 +694,6 @@ void _gdispDeInitDriver(GDriver *g) { #undef gd } -GDisplay *gdispGetDisplay(unsigned display) { - return (GDisplay *)gdriverGetInstance(GDRIVER_TYPE_DISPLAY, display); -} - void gdispSetDisplay(GDisplay *g) { if (g) GDISP = g; } @@ -1001,7 +976,7 @@ void gdispGDrawPixel(GDisplay *g, coord_t x, coord_t y, color_t color) { autoflush(g); MUTEX_EXIT(g); } - + 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; @@ -1110,7 +1085,7 @@ void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c autoflush_stopdone(g); MUTEX_EXIT(g); } - + 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); @@ -1246,7 +1221,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } #endif } - + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION void gdispGSetClip(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { MUTEX_ENTER(g); @@ -1400,7 +1375,7 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c MUTEX_EXIT(g); } #endif - + #if GDISP_NEED_ELLIPSE void gdispGFillEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { coord_t dx, dy; @@ -2662,7 +2637,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co } } } - + static int32_t rounding_div(const int32_t n, const int32_t d) { if ((n < 0) != (d < 0)) @@ -2670,23 +2645,23 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co else return (n + d/2) / d; } - + /* Find a vector (nx, ny) that is perpendicular to (dx, dy) and has length * equal to 'norm'. */ static void get_normal_vector(coord_t dx, coord_t dy, coord_t norm, coord_t *nx, coord_t *ny) { int32_t dx2, dy2, len_sq, norm_sq, norm_sq2; int div, step, best, delta, abs_delta; - + dx2 = dx; dy2 = dy; norm_sq = (int32_t)norm * norm; norm_sq2 = norm_sq * 512; - + /* Scale dx2 and dy2 so that * len_sq / 2 <= norm_sq * 512 <= len_sq * 2. * The scaling by 512 is to yield higher accuracy in division later. */ len_sq = dx2 * dx2 + dy2 * dy2; - + if (len_sq < norm_sq2) { while (len_sq && len_sq < norm_sq2) @@ -2701,69 +2676,69 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co len_sq >>= 2; dx2 >>= 1; dy2 >>= 1; } } - + /* Now find the divider div so that * len_sq / div^2 == norm_sq i.e. div = sqrt(len_sq / norm_sq) * * This is done using bisection search to avoid the need for floating * point sqrt. - * + * * Based on previous scaling, we know that * len_sq / 2 <= norm_sq * 512 <=> div <= sqrt(1024) = 32 * len_sq * 2 >= norm_sq * 512 <=> div >= sqrt(256) = 16 */ div = 24; step = 8; best = 256; - + for (;;) { dx = dx2 / div; dy = dy2 / div; len_sq = dx*dx + dy*dy; - + delta = len_sq - norm_sq; - + abs_delta = (delta >= 0) ? delta : -delta; - + if (abs_delta < best) { *nx = dy; *ny = -dx; best = abs_delta; } - + if (delta > 0) div += step; else if (delta < 0) div -= step; else if (delta == 0) break; - + if (step == 0) break; else step >>= 1; /* Do one round with step = 0 to calculate final result. */ } } - + void gdispGDrawThickLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color, coord_t width, bool_t round) { coord_t dx, dy, nx = 0, ny = 0; - + /* Compute the direction vector for the line */ dx = x1 - x0; dy = y1 - y0; - + /* Draw a small dot if the line length is zero. */ if (dx == 0 && dy == 0) dx += 1; - + /* Compute a normal vector with length 'width'. */ get_normal_vector(dx, dy, width, &nx, &ny); - + /* Handle 1px wide lines gracefully */ if (nx == 0 && ny == 0) nx = 1; - + /* Offset the x0,y0 by half the width of the line. This way we * can keep the width of the line accurate even if it is not evenly * divisible by 2. @@ -2772,11 +2747,11 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co x0 -= rounding_div(nx, 2); y0 -= rounding_div(ny, 2); } - + /* Fill in the point array */ if (!round) { /* We use 4 points for the basic line shape: - * + * * pt1 pt2 * (+n) ------------------------------------ (d+n) * | | @@ -2784,7 +2759,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co * pt0 pt3 */ point pntarray[4]; - + pntarray[0].x = 0; pntarray[0].y = 0; pntarray[1].x = nx; @@ -2793,7 +2768,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co pntarray[2].y = dy + ny; pntarray[3].x = dx; pntarray[3].y = dy; - + gdispGFillConvexPoly(g, x0, y0, pntarray, 4, color); } else { /* We use 4 points for basic shape, plus 4 extra points for ends: @@ -2808,26 +2783,26 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co */ point pntarray[8]; coord_t nx2, ny2; - + /* Magic numbers: * 75/256 = sin(45) / (1 + sqrt(2)) diagonal octagon segments * 106/256 = 1 / (1 + sqrt(2)) octagon side * 53/256 = 0.5 / (1 + sqrt(2)) half of octagon side * 150/256 = 1 - 1 / (1 + sqrt(2)) octagon height minus one side */ - + /* Rotate the normal vector 45 deg counter-clockwise and reduce * to 1 / (1 + sqrt(2)) length, for forming octagonal ends. */ nx2 = rounding_div((nx * 75 + ny * 75), 256); ny2 = rounding_div((-nx * 75 + ny * 75), 256); - + /* Offset and extend the line so that the center of the octagon * is at the specified points. */ x0 += ny * 53 / 256; y0 -= nx * 53 / 256; dx -= ny * 106 / 256; dy += nx * 106 / 256; - + /* Now fill in the points by summing the calculated vectors. */ pntarray[0].x = 0; pntarray[0].y = 0; @@ -2845,7 +2820,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co pntarray[6].y = dy + ny * 150/256 - ny2; pntarray[7].x = dx; pntarray[7].y = dy; - + gdispGFillConvexPoly(g, x0, y0, pntarray, 8, color); } } @@ -3099,19 +3074,19 @@ color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha) uint16_t fg_ratio = alpha + 1; uint16_t bg_ratio = 256 - alpha; uint16_t r, g, b; - + r = RED_OF(fg) * fg_ratio; g = GREEN_OF(fg) * fg_ratio; b = BLUE_OF(fg) * fg_ratio; - + r += RED_OF(bg) * bg_ratio; g += GREEN_OF(bg) * bg_ratio; b += BLUE_OF(bg) * bg_ratio; - + r >>= 8; g >>= 8; b >>= 8; - + return RGB2COLOR(r, g, b); } diff --git a/src/gdisp/sys_defs.h b/src/gdisp/sys_defs.h index d67fdcee..0d51d639 100644 --- a/src/gdisp/sys_defs.h +++ b/src/gdisp/sys_defs.h @@ -111,7 +111,7 @@ extern GDisplay *GDISP; /* Defines relating to the display hardware */ /*===========================================================================*/ -#if GDISP_TOTAL_CONTROLLERS <= 1 +#if !defined(GDISP_DRIVER_LIST) // Pull in the default hardware configuration for a single controller. // If we have multiple controllers the settings must be set in the // users gfxconf.h file. @@ -133,7 +133,7 @@ extern GDisplay *GDISP; * @details It generally defaults to the hardware pixel format. * @note This doesn't need to match the hardware pixel format. * It is definitely more efficient when it does. - * @note When GDISP_TOTAL_CONTROLLERS > 1, this must + * @note When GDISP_DRIVER_LIST is defined, this must * be explicitly defined and you should ensure the best match * with your hardware across all devices. */ @@ -213,13 +213,13 @@ color_t gdispContrastColor(color_t color); * @note The GDISP variable contains the display used by the gdispXxxx routines * as opposed to the gdispGXxxx routines which take an explicit display * parameter. - * @note Displays are numbered from 0 to GDISP_TOTAL_DISPLAYS - 1 + * @note Displays are numbered from 0 to @p gdispGetDisplayCount() - 1 * * @param[in] display The display number (0..n) * * @api */ -GDisplay *gdispGetDisplay(unsigned display); +#define gdispGetDisplay(display) ((GDisplay *)gdriverGetInstance(GDRIVER_TYPE_DISPLAY, display)) /** * @brief Set the current default display to the specified display @@ -235,6 +235,14 @@ GDisplay *gdispGetDisplay(unsigned display); */ void gdispSetDisplay(GDisplay *g); +/** + * @brief Get the count of currently active displays + * @return The count of displays currently in the system + * + * @note Displays are numbered from 0 to @p gdispGetDisplayCount() - 1 + */ +#define gdispGetDisplayCount() gdriverInstanceCount(GDRIVER_TYPE_DISPLAY) + /* Property Functions */ /** @@ -683,20 +691,20 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co */ void gdispGFillConvexPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color); #define gdispFillConvexPoly(x,y,p,i,c) gdispGFillConvexPoly(GDISP,x,y,p,i,c) - + /** * @brief Draw a line with a specified thickness * @details The line thickness is specified in pixels. The line ends can * be selected to be either flat or round. * @note Uses gdispGFillConvexPoly() internally to perform the drawing. - * + * * @param[in] g The display to use * @param[in] x0,y0 The start position * @param[in] x1,y1 The end position * @param[in] color The color to use * @param[in] width The width of the line * @param[in] round Use round ends for the line - * + * * @api */ void gdispGDrawThickLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color, coord_t width, bool_t round); @@ -857,13 +865,13 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co * @brief Make a scaled copy of an existing font. * @details Allocates memory for new font metadata using gfxAlloc, remember to close font after use! * @return A new font or NULL if out of memory. - * + * * @param[in] font The base font to use. * @param[in] scale_x The scale factor in horizontal direction. * @param[in] scale_y The scale factor in vertical direction. */ font_t gdispScaleFont(font_t font, uint8_t scale_x, uint8_t scale_y); - + /** * @brief Get the name of the specified font. * @returns The name of the font. @@ -907,7 +915,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co #define gdispFillRoundedBox(x,y,cx,cy,r,c) gdispGFillRoundedBox(GDISP,x,y,cx,cy,r,c) #endif -/* +/* * Macro definitions */ diff --git a/src/gdisp/sys_options.h b/src/gdisp/sys_options.h index 466bbb98..855f22ff 100644 --- a/src/gdisp/sys_options.h +++ b/src/gdisp/sys_options.h @@ -184,42 +184,26 @@ * @{ */ /** - * @brief The total number of displays. - * @note This can be on just one type of controller or spread across several different controllers + * @brief The total number of displays using the default driver. + * @note If you want to use multiple displays either set GDISP_TOTAL_DISPLAYS or GDISP_DRIVER_LIST + * but not both. */ #ifndef GDISP_TOTAL_DISPLAYS #define GDISP_TOTAL_DISPLAYS 1 #endif - /** - * @brief The total number of controllers. - * @note If this is greater than one, all the hardware acceleration options below - * and the pixel format must be manually specified in your gfxconf.h along with - * @p GDISP_CONTROLLER_LIST. See the gdisp_lld_config.h in each driver to get a list - * of hardware capabilities for each driver in order to work out the common set across - * all the controllers you want to use. - */ - #ifndef GDISP_TOTAL_CONTROLLERS - #define GDISP_TOTAL_CONTROLLERS 1 - #endif - #if defined(__DOXYGEN__) /** - * @brief The list of controllers. - * @note This is required if @p GDISP_TOTAL_CONTROLLERS is greater than one. - * @note The number of entries must match @p GDISP_TOTAL_CONTROLLERS. - * @note See the gdisp_lld.c in each driver (near the top) to get the name of the VMT for a driver. - * @note Replace this example with your own definition in your gfxconf.h file. + * @brief The list of display drivers. + * @note Replace this example with your own definition in your gfxconf.h file. See the gdisp_lld.c + * in each driver (near the top) to get the name of the VMT for a driver. + * @note The same driver can occur more than once in the list to create an extra instance of that driver. + * @note If defining this you must also define GDISP_PIXELFORMAT for your application to use. + * Choose a value that is most common accross all your drivers for efficiency. + * @note If using this you may optionally define the GDISP_HARDWARE_xxx values as either TRUE or FALSE. + * Doing this causes GDISP to assume that all (TRUE) or none (FALSE) of the listed drivers have that + * capability. This can help improve drawing speed and efficiency. */ - #define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_SSD1963 - /** - * @brief The number of displays for each controller. - * @note This is required if @p GDISP_TOTAL_CONTROLLERS is greater than one. - * @note The number of entries must match @p GDISP_TOTAL_CONTROLLERS. - * @note The sum of all the display counts must equal @p GDISP_TOTAL_DISPLAYS (3 for this example) - * or bad things will happen. - * @note Replace this example with your own definition in your gfxconf.h file. - */ - #define GDISP_CONTROLLER_DISPLAYS 2, 1 + #define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_SSD1963 #endif /** * @} @@ -272,7 +256,7 @@ #endif /** * @} - * + * * @name GDISP Text Rendering Options * @{ */ @@ -283,7 +267,7 @@ #ifndef GDISP_NEED_UTF8 #define GDISP_NEED_UTF8 FALSE #endif - + /** * @brief Enable kerning for font rendering (improves character placement). * @details Defaults to FALSE @@ -291,7 +275,7 @@ #ifndef GDISP_NEED_TEXT_KERNING #define GDISP_NEED_TEXT_KERNING FALSE #endif - + /** * @brief Enable antialiased font support * @details Defaults to FALSE @@ -299,7 +283,7 @@ #ifndef GDISP_NEED_ANTIALIAS #define GDISP_NEED_ANTIALIAS FALSE #endif - + /** * @} * diff --git a/src/gdisp/sys_rules.h b/src/gdisp/sys_rules.h index eca55ce3..90b07138 100644 --- a/src/gdisp/sys_rules.h +++ b/src/gdisp/sys_rules.h @@ -24,15 +24,12 @@ #undef GFX_USE_GDRIVER #define GFX_USE_GDRIVER TRUE #endif - #if GDISP_TOTAL_CONTROLLERS > 1 - #ifndef GDISP_CONTROLLER_LIST - #error "GDISP Multiple Controllers: You must specify a value for GDISP_CONTROLLER_LIST" - #endif - #ifndef GDISP_CONTROLLER_DISPLAYS - #error "GDISP Multiple Controllers: You must specify a value for GDISP_CONTROLLER_DISPLAYS" - #endif + #if defined(GDISP_DRIVER_LIST) + #if GDISP_TOTAL_DISPLAYS != 1 + #error "GDISP Multiple Drivers: You can't specify both GDISP_TOTAL_DISPLAYS and GDISP_DRIVER_LIST + #endif #ifndef GDISP_PIXELFORMAT - #error "GDISP Multiple Controllers: You must specify a value for GDISP_PIXELFORMAT" + #error "GDISP Multiple Drivers: You must specify a value for GDISP_PIXELFORMAT when using GDISP_DRIVER_LIST" #endif #endif #if GDISP_NEED_AUTOFLUSH && GDISP_NEED_TIMERFLUSH