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 #include #include @@ -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_SCROLL && GDISP_HARDWARE_SCROLL + void gdisp_lld_vertical_scroll(GDISPDriver *g) { + HDC dcScreen; + RECT rect; + coord_t lines; - #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 (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; @@ -111,15 +105,6 @@ extern GDISPControl *GDISP; #define GDISP_CONTROL_CONTRAST 3 #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 */ @@ -161,6 +146,80 @@ extern GDISPControl *GDISP; #define SkyBlue HTML2COLOR(0x87CEEB) /** @} */ +/*===========================================================================*/ +/* 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 - * @{ - */ +#if !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS) /** - * @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 + * @name GDISP hardware accelerated support + * @{ */ - #ifndef GDISP_HARDWARE_STREAM - #define GDISP_HARDWARE_STREAM 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 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 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 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 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 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 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 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 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 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 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 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 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 -/** @} */ - -/** - * @name GDISP software algorithm choices - * @{ - */ -/** @} */ - -/** - * @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 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 -/** @} */ + /** + * @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; - uint16_t flags; + #if GDISP_MULTIPLE_DRIVERS + const struct GDISPVMT const * vmt; + #endif + + 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 - #endif - #if GDISP_HARDWARE_CLEARS - void gdisp_lld_clear(void); // Uses p.color - #endif - #if GDISP_HARDWARE_FILLS - void gdisp_lld_fill_area(void); // Uses p.x,p.y p.cx,p.cy p.color - #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) - #endif - #if GDISP_HARDWARE_PIXELREAD && GDISP_NEED_PIXELREAD - color_t gdisp_lld_get_pixel_color(void); // Uses p.x,p.y - #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 - #endif - #if GDISP_HARDWARE_CONTROL && GDISP_NEED_CONTROL - void gdisp_lld_control(void); // Uses p.x (=what) p.ptr (=value) - #endif - #if GDISP_HARDWARE_QUERY && GDISP_NEED_QUERY - void *gdisp_lld_query(void); // 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 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 -#ifdef __cplusplus -} -#endif + #if GDISP_HARDWARE_CLEARS + /** + * @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 + /** + * @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 + /** + * @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 + /** + * @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 + /** + * @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 + /** + * @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 + /** + * @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) + /** + * @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 +#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 @@ -20,55 +20,86 @@ * @name GDISP Functionality to be included * @{ */ + /** + * @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 /** * @} * @@ -281,12 +305,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. @@ -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(); + #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; + + #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 + + // 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 + + // 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; - } - #endif - GC->flags |= GDISP_FLG_INSTREAM; + #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; + } - #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 + // 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); - // 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 + // 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 + } - // Don't release the mutex as gdispStreamEnd() will do that. -} + void gdispStreamEnd(void) { + // Only release the mutex and end the stream if we are actually streaming. + if (!(GC->flags & GDISP_FLG_INSTREAM)) + return; -void gdispStreamColor(color_t color) { - // 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; - - #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(); - - // 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; - - #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(); }