From ed153e6a5b9f001bbe49128e6bc53053f55dd37b Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 21 Apr 2017 18:26:22 +0200 Subject: Can plot on a surface from lua --- bam.lua | 2 +- src/lib/bam.lua | 4 +- src/lib/include/kogata/draw.h | 12 ++-- src/lib/libkogata/draw.c | 30 +++++--- src/sysapp/login/main.lua | 16 ++++- src/sysbin/bam.lua | 14 ++-- src/sysbin/lx/lxdrawlib.c | 160 ++++++++++++++++++++++++++++++++++++++++++ src/sysbin/lx/lxinit.c | 1 + src/sysbin/lx/lxlib.c | 14 ++++ src/sysbin/lx/lxlib.h | 6 ++ src/sysbin/terminal/main.c | 2 +- 11 files changed, 236 insertions(+), 25 deletions(-) create mode 100644 src/sysbin/lx/lxdrawlib.c diff --git a/bam.lua b/bam.lua index 395dd00..37fb358 100644 --- a/bam.lua +++ b/bam.lua @@ -132,7 +132,7 @@ local dev_cdrom = cdrom("dev", dev_settings) local rel_settings = TableDeepCopy(base_settings) for _, s in pairs(rel_settings) do s.cc.flags:Add("-Os", "-flto") - s.link.flags:Add("-Os", "-flto", "-Wl,--gc-sections") + s.link.flags:Add("-O3", "-Os", "-flto", "-Wl,--gc-sections") -- Maybe do this, goes with --gc-sections -- s.cc.flags:Add("-ffunction-sections", "-fdata-sections") diff --git a/src/lib/bam.lua b/src/lib/bam.lua index b7bee20..5d749b9 100644 --- a/src/lib/bam.lua +++ b/src/lib/bam.lua @@ -9,7 +9,7 @@ return function(s, common) return { libc = libc, - libkogata = {lib('libkogata'), libc}, - liblua = {lib('lua'), libc} + libkogata = {lib('libkogata')}, + liblua = {lib('lua')} } end diff --git a/src/lib/include/kogata/draw.h b/src/lib/include/kogata/draw.h index fb9fe05..d00036f 100644 --- a/src/lib/include/kogata/draw.h +++ b/src/lib/include/kogata/draw.h @@ -12,6 +12,9 @@ typedef struct { fd_t fd; uint8_t* data; + + int nrefs; + bool own_data; } fb_t; typedef struct font font_t; @@ -21,9 +24,10 @@ typedef uint32_t color_t; // a color is always linked to a FB on which it is to // ---- Buffer creation fb_t *g_fb_from_file(fd_t file, fb_info_t *geom); -fb_t *g_fb_from_mem(uint8_t* region, fb_info_t *geom); +fb_t *g_fb_from_mem(uint8_t* region, fb_info_t *geom, bool own_data); -void g_delete_fb(fb_t *fb); +void g_incref_fb(fb_t *fb); +void g_decref_fb(fb_t *fb); // ---- Color manipulation @@ -39,8 +43,8 @@ void g_line(fb_t *fb, int x1, int y1, int x2, int y2, color_t c); void g_rect(fb_t *fb, int x, int y, int w, int h, color_t c); void g_fillrect(fb_t *fb, int x, int y, int w, int h, color_t c); -void g_rect_r(fb_t *fb, fb_region_t reg, color_t c); -void g_fillrect_r(fb_t *fb, fb_region_t reg, color_t c); +void g_rectregion(fb_t *fb, fb_region_t reg, color_t c); +void g_fillregion(fb_t *fb, fb_region_t reg, color_t c); void g_circle(fb_t *fb, int cx, int cy, int r, color_t c); void g_fillcircle(fb_t *fb, int cx, int cy, int r, color_t c); diff --git a/src/lib/libkogata/draw.c b/src/lib/libkogata/draw.c index 6aa3387..d9a4268 100644 --- a/src/lib/libkogata/draw.c +++ b/src/lib/libkogata/draw.c @@ -22,6 +22,8 @@ fb_t *g_fb_from_file(fd_t file, fb_info_t *geom) { bool map_ok = sc_mmap_file(file, 0, ret->data, geom->height * geom->pitch, MM_READ | MM_WRITE); if (!map_ok) goto error; + ret->nrefs = 1; + return ret; error: @@ -30,7 +32,7 @@ error: return 0; } -fb_t *g_fb_from_mem(uint8_t* data, fb_info_t *geom) { +fb_t *g_fb_from_mem(uint8_t* data, fb_info_t *geom, bool own_data) { fb_t *ret = (fb_t*)malloc(sizeof(fb_t)); if (ret == 0) return 0; @@ -38,15 +40,27 @@ fb_t *g_fb_from_mem(uint8_t* data, fb_info_t *geom) { ret->fd = 0; ret->data = data; + ret->nrefs = 1; + ret->own_data = own_data; + return ret; } -void g_delete_fb(fb_t *fb) { - if (fb->fd != 0) { - sc_munmap(fb->data); - region_free(fb->data); +void g_incref_fb(fb_t *fb) { + fb->nrefs++; +} + +void g_decref_fb(fb_t *fb) { + fb->nrefs--; + if (fb->nrefs == 0) { + if (fb->fd != 0) { + sc_munmap(fb->data); + region_free(fb->data); + } else if (fb->own_data) { + free(fb->data); + } + free(fb); } - free(fb); } // ---- Color management @@ -168,11 +182,11 @@ void g_fillrect(fb_t *fb, int x, int y, int w, int h, color_t c) { } } -void g_rect_r(fb_t *fb, fb_region_t reg, color_t c) { +void g_rectregion(fb_t *fb, fb_region_t reg, color_t c) { g_rect(fb, reg.x, reg.y, reg.w, reg.h, c); } -void g_fillrect_r(fb_t *fb, fb_region_t reg, color_t c) { +void g_fillregion(fb_t *fb, fb_region_t reg, color_t c) { g_fillrect(fb, reg.x, reg.y, reg.w, reg.h, c); } diff --git a/src/sysapp/login/main.lua b/src/sysapp/login/main.lua index dec8b82..50ecd20 100644 --- a/src/sysapp/login/main.lua +++ b/src/sysapp/login/main.lua @@ -1,6 +1,7 @@ local sys = require 'lx.sys' local sysdef= require 'lx.sysdef' local ioctl = require 'lx.ioctl' +local draw = require 'lx.draw' print("Hello, world!") @@ -10,11 +11,22 @@ print("vesa_fd = " .. vesa_fd) local vesa_info = ioctl.fb_get_info(vesa_fd) print("vesa_info = ", vesa_info) +local surface = draw.from_fd(vesa_fd, vesa_info) +for x = 0, 255 do + for y = 0, 255 do + surface:plot(x, y, surface:rgb(x, y, 0)) + end +end + local i = 1 while true do - print(i) + surface:plot(i % (vesa_info.width-3), + i % (vesa_info.height-1), + surface:rgb(i % 256, + (i + 96) % 256, + (i + 2*96) % 256)) i = i + 1 - sys.usleep(1000000) + if i % 100000 == 0 then print(i) end end os.exit() diff --git a/src/sysbin/bam.lua b/src/sysbin/bam.lua index 7c2351b..5fccf4c 100644 --- a/src/sysbin/bam.lua +++ b/src/sysbin/bam.lua @@ -15,14 +15,14 @@ return function(s, lib) end return { - sysbin_exe('init', {lib.libkogata}), - sysbin_exe('giosrv', {lib.libkogata}), - sysbin_exe('login', {lib.libkogata}), - sysbin_exe('terminal', {lib.libkogata}), - sysbin_exe('shell', {lib.libkogata}), + sysbin_exe('init', {lib.libc, lib.libkogata}), + sysbin_exe('giosrv', {lib.libc, lib.libkogata}), + sysbin_exe('login', {lib.libc, lib.libkogata}), + sysbin_exe('terminal', {lib.libc, lib.libkogata}), + sysbin_exe('shell', {lib.libc, lib.libkogata}), - sysbin_exe('lua', {lib.liblua}), + sysbin_exe('lua', {lib.libc, lib.liblua}), -- sysbin_exe('luac', {liblua}), - sysbin_exe('lx', {lib.liblua}), + sysbin_exe('lx', {lib.libc, lib.liblua, lib.libkogata}), } end diff --git a/src/sysbin/lx/lxdrawlib.c b/src/sysbin/lx/lxdrawlib.c new file mode 100644 index 0000000..71c9819 --- /dev/null +++ b/src/sysbin/lx/lxdrawlib.c @@ -0,0 +1,160 @@ +/* +** Lua eXtended ioctl library +*/ + +#define lxdrawlib_c +#define LUA_LIB + +#include + + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include "lxlib.h" + + +typedef struct { + fb_t *fb; + fb_region_t subregion; + bool has_subregion; +} drawlib_surface; + +#define SURFACE "lx.draw.surface" + +static int draw_from_fd(lua_State *L) { + int fd = luaL_checkinteger(L, 1); + luaL_checktype(L, 2, LUA_TTABLE); + + fb_info_t geom; + geom.width = getintfield(L, 2, "width"); + geom.height = getintfield(L, 2, "height"); + geom.bpp = getintfield(L, 2, "bpp"); + geom.pitch = getintfield(L, 2, "pitch"); + geom.memory_model = getintfield(L, 2, "memory_model"); + + drawlib_surface *s = (drawlib_surface*)lua_newuserdata(L, sizeof(drawlib_surface)); + luaL_getmetatable(L, SURFACE); + lua_setmetatable(L, -2); + + s->fb = g_fb_from_file(fd, &geom); + if (s->fb == NULL) { + lua_pop(L, 1); + lua_pushnil(L); + } else { + s->subregion.x = s->subregion.y = 0; + s->subregion.w = geom.width; + s->subregion.h = geom.height; + s->has_subregion = false; + } + return 1; +} + +static int surface_gc(lua_State *L) { + drawlib_surface *s = (drawlib_surface*)luaL_checkudata(L, 1, SURFACE); + + if(s->fb == NULL) { + luaL_error(L, "s->fb == NULL ?"); + } + g_decref_fb(s->fb); + s->fb = NULL; + + return 0; +} + +static int surface_sub(lua_State *L) { + drawlib_surface *s = (drawlib_surface*)luaL_checkudata(L, 1, SURFACE); + int x = luaL_checkinteger(L, 2); + int y = luaL_checkinteger(L, 3); + int w, h; + if (lua_isinteger(L, 4)) { + w = luaL_checkinteger(L, 4); + } else { + w = s->subregion.w - x; + } + if (lua_isinteger(L, 5)) { + h = luaL_checkinteger(L, 5); + } else { + h = s->subregion.h - y; + } + + if (x < 0 || y < 0 || w < 0 || h < 0) + luaL_error(L, "negative argument is invalid"); + if (x+w > (int)s->subregion.w) luaL_error(L, "w too big"); + if (y+h > (int)s->subregion.h) luaL_error(L, "h too big"); + + drawlib_surface *s2 = (drawlib_surface*)lua_newuserdata(L, sizeof(drawlib_surface)); + luaL_getmetatable(L, SURFACE); + lua_setmetatable(L, -2); + + s2->fb = s->fb; + s2->has_subregion = true; + s2->subregion.x = s->subregion.x + x; + s2->subregion.y = s->subregion.y + y; + s2->subregion.w = w; + s2->subregion.h = h; + + return 1; +} + +static int surface_rgb(lua_State *L) { + drawlib_surface *s = (drawlib_surface*)luaL_checkudata(L, 1, SURFACE); + int r = luaL_checkinteger(L, 2); + int g = luaL_checkinteger(L, 3); + int b = luaL_checkinteger(L, 4); + + color_t c = g_color_rgb(s->fb, r, g, b); + lua_pushlightuserdata(L, (void*)c); + return 1; +} + +static int surface_plot(lua_State *L) { + drawlib_surface *s = (drawlib_surface*)luaL_checkudata(L, 1, SURFACE); + int x = luaL_checkinteger(L, 2); + int y = luaL_checkinteger(L, 3); + color_t c = (color_t)lx_checklightudata(L, 4); + + g_plot(s->fb, x, y, c); + return 0; +} + +/* }====================================================== */ + +static const luaL_Reg drawlib[] = { + {"from_fd", draw_from_fd}, + {NULL, NULL} +}; + +static const luaL_Reg surface_meta[] = { + {"sub", surface_sub}, + {"rgb", surface_rgb}, + {"plot", surface_plot}, + {"__gc", surface_gc}, + {NULL, NULL} +}; + + +LUAMOD_API int lx_open_draw (lua_State *L) { + luaL_newlib(L, drawlib); + + luaL_newmetatable(L, SURFACE); + luaL_setfuncs(L, surface_meta, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + return 1; +} + + +/* vim: set sts=2 ts=2 sw=2 tw=0 et :*/ diff --git a/src/sysbin/lx/lxinit.c b/src/sysbin/lx/lxinit.c index b727ccd..948659b 100644 --- a/src/sysbin/lx/lxinit.c +++ b/src/sysbin/lx/lxinit.c @@ -36,6 +36,7 @@ static const luaL_Reg loadedlibs[] = { {LX_SYSLIBNAME, lx_open_sys}, {LX_MSGLIBNAME, lx_open_msg}, {LX_IOCTLLIBNAME, lx_open_ioctl}, + {LX_DRAWLIBNAME, lx_open_draw}, {NULL, NULL} }; diff --git a/src/sysbin/lx/lxlib.c b/src/sysbin/lx/lxlib.c index 9f6843b..ed266f7 100644 --- a/src/sysbin/lx/lxlib.c +++ b/src/sysbin/lx/lxlib.c @@ -29,6 +29,13 @@ bool lx_checkboolean(lua_State *L, int arg) { return lua_toboolean(L, arg); } +void* lx_checklightudata(lua_State *L, int arg) { + if (!lua_islightuserdata(L, arg)) { + luaL_argerror(L, arg, "expected light userdata"); + } + return lua_touserdata(L, arg); +} + void setintfield (lua_State *L, const char *key, int value) { lua_pushinteger(L, value); @@ -39,3 +46,10 @@ void setstrfield (lua_State *L, const char *key, const char* value) { lua_pushstring(L, value); lua_setfield(L, -2, key); } + +int getintfield(lua_State *L, int arg, const char *key) { + lua_getfield(L, arg, key); + int v = luaL_checkinteger(L, -1); + lua_pop(L, 1); + return v; +} diff --git a/src/sysbin/lx/lxlib.h b/src/sysbin/lx/lxlib.h index 260db97..643d5c8 100644 --- a/src/sysbin/lx/lxlib.h +++ b/src/sysbin/lx/lxlib.h @@ -8,9 +8,12 @@ // Helper for libraries bool lx_checkboolean(lua_State *L, int arg); +void* lx_checklightudata(lua_State *L, int arg); void setintfield (lua_State *L, const char *key, int value); void setstrfield (lua_State *L, const char *key, const char* value); +int getintfield(lua_State *L, int arg, const char *key); + #define LX_SYSLIBNAME "lx.sys" LUAMOD_API int (lx_open_sys) (lua_State *L); @@ -22,6 +25,9 @@ LUAMOD_API int (lx_open_ioctl) (lua_State *L); LUAMOD_API int (luaopen_cmsgpack) (lua_State *L); #define lx_open_msg luaopen_cmsgpack +#define LX_DRAWLIBNAME "lx.draw" +LUAMOD_API int (lx_open_draw) (lua_State *L); + /* open all previous libraries */ LUALIB_API void (lx_openlibs) (lua_State *L); diff --git a/src/sysbin/terminal/main.c b/src/sysbin/terminal/main.c index d6d0fe4..c7e4969 100644 --- a/src/sysbin/terminal/main.c +++ b/src/sysbin/terminal/main.c @@ -302,7 +302,7 @@ void gip_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m term_t *c = (term_t*)s->data; if (c->fb != 0) { - g_delete_fb(c->fb); + g_decref_fb(c->fb); c->fb = 0; } if (c->fd != 0) { -- cgit v1.2.3