aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/multiple/Win32/gdisp_lld.c503
-rw-r--r--drivers/multiple/Win32/gdisp_lld_config.h15
-rw-r--r--include/gdisp/gdisp.h140
-rw-r--r--include/gdisp/lld/gdisp_lld.h613
-rw-r--r--include/gdisp/options.h136
-rw-r--r--include/gfx_rules.h22
-rw-r--r--src/gdisp/gdisp.c461
7 files changed, 1065 insertions, 825 deletions
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 91b86616..d6c6b2fb 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -8,22 +8,15 @@
/**
* @file drivers/multiple/Win32/gdisp_lld.c
* @brief GDISP Graphics Driver subsystem low level driver source for Win32.
- *
- * @addtogroup GDISP
- * @{
*/
#include "gfx.h"
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
+#define GDISP_LLD_DECLARATIONS
#include "gdisp/lld/gdisp_lld.h"
-// Declare our driver object
-GDISPDriver GDISP_Win32;
-
-#define GC (&GDISP_Win32)
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -41,10 +34,6 @@ GDISPDriver GDISP_Win32;
#if GINPUT_NEED_TOGGLE
/* Include toggle support code */
#include "ginput/lld/toggle.h"
-
- const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
- {0, 0xFF, 0x00, 0},
- };
#endif
#if GINPUT_NEED_MOUSE
@@ -298,19 +287,13 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) {
/* Driver exported functions. */
/*===========================================================================*/
-/* ---- Required Routines ---- */
-/*
- The following 2 routines are required.
- All other routines are optional.
-*/
-
/**
- * @brief Low level GDISP driver initialisation.
+ * @brief Low level GDISP driver initialization.
* @return TRUE if successful, FALSE on error.
*
* @notapi
*/
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
RECT rect;
gfxThreadHandle hth;
@@ -333,45 +316,45 @@ bool_t gdisp_lld_init(void) {
Sleep(1);
/* Initialise the GDISP structure to match */
- GC->g.Orientation = GDISP_ROTATE_0;
- GC->g.Powermode = powerOn;
- GC->g.Backlight = 100;
- GC->g.Contrast = 50;
- GC->g.Width = wWidth;
- GC->g.Height = wHeight;
+ g->g.Orientation = GDISP_ROTATE_0;
+ g->g.Powermode = powerOn;
+ g->g.Backlight = 100;
+ g->g.Contrast = 50;
+ g->g.Width = wWidth;
+ g->g.Height = wHeight;
return TRUE;
}
#if GDISP_HARDWARE_DRAWPIXEL
- void gdisp_lld_draw_pixel(void) {
+ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) {
HDC dcScreen;
int x, y;
COLORREF color;
- color = COLOR2BGR(GC->p.color);
+ color = COLOR2BGR(g->p.color);
#if GDISP_NEED_CONTROL
- switch(GC->g.Orientation) {
+ switch(g->g.Orientation) {
case GDISP_ROTATE_0:
- x = GC->p.x;
- y = GC->p.y;
+ x = g->p.x;
+ y = g->p.y;
break;
case GDISP_ROTATE_90:
- x = GC->g.Height - 1 - GC->p.y;
- y = GC->p.x;
+ x = g->g.Height - 1 - g->p.y;
+ y = g->p.x;
break;
case GDISP_ROTATE_180:
- x = GC->g.Width - 1 - GC->p.x;
- y = GC->g.Height - 1 - GC->p.y;
+ x = g->g.Width - 1 - g->p.x;
+ y = g->g.Height - 1 - g->p.y;
break;
case GDISP_ROTATE_270:
- x = GC->p.y;
- y = GC->g.Width - 1 - GC->p.x;
+ x = g->p.y;
+ y = g->g.Width - 1 - g->p.x;
break;
}
#else
- x = GC->p.x;
- y = GC->p.y;
+ x = g->p.x;
+ y = g->p.y;
#endif
// Draw the pixel on the screen and in the buffer.
@@ -384,176 +367,46 @@ bool_t gdisp_lld_init(void) {
/* ---- Optional Routines ---- */
-#if 0
-#if GDISP_HARDWARE_LINES
- /**
- * @brief Draw a line.
- * @note Optional - The high level driver can emulate using software.
- *
- * @param[in] x0, y0 The start of the line
- * @param[in] x1, y1 The end of the line
- * @param[in] color The color of the line
- *
- * @notapi
- */
- void gdisp_lld_draw_line(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) {
- POINT p;
- HPEN pen;
- HDC dc;
- HGDIOBJ old;
- #if GDISP_NEED_CLIP
- HRGN clip;
- #endif
- #if WIN32_USE_MSG_REDRAW
- RECT rect;
- #endif
- #if GDISP_NEED_CONTROL
- coord_t t;
- #endif
-
- #if GDISP_NEED_CLIP
- clip = NULL;
- #endif
-
- #if GDISP_NEED_CONTROL
- switch(GC->g.Orientation) {
- case GDISP_ROTATE_0:
- #if GDISP_NEED_CLIP
- // Clip post orientation change
- if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
- clip = CreateRectRgn(GC->g.clipx0, GC->g.clipy0, GC->g.clipx1, GC->g.clipy1);
- #endif
- break;
- case GDISP_ROTATE_90:
- t = GC->g.Height - 1 - y0;
- y0 = x0;
- x0 = t;
- t = GC->g.Height - 1 - y1;
- y1 = x1;
- x1 = t;
- #if GDISP_NEED_CLIP
- // Clip post orientation change
- if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
- clip = CreateRectRgn(GC->g.Height-1-GC->g.clipy1, GC->g.clipx0, GC->g.Height-1-GC->g.clipy0, GC->g.clipx1);
- #endif
- break;
- case GDISP_ROTATE_180:
- x0 = GC->g.Width - 1 - x0;
- y0 = GC->g.Height - 1 - y0;
- x1 = GC->g.Width - 1 - x1;
- y1 = GC->g.Height - 1 - y1;
- #if GDISP_NEED_CLIP
- // Clip post orientation change
- if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
- clip = CreateRectRgn(GC->g.Width-1-GC->g.clipx1, GC->g.Height-1-GC->g.clipy1, GC->g.Width-1-GC->g.clipx0, GC->g.Height-1-GC->g.clipy0);
- #endif
- break;
- case GDISP_ROTATE_270:
- t = GC->g.Width - 1 - x0;
- x0 = y0;
- y0 = t;
- t = GC->g.Width - 1 - x1;
- x1 = y1;
- y1 = t;
- #if GDISP_NEED_CLIP
- // Clip post orientation change
- if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
- clip = CreateRectRgn(GC->g.clipy0, GC->g.Width-1-GC->g.clipx1, GC->g.clipy1, GC->g.Width-1-GC->g.clipx0);
- #endif
- break;
- }
- #else
- #if GDISP_NEED_CLIP
- clip = NULL;
- if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
- clip = CreateRectRgn(GC->g.clipx0, GC->g.clipy0, GC->g.clipx1, GC->g.clipy1);
- #endif
- #endif
-
- color = COLOR2BGR(color);
- pen = CreatePen(PS_SOLID, 1, color);
- if (pen) {
- // Draw the line in the buffer
- #if GDISP_NEED_CLIP
- if (clip) SelectClipRgn(dcBuffer, clip);
- #endif
- old = SelectObject(dcBuffer, pen);
- MoveToEx(dcBuffer, x0, y0, &p);
- LineTo(dcBuffer, x1, y1);
- SelectObject(dcBuffer, old);
- SetPixel(dcBuffer, x1, y1, color);
- #if GDISP_NEED_CLIP
- if (clip) SelectClipRgn(dcBuffer, NULL);
- #endif
-
- #if WIN32_USE_MSG_REDRAW
- rect.left = x0; rect.right = x1+1;
- rect.top = y0; rect.bottom = y1+1;
- InvalidateRect(winRootWindow, &rect, FALSE);
- UpdateWindow(winRootWindow);
- #else
- // Redrawing the line on the screen is cheaper than invalidating the whole rectangular area
- dc = GetDC(winRootWindow);
- #if GDISP_NEED_CLIP
- if (clip) SelectClipRgn(dc, clip);
- #endif
- old = SelectObject(dc, pen);
- MoveToEx(dc, x0, y0, &p);
- LineTo(dc, x1, y1);
- SelectObject(dc, old);
- SetPixel(dc, x1, y1, color);
- #if GDISP_NEED_CLIP
- if (clip) SelectClipRgn(dc, NULL);
- #endif
- ReleaseDC(winRootWindow, dc);
- #endif
-
- DeleteObject(pen);
- }
- }
-#endif
-#endif
-
#if GDISP_HARDWARE_FILLS
- void gdisp_lld_fill_area(void) {
+ LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
HDC dcScreen;
RECT rect;
HBRUSH hbr;
COLORREF color;
- color = COLOR2BGR(GC->p.color);
+ color = COLOR2BGR(g->p.color);
#if GDISP_NEED_CONTROL
- switch(GC->g.Orientation) {
+ switch(g->g.Orientation) {
case GDISP_ROTATE_0:
- rect.top = GC->p.y;
- rect.bottom = rect.top + GC->p.cy;
- rect.left = GC->p.x;
- rect.right = rect.left + GC->p.cx;
+ rect.top = g->p.y;
+ rect.bottom = rect.top + g->p.cy;
+ rect.left = g->p.x;
+ rect.right = rect.left + g->p.cx;
break;
case GDISP_ROTATE_90:
- rect.top = GC->p.x;
- rect.bottom = rect.top + GC->p.cx;
- rect.right = GC->g.Height - GC->p.y;
- rect.left = rect.right - GC->p.cy;
+ rect.top = g->p.x;
+ rect.bottom = rect.top + g->p.cx;
+ rect.right = g->g.Height - g->p.y;
+ rect.left = rect.right - g->p.cy;
break;
case GDISP_ROTATE_180:
- rect.bottom = GC->g.Height - GC->p.y;
- rect.top = rect.bottom - GC->p.cy;
- rect.right = GC->g.Width - GC->p.x;
- rect.left = rect.right - GC->p.cx;
+ rect.bottom = g->g.Height - g->p.y;
+ rect.top = rect.bottom - g->p.cy;
+ rect.right = g->g.Width - g->p.x;
+ rect.left = rect.right - g->p.cx;
break;
case GDISP_ROTATE_270:
- rect.bottom = GC->g.Width - GC->p.x;
- rect.top = rect.bottom - GC->p.cx;
- rect.left = GC->p.y;
- rect.right = rect.left + GC->p.cy;
+ rect.bottom = g->g.Width - g->p.x;
+ rect.top = rect.bottom - g->p.cx;
+ rect.left = g->p.y;
+ rect.right = rect.left + g->p.cy;
break;
}
#else
- rect.top = GC->p.y;
- rect.bottom = rect.top + GC->p.cy;
- rect.left = GC->p.x;
- rect.right = rect.left + GC->p.cx;
+ rect.top = g->p.y;
+ rect.bottom = rect.top + g->p.cy;
+ rect.left = g->p.x;
+ rect.right = rect.left + g->p.cx;
#endif
hbr = CreateSolidBrush(color);
@@ -567,7 +420,7 @@ bool_t gdisp_lld_init(void) {
}
#endif
-#if (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL) || defined(__DOXYGEN__)
+#if 0 && (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL)
static pixel_t *rotateimg(coord_t cx, coord_t cy, coord_t srcx, coord_t srccx, const pixel_t *buffer) {
pixel_t *dstbuf;
pixel_t *dst;
@@ -615,7 +468,7 @@ bool_t gdisp_lld_init(void) {
}
#endif
-#if GDISP_HARDWARE_BITFILLS
+#if 0 && GDISP_HARDWARE_BITFILLS
/**
* @brief Fill an area with a bitmap.
* @note Optional - The high level driver can emulate using software.
@@ -628,23 +481,13 @@ bool_t gdisp_lld_init(void) {
*
* @notapi
*/
- void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
+ void gdisp_lld_blit_area(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
BITMAPV4HEADER bmpInfo;
RECT rect;
#if GDISP_NEED_CONTROL
pixel_t *srcimg;
#endif
- #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
- // Clip pre orientation change
- if (x < GC->g.clipx0) { cx -= GC->g.clipx0 - x; srcx += GC->g.clipx0 - x; x = GC->g.clipx0; }
- if (y < GC->g.clipy0) { cy -= GC->g.clipy0 - y; srcy += GC->g.clipy0 - y; y = GC->g.clipy0; }
- if (srcx+cx > srccx) cx = srccx - srcx;
- if (cx <= 0 || cy <= 0 || x >= GC->g.clipx1 || y >= GC->g.clipy1) return;
- if (x+cx > GC->g.clipx1) cx = GC->g.clipx1 - x;
- if (y+cy > GC->g.clipy1) cy = GC->g.clipy1 - y;
- #endif
-
// Make everything relative to the start of the line
buffer += srccx*srcy;
srcy = 0;
@@ -724,225 +567,142 @@ bool_t gdisp_lld_init(void) {
}
#endif
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
- /**
- * @brief Get the color of a particular pixel.
- * @note Optional.
- * @note If x,y is off the screen, the result is undefined.
- * @return The color of the specified pixel.
- *
- * @param[in] x, y The start of the text
- *
- * @notapi
- */
- color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
- color_t color;
- #if GDISP_NEED_CONTROL
- coord_t t;
- #endif
-
- #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
- // Clip pre orientation change
- if (x < 0 || x >= GC->g.Width || y < 0 || y >= GC->g.Height) return 0;
- #endif
+#if GDISP_HARDWARE_PIXELREAD
+ LLDSPEC color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
+ COLORREF color;
#if GDISP_NEED_CONTROL
- switch(GC->g.Orientation) {
+ switch(g->g.Orientation) {
case GDISP_ROTATE_0:
+ color = GetPixel(dcBuffer, g->p.x, g->p.y);
break;
case GDISP_ROTATE_90:
- t = GC->g.Height - 1 - y;
- y = x;
- x = t;
+ color = GetPixel(dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
break;
case GDISP_ROTATE_180:
- x = GC->g.Width - 1 - x;
- y = GC->g.Height - 1 - y;
+ color = GetPixel(dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
break;
case GDISP_ROTATE_270:
- t = GC->g.Width - 1 - x;
- x = y;
- y = t;
+ color = GetPixel(dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
break;
}
+ #else
+ color = GetPixel(dcBuffer, g->p.x, g->p.y);
#endif
- color = GetPixel(dcBuffer, x, y);
return BGR2COLOR(color);
}
#endif
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
- /**
- * @brief Scroll vertically a section of the screen.
- * @note Optional.
- * @note If x,y + cx,cy is off the screen, the result is undefined.
- * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
- *
- * @param[in] x, y The start of the area to be scrolled
- * @param[in] cx, cy The size of the area to be scrolled
- * @param[in] lines The number of lines to scroll (Can be positive or negative)
- * @param[in] bgcolor The color to fill the newly exposed area.
- *
- * @notapi
- */
- void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
- RECT rect, frect, srect;
- HBRUSH hbr;
-
- #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
- // Clip pre orientation change
- if (x < GC->g.clipx0) { cx -= GC->g.clipx0 - x; x = GC->g.clipx0; }
- if (y < GC->g.clipy0) { cy -= GC->g.clipy0 - y; y = GC->g.clipy0; }
- if (!lines || cx <= 0 || cy <= 0 || x >= GC->g.clipx1 || y >= GC->g.clipy1) return;
- if (x+cx > GC->g.clipx1) cx = GC->g.clipx1 - x;
- if (y+cy > GC->g.clipy1) cy = GC->g.clipy1 - y;
- #endif
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+ void gdisp_lld_vertical_scroll(GDISPDriver *g) {
+ HDC dcScreen;
+ RECT rect;
+ coord_t lines;
- if (lines > cy) lines = cy;
- else if (-lines > cy) lines = -cy;
-
- bgcolor = COLOR2BGR(bgcolor);
- hbr = CreateSolidBrush(bgcolor);
-
#if GDISP_NEED_CONTROL
switch(GC->g.Orientation) {
case GDISP_ROTATE_0:
- rect.top = y;
- rect.bottom = rect.top+cy;
- rect.left = x;
- rect.right = rect.left+cx;
- lines = -lines;
+ rect.top = g->p.y;
+ rect.bottom = rect.top+g->p.cy;
+ rect.left = g->p.x;
+ rect.right = rect.left+g->p.cx;
+ lines = -g->p.y1;
goto vertical_scroll;
case GDISP_ROTATE_90:
- rect.top = x;
- rect.bottom = rect.top+cx;
- rect.right = GC->g.Height - y;
- rect.left = rect.right-cy;
+ rect.top = g->p.x;
+ rect.bottom = rect.top+g->p.cx;
+ rect.right = g->g.Height - g->p.y;
+ rect.left = rect.right-g->p.cy;
+ lines = g->p.y1;
goto horizontal_scroll;
case GDISP_ROTATE_180:
- rect.bottom = GC->g.Height - y;
- rect.top = rect.bottom-cy;
- rect.right = GC->g.Width - x;
- rect.left = rect.right-cx;
+ rect.bottom = g->g.Height - g->p.y;
+ rect.top = rect.bottom-g->p.cy;
+ rect.right = GC->g.Width - g->p.x;
+ rect.left = rect.right-g->p.cx;
+ lines = g->p.y1;
vertical_scroll:
- srect.left = frect.left = rect.left;
- srect.right = frect.right = rect.right;
if (lines > 0) {
- srect.top = frect.top = rect.top;
- frect.bottom = rect.top+lines;
- srect.bottom = rect.bottom-lines;
+ rect.bottom -= lines;
} else {
- srect.bottom = frect.bottom = rect.bottom;
- frect.top = rect.bottom+lines;
- srect.top = rect.top-lines;
+ rect.top -= lines;
+ }
+ if (g->p.cy >= lines && g->p.cy >= -lines) {
+ dcScreen = GetDC(winRootWindow);
+ ScrollDC(dcBuffer, 0, lines, &rect, 0, 0, 0);
+ ScrollDC(dcScreen, 0, lines, &rect, 0, 0, 0);
+ ReleaseDC(winRootWindow, dcScreen);
}
- if (cy >= lines && cy >= -lines)
- ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
break;
case GDISP_ROTATE_270:
- rect.bottom = GC->g.Width - x;
- rect.top = rect.bottom-cx;
- rect.left = y;
- rect.right = rect.left+cy;
- lines = -lines;
+ rect.bottom = g->g.Width - g->p.x;
+ rect.top = rect.bottom-g->p.cx;
+ rect.left = g->p.y;
+ rect.right = rect.left+g->p.cy;
+ lines = -g->p.y1;
horizontal_scroll:
- srect.top = frect.top = rect.top;
- srect.bottom = frect.bottom = rect.bottom;
if (lines > 0) {
- srect.left = frect.left = rect.left;
- frect.right = rect.left+lines;
- srect.right = rect.right-lines;
+ rect.right -= lines;
} else {
- srect.right = frect.right = rect.right;
- frect.left = rect.right+lines;
- srect.left = rect.left-lines;
+ rect.left -= lines;
+ }
+ if (g->p.cy >= lines && g->p.cy >= -lines) {
+ dcScreen = GetDC(winRootWindow);
+ ScrollDC(dcBuffer, lines, 0, &rect, 0, 0, 0);
+ ScrollDC(dcScreen, lines, 0, &rect, 0, 0, 0);
+ ReleaseDC(winRootWindow, dcScreen);
}
- if (cy >= lines && cy >= -lines)
- ScrollDC(dcBuffer, lines, 0, &srect, 0, 0, 0);
break;
}
#else
- rect.top = y;
- rect.bottom = rect.top+cy;
- rect.left = x;
- rect.right = rect.left+cx;
- lines = -lines;
- srect.left = frect.left = rect.left;
- srect.right = frect.right = rect.right;
+ rect.top = g->p.y;
+ rect.bottom = rect.top+g->p.cy;
+ rect.left = g->p.x;
+ rect.right = rect.left+g->p.cx;
+ lines = -g->p.y1;
if (lines > 0) {
- srect.top = frect.top = rect.top;
- frect.bottom = rect.top+lines;
- srect.bottom = rect.bottom-lines;
+ rect.bottom -= lines;
} else {
- srect.bottom = frect.bottom = rect.bottom;
- frect.top = rect.bottom+lines;
- srect.top = rect.top-lines;
+ rect.top -= lines;
+ }
+ if (g->p.cy >= lines && g->p.cy >= -lines) {
+ dcScreen = GetDC(winRootWindow);
+ ScrollDC(dcBuffer, 0, lines, &rect, 0, 0, 0);
+ ScrollDC(dcScreen, 0, lines, &rect, 0, 0, 0);
+ ReleaseDC(winRootWindow, dcScreen);
}
- if (cy >= lines && cy >= -lines)
- ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
#endif
-
- if (hbr)
- FillRect(dcBuffer, &frect, hbr);
- InvalidateRect(winRootWindow, &rect, FALSE);
- UpdateWindow(winRootWindow);
}
#endif
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
- /**
- * @brief Driver Control
- * @detail Unsupported control codes are ignored.
- * @note The value parameter should always be typecast to (void *).
- * @note There are some predefined and some specific to the low level driver.
- * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
- * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
- * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
- * that only supports off/on anything other
- * than zero is on.
- * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
- * GDISP_CONTROL_LLD - Low level driver control constants start at
- * this value.
- *
- * @param[in] what What to do.
- * @param[in] value The value to use (always cast to a void *).
- *
- * @notapi
- */
- void gdisp_lld_control(unsigned what, void *value) {
- switch(what) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+ LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+ switch(g->p.x) {
case GDISP_CONTROL_ORIENTATION:
- if (GC->g.Orientation == (gdisp_orientation_t)value)
+ if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
- switch((gdisp_orientation_t)value) {
+ switch((orientation_t)g->p.ptr) {
case GDISP_ROTATE_0:
- GC->g.Width = wWidth;
- GC->g.Height = wHeight;
+ g->g.Width = wWidth;
+ g->g.Height = wHeight;
break;
case GDISP_ROTATE_90:
- GC->g.Height = wWidth;
- GC->g.Width = wHeight;
+ g->g.Height = wWidth;
+ g->g.Width = wHeight;
break;
case GDISP_ROTATE_180:
- GC->g.Width = wWidth;
- GC->g.Height = wHeight;
+ g->g.Width = wWidth;
+ g->g.Height = wHeight;
break;
case GDISP_ROTATE_270:
- GC->g.Height = wWidth;
- GC->g.Width = wHeight;
+ g->g.Height = wWidth;
+ g->g.Width = wHeight;
break;
default:
return;
}
-
- #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
- GC->g.clipx0 = 0;
- GC->g.clipy0 = 0;
- GC->g.clipx1 = GC->g.Width;
- GC->g.clipy1 = GC->g.Height;
- #endif
- GC->g.Orientation = (gdisp_orientation_t)value;
+ g->g.Orientation = (orientation_t)g->p.ptr;
return;
/*
case GDISP_CONTROL_POWER:
@@ -954,25 +714,22 @@ bool_t gdisp_lld_init(void) {
#endif
#if GINPUT_NEED_MOUSE
-
void ginput_lld_mouse_init(void) {}
-
void ginput_lld_mouse_get_reading(MouseReading *pt) {
pt->x = mousex;
pt->y = mousey > wHeight ? wHeight : mousey;
pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
pt->buttons = mousebuttons;
}
-
#endif /* GINPUT_NEED_MOUSE */
#if GINPUT_NEED_TOGGLE
-
+ const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
+ {0, 0xFF, 0x00, 0},
+ };
void ginput_lld_toggle_init(const GToggleConfig *ptc) { (void) ptc; }
unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { (void) ptc; return toggles; }
-
#endif /* GINPUT_NEED_MOUSE */
#endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index 357febe4..4a526f07 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -25,19 +25,14 @@
#define GDISP_DRIVER_NAME "Win32"
#define GDISP_DRIVER_STRUCT GDISP_Win32
-#define GDISP_HARDWARE_STREAM FALSE
-#define GDISP_HARDWARE_STREAM_END FALSE
#define GDISP_HARDWARE_DRAWPIXEL TRUE
-#define GDISP_HARDWARE_CLEARS FALSE
#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_PIXELREAD TRUE
+#define GDISP_HARDWARE_CONTROL TRUE
//#define GDISP_HARDWARE_BITFILLS TRUE
-//#define GDISP_HARDWARE_SCROLL TRUE
-//#define GDISP_HARDWARE_PIXELREAD TRUE
-//#define GDISP_HARDWARE_CONTROL TRUE
-#define GDISP_HARDWARE_QUERY FALSE
-#define GDISP_HARDWARE_CLIP FALSE
-
-#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
+#define GDISP_HARDWARE_SCROLL TRUE
+
+#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
#endif /* GFX_USE_GDISP */
diff --git a/include/gdisp/gdisp.h b/include/gdisp/gdisp.h
index 3a1968ed..cb98b46d 100644
--- a/include/gdisp/gdisp.h
+++ b/include/gdisp/gdisp.h
@@ -43,21 +43,15 @@ typedef int16_t coord_t;
/**
* @brief Type for a 2D point on the screen.
*/
-typedef struct point_t {
- coord_t x, y;
- } point;
+typedef struct point { coord_t x, y; } point, point_t;
/**
* @brief Type for the text justification.
*/
-typedef enum justify {
- justifyLeft = 0,
- justifyCenter = 1,
- justifyRight = 2
-} justify_t;
+typedef enum justify { justifyLeft=0, justifyCenter=1, justifyRight=2 } justify_t;
/**
* @brief Type for the font metric.
*/
-typedef enum fontmetric {fontHeight, fontDescendersHeight, fontLineSpacing, fontCharPadding, fontMinWidth, fontMaxWidth} fontmetric_t;
+typedef enum fontmetric { fontHeight, fontDescendersHeight, fontLineSpacing, fontCharPadding, fontMinWidth, fontMaxWidth } fontmetric_t;
/**
* @brief The type of a font.
*/
@@ -65,11 +59,11 @@ typedef const struct mf_font_s* font_t;
/**
* @brief Type for the screen orientation.
*/
-typedef enum orientation {GDISP_ROTATE_0, GDISP_ROTATE_90, GDISP_ROTATE_180, GDISP_ROTATE_270} gdisp_orientation_t;
+typedef enum orientation { GDISP_ROTATE_0=0, GDISP_ROTATE_90=90, GDISP_ROTATE_180=180, GDISP_ROTATE_270=270 } orientation_t;
/**
* @brief Type for the available power modes for the screen.
*/
-typedef enum powermode {powerOff, powerSleep, powerDeepSleep, powerOn} gdisp_powermode_t;
+typedef enum powermode { powerOff, powerSleep, powerDeepSleep, powerOn } powermode_t;
/*
* This is not documented in Doxygen as it is meant to be a black-box.
@@ -79,8 +73,8 @@ typedef enum powermode {powerOff, powerSleep, powerDeepSleep, powerOn} gdisp_pow
typedef struct GDISPControl {
coord_t Width;
coord_t Height;
- gdisp_orientation_t Orientation;
- gdisp_powermode_t Powermode;
+ orientation_t Orientation;
+ powermode_t Powermode;
uint8_t Backlight;
uint8_t Contrast;
} GDISPControl;
@@ -112,15 +106,6 @@ extern GDISPControl *GDISP;
#define GDISP_CONTROL_LLD 1000
/**
- * @brief Driver Query Constants
- * @details Unsupported query codes return (void *)-1.
- * @note The result should be typecast the required type.
- * @note GDISP_QUERY_LLD - Low level driver control constants start at
- * this value.
- */
-#define GDISP_QUERY_LLD 1000
-
-/**
* @brief Driver Pixel Format Constants
*/
#define GDISP_PIXELFORMAT_MONO 1
@@ -162,6 +147,80 @@ extern GDISPControl *GDISP;
/** @} */
/*===========================================================================*/
+/* Defines relating to the display hardware */
+/*===========================================================================*/
+
+#if GDISP_MULTIPLE_DRIVERS || defined(__DOXYGEN__)
+ /**
+ * @name GDISP pixel format choices
+ * @{
+ */
+ /**
+ * @brief The pixel format.
+ * @default It generally defaults to the hardware pixel format.
+ * @note This doesn't need to match the hardware pixel format.
+ * It is definitely more efficient when it does.
+ * @note When GDISP_MULTIPLE_DRIVERS is defined, this should
+ * also be explicitly defined to ensure the best match
+ * with your hardware across all devices.
+ * @note Should be set to one of the following:
+ * GDISP_PIXELFORMAT_RGB565
+ * GDISP_PIXELFORMAT_BGR565
+ * GDISP_PIXELFORMAT_RGB888
+ * GDISP_PIXELFORMAT_RGB444
+ * GDISP_PIXELFORMAT_RGB332
+ * GDISP_PIXELFORMAT_RGB666
+ * GDISP_PIXELFORMAT_CUSTOM
+ * @note If you set GDISP_PIXELFORMAT_CUSTOM you need to also define
+ * color_t, RGB2COLOR(r,g,b), HTML2COLOR(h),
+ * RED_OF(c), GREEN_OF(c), BLUE_OF(c),
+ * COLOR(c) and MASKCOLOR.
+ */
+ #ifndef GDISP_PIXELFORMAT
+ #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_ERROR
+ #endif
+ /**
+ * @brief Do pixels require packing for a blit
+ * @note Is only valid for a pixel format that doesn't fill it's datatype. ie formats:
+ * GDISP_PIXELFORMAT_RGB888
+ * GDISP_PIXELFORMAT_RGB444
+ * GDISP_PIXELFORMAT_RGB666
+ * GDISP_PIXELFORMAT_CUSTOM
+ * @note If you use GDISP_PIXELFORMAT_CUSTOM and packed bit fills
+ * you need to also define @p gdispPackPixels(buf,cx,x,y,c)
+ * @note If you are using GDISP_HARDWARE_BITFILLS = FALSE then the pixel
+ * format must not be a packed format as the software blit does
+ * not support packed pixels
+ * @note Very few cases should actually require packed pixels as the low
+ * level driver can also pack on the fly as it is sending it
+ * to the graphics device.
+ */
+ #ifndef GDISP_PACKED_PIXELS
+ #define GDISP_PACKED_PIXELS FALSE
+ #endif
+
+ /**
+ * @brief Do lines of pixels require packing for a blit
+ * @note Ignored if GDISP_PACKED_PIXELS is FALSE
+ */
+ #ifndef GDISP_PACKED_LINES
+ #define GDISP_PACKED_LINES FALSE
+ #endif
+ /** @} */
+#else
+ #include "gdisp_lld_config.h"
+ #ifndef GDISP_PIXELFORMAT
+ #define GDISP_PIXELFORMAT GDISP_LLD_PIXELFORMAT
+ #endif
+ #ifndef GDISP_PACKED_PIXELS
+ #define GDISP_PACKED_PIXELS FALSE
+ #endif
+ #ifndef GDISP_PACKED_LINES
+ #define GDISP_PACKED_LINES FALSE
+ #endif
+#endif
+
+/*===========================================================================*/
/* Defines related to the pixel format */
/*===========================================================================*/
@@ -274,26 +333,6 @@ extern GDISPControl *GDISP;
#error "GDISP: No supported pixel format has been specified."
#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
-
-#if GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL
- #error "GDISP: Hardware scrolling is wanted but not supported."
-#endif
-
-#if GDISP_NEED_PIXELREAD && !GDISP_HARDWARE_PIXELREAD
- #error "GDISP: Pixel read-back is wanted but not supported."
-#endif
-
/**
* @brief The type of a pixel.
*/
@@ -775,23 +814,6 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color);
#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
-
/*
* Macro definitions
*/
diff --git a/include/gdisp/lld/gdisp_lld.h b/include/gdisp/lld/gdisp_lld.h
index 46d5488a..38c0ccc0 100644
--- a/include/gdisp/lld/gdisp_lld.h
+++ b/include/gdisp/lld/gdisp_lld.h
@@ -18,188 +18,141 @@
#if GFX_USE_GDISP || defined(__DOXYGEN__)
+#if GDISP_MULTIPLE_DRIVERS && defined(GDISP_LLD_DECLARATIONS)
+ // include hardware definitions
+ #include "gdisp_lld_config.h"
+#endif
+
/*===========================================================================*/
/* Error checks. */
/*===========================================================================*/
-/**
- * @name GDISP hardware accelerated support
- * @{
- */
- /**
- * @brief Hardware streaming interface is supported.
- * @details If set to @p FALSE software emulation is used.
- * @note Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
- */
- #ifndef GDISP_HARDWARE_STREAM
- #define GDISP_HARDWARE_STREAM FALSE
- #endif
-
- /**
- * @brief Hardware streaming requires an explicit end call.
- * @details If set to @p FALSE if an explicit stream end call is not required.
- */
- #ifndef GDISP_HARDWARE_STREAM_END
- #define GDISP_HARDWARE_STREAM_END FALSE
- #endif
-
+#if !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS)
/**
- * @brief Hardware accelerated draw pixel.
- * @details If set to @p FALSE software emulation is used.
- * @note Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
+ * @name GDISP hardware accelerated support
+ * @{
*/
- #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 streaming interface is supported.
+ * @details If set to @p FALSE software emulation is used.
+ * @note Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
+ */
+ #ifndef GDISP_HARDWARE_STREAM
+ #define GDISP_HARDWARE_STREAM 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 streaming requires an explicit end call.
+ * @details If set to @p FALSE if an explicit stream end call is not required.
+ */
+ #ifndef GDISP_HARDWARE_STREAM_END
+ #define GDISP_HARDWARE_STREAM_END 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 Hardware accelerated draw pixel.
+ * @details If set to @p FALSE software emulation is used.
+ * @note Either GDISP_HARDWARE_STREAM or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver
+ */
+ #ifndef GDISP_HARDWARE_DRAWPIXEL
+ #define GDISP_HARDWARE_DRAWPIXEL 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 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 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 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 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 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 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
-/** @} */
+ /**
+ * @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
-/**
- * @name GDISP software algorithm choices
- * @{
- */
-/** @} */
+ /**
+ * @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
-/**
- * @name GDISP pixel format choices
- * @{
- */
- /**
- * @brief The native pixel format for this device
- * @note Should be set to one of the following:
- * GDISP_PIXELFORMAT_RGB565
- * GDISP_PIXELFORMAT_BGR565
- * GDISP_PIXELFORMAT_RGB888
- * GDISP_PIXELFORMAT_RGB444
- * GDISP_PIXELFORMAT_RGB332
- * GDISP_PIXELFORMAT_RGB666
- * GDISP_PIXELFORMAT_CUSTOM
- * @note If you set GDISP_PIXELFORMAT_CUSTOM you need to also define
- * color_t, RGB2COLOR(r,g,b), HTML2COLOR(h),
- * RED_OF(c), GREEN_OF(c), BLUE_OF(c),
- * COLOR(c) and MASKCOLOR.
- */
- #ifndef GDISP_PIXELFORMAT
- #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_ERROR
- #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 Do pixels require packing for a blit
- * @note Is only valid for a pixel format that doesn't fill it's datatype. ie formats:
- * GDISP_PIXELFORMAT_RGB888
- * GDISP_PIXELFORMAT_RGB444
- * GDISP_PIXELFORMAT_RGB666
- * GDISP_PIXELFORMAT_CUSTOM
- * @note If you use GDISP_PIXELFORMAT_CUSTOM and packed bit fills
- * you need to also define @p gdispPackPixels(buf,cx,x,y,c)
- * @note If you are using GDISP_HARDWARE_BITFILLS = FALSE then the pixel
- * format must not be a packed format as the software blit does
- * not support packed pixels
- * @note Very few cases should actually require packed pixels as the low
- * level driver can also pack on the fly as it is sending it
- * to the graphics device.
- */
- #ifndef GDISP_PACKED_PIXELS
- #define GDISP_PACKED_PIXELS 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 Do lines of pixels require packing for a blit
- * @note Ignored if GDISP_PACKED_PIXELS is FALSE
- */
- #ifndef GDISP_PACKED_LINES
- #define GDISP_PACKED_LINES 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
+ /** @} */
+#endif
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
typedef struct GDISPDriver {
- GDISPControl g;
+ GDISPControl g;
+
+ #if GDISP_MULTIPLE_DRIVERS
+ const struct GDISPVMT const * vmt;
+ #endif
- uint16_t flags;
+ uint16_t flags;
#define GDISP_FLG_INSTREAM 0x0001
// Multithread Mutex
#if GDISP_NEED_MULTITHREAD
- gfxMutex mutex;
+ 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 */
+ #if (GDISP_MULTIPLE_DRIVERS || !GDISP_HARDWARE_CLIP) && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION)
+ coord_t clipx0, clipy0;
+ coord_t clipx1, clipy1; /* not inclusive */
#endif
// Driver call parameters
@@ -212,8 +165,10 @@ typedef struct GDISPDriver {
void *ptr;
} p;
- // Text rendering parameters
+ // In call working buffers
+
#if GDISP_NEED_TEXT
+ // Text rendering parameters
struct {
font_t font;
color_t color;
@@ -222,53 +177,363 @@ typedef struct GDISPDriver {
coord_t clipx1, clipy1;
} t;
#endif
+ #if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM && GDISP_HARDWARE_BITFILLS))
+ // A pixel line buffer
+ color_t linebuf[GDISP_LINEBUF_SIZE];
+ #endif
+
} GDISPDriver;
-extern GDISPDriver GDISP_DRIVER_STRUCT;
+#if !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS)
+ #if GDISP_MULTIPLE_DRIVERS
+ #define LLDSPEC static
+ #else
+ #define LLDSPEC
+ #endif
-#ifdef __cplusplus
-extern "C" {
-#endif
+ #ifdef __cplusplus
+ extern "C" {
+ #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(GDISPDriver *g);
- bool_t gdisp_lld_init(void);
#if GDISP_HARDWARE_STREAM
- void gdisp_lld_stream_start(void); // Uses p.x,p.y p.cx,p.cy
- void gdisp_lld_stream_color(void); // Uses p.color
+ /**
+ * @brief Start a streamed operation
+ * @pre GDISP_HARDWARE_STREAM 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_stream_start(GDISPDriver *g);
+ /**
+ * @brief Send a pixel to the current streaming position and then increment that position
+ * @pre GDISP_HARDWARE_STREAM 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_stream_color(GDISPDriver *g);
+
+ #if GDISP_HARDWARE_STREAM_READ
+ /**
+ * @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 and 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_stream_read(GDISPDriver *g);
+ #endif
+
#if GDISP_HARDWARE_STREAM_END
- void gdisp_lld_stream_stop(void); // Uses no parameters
+ /**
+ * @brief End the current streaming operation
+ * @pre GDISP_HARDWARE_STREAM and GDISP_HARDWARE_STREAM_END is TRUE
+ *
+ * @param[in] g The driver structure
+ *
+ * @note The parameter variables must not be altered by the driver.
+ */
+ LLDSPEC void gdisp_lld_stream_stop(GDISPDriver *g);
#endif
#endif
+
#if GDISP_HARDWARE_DRAWPIXEL
- void gdisp_lld_draw_pixel(void); // Uses p.x,p.y p.color
+ /**
+ * @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(GDISPDriver *g);
#endif
+
#if GDISP_HARDWARE_CLEARS
- void gdisp_lld_clear(void); // Uses p.color
+ /**
+ * @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(GDISPDriver *g);
#endif
+
#if GDISP_HARDWARE_FILLS
- void gdisp_lld_fill_area(void); // Uses p.x,p.y p.cx,p.cy p.color
+ /**
+ * @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(GDISPDriver *g);
#endif
+
#if GDISP_HARDWARE_BITFILLS
- void gdisp_lld_blit_area_ex(void); // Uses p.x,p.y p.cx,p.cy p.x1,p.y1 (=srcx,srcy) p.x2 (=srccx), p.ptr (=buffer)
+ /**
+ * @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(GDISPDriver *g);
#endif
- #if GDISP_HARDWARE_PIXELREAD && GDISP_NEED_PIXELREAD
- color_t gdisp_lld_get_pixel_color(void); // Uses p.x,p.y
+
+ #if GDISP_HARDWARE_PIXELREAD
+ /**
+ * @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(GDISPDriver *g);
#endif
+
#if GDISP_HARDWARE_SCROLL && GDISP_NEED_SCROLL
- void gdisp_lld_vertical_scroll(void); // Uses p.x,p.y p.cx,p.cy, p.y1 (=lines) p.color
+ /**
+ * @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(GDISPDriver *g);
#endif
+
#if GDISP_HARDWARE_CONTROL && GDISP_NEED_CONTROL
- void gdisp_lld_control(void); // Uses p.x (=what) p.ptr (=value)
+ /**
+ * @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(GDISPDriver *g);
#endif
+
#if GDISP_HARDWARE_QUERY && GDISP_NEED_QUERY
- void *gdisp_lld_query(void); // Uses p.x (=what);
+ /**
+ * @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(GDISPDriver *g); // Uses p.x (=what);
#endif
+
#if GDISP_HARDWARE_CLIP && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION)
- void gdisp_lld_set_clip(void); // Uses p.x,p.y p.cx,p.cy
+ /**
+ * @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(GDISPDriver *g);
#endif
-#ifdef __cplusplus
-}
-#endif
+ #ifdef __cplusplus
+ }
+ #endif
+#endif // !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS)
+
+
+#if GDISP_MULTIPLE_DRIVERS
+
+ typedef struct GDISPVMT {
+ bool_t (*init)(GDISPDriver *g);
+ void (*streamstart)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy
+ void (*streamcolor)(GDISPDriver *g); // Uses p.color
+ color_t (*streamread)(GDISPDriver *g); // Uses no parameters
+ void (*streamstop)(GDISPDriver *g); // Uses no parameters
+ void (*pixel)(GDISPDriver *g); // Uses p.x,p.y p.color
+ void (*clear)(GDISPDriver *g); // Uses p.color
+ void (*fill)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy p.color
+ void (*blit)(GDISPDriver *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)(GDISPDriver *g); // Uses p.x,p.y
+ void (*vscroll)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy, p.y1 (=lines) p.color
+ void (*control)(GDISPDriver *g); // Uses p.x (=what) p.ptr (=value)
+ void *(*query)(GDISPDriver *g); // Uses p.x (=what);
+ void (*setclip)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy
+ } GDISPVMT;
+
+ #ifdef GDISP_LLD_DECLARATIONS
+ #define GDISP_DRIVER_STRUCT_INIT {{0}, &VMT}
+ static const GDISPVMT VMT = {
+ gdisp_lld_init,
+ #if GDISP_HARDWARE_STREAM
+ gdisp_lld_stream_start,
+ gdisp_lld_stream_color,
+ gdisp_lld_stream_read,
+ #if GDISP_HARDWARE_STREAM_END
+ gdisp_lld_stream_stop,
+ #else
+ 0,
+ #endif
+ #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
+ };
+ GDISPDriver GDISP_DRIVER_STRUCT = {{0}, &VMT};
+
+ #else
+ #define gdisp_lld_init(g) g->vmt->init(g)
+ #define gdisp_lld_stream_start(g) g->vmt->streamstart(g)
+ #define gdisp_lld_stream_color(g) g->vmt->streamcolor(g)
+ #define gdisp_lld_stream_read(g) g->vmt->streamread(g)
+ #define gdisp_lld_stream_stop(g) g->vmt->streamstop(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)
+
+ extern GDISPDriver GDISP_DRIVER_STRUCT;
+
+ #endif // GDISP_LLD_DECLARATIONS
+
+#else // GDISP_MULTIPLE_DRIVERS
+ #ifdef GDISP_LLD_DECLARATIONS
+ GDISPDriver GDISP_DRIVER_STRUCT;
+ #else
+ extern GDISPDriver GDISP_DRIVER_STRUCT;
+ #endif
+
+#endif // GDISP_MULTIPLE_DRIVERS
+
+ /* 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 */
diff --git a/include/gdisp/options.h b/include/gdisp/options.h
index d5818284..1a0f6907 100644
--- a/include/gdisp/options.h
+++ b/include/gdisp/options.h
@@ -21,54 +21,85 @@
* @{
*/
/**
+ * @brief Should support for multiple displays be provided.
+ * @details Defaults to FALSE.
+ * @note Setting this to TRUE can significantly increase code size as many
+ * optimizations that remove code through conditional compilation can't
+ * be done. It may also slow some graphics operations as extra tests must
+ * be performed to determine how to do a particular operation. For these
+ * reasons do not set it to TRUE unless you really need multiple display
+ * support.
+ */
+ #ifndef GDISP_MULTIPLE_DRIVERS
+ #define GDISP_MULTIPLE_DRIVERS FALSE
+ #endif
+ /**
* @brief Should all operations be clipped to the screen and colors validated.
* @details Defaults to TRUE.
* @note If this is FALSE, any operations that extend beyond the
* edge of the screen will have undefined results. Any
* out-of-range colors will produce undefined results.
- * @note If defined then all low level and high level GDISP driver routines
- * must check the validity of inputs and do something sensible
- * if they are out of range. It doesn't have to be efficient,
- * just valid.
+ * @note This should always be left as the default (TRUE) unless you
+ * are a maniac for speed and you have thoroughly tested your code
+ * and it never overwrites the edges of the screen.
+ * @note Setting GDISP_NEED_CLIP to TRUE internally uses the same mechanism
+ * as this validation. There is no advantage in setting this FALSE if
+ * GDISP_NEED_CLIP is TRUE.
*/
#ifndef GDISP_NEED_VALIDATION
- #define GDISP_NEED_VALIDATION TRUE
+ #define GDISP_NEED_VALIDATION TRUE
#endif
/**
* @brief Are clipping functions needed.
* @details Defaults to TRUE
*/
#ifndef GDISP_NEED_CLIP
- #define GDISP_NEED_CLIP TRUE
+ #define GDISP_NEED_CLIP TRUE
+ #endif
+ /**
+ * @brief Streaming functions are needed
+ * @details Defaults to FALSE.
+ */
+ #ifndef GDISP_NEED_STREAMING
+ #define GDISP_NEED_STREAMING FALSE
#endif
/**
* @brief Are text functions needed.
* @details Defaults to TRUE
+ * @note You must also define at least one font.
*/
#ifndef GDISP_NEED_TEXT
- #define GDISP_NEED_TEXT TRUE
+ #define GDISP_NEED_TEXT TRUE
#endif
/**
* @brief Are circle functions needed.
- * @details Defaults to TRUE
+ * @details Defaults to FALSE
+ * @note Uses integer algorithms only. It does not use any trig or floating point.
*/
#ifndef GDISP_NEED_CIRCLE
- #define GDISP_NEED_CIRCLE TRUE
+ #define GDISP_NEED_CIRCLE FALSE
#endif
/**
* @brief Are ellipse functions needed.
- * @details Defaults to TRUE
+ * @details Defaults to FALSE
+ * @note Uses integer algorithms only. It does not use any trig or floating point.
*/
#ifndef GDISP_NEED_ELLIPSE
- #define GDISP_NEED_ELLIPSE TRUE
+ #define GDISP_NEED_ELLIPSE FALSE
#endif
/**
* @brief Are arc functions needed.
* @details Defaults to FALSE
- * @note Requires the maths library to be included in the link. ie -lm
+ * @note This can be compiled using fully integer mathematics by
+ * defining GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG as TRUE.
+ * @note This can be compiled to use floating point but no trig functions
+ * by defining GFX_USE_GMISC and GMISC_NEED_FASTTRIG as TRUE.
+ * @note If neither of the above are defined it requires the maths library
+ * to be included in the link to provide floating point and trig support.
+ * ie include -lm in your compiler flags.
*/
#ifndef GDISP_NEED_ARC
- #define GDISP_NEED_ARC FALSE
+ #define GDISP_NEED_ARC FALSE
#endif
/**
* @brief Are convex polygon functions needed.
@@ -88,7 +119,7 @@
* option will cause a compile error.
*/
#ifndef GDISP_NEED_SCROLL
- #define GDISP_NEED_SCROLL FALSE
+ #define GDISP_NEED_SCROLL FALSE
#endif
/**
* @brief Is the capability to read pixels back needed.
@@ -98,7 +129,7 @@
* option will cause a compile error.
*/
#ifndef GDISP_NEED_PIXELREAD
- #define GDISP_NEED_PIXELREAD FALSE
+ #define GDISP_NEED_PIXELREAD FALSE
#endif
/**
* @brief Control some aspect of the hardware operation.
@@ -107,7 +138,7 @@
* screen rotation, backlight levels, contrast etc
*/
#ifndef GDISP_NEED_CONTROL
- #define GDISP_NEED_CONTROL FALSE
+ #define GDISP_NEED_CONTROL FALSE
#endif
/**
* @brief Query some aspect of the hardware operation.
@@ -115,21 +146,14 @@
* @note This allows query of hardware specific features
*/
#ifndef GDISP_NEED_QUERY
- #define GDISP_NEED_QUERY FALSE
+ #define GDISP_NEED_QUERY FALSE
#endif
/**
* @brief Is the image interface required.
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE
- #define GDISP_NEED_IMAGE FALSE
- #endif
- /**
- * @brief Is the messaging api interface required.
- * @details Defaults to FALSE
- */
- #ifndef GDISP_NEED_MSGAPI
- #define GDISP_NEED_MSGAPI FALSE
+ #define GDISP_NEED_IMAGE FALSE
#endif
/**
* @}
@@ -143,42 +167,42 @@
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE_NATIVE
- #define GDISP_NEED_IMAGE_NATIVE FALSE
+ #define GDISP_NEED_IMAGE_NATIVE FALSE
#endif
/**
* @brief Is GIF image decoding required.
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE_GIF
- #define GDISP_NEED_IMAGE_GIF FALSE
+ #define GDISP_NEED_IMAGE_GIF FALSE
#endif
/**
* @brief Is BMP image decoding required.
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE_BMP
- #define GDISP_NEED_IMAGE_BMP FALSE
+ #define GDISP_NEED_IMAGE_BMP FALSE
#endif
/**
* @brief Is JPG image decoding required.
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE_JPG
- #define GDISP_NEED_IMAGE_JPG FALSE
+ #define GDISP_NEED_IMAGE_JPG FALSE
#endif
/**
* @brief Is PNG image decoding required.
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE_PNG
- #define GDISP_NEED_IMAGE_PNG FALSE
+ #define GDISP_NEED_IMAGE_PNG FALSE
#endif
/**
* @brief Is memory accounting required during image decoding.
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_IMAGE_ACCOUNTING
- #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
+ #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
#endif
/**
* @}
@@ -191,7 +215,7 @@
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_UTF8
- #define GDISP_NEED_UTF8 FALSE
+ #define GDISP_NEED_UTF8 FALSE
#endif
/**
@@ -199,7 +223,7 @@
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_TEXT_KERNING
- #define GDISP_NEED_TEXT_KERNING FALSE
+ #define GDISP_NEED_TEXT_KERNING FALSE
#endif
/**
@@ -207,7 +231,7 @@
* @details Defaults to FALSE
*/
#ifndef GDISP_NEED_ANTIALIAS
- #define GDISP_NEED_ANTIALIAS FALSE
+ #define GDISP_NEED_ANTIALIAS FALSE
#endif
/**
@@ -219,27 +243,10 @@
/**
* @brief Do the drawing functions need to be thread-safe.
* @details Defaults to FALSE
- * @note Both GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC make
- * the gdisp API thread-safe.
- * @note This is more efficient than GDISP_NEED_ASYNC as it only
- * requires a context switch if something else is already
- * drawing.
*/
#ifndef GDISP_NEED_MULTITHREAD
#define GDISP_NEED_MULTITHREAD FALSE
#endif
- /**
- * @brief Use asynchronous calls (multi-thread safe).
- * @details Defaults to FALSE
- * @note Both GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC make
- * the gdisp API thread-safe.
- * @note Turning this on adds two context switches per transaction
- * so it can significantly slow graphics drawing but it allows
- * drawing operations to continue in the background.
- */
- #ifndef GDISP_NEED_ASYNC
- #define GDISP_NEED_ASYNC FALSE
- #endif
/**
* @}
*
@@ -257,6 +264,23 @@
* @name GDISP Optional Sizing Parameters
* @{
*/
+ /**
+ * @brief The size of pixel buffer (in pixels) used for optimization.
+ * @details Set to zero to guarantee disabling of the buffer.
+ * @note Depending on the driver and what operations the application
+ * needs, this buffer may never be allocated.
+ * @note Setting the size to zero may cause some operations to not
+ * compile eg. Scrolling if there is no hardware scroll support.
+ * @note Increasing the size will speedup certain operations
+ * at the expense of RAM.
+ * @note Currently only used to support scrolling on hardware without
+ * scrolling support, and to increase the speed of streaming
+ * operations on non-streaming hardware where there is a
+ * hardware supported bit-blit.
+ */
+ #ifndef GDISP_LINEBUF_SIZE
+ #define GDISP_LINEBUF_SIZE 128
+ #endif
/**
* @}
*
@@ -282,12 +306,6 @@
/* #define GDISP_SCREEN_WIDTH nnnn */
/* #define GDISP_SCREEN_HEIGHT nnnn */
/**
- * @brief Define which threading model to use.
- * @details Optional for the X11 driver.
- * @note Defaults to TRUE. Setting to FALSE causes POSIX threads to be used
- */
- /* #define GDISP_THREAD_CHIBIOS FALSE */
- /**
* @brief Define which bus interface to use.
* @details Only required by the SSD1963 driver.
* @note This will be replaced eventually by board definition files
@@ -296,10 +314,6 @@
/* #define GDISP_USE_GPIO */
/** @} */
-#if GFX_USE_GDISP
- #include "gdisp_lld_config.h"
-#endif
-
#endif /* _GDISP_OPTIONS_H */
/** @} */
diff --git a/include/gfx_rules.h b/include/gfx_rules.h
index afd2a8fe..a8dd031e 100644
--- a/include/gfx_rules.h
+++ b/include/gfx_rules.h
@@ -134,17 +134,13 @@
#endif
#if GFX_USE_GDISP
- #if GDISP_NEED_MULTITHREAD && GDISP_NEED_ASYNC
- #error "GDISP: Only one of GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC should be defined."
- #endif
- #if GDISP_NEED_ASYNC && !(GFX_USE_GQUEUE && GQUEUE_NEED_GSYNC)
- #if GFX_DISPLAY_RULE_WARNINGS
- #warning "GDISP: GDISP_NEED_ASYNC requires GFX_USE_GQUEUE and GQUEUE_NEED_GSYNC. They have been turned on for you."
+ #if GDISP_MULTIPLE_DRIVERS
+ #ifndef GDISP_PIXELFORMAT
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GDISP: GDISP_MULTIPLE_DRIVERS requires GDISP_PIXELFORMAT to be set. It has been defaulted to GDISP_PIXELFORMAT_RGB565."
+ #endif
+ #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
#endif
- #undef GFX_USE_GQUEUE
- #define GFX_USE_GQUEUE TRUE
- #undef GQUEUE_NEED_GSYNC
- #define GQUEUE_NEED_GSYNC TRUE
#endif
#if GDISP_NEED_ANTIALIAS && !GDISP_NEED_PIXELREAD
#if GDISP_HARDWARE_PIXELREAD
@@ -161,11 +157,11 @@
#endif
#if (defined(GDISP_INCLUDE_FONT_SMALL) && GDISP_INCLUDE_FONT_SMALL) || (defined(GDISP_INCLUDE_FONT_LARGER) && GDISP_INCLUDE_FONT_LARGER)
#if GFX_DISPLAY_RULE_WARNINGS
- #warning "GDISP: An old font (Small or Larger) has been defined. A single default font of DEJAVUSANS12 has been added instead."
+ #warning "GDISP: An old font (Small or Larger) has been defined. A single default font of UI2 has been added instead."
#warning "GDISP: Please see <$(GFXLIB)/include/gdisp/fonts/fonts.h> for a list of available font names."
#endif
- #undef GDISP_INCLUDE_FONT_DEJAVUSANS12
- #define GDISP_INCLUDE_FONT_DEJAVUSANS12 TRUE
+ #undef GDISP_INCLUDE_FONT_UI2
+ #define GDISP_INCLUDE_FONT_UI2 TRUE
#endif
#endif
diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c
index 1aecd26c..25c2621d 100644
--- a/src/gdisp/gdisp.c
+++ b/src/gdisp/gdisp.c
@@ -50,7 +50,7 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
#if GDISP_HARDWARE_STREAM_END
#define STREAM_CLEAR() if ((GC->flags & GDISP_FLG_INSTREAM)) { \
- gdisp_lld_stream_end(); \
+ gdisp_lld_stream_end(GC); \
GC->flags &= ~GDISP_FLG_INSTREAM; \
}
#else
@@ -71,10 +71,10 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
#if NEED_CLIPPING
static INLINE void drawpixel_clip(void) {
if (GC->p.x >= GC->clipx0 && GC->p.x < GC->clipx1 && GC->p.y >= GC->clipy0 && GC->p.y < GC->clipy1)
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
}
#else
- #define drawpixel_clip() gdisp_lld_draw_pixel()
+ #define drawpixel_clip() gdisp_lld_draw_pixel(GC)
#endif
#else
// Worst is streaming
@@ -85,10 +85,10 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
#endif
GC->cx = GC->cy = 1;
- gdisp_lld_stream_start();
- gdisp_lld_stream_color();
+ gdisp_lld_stream_start(GC);
+ gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end();
+ gdisp_lld_stream_end(GC);
#endif
}
#endif
@@ -99,7 +99,7 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
// Note: This is not clipped
#if GDISP_HARDWARE_FILLS
// Best is hardware accelerated area fill
- #define fillarea() gdisp_lld_fill_area()
+ #define fillarea() gdisp_lld_fill_area(GC)
#elif GDISP_HARDWARE_STREAM
// Next best is hardware streaming
static INLINE void fillarea(void) {
@@ -107,11 +107,11 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
area = (uint32_t)GC->p.cx * GC->p.cy;
- gdisp_lld_stream_start();
+ gdisp_lld_stream_start(GC);
for(; area; area--)
- gdisp_lld_stream_color();
+ gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end(gc);
+ gdisp_lld_stream_end(GC);
#endif
}
#else
@@ -125,7 +125,7 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g;
y1 = GC->p.y + GC->p.cy;
for(; GC->p.y < y1; GC->p.y++, GC->p.x = x0)
for(; GC->p.x < x1; GC->p.x++)
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
GC->p.y = y0;
}
#endif
@@ -164,14 +164,14 @@ static void hline_clip(void) {
if (GC->p.x == GC->p.x1) {
#if GDISP_HARDWARE_DRAWPIXEL
// Best is hardware accelerated pixel draw
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
#else
// Worst is streaming
GC->p.cx = GC->p.cy = 1;
- gdisp_lld_stream_start();
- gdisp_lld_stream_color();
+ gdisp_lld_stream_start(GC);
+ gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end();
+ gdisp_lld_stream_end(GC);
#endif
#endif
return;
@@ -182,19 +182,19 @@ static void hline_clip(void) {
// Best is hardware accelerated area fill
GC->p.cx = GC->p.x1 - GC->p.x + 1;
GC->p.cy = 1;
- gdisp_lld_fill_area();
+ gdisp_lld_fill_area(GC);
#elif GDISP_HARDWARE_STREAM
// Next best is streaming
GC->p.cx = GC->p.x1 - GC->p.x;
- gdisp_lld_stream_start();
- do { gdisp_lld_stream_color(); } while(GC->p.cx--);
+ gdisp_lld_stream_start(GC);
+ do { gdisp_lld_stream_color(GC); } while(GC->p.cx--);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end();
+ gdisp_lld_stream_end(GC);
#endif
#else
// Worst is drawing pixels
for(; GC->p.x <= GC->p.x1; GC->p.x++)
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
#endif
}
@@ -221,14 +221,14 @@ static void vline_clip(void) {
if (GC->p.y == GC->p.y1) {
#if GDISP_HARDWARE_DRAWPIXEL
// Best is hardware accelerated pixel draw
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
#else
// Worst is streaming
GC->p.cx = GC->p.cy = 1;
- gdisp_lld_stream_start();
- gdisp_lld_stream_color();
+ gdisp_lld_stream_start(GC);
+ gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end();
+ gdisp_lld_stream_end(GC);
#endif
#endif
return;
@@ -239,19 +239,19 @@ static void vline_clip(void) {
// Best is hardware accelerated area fill
GC->p.cy = GC->p.y1 - GC->p.y + 1;
GC->p.cx = 1;
- gdisp_lld_fill_area();
+ gdisp_lld_fill_area(GC);
#elif GDISP_HARDWARE_STREAM
// Next best is streaming
GC->p.cy = GC->p.y1 - GC->p.y;
- gdisp_lld_stream_start();
- do { gdisp_lld_stream_color(); } while(GC->p.cy--);
+ gdisp_lld_stream_start(GC);
+ do { gdisp_lld_stream_color(GC); } while(GC->p.cy--);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end();
+ gdisp_lld_stream_end(GC);
#endif
#else
// Worst is drawing pixels
for(; GC->p.y <= GC->p.y1; GC->p.y++)
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
#endif
}
@@ -342,14 +342,15 @@ void _gdispInit(void) {
/* Initialise driver */
MUTEX_ENTER();
- gdisp_lld_init();
+ GC->flags = 0;
+ gdisp_lld_init(GC);
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
#if GDISP_HARDWARE_CLIP
GC->p.x = x;
GC->p.y = y;
GC->p.cx = cx;
GC->p.cy = cy;
- gdisp_lld_set_clip();
+ gdisp_lld_set_clip(GC);
#else
GC->clipx0 = 0;
GC->clipy0 = 0;
@@ -360,75 +361,140 @@ void _gdispInit(void) {
MUTEX_EXIT();
}
-void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) {
- MUTEX_ENTER();
+#if GDISP_NEED_STREAMING
+ void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ MUTEX_ENTER();
- #if NEED_CLIPPING
- // Test if the area is valid - if not then exit
- if (x < GC->clipx0 || x+cx >= GC->clipx1 || y < GC->clipy0 || y+cy >= GC->clipy1) {
- MUTEX_EXIT();
- return;
- }
- #endif
+ #if NEED_CLIPPING
+ // Test if the area is valid - if not then exit
+ if (x < GC->clipx0 || x+cx >= GC->clipx1 || y < GC->clipy0 || y+cy >= GC->clipy1) {
+ MUTEX_EXIT();
+ return;
+ }
+ #endif
- GC->flags |= GDISP_FLG_INSTREAM;
+ GC->flags |= GDISP_FLG_INSTREAM;
- #if GDISP_HARDWARE_STREAM
- // Best is hardware streaming
- GC->p.x = x;
- GC->p.y = y;
- GC->p.cx = cx;
- GC->p.cy = cy;
- gdisp_lld_stream_start();
- #else
- // Worst - save the parameters and use pixel drawing
+ #if GDISP_HARDWARE_STREAM
+ // Best is hardware streaming
+ GC->p.x = x;
+ GC->p.y = y;
+ GC->p.cx = cx;
+ GC->p.cy = cy;
+ gdisp_lld_stream_start(GC);
+ #else
+ // Worst - save the parameters and use pixel drawing
+
+ // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position, cx = bufpos
+ GC->p.x1 = GC->p.x = x;
+ GC->p.y1 = GC->p.y = y;
+ GC->p.x2 = x + cx;
+ GC->p.y2 = y + cy;
+ GC->p.cx = 0;
+ #endif
- // Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position
- GC->p.x1 = GC->p.x = x;
- GC->p.y1 = GC->p.y = y;
- GC->p.x2 = GC->p.x + GC->p.cx;
- GC->p.x2 = GC->p.x + GC->p.cx;
- #endif
+ // Don't release the mutex as gdispStreamEnd() will do that.
+ }
- // Don't release the mutex as gdispStreamEnd() will do that.
-}
+ void gdispStreamColor(color_t color) {
+ #if !GDISP_HARDWARE_STREAM && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
+ coord_t pos, sx1, sy1, sx2;
+ #endif
-void gdispStreamColor(color_t color) {
- // Don't touch the mutex as we should already own it
+ // Don't touch the mutex as we should already own it
- // Ignore this call if we are not streaming
- if (!(GC->flags & GDISP_FLG_INSTREAM))
- return;
+ // Ignore this call if we are not streaming
+ if (!(GC->flags & GDISP_FLG_INSTREAM))
+ return;
- #if GDISP_HARDWARE_STREAM
- // Best is hardware streaming
- GC->p.color = color;
- gdisp_lld_stream_color();
- #else
- // Worst is using pixel drawing
- GC->p.color = color;
- gdisp_lld_draw_pixel();
+ #if GDISP_HARDWARE_STREAM
+ // Best is hardware streaming
+ GC->p.color = color;
+ gdisp_lld_stream_color(GC);
+ #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
+ GC->linebuf[GC->p.cx++] = color;
+ if (GC->p.cx >= GDISP_LINEBUF_SIZE) {
+ pos = GC->p.cx;
+ sx1 = GC->p.x1;
+ sy1 = GC->p.y1;
+ sx2 = GC->p.x2;
+ GC->p.x -= pos;
+ GC->p.cx = pos;
+ GC->p.cy = 1;
+ GC->p.x1 = 0;
+ GC->p.y1 = 0;
+ GC->p.x2 = pos;
+ GC->p.ptr = (void *)GC->linebuf;
+ gdisp_lld_blit_area(GC);
+ GC->p.x1 = sx1;
+ GC->p.y1 = sy1;
+ GC->p.x2 = sx2;
+ GC->p.x += pos;
+ GC->p.cx = 0;
+ }
- // Just wrap at end-of-line and end-of-buffer
- if (++GC->p.x >= GC->p.x2) {
- GC->p.x = GC->p.x1;
- if (++GC->p.y >= GC->p.x2)
- GC->p.y = GC->p.y1;
- }
- #endif
-}
+ // Just wrap at end-of-line and end-of-buffer
+ if (++GC->p.x >= GC->p.x2) {
+ if (GC->p.cx) {
+ pos = GC->p.cx;
+ sx1 = GC->p.x1;
+ sy1 = GC->p.y1;
+ sx2 = GC->p.x2;
+ GC->p.x -= pos;
+ GC->p.cx = pos;
+ GC->p.cy = 1;
+ GC->p.x1 = 0;
+ GC->p.y1 = 0;
+ GC->p.x2 = pos;
+ GC->p.ptr = (void *)GC->linebuf;
+ gdisp_lld_blit_area(GC);
+ GC->p.x1 = sx1;
+ GC->p.y1 = sy1;
+ GC->p.x2 = sx2;
+ GC->p.cx = 0;
+ }
+ GC->p.x = GC->p.x1;
+ if (++GC->p.y >= GC->p.x2)
+ GC->p.y = GC->p.y1;
+ }
+ #else
+ // Worst is using pixel drawing
+ GC->p.color = color;
+ gdisp_lld_draw_pixel(GC);
+
+ // Just wrap at end-of-line and end-of-buffer
+ if (++GC->p.x >= GC->p.x2) {
+ GC->p.x = GC->p.x1;
+ if (++GC->p.y >= GC->p.x2)
+ GC->p.y = GC->p.y1;
+ }
+ #endif
+ }
-void gdispStreamEnd(void) {
- // Only release the mutex and end the stream if we are actually streaming.
- if (!(GC->flags & GDISP_FLG_INSTREAM))
- return;
+ void gdispStreamEnd(void) {
+ // Only release the mutex and end the stream if we are actually streaming.
+ if (!(GC->flags & GDISP_FLG_INSTREAM))
+ return;
- #if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end();
- #endif
- GC->flags &= ~GDISP_FLG_INSTREAM;
- MUTEX_EXIT();
-}
+ #if GDISP_HARDWARE_STREAM
+ #if GDISP_HARDWARE_STREAM_END
+ gdisp_lld_stream_end(GC);
+ #endif
+ #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS
+ if (GC->p.cx) {
+ GC->p.x -= GC->p.cx;
+ GC->p.cy = 1;
+ GC->p.x1 = 0;
+ GC->p.y1 = 0;
+ GC->p.x2 = GC->p.cx;
+ GC->p.ptr = (void *)GC->linebuf;
+ gdisp_lld_blit_area(GC);
+ }
+ #endif
+ GC->flags &= ~GDISP_FLG_INSTREAM;
+ MUTEX_EXIT();
+ }
+#endif
void gdispDrawPixel(coord_t x, coord_t y, color_t color) {
MUTEX_ENTER();
@@ -457,14 +523,14 @@ void gdispClear(color_t color) {
#if GDISP_HARDWARE_CLEARS
// Best is hardware accelerated clear
GC->p.color = color;
- gdisp_lld_clear();
+ gdisp_lld_clear(GC);
#elif GDISP_HARDWARE_FILLS
// Next best is hardware accelerated area fill
GC->p.x = GC->p.y = 0;
GC->p.cx = GC->g.Width;
GC->p.cy = GC->g.Height;
GC->p.color = color;
- gdisp_lld_fill_area();
+ gdisp_lld_fill_area(GC);
#elif GDISP_HARDWARE_STREAM
// Next best is streaming
uint32_t area;
@@ -475,18 +541,18 @@ void gdispClear(color_t color) {
GC->p.color = color;
area = (uint32_t)GC->p.cx * GC->p.cy;
- gdisp_lld_stream_start();
+ gdisp_lld_stream_start(GC);
for(; area; area--)
- gdisp_lld_stream_color();
+ gdisp_lld_stream_color(GC);
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end(gc);
+ gdisp_lld_stream_end(GC);
#endif
#else
// Worst is drawing pixels
GC->p.color = color;
for(GC->p.y = 0; GC->p.y < GC->g.Height; GC->p.y++)
for(GC->p.x = 0; GC->p.x < GC->g.Width; GC->p.x++)
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
#endif
MUTEX_EXIT();
}
@@ -527,7 +593,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.y1 = srcy;
GC->p.x2 = srccx;
GC->p.ptr = (void *)buffer;
- gdisp_lld_blit_area_ex();
+ gdisp_lld_blit_area(GC);
#elif GDISP_HARDWARE_STREAM
// Next best is hardware streaming
@@ -537,15 +603,15 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
srcy = y + cy;
srccx -= cx;
- gdisp_lld_stream_start(gc);
+ gdisp_lld_stream_start(GC);
for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) {
for(GC->p.x = x; GC->p.x < srcx; GC->p.x++) {
GC->p.color = *buffer++;
- gdisp_lld_stream_color();
+ gdisp_lld_stream_color(GC);
}
}
#if GDISP_HARDWARE_STREAM_END
- gdisp_lld_stream_end(gc);
+ gdisp_lld_stream_end(GC);
#endif
#else
// Worst is drawing pixels
@@ -559,7 +625,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
for(GC->p.y = y; GC->p.y < srcy; GC->p.y++, buffer += srccx) {
for(GC->p.x=x; GC->p.x < srcx; GC->p.x++) {
GC->p.color = *buffer++;
- gdisp_lld_draw_pixel();
+ gdisp_lld_draw_pixel(GC);
}
}
#endif
@@ -575,7 +641,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.y = y;
GC->p.cx = cx;
GC->p.cy = cy;
- gdisp_lld_set_clip();
+ gdisp_lld_set_clip(GC);
#else
// Worst is using software clipping
if (x < 0) { cx += x; x = 0; }
@@ -1456,9 +1522,26 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
/* Always synchronous as it must return a value */
MUTEX_ENTER();
- GC->p.x = x;
- GC->p.y = y;
- c = gdisp_lld_get_pixel_color();
+ #if GDISP_HARDWARE_PIXELREAD
+ // Best is direct pixel read
+ GC->p.x = x;
+ GC->p.y = y;
+ c = gdisp_lld_get_pixel_color(GC);
+ #elif GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ
+ // Next best is hardware streaming
+ GC->p.x = x;
+ GC->p.y = y;
+ GC->p.cx = 1;
+ GC->p.cy = 1;
+ gdisp_lld_stream_start(GC);
+ c = gdisp_lld_stream_read(GC);
+ #if GDISP_HARDWARE_STREAM_END
+ gdisp_lld_stream_end(GC);
+ #endif
+ #else
+ // Worst is "not possible"
+ #error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display"
+ #endif
MUTEX_EXIT();
return c;
@@ -1467,21 +1550,127 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
#if GDISP_NEED_SCROLL
void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ coord_t abslines;
+ #if !GDISP_HARDWARE_SCROLL
+ coord_t fy, dy, ix, fx, i, j;
+ #endif
+
MUTEX_ENTER();
#if NEED_CLIPPING
if (x < GC->clipx0) { cx -= GC->clipx0 - x; x = GC->clipx0; }
if (y < GC->clipy0) { cy -= GC->clipy0 - y; y = GC->clipy0; }
- if (cx <= 0 || cy <= 0 || x >= GC->clipx1 || y >= GC->clipy1) { MUTEX_EXIT(); return; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GC->clipx1 || y >= GC->clipy1) { MUTEX_EXIT(); return; }
if (x+cx > GC->clipx1) cx = GC->clipx1 - x;
if (y+cy > GC->clipy1) cy = GC->clipy1 - y;
#endif
+
+ abslines = lines < 0 ? -lines : lines;
+ if (abslines >= cy) {
+ abslines = cy;
+ cy = 0;
+ } else {
+ #if GDISP_HARDWARE_SCROLL
+ GC->p.x = x;
+ GC->p.y = y;
+ GC->p.cx = cx;
+ GC->p.cy = cy;
+ GC->p.y1 = lines;
+ GC->p.color = bgcolor;
+ gdisp_lld_vertical_scroll(GC);
+ cy -= abslines;
+ #elif GDISP_LINEBUF_SIZE == 0
+ #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support and GDISP_LINEBUF_SIZE is zero."
+ #else
+ cy -= abslines;
+ if (lines < 0) {
+ fy = y+cx-1;
+ dy = -1;
+ } else {
+ fy = y;
+ dy = 1;
+ }
+ // Move the screen - one line at a time
+ for(i = 0; i < cy; i++, fy += dy) {
+
+ // Handle where the buffer is smaller than a line
+ for(ix=0; ix < cx; ix += GDISP_LINEBUF_SIZE) {
+
+ // Calculate the data we can move in one operation
+ fx = cx - ix;
+ if (fx > GDISP_LINEBUF_SIZE)
+ fx = GDISP_LINEBUF_SIZE;
+
+ // Read one line of data from the screen
+ #if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_READ
+ // Best is hardware streaming
+ GC->p.x = x+ix;
+ GC->p.y = fy+lines;
+ GC->p.cx = fx;
+ GC->p.cy = 1;
+ gdisp_lld_stream_start(GC);
+ for(j=0; j < fx; j++)
+ GC->linebuf[j] = gdisp_lld_stream_read(GC);
+ #if GDISP_HARDWARE_STREAM_END
+ gdisp_lld_stream_end(GC);
+ #endif
+ #elif GDISP_HARDWARE_PIXELREAD
+ // Next best is single pixel reads
+ for(j=0; j < fx; j++) {
+ GC->p.x = x+ix+j;
+ GC->p.y = fy+lines;
+ GC->linebuf[j] = gdisp_lld_get_pixel_color(GC);
+ }
+ #else
+ // Worst is "not possible"
+ #error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support for scrolling or reading pixels."
+ #endif
+
+ // Write that line to the new location
+ #if GDISP_HARDWARE_BITFILLS
+ // Best is hardware bitfills
+ GC->p.x = x+ix;
+ GC->p.y = fy;
+ GC->p.cx = fx;
+ GC->p.cy = 1;
+ GC->p.x1 = 0;
+ GC->p.y1 = 0;
+ GC->p.x2 = fx;
+ GC->p.ptr = (void *)GC->linebuf;
+ gdisp_lld_blit_area(GC);
+ #elif GDISP_HARDWARE_STREAM
+ // Next best is hardware streaming
+ GC->p.x = x+ix;
+ GC->p.y = fy;
+ GC->p.cx = fx;
+ GC->p.cy = 1;
+ gdisp_lld_stream_start(GC);
+ for(j = 0; j < fx; j++) {
+ GC->p.color = GC->linebuf[j];
+ gdisp_lld_stream_color(GC);
+ }
+ #if GDISP_HARDWARE_STREAM_END
+ gdisp_lld_stream_end(GC);
+ #endif
+ #else
+ // Worst is drawing pixels
+ GC->p.y = fy;
+ for(GC->p.x = x+ix, j = 0; j < fx; GC->p.x++, j++) {
+ GC->p.color = GC->linebuf[j];
+ gdisp_lld_draw_pixel(GC);
+ }
+ #endif
+ }
+ }
+ #endif
+ }
+
+ /* fill the remaining gap */
GC->p.x = x;
- GC->p.y = y;
+ GC->p.y = lines > 0 ? (y+cy) : y;
GC->p.cx = cx;
- GC->p.cy = cy;
- GC->p.y1 = lines;
+ GC->p.cy = abslines;
GC->p.color = bgcolor;
- gdisp_lld_vertical_scroll();
+ fillarea();
MUTEX_EXIT();
}
#endif
@@ -1492,7 +1681,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
MUTEX_ENTER();
GC->p.x = what;
GC->p.ptr = value;
- gdisp_lld_control();
+ gdisp_lld_control(GC);
#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
if (what == GDISP_CONTROL_ORIENTATION) {
#if GDISP_HARDWARE_CLIP
@@ -1501,7 +1690,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
GC->p.y = 0;
GC->p.cx = GC->g.Width;
GC->p.cy = GC->g.Height;
- gdisp_lld_set_clip();
+ gdisp_lld_set_clip(GC);
#else
// Worst is software clipping
GC->clipx0 = 0;
@@ -1529,7 +1718,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx,
MUTEX_ENTER();
GC->p.x = (coord_t)what;
- res = gdisp_lld_query();
+ res = gdisp_lld_query(GC);
MUTEX_EXIT();
return res;
}
@@ -1677,42 +1866,46 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
#if GDISP_NEED_TEXT
#include "mcufont.h"
- #if GDISP_NEED_ANTIALIAS && GDISP_NEED_PIXELREAD
+ #if GDISP_NEED_ANTIALIAS && GDISP_HARDWARE_PIXELREAD
static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
- if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return;
+ #define GD ((GDISPDriver *)state)
+ if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return;
if (alpha == 255) {
- GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; GC->p.color = GC->t.color;
+ GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color;
hline_clip();
} else {
for (; count; count--, x++) {
- GC->p.x = x; GC->p.y = y;
- GC->p.color = gdispBlendColor(GC->t.color, gdisp_lld_get_pixel_color(), alpha);
+ GD->p.x = x; GD->p.y = y;
+ GD->p.color = gdispBlendColor(GD->t.color, gdisp_lld_get_pixel_color(GD), alpha);
drawpixel_clip();
}
}
+ #undef GD
}
#else
static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
- (void) state;
- if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return;
+ #define GD ((GDISPDriver *)state)
+ if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return;
if (alpha > 0x80) { // A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased
- GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1; GC->p.color = GC->t.color;
+ GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color;
hline_clip();
}
+ #undef GD
}
#endif
#if GDISP_NEED_ANTIALIAS
static void fillcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
- (void) state;
- if (y < GC->t.clipy0 || y >= GC->t.clipy1 || x < GC->t.clipx0 || x+count > GC->t.clipx1) return;
+ #define GD ((GDISPDriver *)state)
+ if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return;
if (alpha == 255) {
- GC->p.color = GC->t.color;
+ GD->p.color = GD->t.color;
} else {
- GC->p.color = gdispBlendColor(GC->t.color, GC->t.bgcolor, alpha);
+ GD->p.color = gdispBlendColor(GD->t.color, GD->t.bgcolor, alpha);
}
- GC->p.x = x; GC->p.y = y; GC->p.x1 = x+count-1;
+ GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1;
hline_clip();
+ #undef GD
}
#else
#define fillcharline drawcharline
@@ -1720,14 +1913,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
/* Callback to render characters. */
static uint8_t drawcharglyph(int16_t x, int16_t y, mf_char ch, void *state) {
- (void) state;
- return mf_render_character(GC->t.font, x, y, ch, drawcharline, 0);
+ return mf_render_character(GC->t.font, x, y, ch, drawcharline, state);
}
/* Callback to render characters. */
static uint8_t fillcharglyph(int16_t x, int16_t y, mf_char ch, void *state) {
- (void) state;
- return mf_render_character(GC->t.font, x, y, ch, fillcharline, 0);
+ return mf_render_character(GC->t.font, x, y, ch, fillcharline, state);
}
void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) {
@@ -1738,7 +1929,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
GC->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x;
GC->t.clipy1 = y + font->height;
GC->t.color = color;
- mf_render_character(font, x, y, c, drawcharline, 0);
+ mf_render_character(font, x, y, c, drawcharline, GC);
MUTEX_EXIT();
}
@@ -1756,7 +1947,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) {
fillarea();
- mf_render_character(font, x, y, c, fillcharline, 0);
+ mf_render_character(font, x, y, c, fillcharline, GC);
}
MUTEX_EXIT();
}
@@ -1770,7 +1961,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
GC->t.clipy1 = y + font->height;
GC->t.color = color;
- mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, 0);
+ mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, GC);
MUTEX_EXIT();
}
@@ -1788,7 +1979,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) {
fillarea();
- mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, 0);
+ mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, GC);
}
MUTEX_EXIT();
}
@@ -1816,7 +2007,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
}
y += (cy+1 - font->height)/2;
- mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, 0);
+ mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, GC);
MUTEX_EXIT();
}
@@ -1852,7 +2043,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
y += (cy+1 - font->height)/2;
/* Render */
- mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, 0);
+ mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, GC);
}
MUTEX_EXIT();
}