graphics, kernel: update cursor pos on kMain hlt hit

This commit is contained in:
Edgaru089 2021-10-10 23:20:00 +08:00
parent def2c3bf7a
commit dfce649314
3 changed files with 116 additions and 41 deletions

View File

@ -1,6 +1,7 @@
#include "graphics.h"
#include "color.h"
#include "unifont.h"
#include "../runtime/stdio.h"
#include <efiprot.h>
@ -26,14 +27,17 @@ static EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
static EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
static UINTN sizeofInfo, nModes, nativeMode;
static HelosGraphics_Mode modes[128];
HelosGraphics_Mode graphics_SystemVideoMode;
void *graphics_DeviceFramebuffer;
void * graphics_Framebuffer;
uint64_t graphics_FramebufferSize;
uint32_t graphics_Doublebuffer[2048 * 1024];
xcursor_ChunkHeader_Image *graphics_Cursor;
int graphics_MouseCursorX, graphics_MouseCursorY;
void graphics_Init() {
assert(sizeof(HelosGraphics_Color) == sizeof(uint32_t) && "HelosGraphics_Color not packed to be 32-bit(4 bytes)");
@ -99,8 +103,12 @@ void graphics_Init() {
}
#undef CASE
graphics_SystemVideoMode = modes[nativeMode];
graphics_Framebuffer = (void *)graphics_Doublebuffer;
graphics_CursorX = graphics_CursorY = 0;
graphics_MouseCursorX = graphics_SystemVideoMode.Width / 2;
graphics_MouseCursorY = graphics_SystemVideoMode.Height / 2;
}
@ -112,17 +120,17 @@ void graphics_SetPixel_RGB(int posX, int posY, const HelosGraphics_Color *color)
uint8_t A;
} colorRGB = {color->R, color->G, color->B, 0};
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * posY + 4 * posX)) = (*((uint32_t *)&colorRGB));
*((uint32_t *)(graphics_Framebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * posY + 4 * posX)) = (*((uint32_t *)&colorRGB));
}
void graphics_SetPixel_BGR(int posX, int posY, const HelosGraphics_Color *color) {
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * posY + 4 * posX)) = (*((uint32_t *)color)) & 0x00ffffffu;
*((uint32_t *)(graphics_Framebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * posY + 4 * posX)) = (*((uint32_t *)color)) & 0x00ffffffu;
}
void graphics_GetSize(int *sizeX, int *sizeY, int *bitsPerPixel) {
*sizeX = modes[nativeMode].Width;
*sizeY = modes[nativeMode].Height;
*sizeX = graphics_SystemVideoMode.Width;
*sizeY = graphics_SystemVideoMode.Height;
*bitsPerPixel = 24;
}
@ -134,13 +142,13 @@ void graphics_ClearBuffer(const HelosGraphics_Color *color) {
return;
}
if (modes[nativeMode].PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
if (graphics_SystemVideoMode.PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
struct {
uint8_t R, G, B;
uint8_t A;
} colorRGB = {color->R, color->G, color->B, 0};
data = (*(uint32_t *)&colorRGB) & 0x00ffffffu;
} else if (modes[nativeMode].PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
} else if (graphics_SystemVideoMode.PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
data = (*(uint32_t *)color) & 0x00ffffffu;
}
@ -151,17 +159,47 @@ void graphics_ClearBuffer(const HelosGraphics_Color *color) {
}
}
static inline size_t min(size_t x, size_t y) {
return x < y ? x : y;
}
void graphics_SwapBuffer() {
memcpy(graphics_DeviceFramebuffer, graphics_Framebuffer, graphics_FramebufferSize);
if (graphics_Cursor) {
// TODO Optimize mouse cursor overlay render
/*if (graphics_SystemVideoMode.PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
for (int i = 0; i < graphics_Cursor->height; i++) {
if (graphics_MouseCursorY + i >= graphics_SystemVideoMode.Height)
break;
memcpy(
graphics_DeviceFramebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * graphics_CursorY + 4 * graphics_CursorX,
&graphics_Cursor->pixels[i * graphics_Cursor->width],
min(graphics_Cursor->width, graphics_SystemVideoMode.Width - graphics_MouseCursorX) * 4);
}
} else {*/
for (int y = 0; y < graphics_Cursor->height; y++) {
if (graphics_MouseCursorY + y >= graphics_SystemVideoMode.Height)
break;
for (int x = 0; x < min(graphics_Cursor->width, graphics_SystemVideoMode.Width - graphics_MouseCursorX); x++) {
//graphics_SetPixel_RGB(x + graphics_MouseCursorX, y + graphics_MouseCursorY, &graphics_Cursor->pixels[y * graphics_Cursor->width + x]);
HelosGraphics_Color *pixel = &graphics_Cursor->pixels[y * graphics_Cursor->width + x];
if (pixel->A <= 0x7f)
continue;
*((uint32_t *)(graphics_DeviceFramebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * (y + graphics_MouseCursorY) + 4 * (x + graphics_MouseCursorX))) = (*((uint32_t *)&graphics_Cursor->pixels[y * graphics_Cursor->width + x])) & 0x00ffffffu;
}
}
//}
}
}
void graphics_FillPixel(int startX, int startY, int endX, int endY, const HelosGraphics_Color *color) {
// TODO Optimize this! This is too sloooow
if (gop->Mode->Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
if (graphics_SystemVideoMode.PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
for (int i = startX; i < endX; i++)
for (int j = startY; j < endY; j++)
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * j + 4 * i)) = (*((uint32_t *)color)) & 0x00ffffffu;
else if (gop->Mode->Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor)
*((uint32_t *)(graphics_Framebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * j + 4 * i)) = (*((uint32_t *)color)) & 0x00ffffffu;
else if (graphics_SystemVideoMode.PixelFormat == PixelRedGreenBlueReserved8BitPerColor)
for (int i = startX; i < endX; i++)
for (int j = startY; j < endY; j++) {
struct {
@ -169,7 +207,7 @@ void graphics_FillPixel(int startX, int startY, int endX, int endY, const HelosG
uint8_t A;
} colorRGB = {color->B, color->G, color->R, 0};
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * j + 4 * i)) = (*((uint32_t *)&colorRGB));
*((uint32_t *)(graphics_Framebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * j + 4 * i)) = (*((uint32_t *)&colorRGB));
}
}
@ -178,24 +216,24 @@ int graphics_CursorX, graphics_CursorY;
void graphics_Scroll(int scrollY) {
memmove(
graphics_Doublebuffer,
graphics_Doublebuffer + modes[nativeMode].PixelsPerLine * scrollY,
sizeof(uint32_t) * (modes[nativeMode].PixelsPerLine * (modes[nativeMode].Height - scrollY)));
graphics_Doublebuffer + graphics_SystemVideoMode.PixelsPerLine * scrollY,
sizeof(uint32_t) * (graphics_SystemVideoMode.PixelsPerLine * (graphics_SystemVideoMode.Height - scrollY)));
// TODO proper memset instead of this sloooow FillPixel
/*memset(
graphics_Doublebuffer + modes[nativeMode].PixelsPerLine * (modes[nativeMode].Height - scrollY),
graphics_Doublebuffer + graphics_SystemVideoMode.PixelsPerLine * (graphics_SystemVideoMode.Height - scrollY),
0,
sizeof(uint32_t) * modes[nativeMode].PixelsPerLine * (scrollY));*/
graphics_FillPixel(0, modes[nativeMode].Height - scrollY, modes[nativeMode].Width, modes[nativeMode].Height, &HelosGraphics_Color_Black);
sizeof(uint32_t) * graphics_SystemVideoMode.PixelsPerLine * (scrollY));*/
graphics_FillPixel(0, graphics_SystemVideoMode.Height - scrollY, graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height, &HelosGraphics_Color_Black);
}
void graphics_ElementSize(int sizeX, int sizeY) {
if (graphics_CursorX + sizeX >= modes[nativeMode].Width) { // line breaking required
if (graphics_CursorX + sizeX >= graphics_SystemVideoMode.Width) { // line breaking required
graphics_CursorY += sizeY;
graphics_CursorX = 0;
}
if (graphics_CursorY + sizeY >= modes[nativeMode].Height) { // scrolling required
graphics_Scroll(sizeY + graphics_CursorY - modes[nativeMode].Height);
graphics_CursorY = modes[nativeMode].Height - sizeY;
if (graphics_CursorY + sizeY >= graphics_SystemVideoMode.Height) { // scrolling required
graphics_Scroll(sizeY + graphics_CursorY - graphics_SystemVideoMode.Height);
graphics_CursorY = graphics_SystemVideoMode.Height - sizeY;
}
}

View File

@ -3,6 +3,8 @@
#include "../main.h"
#include "efiprot.h"
#include "color.h"
#include "xcursor/xcursor.h"
#ifdef __cplusplus
extern "C" {
@ -12,22 +14,6 @@ extern "C" {
#define HELOS_GRAPHICS_TARGET_MODE_WIDTH 1600
#define HELOS_GRAPHICS_TARGET_MODE_HEIGHT 900
// HelosGraphics_Color is in ARGB little-endian packed format
// (B,G,R,A in byte order)
typedef struct {
uint8_t B, G, R;
uint8_t A;
} PACKED HelosGraphics_Color;
extern const HelosGraphics_Color
HelosGraphics_Color_Black,
HelosGraphics_Color_White,
HelosGraphics_Color_Red,
HelosGraphics_Color_Green,
HelosGraphics_Color_Blue,
HelosGraphics_Color_Cyan,
HelosGraphics_Color_Magenta,
HelosGraphics_Color_Yellow;
typedef struct {
int Width, Height;
@ -40,6 +26,10 @@ typedef struct {
extern void * graphics_DeviceFramebuffer; // this is the framebuffer directly for the device via memory mapping.
extern void * graphics_Framebuffer; // this is the double-buffered framebuffer (back buffer)
extern uint64_t graphics_FramebufferSize;
extern HelosGraphics_Mode graphics_SystemVideoMode; // system video mode
extern xcursor_ChunkHeader_Image *graphics_Cursor; // mouse cursor image
extern int graphics_MouseCursorX, graphics_MouseCursorY;
// Init() must be called prior to ExitBootServices()

View File

@ -15,6 +15,10 @@
#include "../execformat/pe/reloc.h"
void execformat_pe_ReadSystemHeader(execformat_pe_PortableExecutable *pe);
#include "../graphics/graphics.h"
#include "../graphics/xcursor/xcursor.h"
#include "../embed/files.h"
static void tellRIP() {
uint64_t a, b;
asm volatile("leaq (%%rip), %0\n\tleaq runtime_InitPaging(%%rip), %1"
@ -22,6 +26,14 @@ static void tellRIP() {
io_Printf("tellRIP(): Stack position: %llx, RIP=%llx, kMain_StackPosition:%llx(%llx), interrupt_Int128: %llx\n", &a, a, (uint64_t)&kMain_StackPosition, b, (uint64_t)interrupt_Int128);
}
static inline int minmax(int val, int min, int max) {
if (val > max)
return max;
if (val < min)
return min;
return val;
}
SYSV_ABI void kMain() {
io_WriteConsoleASCII("Yes! kMain survived!\n");
@ -44,8 +56,43 @@ SYSV_ABI void kMain() {
irq_pic_ps2_Init();
io_WriteConsoleASCII("PIC PS/2 OK\n");
xcursor_Xcursor cursor;
xcursor_LoadMemory(&cursor, (void *)embed_Xcursor_Default_Data, embed_Xcursor_Default_Data_End - embed_Xcursor_Default_Data);
if (cursor.header) {
for (int i = 0; i < cursor.n; i++) {
if (cursor.toc[i].type == XCURSOR_CHUNKTYPE_IMAGE /*&& ((xcursor_ChunkHeader_Image *)(embed_Xcursor_Default_Data + cursor.toc[i].offset))->subtype == 24*/) {
xcursor_ChunkHeader_Image *image = (xcursor_ChunkHeader_Image *)(embed_Xcursor_Default_Data + cursor.toc[i].offset);
io_Printf("xcursor_Default: Loading size=%dx%d\n", image->width, image->height);
graphics_Cursor = image;
break;
}
}
} else
io_WriteConsoleASCII("xcursor_Default: failed to load\n");
for (;;) {
asm volatile("hlt");
io_WriteConsoleASCII("kMain: Interrupt hit\n");
while (queue_Size(&irq_pic_ps2_QueueMouse) >= (irq_pic_ps2_Mouse4Bytes ? 4 : 3)) {
unsigned int moveX, moveY, state;
do {
state = queue_PopByte(&irq_pic_ps2_QueueMouse);
} while (!(state & (1u << 3)));
unsigned int d = queue_PopByte(&irq_pic_ps2_QueueMouse);
moveX = d - ((state << 4) & 0x100);
d = queue_PopByte(&irq_pic_ps2_QueueMouse);
moveY = d - ((state << 3) & 0x100);
graphics_MouseCursorX = minmax(graphics_MouseCursorX + *((int *)&moveX), 0, graphics_SystemVideoMode.Width - 1);
graphics_MouseCursorY = minmax(graphics_MouseCursorY - *((int *)&moveY), 0, graphics_SystemVideoMode.Height - 1);
if (irq_pic_ps2_Mouse4Bytes)
queue_PopByte(&irq_pic_ps2_QueueMouse);
}
//io_WriteConsoleASCII("kMain: Interrupt hit\n");
graphics_SwapBuffer();
}
}