Windows gpu rendering

This commit is contained in:
Łukasz Magiera 2016-03-02 22:24:08 +01:00
parent af670a7af3
commit f3a6d7e409
4 changed files with 462 additions and 6 deletions

View File

@ -39,13 +39,13 @@ winexe: $(BUILD)$(OUTNAME)
cp $(BUILD)$(OUTNAME) $(BUILD)$(OUTNAME).exe cp $(BUILD)$(OUTNAME) $(BUILD)$(OUTNAME).exe
win: LIBS+= -lws2_32 win: LIBS+= -lws2_32 -lgdi32
win: all winexe win: all winexe
win-build: LIBS+= -lws2_32 win-build: LIBS+= -lws2_32 -lgdi32
win-build: build winexe win-build: build winexe
win-debug: LIBS+= -lws2_32 win-debug: LIBS+= -lws2_32 -lgdi32
win-debug: debug winexe win-debug: debug winexe
$(BUILDDIRECTORIES): $(BUILDDIRECTORIES):

View File

@ -6,11 +6,100 @@
#include <lauxlib.h> #include <lauxlib.h>
#include <windows.h> #include <windows.h>
#define BYPP 4
#define RES_X 800
#define RES_Y 600
#define CHARSW (RES_X / 8)
#define CHARSH (RES_Y / 16)
#define XY_TO_WIN(x, y) (((y) * RES_X * BYPP) + ((x) * BYPP))
#define XY_TO_COLBUF(x, y, z) (((((y) * CHARSW) + (x)) * 2) + (z))
#define XY_TO_CHRBUF(x, y) (((y) * CHARSW) + (x))
#define WINDOW_CLASS "LuPi2 GPU" #define WINDOW_CLASS "LuPi2 GPU"
#define WINDOW_TITLE "LuPi2" #define WINDOW_TITLE "LuPi2"
#define uchar unsigned char
uchar *screenbb = NULL;
HBITMAP screenbmap = NULL;
char *colbuf = 0;
ushort *chrbuf = 0;
int palette[256];
float pal_yuv[768];
static inline float yuv_y(int r, int g, int b) {
float rf = r/255.0f;
float gf = g/255.0f;
float bf = b/255.0f;
return 0.299f * r + 0.587f * g + 0.114f * b;
}
static inline float yuv_u(int r, int g, int b) {
float rf = r/255.0f;
float gf = g/255.0f;
float bf = b/255.0f;
return -0.147f * r - 0.289f * g + 0.436f * b;
}
static inline float yuv_v(int r, int g, int b) {
float rf = r/255.0f;
float gf = g/255.0f;
float bf = b/255.0f;
return 0.615f * r - 0.515f * g - 0.100f * b;
}
/**************************************/
static inline int win_draw_32(int x, int y, int bg, int fg, int chr, int cwd) {
int px, py;
int c = 0;
int* ptr;
ptr = (int*) (&screenbb[XY_TO_WIN((x * 8), ((y * 16) + py))]);
for (py = 0; py < 16; py++) {
if (cwd == 2) {
c = (res_unifont[chr * 33 + 2 + (py * 2)] << 8) | res_unifont[chr * 33 + 1 + (py * 2)];
} else if (cwd == 1) {
c = res_unifont[chr * 33 + 1 + py];
}
for (px = (cwd == 2 ? 15 : 7); px >= 0; px--) {
ptr[px] = (c & 1) ? fg : bg;
c >>= 1;
}
ptr += (RES_X * BYPP) >> 2;
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) { switch(msg) {
case WM_PAINT: {
logn("win: PAINT");
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
screenbmap = CreateBitmap(RES_X, RES_Y, 1, BYPP * 8, (void*) screenbb);
HDC src = CreateCompatibleDC(hdc);
SelectObject(src, screenbmap);
BitBlt(hdc, 0, 0, RES_X, RES_Y, src, 0, 0, SRCCOPY);
DeleteDC(src);
EndPaint(hwnd, &ps);
}
break;
case WM_CREATE:
logn("win: Create");
screenbb = (uchar*) calloc(RES_X * RES_Y, BYPP);
//for(int i = 0; i < RES_X * RES_Y * BYPP; i++) screenbb[i] = (uchar) rand();
win_draw_32(0, 0, 0, 0xFFFFFF, 'H', 1);
win_draw_32(1, 0, 0, 0xFFFFFF, 'e', 1);
win_draw_32(2, 0, 0, 0xFFFFFF, 'l', 1);
win_draw_32(3, 0, 0, 0xFFFFFF, 'l', 1);
win_draw_32(4 , 0, 0, 0xFFFFFF, 'o', 1);
colbuf = (char *)malloc(2 * CHARSW * CHARSH);
chrbuf = (ushort *)malloc(2 * CHARSW * CHARSH);
break;
case WM_CLOSE: case WM_CLOSE:
DestroyWindow(hwnd); DestroyWindow(hwnd);
exit(0); /* TODO: Push exit event? Or just remove gpu component?? */ exit(0); /* TODO: Push exit event? Or just remove gpu component?? */
@ -24,7 +113,11 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
return 0; return 0;
} }
static int l_open(lua_State *L) { static int l_open(lua_State *L) {
logn("win: INIT");
WNDCLASSEX wc; WNDCLASSEX wc;
HWND hwnd; HWND hwnd;
@ -52,7 +145,7 @@ static int l_open(lua_State *L) {
WINDOW_CLASS, WINDOW_CLASS,
WINDOW_TITLE, WINDOW_TITLE,
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, CW_USEDEFAULT, CW_USEDEFAULT, RES_X, RES_Y,
NULL, NULL, GetModuleHandle(NULL), NULL); NULL, NULL, GetModuleHandle(NULL), NULL);
if(hwnd == NULL) { if(hwnd == NULL) {
@ -64,13 +157,225 @@ static int l_open(lua_State *L) {
ShowWindow(hwnd, SW_SHOW); ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd); UpdateWindow(hwnd);
InvalidateRect(hwnd, NULL, TRUE);
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
/**************************************/
static int win_draw(int x, int y, int bg, int fg, int chr) {
if (x < 0 || x >= CHARSW || y < 0 || y >= CHARSH || bg < 0 || bg >= 256 || fg < 0 || fg >= 256
|| chr < 0 || chr >= 65536) {
return 0;
}
colbuf[XY_TO_COLBUF(x, y, 0)] = (char) bg;
colbuf[XY_TO_COLBUF(x, y, 1)] = (char) fg;
chrbuf[XY_TO_CHRBUF(x, y)] = (ushort) chr;
int cwd = res_unifont[chr * 33];
if (cwd == 2 && x < (CHARSW - 1)) {
chrbuf[XY_TO_CHRBUF(x + 1, y)] = (ushort) 0;
}
win_draw_32(x,y,palette[bg],palette[fg],chr,cwd);
return 0;
}
static int win_copy(int x, int y, int w, int h, int x2, int y2) {
int i, j;
char* tmp = (char*) malloc(w*h*BYPP);
for (j = 0; j < h; j++) {
char* ptr = &screenbb[XY_TO_WIN((x), ((y) + (j)))];
memcpy(&tmp[w*j*BYPP], ptr, w*BYPP);
}
for (j = 0; j < h; j++) {
char* ptr = &screenbb[XY_TO_WIN((x2), (y2 + (j)))];
memcpy(ptr, &tmp[w*j*BYPP], w*BYPP);
}
free(tmp);
}
static int l_set_palette (lua_State *L) {
int i = lua_tonumber(L, 1);
int pal = lua_tonumber(L, 2);
if(i >= 0 && i < 256) {
// calculate yuv
int r = (pal >> 16) & 0xFF;
int g = (pal >> 8) & 0xFF;
int b = pal & 0xFF;
pal_yuv[i*3] = yuv_y(r, g, b);
pal_yuv[i*3+1] = yuv_u(r, g, b);
pal_yuv[i*3+2] = yuv_v(r, g, b);
// set palette color
palette[i] = pal;
}
return 0;
}
static int l_put (lua_State *L) {
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
int bg = lua_tonumber(L, 3);
int fg = lua_tonumber(L, 4);
int chr = lua_tonumber(L, 5);
return win_draw(x, y, bg, fg, chr);
}
static int l_get_nearest (lua_State *L) {
int nck = 0;
float ncv = 1000000;
int i;
int col = lua_tonumber(L, 1);
int r = (col >> 16) & 0xFF;
int g = (col >> 8) & 0xFF;
int b = (col) & 0xFF;
float coly = yuv_y(r, g, b);
float colu = yuv_u(r, g, b);
float colv = yuv_v(r, g, b);
float dist,dy,du,dv;
for (i = 0; i < 256; i++) {
if (palette[i] == col) {
lua_pushnumber(L, i);
return 1;
}
dy = coly - pal_yuv[i*3];
du = colu - pal_yuv[i*3+1];
dv = colv - pal_yuv[i*3+2];
dist = dy*dy + du*du + dv*dv;
if (dist < ncv) {
nck = i;
ncv = dist;
}
}
lua_pushnumber(L, nck);
return 1;
}
static int l_copy (lua_State *L) {
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
int w = lua_tonumber(L, 3);
int h = lua_tonumber(L, 4);
int tx = x+lua_tonumber(L, 5);
int ty = y+lua_tonumber(L, 6);
int j, px = x<<3, py = y<<4, pw = w<<3, ph = h<<4, ptx = tx<<3, pty = ty<<4;
char* tmpcol = (char*) malloc(w*h*2);
char* tmpchr = (char*) malloc(w*h*2);
for (j = 0; j < h; j++) {
memcpy(&tmpcol[j*w*2], &colbuf[XY_TO_COLBUF(x, y+j, 0)], w * 2);
memcpy(&tmpchr[j*w*2], &chrbuf[XY_TO_CHRBUF(x, y+j)], w * 2);
}
win_copy(px, py, pw, ph, ptx, pty);
for (j = 0; j < h; j++) {
memcpy(&colbuf[XY_TO_COLBUF(tx, ty+j, 0)], &tmpcol[j*w*2], w * 2);
memcpy(&chrbuf[XY_TO_CHRBUF(tx, ty+j)], &tmpchr[j*w*2], w * 2);
}
free(tmpcol);
free(tmpchr);
}
static int l_fill (lua_State *L) {
int x1 = lua_tonumber(L, 1);
int y1 = lua_tonumber(L, 2);
int x2 = lua_tonumber(L, 3);
int y2 = lua_tonumber(L, 4);
int bg = lua_tonumber(L, 5);
int fg = lua_tonumber(L, 6);
int chr = lua_tonumber(L, 7);
int i, j;
for (i = y1; i <= y2; i++) {
for (j = x1; j <= x2; j++) {
win_draw(j, i, bg, fg, chr);
}
}
return 0;
}
static int l_winfill (lua_State *L) {
int x1 = lua_tonumber(L, 1);
int y1 = lua_tonumber(L, 2);
int x2 = lua_tonumber(L, 3);
int y2 = lua_tonumber(L, 4);
int bg = lua_tonumber(L, 5);
int fg = lua_tonumber(L, 6);
int chr = lua_tonumber(L, 7);
int i, j;
for (i = y1; i <= y2; i++) {
for (j = x1; j <= x2; j++) {
win_draw(j, i, bg, fg, chr);
}
}
return 0;
}
static int l_get_width (lua_State *L) {
lua_pushnumber(L, CHARSW);
return 1;
}
static int l_get_height (lua_State *L) {
lua_pushnumber(L, CHARSH);
return 1;
}
static int l_getbg (lua_State *L) {
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
if (x >= 0 && y >= 0 && x < CHARSW && y < CHARSH) {
lua_pushnumber(L, colbuf[XY_TO_COLBUF(x, y, 0)]);
} else {
lua_pushnumber(L, 0);
}
return 1;
}
static int l_getfg (lua_State *L) {
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
if (x >= 0 && y >= 0 && x < CHARSW && y < CHARSH) {
lua_pushnumber(L, colbuf[XY_TO_COLBUF(x, y, 1)]);
} else {
lua_pushnumber(L, 0);
}
return 1;
}
static int l_get (lua_State *L) {
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
if (x >= 0 && y >= 0 && x < CHARSW && y < CHARSH) {
lua_pushnumber(L, chrbuf[XY_TO_CHRBUF(x, y)]);
} else {
lua_pushnumber(L, 0);
}
return 1;
}
void winapigpu_init(lua_State* L) { void winapigpu_init(lua_State* L) {
struct luaL_Reg winlib[] = { struct luaL_Reg winlib[] = {
{"open", l_open}, {"open", l_open},
{"setPalette", l_set_palette},
{"getWidth", l_get_width},
{"getHeight", l_get_height},
{"put", l_put},
{"copy", l_copy},
{"fill", l_fill},
{"getBackground", l_getbg},
{"getForeground", l_getfg},
{"get", l_get},
{"getNearest", l_get_nearest},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -91,7 +91,7 @@ function fbgpu.start()
return fb.getWidth(), fb.getHeight() return fb.getWidth(), fb.getHeight()
end end
function gpu.getViewport() function gpu.getViewport()
return termutils.getSize() return fb.getWidth(), fb.getHeight()
end end
function gpu.setViewport(w, h) function gpu.setViewport(w, h)
checkArg(1, w, "number") checkArg(1, w, "number")

View File

@ -1,11 +1,162 @@
local wingpu = {} local wingpu = {}
local mapping = {}
for i=0,15 do
mapping[i] = (i * 15) << 16 | (i * 15) << 8 | (i * 15)
end
for i=0,239 do
local b = math.floor((i % 5) * 255 / 4.0)
local g = math.floor((math.floor(i / 5.0) % 8) * 255 / 7.0)
local r = math.floor((math.floor(i / 40.0) % 6) * 255 / 5.0)
mapping[16+i] = r << 16 | g << 8 | b
end
local win = winapigpu
for k,v in pairs(mapping) do
win.setPalette(k, v)
end
local background = 0
local foreground = 0
function wingpu.start() function wingpu.start()
local s, reason = winapigpu.open() local gpu = {}
function gpu.bind() return false, "This is static bound gpu" end
function gpu.getScreen() return "n/a" end
function gpu.setBackground(color, isPaletteIndex)
checkArg(1, color, "number")
checkArg(2, isPaletteIndex, "boolean", "nil")
if isPaletteIndex and color >= 0 and color < 256 then
background = color
return mapping[color]
end
local old = background
background = win.getNearest(color)
return mapping[old]
end
function gpu.setForeground(color, isPaletteIndex)
checkArg(1, color, "number")
checkArg(2, isPaletteIndex, "boolean", "nil")
if isPaletteIndex and color >= 0 and color < 256 then
foreground = color
return mapping[color]
end
local old = foreground
foreground = win.getNearest(color)
return mapping[old]
end
function gpu.getBackground()
return mapping[background], false
end
function gpu.getForeground()
return mapping[foreground], false
end
function gpu.getPaletteColor()
return nil
end
function gpu.setPaletteColor(index, value)
checkArg(1, index, "number")
checkArg(2, value, "number")
win.setPalette(index, value)
return value
end
function gpu.maxDepth()
return 8
end
function gpu.setDepth()
return false
end
function gpu.getDepth()
return 8
end
function gpu.maxResolution()
return win.getWidth(), win.getHeight()
end
function gpu.getResolution()
return win.getWidth(), win.getHeight()
end
function gpu.getViewport()
return win.getWidth(), win.getHeight()
end
function gpu.setViewport(w, h)
checkArg(1, w, "number")
checkArg(2, h, "number")
return false, "Viewport not supported for this gpu"
end
function gpu.setResolution(w, h)
checkArg(1, w, "number")
checkArg(2, h, "number")
return false, "Non resizeable gpu"
end
function gpu.get(x, y)
checkArg(1, x, "number")
checkArg(2, y, "number")
return utf8.char(win.get(x-1, y-1))
end
function gpu.set(x, y, value, vertical)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, value, "string")
checkArg(4, vertical, "boolean", "nil")
x = math.floor(x)
y = math.floor(y)
if not vertical then
local i = 0
value:gsub(".", function(c)
win.put(x+i-1, y-1, background, foreground, utf8.codepoint(c))
i = i+1
end)
else
local i = 0
value:gsub(".", function(c)
win.put(x-1, y+i-1, background, foreground, utf8.codepoint(c))
i = i+1
end)
end
return true
end
function gpu.copy(x, y, w, h, tx, ty) --TODO: Check(check X multiple times)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, w, "number")
checkArg(4, h, "number")
checkArg(5, tx, "number")
checkArg(6, ty, "number")
win.copy(x-1, y-1, w, h, tx, ty);
return true
end
function gpu.fill(x, y, w, h, ch)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, w, "number")
checkArg(4, h, "number")
checkArg(5, ch, "string")
ch = ch:sub(1, 1)
win.fill(x-1, y-1, x+w-2, y+h-2, background, foreground, utf8.codepoint(ch))
return true
end
local w, h = gpu.getResolution()
gpu.setForeground(0xFFFFFF)
gpu.setBackground(0x000000)
local s, reason = win.open()
if not s then if not s then
lprint("Couldn't open window: " .. tostring(reason)) lprint("Couldn't open window: " .. tostring(reason))
end end
modules.component.api.register(nil, "gpu", gpu)
modules.component.api.register(nil, "screen", {getKeyboards = function() return {"TODO:SetThisUuid"} end}) --verry dummy screen, TODO: make it better, kbd uuid also in epoll.c
modules.component.api.register("TODO:SetThisUuid", "keyboard", {})
return s return s
end end
return wingpu return wingpu