ugfx/src/gdisp/gdisp_driver.h
Joel Bodenmann 9c0678a291 Avoid duplicate const specifier compiler warnings
The original code is perfectly valid standard C. However, some compilers (especially GCC) complain about duplicate const specifiers anyway.
At this point we cave in as there doesn't seem to be any efforts to fix this problem by the corresponding compiler vendors.

uGFX v3 will no longer suffer from this problem as the driver interface works differently in this area.
2021-08-12 12:20:07 +02:00

1062 lines
38 KiB
C

/*
* 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.io/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 "../gdriver/gdriver.h"
// Are we currently compiling the driver itself?
#if defined(GDISP_DRIVER_VMT)
#define IN_DRIVER GFXON
#else
#define IN_DRIVER GFXOFF
#endif
// Is this a multiple driver situation?
#if defined(GDISP_DRIVER_LIST)
#define IS_MULTIPLE GFXON
#else
#define IS_MULTIPLE GFXOFF
#endif
// Do we need to use VMT calling rather than direct calls to the driver?
#if IS_MULTIPLE || GDISP_NEED_PIXMAP
#define USE_VMT GFXON
#else
#define USE_VMT GFXOFF
#endif
// Are we in the pixmap virtual driver
#ifndef IN_PIXMAP_DRIVER
#define IN_PIXMAP_DRIVER GFXOFF
#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 GFXOFF
#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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXON, GFXOFF 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 GFXOFF as they are needed for pixmap drawing
// Similarly some routines MUST not be GFXON 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 == GFXON
#undef GDISP_HARDWARE_FLUSH
#define GDISP_HARDWARE_FLUSH HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_STREAM_WRITE == GFXON
#undef GDISP_HARDWARE_STREAM_WRITE
#define GDISP_HARDWARE_STREAM_WRITE HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_STREAM_READ == GFXON
#undef GDISP_HARDWARE_STREAM_READ
#define GDISP_HARDWARE_STREAM_READ HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_CLEARS == GFXON
#undef GDISP_HARDWARE_CLEARS
#define GDISP_HARDWARE_CLEARS HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_FILLS == GFXON
#undef GDISP_HARDWARE_FILLS
#define GDISP_HARDWARE_FILLS HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_BITFILLS == GFXON
#undef GDISP_HARDWARE_BITFILLS
#define GDISP_HARDWARE_BITFILLS HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_SCROLL == GFXON
#undef GDISP_HARDWARE_SCROLL
#define GDISP_HARDWARE_SCROLL HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_QUERY == GFXON
#undef GDISP_HARDWARE_QUERY
#define GDISP_HARDWARE_QUERY HARDWARE_AUTODETECT
#endif
#if GDISP_HARDWARE_CLIP == GFXON
#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) { ((gColor *)(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 gPixel *buf, gCoord cx, gCoord x, gCoord y, gColor 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 {
gCoord Width;
gCoord Height;
gOrientation Orientation;
gPowermode Powermode;
gU8 Backlight;
gU8 Contrast;
} g;
void * priv; // A private area just for the drivers use.
void * board; // A private area just for the board interfaces use.
gU8 systemdisplay;
gU8 controllerdisplay;
gU16 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
gMutex mutex;
#endif
// Software clipping
#if GDISP_HARDWARE_CLIP != GFXON && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION)
gCoord clipx0, clipy0;
gCoord clipx1, clipy1; /* not inclusive */
#endif
// Driver call parameters
struct {
gCoord x, y;
gCoord cx, cy;
gCoord x1, y1;
gCoord x2, y2;
gColor color;
void *ptr;
} p;
// In call working buffers
#if GDISP_NEED_TEXT
// Text rendering parameters
struct {
gFont font;
gColor color;
gColor bgcolor;
gCoord clipx0, clipy0;
gCoord clipx1, clipy1;
#if GDISP_NEED_TEXT_WORDWRAP
gCoord wrapx, wrapy;
gJustify lrj;
#endif
} t;
#endif
#if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM_WRITE && GDISP_HARDWARE_BITFILLS))
// A pixel line buffer
gColor 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
gBool (*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
gColor (*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)
gColor (*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 be static or not
#if USE_VMT
#define LLDSPEC static
#else
#define LLDSPEC
#endif
/**
* @brief Initialize the driver.
* @return gTrue if successful.
* @param[in] g The driver structure
* @param[out] g->g The driver must fill in the GDISPControl structure
*/
LLDSPEC gBool gdisp_lld_init(GDisplay *g);
#if GDISP_HARDWARE_DEINIT || defined(__DOXYGEN__)
/**
* @brief The driver is being de-initialized
* @pre GDISP_HARDWARE_FLUSH is GFXON
*
* @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 GFXON
*
* @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 GFXON
*
* @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 GFXON.
*/
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 GFXON
*
* @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 GFXON
*
* @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 GFXON and GDISP_HARDWARE_STREAM_WRITE is GFXON
*
* @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 GFXON
*
* @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 GFXON
*
* @param[in] g The driver structure
*
* @note The parameter variables must not be altered by the driver.
*/
LLDSPEC gColor gdisp_lld_read_color(GDisplay *g);
/**
* @brief End the current streaming operation
* @pre GDISP_HARDWARE_STREAM_READ is GFXON
*
* @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 GFXON
*
* @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 GFXON
*
* @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 GFXON
*
* @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 GFXON
*
* @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 GFXON (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 gColor 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 GFXON (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 GFXON (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 GFXON (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 GFXON (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 GFXON"
#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
gBool _gdispInitDriver(GDriver *g, void *param, unsigned driverinstance, unsigned systeminstance);
void _gdispPostInitDriver(GDriver *g);
void _gdispDeInitDriver(GDriver *g);
#ifdef __cplusplus
}
#endif
// Build the VMT
/*
* This should read: const GDISPVMT const GDISP_DRIVER_VMT[1] = {{
* However, some major C compilers complain about duplicate const specifiers although this is perfectly valid standard C.
*/
const GDISPVMT 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 gU8
#define LLDCOLOR_TYPE_BITS 8
#elif LLDCOLOR_BITS <= 16
#define LLDCOLOR_TYPE gU16
#define LLDCOLOR_TYPE_BITS 16
#elif LLDCOLOR_BITS <= 32
#define LLDCOLOR_TYPE gU32
#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 GFXOFF
#else
#define LLDCOLOR_NEEDS_MASK GFXON
#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_G+LLDCOLOR_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) (((LLDCOLOR_TYPE)((b) & (0xFF & ~((1<<(8-LLDCOLOR_BITS_B))-1)))) >> (8-(LLDCOLOR_BITS_B+LLDCOLOR_SHIFT_B)))
#endif
#define LLDLUMA_OF(c) ((LLDRED_OF(c)+((gU16)LLDGREEN_OF(c)<<1)+LLDBLUE_OF(c))>>2)
#define LLDEXACT_RED_OF(c) (((gU16)(((c)>>LLDCOLOR_SHIFT_R)&((1<<LLDCOLOR_BITS_R)-1))*255)/((1<<LLDCOLOR_BITS_R)-1))
#define LLDEXACT_GREEN_OF(c) (((gU16)(((c)>>LLDCOLOR_SHIFT_G)&((1<<LLDCOLOR_BITS_G)-1))*255)/((1<<LLDCOLOR_BITS_G)-1))
#define LLDEXACT_BLUE_OF(c) (((gU16)(((c)>>LLDCOLOR_SHIFT_B)&((1<<LLDCOLOR_BITS_B)-1))*255)/((1<<LLDCOLOR_BITS_B)-1))
#define LLDEXACT_LUMA_OF(c) ((LLDEXACT_RED_OF(c)+((gU16)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 gU8
#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 GFXOFF
#else
#define LLDCOLOR_NEEDS_MASK GFXON
#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)(((gU16)(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) ((((gU16)(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 GFXON
#else
#define GDISP_HARDWARE_USE_EXACT_COLOR GFXOFF
#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)
#elif COLOR_SYSTEM == GDISP_COLORSYSTEM_GRAYSCALE || LLDCOLOR_SYSTEM == GDISP_COLORSYSTEM_GRAYSCALE
#if GDISP_HARDWARE_USE_EXACT_COLOR
#define gdispColor2Native(c) LLDLUMA2COLOR(EXACT_LUMA_OF(c))
#define gdispNative2Color(c) LUMA2COLOR(LLDEXACT_LUMA_OF(c))
#else
#define gdispColor2Native(c) LLDLUMA2COLOR(LUMA_OF(c))
#define gdispNative2Color(c) LUMA2COLOR(LLDLUMA_OF(c))
#endif
#elif COLOR_SYSTEM == GDISP_COLORSYSTEM_TRUECOLOR && LLDCOLOR_SYSTEM == GDISP_COLORSYSTEM_TRUECOLOR
#if GDISP_HARDWARE_USE_EXACT_COLOR
#define gdispColor2Native(c) LLDRGB2COLOR(EXACT_RED_OF(c), EXACT_GREEN_OF(c), EXACT_BLUE_OF(c))
#define gdispNative2Color(c) RGB2COLOR(LLDEXACT_RED_OF(c), LLDEXACT_GREEN_OF(c), LLDEXACT_BLUE_OF(c))
#else
#define gdispColor2Native(c) LLDRGB2COLOR(RED_OF(c), GREEN_OF(c), BLUE_OF(c))
#define gdispNative2Color(c) RGB2COLOR(LLDRED_OF(c), LLDGREEN_OF(c), LLDBLUE_OF(c))
#endif
#else
#error "GDISP: This pixel format conversion is not supported yet"
#endif
#endif
//------------------------------------------------------------------------------------------------------------
#undef IN_PIXMAP_DRIVER
#undef IS_MULTIPLE
#undef IN_DRIVER
#undef USE_VMT
#endif /* GFX_USE_GDISP */
#endif /* _GDISP_LLD_H */
/** @} */