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();