From d22bc07e7adf459b2b83fcd0e5bd6475c18e1e9a Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 12 Oct 2013 13:24:40 +1000 Subject: [PATCH] Multiple displays across one or more controllers is now fully supported. Only the Win32 driver supports this so far. Other drivers are currently broken due to API changes and will be fixed. --- drivers/multiple/Win32/gdisp_lld.c | 739 ++++--- drivers/multiple/Win32/gdisp_lld_config.h | 7 +- .../multiple/Win32/ginput_lld_toggle_config.h | 15 +- drivers/multiple/X/gdisp_lld_config.h | 9 +- gfxconf.example.h | 23 + include/gdisp/gdisp.h | 343 ++-- include/gdisp/lld/gdisp_lld.h | 319 ++- include/gdisp/options.h | 57 +- include/gfx_rules.h | 8 +- src/gdisp/gdisp.c | 1769 +++++++++-------- src/gfx.c | 1 - 11 files changed, 1862 insertions(+), 1428 deletions(-) diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c index 41141a90..65627e1c 100644 --- a/drivers/multiple/Win32/gdisp_lld.c +++ b/drivers/multiple/Win32/gdisp_lld.c @@ -9,12 +9,11 @@ * @file drivers/multiple/Win32/gdisp_lld.c * @brief GDISP Graphics Driver subsystem low level driver source for Win32. */ - #include "gfx.h" #if GFX_USE_GDISP -#define GDISP_LLD_DECLARATIONS +#define GDISP_DRIVER_VMT GDISPVMT_Win32 #include "gdisp/lld/gdisp_lld.h" #include @@ -31,51 +30,80 @@ #define GDISP_SCREEN_HEIGHT 480 #endif +#define GDISP_FLG_READY (GDISP_FLG_DRIVER<<0) +#define GDISP_FLG_HASTOGGLE (GDISP_FLG_DRIVER<<1) +#define GDISP_FLG_HASMOUSE (GDISP_FLG_DRIVER<<2) + #if GINPUT_NEED_TOGGLE /* Include toggle support code */ #include "ginput/lld/toggle.h" #endif +#if GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888 + #error "GDISP Win32: This driver currently only supports the RGB888 pixel format." +#endif + #if GINPUT_NEED_MOUSE /* Include mouse support code */ #include "ginput/lld/mouse.h" #endif +// Setting this to TRUE delays updating the screen +// to the windows paint routine. Due to the +// drawing lock this does not add as much speed +// as might be expected but it is still faster in +// all tested circumstances and for all operations +// even draw_pixel(). +// This is probably due to drawing operations being +// combined as the update regions are merged. +#define GDISP_WIN32_USE_INDIRECT_UPDATE TRUE + +// How far extra windows should be offset from the first. +#define DISPLAY_X_OFFSET 50 +#define DISPLAY_Y_OFFSET 50 + +static DWORD winThreadId; +static ATOM winClass; +static volatile bool_t QReady; +static HANDLE drawMutex; + + /*===========================================================================*/ /* Driver local routines . */ /*===========================================================================*/ -#define WIN32_USE_MSG_REDRAW FALSE #if GINPUT_NEED_TOGGLE #define WIN32_BUTTON_AREA 16 #else #define WIN32_BUTTON_AREA 0 #endif -#define APP_NAME "GDISP" +#define APP_NAME "uGFX" #define COLOR2BGR(c) ((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF)) #define BGR2COLOR(c) COLOR2BGR(c) -static HWND winRootWindow = NULL; -static HDC dcBuffer = NULL; -static HBITMAP dcBitmap = NULL; -static HBITMAP dcOldBitmap; -static volatile bool_t isReady = FALSE; -static coord_t wWidth, wHeight; +typedef struct winPriv { + HWND hwnd; + HDC dcBuffer; + HBITMAP dcBitmap; + HBITMAP dcOldBitmap; + #if GINPUT_NEED_MOUSE + coord_t mousex, mousey; + uint16_t mousebuttons; + #endif + #if GINPUT_NEED_TOGGLE + uint8_t toggles; + #endif +} winPriv; -#if GINPUT_NEED_MOUSE - static coord_t mousex, mousey; - static uint16_t mousebuttons; -#endif -#if GINPUT_NEED_TOGGLE - static uint8_t toggles = 0; -#endif static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - HDC dc; - PAINTSTRUCT ps; + HDC dc; + PAINTSTRUCT ps; + GDisplay * g; + winPriv * priv; #if GINPUT_NEED_TOGGLE HBRUSH hbrOn, hbrOff; HPEN pen; @@ -88,86 +116,135 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) switch (Msg) { case WM_CREATE: + // Get our GDisplay structure and attach it to the window + g = (GDisplay *)((LPCREATESTRUCT)lParam)->lpCreateParams; + priv = (winPriv *)g->priv; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g); + + // Fill in the private area + priv->hwnd = hWnd; + dc = GetDC(hWnd); + priv->dcBitmap = CreateCompatibleBitmap(dc, g->g.Width, g->g.Height); + priv->dcBuffer = CreateCompatibleDC(dc); + ReleaseDC(hWnd, dc); + priv->dcOldBitmap = SelectObject(priv->dcBuffer, priv->dcBitmap); + + // Mark the window as ready to go + g->flags |= GDISP_FLG_READY; break; - case WM_LBUTTONDOWN: - #if GINPUT_NEED_MOUSE - if ((coord_t)HIWORD(lParam) < wHeight) { - mousebuttons |= GINPUT_MOUSE_BTN_LEFT; - goto mousemove; - } - #endif - #if GINPUT_NEED_TOGGLE - bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth); - toggles ^= bit; - rect.left = 0; - rect.right = wWidth; - rect.top = wHeight; - rect.bottom = wHeight + WIN32_BUTTON_AREA; - InvalidateRect(hWnd, &rect, FALSE); - UpdateWindow(hWnd); - #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE - ginputToggleWakeup(); + + #if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE + case WM_LBUTTONDOWN: + // Get our GDisplay structure + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + + // Handle mouse down on the window + #if GINPUT_NEED_MOUSE + if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) { + priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT; + goto mousemove; + } #endif - #endif - break; - case WM_LBUTTONUP: - #if GINPUT_NEED_TOGGLE - if ((toggles & 0x0F)) { - toggles &= ~0x0F; - rect.left = 0; - rect.right = wWidth; - rect.top = wHeight; - rect.bottom = wHeight + WIN32_BUTTON_AREA; - InvalidateRect(hWnd, &rect, FALSE); - UpdateWindow(hWnd); - #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE - ginputToggleWakeup(); - #endif - } - #endif - #if GINPUT_NEED_MOUSE - if ((coord_t)HIWORD(lParam) < wHeight) { - mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; + + // Handle mouse down on the toggle area + #if GINPUT_NEED_TOGGLE + if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) { + bit = 1 << ((coord_t)LOWORD(lParam)*8/g->g.Width); + priv->toggles ^= bit; + rect.left = 0; + rect.right = GDISP_SCREEN_WIDTH; + rect.top = GDISP_SCREEN_HEIGHT; + rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA; + InvalidateRect(hWnd, &rect, FALSE); + UpdateWindow(hWnd); + #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE + ginputToggleWakeup(); + #endif + } + #endif + break; + + case WM_LBUTTONUP: + // Get our GDisplay structure + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + + // Handle mouse up on the toggle area + #if GINPUT_NEED_TOGGLE + if ((g->flags & GDISP_FLG_HASTOGGLE)) { + if ((priv->toggles & 0x0F)) { + priv->toggles &= ~0x0F; + rect.left = 0; + rect.right = GDISP_SCREEN_WIDTH; + rect.top = GDISP_SCREEN_HEIGHT; + rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA; + InvalidateRect(hWnd, &rect, FALSE); + UpdateWindow(hWnd); + #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE + ginputToggleWakeup(); + #endif + } + } + #endif + + // Handle mouse up on the window + #if GINPUT_NEED_MOUSE + if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) { + priv->mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; + goto mousemove; + } + #endif + break; + #endif + + #if GINPUT_NEED_MOUSE + case WM_MBUTTONDOWN: + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) { + priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; goto mousemove; } - #endif - break; -#if GINPUT_NEED_MOUSE - case WM_MBUTTONDOWN: - if ((coord_t)HIWORD(lParam) < wHeight) { - mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; - goto mousemove; - } - break; - case WM_MBUTTONUP: - if ((coord_t)HIWORD(lParam) < wHeight) { - mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; - goto mousemove; - } - break; - case WM_RBUTTONDOWN: - if ((coord_t)HIWORD(lParam) < wHeight) { - mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; - goto mousemove; - } - break; - case WM_RBUTTONUP: - if ((coord_t)HIWORD(lParam) < wHeight) { - mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; - goto mousemove; - } - break; - case WM_MOUSEMOVE: - if ((coord_t)HIWORD(lParam) >= wHeight) break; - mousemove: - mousex = (coord_t)LOWORD(lParam); - mousey = (coord_t)HIWORD(lParam); - #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE - ginputMouseWakeup(); - #endif - break; -#endif + case WM_MBUTTONUP: + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) { + priv->mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; + goto mousemove; + } + break; + case WM_RBUTTONDOWN: + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) { + priv->mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; + goto mousemove; + } + break; + case WM_RBUTTONUP: + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) { + priv->mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; + goto mousemove; + } + break; + case WM_MOUSEMOVE: + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT || !(g->flags & GDISP_FLG_HASMOUSE)) + break; + mousemove: + priv->mousex = (coord_t)LOWORD(lParam); + priv->mousey = (coord_t)HIWORD(lParam); + #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE + ginputMouseWakeup(); + #endif + break; + #endif + case WM_SYSKEYDOWN: case WM_KEYDOWN: case WM_SYSKEYUP: @@ -178,26 +255,41 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) case WM_SYSCHAR: case WM_SYSDEADCHAR: break; + + case WM_ERASEBKGND: + // Pretend we have erased the background. + // We know we don't really need to do this as we + // redraw the entire surface in the WM_PAINT handler. + return TRUE; + case WM_PAINT: + // Get our GDisplay structure + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + + // Paint the main window area + WaitForSingleObject(drawMutex, INFINITE); dc = BeginPaint(hWnd, &ps); BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, - (ps.rcPaint.bottom > wHeight ? wHeight : ps.rcPaint.bottom) - ps.rcPaint.top, - dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); + (ps.rcPaint.bottom > GDISP_SCREEN_HEIGHT ? GDISP_SCREEN_HEIGHT : ps.rcPaint.bottom) - ps.rcPaint.top, + priv->dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); + + // Paint the toggle area #if GINPUT_NEED_TOGGLE - if (ps.rcPaint.bottom >= wHeight) { + if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) { pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black)); hbrOn = CreateSolidBrush(COLOR2BGR(Blue)); hbrOff = CreateSolidBrush(COLOR2BGR(Gray)); old = SelectObject(dc, pen); - MoveToEx(dc, 0, wHeight, &p); - LineTo(dc, wWidth, wHeight); + MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p); + LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT); for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) { rect.left = pos; - rect.right = pos + wWidth/8; - rect.top = wHeight; - rect.bottom = wHeight + WIN32_BUTTON_AREA; - FillRect(dc, &rect, (toggles & bit) ? hbrOn : hbrOff); + rect.right = pos + GDISP_SCREEN_WIDTH/8; + rect.top = GDISP_SCREEN_HEIGHT; + rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA; + FillRect(dc, &rect, (priv->toggles & bit) ? hbrOn : hbrOff); if (pos > 0) { MoveToEx(dc, rect.left, rect.top, &p); LineTo(dc, rect.left, rect.bottom); @@ -209,74 +301,75 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) } #endif EndPaint(hWnd, &ps); + ReleaseMutex(drawMutex); break; + case WM_DESTROY: + // Get our GDisplay structure + g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + priv = (winPriv *)g->priv; + + // Restore the window and free our bitmaps + SelectObject(priv->dcBuffer, priv->dcOldBitmap); + DeleteDC(priv->dcBuffer); + DeleteObject(priv->dcBitmap); + + // Cleanup the private area + gfxFree(priv); + + // Quit the application PostQuitMessage(0); - SelectObject(dcBuffer, dcOldBitmap); - DeleteDC(dcBuffer); - DeleteObject(dcBitmap); - winRootWindow = NULL; + + // Actually the above doesn't work (who knows why) + ExitProcess(0); break; + default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; } -static void InitWindow(void) { - HANDLE hInstance; - WNDCLASS wc; - RECT rect; - HDC dc; - - hInstance = GetModuleHandle(NULL); - - wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC; - wc.lpfnWndProc = (WNDPROC)myWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = GetStockObject(WHITE_BRUSH); - wc.lpszMenuName = NULL; - wc.lpszClassName = APP_NAME; - RegisterClass(&wc); - - rect.top = 0; rect.bottom = wHeight+WIN32_BUTTON_AREA; - rect.left = 0; rect.right = wWidth; - AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0); - winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0, - rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL); - assert(winRootWindow != NULL); - - - GetClientRect(winRootWindow, &rect); - wWidth = rect.right-rect.left; - wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA; - - dc = GetDC(winRootWindow); - dcBitmap = CreateCompatibleBitmap(dc, wWidth, wHeight); - dcBuffer = CreateCompatibleDC(dc); - ReleaseDC(winRootWindow, dc); - dcOldBitmap = SelectObject(dcBuffer, dcBitmap); - - ShowWindow(winRootWindow, SW_SHOW); - UpdateWindow(winRootWindow); - isReady = TRUE; -} - static DECLARE_THREAD_STACK(waWindowThread, 1024); static DECLARE_THREAD_FUNCTION(WindowThread, param) { (void)param; MSG msg; - InitWindow(); + // Establish this thread as a message queue thread + winThreadId = GetCurrentThreadId(); + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + QReady = TRUE; + do { gfxSleepMilliseconds(1); while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + // Is this our special thread message to create a new window? + if (!msg.hwnd && msg.message == WM_USER) { + RECT rect; + GDisplay *g; + + g = (GDisplay *)msg.lParam; + + // Set the window rectangle + rect.top = 0; rect.bottom = g->g.Height; + rect.left = 0; rect.right = g->g.Width; + #if GINPUT_NEED_TOGGLE + if ((g->flags & GDISP_FLG_HASTOGGLE)) + rect.bottom += WIN32_BUTTON_AREA; + #endif + AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0); + + // Create the window + msg.hwnd = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_BORDER, msg.wParam*DISPLAY_X_OFFSET, msg.wParam*DISPLAY_Y_OFFSET, + rect.right-rect.left, rect.bottom-rect.top, 0, 0, + GetModuleHandle(NULL), g); + assert(msg.hwnd != NULL); + + // Or just a normal window message + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } } while (msg.message != WM_QUIT); ExitProcess(0); @@ -287,44 +380,89 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) { /* Driver exported functions. */ /*===========================================================================*/ -LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { - RECT rect; - gfxThreadHandle hth; +LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) { + winPriv * priv; + char buf[132]; - /* Set the window dimensions */ - GetWindowRect(GetDesktopWindow(), &rect); - wWidth = rect.right - rect.left; - wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA; - if (wWidth > GDISP_SCREEN_WIDTH) - wWidth = GDISP_SCREEN_WIDTH; - if (wHeight > GDISP_SCREEN_HEIGHT) - wHeight = GDISP_SCREEN_HEIGHT; + // Initialise the window thread and the window class (if it hasn't been done already) + if (!QReady) { + gfxThreadHandle hth; + WNDCLASS wc; - /* Initialise the window */ - if (!(hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0))) { - fprintf(stderr, "Cannot create window thread\n"); - exit(-1); + // Create the draw mutex + drawMutex = CreateMutex(NULL, FALSE, NULL); + + // Create the thread + hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0); + assert(hth != NULL); + gfxThreadClose(hth); + + wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)myWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = APP_NAME; + winClass = RegisterClass(&wc); + assert(winClass != 0); + + // Wait for our thread to be ready + while (!QReady) + Sleep(1); } - gfxThreadClose(hth); - while (!isReady) - Sleep(1); - /* Initialise the GDISP structure to match */ + // Initialise the GDISP structure 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; + g->g.Width = GDISP_SCREEN_WIDTH; + g->g.Height = GDISP_SCREEN_HEIGHT; + + // Turn on toggles for the first GINPUT_TOGGLE_CONFIG_ENTRIES windows + #if GINPUT_NEED_TOGGLE + if (display < GINPUT_TOGGLE_CONFIG_ENTRIES) + g->flags |= GDISP_FLG_HASTOGGLE; + #endif + + // Only turn on mouse on the first window for now + #if GINPUT_NEED_MOUSE + if (!display) + g->flags |= GDISP_FLG_HASMOUSE; + #endif + + // Create a private area for this window + priv = (winPriv *)gfxAlloc(sizeof(winPriv)); + assert(priv != NULL); + memset(priv, 0, sizeof(winPriv)); + g->priv = priv; + + // Create the window in the message thread + PostThreadMessage(winThreadId, WM_USER, (WPARAM)display, (LPARAM)g); + + // Wait for the window creation to complete (for safety) + while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY)) + Sleep(1); + + sprintf(buf, APP_NAME " - %u", display+1); + SetWindowText(priv->hwnd, buf); + ShowWindow(priv->hwnd, SW_SHOW); + UpdateWindow(priv->hwnd); + return TRUE; } #if GDISP_HARDWARE_DRAWPIXEL - LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) { - HDC dcScreen; + LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { + winPriv * priv; int x, y; COLORREF color; + priv = g->priv; color = COLOR2BGR(g->p.color); #if GDISP_NEED_CONTROL @@ -352,23 +490,41 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { #endif // Draw the pixel on the screen and in the buffer. - dcScreen = GetDC(winRootWindow); - SetPixel(dcScreen, x, y, color); - SetPixel(dcBuffer, x, y, color); - ReleaseDC(winRootWindow, dcScreen); + WaitForSingleObject(drawMutex, INFINITE); + SetPixel(priv->dcBuffer, x, y, color); + #if GDISP_WIN32_USE_INDIRECT_UPDATE + ReleaseMutex(drawMutex); + { + RECT r; + r.left = g->p.x; r.right = g->p.x+1; + r.top = g->p.y; r.bottom = g->p.y+1; + InvalidateRect(priv->hwnd, &r, FALSE); + } + #else + { + HDC dc; + dc = GetDC(priv->hwnd); + SetPixel(dc, x, y, color); + ReleaseDC(priv->hwnd, dc); + ReleaseMutex(drawMutex); + } + #endif } #endif /* ---- Optional Routines ---- */ #if GDISP_HARDWARE_FILLS - LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) { - HDC dcScreen; + LLDSPEC void gdisp_lld_fill_area(GDisplay *g) { + winPriv * priv; RECT rect; HBRUSH hbr; COLORREF color; + priv = g->priv; color = COLOR2BGR(g->p.color); + hbr = CreateSolidBrush(color); + #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: @@ -403,29 +559,34 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { rect.right = rect.left + g->p.cx; #endif - hbr = CreateSolidBrush(color); - dcScreen = GetDC(winRootWindow); - FillRect(dcScreen, &rect, hbr); - FillRect(dcBuffer, &rect, hbr); - ReleaseDC(winRootWindow, dcScreen); + WaitForSingleObject(drawMutex, INFINITE); + FillRect(priv->dcBuffer, &rect, hbr); + #if GDISP_WIN32_USE_INDIRECT_UPDATE + ReleaseMutex(drawMutex); + InvalidateRect(priv->hwnd, &rect, FALSE); + #else + { + HDC dc; + dc = GetDC(priv->hwnd); + FillRect(dc, &rect, hbr); + ReleaseDC(priv->hwnd, dc); + ReleaseMutex(drawMutex); + } + #endif DeleteObject(hbr); } #endif #if GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL - static pixel_t *rotateimg(GDISPDriver *g, const pixel_t *buffer) { + static pixel_t *rotateimg(GDisplay *g, const pixel_t *buffer) { pixel_t *dstbuf; pixel_t *dst; const pixel_t *src; size_t sz; coord_t i, j; - // Shortcut. - if (g->g.Orientation == GDISP_ROTATE_0 && g->p.x1 == 0 && g->p.cx == g->p.x2) - return (pixel_t *)buffer; - // Allocate the destination buffer sz = (size_t)g->p.cx * (size_t)g->p.cy; if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t)))) @@ -433,11 +594,6 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { // Copy the bits we need switch(g->g.Orientation) { - case GDISP_ROTATE_0: - for(dst = dstbuf, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) - for(i = 0; i < g->p.cx; i++) - *dst++ = *src++; - break; case GDISP_ROTATE_90: for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) { dst = dstbuf+sz-g->p.cy+j; @@ -463,16 +619,14 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { #endif #if GDISP_HARDWARE_BITFILLS - LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) { - BITMAPV4HEADER bmpInfo; - HDC dcScreen; - pixel_t * buffer; - #if GDISP_NEED_CONTROL - RECT rect; - pixel_t * srcimg; - #endif + LLDSPEC void gdisp_lld_blit_area(GDisplay *g) { + winPriv * priv; + pixel_t * buffer; + RECT rect; + BITMAPV4HEADER bmpInfo; // Make everything relative to the start of the line + priv = g->priv; buffer = g->p.ptr; buffer += g->p.x2*g->p.y1; @@ -492,13 +646,10 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { bmpInfo.bV4CSType = 0; //LCS_sRGB; #if GDISP_NEED_CONTROL - bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t); - srcimg = rotateimg(g, buffer); - if (!srcimg) return; - switch(g->g.Orientation) { case GDISP_ROTATE_0: - bmpInfo.bV4Width = g->p.cx; + bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t); + bmpInfo.bV4Width = g->p.x2; bmpInfo.bV4Height = -g->p.cy; /* top-down image */ rect.top = g->p.y; rect.bottom = rect.top+g->p.cy; @@ -506,6 +657,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { rect.right = rect.left+g->p.cx; break; case GDISP_ROTATE_90: + if (!(buffer = rotateimg(g, buffer))) return; + bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t); bmpInfo.bV4Width = g->p.cy; bmpInfo.bV4Height = -g->p.cx; /* top-down image */ rect.bottom = g->g.Width - g->p.x; @@ -514,6 +667,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { rect.right = rect.left+g->p.cy; break; case GDISP_ROTATE_180: + if (!(buffer = rotateimg(g, buffer))) return; + bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t); bmpInfo.bV4Width = g->p.cx; bmpInfo.bV4Height = -g->p.cy; /* top-down image */ rect.bottom = g->g.Height-1 - g->p.y; @@ -522,6 +677,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { rect.left = rect.right-g->p.cx; break; case GDISP_ROTATE_270: + if (!(buffer = rotateimg(g, buffer))) return; + bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t); bmpInfo.bV4Width = g->p.cy; bmpInfo.bV4Height = -g->p.cx; /* top-down image */ rect.top = g->p.x; @@ -530,58 +687,78 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { rect.left = rect.right-g->p.cy; break; } - dcScreen = GetDC(winRootWindow); - SetDIBitsToDevice(dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); - SetDIBitsToDevice(dcScreen, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); - ReleaseDC(winRootWindow, dcScreen); - if (srcimg != buffer) - free(srcimg); - #else + bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t); bmpInfo.bV4Width = g->p.x2; bmpInfo.bV4Height = -g->p.cy; /* top-down image */ - bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t); - dcScreen = GetDC(winRootWindow); - SetDIBitsToDevice(dcBuffer, g->p.x, g->p.y, g->p.cx, g->p.cy, g->p.x1, 0, 0, g->p.cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); - SetDIBitsToDevice(dcScreen, g->p.x, g->p.y, g->p.cx, g->p.cy, g->p.x1, 0, 0, g->p.cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); - ReleaseDC(winRootWindow, dcScreen); + 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 + + WaitForSingleObject(drawMutex, INFINITE); + SetDIBitsToDevice(priv->dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); + #if GDISP_WIN32_USE_INDIRECT_UPDATE + ReleaseMutex(drawMutex); + InvalidateRect(priv->hwnd, &rect, FALSE); + #else + { + HDC dc; + dc = GetDC(priv->hwnd); + SetDIBitsToDevice(dc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); + ReleaseDC(priv->hwnd, dc); + ReleaseMutex(drawMutex); + } + #endif + + #if GDISP_NEED_CONTROL + if (buffer != (pixel_t *)g->p.ptr) + free(srcimg); #endif } #endif #if GDISP_HARDWARE_PIXELREAD - LLDSPEC color_t gdisp_lld_get_pixel_color(GDISPDriver *g) { + LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { + winPriv * priv; COLORREF color; + priv = g->priv; + + WaitForSingleObject(drawMutex, INFINITE); #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: - color = GetPixel(dcBuffer, g->p.x, g->p.y); + color = GetPixel(priv->dcBuffer, g->p.x, g->p.y); break; case GDISP_ROTATE_90: - color = GetPixel(dcBuffer, g->p.y, g->g.Width - 1 - g->p.x); + color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x); break; case GDISP_ROTATE_180: - color = GetPixel(dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y); + color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y); break; case GDISP_ROTATE_270: - color = GetPixel(dcBuffer, g->g.Height - 1 - g->p.y, g->p.x); + color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x); break; } #else - color = GetPixel(dcBuffer, g->p.x, g->p.y); + color = GetPixel(priv->dcBuffer, g->p.x, g->p.y); #endif + ReleaseMutex(drawMutex); return BGR2COLOR(color); } #endif #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL - LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) { - HDC dcScreen; + LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) { + winPriv * priv; RECT rect; coord_t lines; + priv = g->priv; + #if GDISP_NEED_CONTROL switch(GC->g.Orientation) { case GDISP_ROTATE_0: @@ -611,10 +788,20 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { 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); + WaitForSingleObject(drawMutex, INFINITE); + ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0); + #if GDISP_WIN32_USE_INDIRECT_UPDATE + ReleaseMutex(drawMutex); + InvalidateRect(priv->hwnd, &rect, FALSE); + #else + { + HDC dc; + dc = GetDC(priv->hwnd); + ScrollDC(dc, 0, lines, &rect, 0, 0, 0); + ReleaseDC(priv->hwnd, dc); + ReleaseMutex(drawMutex); + } + #endif } break; case GDISP_ROTATE_270: @@ -630,10 +817,20 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { 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); + WaitForSingleObject(drawMutex, INFINITE); + ScrollDC(priv->dcBuffer, lines, 0, &rect, 0, 0, 0); + #if GDISP_WIN32_USE_INDIRECT_UPDATE + ReleaseMutex(drawMutex); + InvalidateRect(priv->hwnd, &rect, FALSE); + #else + { + HDC dc; + dc = GetDC(priv->hwnd); + ScrollDC(dc, lines, 0, &rect, 0, 0, 0); + ReleaseDC(priv->hwnd, dc); + ReleaseMutex(drawMutex); + } + #endif } break; } @@ -649,17 +846,27 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { 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); + WaitForSingleObject(drawMutex, INFINITE); + ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0); + #if GDISP_WIN32_USE_INDIRECT_UPDATE + ReleaseMutex(drawMutex); + InvalidateRect(priv->hwnd, &rect, FALSE); + #else + { + HDC dc; + dc = GetDC(priv->hwnd); + ScrollDC(dc, 0, lines, &rect, 0, 0, 0); + ReleaseDC(priv->hwnd, dc); + ReleaseMutex(drawMutex); + } + #endif } #endif } #endif #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL - LLDSPEC void gdisp_lld_control(GDISPDriver *g) { + LLDSPEC void gdisp_lld_control(GDisplay *g) { switch(g->p.x) { case GDISP_CONTROL_ORIENTATION: if (g->g.Orientation == (orientation_t)g->p.ptr) @@ -667,13 +874,13 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { switch((orientation_t)g->p.ptr) { case GDISP_ROTATE_0: case GDISP_ROTATE_180: - g->g.Width = wWidth; - g->g.Height = wHeight; + g->g.Width = GDISP_SCREEN_WIDTH; + g->g.Height = GDISP_SCREEN_HEIGHT; break; case GDISP_ROTATE_90: case GDISP_ROTATE_270: - g->g.Height = wWidth; - g->g.Width = wHeight; + g->g.Height = GDISP_SCREEN_WIDTH; + g->g.Width = GDISP_SCREEN_HEIGHT; break; default: return; @@ -692,20 +899,38 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { #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; + GDisplay *g; + + g = GDISP_WIN32; + pt->x = g->priv->mousex; + pt->y = g->priv->mousey > g->g.Height ? g->g.Height : mousey; + pt->z = (g->priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0; + pt->buttons = g->priv->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 */ + #if GINPUT_TOGGLE_CONFIG_ENTRIES > GDISP_DRIVER_COUNT_WIN32 + #error "GDISP Win32: GINPUT_TOGGLE_CONFIG_ENTRIES must not be greater than GDISP_DRIVER_COUNT_WIN32" + #endif + + GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES]; + + void ginput_lld_toggle_init(const GToggleConfig *ptc) { + // Save the associated window struct + ptc->id = &GDISP_WIN32[ptc - GInputToggleConfigTable]; + + // We have 8 buttons per window. + ptc->mask = 0xFF; + + // No inverse or special mode + ptc->invert = 0x00; + ptc->mode = 0; + } + unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { + return ((GDisplay *)(ptc->id))->priv->toggles; + } +#endif /* GINPUT_NEED_TOGGLE */ #endif /* GFX_USE_GDISP */ diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h index b8a030ef..5720eaed 100644 --- a/drivers/multiple/Win32/gdisp_lld_config.h +++ b/drivers/multiple/Win32/gdisp_lld_config.h @@ -16,15 +16,12 @@ #ifndef _GDISP_LLD_CONFIG_H #define _GDISP_LLD_CONFIG_H -#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ +#if GFX_USE_GDISP /*===========================================================================*/ /* Driver hardware support. */ /*===========================================================================*/ -#define GDISP_DRIVER_NAME "Win32" -#define GDISP_DRIVER_STRUCT GDISP_Win32 - #define GDISP_HARDWARE_DRAWPIXEL TRUE #define GDISP_HARDWARE_FILLS TRUE #define GDISP_HARDWARE_PIXELREAD TRUE @@ -32,7 +29,7 @@ #define GDISP_HARDWARE_BITFILLS TRUE #define GDISP_HARDWARE_SCROLL TRUE -#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 +#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 #endif /* GFX_USE_GDISP */ diff --git a/drivers/multiple/Win32/ginput_lld_toggle_config.h b/drivers/multiple/Win32/ginput_lld_toggle_config.h index 2e61d073..dd0c9b5c 100644 --- a/drivers/multiple/Win32/ginput_lld_toggle_config.h +++ b/drivers/multiple/Win32/ginput_lld_toggle_config.h @@ -20,9 +20,16 @@ #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE -#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - ether works here) -#define GINPUT_TOGGLE_NUM_PORTS 8 // The total number of toggle inputs -#define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries +#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - either works here) + +// This driver is unique in that it can support 8 buttons per window across multiple windows. +// GINPUT_TOGGLE_CONFIG_ENTRIES just must be less than the number of GDISP windows (GDISP_DRIVER_COUNT_WIN32). +#ifndef GINPUT_TOGGLE_CONFIG_ENTRIES + #define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries +#endif + +// The total number of toggle inputs +#define GINPUT_TOGGLE_NUM_PORTS (8 * GINPUT_TOGGLE_CONFIG_ENTRIES) #define GINPUT_TOGGLE_SW1 0 // Switch 1 - Toggle #define GINPUT_TOGGLE_SW2 1 // Switch 2 - Toggle @@ -33,6 +40,8 @@ #define GINPUT_TOGGLE_MOMENTARY2 5 // Switch 6 - Momentary #define GINPUT_TOGGLE_MOMENTARY3 6 // Switch 7 - Momentary #define GINPUT_TOGGLE_MOMENTARY4 7 // Switch 8 - Momentary + +// This pattern of switch and momentary action is repeated across all windows. #endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */ diff --git a/drivers/multiple/X/gdisp_lld_config.h b/drivers/multiple/X/gdisp_lld_config.h index 0bd76a2c..7c04b1b9 100644 --- a/drivers/multiple/X/gdisp_lld_config.h +++ b/drivers/multiple/X/gdisp_lld_config.h @@ -22,7 +22,12 @@ /* Driver hardware support. */ /*===========================================================================*/ -#define GDISP_DRIVER_NAME "Linux emulator - X11" +#ifndef GDISP_DRIVER_COUNT_X11 + #define GDISP_DRIVER_COUNT_X11 1 +#endif +#define GDISP_DRIVER_COUNT GDISP_DRIVER_COUNT_X11 + +#define GDISP_DRIVER_NAME "Linux emulator - X11" #define GDISP_DRIVER_STRUCT GDISP_X11 #define GDISP_HARDWARE_DRAWPIXEL TRUE @@ -32,7 +37,7 @@ #define GDISP_HARDWARE_PIXELREAD TRUE #define GDISP_HARDWARE_CONTROL FALSE -#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 +#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 #endif /* GFX_USE_GDISP */ diff --git a/gfxconf.example.h b/gfxconf.example.h index e6be90db..f3a1e165 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -141,6 +141,29 @@ #define GMISC_NEED_FIXEDTRIG FALSE #define GMISC_NEED_INVSQRT FALSE +/* Optional Multiple Display support */ +/* + #define GDISP_TOTAL_DISPLAYS 1 + #define GDISP_TOTAL_CONTROLLERS 1 + + // Extra stuff needed for when GDISP_TOTAL_CONTROLLERS > 1 + #define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_Win32 + #define GDISP_CONTROLLER_DISPLAYS 1, 1 + #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 + #define GDISP_HARDWARE_STREAM_WRITE FALSE + #define GDISP_HARDWARE_STREAM_READ FALSE + #define GDISP_HARDWARE_STREAM_POS FALSE + #define GDISP_HARDWARE_DRAWPIXEL FALSE + #define GDISP_HARDWARE_CLEARS FALSE + #define GDISP_HARDWARE_FILLS FALSE + #define GDISP_HARDWARE_BITFILLS FALSE + #define GDISP_HARDWARE_SCROLL FALSE + #define GDISP_HARDWARE_PIXELREAD FALSE + #define GDISP_HARDWARE_CONTROL FALSE + #define GDISP_HARDWARE_QUERY FALSE + #define GDISP_HARDWARE_CLIP FALSE +*/ + /* Optional Parameters for various subsystems */ /* #define GDISP_LINEBUF_SIZE 128 diff --git a/include/gdisp/gdisp.h b/include/gdisp/gdisp.h index 6b2f5b47..7f0f8012 100644 --- a/include/gdisp/gdisp.h +++ b/include/gdisp/gdisp.h @@ -17,6 +17,10 @@ * * @pre GFX_USE_GDISP must be set to TRUE in gfxconf.h * + * @note Each drawing routine supports a gispXXXX and a gdispGXXXX function. The difference is that the + * gdispXXXX function does not require a display to be specified. Note there is a slight anomoly + * in the naming with gdispGBlitArea() vs gdispBlitAreaEx() and gdispBlitArea(), the later of + * which is now deprecated. * @{ */ @@ -79,7 +83,18 @@ typedef struct GDISPControl { uint8_t Contrast; } GDISPControl; -extern GDISPControl *GDISP; +/* + * Our black box display structure. We know only one thing about it... + * The first member is a GDISPControl structure. + */ +typedef struct GDisplay GDisplay; + +/** + * @brief The default screen to use for the gdispXXXX calls. + * @note This is set by default to the first display in the system. You can change + * it by calling @p gdispGSetDisplay(). + */ +extern GDisplay *GDISP; /*===========================================================================*/ /* Constants. */ @@ -150,75 +165,69 @@ 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 +#if !defined(GDISP_TOTAL_CONTROLLERS) || GDISP_TOTAL_CONTROLLERS == 1 + // Pull in the default hardware configuration for a single controller. + // If we have multiple controllers the settings must be set in the + // users gfxconf.h file. #include "gdisp_lld_config.h" +#endif + +/** + * @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_TOTAL_CONTROLLERS > 1, 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_LLD_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 -#endif +/** @} */ /*===========================================================================*/ /* Defines related to the pixel format */ @@ -356,48 +365,68 @@ extern "C" { */ color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha); +/** + * @brief Set the current default display to the specified display + * @note The default display is used for the gdispXxxx functions. + * @note Displays are numbered from 0 to GDISP_TOTAL_DISPLAYS - 1 + * @note If an invalid display number is specified the request is ignored. + * + * @param[in] display The display number (0..n) + * + * @api + */ +void gdispSetDisplay(unsigned display); + /* Drawing Functions */ /** * @brief Clear the display to the specified color. * + * @param[in] g The display to use * @param[in] color The color to use when clearing the screen * * @api */ -void gdispClear(color_t color); +void gdispGClear(GDisplay *g, color_t color); +#define gdispClear(c) gdispGClear(GDISP, c) /** * @brief Set a pixel in the specified color. * + * @param[in] g The display to use * @param[in] x,y The position to set the pixel. * @param[in] color The color to use * * @api */ -void gdispDrawPixel(coord_t x, coord_t y, color_t color); +void gdispGDrawPixel(GDisplay *g, coord_t x, coord_t y, color_t color); +#define gdispDrawPixel(x,y,c) gdispGDrawPixel(GDISP,x,y,c) /** * @brief Draw a line. * + * @param[in] g The display to use * @param[in] x0,y0 The start position * @param[in] x1,y1 The end position * @param[in] color The color to use * * @api */ -void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); +void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); +#define gdispDrawLine(x0,y0,x1,y1,c) gdispGDrawLine(GDISP,x0,y0,x1,y1,c) /** * @brief Fill an area with a color. * + * @param[in] g The display to use * @param[in] x,y The start position * @param[in] cx,cy The size of the box (outside dimensions) * @param[in] color The color to use * * @api */ -void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); +void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); +#define gdispFillArea(x,y,cx,cy,c) gdispGFillArea(GDISP,x,y,cx,cy,c) /** * @brief Fill an area using the supplied bitmap. @@ -409,6 +438,7 @@ void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * or at least retained until this call has finished the blit. You can * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE. * + * @param[in] g The display to use * @param[in] x,y The start position * @param[in] cx,cy The size of the filled area * @param[in] srcx,srcy The bitmap position to start the fill form @@ -417,18 +447,21 @@ void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ -void gdispBlitAreaEx(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 gdispGBlitArea(GDisplay *g, 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); +#define gdispBlitAreaEx(x,y,cx,cy,sx,sy,rx,b) gdispGBlitArea(GDISP,x,y,cx,cy,sx,sy,rx,b) /** * @brief Draw a rectangular box. * + * @param[in] g The display to use * @param[in] x,y The start position * @param[in] cx,cy The size of the box (outside dimensions) * @param[in] color The color to use * * @api */ -void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); +void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); +#define gdispDrawBox(x,y,cx,cy,c) gdispGDrawBox(GDISP,x,y,cx,cy,c) /* Streaming Functions */ @@ -450,12 +483,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @note A streaming operation may be terminated early (without writing to every location * in the stream area) by calling @p gdispStreamStop(). * + * @param[in] g The display to use * @param[in] x,y The start position * @param[in] cx,cy The size of the streamable area * * @api */ - void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy); + void gdispGStreamStart(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy); + #define gdispStreamStart(x,y,cx,cy) gdispGStreamStart(GDISP,x,y,cx,cy) /** * @brief Send pixel data to the stream. @@ -464,11 +499,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @note If the gdispStreamStart() has not been called (or failed due to clipping), the * data provided here is simply thrown away. * + * @param[in] g The display to use * @param[in] color The color of the pixel to write * * @api */ - void gdispStreamColor(color_t color); + void gdispGStreamColor(GDisplay *g, color_t color); + #define gdispStreamColor(c) gdispGStreamColor(GDISP,c) /** * @brief Finish the current streaming operation. @@ -477,9 +514,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @note If the gdispStreamStart() has not been called (or failed due to clipping), this * call is simply ignored. * + * @param[in] g The display to use + * * @api */ - void gdispStreamStop(void); + void gdispGStreamStop(GDisplay *g); + #define gdispStreamStop() gdispGStreamStop(GDISP) #endif /* Clipping Functions */ @@ -488,12 +528,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); /** * @brief Clip all drawing to the defined area. * - * @param[in] x,y The start position - * @param[in] cx,cy The size of the clip area + * @param[in] g The display to use + * @param[in] x,y The start position + * @param[in] cx,cy The size of the clip area * * @api */ - void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy); + void gdispGSetClip(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy); + #define gdispSetClip(x,y,cx,cy) gdispGSetClip(GDISP,x,y,cx,cy) #endif /* Circle Functions */ @@ -502,24 +544,28 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); /** * @brief Draw a circle. * + * @param[in] g The display to use * @param[in] x,y The center of the circle * @param[in] radius The radius of the circle * @param[in] color The color to use * * @api */ - void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color); + void gdispGDrawCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color); + #define gdispDrawCircle(x,y,r,c) gdispGDrawCircle(GDISP,x,y,r,c) /** * @brief Draw a filled circle. * + * @param[in] g The display to use * @param[in] x,y The center of the circle * @param[in] radius The radius of the circle * @param[in] color The color to use * * @api */ - void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color); + void gdispGFillCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color); + #define gdispFillCircle(x,y,r,c) gdispGFillCircle(GDISP,x,y,r,c) #endif /* Ellipse Functions */ @@ -528,24 +574,28 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); /** * @brief Draw an ellipse. * - * @param[in] x,y The center of the ellipse - * @param[in] a,b The dimensions of the ellipse - * @param[in] color The color to use + * @param[in] g The display to use + * @param[in] x,y The center of the ellipse + * @param[in] a,b The dimensions of the ellipse + * @param[in] color The color to use * * @api */ - void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); + void gdispGDrawEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color); + #define gdispDrawEllipse(x,y,a,b,c) gdispGDrawEllipse(GDISP,x,y,a,b,c) /** * @brief Draw a filled ellipse. * - * @param[in] x,y The center of the ellipse - * @param[in] a,b The dimensions of the ellipse - * @param[in] color The color to use + * @param[in] g The display to use + * @param[in] x,y The center of the ellipse + * @param[in] a,b The dimensions of the ellipse + * @param[in] color The color to use * * @api */ - void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); + void gdispGFillEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color); + #define gdispFillEllipse(x,y,a,b,c) gdispGFillEllipse(GDISP,x,y,a,b,c) #endif /* Arc Functions */ @@ -554,6 +604,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); /* * @brief Draw an arc. * + * @param[in] g The display to use * @param[in] x0,y0 The center point * @param[in] radius The radius of the arc * @param[in] start The start angle (0 to 360) @@ -562,12 +613,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + void gdispGDrawArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + #define gdispDrawArc(x,y,r,s,e,c) gdispGDrawArc(GDISP,x,y,r,s,e,c) /* * @brief Draw a filled arc. * @note Not very efficient currently - does lots of overdrawing * + * @param[in] g The display to use * @param[in] x0,y0 The center point * @param[in] radius The radius of the arc * @param[in] start The start angle (0 to 360) @@ -576,7 +629,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + void gdispGFillArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + #define gdispFillArc(x,y,r,s,e,c) gdispGFillArc(GDISP,x,y,r,s,e,c) #endif /* Read a pixel Function */ @@ -586,11 +640,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @brief Get the color of a pixel. * @return The color of the pixel. * - * @param[in] x,y The position of the pixel + * @param[in] g The display to use + * @param[in] x,y The position of the pixel * * @api */ - color_t gdispGetPixelColor(coord_t x, coord_t y); + color_t gdispGGetPixelColor(GDisplay *g, coord_t x, coord_t y); + #define gdispGetPixelColor(x,y) gdispGGetPixelColor(GDISP,x,y) #endif /* Scrolling Function - clears the area scrolled out */ @@ -602,14 +658,16 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @note Optional. * @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. + * @param[in] g The display to use + * @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. * * @api */ - void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor); + void gdispGVerticalScroll(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor); + #define gdispVerticalScroll(x,y,cx,cy,l,b) gdispGVerticalScroll(GDISP,x,y,cx,cy,l,b) #endif /* Set driver specific control */ @@ -620,12 +678,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @note Depending on the hardware implementation this function may not * support some codes. They will be ignored. * + * @param[in] g The display to use * @param[in] what what you want to control * @param[in] value The value to be assigned * * @api */ - void gdispControl(unsigned what, void *value); + void gdispGControl(GDisplay *g, unsigned what, void *value); + #define gdispControl(w,v) gdispGControl(GDISP,w,v) #endif /* Query driver specific data */ @@ -636,17 +696,20 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @note The result must be typecast to the correct type. * @note An unsupported query will return (void *)-1. * + * @param[in] g The display to use * @param[in] what What to query * * @api */ - void *gdispQuery(unsigned what); + void *gdispGQuery(GDisplay *g, unsigned what); + #define gdispQuery(w) gdispGQuery(GDISP,w) #endif #if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__) /** * @brief Draw an enclosed polygon (convex, non-convex or complex). * + * @param[in] g The display to use * @param[in] tx, ty Transform all points in pntarray by tx, ty * @param[in] pntarray An array of points * @param[in] cnt The number of points in the array @@ -654,12 +717,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispDrawPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color); + void gdispGDrawPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color); + #define gdispDrawPoly(x,y,p,i,c) gdispGDrawPoly(GDISP,x,y,p,i,c) /** * @brief Fill a convex polygon * @details Doesn't handle non-convex or complex polygons. * + * @param[in] g The display to use * @param[in] tx, ty Transform all points in pntarray by tx, ty * @param[in] pntarray An array of points * @param[in] cnt The number of points in the array @@ -675,7 +740,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color); + void gdispGFillConvexPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color); + #define gdispFillConvexPoly(x,y,p,i,c) gdispGFillConvexPoly(GDISP,x,y,p,i,c) #endif /* Text Functions */ @@ -684,6 +750,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); /** * @brief Draw a text character. * + * @param[in] g The display to use * @param[in] x,y The position for the text * @param[in] c The character to draw * @param[in] font The font to use @@ -691,11 +758,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color); + void gdispGDrawChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color); + #define gdispDrawChar(x,y,s,f,c) gdispGDrawChar(GDISP,x,y,s,f,c) /** * @brief Draw a text character with a filled background. * + * @param[in] g The display to use * @param[in] x,y The position for the text * @param[in] c The character to draw * @param[in] font The font to use @@ -704,11 +773,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor); + void gdispGFillChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor); + #define gdispFillChar(x,y,s,f,c,b) gdispGFillChar(GDISP,x,y,s,f,c,b) /** * @brief Draw a text string. * + * @param[in] g The display to use * @param[in] x,y The position for the text * @param[in] font The font to use * @param[in] str The string to draw @@ -716,11 +787,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color); + void gdispGDrawString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color); + #define gdispDrawString(x,y,s,f,c) gdispGDrawString(GDISP,x,y,s,f,c) /** * @brief Draw a text string. * + * @param[in] g The display to use * @param[in] x,y The position for the text * @param[in] str The string to draw * @param[in] font The font to use @@ -729,11 +802,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor); + void gdispGFillString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor); + #define gdispFillString(x,y,s,f,c,b) gdispGFillString(GDISP,x,y,s,f,c,b) /** * @brief Draw a text string vertically centered within the specified box. * + * @param[in] g The display to use * @param[in] x,y The position for the text (need to define top-right or base-line - check code) * @param[in] cx,cy The width and height of the box * @param[in] str The string to draw @@ -743,12 +818,14 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify); + void gdispGDrawStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify); + #define gdispDrawStringBox(x,y,cx,cy,s,f,c,j) gdispGDrawStringBox(GDISP,x,y,cx,cy,s,f,c,j) /** * @brief Draw a text string vertically centered within the specified box. The box background is filled with the specified background color. * @note The entire box is filled * + * @param[in] g The display to use * @param[in] x,y The position for the text (need to define top-right or base-line - check code) * @param[in] cx,cy The width and height of the box * @param[in] str The string to draw @@ -759,7 +836,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgColor, justify_t justify); + void gdispGFillStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgColor, justify_t justify); + #define gdispFillStringBox(x,y,cx,cy,s,f,c,b,j) gdispGFillStringBox(GDISP,x,y,cx,cy,s,f,c,b,j) /** * @brief Get a metric of a font. @@ -844,6 +922,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); /** * @brief Draw a rectangular box with rounded corners * + * @param[in] g The display to use * @param[in] x,y The start position * @param[in] cx,cy The size of the box (outside dimensions) * @param[in] radius The radius of the rounded corners @@ -851,11 +930,13 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color); + void gdispGDrawRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color); + #define gdispDrawRoundedBox(x,y,cx,cy,r,c) gdispGDrawRoundedBox(GDISP,x,y,cx,cy,r,c) /** * @brief Draw a filled rectangular box with rounded corners * + * @param[in] g The display to use * @param[in] x,y The start position * @param[in] cx,cy The size of the box (outside dimensions) * @param[in] radius The radius of the rounded corners @@ -863,7 +944,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ - void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color); + void gdispGFillRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color); + #define gdispFillRoundedBox(x,y,cx,cy,r,c) gdispGFillRoundedBox(GDISP,x,y,cx,cy,r,c) #endif /* @@ -871,7 +953,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); */ /* Now obsolete functions */ -#define gdispBlitArea(x, y, cx, cy, buffer) gdispBlitAreaEx(x, y, cx, cy, 0, 0, cx, buffer) +#define gdispBlitArea(x, y, cx, cy, buffer) gdispGBlitArea(GDISP, x, y, cx, cy, 0, 0, cx, buffer) /* Macro definitions for common gets and sets */ @@ -879,26 +961,31 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * @brief Set the display power mode. * @note Ignored if not supported by the display. * + * @param[in] g The display to use * @param[in] powerMode The new power mode * * @api */ -#define gdispSetPowerMode(powerMode) gdispControl(GDISP_CONTROL_POWER, (void *)(unsigned)(powerMode)) +#define gdispGSetPowerMode(g, powerMode) gdispGControl((g), GDISP_CONTROL_POWER, (void *)(unsigned)(powerMode)) +#define gdispSetPowerMode(powerMode) gdispGControl(GDISP, GDISP_CONTROL_POWER, (void *)(unsigned)(powerMode)) /** * @brief Set the display orientation. * @note Ignored if not supported by the display. * + * @param[in] g The display to use * @param[in] newOrientation The new orientation * * @api */ -#define gdispSetOrientation(newOrientation) gdispControl(GDISP_CONTROL_ORIENTATION, (void *)(unsigned)(newOrientation)) +#define gdispGSetOrientation(g, newOrientation) gdispGControl((g), GDISP_CONTROL_ORIENTATION, (void *)(unsigned)(newOrientation)) +#define gdispSetOrientation(newOrientation) gdispGControl(GDISP, GDISP_CONTROL_ORIENTATION, (void *)(unsigned)(newOrientation)) /** * @brief Set the display backlight. * @note Ignored if not supported by the display. * + * @param[in] g The display to use * @param[in] percent The new brightness (0 - 100%) * * @note For displays that only support backlight off and on, @@ -906,68 +993,92 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); * * @api */ -#define gdispSetBacklight(percent) gdispControl(GDISP_CONTROL_BACKLIGHT, (void *)(unsigned)(percent)) +#define gdispGSetBacklight(g, percent) gdispGControl((g), GDISP_CONTROL_BACKLIGHT, (void *)(unsigned)(percent)) +#define gdispSetBacklight(percent) gdispGControl(GDISP, GDISP_CONTROL_BACKLIGHT, (void *)(unsigned)(percent)) /** * @brief Set the display contrast. * @note Ignored if not supported by the display. * + * @param[in] g The display to use * @param[in] percent The new contrast (0 - 100%) * * @api */ -#define gdispSetContrast(percent) gdispControl(GDISP_CONTROL_CONTRAST, (void *)(unsigned)(percent)) +#define gdispGSetContrast(g, percent) gdispGControl((g), GDISP_CONTROL_CONTRAST, (void *)(unsigned)(percent)) +#define gdispSetContrast(percent) gdispGControl(GDISP, GDISP_CONTROL_CONTRAST, (void *)(unsigned)(percent)) /** * @brief Get the display width in pixels. * + * @param[in] g The display to use + * * @api */ -#define gdispGetWidth() (GDISP->Width) +#define gdispGGetWidth(g) (((GDISPControl *)(g))->Width) +#define gdispGetWidth() gdispGGetWidth(GDISP) /** * @brief Get the display height in pixels. * + * @param[in] g The display to use + * * @api */ -#define gdispGetHeight() (GDISP->Height) +#define gdispGGetHeight(g) (((GDISPControl *)(g))->Height) +#define gdispGetHeight() gdispGGetHeight(GDISP) /** * @brief Get the current display power mode. * + * @param[in] g The display to use + * * @api */ -#define gdispGetPowerMode() (GDISP->Powermode) +#define gdispGGetPowerMode(g) (((GDISPControl *)(g))->Powermode) +#define gdispGetPowerMode() gdispGGetPowerMode(GDISP) /** * @brief Get the current display orientation. * + * @param[in] g The display to use + * * @api */ -#define gdispGetOrientation() (GDISP->Orientation) +#define gdispGGetOrientation(g) (((GDISPControl *)(g))->Orientation) +#define gdispGetOrientation() gdispGGetOrientation(GDISP) /** * @brief Get the current display backlight brightness. * + * @param[in] g The display to use + * * @api */ -#define gdispGetBacklight() (GDISP->Backlight) +#define gdispGGetBacklight(g) (((GDISPControl *)(g))->Backlight) +#define gdispGetBacklight() gdispGGetBacklight(GDISP) /** * @brief Get the current display contrast. * + * @param[in] g The display to use + * * @api */ -#define gdispGetContrast() (GDISP->Contrast) +#define gdispGGetContrast(g) (((GDISPControl *)(g))->Contrast) +#define gdispGetContrast() gdispGGetContrast(GDISP) /* More interesting macro's */ /** * @brief Reset the clip area to the full screen * + * @param[in] g The display to use + * * @api */ -#define gdispUnsetClip() gdispSetClip(0,0,gdispGetWidth(),gdispGetHeight()) +#define gdispGUnsetClip(g) gdispGSetClip((g),0,0,(g)->Width,(g)->Height) +#define gdispUnsetClip() gdispGUnsetClip(GDISP) #ifdef __cplusplus } diff --git a/include/gdisp/lld/gdisp_lld.h b/include/gdisp/lld/gdisp_lld.h index 4813d828..2a6f90b7 100644 --- a/include/gdisp/lld/gdisp_lld.h +++ b/include/gdisp/lld/gdisp_lld.h @@ -18,140 +18,136 @@ #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. */ /*===========================================================================*/ -#if !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS) +/** + * @name GDISP hardware accelerated support + * @{ + */ /** - * @name GDISP hardware accelerated support - * @{ + * @brief Hardware streaming writing is supported. + * @details If set to @p FALSE software emulation is used. + * @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver */ - /** - * @brief Hardware streaming writing is supported. - * @details If set to @p FALSE software emulation is used. - * @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver - */ - #ifndef GDISP_HARDWARE_STREAM_WRITE - #define GDISP_HARDWARE_STREAM_WRITE FALSE - #endif + #ifndef GDISP_HARDWARE_STREAM_WRITE + #define GDISP_HARDWARE_STREAM_WRITE FALSE + #endif - /** - * @brief Hardware streaming reading of the display surface is supported. - * @details If set to @p FALSE this routine is not available. - */ - #ifndef GDISP_HARDWARE_STREAM_READ - #define GDISP_HARDWARE_STREAM_READ FALSE - #endif + /** + * @brief Hardware streaming reading of the display surface is supported. + * @details If set to @p FALSE this routine is not available. + */ + #ifndef GDISP_HARDWARE_STREAM_READ + #define GDISP_HARDWARE_STREAM_READ FALSE + #endif - /** - * @brief Hardware supports setting the cursor position within the stream window. - * @details If set to @p FALSE this routine is not available. - * @note This is used to optimise setting of individual pixels within a stream window. - * It should therefore not be implemented unless it is cheaper than just setting - * a new window. - */ - #ifndef GDISP_HARDWARE_STREAM_POS - #define GDISP_HARDWARE_STREAM_POS FALSE - #endif + /** + * @brief Hardware supports setting the cursor position within the stream window. + * @details If set to @p FALSE this routine is not available. + * @note This is used to optimise setting of individual pixels within a stream window. + * It should therefore not be implemented unless it is cheaper than just setting + * a new window. + */ + #ifndef GDISP_HARDWARE_STREAM_POS + #define GDISP_HARDWARE_STREAM_POS FALSE + #endif - /** - * @brief Hardware accelerated draw pixel. - * @details If set to @p FALSE software emulation is used. - * @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver - */ - #ifndef GDISP_HARDWARE_DRAWPIXEL - #define GDISP_HARDWARE_DRAWPIXEL FALSE - #endif + /** + * @brief Hardware accelerated draw pixel. + * @details If set to @p FALSE software emulation is used. + * @note Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driver + */ + #ifndef GDISP_HARDWARE_DRAWPIXEL + #define GDISP_HARDWARE_DRAWPIXEL FALSE + #endif - /** - * @brief Hardware accelerated screen clears. - * @details If set to @p FALSE software emulation is used. - * @note This clears the entire display surface regardless of the clipping area currently set - */ - #ifndef GDISP_HARDWARE_CLEARS - #define GDISP_HARDWARE_CLEARS FALSE - #endif + /** + * @brief Hardware accelerated 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 - /** @} */ -#endif + /** + * @brief The driver supports a clipping in hardware. + * @details If set to @p FALSE there is no support for non-standard queries. + * @note If this is defined the driver must perform its own clipping on all calls to + * the driver and respond appropriately if a parameter is outside the display area. + * @note If this is not defined then the software ensures that all calls to the + * driver do not exceed the display area (provided GDISP_NEED_CLIP or GDISP_NEED_VALIDATION + * has been set). + */ + #ifndef GDISP_HARDWARE_CLIP + #define GDISP_HARDWARE_CLIP FALSE + #endif +/** @} */ /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ -typedef struct GDISPDriver { - GDISPControl g; +typedef struct GDisplay { + GDISPControl g; // The public GDISP stuff - must be the first element - #if GDISP_MULTIPLE_DRIVERS - const struct GDISPVMT const * vmt; + #if GDISP_TOTAL_CONTROLLERS > 1 + const struct GDISPVMT const * vmt; // The Virtual Method Table #endif + void * priv; // A private area just for the drivers use. + + uint16_t flags; #define GDISP_FLG_INSTREAM 0x0001 // We are in a user based stream operation #define GDISP_FLG_SCRSTREAM 0x0002 // The stream area currently covers the whole screen @@ -163,7 +159,7 @@ typedef struct GDISPDriver { #endif // Software clipping - #if (GDISP_MULTIPLE_DRIVERS || !GDISP_HARDWARE_CLIP) && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION) + #if !GDISP_HARDWARE_CLIP && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION) coord_t clipx0, clipy0; coord_t clipx1, clipy1; /* not inclusive */ #endif @@ -195,10 +191,10 @@ typedef struct GDISPDriver { color_t linebuf[GDISP_LINEBUF_SIZE]; #endif -} GDISPDriver; +} GDisplay; -#if !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS) || defined(__DOXYGEN__) - #if GDISP_MULTIPLE_DRIVERS +#if GDISP_TOTAL_CONTROLLERS == 1 || defined(GDISP_DRIVER_VMT) || defined(__DOXYGEN__) + #if GDISP_TOTAL_CONTROLLERS > 1 #define LLDSPEC static #else #define LLDSPEC @@ -212,9 +208,10 @@ typedef struct GDISPDriver { * @brief Initialize the driver. * @return TRUE if successful. * @param[in] g The driver structure + * @param[in] display The display number for this controller 0..n * @param[out] g->g The driver must fill in the GDISPControl structure */ - LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g); + LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display); #if GDISP_HARDWARE_STREAM_WRITE || defined(__DOXYGEN__) /** @@ -230,7 +227,7 @@ typedef struct GDISPDriver { * undefined results. * @note This must be followed by a call to @p gdisp_lld_write_pos() if GDISP_HARDWARE_STREAM_POS is TRUE. */ - LLDSPEC void gdisp_lld_write_start(GDISPDriver *g); + LLDSPEC void gdisp_lld_write_start(GDisplay *g); /** * @brief Send a pixel to the current streaming position and then increment that position @@ -241,7 +238,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_write_color(GDISPDriver *g); + LLDSPEC void gdisp_lld_write_color(GDisplay *g); /** * @brief End the current streaming write operation @@ -251,7 +248,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_write_stop(GDISPDriver *g); + LLDSPEC void gdisp_lld_write_stop(GDisplay *g); #if GDISP_HARDWARE_STREAM_POS || defined(__DOXYGEN__) /** @@ -263,7 +260,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_write_pos(GDISPDriver *g); + LLDSPEC void gdisp_lld_write_pos(GDisplay *g); #endif #endif @@ -280,7 +277,7 @@ typedef struct GDISPDriver { * @note Streaming operations that wrap the defined window have * undefined results. */ - LLDSPEC void gdisp_lld_read_start(GDISPDriver *g); + LLDSPEC void gdisp_lld_read_start(GDisplay *g); /** * @brief Read a pixel from the current streaming position and then increment that position @@ -291,7 +288,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC color_t gdisp_lld_read_color(GDISPDriver *g); + LLDSPEC color_t gdisp_lld_read_color(GDisplay *g); /** * @brief End the current streaming operation @@ -301,7 +298,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_read_stop(GDISPDriver *g); + LLDSPEC void gdisp_lld_read_stop(GDisplay *g); #endif #if GDISP_HARDWARE_DRAWPIXEL || defined(__DOXYGEN__) @@ -315,7 +312,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g); + LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g); #endif #if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__) @@ -328,7 +325,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_clear(GDISPDriver *g); + LLDSPEC void gdisp_lld_clear(GDisplay *g); #endif #if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) @@ -343,7 +340,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g); + LLDSPEC void gdisp_lld_fill_area(GDisplay *g); #endif #if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) @@ -360,7 +357,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g); + LLDSPEC void gdisp_lld_blit_area(GDisplay *g); #endif #if GDISP_HARDWARE_PIXELREAD || defined(__DOXYGEN__) @@ -374,7 +371,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC color_t gdisp_lld_get_pixel_color(GDISPDriver *g); + LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g); #endif #if (GDISP_HARDWARE_SCROLL && GDISP_NEED_SCROLL) || defined(__DOXYGEN__) @@ -393,7 +390,7 @@ typedef struct GDISPDriver { * @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); + LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g); #endif #if (GDISP_HARDWARE_CONTROL && GDISP_NEED_CONTROL) || defined(__DOXYGEN__) @@ -407,7 +404,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_control(GDISPDriver *g); + LLDSPEC void gdisp_lld_control(GDisplay *g); #endif #if (GDISP_HARDWARE_QUERY && GDISP_NEED_QUERY) || defined(__DOXYGEN__) @@ -421,7 +418,7 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void *gdisp_lld_query(GDISPDriver *g); // Uses p.x (=what); + LLDSPEC void *gdisp_lld_query(GDisplay *g); // Uses p.x (=what); #endif #if (GDISP_HARDWARE_CLIP && (GDISP_NEED_CLIP || GDISP_NEED_VALIDATION)) || defined(__DOXYGEN__) @@ -435,40 +432,39 @@ typedef struct GDISPDriver { * * @note The parameter variables must not be altered by the driver. */ - LLDSPEC void gdisp_lld_set_clip(GDISPDriver *g); + LLDSPEC void gdisp_lld_set_clip(GDisplay *g); #endif #ifdef __cplusplus } #endif -#endif // !GDISP_MULTIPLE_DRIVERS || defined(GDISP_LLD_DECLARATIONS) +#endif // GDISP_TOTAL_CONTROLLERS == 1 || defined(GDISP_DRIVER_VMT) -#if GDISP_MULTIPLE_DRIVERS +#if GDISP_TOTAL_CONTROLLERS > 1 typedef struct GDISPVMT { - bool_t (*init)(GDISPDriver *g); - void (*writestart)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy - void (*writepos)(GDISPDriver *g); // Uses p.x,p.y - void (*writecolor)(GDISPDriver *g); // Uses p.color - void (*writestop)(GDISPDriver *g); // Uses no parameters - void (*readstart)(GDISPDriver *g); // Uses p.x,p.y p.cx,p.cy - color_t (*readcolor)(GDISPDriver *g); // Uses no parameters - void (*readstop)(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 + bool_t (*init)(GDisplay *g, unsigned display); + void (*writestart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy + void (*writepos)(GDisplay *g); // Uses p.x,p.y + void (*writecolor)(GDisplay *g); // Uses p.color + void (*writestop)(GDisplay *g); // Uses no parameters + void (*readstart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy + color_t (*readcolor)(GDisplay *g); // Uses no parameters + void (*readstop)(GDisplay *g); // Uses no parameters + void (*pixel)(GDisplay *g); // Uses p.x,p.y p.color + void (*clear)(GDisplay *g); // Uses p.color + void (*fill)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy p.color + void (*blit)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy p.x1,p.y1 (=srcx,srcy) p.x2 (=srccx), p.ptr (=buffer) + color_t (*get)(GDisplay *g); // Uses p.x,p.y + void (*vscroll)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy, p.y1 (=lines) p.color + void (*control)(GDisplay *g); // Uses p.x (=what) p.ptr (=value) + void *(*query)(GDisplay *g); // Uses p.x (=what); + void (*setclip)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy } GDISPVMT; - #ifdef GDISP_LLD_DECLARATIONS - #define GDISP_DRIVER_STRUCT_INIT {{0}, &VMT} - static const GDISPVMT VMT = { + #if defined(GDISP_DRIVER_VMT) + const GDISPVMT const GDISP_DRIVER_VMT[1] = {{ gdisp_lld_init, #if GDISP_HARDWARE_STREAM_WRITE gdisp_lld_write_start, @@ -480,7 +476,7 @@ typedef struct GDISPDriver { gdisp_lld_write_color, gdisp_lld_write_stop, #else - 0, 0, 0, + 0, 0, 0, 0, #endif #if GDISP_HARDWARE_STREAM_READ gdisp_lld_read_start, @@ -534,11 +530,10 @@ typedef struct GDISPDriver { #else 0, #endif - }; - GDISPDriver GDISP_DRIVER_STRUCT = {{0}, &VMT}; + }}; #else - #define gdisp_lld_init(g) g->vmt->init(g) + #define gdisp_lld_init(g, display) g->vmt->init(g, display) #define gdisp_lld_write_start(g) g->vmt->writestart(g) #define gdisp_lld_write_pos(g) g->vmt->writepos(g) #define gdisp_lld_write_color(g) g->vmt->writecolor(g) @@ -555,19 +550,9 @@ typedef struct GDISPDriver { #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 +#endif // GDISP_TOTAL_CONTROLLERS > 1 /* Verify information for packed pixels and define a non-packed pixel macro */ #if !GDISP_PACKED_PIXELS diff --git a/include/gdisp/options.h b/include/gdisp/options.h index 1a0f6907..9af7788f 100644 --- a/include/gdisp/options.h +++ b/include/gdisp/options.h @@ -20,19 +20,6 @@ * @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. @@ -155,6 +142,50 @@ #ifndef GDISP_NEED_IMAGE #define GDISP_NEED_IMAGE FALSE #endif +/** + * @} + * + * @name GDISP Multiple Display Support + * @{ + */ + /** + * @brief The total number of displays. + * @note This can be on just one type of controller or spread across several different controllers + */ + #ifndef GDISP_TOTAL_DISPLAYS + #define GDISP_TOTAL_DISPLAYS 1 + #endif + /** + * @brief The total number of controllers. + * @note If this is greater than one, all the hardware acceleration options below + * and the pixel format must be manually specified in your gfxconf.h along with + * @p GDISP_CONTROLLER_LIST. See the gdisp_lld_config.h in each driver to get a list + * of hardware capabilities for each driver in order to work out the common set across + * all the controllers you want to use. + */ + #ifndef GDISP_TOTAL_CONTROLLERS + #define GDISP_TOTAL_CONTROLLERS 1 + #endif + + #if defined(__DOXYGEN__) + /** + * @brief The list of controllers. + * @note This is required if @p GDISP_TOTAL_CONTROLLERS is greater than one. + * @note The number of entries must match @p GDISP_TOTAL_CONTROLLERS. + * @note See the gdisp_lld.c in each driver (near the top) to get the name of the VMT for a driver. + * @note Replace this example with your own definition in your gfxconf.h file. + */ + #define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_SSD1963 + /** + * @brief The number of displays for each controller. + * @note This is required if @p GDISP_TOTAL_CONTROLLERS is greater than one. + * @note The number of entries must match @p GDISP_TOTAL_CONTROLLERS. + * @note The sum of all the display counts must equal @p GDISP_TOTAL_DISPLAYS (3 for this example) + * or bad things will happen. + * @note Replace this example with your own definition in your gfxconf.h file. + */ + #define GDISP_CONTROLLER_DISPLAYS 2, 1 + #endif /** * @} * diff --git a/include/gfx_rules.h b/include/gfx_rules.h index a8dd031e..c58fc5ba 100644 --- a/include/gfx_rules.h +++ b/include/gfx_rules.h @@ -134,12 +134,14 @@ #endif #if GFX_USE_GDISP - #if GDISP_MULTIPLE_DRIVERS + #if GDISP_TOTAL_CONTROLLERS > 1 + #ifndef GDISP_CONTROLLER_LIST + #error "GDISP Multiple Controllers: You must specify a value for GDISP_CONTROLLER_LIST" + #endif #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." + #error "GDISP Multiple Controllers: You must specify a value for GDISP_PIXELFORMAT" #endif - #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 #endif #endif #if GDISP_NEED_ANTIALIAS && !GDISP_NEED_PIXELREAD diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 756d5c1d..41f2f0f9 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -31,81 +31,92 @@ #define INLINE #endif +// Number of milliseconds for the startup logo - 0 means disabled. +#define GDISP_STARTUP_LOGO_TIMEOUT 1000 + /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ -#define GC ((GDISPDriver *)GDISP) -GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; +// The controller array, the display array and the default display +#if GDISP_TOTAL_CONTROLLERS > 1 + typedef const struct GDISPVMT const VMTEL[1]; + extern VMTEL GDISP_CONTROLLER_LIST; + static const struct GDISPVMT const * ControllerList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; + static const unsigned DisplayCountList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS}; +#endif +static GDisplay GDisplayArray[GDISP_TOTAL_DISPLAYS]; +GDisplay *GDISP = GDisplayArray; #if GDISP_NEED_MULTITHREAD - #define MUTEX_INIT() gfxMutexInit(&GC->mutex) - #define MUTEX_ENTER() gfxMutexEnter(&GC->mutex) - #define MUTEX_EXIT() gfxMutexExit(&GC->mutex) + #define MUTEX_INIT(g) gfxMutexInit(&(g)->mutex) + #define MUTEX_ENTER(g) gfxMutexEnter(&(g)->mutex) + #define MUTEX_EXIT(g) gfxMutexExit(&(g)->mutex) #else - #define MUTEX_INIT() - #define MUTEX_ENTER() - #define MUTEX_EXIT() + #define MUTEX_INIT(g) + #define MUTEX_ENTER(g) + #define MUTEX_EXIT(g) #endif #define NEED_CLIPPING (!GDISP_HARDWARE_CLIP && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) + /*==========================================================================*/ /* Internal functions. */ /*==========================================================================*/ #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - static INLINE void setglobalwindow(void) { + static INLINE void setglobalwindow(GDisplay *g) { coord_t x, y; - x = GC->p.x; y = GC->p.y; - GC->p.cx = GC->g.Width; GC->p.cy = GC->g.Height; - gdisp_lld_write_start(GC); - GC->p.x = x; GC->p.y = y; - GC->flags |= GDISP_FLG_SCRSTREAM; + x = g->p.x; y = g->p.y; + g->p.cx = g->g.Width; g->p.cy = g->g.Height; + gdisp_lld_write_start(g); + g->p.x = x; g->p.y = y; + g->flags |= GDISP_FLG_SCRSTREAM; } #endif -// drawpixel_clip() +// drawpixel_clip(g) // Parameters: x,y // Alters: cx, cy (if using streaming) #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw #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(GC); + static INLINE void drawpixel_clip(GDisplay *g) { + if (g->p.x >= g->clipx0 && g->p.x < g->clipx1 && g->p.y >= g->clipy0 && g->p.y < g->clipy1) + gdisp_lld_draw_pixel(g); } #else - #define drawpixel_clip() gdisp_lld_draw_pixel(GC) + #define drawpixel_clip(g) gdisp_lld_draw_pixel(g) #endif #elif GDISP_HARDWARE_STREAM_POS // Next best is cursor based streaming - static INLINE void drawpixel_clip(void) { + static INLINE void drawpixel_clip(GDisplay *g) { #if NEED_CLIPPING - if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1 || GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; #endif - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - gdisp_lld_write_color(GC); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); } #else // Worst is streaming - static INLINE void drawpixel_clip(void) { + static INLINE void drawpixel_clip(GDisplay *g) { #if NEED_CLIPPING - if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1 || GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; #endif - GC->p.cx = GC->p.cy = 1; - gdisp_lld_write_start(GC); - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); } #endif -// fillarea() +// fillarea(g) // Parameters: x,y cx,cy and color // Alters: nothing // Note: This is not clipped @@ -113,94 +124,94 @@ GDISPControl *GDISP = &GDISP_DRIVER_STRUCT.g; // if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - #define fillarea() gdisp_lld_fill_area(GC) + #define fillarea(g) gdisp_lld_fill_area(g) #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming - static INLINE void fillarea(void) { + static INLINE void fillarea(GDisplay *g) { uint32_t area; - area = (uint32_t)GC->p.cx * GC->p.cy; + area = (uint32_t)g->p.cx * g->p.cy; #if GDISP_HARDWARE_STREAM_POS - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - gdisp_lld_write_start(GC); + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif for(; area; area--) - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); } #else // Worst is drawing pixels - static INLINE void fillarea(void) { + static INLINE void fillarea(GDisplay *g) { coord_t x0, y0, x1, y1; - x0 = GC->p.x; - y0 = GC->p.y; - x1 = GC->p.x + GC->p.cx; - 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(GC); - GC->p.y = y0; + x0 = g->p.x; + y0 = g->p.y; + x1 = g->p.x + g->p.cx; + y1 = g->p.y + g->p.cy; + for(; g->p.y < y1; g->p.y++, g->p.x = x0) + for(; g->p.x < x1; g->p.x++) + gdisp_lld_draw_pixel(g); + g->p.y = y0; } #endif #if NEED_CLIPPING - #define TEST_CLIP_AREA(x,y,cx,cy) \ - if ((x) < GC->clipx0) { (cx) -= GC->clipx0 - (x); (x) = GC->clipx0; } \ - if ((y) < GC->clipy0) { (cy) -= GC->clipy0 - (y); (y) = GC->clipy0; } \ - if ((x) + (cx) > GC->clipx1) (cx) = GC->clipx1 - (x); \ - if ((y) + (cy) > GC->clipy1) (cy) = GC->clipy1 - (y); \ - if ((cx) > 0 && (cy) > 0) + #define TEST_CLIP_AREA(g) \ + if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; } \ + if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; } \ + if ((g)->p.x + (g)->p.cx > (g)->clipx1) (g)->p.cx = (g)->clipx1 - (g)->p.x; \ + if ((g)->p.y + (g)->p.cy > (g)->clipy1) (g)->p.cy = (g)->clipy1 - (g)->p.y; \ + if ((g)->p.cx > 0 && (g)->p.cy > 0) #else - #define TEST_CLIP_AREA(x,y,cx,cy) + #define TEST_CLIP_AREA(g) #endif // Parameters: x,y and x1 // Alters: x,y x1,y1 cx,cy // Assumes the window covers the screen and a write_stop() will occur later // if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. -static void hline_clip(void) { +static void hline_clip(GDisplay *g) { // Swap the points if necessary so it always goes from x to x1 - if (GC->p.x1 < GC->p.x) { - GC->p.cx = GC->p.x; GC->p.x = GC->p.x1; GC->p.x1 = GC->p.cx; + if (g->p.x1 < g->p.x) { + g->p.cx = g->p.x; g->p.x = g->p.x1; g->p.x1 = g->p.cx; } // Clipping #if NEED_CLIPPING - if (GC->p.y < GC->clipy0 || GC->p.y >= GC->clipy1) return; - if (GC->p.x < GC->clipx0) GC->p.x = GC->clipx0; - if (GC->p.x1 >= GC->clipx1) GC->p.x1 = GC->clipx1 - 1; - if (GC->p.x1 < GC->p.x) return; + if (g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; + if (g->p.x < g->clipx0) g->p.x = g->clipx0; + if (g->p.x1 >= g->clipx1) g->p.x1 = g->clipx1 - 1; + if (g->p.x1 < g->p.x) return; #endif // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) // Is this a point - if (GC->p.x == GC->p.x1) { + if (g->p.x == g->p.x1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(GC); + gdisp_lld_draw_pixel(g); #elif GDISP_HARDWARE_STREAM_POS // Next best is cursor based streaming - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - gdisp_lld_write_color(GC); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); #else // Worst is streaming - GC->p.cx = GC->p.cy = 1; - gdisp_lld_write_start(GC); - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); #endif return; } @@ -208,65 +219,65 @@ static void hline_clip(void) { #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - GC->p.cx = GC->p.x1 - GC->p.x + 1; - GC->p.cy = 1; - gdisp_lld_fill_area(GC); + g->p.cx = g->p.x1 - g->p.x + 1; + g->p.cy = 1; + gdisp_lld_fill_area(g); #elif GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE // Next best is cursor based streaming - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - do { gdisp_lld_write_color(GC); } while(GC->p.cx--); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + do { gdisp_lld_write_color(g); } while(g->p.cx--); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming - GC->p.cx = GC->p.x1 - GC->p.x + 1; - GC->p.cy = 1; - gdisp_lld_write_start(GC); - do { gdisp_lld_write_color(GC); } while(GC->p.cx--); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.x1 - g->p.x + 1; + g->p.cy = 1; + gdisp_lld_write_start(g); + do { gdisp_lld_write_color(g); } while(g->p.cx--); + gdisp_lld_write_stop(g); #else // Worst is drawing pixels - for(; GC->p.x <= GC->p.x1; GC->p.x++) - gdisp_lld_draw_pixel(GC); + for(; g->p.x <= g->p.x1; g->p.x++) + gdisp_lld_draw_pixel(g); #endif } // Parameters: x,y and y1 // Alters: x,y x1,y1 cx,cy -static void vline_clip(void) { +static void vline_clip(GDisplay *g) { // Swap the points if necessary so it always goes from y to y1 - if (GC->p.y1 < GC->p.y) { - GC->p.cy = GC->p.y; GC->p.y = GC->p.y1; GC->p.y1 = GC->p.cy; + if (g->p.y1 < g->p.y) { + g->p.cy = g->p.y; g->p.y = g->p.y1; g->p.y1 = g->p.cy; } // Clipping #if NEED_CLIPPING - if (GC->p.x < GC->clipx0 || GC->p.x >= GC->clipx1) return; - if (GC->p.y < GC->clipy0) GC->p.y = GC->clipy0; - if (GC->p.y1 >= GC->clipy1) GC->p.y1 = GC->clipy1 - 1; - if (GC->p.y1 < GC->p.y) return; + if (g->p.x < g->clipx0 || g->p.x >= g->clipx1) return; + if (g->p.y < g->clipy0) g->p.y = g->clipy0; + if (g->p.y1 >= g->clipy1) g->p.y1 = g->clipy1 - 1; + if (g->p.y1 < g->p.y) return; #endif // This is an optimization for the point case. It is only worthwhile however if we // have hardware fills or if we support both hardware pixel drawing and hardware streaming #if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) || (GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE) // Is this a point - if (GC->p.y == GC->p.y1) { + if (g->p.y == g->p.y1) { #if GDISP_HARDWARE_DRAWPIXEL // Best is hardware accelerated pixel draw - gdisp_lld_draw_pixel(GC); + gdisp_lld_draw_pixel(g); #elif GDISP_HARDWARE_STREAM_POS // Next best is cursor based streaming - if (!(GC->flags & GDISP_FLG_SCRSTREAM)) - setglobalwindow(); - gdisp_lld_write_pos(GC); - gdisp_lld_write_color(GC); + if (!(g->flags & GDISP_FLG_SCRSTREAM)) + setglobalwindow(g); + gdisp_lld_write_pos(g); + gdisp_lld_write_color(g); #else // Worst is streaming - GC->p.cx = GC->p.cy = 1; - gdisp_lld_write_start(GC); - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + g->p.cx = g->p.cy = 1; + gdisp_lld_write_start(g); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); #endif return; } @@ -274,48 +285,48 @@ static void vline_clip(void) { #if GDISP_HARDWARE_FILLS // Best is hardware accelerated area fill - GC->p.cy = GC->p.y1 - GC->p.y + 1; - GC->p.cx = 1; - gdisp_lld_fill_area(GC); + g->p.cy = g->p.y1 - g->p.y + 1; + g->p.cx = 1; + gdisp_lld_fill_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming #if GDISP_HARDWARE_STREAM_POS - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - GC->p.cy = GC->p.y1 - GC->p.y + 1; - GC->p.cx = 1; - gdisp_lld_write_start(GC); + g->p.cy = g->p.y1 - g->p.y + 1; + g->p.cx = 1; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif - do { gdisp_lld_write_color(GC); } while(GC->p.cy--); - gdisp_lld_write_stop(GC); + do { gdisp_lld_write_color(g); } while(g->p.cy--); + gdisp_lld_write_stop(g); #else // Worst is drawing pixels - for(; GC->p.y <= GC->p.y1; GC->p.y++) - gdisp_lld_draw_pixel(GC); + for(; g->p.y <= g->p.y1; g->p.y++) + gdisp_lld_draw_pixel(g); #endif } // Parameters: x,y and x1,y1 // Alters: x,y x1,y1 cx,cy -static void line_clip(void) { +static void line_clip(GDisplay *g) { int16_t dy, dx; int16_t addx, addy; int16_t P, diff, i; // Is this a horizontal line (or a point) - if (GC->p.y == GC->p.y1) { - hline_clip(); + if (g->p.y == g->p.y1) { + hline_clip(g); return; } // Is this a vertical line (or a point) - if (GC->p.x == GC->p.x1) { - vline_clip(); + if (g->p.x == g->p.x1) { + vline_clip(g); return; } @@ -327,18 +338,18 @@ static void line_clip(void) { // When clipping is needed, all the clipping could also be done up front // instead of on each pixel. - if (GC->p.x1 >= GC->p.x) { - dx = GC->p.x1 - GC->p.x; + if (g->p.x1 >= g->p.x) { + dx = g->p.x1 - g->p.x; addx = 1; } else { - dx = GC->p.x - GC->p.x1; + dx = g->p.x - g->p.x1; addx = -1; } - if (GC->p.y1 >= GC->p.y) { - dy = GC->p.y1 - GC->p.y; + if (g->p.y1 >= g->p.y) { + dy = g->p.y1 - g->p.y; addy = 1; } else { - dy = GC->p.y - GC->p.y1; + dy = g->p.y - g->p.y1; addy = -1; } @@ -348,14 +359,14 @@ static void line_clip(void) { diff = P - dx; for(i=0; i<=dx; ++i) { - drawpixel_clip(); + drawpixel_clip(g); if (P < 0) { P += dy; - GC->p.x += addx; + g->p.x += addx; } else { P += diff; - GC->p.x += addx; - GC->p.y += addy; + g->p.x += addx; + g->p.y += addy; } } } else { @@ -364,90 +375,126 @@ static void line_clip(void) { diff = P - dy; for(i=0; i<=dy; ++i) { - drawpixel_clip(); + drawpixel_clip(g); if (P < 0) { P += dx; - GC->p.y += addy; + g->p.y += addy; } else { P += diff; - GC->p.x += addx; - GC->p.y += addy; + g->p.x += addx; + g->p.y += addy; } } } } +#if GDISP_STARTUP_LOGO_TIMEOUT > 0 + static void StatupLogoDisplay(GDisplay *g) { + gdispGClear(g, Black); + gdispGFillArea(g, g->g.Width/4, g->g.Height/4, g->g.Width/2, g->g.Height/2, Blue); + } +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ /* Our module initialiser */ void _gdispInit(void) { - MUTEX_INIT(); + GDisplay *g; + unsigned i; + #if GDISP_TOTAL_CONTROLLERS > 1 + unsigned j; + #endif + /* Initialise driver */ - MUTEX_ENTER(); - 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(GC); - #else - GC->clipx0 = 0; - GC->clipy0 = 0; - GC->clipx1 = GC->g.Width; - GC->clipy1 = GC->g.Height; - #endif + #if GDISP_TOTAL_CONTROLLERS > 1 + for(g = GDisplayArray, j=0; j < GDISP_TOTAL_CONTROLLERS; j++) + for(i = 0; i < DisplayCountList[j]; g++, i++) { + g->vmt = ControllerList[j]; + #else + for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) { #endif - MUTEX_EXIT(); + MUTEX_INIT(g); + MUTEX_ENTER(g); + g->flags = 0; + gdisp_lld_init(g, i); + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + #if GDISP_HARDWARE_CLIP + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_set_clip(g); + #else + g->clipx0 = 0; + g->clipy0 = 0; + g->clipx1 = g->g.Width; + g->clipy1 = g->g.Height; + #endif + #endif + MUTEX_EXIT(g); + #if GDISP_STARTUP_LOGO_TIMEOUT > 0 + StatupLogoDisplay(g); + #else + gdispGClear(g, Black); + #endif + } + #if GDISP_STARTUP_LOGO_TIMEOUT > 0 + gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); + for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) + gdispGClear(g, Black); + #endif +} + +void gdispSetDisplay(unsigned display) { + if (display < GDISP_TOTAL_DISPLAYS) + GDISP = &GDisplayArray[display]; } #if GDISP_NEED_STREAMING - void gdispStreamStart(coord_t x, coord_t y, coord_t cx, coord_t cy) { - MUTEX_ENTER(); + void gdispGStreamStart(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { + MUTEX_ENTER(g); #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 (x < g->clipx0 || x+cx > g->clipx1 || y < g->clipy0 || y+cy > g->clipy1) { + MUTEX_EXIT(g); return; } #endif - GC->flags |= GDISP_FLG_INSTREAM; + g->flags |= GDISP_FLG_INSTREAM; #if GDISP_HARDWARE_STREAM_WRITE // Best is hardware streaming - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_write_start(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif #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; + g->p.x1 = g->p.x = x; + g->p.y1 = g->p.y = y; + g->p.x2 = x + cx; + g->p.y2 = y + cy; #if (GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS) || GDISP_HARDWARE_FILLS - GC->p.cx = 0; - GC->p.cy = 1; + g->p.cx = 0; + g->p.cy = 1; #endif #endif // Don't release the mutex as gdispStreamEnd() will do that. } - void gdispStreamColor(color_t color) { + void gdispGStreamColor(GDisplay *g, color_t color) { #if !GDISP_HARDWARE_STREAM_WRITE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS coord_t sx1, sy1; #endif @@ -455,224 +502,224 @@ void _gdispInit(void) { // 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)) + if (!(g->flags & GDISP_FLG_INSTREAM)) return; #if GDISP_HARDWARE_STREAM_WRITE // Best is hardware streaming - GC->p.color = color; - gdisp_lld_write_color(GC); + g->p.color = color; + gdisp_lld_write_color(g); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - GC->linebuf[GC->p.cx++] = color; - if (GC->p.cx >= GDISP_LINEBUF_SIZE) { - sx1 = GC->p.x1; - sy1 = GC->p.y1; - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); - GC->p.x1 = sx1; - GC->p.y1 = sy1; - GC->p.x += GC->p.cx; - GC->p.cx = 0; + g->linebuf[g->p.cx++] = color; + if (g->p.cx >= GDISP_LINEBUF_SIZE) { + sx1 = g->p.x1; + sy1 = g->p.y1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + g->p.x1 = sx1; + g->p.y1 = sy1; + g->p.x += g->p.cx; + g->p.cx = 0; } // Just wrap at end-of-line and end-of-buffer - if (GC->p.x+GC->p.cx >= GC->p.x2) { - if (GC->p.cx) { - sx1 = GC->p.x1; - sy1 = GC->p.y1; - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); - GC->p.x1 = sx1; - GC->p.y1 = sy1; - GC->p.cx = 0; + if (g->p.x+g->p.cx >= g->p.x2) { + if (g->p.cx) { + sx1 = g->p.x1; + sy1 = g->p.y1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); + g->p.x1 = sx1; + g->p.y1 = sy1; + g->p.cx = 0; } - GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.y2) - GC->p.y = GC->p.y1; + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } #elif GDISP_HARDWARE_FILLS // Only slightly better than drawing pixels is to look for runs and use fill area - if (!GC->p.cx || GC->p.color == color) { - GC->p.cx++; - GC->p.color = color; + if (!g->p.cx || g->p.color == color) { + g->p.cx++; + g->p.color = color; } else { - if (GC->p.cx == 1) - gdisp_lld_draw_pixel(GC); + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); else - gdisp_lld_fill_area(GC); - GC->p.x += GC->p.cx; - GC->p.color = color; - GC->p.cx = 1; + gdisp_lld_fill_area(g); + g->p.x += g->p.cx; + g->p.color = color; + g->p.cx = 1; } // Just wrap at end-of-line and end-of-buffer - if (GC->p.x+GC->p.cx >= GC->p.x2) { - if (GC->p.cx) { - if (GC->p.cx == 1) - gdisp_lld_draw_pixel(GC); + if (g->p.x+g->p.cx >= g->p.x2) { + if (g->p.cx) { + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); else - gdisp_lld_fill_area(GC); - GC->p.cx = 0; + gdisp_lld_fill_area(g); + g->p.cx = 0; } - GC->p.x = GC->p.x1; - if (++GC->p.y >= GC->p.y2) - GC->p.y = GC->p.y1; + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } #else // Worst is using pixel drawing - GC->p.color = color; - gdisp_lld_draw_pixel(GC); + g->p.color = color; + gdisp_lld_draw_pixel(g); // 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.y2) - GC->p.y = GC->p.y1; + if (++g->p.x >= g->p.x2) { + g->p.x = g->p.x1; + if (++g->p.y >= g->p.y2) + g->p.y = g->p.y1; } #endif } - void gdispStreamStop(void) { + void gdispGStreamStop(GDisplay *g) { // Only release the mutex and end the stream if we are actually streaming. - if (!(GC->flags & GDISP_FLG_INSTREAM)) + if (!(g->flags & GDISP_FLG_INSTREAM)) return; #if GDISP_HARDWARE_STREAM_WRITE - gdisp_lld_write_stop(GC); + gdisp_lld_write_stop(g); #elif GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS - if (GC->p.cx) { - GC->p.x1 = 0; - GC->p.y1 = 0; - GC->p.ptr = (void *)GC->linebuf; - gdisp_lld_blit_area(GC); + if (g->p.cx) { + g->p.x1 = 0; + g->p.y1 = 0; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); } #elif GDISP_HARDWARE_FILLS - if (GC->p.cx) { - if (GC->p.cx == 1) - gdisp_lld_draw_pixel(GC); + if (g->p.cx) { + if (g->p.cx == 1) + gdisp_lld_draw_pixel(g); else - gdisp_lld_fill_area(GC); + gdisp_lld_fill_area(g); } #endif - GC->flags &= ~GDISP_FLG_INSTREAM; - MUTEX_EXIT(); + g->flags &= ~GDISP_FLG_INSTREAM; + MUTEX_EXIT(g); } #endif -void gdispDrawPixel(coord_t x, coord_t y, color_t color) { - MUTEX_ENTER(); - GC->p.x = x; - GC->p.y = y; - GC->p.color = color; - drawpixel_clip(); +void gdispGDrawPixel(GDisplay *g, coord_t x, coord_t y, color_t color) { + MUTEX_ENTER(g); + g->p.x = x; + g->p.y = y; + g->p.color = color; + drawpixel_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - MUTEX_ENTER(); - GC->p.x = x0; - GC->p.y = y0; - GC->p.x1 = x1; - GC->p.y1 = y1; - GC->p.color = color; - line_clip(); +void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { + MUTEX_ENTER(g); + g->p.x = x0; + g->p.y = y0; + g->p.x1 = x1; + g->p.y1 = y1; + g->p.color = color; + line_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispClear(color_t color) { +void gdispGClear(GDisplay *g, color_t color) { // Note - clear() ignores the clipping area. It clears the screen. - MUTEX_ENTER(); + MUTEX_ENTER(g); #if GDISP_HARDWARE_CLEARS // Best is hardware accelerated clear - GC->p.color = color; - gdisp_lld_clear(GC); + g->p.color = color; + gdisp_lld_clear(g); #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(GC); + g->p.x = g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + g->p.color = color; + gdisp_lld_fill_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is streaming uint32_t area; - GC->p.x = GC->p.y = 0; - GC->p.cx = GC->g.Width; - GC->p.cy = GC->g.Height; - GC->p.color = color; - area = (uint32_t)GC->p.cx * GC->p.cy; + g->p.x = g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + g->p.color = color; + area = (uint32_t)g->p.cx * g->p.cy; - gdisp_lld_write_start(GC); + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif for(; area; area--) - gdisp_lld_write_color(GC); - gdisp_lld_write_stop(GC); + gdisp_lld_write_color(g); + gdisp_lld_write_stop(g); #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(GC); + g->p.color = color; + for(g->p.y = 0; g->p.y < g->g.Height; g->p.y++) + for(g->p.x = 0; g->p.x < g->g.Width; g->p.x++) + gdisp_lld_draw_pixel(g); #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - MUTEX_ENTER(); - TEST_CLIP_AREA(x,y,cx,cy) { - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - GC->p.color = color; - fillarea(); +void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + MUTEX_ENTER(g); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.color = color; + TEST_CLIP_AREA(g) { + fillarea(g); } - MUTEX_EXIT(); + MUTEX_EXIT(g); } -void gdispBlitAreaEx(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) { - MUTEX_ENTER(); +void gdispGBlitArea(GDisplay *g, 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) { + MUTEX_ENTER(g); #if NEED_CLIPPING - // This is a different cliping to fillarea() as it needs to take into account srcx,srcy - if (x < GC->clipx0) { cx -= GC->clipx0 - x; srcx += GC->clipx0 - x; x = GC->clipx0; } - if (y < GC->clipy0) { cy -= GC->clipy0 - y; srcy += GC->clipy0 - x; y = GC->clipy0; } - if (x+cx > GC->clipx1) cx = GC->clipx1 - x; - if (y+cy > GC->clipy1) cy = GC->clipy1 - y; + // This is a different cliping to fillarea(g) as it needs to take into account srcx,srcy + if (x < g->clipx0) { cx -= g->clipx0 - x; srcx += g->clipx0 - x; x = g->clipx0; } + if (y < g->clipy0) { cy -= g->clipy0 - y; srcy += g->clipy0 - x; y = g->clipy0; } + if (x+cx > g->clipx1) cx = g->clipx1 - x; + if (y+cy > g->clipy1) cy = g->clipy1 - y; if (srcx+cx > srccx) cx = srccx - srcx; - if (cx <= 0 || cy <= 0) { MUTEX_EXIT(); return; } + if (cx <= 0 || cy <= 0) { MUTEX_EXIT(g); return; } #endif #if GDISP_HARDWARE_BITFILLS // Best is hardware bitfills - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - GC->p.x1 = srcx; - GC->p.y1 = srcy; - GC->p.x2 = srccx; - GC->p.ptr = (void *)buffer; - gdisp_lld_blit_area(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.x1 = srcx; + g->p.y1 = srcy; + g->p.x2 = srccx; + g->p.ptr = (void *)buffer; + gdisp_lld_blit_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming @@ -682,21 +729,21 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_write_start(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif - 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_write_color(GC); + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x = x; g->p.x < srcx; g->p.x++) { + g->p.color = *buffer++; + gdisp_lld_write_color(g); } } - gdisp_lld_write_stop(GC); + gdisp_lld_write_stop(g); #elif GDISP_HARDWARE_FILLS // Only slightly better than drawing pixels is to look for runs and use fill area @@ -706,19 +753,19 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - GC->p.cy = 1; - 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.cx) { - GC->p.cx=1; - GC->p.color = *buffer++; - while(GC->p.x+GC->p.cx < srcx && *buffer == GC->p.color) { - GC->p.cx++; + g->p.cy = 1; + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x=x; g->p.x < srcx; g->p.x += g->p.cx) { + g->p.cx=1; + g->p.color = *buffer++; + while(g->p.x+g->p.cx < srcx && *buffer == g->p.color) { + g->p.cx++; buffer++; } - if (GC->p.cx == 1) { - gdisp_lld_draw_pixel(GC); + if (g->p.cx == 1) { + gdisp_lld_draw_pixel(g); } else { - gdisp_lld_fill_area(GC); + gdisp_lld_fill_area(g); } } } @@ -731,135 +778,135 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, srcy = y + cy; srccx -= cx; - 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(GC); + for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { + for(g->p.x=x; g->p.x < srcx; g->p.x++) { + g->p.color = *buffer++; + gdisp_lld_draw_pixel(g); } } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #if GDISP_NEED_CLIP - void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { - MUTEX_ENTER(); + void gdispGSetClip(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { + MUTEX_ENTER(g); #if GDISP_HARDWARE_CLIP // Best is using hardware clipping - GC->p.x = x; - GC->p.y = y; - GC->p.cx = cx; - GC->p.cy = cy; - gdisp_lld_set_clip(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + gdisp_lld_set_clip(g); #else // Worst is using software clipping if (x < 0) { cx += x; x = 0; } if (y < 0) { cy += y; y = 0; } - if (cx <= 0 || cy <= 0 || x >= GC->g.Width || y >= GC->g.Height) { MUTEX_EXIT(); return; } - GC->clipx0 = x; - GC->clipy0 = y; - GC->clipx1 = x+cx; if (GC->clipx1 > GC->g.Width) GC->clipx1 = GC->g.Width; - GC->clipy1 = y+cy; if (GC->clipy1 > GC->g.Height) GC->clipy1 = GC->g.Height; + if (cx <= 0 || cy <= 0 || x >= g->g.Width || y >= g->g.Height) { MUTEX_EXIT(g); return; } + g->clipx0 = x; + g->clipy0 = y; + g->clipx1 = x+cx; if (g->clipx1 > g->g.Width) g->clipx1 = g->g.Width; + g->clipy1 = y+cy; if (g->clipy1 > g->g.Height) g->clipy1 = g->g.Height; #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_CIRCLE - void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) { + void gdispGDrawCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color) { coord_t a, b, P; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates a = 1; b = radius; P = 4 - radius; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's circle algorithm // Optimized to prevent double drawing - GC->p.x = x; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x + b; GC->p.y = y; drawpixel_clip(); - GC->p.x = x - b; GC->p.y = y; drawpixel_clip(); + g->p.x = x; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x + b; g->p.y = y; drawpixel_clip(g); + g->p.x = x - b; g->p.y = y; drawpixel_clip(g); do { - GC->p.x = x + a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x + b; GC->p.y = y + a; drawpixel_clip(); - GC->p.x = x - b; GC->p.y = y + a; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x + b; GC->p.y = y - a; drawpixel_clip(); - GC->p.x = x - b; GC->p.y = y - a; drawpixel_clip(); + g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x + b; g->p.y = y + a; drawpixel_clip(g); + g->p.x = x - b; g->p.y = y + a; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x + b; g->p.y = y - a; drawpixel_clip(g); + g->p.x = x - b; g->p.y = y - a; drawpixel_clip(g); if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); - GC->p.x = x + a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x + a; GC->p.y = y - b; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y + b; drawpixel_clip(); - GC->p.x = x - a; GC->p.y = y - b; drawpixel_clip(); + g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); + g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_CIRCLE - void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) { + void gdispGFillCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color) { coord_t a, b, P; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates a = 1; b = radius; P = 4 - radius; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's circle algorithm // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); - GC->p.y = y+b; GC->p.x = x; drawpixel_clip(); - GC->p.y = y-b; GC->p.x = x; drawpixel_clip(); + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + g->p.y = y+b; g->p.x = x; drawpixel_clip(g); + g->p.y = y-b; g->p.x = x; drawpixel_clip(g); do { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); if (P < 0) { P += 3 + 2*a++; } else { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); P += 5 + 2*(a++ - b--); } } while(a < b); - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ELLIPSE - void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { + void gdispGDrawEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { coord_t dx, dy; int32_t a2, b2; int32_t err, e2; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates dx = 0; @@ -867,14 +914,14 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a2 = a*a; b2 = b*b; err = b2-(2*b-1)*a2; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's ellipse algorithm do { - GC->p.x = x + dx; GC->p.y = y + dy; drawpixel_clip(); - GC->p.x = x - dx; GC->p.y = y + dy; drawpixel_clip(); - GC->p.x = x - dx; GC->p.y = y - dy; drawpixel_clip(); - GC->p.x = x + dx; GC->p.y = y - dy; drawpixel_clip(); + g->p.x = x + dx; g->p.y = y + dy; drawpixel_clip(g); + g->p.x = x - dx; g->p.y = y + dy; drawpixel_clip(g); + g->p.x = x - dx; g->p.y = y - dy; drawpixel_clip(g); + g->p.x = x + dx; g->p.y = y - dy; drawpixel_clip(g); e2 = 2*err; if(e2 < (2*dx+1)*b2) { @@ -888,22 +935,22 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, } while(dy >= 0); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ELLIPSE - void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { + void gdispGFillEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { coord_t dx, dy; int32_t a2, b2; int32_t err, e2; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Calculate intermediates dx = 0; @@ -911,7 +958,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a2 = a*a; b2 = b*b; err = b2-(2*b-1)*a2; - GC->p.color = color; + g->p.color = color; // Away we go using Bresenham's ellipse algorithm // This is optimized to prevent overdrawing by drawing a line only when a y is about to change value @@ -922,20 +969,20 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, err += (2*dx+1)*b2; } if(e2 > -(2*dy-1)*a2) { - GC->p.y = y + dy; GC->p.x = x - dx; GC->p.x1 = x + dx; hline_clip(); - if (y) { GC->p.y = y - dy; GC->p.x = x - dx; GC->p.x1 = x + dx; hline_clip(); } + g->p.y = y + dy; g->p.x = x - dx; g->p.x1 = x + dx; hline_clip(g); + if (y) { g->p.y = y - dy; g->p.x = x - dx; g->p.x1 = x + dx; hline_clip(g); } dy--; err -= (2*dy-1)*a2; } } while(dy >= 0); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif @@ -944,7 +991,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #include #endif - void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { + void gdispGDrawArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { coord_t a, b, P, sedge, eedge; uint8_t full, sbit, ebit, tbit; @@ -970,8 +1017,8 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, for(tbit=sbit<<1; tbit < ebit; tbit<<=1) full |= tbit; } - MUTEX_ENTER(); - GC->p.color = color; + MUTEX_ENTER(g); + g->p.color = color; if (full) { // Draw full sectors @@ -979,33 +1026,33 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a = 1; b = radius; P = 4 - radius; - if (full & 0x60) { GC->p.y = y+b; GC->p.x = x; drawpixel_clip(); } - if (full & 0x06) { GC->p.y = y-b; GC->p.x = x; drawpixel_clip(); } - if (full & 0x81) { GC->p.y = y; GC->p.x = x+b; drawpixel_clip(); } - if (full & 0x18) { GC->p.y = y; GC->p.x = x-b; drawpixel_clip(); } + if (full & 0x60) { g->p.y = y+b; g->p.x = x; drawpixel_clip(g); } + if (full & 0x06) { g->p.y = y-b; g->p.x = x; drawpixel_clip(g); } + if (full & 0x81) { g->p.y = y; g->p.x = x+b; drawpixel_clip(g); } + if (full & 0x18) { g->p.y = y; g->p.x = x-b; drawpixel_clip(g); } do { - if (full & 0x01) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if (full & 0x02) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x04) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x08) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if (full & 0x10) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if (full & 0x20) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (full & 0x40) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (full & 0x80) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (full & 0x01) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if (full & 0x02) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x04) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x08) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if (full & 0x10) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if (full & 0x20) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if (full & 0x40) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (full & 0x80) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); - if (full & 0xC0) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (full & 0x0C) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x03) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (full & 0x30) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + if (full & 0xC0) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (full & 0x0C) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x03) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (full & 0x30) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } if (full == 0xFF) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif MUTEX_EXIT; @@ -1032,116 +1079,116 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a = 1; b = radius; P = 4 - radius; - if ((sbit & 0x20) || (ebit & 0x40)) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } - if ((sbit & 0x02) || (ebit & 0x04)) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } - if ((sbit & 0x80) || (ebit & 0x01)) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } - if ((sbit & 0x08) || (ebit & 0x10)) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + if ((sbit & 0x20) || (ebit & 0x40)) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } + if ((sbit & 0x02) || (ebit & 0x04)) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } + if ((sbit & 0x80) || (ebit & 0x01)) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } + if ((sbit & 0x08) || (ebit & 0x10)) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } do { - if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if (((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if (((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge) || ((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge) || ((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge) || ((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge) || ((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } else if (end < start) { // Draw start/end sector where it is a non-internal angle // Optimized to prevent double drawing a = 1; b = radius; P = 4 - radius; - if (sbit & 0x60) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } - if (sbit & 0x06) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } - if (sbit & 0x81) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } - if (sbit & 0x18) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + if (sbit & 0x60) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } + if (sbit & 0x06) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } + if (sbit & 0x81) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } + if (sbit & 0x18) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } do { - if ((sbit & 0x01) && (a >= sedge || a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if ((sbit & 0x02) && (a <= sedge || a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if ((sbit & 0x04) && (a >= sedge || a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if ((sbit & 0x08) && (a <= sedge || a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if ((sbit & 0x10) && (a >= sedge || a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if ((sbit & 0x20) && (a <= sedge || a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if ((sbit & 0x40) && (a >= sedge || a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if ((sbit & 0x80) && (a <= sedge || a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if ((sbit & 0x01) && (a >= sedge || a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if ((sbit & 0x02) && (a <= sedge || a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if ((sbit & 0x04) && (a >= sedge || a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if ((sbit & 0x08) && (a <= sedge || a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if ((sbit & 0x10) && (a >= sedge || a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if ((sbit & 0x20) && (a <= sedge || a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if ((sbit & 0x40) && (a >= sedge || a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if ((sbit & 0x80) && (a <= sedge || a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); if (((sbit & 0x04) && (a >= sedge || a <= eedge)) || ((sbit & 0x08) && (a <= sedge || a >= eedge))) - { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x40) && (a >= sedge || a <= eedge)) || ((sbit & 0x80) && (a <= sedge || a >= eedge))) - { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } if (((sbit & 0x01) && (a >= sedge || a <= eedge)) || ((sbit & 0x02) && (a <= sedge || a >= eedge))) - { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x10) && (a >= sedge || a <= eedge)) || ((sbit & 0x20) && (a <= sedge || a >= eedge))) - { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } else { // Draw start/end sector where it is a internal angle // Optimized to prevent double drawing a = 1; b = radius; P = 4 - radius; - if (((sbit & 0x20) && !eedge) || ((sbit & 0x40) && !sedge)) { GC->p.x = x; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x02) && !eedge) || ((sbit & 0x04) && !sedge)) { GC->p.x = x; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x80) && !eedge) || ((sbit & 0x01) && !sedge)) { GC->p.x = x+b; GC->p.y = y; drawpixel_clip(); } - if (((sbit & 0x08) && !eedge) || ((sbit & 0x10) && !sedge)) { GC->p.x = x-b; GC->p.y = y; drawpixel_clip(); } + if (((sbit & 0x20) && !eedge) || ((sbit & 0x40) && !sedge)) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x02) && !eedge) || ((sbit & 0x04) && !sedge)) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x80) && !eedge) || ((sbit & 0x01) && !sedge)) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } + if (((sbit & 0x08) && !eedge) || ((sbit & 0x10) && !sedge)) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } do { - if (((sbit & 0x01) && a >= sedge && a <= eedge)) { GC->p.x = x+b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x02) && a <= sedge && a >= eedge)) { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x04) && a >= sedge && a <= eedge)) { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } - if (((sbit & 0x08) && a <= sedge && a >= eedge)) { GC->p.x = x-b; GC->p.y = y-a; drawpixel_clip(); } - if (((sbit & 0x10) && a >= sedge && a <= eedge)) { GC->p.x = x-b; GC->p.y = y+a; drawpixel_clip(); } - if (((sbit & 0x20) && a <= sedge && a >= eedge)) { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x40) && a >= sedge && a <= eedge)) { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } - if (((sbit & 0x80) && a <= sedge && a >= eedge)) { GC->p.x = x+b; GC->p.y = y+a; drawpixel_clip(); } + if (((sbit & 0x01) && a >= sedge && a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x02) && a <= sedge && a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x04) && a >= sedge && a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } + if (((sbit & 0x08) && a <= sedge && a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } + if (((sbit & 0x10) && a >= sedge && a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } + if (((sbit & 0x20) && a <= sedge && a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x40) && a >= sedge && a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } + if (((sbit & 0x80) && a <= sedge && a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } if (P < 0) P += 3 + 2*a++; else P += 5 + 2*(a++ - b--); } while(a < b); if (((sbit & 0x04) && a >= sedge && a <= eedge) || ((sbit & 0x08) && a <= sedge && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x40) && a >= sedge && a <= eedge) || ((sbit & 0x80) && a <= sedge && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } if (((sbit & 0x01) && a >= sedge && a <= eedge) || ((sbit & 0x02) && a <= sedge && a >= eedge)) - { GC->p.x = x+a; GC->p.y = y-b; drawpixel_clip(); } + { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } if (((sbit & 0x10) && a >= sedge && a <= eedge) || ((sbit & 0x20) && a <= sedge && a >= eedge)) - { GC->p.x = x-a; GC->p.y = y+b; drawpixel_clip(); } + { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ARC - void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { + void gdispGFillArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { coord_t a, b, P; coord_t sy, ey; fixed sxa, sxb, sxd, exa, exb, exd; uint8_t qtr; - MUTEX_ENTER(); + MUTEX_ENTER(g); // Do the trig to get the formulas for the start and end lines. sxa = exa = FIXED(x)+FIXED0_5; @@ -1170,7 +1217,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, a = 1; b = radius; P = 4 - radius; - GC->p.color = color; + g->p.color = color; sxb += sxa; exb += exa; @@ -1181,50 +1228,50 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 0: // S2E2 sy <= ey case 1: // S1E2 sy <= ey if (ey && sy) { - GC->p.x = x; GC->p.x1 = x; // E2S + g->p.x = x; g->p.x1 = x; // E2S sxa -= sxd; exa -= exd; } else if (sy) { - GC->p.x = x-b; GC->p.x1 = x; // C2S + g->p.x = x-b; g->p.x1 = x; // C2S sxa -= sxd; } else if (ey) { - GC->p.x = x; GC->p.x1 = x+b; // E2C + g->p.x = x; g->p.x1 = x+b; // E2C exa -= exd; } else { - GC->p.x = x-b; GC->p.x1 = x+b; // C2C + g->p.x = x-b; g->p.x1 = x+b; // C2C } - GC->p.y = y; - hline_clip(); + g->p.y = y; + hline_clip(g); do { if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S sxa -= sxd; exa -= exd; } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S sxa -= sxd; } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = NONFIXED(sxb); hline_clip(); // E2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = NONFIXED(sxb); hline_clip(g); // E2S sxb += sxd; exb += exd; } else if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S sxb += sxd; } else if (qtr & 1) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; @@ -1236,92 +1283,92 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 19: // S4E2 sy > ey case 22: // S3E1 sy > ey case 23: // S4E1 sy > ey - GC->p.y = y; GC->p.x = x; GC->p.x1 = x+b; hline_clip(); // SE2C + g->p.y = y; g->p.x = x; g->p.x1 = x+b; hline_clip(g); // SE2C sxa += sxd; exa -= exd; do { if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C exa -= exd; } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C exb += exd; } else if (!(qtr & 4)) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; } else if (!(qtr & 1)) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+a; hline_clip(g); // S2C } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+a; hline_clip(g); // C2C } break; case 4: // S2E1 sy <= ey case 5: // S1E1 sy <= ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C do { if (-a >= ey) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C sxa -= sxd; exa -= exd; } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S sxa -= sxd; } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (P < 0) { P += 3 + 2*a++; } else { if (-b >= ey) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C sxb += sxd; exb += exd; } else if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S sxb += sxd; } else if (qtr & 1) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= ey) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C break; case 8: // S2E3 sy <= ey @@ -1332,261 +1379,261 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 25: // S1E3 sy > ey case 28: // S2E3 sy > ey case 29: // S1E3 sy > ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x; hline_clip(); // C2SE + g->p.y = y; g->p.x = x-b; g->p.x1 = x; hline_clip(g); // C2SE sxa -= sxd; exa += exd; do { if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S sxa -= sxd; } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E exa += exd; } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S sxb += sxd; } else if (qtr & 1) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E exb -= exd; } else if (qtr & 4) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S } else if (qtr & 1) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+a; hline_clip(g); // C2C } break; case 10: // S3E3 sy <= ey case 14: // S3E4 sy <= ey - GC->p.y = y; GC->p.x = x; drawpixel_clip(); // S2E + g->p.y = y; g->p.x = x; drawpixel_clip(g); // S2E sxa += sxd; exa += exd; do { if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g); // S2E sxa += sxd; exa += exd; } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E exa += exd; } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = NONFIXED(exb); hline_clip(); // S2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = NONFIXED(exb); hline_clip(g); // S2E sxb -= sxd; exb -= exd; } else if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E exb -= exd; } else if (qtr & 4) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g); // S2E } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; case 11: // S4E3 sy <= ey case 15: // S4E4 sy <= ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C do { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= sy) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; exa += exd; } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E exa += exd; } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C if (b <= sy) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; exb -= exd; } else if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E exb -= exd; } else if (qtr & 4) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= sy) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E } else if (qtr & 4) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; case 16: // S2E2 sy > ey case 20: // S2E1 sy > ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C sxa -= sxd; exa -= exd; do { if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C sxa -= sxd; exa -= exd; } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C exa -= exd; } else if (!(qtr & 4)){ - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (P < 0) { P += 3 + 2*a++; } else { if (-b >= sy) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = NONFIXED(sxb); hline_clip(); // C2S - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g); // C2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C sxb += sxd; exb += exd; } else if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C exb += exd; } else if (!(qtr & 4)){ - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= sy) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = NONFIXED(sxa); hline_clip(); // C2S - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g); // C2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (!(qtr & 4)){ - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C break; case 17: // S1E2 sy > ey case 21: // S1E1 sy > ey if (sy) { - GC->p.x = x; GC->p.x1 = x; // E2S + g->p.x = x; g->p.x1 = x; // E2S sxa -= sxd; exa -= exd; } else { - GC->p.x = x; GC->p.x1 = x+b; // E2C + g->p.x = x; g->p.x1 = x+b; // E2C exa -= exd; } - GC->p.y = y; - hline_clip(); + g->p.y = y; + hline_clip(g); do { if (-a >= sy) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S sxa -= sxd; exa -= exd; } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C exa -= exd; } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (-b >= sy) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = NONFIXED(sxb); hline_clip(); // E2S + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = NONFIXED(sxb); hline_clip(g); // E2S sxb += sxd; exb += exd; } else if (-b >= ey) { - GC->p.y = y-b; GC->p.x = NONFIXED(exb); GC->p.x1 = x+a; hline_clip(); // E2C + g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g); // E2C exb += exd; } else if (!(qtr & 4)) { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (-a >= sy) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = NONFIXED(sxa); hline_clip(); // E2S + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g); // E2S } else if (-a >= ey) { - GC->p.y = y-a; GC->p.x = NONFIXED(exa); GC->p.x1 = x+b; hline_clip(); // E2C + g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g); // E2C } else if (!(qtr & 4)) { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; case 26: // S3E3 sy > ey case 27: // S4E3 sy > ey - GC->p.y = y; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C do { - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; exa += exd; } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { - GC->p.y = y-b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C if (b <= ey) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = NONFIXED(exb); hline_clip(); // C2E - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g); // C2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; exb -= exd; } else if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; } else if (!(qtr & 1)) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); - GC->p.y = y-a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C if (a <= ey) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = NONFIXED(exa); hline_clip(); // C2E - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g); // C2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (!(qtr & 4)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; @@ -1594,52 +1641,52 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, case 31: // S4E4 sy > ey do { if (a <= ey) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = NONFIXED(exa); hline_clip(); // S2E + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g); // S2E sxa += sxd; exa += exd; } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C sxa += sxd; } else if (!(qtr & 1)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } if (P < 0) { P += 3 + 2*a++; } else { if (b <= ey) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = NONFIXED(exb); hline_clip(); // S2E + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = NONFIXED(exb); hline_clip(g); // S2E sxb -= sxd; exb -= exd; } else if (b <= sy) { - GC->p.y = y+b; GC->p.x = NONFIXED(sxb); GC->p.x1 = x+a; hline_clip(); // S2C + g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g); // S2C sxb -= sxd; } else if (!(qtr & 1)) { - GC->p.y = y+b; GC->p.x = x-a; GC->p.x1 = x+a; hline_clip(); // C2C + g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); // C2C } P += 5 + 2*(a++ - b--); } } while(a < b); if (a <= ey) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (a <= sy) { - GC->p.y = y+a; GC->p.x = NONFIXED(sxa); GC->p.x1 = x+b; hline_clip(); // S2C + g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g); // S2C } else if (!(qtr & 4)) { - GC->p.y = y+a; GC->p.x = x-b; GC->p.x1 = x+b; hline_clip(); // C2C + g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); // C2C } break; } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_ARC - void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { + void gdispGDrawRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { if (2*radius > cx || 2*radius > cy) { gdispDrawBox(x, y, cx, cy, color); return; @@ -1656,7 +1703,7 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #endif #if GDISP_NEED_ARC - void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { + void gdispGFillRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { coord_t radius2; radius2 = radius*2; @@ -1675,49 +1722,49 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #endif #if GDISP_NEED_PIXELREAD - color_t gdispGetPixelColor(coord_t x, coord_t y) { + color_t gdispGGetPixelColor(GDisplay *g, coord_t x, coord_t y) { color_t c; /* Always synchronous as it must return a value */ - MUTEX_ENTER(); + MUTEX_ENTER(g); #if GDISP_HARDWARE_PIXELREAD // Best is direct pixel read - GC->p.x = x; - GC->p.y = y; - c = gdisp_lld_get_pixel_color(GC); + g->p.x = x; + g->p.y = y; + c = gdisp_lld_get_pixel_color(g); #elif 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_read_start(GC); - c = gdisp_lld_read_color(GC); - gdisp_lld_read_stop(GC); + g->p.x = x; + g->p.y = y; + g->p.cx = 1; + g->p.cy = 1; + gdisp_lld_read_start(g); + c = gdisp_lld_read_color(g); + gdisp_lld_read_stop(g); #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(); + MUTEX_EXIT(g); return c; } #endif #if GDISP_NEED_SCROLL - void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { + void gdispGVerticalScroll(GDisplay *g, 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(); + MUTEX_ENTER(g); #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 (!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; + if (x < g->clipx0) { cx -= g->clipx0 - x; x = g->clipx0; } + if (y < g->clipy0) { cy -= g->clipy0 - y; y = g->clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= g->clipx1 || y >= g->clipy1) { MUTEX_EXIT(g); return; } + if (x+cx > g->clipx1) cx = g->clipx1 - x; + if (y+cy > g->clipy1) cy = g->clipy1 - y; #endif abslines = lines < 0 ? -lines : lines; @@ -1726,13 +1773,13 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, 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); + g->p.x = x; + g->p.y = y; + g->p.cx = cx; + g->p.cy = cy; + g->p.y1 = lines; + g->p.color = bgcolor; + gdisp_lld_vertical_scroll(g); 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." @@ -1759,20 +1806,20 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, // Read one line of data from the screen #if 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_read_start(GC); + g->p.x = x+ix; + g->p.y = fy+lines; + g->p.cx = fx; + g->p.cy = 1; + gdisp_lld_read_start(g); for(j=0; j < fx; j++) - GC->linebuf[j] = gdisp_lld_read_color(GC); - gdisp_lld_read_stop(GC); + g->linebuf[j] = gdisp_lld_read_color(g); + gdisp_lld_read_stop(g); #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); + g->p.x = x+ix+j; + g->p.y = fy+lines; + g->linebuf[j] = gdisp_lld_get_pixel_color(g); } #else // Worst is "not possible" @@ -1782,36 +1829,36 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, // 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); + g->p.x = x+ix; + g->p.y = fy; + g->p.cx = fx; + g->p.cy = 1; + g->p.x1 = 0; + g->p.y1 = 0; + g->p.x2 = fx; + g->p.ptr = (void *)g->linebuf; + gdisp_lld_blit_area(g); #elif GDISP_HARDWARE_STREAM_WRITE // Next best is hardware streaming - GC->p.x = x+ix; - GC->p.y = fy; - GC->p.cx = fx; - GC->p.cy = 1; - gdisp_lld_write_start(GC); + g->p.x = x+ix; + g->p.y = fy; + g->p.cx = fx; + g->p.cy = 1; + gdisp_lld_write_start(g); #if GDISP_HARDWARE_STREAM_POS - gdisp_lld_write_pos(GC); + gdisp_lld_write_pos(g); #endif for(j = 0; j < fx; j++) { - GC->p.color = GC->linebuf[j]; - gdisp_lld_write_color(GC); + g->p.color = g->linebuf[j]; + gdisp_lld_write_color(g); } - gdisp_lld_write_stop(GC); + gdisp_lld_write_stop(g); #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); + g->p.y = fy; + for(g->p.x = x+ix, j = 0; j < fx; g->p.x++, j++) { + g->p.color = g->linebuf[j]; + gdisp_lld_draw_pixel(g); } #endif } @@ -1820,45 +1867,45 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, } /* fill the remaining gap */ - GC->p.x = x; - GC->p.y = lines > 0 ? (y+cy) : y; - GC->p.cx = cx; - GC->p.cy = abslines; - GC->p.color = bgcolor; - fillarea(); - MUTEX_EXIT(); + g->p.x = x; + g->p.y = lines > 0 ? (y+cy) : y; + g->p.cx = cx; + g->p.cy = abslines; + g->p.color = bgcolor; + fillarea(g); + MUTEX_EXIT(g); } #endif #if GDISP_NEED_CONTROL #if GDISP_HARDWARE_CONTROL - void gdispControl(unsigned what, void *value) { - MUTEX_ENTER(); - GC->p.x = what; - GC->p.ptr = value; - gdisp_lld_control(GC); + void gdispGControl(GDisplay *g, unsigned what, void *value) { + MUTEX_ENTER(g); + g->p.x = what; + g->p.ptr = value; + gdisp_lld_control(g); #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION if (what == GDISP_CONTROL_ORIENTATION) { #if GDISP_HARDWARE_CLIP // Best is hardware clipping - GC->p.x = 0; - GC->p.y = 0; - GC->p.cx = GC->g.Width; - GC->p.cy = GC->g.Height; - gdisp_lld_set_clip(GC); + g->p.x = 0; + g->p.y = 0; + g->p.cx = g->g.Width; + g->p.cy = g->g.Height; + gdisp_lld_set_clip(g); #else // Worst is software clipping - GC->clipx0 = 0; - GC->clipy0 = 0; - GC->clipx1 = GC->g.Width; - GC->clipy1 = GC->g.Height; + g->clipx0 = 0; + g->clipy0 = 0; + g->clipx1 = g->g.Width; + g->clipy1 = g->g.Height; #endif } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #else - void gdispControl(unsigned what, void *value) { + void gdispGControl(GDisplay *g, unsigned what, void *value) { (void)what; (void)value; /* Ignore everything */ @@ -1868,17 +1915,17 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, #if GDISP_NEED_QUERY #if GDISP_HARDWARE_QUERY - void *gdispQuery(unsigned what) { + void *gdispGQuery(GDisplay *g, unsigned what) { void *res; - MUTEX_ENTER(); - GC->p.x = (coord_t)what; - res = gdisp_lld_query(GC); - MUTEX_EXIT(); + MUTEX_ENTER(g); + g->p.x = (coord_t)what; + res = gdisp_lld_query(g); + MUTEX_EXIT(g); return res; } #else - void *gdispQuery(unsigned what) { + void *gdispGQuery(GDisplay *g, unsigned what) { (void) what; return (void *)-1; } @@ -1889,63 +1936,63 @@ void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, /* High Level Driver Routines. */ /*===========================================================================*/ -void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { +void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { if (cx <= 0 || cy <= 0) return; cx = x+cx-1; cy = y+cy-1; // cx, cy are now the end point. - MUTEX_ENTER(); + MUTEX_ENTER(g); - GC->p.color = color; + g->p.color = color; if (cx - x > 2) { - GC->p.x = x; GC->p.y = y; GC->p.x1 = cx; hline_clip(); + g->p.x = x; g->p.y = y; g->p.x1 = cx; hline_clip(g); if (y != cy) { - GC->p.x = x; GC->p.y = cy; GC->p.x1 = cx; hline_clip(); + g->p.x = x; g->p.y = cy; g->p.x1 = cx; hline_clip(g); if (cy - y > 2) { y++; cy--; - GC->p.x = x; GC->p.y = y; GC->p.y1 = cy; vline_clip(); - GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + g->p.x = x; g->p.y = y; g->p.y1 = cy; vline_clip(g); + g->p.x = cx; g->p.y = y; g->p.y1 = cy; vline_clip(g); } } } else { - GC->p.x = x; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + g->p.x = x; g->p.y = y; g->p.y1 = cy; vline_clip(g); if (x != cx) { - GC->p.x = cx; GC->p.y = y; GC->p.y1 = cy; vline_clip(); + g->p.x = cx; g->p.y = y; g->p.y1 = cy; vline_clip(g); } } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } #if GDISP_NEED_CONVEX_POLYGON - void gdispDrawPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { + void gdispGDrawPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { const point *epnt, *p; epnt = &pntarray[cnt-1]; - MUTEX_ENTER(); - GC->p.color = color; + MUTEX_ENTER(g); + g->p.color = color; for(p = pntarray; p < epnt; p++) { - GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+p[1].x; GC->p.y1=ty+p[1].y; line_clip(); + g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+p[1].x; g->p.y1=ty+p[1].y; line_clip(g); } - GC->p.x=tx+p->x; GC->p.y=ty+p->y; GC->p.x1=tx+pntarray->x; GC->p.y1=ty+pntarray->y; line_clip(); + g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+pntarray->x; g->p.y1=ty+pntarray->y; line_clip(g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { + void gdispGFillConvexPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { const point *lpnt, *rpnt, *epnts; fixed lx, rx, lk, rk; coord_t y, ymax, lxc, rxc; @@ -1975,8 +2022,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { lk = (FIXED(lpnt->x) - lx) / (lpnt->y - y); rk = (FIXED(rpnt->x) - rx) / (rpnt->y - y); - MUTEX_ENTER(); - GC->p.color = color; + MUTEX_ENTER(g); + g->p.color = color; while(1) { /* Determine our boundary */ ymax = rpnt->y < lpnt->y ? rpnt->y : lpnt->y; @@ -1991,9 +2038,9 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { * of pixels. */ if (lxc < rxc) { - GC->p.x=tx+lxc; GC->p.y=ty+y; GC->p.x1=tx+rxc-1; hline_clip(); + g->p.x=tx+lxc; g->p.y=ty+y; g->p.x1=tx+rxc-1; hline_clip(g); } else if (lxc > rxc) { - GC->p.x=tx+rxc; GC->p.y=ty+y; GC->p.x1=tx+lxc-1; hline_clip(); + g->p.x=tx+rxc; g->p.y=ty+y; g->p.x1=tx+lxc-1; hline_clip(g); } lx += lk; @@ -2002,12 +2049,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { if (!cnt) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return; } cnt--; @@ -2017,12 +2064,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { for (lpnt = lpnt <= pntarray ? epnts : lpnt-1; lpnt->y == y; cnt--) { if (!cnt) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return; } lx = FIXED(lpnt->x); @@ -2033,12 +2080,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { if (!cnt) { #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); return; } rx = FIXED(rpnt->x); @@ -2055,27 +2102,27 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { #if GDISP_NEED_ANTIALIAS && GDISP_HARDWARE_PIXELREAD static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - #define GD ((GDISPDriver *)state) + #define GD ((GDisplay *)state) if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; - hline_clip(); + hline_clip(g); } else { for (; count; count--, x++) { GD->p.x = x; GD->p.y = y; GD->p.color = gdispBlendColor(GD->t.color, gdisp_lld_get_pixel_color(GD), alpha); - drawpixel_clip(); + drawpixel_clip(g); } } #undef GD } #else static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - #define GD ((GDISPDriver *)state) + #define GD ((GDisplay *)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 GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; - hline_clip(); + hline_clip(g); } #undef GD } @@ -2083,7 +2130,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { #if GDISP_NEED_ANTIALIAS static void fillcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { - #define GD ((GDISPDriver *)state) + #define GD ((GDisplay *)state) if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return; if (alpha == 255) { GD->p.color = GD->t.color; @@ -2091,7 +2138,7 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { GD->p.color = gdispBlendColor(GD->t.color, GD->t.bgcolor, alpha); } GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; - hline_clip(); + hline_clip(g); #undef GD } #else @@ -2100,110 +2147,110 @@ 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) { - return mf_render_character(GC->t.font, x, y, ch, drawcharline, state); + return mf_render_character(g->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) { - return mf_render_character(GC->t.font, x, y, ch, fillcharline, state); + return mf_render_character(g->t.font, x, y, ch, fillcharline, state); } - void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { - MUTEX_ENTER(); - GC->t.font = font; - GC->t.clipx0 = x; - GC->t.clipy0 = y; - 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, GC); + void gdispGDrawChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { + MUTEX_ENTER(g); + g->t.font = font; + g->t.clipx0 = x; + g->t.clipy0 = y; + g->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x; + g->t.clipy1 = y + font->height; + g->t.color = color; + mf_render_character(font, x, y, c, drawcharline, g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { - MUTEX_ENTER(); - GC->p.cx = mf_character_width(font, c) + font->baseline_x; - GC->p.cy = font->height; - GC->t.font = font; - GC->t.clipx0 = GC->p.x = x; - GC->t.clipy0 = GC->p.y = y; - GC->t.clipx1 = GC->p.x+GC->p.cx; - GC->t.clipy1 = GC->p.y+GC->p.cy; - GC->t.color = color; - GC->t.bgcolor = GC->p.color = bgcolor; + void gdispGFillChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { + MUTEX_ENTER(g); + g->p.cx = mf_character_width(font, c) + font->baseline_x; + g->p.cy = font->height; + g->t.font = font; + g->t.clipx0 = g->p.x = x; + g->t.clipy0 = g->p.y = y; + g->t.clipx1 = g->p.x+g->p.cx; + g->t.clipy1 = g->p.y+g->p.cy; + g->t.color = color; + g->t.bgcolor = g->p.color = bgcolor; - TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { - fillarea(); - mf_render_character(font, x, y, c, fillcharline, GC); + TEST_CLIP_AREA(g) { + fillarea(g); + mf_render_character(font, x, y, c, fillcharline, g); } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color) { - MUTEX_ENTER(); - GC->t.font = font; - GC->t.clipx0 = x; - GC->t.clipy0 = y; - GC->t.clipx1 = x + mf_get_string_width(font, str, 0, 0); - GC->t.clipy1 = y + font->height; - GC->t.color = color; + void gdispGDrawString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color) { + MUTEX_ENTER(g); + g->t.font = font; + g->t.clipx0 = x; + g->t.clipy0 = y; + g->t.clipx1 = x + mf_get_string_width(font, str, 0, 0); + g->t.clipy1 = y + font->height; + g->t.color = color; - mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, GC); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { - MUTEX_ENTER(); - GC->p.cx = mf_get_string_width(font, str, 0, 0); - GC->p.cy = font->height; - GC->t.font = font; - GC->t.clipx0 = GC->p.x = x; - GC->t.clipy0 = GC->p.y = y; - GC->t.clipx1 = GC->p.x+GC->p.cx; - GC->t.clipy1 = GC->p.y+GC->p.cy; - GC->t.color = color; - GC->t.bgcolor = GC->p.color = bgcolor; + void gdispGFillString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { + MUTEX_ENTER(g); + g->p.cx = mf_get_string_width(font, str, 0, 0); + g->p.cy = font->height; + g->t.font = font; + g->t.clipx0 = g->p.x = x; + g->t.clipy0 = g->p.y = y; + g->t.clipx1 = g->p.x+g->p.cx; + g->t.clipy1 = g->p.y+g->p.cy; + g->t.color = color; + g->t.bgcolor = g->p.color = bgcolor; - 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, GC); + TEST_CLIP_AREA(g) { + fillarea(g); + mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, g); } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { - MUTEX_ENTER(); - GC->t.font = font; - GC->t.clipx0 = x; - GC->t.clipy0 = y; - GC->t.clipx1 = x+cx; - GC->t.clipy1 = y+cy; - GC->t.color = color; + void gdispGDrawStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { + MUTEX_ENTER(g); + g->t.font = font; + g->t.clipx0 = x; + g->t.clipy0 = y; + g->t.clipx1 = x+cx; + g->t.clipy1 = y+cy; + g->t.color = color; /* Select the anchor position */ switch(justify) { @@ -2219,33 +2266,33 @@ 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, GC); + mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, g); #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } - void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { - MUTEX_ENTER(); - GC->p.cx = cx; - GC->p.cy = cy; - GC->t.font = font; - GC->t.clipx0 = GC->p.x = x; - GC->t.clipy0 = GC->p.y = y; - GC->t.clipx1 = x+cx; - GC->t.clipy1 = y+cy; - GC->t.color = color; - GC->t.bgcolor = GC->p.color = bgcolor; + void gdispGFillStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { + MUTEX_ENTER(g); + g->p.cx = cx; + g->p.cy = cy; + g->t.font = font; + g->t.clipx0 = g->p.x = x; + g->t.clipy0 = g->p.y = y; + g->t.clipx1 = x+cx; + g->t.clipy1 = y+cy; + g->t.color = color; + g->t.bgcolor = g->p.color = bgcolor; - TEST_CLIP_AREA(GC->p.x, GC->p.y, GC->p.cx, GC->p.cy) { + TEST_CLIP_AREA(g) { // background fill - fillarea(); + fillarea(g); /* Select the anchor position */ switch(justify) { @@ -2262,16 +2309,16 @@ 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, GC); + mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, g); } #if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE - if ((GC->flags & GDISP_FLG_SCRSTREAM)) { - gdisp_lld_write_stop(GC); - GC->flags &= ~GDISP_FLG_SCRSTREAM; + if ((g->flags & GDISP_FLG_SCRSTREAM)) { + gdisp_lld_write_stop(g); + g->flags &= ~GDISP_FLG_SCRSTREAM; } #endif - MUTEX_EXIT(); + MUTEX_EXIT(g); } coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) { diff --git a/src/gfx.c b/src/gfx.c index 92533937..09d0798b 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -71,7 +71,6 @@ void gfxInit(void) { #endif #if GFX_USE_GDISP _gdispInit(); - gdispClear(Black); #endif #if GFX_USE_GWIN _gwinInit();