diff options
Diffstat (limited to 'src/gdisp/gdisp_driver.h')
-rw-r--r-- | src/gdisp/gdisp_driver.h | 1070 |
1 files changed, 1070 insertions, 0 deletions
diff --git a/src/gdisp/gdisp_driver.h b/src/gdisp/gdisp_driver.h new file mode 100644 index 00000000..085e248f --- /dev/null +++ b/src/gdisp/gdisp_driver.h @@ -0,0 +1,1070 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file src/gdisp/gdisp_driver.h + * @brief GDISP Graphic Driver subsystem low level driver header. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_H +#define _GDISP_LLD_H + +#if GFX_USE_GDISP + +// Include the GDRIVER infrastructure +#include "src/gdriver/gdriver.h" + +// Are we currently compiling the driver itself? +#if defined(GDISP_DRIVER_VMT) + #define IN_DRIVER TRUE +#else + #define IN_DRIVER FALSE +#endif + +// Is this a multiple driver situation? +#if defined(GDISP_DRIVER_LIST) + #define IS_MULTIPLE TRUE +#else + #define IS_MULTIPLE FALSE +#endif + +// Do we need to use VMT calling rather than direct calls to the driver? +#if IS_MULTIPLE || GDISP_NEED_PIXMAP + #define USE_VMT TRUE +#else + #define USE_VMT FALSE +#endif + +// Are we in the pixmap virtual driver +#ifndef IN_PIXMAP_DRIVER + #define IN_PIXMAP_DRIVER FALSE +#endif + +//------------------------------------------------------------------------------------------------------------ + +// Our special auto-detect hardware code which uses the VMT. +#define HARDWARE_AUTODETECT 2 + +#if USE_VMT && !IN_DRIVER + // Multiple controllers the default is to hardware detect + #define HARDWARE_DEFAULT HARDWARE_AUTODETECT +#else + // The default is not to include code functions that aren't needed + #define HARDWARE_DEFAULT FALSE +#endif + +//------------------------------------------------------------------------------------------------------------ + +/** + * @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_DRIVER_LIST is defined + * @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 + * + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined + * @note Some controllers ** require ** the application to flush + */ + #ifndef GDISP_HARDWARE_FLUSH + #define GDISP_HARDWARE_FLUSH HARDWARE_DEFAULT + #endif + + /** + * @brief Hardware streaming writing is supported. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @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 + #define GDISP_HARDWARE_STREAM_WRITE HARDWARE_DEFAULT + #endif + + /** + * @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_DRIVER_LIST is defined + * + */ + #ifndef GDISP_HARDWARE_STREAM_READ + #define GDISP_HARDWARE_STREAM_READ HARDWARE_DEFAULT + #endif + + /** + * @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_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. + */ + #ifndef GDISP_HARDWARE_STREAM_POS + #define GDISP_HARDWARE_STREAM_POS HARDWARE_DEFAULT + #endif + + /** + * @brief Hardware accelerated draw pixel. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @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 + #define GDISP_HARDWARE_DRAWPIXEL HARDWARE_DEFAULT + #endif + + /** + * @brief Hardware accelerated screen clears. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @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 + #define GDISP_HARDWARE_CLEARS HARDWARE_DEFAULT + #endif + + /** + * @brief Hardware accelerated rectangular fills. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined + */ + #ifndef GDISP_HARDWARE_FILLS + #define GDISP_HARDWARE_FILLS HARDWARE_DEFAULT + #endif + + /** + * @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_DRIVER_LIST is defined + */ + #ifndef GDISP_HARDWARE_BITFILLS + #define GDISP_HARDWARE_BITFILLS HARDWARE_DEFAULT + #endif + + /** + * @brief Hardware accelerated scrolling. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined + */ + #ifndef GDISP_HARDWARE_SCROLL + #define GDISP_HARDWARE_SCROLL HARDWARE_DEFAULT + #endif + + /** + * @brief Reading back of pixel values. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_DRIVER_LIST is defined + */ + #ifndef GDISP_HARDWARE_PIXELREAD + #define GDISP_HARDWARE_PIXELREAD HARDWARE_DEFAULT + #endif + + /** + * @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_DRIVER_LIST is defined + */ + #ifndef GDISP_HARDWARE_CONTROL + #define GDISP_HARDWARE_CONTROL HARDWARE_DEFAULT + #endif + + /** + * @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_DRIVER_LIST is defined + */ + #ifndef GDISP_HARDWARE_QUERY + #define GDISP_HARDWARE_QUERY HARDWARE_DEFAULT + #endif + + /** + * @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_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 + * driver do not exceed the display area (provided GDISP_NEED_CLIP or GDISP_NEED_VALIDATION + * has been set). + */ + #ifndef GDISP_HARDWARE_CLIP + #define GDISP_HARDWARE_CLIP HARDWARE_DEFAULT + #endif +/** @} */ + +//------------------------------------------------------------------------------------------------------------ + +// For pixmaps certain routines MUST not be FALSE as they are needed for pixmap drawing +// Similarly some routines MUST not be TRUE as pixmap's don't provide them. +#if GDISP_NEED_PIXMAP && !IN_DRIVER + #if !GDISP_HARDWARE_DEINIT + #undef GDISP_HARDWARE_DEINIT + #define GDISP_HARDWARE_DEINIT HARDWARE_AUTODETECT + #endif + #if !GDISP_HARDWARE_DRAWPIXEL + #undef GDISP_HARDWARE_DRAWPIXEL + #define GDISP_HARDWARE_DRAWPIXEL HARDWARE_AUTODETECT + #endif + #if !GDISP_HARDWARE_PIXELREAD + #undef GDISP_HARDWARE_PIXELREAD + #define GDISP_HARDWARE_PIXELREAD HARDWARE_AUTODETECT + #endif + #if !GDISP_HARDWARE_CONTROL + #undef GDISP_HARDWARE_CONTROL + #define GDISP_HARDWARE_CONTROL HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_FLUSH == TRUE + #undef GDISP_HARDWARE_FLUSH + #define GDISP_HARDWARE_FLUSH HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_STREAM_WRITE == TRUE + #undef GDISP_HARDWARE_STREAM_WRITE + #define GDISP_HARDWARE_STREAM_WRITE HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_STREAM_READ == TRUE + #undef GDISP_HARDWARE_STREAM_READ + #define GDISP_HARDWARE_STREAM_READ HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_CLEARS == TRUE + #undef GDISP_HARDWARE_CLEARS + #define GDISP_HARDWARE_CLEARS HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_FILLS == TRUE + #undef GDISP_HARDWARE_FILLS + #define GDISP_HARDWARE_FILLS HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_BITFILLS == TRUE + #undef GDISP_HARDWARE_BITFILLS + #define GDISP_HARDWARE_BITFILLS HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_SCROLL == TRUE + #undef GDISP_HARDWARE_SCROLL + #define GDISP_HARDWARE_SCROLL HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_QUERY == TRUE + #undef GDISP_HARDWARE_QUERY + #define GDISP_HARDWARE_QUERY HARDWARE_AUTODETECT + #endif + #if GDISP_HARDWARE_CLIP == TRUE + #undef GDISP_HARDWARE_CLIP + #define GDISP_HARDWARE_CLIP HARDWARE_AUTODETECT + #endif +#endif + +//------------------------------------------------------------------------------------------------------------ + +/* Verify information for packed pixels and define a non-packed pixel macro */ +#if !GDISP_PACKED_PIXELS + #define gdispPackPixels(buf,cx,x,y,c) { ((color_t *)(buf))[(y)*(cx)+(x)] = (c); } +#elif !GDISP_HARDWARE_BITFILLS + #error "GDISP: packed pixel formats are only supported for hardware accelerated drivers." +#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888 \ + && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB444 \ + && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB666 \ + && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM + #error "GDISP: A packed pixel format has been specified for an unsupported pixel format." +#endif + +/* Support routine for packed pixel formats */ +#if !defined(gdispPackPixels) || defined(__DOXYGEN__) + /** + * @brief Pack a pixel into a pixel buffer. + * @note This function performs no buffer boundary checking + * regardless of whether GDISP_NEED_CLIP has been specified. + * + * @param[in] buf The buffer to put the pixel in + * @param[in] cx The width of a pixel line + * @param[in] x, y The location of the pixel to place + * @param[in] color The color to put into the buffer + * + * @api + */ + void gdispPackPixels(const pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color); +#endif + +//------------------------------------------------------------------------------------------------------------ + +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 + + struct GDISPControl { + coord_t Width; + coord_t Height; + orientation_t Orientation; + powermode_t Powermode; + uint8_t Backlight; + uint8_t Contrast; + } g; + + void * priv; // A private area just for the drivers use. + void * board; // A private area just for the board interfaces use. + + uint8_t systemdisplay; + uint8_t controllerdisplay; + uint16_t flags; + #define GDISP_FLG_INSTREAM 0x0001 // We are in a user based stream operation + #define GDISP_FLG_SCRSTREAM 0x0002 // The stream area currently covers the whole screen + #define GDISP_FLG_DRIVER 0x0004 // This flags and above are for use by the driver + + // Multithread Mutex + #if GDISP_NEED_MULTITHREAD + gfxMutex mutex; + #endif + + // Software clipping + #if GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION) + coord_t clipx0, clipy0; + coord_t clipx1, clipy1; /* not inclusive */ + #endif + + // Driver call parameters + struct { + coord_t x, y; + coord_t cx, cy; + coord_t x1, y1; + coord_t x2, y2; + color_t color; + void *ptr; + } p; + + // In call working buffers + + #if GDISP_NEED_TEXT + // Text rendering parameters + struct { + font_t font; + color_t color; + color_t bgcolor; + coord_t clipx0, clipy0; + coord_t clipx1, clipy1; + } t; + #endif + #if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM_WRITE && GDISP_HARDWARE_BITFILLS)) + // A pixel line buffer + color_t linebuf[GDISP_LINEBUF_SIZE]; + #endif +}; + +typedef struct GDISPVMT { + GDriverVMT d; + #define GDISP_VFLG_DYNAMICONLY 0x0001 // This display should never be statically initialised + #define GDISP_VFLG_PIXMAP 0x0002 // This is a pixmap display + 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 + void (*writestop)(GDisplay *g); // Uses no parameters + void (*readstart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy + color_t (*readcolor)(GDisplay *g); // Uses no parameters + void (*readstop)(GDisplay *g); // Uses no parameters + void (*pixel)(GDisplay *g); // Uses p.x,p.y p.color + void (*clear)(GDisplay *g); // Uses p.color + void (*fill)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy p.color + void (*blit)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy p.x1,p.y1 (=srcx,srcy) p.x2 (=srccx), p.ptr (=buffer) + color_t (*get)(GDisplay *g); // Uses p.x,p.y + void (*vscroll)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy, p.y1 (=lines) p.color + void (*control)(GDisplay *g); // Uses p.x (=what) p.ptr (=value) + void *(*query)(GDisplay *g); // Uses p.x (=what); + void (*setclip)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy + void (*flush)(GDisplay *g); // Uses no parameters +} GDISPVMT; + +//------------------------------------------------------------------------------------------------------------ + +// Do we need function definitions or macro's (via the VMT) +#if IN_DRIVER || !USE_VMT || defined(__DOXYGEN__) + #ifdef __cplusplus + extern "C" { + #endif + + // Should the driver routines should be static or not + #if USE_VMT + #define LLDSPEC static + #else + #define LLDSPEC + #endif + + /** + * @brief Initialize the driver. + * @return TRUE if successful. + * @param[in] g The driver structure + * @param[out] g->g The driver must fill in the GDISPControl structure + */ + 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 + * @pre GDISP_HARDWARE_FLUSH is TRUE + * + * @param[in] g The driver structure + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_flush(GDisplay *g); + #endif + + #if GDISP_HARDWARE_STREAM_WRITE || defined(__DOXYGEN__) + /** + * @brief Start a streamed write operation + * @pre GDISP_HARDWARE_STREAM_WRITE is TRUE + * + * @param[in] g The driver structure + * + * @note g->p.x,g->p.y The window position + * @note g->p.cx,g->p.cy The window size + * + * @note The parameter variables must not be altered by the driver. + * @note Streaming operations that wrap the defined window have + * undefined results. + * @note This must be followed by a call to @p gdisp_lld_write_pos() if GDISP_HARDWARE_STREAM_POS is TRUE. + */ + LLDSPEC void gdisp_lld_write_start(GDisplay *g); + + /** + * @brief Send a pixel to the current streaming position and then increment that position + * @pre GDISP_HARDWARE_STREAM_WRITE is TRUE + * + * @param[in] g The driver structure + * + * @note g->p.color The color to display at the curent position + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_write_color(GDisplay *g); + + /** + * @brief End the current streaming write operation + * @pre GDISP_HARDWARE_STREAM_WRITE is TRUE + * + * @param[in] g The driver structure + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_write_stop(GDisplay *g); + + #if GDISP_HARDWARE_STREAM_POS || defined(__DOXYGEN__) + /** + * @brief Change the current position within the current streaming window + * @pre GDISP_HARDWARE_STREAM_POS is TRUE and GDISP_HARDWARE_STREAM_WRITE is TRUE + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The new position (which will always be within the existing stream window) + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_write_pos(GDisplay *g); + #endif + #endif + + #if GDISP_HARDWARE_STREAM_READ || defined(__DOXYGEN__) + /** + * @brief Start a streamed read operation + * @pre GDISP_HARDWARE_STREAM_READ is TRUE + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The window position + * @param[in] g->p.cx,g->p.cy The window size + * + * @note The parameter variables must not be altered by the driver. + * @note Streaming operations that wrap the defined window have + * undefined results. + */ + LLDSPEC void gdisp_lld_read_start(GDisplay *g); + + /** + * @brief Read a pixel from the current streaming position and then increment that position + * @return The color at the current position + * @pre GDISP_HARDWARE_STREAM_READ is TRUE + * + * @param[in] g The driver structure + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC color_t gdisp_lld_read_color(GDisplay *g); + + /** + * @brief End the current streaming operation + * @pre GDISP_HARDWARE_STREAM_READ is TRUE + * + * @param[in] g The driver structure + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_read_stop(GDisplay *g); + #endif + + #if GDISP_HARDWARE_DRAWPIXEL || defined(__DOXYGEN__) + /** + * @brief Draw a pixel + * @pre GDISP_HARDWARE_DRAWPIXEL is TRUE + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The pixel position + * @param[in] g->p.color The color to set + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g); + #endif + + #if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__) + /** + * @brief Clear the screen using the defined color + * @pre GDISP_HARDWARE_CLEARS is TRUE + * + * @param[in] g The driver structure + * @param[in] g->p.color The color to set + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_clear(GDisplay *g); + #endif + + #if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) + /** + * @brief Fill an area with a single color + * @pre GDISP_HARDWARE_FILLS is TRUE + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The area position + * @param[in] g->p.cx,g->p.cy The area size + * @param[in] g->p.color The color to set + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_fill_area(GDisplay *g); + #endif + + #if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) + /** + * @brief Fill an area using a bitmap + * @pre GDISP_HARDWARE_BITFILLS is TRUE + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The area position + * @param[in] g->p.cx,g->p.cy The area size + * @param[in] g->p.x1,g->p.y1 The starting position in the bitmap + * @param[in] g->p.x2 The width of a bitmap line + * @param[in] g->p.ptr The pointer to the bitmap + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_blit_area(GDisplay *g); + #endif + + #if GDISP_HARDWARE_PIXELREAD || defined(__DOXYGEN__) + /** + * @brief Read a pixel from the display + * @return The color at the defined position + * @pre GDISP_HARDWARE_PIXELREAD is TRUE (and the application needs it) + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The pixel position + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g); + #endif + + #if (GDISP_HARDWARE_SCROLL && GDISP_NEED_SCROLL) || defined(__DOXYGEN__) + /** + * @brief Scroll an area of the screen + * @pre GDISP_HARDWARE_SCROLL is TRUE (and the application needs it) + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The area position + * @param[in] g->p.cx,g->p.cy The area size + * @param[in] g->p.y1 The number of lines to scroll (positive or negative) + * + * @note The parameter variables must not be altered by the driver. + * @note This can be easily implemented if the hardware supports + * display area to display area copying. + * @note Clearing the exposed area on the scroll operation is not + * needed as the high level code handles this. + */ + LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g); + #endif + + #if (GDISP_HARDWARE_CONTROL && GDISP_NEED_CONTROL) || defined(__DOXYGEN__) + /** + * @brief Control some feature of the hardware + * @pre GDISP_HARDWARE_CONTROL is TRUE (and the application needs it) + * + * @param[in] g The driver structure + * @param[in] g->p.x The operation to perform + * @param[in] g->p.ptr The operation parameter + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_control(GDisplay *g); + #endif + + #if (GDISP_HARDWARE_QUERY && GDISP_NEED_QUERY) || defined(__DOXYGEN__) + /** + * @brief Query some feature of the hardware + * @return The information requested (typecast as void *) + * @pre GDISP_HARDWARE_QUERY is TRUE (and the application needs it) + * + * @param[in] g The driver structure + * @param[in] g->p.x What to query + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void *gdisp_lld_query(GDisplay *g); // Uses p.x (=what); + #endif + + #if (GDISP_HARDWARE_CLIP && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION)) || defined(__DOXYGEN__) + /** + * @brief Set the hardware clipping area + * @pre GDISP_HARDWARE_CLIP is TRUE (and the application needs it) + * + * @param[in] g The driver structure + * @param[in] g->p.x,g->p.y The area position + * @param[in] g->p.cx,g->p.cy The area size + * + * @note The parameter variables must not be altered by the driver. + */ + LLDSPEC void gdisp_lld_set_clip(GDisplay *g); + #endif + + #ifdef __cplusplus + } + #endif + +#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) + #define gdisp_lld_write_color(g) gvmt(g)->writecolor(g) + #define gdisp_lld_write_stop(g) gvmt(g)->writestop(g) + #define gdisp_lld_read_start(g) gvmt(g)->readstart(g) + #define gdisp_lld_read_color(g) gvmt(g)->readcolor(g) + #define gdisp_lld_read_stop(g) gvmt(g)->readstop(g) + #define gdisp_lld_draw_pixel(g) gvmt(g)->pixel(g) + #define gdisp_lld_clear(g) gvmt(g)->clear(g) + #define gdisp_lld_fill_area(g) gvmt(g)->fill(g) + #define gdisp_lld_blit_area(g) gvmt(g)->blit(g) + #define gdisp_lld_get_pixel_color(g) gvmt(g)->get(g) + #define gdisp_lld_vertical_scroll(g) gvmt(g)->vscroll(g) + #define gdisp_lld_control(g) gvmt(g)->control(g) + #define gdisp_lld_query(g) gvmt(g)->query(g) + #define gdisp_lld_set_clip(g) gvmt(g)->setclip(g) +#endif + +//------------------------------------------------------------------------------------------------------------ + +// If compiling the driver then build the VMT and set the low level driver color macros. +#if IN_DRIVER + + // Make sure the driver has a valid model + #if !GDISP_HARDWARE_STREAM_WRITE && !GDISP_HARDWARE_DRAWPIXEL + #error "GDISP Driver: Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be TRUE" + #endif + + // If we are not using multiple displays then hard-code the VMT name (except for the pixmap driver) + #if !IS_MULTIPLE && !IN_PIXMAP_DRIVER + #undef GDISP_DRIVER_VMT + #define GDISP_DRIVER_VMT GDISPVMT_OnlyOne + #endif + + // Default the flags if the driver doesn't specify any + #ifndef GDISP_DRIVER_VMT_FLAGS + #define GDISP_DRIVER_VMT_FLAGS 0 + #endif + + // Routines needed by the general driver VMT + #ifdef __cplusplus + extern "C" { + #endif + bool_t _gdispInitDriver(GDriver *g, void *param, unsigned driverinstance, unsigned systeminstance); + void _gdispPostInitDriver(GDriver *g); + void _gdispDeInitDriver(GDriver *g); + #ifdef __cplusplus + } + #endif + + // Build the VMT + const GDISPVMT const GDISP_DRIVER_VMT[1] = {{ + { 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 + gdisp_lld_write_pos, + #else + 0, + #endif + gdisp_lld_write_color, + gdisp_lld_write_stop, + #else + 0, 0, 0, 0, + #endif + #if GDISP_HARDWARE_STREAM_READ + gdisp_lld_read_start, + gdisp_lld_read_color, + gdisp_lld_read_stop, + #else + 0, 0, 0, + #endif + #if GDISP_HARDWARE_DRAWPIXEL + gdisp_lld_draw_pixel, + #else + 0, + #endif + #if GDISP_HARDWARE_CLEARS + gdisp_lld_clear, + #else + 0, + #endif + #if GDISP_HARDWARE_FILLS + gdisp_lld_fill_area, + #else + 0, + #endif + #if GDISP_HARDWARE_BITFILLS + gdisp_lld_blit_area, + #else + 0, + #endif + #if GDISP_HARDWARE_PIXELREAD + gdisp_lld_get_pixel_color, + #else + 0, + #endif + #if GDISP_HARDWARE_SCROLL && GDISP_NEED_SCROLL + gdisp_lld_vertical_scroll, + #else + 0, + #endif + #if GDISP_HARDWARE_CONTROL && GDISP_NEED_CONTROL + gdisp_lld_control, + #else + 0, + #endif + #if GDISP_HARDWARE_QUERY && GDISP_NEED_QUERY + gdisp_lld_query, + #else + 0, + #endif + #if GDISP_HARDWARE_CLIP && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION) + gdisp_lld_set_clip, + #else + 0, + #endif + #if GDISP_HARDWARE_FLUSH + gdisp_lld_flush, + #else + 0, + #endif + }}; + + //-------------------------------------------------------------------------------------------------------- + + /* Low level driver pixel format information */ + //------------------------- + // True-Color color system + //------------------------- + #if GDISP_LLD_PIXELFORMAT & GDISP_COLORSYSTEM_TRUECOLOR + #define LLDCOLOR_SYSTEM GDISP_COLORSYSTEM_TRUECOLOR + + // Calculate the number of bits + #define LLDCOLOR_BITS_R ((GDISP_LLD_PIXELFORMAT>>8) & 0x0F) + #define LLDCOLOR_BITS_G ((GDISP_LLD_PIXELFORMAT>>4) & 0x0F) + #define LLDCOLOR_BITS_B ((GDISP_LLD_PIXELFORMAT>>0) & 0x0F) + #define LLDCOLOR_BITS (LLDCOLOR_BITS_R + LLDCOLOR_BITS_G + LLDCOLOR_BITS_B) + + // From the number of bits determine COLOR_TYPE, COLOR_TYPE_BITS and masking + #if LLDCOLOR_BITS <= 8 + #define LLDCOLOR_TYPE uint8_t + #define LLDCOLOR_TYPE_BITS 8 + #elif LLDCOLOR_BITS <= 16 + #define LLDCOLOR_TYPE uint16_t + #define LLDCOLOR_TYPE_BITS 16 + #elif LLDCOLOR_BITS <= 32 + #define LLDCOLOR_TYPE uint32_t + #define LLDCOLOR_TYPE_BITS 32 + #else + #error "GDISP: Cannot define low level driver color types with more than 32 bits" + #endif + #if LLDCOLOR_TYPE_BITS == LLDCOLOR_BITS + #define LLDCOLOR_NEEDS_MASK FALSE + #else + #define LLDCOLOR_NEEDS_MASK TRUE + #endif + #define LLDCOLOR_MASK() ((1 << LLDCOLOR_BITS)-1) + + // Calculate the component bit shifts + #if (GDISP_LLD_PIXELFORMAT & GDISP_COLORSYSTEM_MASK) == GDISP_COLORSYSTEM_RGB + #define LLDCOLOR_SHIFT_R (LLDCOLOR_BITS_B+LLDCOLOR_BITS_G) + #define LLDCOLOR_SHIFT_G LLDCOLOR_BITS_B + #define LLDCOLOR_SHIFT_B 0 + #else + #define LLDCOLOR_SHIFT_B (LLDCOLOR_BITS_R+LLDCOLOR_BITS_G) + #define LLDCOLOR_SHIFT_G LLDCOLOR_BITS_R + #define LLDCOLOR_SHIFT_R 0 + #endif + + // Calculate LLDRED_OF, LLDGREEN_OF, LLDBLUE_OF and LLDRGB2COLOR + #if LLDCOLOR_BITS_R + LLDCOLOR_SHIFT_R == 8 + #define LLDRED_OF(c) ((c) & (((1<<LLDCOLOR_BITS_R)-1) << LLDCOLOR_SHIFT_R)) + #define LLDRGB2COLOR_R(r) ((LLDCOLOR_TYPE)((r) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_R))-1)))) + #elif LLDCOLOR_BITS_R + LLDCOLOR_SHIFT_R > 8 + #define LLDRED_OF(c) (((c) & (((1<<LLDCOLOR_BITS_R)-1) << LLDCOLOR_SHIFT_R)) >> (LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R-8)) + #define LLDRGB2COLOR_R(r) (((LLDCOLOR_TYPE)((r) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_R))-1)))) << (LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R-8)) + #else // LLDCOLOR_BITS_R + LLDCOLOR_SHIFT_R < 8 + #define LLDRED_OF(c) (((c) & (((1<<LLDCOLOR_BITS_R)-1) << LLDCOLOR_SHIFT_R)) << (8-(LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R))) + #define LLDRGB2COLOR_R(r) (((LLDCOLOR_TYPE)((r) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_R))-1)))) >> (8-(LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R))) + #endif + #if LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G == 8 + #define LLDGREEN_OF(c) ((c) & (((1<<LLDCOLOR_BITS_G)-1) << LLDCOLOR_SHIFT_G)) + #define LLDRGB2COLOR_G(g) ((LLDCOLOR_TYPE)((g) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_G))-1)))) + #elif LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G > 8 + #define LLDGREEN_OF(c) (((c) & (((1<<LLDCOLOR_BITS_G)-1) << LLDCOLOR_SHIFT_G)) >> (LLDCOLOR_BITS_G+LLDCOLOR_SHIFT_G-8)) + #define LLDRGB2COLOR_G(g) (((LLDCOLOR_TYPE)((g) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_G))-1)))) << (LLDCOLOR_BITS_G+LLDCOLOR_SHIFT_G-8)) + #else // LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G < 8 + #define LLDGREEN_OF(c) (((c) & (((1<<LLDCOLOR_BITS_G)-1) << LLDCOLOR_SHIFT_G)) << (8-(LLDCOLOR_BITS_G+LLDCOLOR_SHIFT_G))) + #define LLDRGB2COLOR_G(g) (((LLDCOLOR_TYPE)((g) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_G))-1)))) >> (8-(LLDCOLOR_BITS_LLDG+COLOR_SHIFT_G))) + #endif + #if LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B == 8 + #define LLDBLUE_OF(c) ((c) & (((1<<LLDCOLOR_BITS_B)-1) << LLDCOLOR_SHIFT_B)) + #define LLDRGB2COLOR_B(b) ((LLDCOLOR_TYPE)((b) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1)))) + #elif LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B > 8 + #define LLDBLUE_OF(c) (((c) & (((1<<LLDCOLOR_BITS_B)-1) << LLDCOLOR_SHIFT_B)) >> (LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B-8)) + #define LLDRGB2COLOR_B(b) (((LLDCOLOR_TYPE)((b) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1)))) << (LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B-8)) + #else // LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B < 8 + #define LLDBLUE_OF(c) (((c) & (((1<<LLDCOLOR_BITS_B)-1) << LLDCOLOR_SHIFT_B)) << (8-(LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B))) + #define LLDRGB2COLOR_B(b) (((COLOR_TYPE)((b) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1)))) >> (8-(LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B))) + #endif + #define LLDLUMA_OF(c) ((LLDRED_OF(c)+((uint16_t)LLDGREEN_OF(c)<<1)+LLDBLUE_OF(c))>>2) + #define LLDEXACT_RED_OF(c) (((uint16_t)(((c)>>LLDCOLOR_SHIFT_R)&((1<<LLDCOLOR_BITS_R)-1))*255)/((1<<LLDCOLOR_BITS_R)-1)) + #define LLDEXACT_GREEN_OF(c) (((uint16_t)(((c)>>LLDCOLOR_SHIFT_G)&((1<<LLDCOLOR_BITS_G)-1))*255)/((1<<LLDCOLOR_BITS_G)-1)) + #define LLDEXACT_BLUE_OF(c) (((uint16_t)(((c)>>LLDCOLOR_SHIFT_B)&((1<<LLDCOLOR_BITS_B)-1))*255)/((1<<LLDCOLOR_BITS_B)-1)) + #define LLDEXACT_LUMA_OF(c) ((LLDEXACT_RED_OF(c)+((uint16_t)LLDEXACT_GREEN_OF(c)<<1)+LLDEXACT_BLUE_OF(c))>>2) + #define LLDLUMA2COLOR(l) (LLDRGB2COLOR_R(l) | LLDRGB2COLOR_G(l) | LLDRGB2COLOR_B(l)) + #define LLDRGB2COLOR(r,g,b) (LLDRGB2COLOR_R(r) | LLDRGB2COLOR_G(g) | LLDRGB2COLOR_B(b)) + + // Calculate LLDHTML2COLOR + #if LLDCOLOR_BITS_R + LLDCOLOR_SHIFT_R == 24 + #define LLDHTML2COLOR_R(h) ((h) & ((0xFF & ~((1<<(8-LLDCOLOR_BITS_R))-1))<<16)) + #elif COLOR_BITS_R + COLOR_SHIFT_R > 24 + #define LLDHTML2COLOR_R(h) (((h) & ((0xFF & ~((1<<(8-LLDCOLOR_BITS_R))-1))<<16)) << (LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R-24)) + #else // COLOR_BITS_R + COLOR_SHIFT_R < 24 + #define LLDHTML2COLOR_R(h) (((h) & ((0xFF & ~((1<<(8-LLDCOLOR_BITS_R))-1))<<16)) >> (24-(LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R))) + #endif + #if LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G == 16 + #define LLDHTML2COLOR_G(h) ((h) & ((0xFF & ~((1<<(8-LLDCOLOR_BITS_G))-1))<<8)) + #elif LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G > 16 + #define LLDHTML2COLOR_G(h) (((h) & ((0xFF & ~((1<<(8-LLDCOLOR_BITS_G))-1))<<8)) << (LLDCOLOR_BITS_G+LLDCOLOR_SHIFT_G-16)) + #else // LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G < 16 + #define LLDHTML2COLOR_G(h) (((h) & ((0xFF & ~((1<<(8-LLDCOLOR_BITS_G))-1))<<8)) >> (16-(LLDCOLOR_BITS_G+LLDCOLOR_SHIFT_G))) + #endif + #if LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B == 8 + #define LLDHTML2COLOR_B(h) ((h) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1))) + #elif LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B > 8 + #define LLDHTML2COLOR_B(h) (((h) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1))) << (LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B-8)) + #else // LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B < 8 + #define LLDHTML2COLOR_B(h) (((h) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1))) >> (8-(LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B))) + #endif + #define LLDHTML2COLOR(h) ((LLDCOLOR_TYPE)(LLDHTML2COLOR_R(h) | LLDHTML2COLOR_G(h) | LLDHTML2COLOR_B(h))) + + //------------------------- + // Gray-scale color system + //------------------------- + #elif (GDISP_LLD_PIXELFORMAT & GDISP_COLORSYSTEM_MASK) == GDISP_COLORSYSTEM_GRAYSCALE + #define LLDCOLOR_SYSTEM GDISP_COLORSYSTEM_GRAYSCALE + + // Calculate the number of bits and shifts + #define LLDCOLOR_BITS (GDISP_LLD_PIXELFORMAT & 0xFF) + #define LLDCOLOR_BITS_R LLDCOLOR_BITS + #define LLDCOLOR_BITS_G LLDCOLOR_BITS + #define LLDCOLOR_BITS_B LLDCOLOR_BITS + #define LLDCOLOR_SHIFT_R 0 + #define LLDCOLOR_SHIFT_G 0 + #define LLDCOLOR_SHIFT_B 0 + + // From the number of bits determine COLOR_TYPE, COLOR_TYPE_BITS and masking + #if LLDCOLOR_BITS <= 8 + #define LLDCOLOR_TYPE uint8_t + #define LLDCOLOR_TYPE_BITS 8 + #else + #error "GDISP: Cannot define gray-scale low level driver color types with more than 8 bits" + #endif + #if LLDCOLOR_TYPE_BITS == LLDCOLOR_BITS + #define LLDCOLOR_NEEDS_MASK FALSE + #else + #define LLDCOLOR_NEEDS_MASK TRUE + #endif + #define LLDCOLOR_MASK() ((1 << LLDCOLOR_BITS)-1) + + #if COLOR_BITS == 1 + #define LLDRGB2COLOR(r,g,b) (((r)|(g)|(b)) ? 1 : 0) + #define LLDLUMA2COLOR(l) ((l) ? 1 : 0) + #define LLDHTML2COLOR(h) ((h) ? 1 : 0) + #define LLDLUMA_OF(c) ((c) ? 255 : 0) + #define LLDEXACT_LUMA_OF(c) LLDLUMA_OF(c) + #else + // They eye is more sensitive to green + #define LLDRGB2COLOR(r,g,b) ((LLDCOLOR_TYPE)(((uint16_t)(r)+(g)+(g)+(b)) >> (10-LLDCOLOR_BITS))) + #define LLDLUMA2COLOR(l) ((LLDCOLOR_TYPE)((l)>>(8-LLDCOLOR_BITS))) + #define LLDHTML2COLOR(h) ((LLDCOLOR_TYPE)(((((h)&0xFF0000)>>16)+(((h)&0x00FF00)>>7)+((h)&0x0000FF)) >> (10-LLDCOLOR_BITS))) + #define LLDLUMA_OF(c) (((c) & ((1<<LLDCOLOR_BITS)-1)) << (8-LLDCOLOR_BITS)) + #define LLDEXACT_LUMA_OF(c) ((((uint16_t)(c) & ((1<<LLDCOLOR_BITS)-1))*255)/((1<<LLDCOLOR_BITS)-1)) + #endif + + #define LLDRED_OF(c) LLDLUMA_OF(c) + #define LLDGREEN_OF(c) LLDLUMA_OF(c) + #define LLDBLUE_OF(c) LLDLUMA_OF(c) + #define LLDEXACT_RED_OF(c) LLDEXACT_LUMA_OF(c) + #define LLDEXACT_GREEN_OF(c) LLDEXACT_LUMA_OF(c) + #define LLDEXACT_BLUE_OF(c) LLDEXACT_LUMA_OF(c) + + //------------------------- + // Palette color system + //------------------------- + #elif (GDISP_LLD_PIXELFORMAT & GDISP_COLORSYSTEM_MASK) == GDISP_COLORSYSTEM_PALETTE + #define LLDCOLOR_SYSTEM GDISP_COLORSYSTEM_PALETTE + + #error "GDISP: A palette color system for low level drivers is not currently supported" + + //------------------------- + // Some other color system + //------------------------- + #else + #error "GDISP: Unsupported color system for low level drivers" + #endif + + /* Which is the larger color type */ + #if COLOR_BITS > LLDCOLOR_BITS + #define LARGER_COLOR_BITS COLOR_BITS + #define LARGER_COLOR_TYPE COLOR_TYPE + #else + #define LARGER_COLOR_BITS LLDCOLOR_BITS + #define LARGER_COLOR_TYPE LLDCOLOR_TYPE + #endif + + /** + * @brief Controls color conversion accuracy for a low level driver + * @details Should higher precision be used when converting colors. + * @note Color conversion is only necessary if GDISP_PIXELFORMAT != GDISP_LLD_PIXELFORMAT + * @note It only makes sense to turn this on if you have a high bit depth display but + * are running the application in low bit depths. + * @note To achieve higher color accuracy bit shifting is replaced with multiplies and divides. + */ + #ifndef GDISP_HARDWARE_USE_EXACT_COLOR + #if LLDCOLOR_BITS_R - COLOR_BITS_R >= LLDCOLOR_BITS_R/2 || LLDCOLOR_BITS_G - COLOR_BITS_G >= LLDCOLOR_BITS_G/2 || LLDCOLOR_BITS_B - COLOR_BITS_B >= LLDCOLOR_BITS_B/2 + #define GDISP_HARDWARE_USE_EXACT_COLOR TRUE + #else + #define GDISP_HARDWARE_USE_EXACT_COLOR FALSE + #endif + #endif + + /* Low level driver pixel format conversion functions */ + #if GDISP_PIXELFORMAT == GDISP_LLD_PIXELFORMAT || defined(__DOXYGEN__) + /** + * @brief Convert from a standard color format to the low level driver pixel format + * @note For use only by low level drivers + */ + #define gdispColor2Native(c) (c) + /** + * @brief Convert from a low level driver pixel format to the standard color format + * @note For use only by low level drivers + */ + #define gdispNative2Color(c) (c) + #else + static LLDCOLOR_TYPE gdispColor2Native(color_t c) { + #if COLOR_SYSTEM == GDISP_COLORSYSTEM_GRAYSCALE || LLDCOLOR_SYSTEM == GDISP_COLORSYSTEM_GRAYSCALE + #if GDISP_HARDWARE_USE_EXACT_COLOR + return LLDLUMA2COLOR(EXACT_LUMA_OF(c)); + #else + return LLDLUMA2COLOR(LUMA_OF(c)); + #endif + #elif COLOR_SYSTEM == GDISP_COLORSYSTEM_TRUECOLOR && LLDCOLOR_SYSTEM == GDISP_COLORSYSTEM_TRUECOLOR + #if GDISP_HARDWARE_USE_EXACT_COLOR + return LLDRGB2COLOR(EXACT_RED_OF(c), EXACT_GREEN_OF(c), EXACT_BLUE_OF(c)); + #else + return LLDRGB2COLOR(RED_OF(c), GREEN_OF(c), BLUE_OF(c)); + #endif + #else + #error "GDISP: This pixel format conversion is not supported yet" + #endif + } + static color_t gdispNative2Color(LLDCOLOR_TYPE c) { + #if COLOR_SYSTEM == GDISP_COLORSYSTEM_GRAYSCALE || LLDCOLOR_SYSTEM == GDISP_COLORSYSTEM_GRAYSCALE + #if GDISP_HARDWARE_USE_EXACT_COLOR + return LUMA2COLOR(LLDEXACT_LUMA_OF(c)); + #else + return LUMA2COLOR(LLDLUMA_OF(c)); + #endif + #elif COLOR_SYSTEM == GDISP_COLORSYSTEM_TRUECOLOR && LLDCOLOR_SYSTEM == GDISP_COLORSYSTEM_TRUECOLOR + #if GDISP_HARDWARE_USE_EXACT_COLOR + return RGB2COLOR(LLDEXACT_RED_OF(c), LLDEXACT_GREEN_OF(c), LLDEXACT_BLUE_OF(c)); + #else + return RGB2COLOR(LLDRED_OF(c), LLDGREEN_OF(c), LLDBLUE_OF(c)); + #endif + #else + #error "GDISP: This pixel format conversion is not supported yet" + #endif + } + #endif + +#endif + +//------------------------------------------------------------------------------------------------------------ + +#undef IN_PIXMAP_DRIVER +#undef IS_MULTIPLE +#undef IN_DRIVER +#undef USE_VMT +#endif /* GFX_USE_GDISP */ + +#endif /* _GDISP_LLD_H */ +/** @} */ |