LLDSPEC void gdisp_lld_fill_area(GDisplay *g) { coord_t sy, ey; coord_t sx, ex; coord_t col; unsigned spage, zpages; uint8_t * base; uint8_t mask; switch(g->g.Orientation) { default: case GDISP_ROTATE_0: sx = g->p.x; ex = g->p.x + g->p.cx - 1; sy = g->p.y; ey = sy + g->p.cy - 1; break; case GDISP_ROTATE_90: sx = g->p.y; ex = g->p.y + g->p.cy - 1; sy = GDISP_SCREEN_HEIGHT - g->p.x - g->p.cx; ey = GDISP_SCREEN_HEIGHT-1 - g->p.x; break; case GDISP_ROTATE_180: sx = GDISP_SCREEN_WIDTH - g->p.x - g->p.cx; ex = GDISP_SCREEN_WIDTH-1 - g->p.x; sy = GDISP_SCREEN_HEIGHT - g->p.y - g->p.cy; ey = GDISP_SCREEN_HEIGHT-1 - g->p.y; break; case GDISP_ROTATE_270: sx = GDISP_SCREEN_WIDTH - g->p.y - g->p.cy; ex = GDISP_SCREEN_WIDTH-1 - g->p.y; sy = g->p.x; ey = g->p.x + g->p.cx - 1; break; } spage = sy / 8; base = RAM(g) + SSD1306_PAGE_OFFSET + SSD1306_PAGE_WIDTH * spage; mask = 0xff << (sy&7); zpages = (ey / 8) - spage; if (gdispColor2Native(g->p.color) == gdispColor2Native(Black)) { while (zpages--) { for (col = sx; col <= ex; col++) base[col] &= ~mask; mask = 0xff; base += SSD1306_PAGE_WIDTH; } mask &= (0xff >> (7 - (ey&7))); for (col = sx; col <= ex; col++) base[col] &= ~mask; } else { while (zpages--) {
LLDSPEC void gdisp_lld_write_color(GDisplay *g) { LLDCOLOR_TYPE c; c = gdispColor2Native(g->p.color); write_data(g, c >> 8); write_data(g, c & 0xFF); }
LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g) { unsigned pos; #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: default: pos = PIXIL_POS(g, g->p.x, g->p.y); break; case GDISP_ROTATE_90: pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-1); break; case GDISP_ROTATE_180: pos = PIXIL_POS(g, g->g.Width-g->p.x-1, g->g.Height-g->p.y-1); break; case GDISP_ROTATE_270: pos = PIXIL_POS(g, g->g.Height-g->p.y-1, g->p.x); break; } #else pos = PIXIL_POS(g, g->p.x, g->p.y); #endif #if LTDC_USE_DMA2D while(DMA2D->CR & DMA2D_CR_START); #endif PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color); }
LLDSPEC void gdisp_lld_blit_area(GDisplay *g) { netPriv * priv; pixel_t * buffer; uint16_t buf[5]; coord_t x, y; #if GDISP_DONT_WAIT_FOR_NET_DISPLAY if (!(g->flags & GDISP_FLG_CONNECTED)) return; #else while(!(g->flags & GDISP_FLG_CONNECTED)) gfxSleepMilliseconds(200); #endif // Make everything relative to the start of the line buffer = g->p.ptr; buffer += g->p.x2*g->p.y1; priv = g->priv; buf[0] = GNETCODE_BLIT; buf[1] = g->p.x; buf[2] = g->p.y; buf[3] = g->p.cx; buf[4] = g->p.cy; MUTEX_ENTER; sendpkt(priv->netfd, buf, 5); for(y = 0; y < g->p.cy; y++, buffer += g->p.x2 - g->p.cx) { for(x = 0; x < g->p.cx; x++, buffer++) { buf[0] = gdispColor2Native(buffer[0]); sendpkt(priv->netfd, buf, 1); } } MUTEX_EXIT; }
LLDSPEC void gdisp_lld_fill_area(GDisplay *g) { uint16_t c; c = gdispColor2Native(g->p.color); acquire_bus(g); set_viewport(g); set_cursor(g); dma_with_noinc(g, &c, g->p.cx*g->p.cy); release_bus(g); }
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { winPriv * priv; int x, y; COLORREF color; priv = g->priv; color = gdispColor2Native(g->p.color); #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: default: x = g->p.x; y = g->p.y; break; case GDISP_ROTATE_90: x = g->p.y; y = g->g.Width - 1 - g->p.x; break; case GDISP_ROTATE_180: x = g->g.Width - 1 - g->p.x; y = g->g.Height - 1 - g->p.y; break; case GDISP_ROTATE_270: x = g->g.Height - 1 - g->p.y; y = g->p.x; break; } #else x = g->p.x; y = g->p.y; #endif // Draw the pixel on the screen and in the buffer. WaitForSingleObject(drawMutex, INFINITE); SetPixel(priv->dcBuffer, x, y, color); #if GDISP_WIN32_USE_INDIRECT_UPDATE ReleaseMutex(drawMutex); { RECT r; r.left = x; r.right = x+1; r.top = y; r.bottom = 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 }
LLDSPEC void gdisp_lld_fill_area(GDisplay* g) { #if GDISP_NO_DMA_FROM_STACK static LLDCOLOR_TYPE c; #else LLDCOLOR_TYPE c; #endif c = gdispColor2Native(g->p.color); acquire_bus(g); set_viewport(g); set_cursor(g); dma_with_noinc(g, &c, g->p.cx * g->p.cy); release_bus(g); }
// Uses p.x,p.y p.cx,p.cy p.color LLDSPEC void gdisp_lld_fill_area(GDisplay* g) { uint32_t pos; uint32_t lineadd; uint32_t shape; // Wait until DMA2D is ready while(DMA2D->CR & DMA2D_CR_START); #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: default: pos = PIXIL_POS(g, g->p.x, g->p.y); lineadd = g->g.Width - g->p.cx; shape = (g->p.cx << 16) | (g->p.cy); break; case GDISP_ROTATE_90: pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-g->p.cx); lineadd = g->g.Height - g->p.cy; shape = (g->p.cy << 16) | (g->p.cx); break; case GDISP_ROTATE_180: pos = PIXIL_POS(g, g->g.Width-g->p.x-g->p.cx, g->g.Height-g->p.y-g->p.cy); lineadd = g->g.Width - g->p.cx; shape = (g->p.cx << 16) | (g->p.cy); break; case GDISP_ROTATE_270: pos = PIXIL_POS(g, g->g.Height-g->p.y-g->p.cy, g->p.x); lineadd = g->g.Height - g->p.cy; shape = (g->p.cy << 16) | (g->p.cx); break; } #else pos = PIXIL_POS(g, g->p.x, g->p.y); lineadd = g->g.Width - g->p.cx; shape = (g->p.cx << 16) | (g->p.cy); #endif // Start the DMA2D DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, pos); DMA2D->OOR = lineadd; DMA2D->NLR = shape; DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color)); DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START; }
LLDSPEC void gdisp_lld_clear(GDisplay *g) { acquire_bus(g); write_cmd(g, SSD1327_SET_COLUMN_ADDRESS); write_data(g, 0); write_data(g, GDISP_SCREEN_WIDTH - 1); write_cmd(g, SSD1327_SET_ROW_ADDRESS); write_data(g, 0); write_data(g, GDISP_SCREEN_HEIGHT - 1); write_cmd(g, SSD1327_WRITE_RAM); LLDCOLOR_TYPE c; c = gdispColor2Native(g->p.color); uint16_t i = 0; for (i = 0; i < GDISP_SCREEN_WIDTH*GDISP_SCREEN_HEIGHT; i++) { write_data(g, c >> 8); write_data(g, c & 0xFF); } release_bus(g); }
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { netPriv * priv; uint16_t buf[4]; #if GDISP_DONT_WAIT_FOR_NET_DISPLAY if (!(g->flags & GDISP_FLG_CONNECTED)) return; #else while(!(g->flags & GDISP_FLG_CONNECTED)) gfxSleepMilliseconds(200); #endif priv = g->priv; buf[0] = GNETCODE_PIXEL; buf[1] = g->p.x; buf[2] = g->p.y; buf[3] = gdispColor2Native(g->p.color); MUTEX_ENTER; sendpkt(priv->netfd, buf, 4); MUTEX_EXIT; }
LLDSPEC void gdisp_lld_write_color(GDisplay *g) { write_data(g, gdispColor2Native(g->p.color)); }
LLDSPEC void gdisp_lld_fill_area(GDisplay *g) { winPriv * priv; RECT rect; HBRUSH hbr; COLORREF color; priv = g->priv; color = gdispColor2Native(g->p.color); hbr = CreateSolidBrush(color); #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: default: rect.top = g->p.y; rect.bottom = rect.top + g->p.cy; rect.left = g->p.x; rect.right = rect.left + g->p.cx; break; case GDISP_ROTATE_90: rect.bottom = g->g.Width - g->p.x; rect.top = rect.bottom - g->p.cx; rect.left = g->p.y; rect.right = rect.left + g->p.cy; break; case GDISP_ROTATE_180: rect.bottom = g->g.Height - g->p.y; rect.top = rect.bottom - g->p.cy; rect.right = g->g.Width - g->p.x; rect.left = rect.right - g->p.cx; break; case GDISP_ROTATE_270: rect.top = g->p.x; rect.bottom = rect.top + g->p.cx; rect.right = g->g.Height - g->p.y; rect.left = rect.right - g->p.cy; break; } #else 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); 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); }
LLDSPEC void gdisp_lld_write_color(GDisplay *g) { winPriv * priv; int x, y; COLORREF color; priv = g->priv; color = gdispColor2Native(g->p.color); if (!(g->flags & GDISP_FLG_WSTREAM)) BAD_PARAMETER("write_color: not in streaming mode"); if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1) BAD_PARAMETER("write_color: cursor outside streaming area"); if (g->flags & GDISP_FLG_WRAPPED) { BAD_PARAMETER("write_color: Warning - Area wrapped."); g->flags &= ~GDISP_FLG_WRAPPED; } #if GDISP_NEED_CONTROL switch(g->g.Orientation) { case GDISP_ROTATE_0: default: x = priv->x; y = priv->y; break; case GDISP_ROTATE_90: x = priv->y; y = g->g.Width - 1 - priv->x; break; case GDISP_ROTATE_180: x = g->g.Width - 1 - priv->x; y = g->g.Height - 1 - priv->y; break; case GDISP_ROTATE_270: x = g->g.Height - 1 - priv->y; y = priv->x; break; } #else x = priv->x; y = priv->y; #endif // Draw the pixel on the screen and in the buffer. WaitForSingleObject(drawMutex, INFINITE); SetPixel(priv->dcBuffer, x, y, color); #if GDISP_WIN32_USE_INDIRECT_UPDATE ReleaseMutex(drawMutex); { RECT r; r.left = x; r.right = x+1; r.top = y; r.bottom = 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 // Update the cursor if (++priv->x > priv->x1) { priv->x = priv->x0; if (++priv->y > priv->y1) { g->flags |= GDISP_FLG_WRAPPED; priv->y = priv->y0; } } }
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; RECT rect; HGDIOBJ old; POINT p; coord_t pos; uint8_t bit; #endif 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) < GDISP_SCREEN_HEIGHT) { priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT; goto mousemove; } #endif // 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) { 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) { priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; goto mousemove; } break; case WM_MBUTTONUP: g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA); priv = (winPriv *)g->priv; if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) { 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) { 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) { 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) break; mousemove: priv->mousex = (coord_t)LOWORD(lParam); priv->mousey = (coord_t)HIWORD(lParam); if ((gmvmt(priv->mouse)->d.flags & GMOUSE_VFLG_NOPOLL)) // For normal setup this is always TRUE _gmouseWakeup(priv->mouse); break; #endif case WM_SYSKEYDOWN: case WM_KEYDOWN: case WM_SYSKEYUP: case WM_KEYUP: break; case WM_CHAR: case WM_DEADCHAR: 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 > 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 >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) { pen = CreatePen(PS_SOLID, 1, gdispColor2Native(Black)); hbrOn = CreateSolidBrush(gdispColor2Native(Blue)); hbrOff = CreateSolidBrush(gdispColor2Native(Gray)); old = SelectObject(dc, pen); 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 + 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); } } DeleteObject(hbrOn); DeleteObject(hbrOff); SelectObject(dc, old); } #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); // Actually the above doesn't work (who knows why) ExitProcess(0); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; }
LLDSPEC void gdisp_lld_write_color(GDisplay *g) { color_t color = gdispColor2Native(g->p.color); write_cmd(g, color >> 8); write_cmd(g, color & 0xff); }