Multiple displays across one or more controllers is now fully supported.

Only the Win32 driver supports this so far.
Other drivers are currently broken due to API changes and will be fixed.
ugfx_release_2.6
inmarket 2013-10-12 13:24:40 +10:00
parent b3ee216bd2
commit d22bc07e7a
11 changed files with 1862 additions and 1428 deletions

View File

@ -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 <stdio.h>
@ -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
static coord_t mousex, mousey;
static uint16_t mousebuttons;
coord_t mousex, mousey;
uint16_t mousebuttons;
#endif
#if GINPUT_NEED_TOGGLE
static uint8_t toggles = 0;
uint8_t toggles;
#endif
} winPriv;
static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
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;
#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) < wHeight) {
mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
goto mousemove;
}
#endif
// Handle mouse down on the toggle area
#if GINPUT_NEED_TOGGLE
bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth);
toggles ^= bit;
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 = wWidth;
rect.top = wHeight;
rect.bottom = wHeight + WIN32_BUTTON_AREA;
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 ((toggles & 0x0F)) {
toggles &= ~0x0F;
if ((g->flags & GDISP_FLG_HASTOGGLE)) {
if ((priv->toggles & 0x0F)) {
priv->toggles &= ~0x0F;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;
rect.bottom = wHeight + WIN32_BUTTON_AREA;
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) < wHeight) {
mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
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:
if ((coord_t)HIWORD(lParam) < wHeight) {
mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
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_MBUTTONUP:
if ((coord_t)HIWORD(lParam) < wHeight) {
mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
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:
if ((coord_t)HIWORD(lParam) < wHeight) {
mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
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:
if ((coord_t)HIWORD(lParam) < wHeight) {
mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
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:
if ((coord_t)HIWORD(lParam) >= wHeight)
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:
mousex = (coord_t)LOWORD(lParam);
mousey = (coord_t)HIWORD(lParam);
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,75 +301,76 @@ 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)) {
// 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);
return msg.wParam;
@ -287,44 +380,89 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) {
/* Driver exported functions. */
/*===========================================================================*/
LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
RECT rect;
LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
winPriv * priv;
char buf[132];
// Initialise the window thread and the window class (if it hasn't been done already)
if (!QReady) {
gfxThreadHandle hth;
WNDCLASS wc;
/* 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;
// Create the draw mutex
drawMutex = CreateMutex(NULL, FALSE, NULL);
/* Initialise the window */
if (!(hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0))) {
fprintf(stderr, "Cannot create window thread\n");
exit(-1);
}
// Create the thread
hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0);
assert(hth != NULL);
gfxThreadClose(hth);
while (!isReady)
Sleep(1);
/* Initialise the GDISP structure to match */
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);
}
// 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;
LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
winPriv * priv;
pixel_t * buffer;
#if GDISP_NEED_CONTROL
RECT rect;
pixel_t * srcimg;
#endif
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 */

View File

@ -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 */

View File

@ -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_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
@ -34,6 +41,8 @@
#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 */
#endif /* _GINPUT_LLD_TOGGLE_CONFIG_H */

View File

@ -22,6 +22,11 @@
/* Driver hardware support. */
/*===========================================================================*/
#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

View File

@ -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

View File

@ -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,7 +165,13 @@ extern GDISPControl *GDISP;
/* Defines relating to the display hardware */
/*===========================================================================*/
#if GDISP_MULTIPLE_DRIVERS || defined(__DOXYGEN__)
#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
* @{
@ -160,7 +181,7 @@ extern GDISPControl *GDISP;
* @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
* @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:
@ -207,18 +228,6 @@ extern GDISPControl *GDISP;
#define GDISP_PACKED_LINES FALSE
#endif
/** @} */
#else
#include "gdisp_lld_config.h"
#ifndef GDISP_PIXELFORMAT
#define GDISP_PIXELFORMAT GDISP_LLD_PIXELFORMAT
#endif
#ifndef GDISP_PACKED_PIXELS
#define GDISP_PACKED_PIXELS FALSE
#endif
#ifndef GDISP_PACKED_LINES
#define GDISP_PACKED_LINES FALSE
#endif
#endif
/*===========================================================================*/
/* Defines related to the pixel format */
@ -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] 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] 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] 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] 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,6 +658,7 @@ 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] 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)
@ -609,7 +666,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
*
* @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
}

View File

@ -18,16 +18,10 @@
#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
* @{
@ -139,19 +133,21 @@
#define GDISP_HARDWARE_CLIP FALSE
#endif
/** @} */
#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

View File

@ -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
/**
* @}
*

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -71,7 +71,6 @@ void gfxInit(void) {
#endif
#if GFX_USE_GDISP
_gdispInit();
gdispClear(Black);
#endif
#if GFX_USE_GWIN
_gwinInit();