ugfx/include/gdisp/lld/gdisp_lld.h
inmarket d22bc07e7a Multiple displays across one or more controllers is now fully supported.
Only the Win32 driver supports this so far.
Other drivers are currently broken due to API changes and will be fixed.
2013-10-12 13:24:40 +10:00

590 lines
19 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.org/license.html
*/
/**
* @file include/gdisp/lld/gdisp_lld.h
* @brief GDISP Graphic Driver subsystem low level driver header.
*
* @addtogroup GDISP
* @{
*/
#ifndef _GDISP_LLD_H
#define _GDISP_LLD_H
#if GFX_USE_GDISP || defined(__DOXYGEN__)
/*===========================================================================*/
/* Error checks. */
/*===========================================================================*/
/**
* @name GDISP hardware accelerated support
* @{
*/
/**
* @brief Hardware streaming writing is supported.
* @details If set to @p FALSE software emulation is used.
* @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
*/
#ifndef GDISP_HARDWARE_STREAM_WRITE
#define GDISP_HARDWARE_STREAM_WRITE FALSE
#endif
/**
* @brief Hardware streaming reading of the display surface is supported.
* @details If set to @p FALSE this routine is not available.
*/
#ifndef GDISP_HARDWARE_STREAM_READ
#define GDISP_HARDWARE_STREAM_READ FALSE
#endif
/**
* @brief Hardware supports setting the cursor position within the stream window.
* @details If set to @p FALSE this routine is not available.
* @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 FALSE
#endif
/**
* @brief Hardware accelerated draw pixel.
* @details If set to @p FALSE software emulation is used.
* @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
*/
#ifndef GDISP_HARDWARE_DRAWPIXEL
#define GDISP_HARDWARE_DRAWPIXEL FALSE
#endif
/**
* @brief Hardware accelerated screen clears.
* @details If set to @p FALSE software emulation is used.
* @note This clears the entire display surface regardless of the clipping area currently set
*/
#ifndef GDISP_HARDWARE_CLEARS
#define GDISP_HARDWARE_CLEARS FALSE
#endif
/**
* @brief Hardware accelerated rectangular fills.
* @details If set to @p FALSE software emulation is used.
*/
#ifndef GDISP_HARDWARE_FILLS
#define GDISP_HARDWARE_FILLS FALSE
#endif
/**
* @brief Hardware accelerated fills from an image.
* @details If set to @p FALSE software emulation is used.
*/
#ifndef GDISP_HARDWARE_BITFILLS
#define GDISP_HARDWARE_BITFILLS FALSE
#endif
/**
* @brief Hardware accelerated scrolling.
* @details If set to @p FALSE there is no support for scrolling.
*/
#ifndef GDISP_HARDWARE_SCROLL
#define GDISP_HARDWARE_SCROLL FALSE
#endif
/**
* @brief Reading back of pixel values.
* @details If set to @p FALSE there is no support for pixel read-back.
*/
#ifndef GDISP_HARDWARE_PIXELREAD
#define GDISP_HARDWARE_PIXELREAD FALSE
#endif
/**
* @brief The driver supports one or more control commands.
* @details If set to @p FALSE there is no support for control commands.
*/
#ifndef GDISP_HARDWARE_CONTROL
#define GDISP_HARDWARE_CONTROL FALSE
#endif
/**
* @brief The driver supports a non-standard query.
* @details If set to @p FALSE there is no support for non-standard queries.
*/
#ifndef GDISP_HARDWARE_QUERY
#define GDISP_HARDWARE_QUERY FALSE
#endif
/**
* @brief The driver supports a clipping in hardware.
* @details If set to @p FALSE there is no support for non-standard queries.
* @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 FALSE
#endif
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
typedef struct GDisplay {
GDISPControl g; // The public GDISP stuff - must be the first element
#if GDISP_TOTAL_CONTROLLERS > 1
const struct GDISPVMT const * vmt; // The Virtual Method Table
#endif
void * priv; // A private area just for the drivers use.
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 && (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
} GDisplay;
#if GDISP_TOTAL_CONTROLLERS == 1 || defined(GDISP_DRIVER_VMT) || defined(__DOXYGEN__)
#if GDISP_TOTAL_CONTROLLERS > 1
#define LLDSPEC static
#else
#define LLDSPEC
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize the driver.
* @return TRUE if successful.
* @param[in] g The driver structure
* @param[in] display The display number for this controller 0..n
* @param[out] g->g The driver must fill in the GDISPControl structure
*/
LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display);
#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
* @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.
* @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
* @param[in] 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
#endif // GDISP_TOTAL_CONTROLLERS == 1 || defined(GDISP_DRIVER_VMT)
#if GDISP_TOTAL_CONTROLLERS > 1
typedef struct GDISPVMT {
bool_t (*init)(GDisplay *g, unsigned display);
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
} GDISPVMT;
#if defined(GDISP_DRIVER_VMT)
const GDISPVMT const GDISP_DRIVER_VMT[1] = {{
gdisp_lld_init,
#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
}};
#else
#define gdisp_lld_init(g, display) g->vmt->init(g, display)
#define gdisp_lld_write_start(g) g->vmt->writestart(g)
#define gdisp_lld_write_pos(g) g->vmt->writepos(g)
#define gdisp_lld_write_color(g) g->vmt->writecolor(g)
#define gdisp_lld_write_stop(g) g->vmt->writestop(g)
#define gdisp_lld_read_start(g) g->vmt->readstart(g)
#define gdisp_lld_read_color(g) g->vmt->readcolor(g)
#define gdisp_lld_read_stop(g) g->vmt->readstop(g)
#define gdisp_lld_draw_pixel(g) g->vmt->pixel(g)
#define gdisp_lld_clear(g) g->vmt->clear(g)
#define gdisp_lld_fill_area(g) g->vmt->fill(g)
#define gdisp_lld_blit_area(g) g->vmt->blit(g)
#define gdisp_lld_get_pixel_color(g) g->vmt->get(g)
#define gdisp_lld_vertical_scroll(g) g->vmt->vscroll(g)
#define gdisp_lld_control(g) g->vmt->control(g)
#define gdisp_lld_query(g) g->vmt->query(g)
#define gdisp_lld_set_clip(g) g->vmt->setclip(g)
#endif // GDISP_LLD_DECLARATIONS
#endif // GDISP_TOTAL_CONTROLLERS > 1
/* 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
#endif /* GFX_USE_GDISP */
#endif /* _GDISP_LLD_H */
/** @} */