experimental optimize canvas:set_data using ffi

This commit is contained in:
MihailRis
2025-03-08 18:04:10 +03:00
parent 6078a8802e
commit e48216da40
6 changed files with 61 additions and 13 deletions
+28
View File
@@ -1,3 +1,31 @@
local _ffi = ffi
ffi = nil
-- Lua has no parallelizm, also _set_data does not call any lua functions so
-- may be reused one global ffi buffer per lua_State
local canvas_ffi_buffer
local canvas_ffi_buffer_size = 0
function __vc_Canvas_set_data(self, data)
if type(data) == "cdata" then
self:_set_data(tostring(_ffi.cast("uintptr_t", data)))
end
local width = self.width
local height = self.height
local size = width * height * 4
if size > canvas_ffi_buffer_size then
canvas_ffi_buffer = _ffi.new(
string.format("unsigned char[%s]", size)
)
canvas_ffi_buffer_size = size
end
for i=0, size - 1 do
canvas_ffi_buffer[i] = data[i + 1]
end
self:_set_data(tostring(_ffi.cast("uintptr_t", canvas_ffi_buffer)))
end
-- Check if given table is an array -- Check if given table is an array
function is_array(x) function is_array(x)
if #x > 0 then if #x > 0 then
+11 -8
View File
@@ -88,14 +88,17 @@ static void create_libs(State* L, StateType stateType) {
void lua::init_state(State* L, StateType stateType) { void lua::init_state(State* L, StateType stateType) {
// Allowed standard libraries // Allowed standard libraries
pop(L, luaopen_base(L)); luaL_openlibs(L);
pop(L, luaopen_math(L));
pop(L, luaopen_string(L)); if (getglobal(L, "require")) {
pop(L, luaopen_table(L)); pushstring(L, "ffi");
pop(L, luaopen_debug(L)); if (call_nothrow(L, 1, 1)) {
pop(L, luaopen_jit(L)); setglobal(L, "ffi");
pop(L, luaopen_bit(L)); }
pop(L, luaopen_os(L)); }
pushnil(L);
setglobal(L, "io");
const char* removed_os[] { const char* removed_os[] {
"execute", "exit", "remove", "rename", "setlocale", "tmpname", nullptr}; "execute", "exit", "remove", "rename", "setlocale", "tmpname", nullptr};
remove_lib_funcs(L, "os", removed_os); remove_lib_funcs(L, "os", removed_os);
+6 -2
View File
@@ -163,20 +163,23 @@ int lua::call(State* L, int argc, int nresults) {
int handler_pos = gettop(L) - argc; int handler_pos = gettop(L) - argc;
pushcfunction(L, l_error_handler); pushcfunction(L, l_error_handler);
insert(L, handler_pos); insert(L, handler_pos);
int top = gettop(L);
if (lua_pcall(L, argc, nresults, handler_pos)) { if (lua_pcall(L, argc, nresults, handler_pos)) {
std::string log = tostring(L, -1); std::string log = tostring(L, -1);
pop(L); pop(L);
remove(L, handler_pos); remove(L, handler_pos);
throw luaerror(log); throw luaerror(log);
} }
int added = gettop(L) - (top - argc - 1);
remove(L, handler_pos); remove(L, handler_pos);
return nresults == -1 ? 1 : nresults; return added;
} }
int lua::call_nothrow(State* L, int argc, int nresults) { int lua::call_nothrow(State* L, int argc, int nresults) {
int handler_pos = gettop(L) - argc; int handler_pos = gettop(L) - argc;
pushcfunction(L, l_error_handler); pushcfunction(L, l_error_handler);
insert(L, handler_pos); insert(L, handler_pos);
int top = gettop(L);
if (lua_pcall(L, argc, -1, handler_pos)) { if (lua_pcall(L, argc, -1, handler_pos)) {
auto errorstr = tostring(L, -1); auto errorstr = tostring(L, -1);
if (errorstr) { if (errorstr) {
@@ -188,8 +191,9 @@ int lua::call_nothrow(State* L, int argc, int nresults) {
remove(L, handler_pos); remove(L, handler_pos);
return 0; return 0;
} }
int added = gettop(L) - (top - argc - 1);
remove(L, handler_pos); remove(L, handler_pos);
return 1; return added;
} }
void lua::dump_stack(State* L) { void lua::dump_stack(State* L) {
+5 -1
View File
@@ -25,7 +25,8 @@ namespace lua {
if (n < 0) { if (n < 0) {
abort(); abort();
} }
if (lua_gettop(L) < n) { int top = lua_gettop(L);
if (top < n) {
abort(); abort();
} }
#endif #endif
@@ -63,6 +64,9 @@ namespace lua {
inline void rawseti(lua::State* L, int n, int idx = -2) { inline void rawseti(lua::State* L, int n, int idx = -2) {
lua_rawseti(L, idx, n); lua_rawseti(L, idx, n);
} }
inline void rawset(lua::State* L, int idx = -3) {
lua_rawset(L, idx);
}
inline int createtable(lua::State* L, int narr, int nrec) { inline int createtable(lua::State* L, int narr, int nrec) {
lua_createtable(L, narr, nrec); lua_createtable(L, narr, nrec);
@@ -136,6 +136,12 @@ static int l_set_data(State* L) {
auto& canvas = require_canvas(L, 1); auto& canvas = require_canvas(L, 1);
auto& image = canvas.data(); auto& image = canvas.data();
auto data = image.getData(); auto data = image.getData();
if (lua::isstring(L, 2)) {
auto ptr = reinterpret_cast<ubyte*>(std::stoull(lua::tostring(L, 2)));
std::memcpy(data, ptr, image.getDataSize());
return 0;
}
int len = objlen(L, 2); int len = objlen(L, 2);
if (len < image.getDataSize()) { if (len < image.getDataSize()) {
throw std::runtime_error( throw std::runtime_error(
@@ -167,7 +173,7 @@ static std::unordered_map<std::string, lua_CFunction> methods {
{"blit", lua::wrap<l_blit>}, {"blit", lua::wrap<l_blit>},
{"clear", lua::wrap<l_clear>}, {"clear", lua::wrap<l_clear>},
{"update", lua::wrap<l_update>}, {"update", lua::wrap<l_update>},
{"set_data", lua::wrap<l_set_data>}, {"_set_data", lua::wrap<l_set_data>},
}; };
static int l_meta_index(State* L) { static int l_meta_index(State* L) {
@@ -189,6 +195,9 @@ static int l_meta_index(State* L) {
if (!strcmp(name, "height")) { if (!strcmp(name, "height")) {
return pushinteger(L, data.getHeight()); return pushinteger(L, data.getHeight());
} }
if (!strcmp(name, "set_data")) {
return getglobal(L, "__vc_Canvas_set_data");
}
if (auto func = methods.find(tostring(L, 2)); func != methods.end()) { if (auto func = methods.find(tostring(L, 2)); func != methods.end()) {
return pushcfunction(L, func->second); return pushcfunction(L, func->second);
} }
+1 -1
View File
@@ -120,7 +120,7 @@ std::unique_ptr<Process> scripting::start_coroutine(
lua::loadbuffer(L, 0, source, script.name()); lua::loadbuffer(L, 0, source, script.name());
if (lua::call(L, 1)) { if (lua::call(L, 1)) {
int id = lua::tointeger(L, -1); int id = lua::tointeger(L, -1);
lua::pop(L, 2); lua::pop(L, 1);
return std::make_unique<LuaCoroutine>(L, id); return std::make_unique<LuaCoroutine>(L, id);
} }
lua::pop(L); lua::pop(L);