experimental optimize canvas:set_data using ffi
This commit is contained in:
parent
6078a8802e
commit
e48216da40
@ -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
|
||||
function is_array(x)
|
||||
if #x > 0 then
|
||||
|
||||
@ -88,14 +88,17 @@ static void create_libs(State* L, StateType stateType) {
|
||||
|
||||
void lua::init_state(State* L, StateType stateType) {
|
||||
// Allowed standard libraries
|
||||
pop(L, luaopen_base(L));
|
||||
pop(L, luaopen_math(L));
|
||||
pop(L, luaopen_string(L));
|
||||
pop(L, luaopen_table(L));
|
||||
pop(L, luaopen_debug(L));
|
||||
pop(L, luaopen_jit(L));
|
||||
pop(L, luaopen_bit(L));
|
||||
pop(L, luaopen_os(L));
|
||||
luaL_openlibs(L);
|
||||
|
||||
if (getglobal(L, "require")) {
|
||||
pushstring(L, "ffi");
|
||||
if (call_nothrow(L, 1, 1)) {
|
||||
setglobal(L, "ffi");
|
||||
}
|
||||
}
|
||||
pushnil(L);
|
||||
setglobal(L, "io");
|
||||
|
||||
const char* removed_os[] {
|
||||
"execute", "exit", "remove", "rename", "setlocale", "tmpname", nullptr};
|
||||
remove_lib_funcs(L, "os", removed_os);
|
||||
|
||||
@ -163,20 +163,23 @@ int lua::call(State* L, int argc, int nresults) {
|
||||
int handler_pos = gettop(L) - argc;
|
||||
pushcfunction(L, l_error_handler);
|
||||
insert(L, handler_pos);
|
||||
int top = gettop(L);
|
||||
if (lua_pcall(L, argc, nresults, handler_pos)) {
|
||||
std::string log = tostring(L, -1);
|
||||
pop(L);
|
||||
remove(L, handler_pos);
|
||||
throw luaerror(log);
|
||||
}
|
||||
int added = gettop(L) - (top - argc - 1);
|
||||
remove(L, handler_pos);
|
||||
return nresults == -1 ? 1 : nresults;
|
||||
return added;
|
||||
}
|
||||
|
||||
int lua::call_nothrow(State* L, int argc, int nresults) {
|
||||
int handler_pos = gettop(L) - argc;
|
||||
pushcfunction(L, l_error_handler);
|
||||
insert(L, handler_pos);
|
||||
int top = gettop(L);
|
||||
if (lua_pcall(L, argc, -1, handler_pos)) {
|
||||
auto errorstr = tostring(L, -1);
|
||||
if (errorstr) {
|
||||
@ -188,8 +191,9 @@ int lua::call_nothrow(State* L, int argc, int nresults) {
|
||||
remove(L, handler_pos);
|
||||
return 0;
|
||||
}
|
||||
int added = gettop(L) - (top - argc - 1);
|
||||
remove(L, handler_pos);
|
||||
return 1;
|
||||
return added;
|
||||
}
|
||||
|
||||
void lua::dump_stack(State* L) {
|
||||
|
||||
@ -25,7 +25,8 @@ namespace lua {
|
||||
if (n < 0) {
|
||||
abort();
|
||||
}
|
||||
if (lua_gettop(L) < n) {
|
||||
int top = lua_gettop(L);
|
||||
if (top < n) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
@ -63,6 +64,9 @@ namespace lua {
|
||||
inline void rawseti(lua::State* L, int n, int idx = -2) {
|
||||
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) {
|
||||
lua_createtable(L, narr, nrec);
|
||||
|
||||
@ -136,6 +136,12 @@ static int l_set_data(State* L) {
|
||||
auto& canvas = require_canvas(L, 1);
|
||||
auto& image = canvas.data();
|
||||
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);
|
||||
if (len < image.getDataSize()) {
|
||||
throw std::runtime_error(
|
||||
@ -167,7 +173,7 @@ static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"blit", lua::wrap<l_blit>},
|
||||
{"clear", lua::wrap<l_clear>},
|
||||
{"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) {
|
||||
@ -189,6 +195,9 @@ static int l_meta_index(State* L) {
|
||||
if (!strcmp(name, "height")) {
|
||||
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()) {
|
||||
return pushcfunction(L, func->second);
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ std::unique_ptr<Process> scripting::start_coroutine(
|
||||
lua::loadbuffer(L, 0, source, script.name());
|
||||
if (lua::call(L, 1)) {
|
||||
int id = lua::tointeger(L, -1);
|
||||
lua::pop(L, 2);
|
||||
lua::pop(L, 1);
|
||||
return std::make_unique<LuaCoroutine>(L, id);
|
||||
}
|
||||
lua::pop(L);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user