/* * 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 "../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; orientation_t Orientation; gPowermode 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 != 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 { font_t 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 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 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< 8 #define LLDRED_OF(c) (((c) & (((1<> (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<> (8-(LLDCOLOR_BITS_R+LLDCOLOR_SHIFT_R))) #endif #if LLDCOLOR_BITS_G + LLDCOLOR_SHIFT_G == 8 #define LLDGREEN_OF(c) ((c) & (((1< 8 #define LLDGREEN_OF(c) (((c) & (((1<> (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<> (8-(LLDCOLOR_BITS_G+LLDCOLOR_SHIFT_G))) #endif #if LLDCOLOR_BITS_B + LLDCOLOR_SHIFT_B == 8 #define LLDBLUE_OF(c) ((c) & (((1< 8 #define LLDBLUE_OF(c) (((c) & (((1<> (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<> (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_SHIFT_G)&((1<>LLDCOLOR_SHIFT_B)&((1<>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 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)(((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 #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 */ /** @} */