diff --git a/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c b/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c index bfe430df..802f2822 100644 --- a/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c +++ b/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c @@ -12,7 +12,7 @@ #define GDISP_DRIVER_VMT GDISPVMT_uGFXnet #include "drivers/multiple/uGFXnet/gdisp_lld_config.h" #include "src/gdisp/driver.h" -#include "drivers/multiple/uGFXnet/uGFXnetProtocol.h" +#include "uGFXnetProtocol.h" #ifndef GDISP_SCREEN_WIDTH #define GDISP_SCREEN_WIDTH 640 @@ -47,6 +47,7 @@ #if defined(WIN32) || GFX_USE_OS_WIN32 #include #define SOCKET_TYPE SOCKET + #define socklen_t int static void StopSockets(void) { WSACleanup(); diff --git a/src/gdisp/driver.h b/src/gdisp/driver.h index 82435589..5213e5ae 100644 --- a/src/gdisp/driver.h +++ b/src/gdisp/driver.h @@ -36,6 +36,17 @@ * @name GDISP hardware accelerated support * @{ */ + /** + * @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 This is most useful for displays such as remote network displays. + */ + #ifndef GDISP_HARDWARE_DEINIT + #define GDISP_HARDWARE_DEINIT HARDWARE_DEFAULT + #endif + /** * @brief The display hardware can benefit from being flushed. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT @@ -215,7 +226,7 @@ struct GDisplay { struct GDriver d; // This must be the first element - #define gvmt(g) ((const GDISPVMT const *)(g)->d.vmt) // For ease of access to the vmt member + #define gvmt(g) ((const GDISPVMT const *)((g)->d.vmt)) // For ease of access to the vmt member struct GDISPControl { coord_t Width; @@ -278,6 +289,7 @@ struct GDisplay { typedef struct GDISPVMT { GDriverVMT vmtdriver; bool_t (*init)(GDisplay *g); + void (*deinit)(GDisplay *g); void (*writestart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy void (*writepos)(GDisplay *g); // Uses p.x,p.y void (*writecolor)(GDisplay *g); // Uses p.color @@ -318,6 +330,17 @@ typedef struct GDISPVMT { */ LLDSPEC bool_t gdisp_lld_init(GDisplay *g); + #if GDISP_HARDWARE_DEINIT || defined(__DOXYGEN__) + /** + * @brief The driver is being de-initialized + * @pre GDISP_HARDWARE_FLUSH is TRUE + * + * @param[in] g The driver structure + * + */ + LLDSPEC void gdisp_lld_deinit(GDisplay *g); + #endif + #if GDISP_HARDWARE_FLUSH || defined(__DOXYGEN__) /** * @brief Flush the current drawing operations to the display @@ -559,6 +582,7 @@ typedef struct GDISPVMT { #else #define gdisp_lld_init(g) gvmt(g)->init(g) + #define gdisp_lld_deinit(g) gvmt(g)->deinit(g) #define gdisp_lld_flush(g) gvmt(g)->flush(g) #define gdisp_lld_write_start(g) gvmt(g)->writestart(g) #define gdisp_lld_write_pos(g) gvmt(g)->writepos(g) @@ -594,12 +618,18 @@ typedef struct GDISPVMT { // Routines needed by the general driver VMT bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance); - void _gdispDeinitDriver(GDriver *g); + void _gdispPostInitDriver(GDriver *g); + void _gdispDeInitDriver(GDriver *g); // Build the VMT const GDISPVMT const GDISP_DRIVER_VMT[1] = {{ - { GDRIVER_TYPE_DISPLAY, 0, sizeof(GDisplay), _gdispInitDriver, _gdispDeinitDriver }, + { GDRIVER_TYPE_DISPLAY, 0, sizeof(GDisplay), _gdispInitDriver, _gdispPostInitDriver, _gdispDeInitDriver }, gdisp_lld_init, + #if GDISP_HARDWARE_DEINIT + gdisp_lld_deinit, + #else + 0, + #endif #if GDISP_HARDWARE_STREAM_WRITE gdisp_lld_write_start, #if GDISP_HARDWARE_STREAM_POS diff --git a/src/gdisp/gdisp_gdisp.c b/src/gdisp/gdisp_gdisp.c index 5b99da6c..a34788b2 100644 --- a/src/gdisp/gdisp_gdisp.c +++ b/src/gdisp/gdisp_gdisp.c @@ -55,10 +55,12 @@ GDisplay *GDISP; #define MUTEX_INIT(g) gfxMutexInit(&(g)->mutex) #define MUTEX_ENTER(g) gfxMutexEnter(&(g)->mutex) #define MUTEX_EXIT(g) gfxMutexExit(&(g)->mutex) + #define MUTEX_DEINIT(g) gfxMutexDestroy(&(g)->mutex) #else #define MUTEX_INIT(g) #define MUTEX_ENTER(g) #define MUTEX_EXIT(g) + #define MUTEX_DEINIT(g) #endif #define NEED_CLIPPING (GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) @@ -564,18 +566,68 @@ 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) + { + int i; + + extern GDriverVMTList GDISP_CONTROLLER_LIST; + static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; + + for(i = 0; i < GDISP_TOTAL_CONTROLLERS; 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; + + extern GDriverVMTList GDISPVMT_OnlyOne; + + for(cnt = 0; cnt < GDISP_TOTAL_DISPLAYS; cnt++) + gdriverRegister(GDISPVMT_OnlyOne); + } + + // One and only one display + #else + { + extern GDriverVMTList GDISPVMT_OnlyOne; + + gdriverRegister(GDISPVMT_OnlyOne); + } + #endif + // Re-clear the display after the timeout if we added the logo #if GDISP_STARTUP_LOGO_TIMEOUT > 0 - GDisplay *g; + { + GDisplay *g; - gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); - initDone = TRUE; + gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); - for(g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, 0); g; g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g)) { - gdispGClear(g, GDISP_STARTUP_COLOR); - #if GDISP_HARDWARE_FLUSH - gdispGFlush(g); - #endif + for(g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, 0); g; g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g)) { + gdispGClear(g, GDISP_STARTUP_COLOR); + #if GDISP_HARDWARE_FLUSH + gdispGFlush(g); + #endif + } + + initDone = TRUE; } #endif @@ -605,22 +657,32 @@ bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance) { MUTEX_ENTER(gd); ret = gdisp_lld_init(gd); MUTEX_EXIT(gd); - if (!ret) return FALSE; + return ret; - // Set orientation, clip, blankscreen, startup logo and then flush + #undef gd +} + +void _gdispPostInitDriver(GDriver *g) { + #define gd ((GDisplay *)g) + + // Set orientation, clip #if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL gdispGControl(gd, GDISP_CONTROL_ORIENTATION, (void *)GDISP_DEFAULT_ORIENTATION); #endif #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP gdispGSetClip(gd, 0, 0, gd->g.Width, gd->g.Height); #endif + + // Clear the Screen gdispGClear(gd, GDISP_STARTUP_COLOR); + // Display the startup logo if this is a static initialised display #if GDISP_STARTUP_LOGO_TIMEOUT > 0 if (!initDone) StartupLogoDisplay(gd); #endif + // Flush #if GDISP_HARDWARE_FLUSH gdispGFlush(gd); #endif @@ -629,14 +691,28 @@ bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance) { if (!GDISP) GDISP = gd; - return TRUE; - #undef gd } -void _gdispDeinitDriver(GDriver *g) { - (void) g; - // For now do nothing +void _gdispDeInitDriver(GDriver *g) { + #define gd ((GDisplay *)g) + + if (GDISP == gd) + GDISP = (GDisplay *)gdriverGetInstance(GDRIVER_TYPE_DISPLAY, 0); + + #if GDISP_HARDWARE_DEINIT + #if GDISP_HARDWARE_DEINIT == HARDWARE_AUTODETECT + if (gvmt(gd)->deinit) + #endif + { + MUTEX_ENTER(gd); + gdisp_lld_deinit(gd); + MUTEX_EXIT(gd); + } + #endif + MUTEX_DEINIT(gd); + + #undef gd } GDisplay *gdispGetDisplay(unsigned display) { diff --git a/src/gdriver/gdriver_gdriver.c b/src/gdriver/gdriver_gdriver.c index 2c73719e..90a1d932 100644 --- a/src/gdriver/gdriver_gdriver.c +++ b/src/gdriver/gdriver_gdriver.c @@ -14,51 +14,8 @@ // Define the tables to hold the driver instances. static GDriver *dhead; -// Definition that allows getting addresses of structures -typedef const struct GDriverVMT const VMT_EL[1]; - // The system initialization. void _gdriverInit(void) { - #if GFX_USE_GDISP - { - // 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 VMT_EL 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) - int i; - - - extern VMT_EL GDISP_CONTROLLER_LIST; - static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; - for(i = 0; i < GDISP_TOTAL_CONTROLLERS; 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; - - extern VMT_EL GDISPVMT_OnlyOne; - for(cnt = 0; cnt < GDISP_TOTAL_DISPLAYS; cnt++) - gdriverRegister(GDISPVMT_OnlyOne); - - // One and only one display - #else - extern VMT_EL GDISPVMT_OnlyOne; - gdriverRegister(GDISPVMT_OnlyOne); - #endif - } - #endif // Drivers not loaded yet // GINPUT_NEED_MOUSE @@ -107,6 +64,10 @@ GDriver *gdriverRegister(const GDriverVMT *vmt) { else dhead = pd; + // Do the post init + if (vmt->postinit) + vmt->postinit(pd); + return pd; } diff --git a/src/gdriver/sys_defs.h b/src/gdriver/sys_defs.h index c5ab9862..7f50fc6d 100644 --- a/src/gdriver/sys_defs.h +++ b/src/gdriver/sys_defs.h @@ -67,12 +67,27 @@ typedef struct GDriverVMT { uint16_t type; // @< What type of driver this is uint16_t flags; // @< Flags for the driver. Meaning is specific to each driver type. uint32_t objsize; // @< How big the runtime driver structure is - bool_t (*init)(GDriver *driver, int driverinstance, int systeminstance); // @< Initialise the driver. + bool_t (*init)(GDriver *driver, int driverinstance, int systeminstance); // @< Initialise the driver. Returns TRUE if OK. // driverinstance is the instance 0..n of this driver. // systeminstance is the instance 0..n of this type of device. + void (*postinit)(GDriver *driver); // @< Called once the driver is registered. void (*deinit)(GDriver *driver); // @< De-initialise the driver } GDriverVMT; +/** + * @brief A definition that allows getting addresses of GDriverVMT structures to put into a list. + * @note eg. + * const MyDriverVMTtype a[1] = {{...}}; + * const MyDriverVMTtype b[1] = {{...}}; + * ... + * #define DRIVER_LIST a, b + * extern GDriverVMTList DRIVER_LIST; // Now treated as single element arrays of GDriverVMT + * const GDriverVMT const * mylist = { DRIVER_LIST }; + * + * + */ +typedef const struct GDriverVMT const GDriverVMTList[1]; + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/