From 7ba7fc24f6efa892a749c4ab45fc716d60fe4f7b Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Mon, 31 Mar 2014 12:42:33 +0300 Subject: [PATCH] Use overcommit for palettes, bitmaps, dbitmaps and tilemaps This makes the large size of these objects visible to Lua, hopefully allowing Lua GC to make better decisions. --- include/library/lua-class.hpp | 11 +++ include/lua/bitmap.hpp | 24 +++++-- src/emulation/bsnes-legacy/bitmap.cpp | 4 +- src/lua/gui-bitmap.cpp | 99 ++++++++++++++++++--------- src/lua/gui-tilemap.cpp | 20 ++++-- 5 files changed, 109 insertions(+), 49 deletions(-) diff --git a/include/library/lua-class.hpp b/include/library/lua-class.hpp index 2ec814ea..505fe4c5 100644 --- a/include/library/lua-class.hpp +++ b/include/library/lua-class.hpp @@ -204,6 +204,17 @@ private: bool registered; }; +static const size_t overcommit_std_align = 32; + +/** + * Align a overcommit pointer. + */ +template U* align_overcommit(T* th) +{ + size_t ptr = reinterpret_cast(th) + sizeof(T); + return reinterpret_cast(ptr + (overcommit_std_align - ptr % overcommit_std_align) % overcommit_std_align); +} + /** * The type of Lua classes. */ diff --git a/include/lua/bitmap.hpp b/include/lua/bitmap.hpp index 91e59843..c3e1d937 100644 --- a/include/lua/bitmap.hpp +++ b/include/lua/bitmap.hpp @@ -14,9 +14,15 @@ struct lua_palette { - std::vector colors; + std::vector lcolors; + framebuffer::color* colors; + framebuffer::color* scolors; lua_palette(lua::state& L); - static size_t overcommit() { return 0; } + size_t color_count; + const static size_t reserved_colors = 32; + static size_t overcommit() { + return lua::overcommit_std_align + reserved_colors * sizeof(framebuffer::color); + } ~lua_palette(); threads::lock palette_mutex; std::string print(); @@ -27,16 +33,20 @@ struct lua_palette int hash(lua::state& L, lua::parameters& P); int debug(lua::state& L, lua::parameters& P); int adjust_transparency(lua::state& L, lua::parameters& P); + void adjust_palette_size(size_t newsize); + void push_back(const framebuffer::color& c); }; struct lua_bitmap { lua_bitmap(lua::state& L, uint32_t w, uint32_t h); - static size_t overcommit(uint32_t w, uint32_t h) { return 0; } + static size_t overcommit(uint32_t w, uint32_t h) { + return lua::overcommit_std_align + sizeof(uint16_t) * w * h; + } ~lua_bitmap(); size_t width; size_t height; - std::vector pixels; + uint16_t* pixels; std::vector save_png(const lua_palette& pal) const; std::string print(); static int create(lua::state& L, lua::parameters& P); @@ -54,11 +64,13 @@ struct lua_bitmap struct lua_dbitmap { lua_dbitmap(lua::state& L, uint32_t w, uint32_t h); - static size_t overcommit(uint32_t w, uint32_t h) { return 0; } + static size_t overcommit(uint32_t w, uint32_t h) { + return lua::overcommit_std_align + sizeof(framebuffer::color) * w * h; + } ~lua_dbitmap(); size_t width; size_t height; - std::vector pixels; + framebuffer::color* pixels; std::vector save_png() const; std::string print(); static int create(lua::state& L, lua::parameters& P); diff --git a/src/emulation/bsnes-legacy/bitmap.cpp b/src/emulation/bsnes-legacy/bitmap.cpp index a7e55f5c..433a49a5 100644 --- a/src/emulation/bsnes-legacy/bitmap.cpp +++ b/src/emulation/bsnes-legacy/bitmap.cpp @@ -109,7 +109,7 @@ namespace if(!create) { P(p); - size_t ccount = p->colors.size(); + size_t ccount = p->color_count; if(ccount != 16 && ccount != 256) throw std::runtime_error("Palette to read must be 16 or 256 colors"); full = (ccount == 256); @@ -127,7 +127,7 @@ namespace size_t ps = full ? 256 : 16; if(create) { p = lua::_class::create(L); - p->colors.resize(ps); + p->adjust_palette_size(ps); } uint8_t* mem = reinterpret_cast(lsnes_memory.get_physical_mapping(addr, 2 * ps)); if(mem) { diff --git a/src/lua/gui-bitmap.cpp b/src/lua/gui-bitmap.cpp index 60dd07e9..604a3abc 100644 --- a/src/lua/gui-bitmap.cpp +++ b/src/lua/gui-bitmap.cpp @@ -41,11 +41,11 @@ std::vector lua_bitmap::save_png(const lua_palette& pal) const img.has_palette = true; img.has_alpha = false; img.data.resize(width * height); - img.palette.resize(pal.colors.size()); + img.palette.resize(pal.color_count); for(size_t i = 0; i < width * height; i++) { img.data[i] = pixels[i]; } - for(size_t i = 0; i < pal.colors.size(); i++) { + for(size_t i = 0; i < pal.color_count; i++) { const framebuffer::color& c = pal.colors[i]; if(c.origa != 256) img.has_alpha = true; @@ -100,8 +100,8 @@ namespace size_t w, h; framebuffer::color* palette; if(b) { - palette = &p->colors[0]; - pallim = p->colors.size(); + palette = p->colors; + pallim = p->color_count; w = b->width; h = b->height; } else { @@ -150,7 +150,7 @@ namespace operand_dbitmap(lua_dbitmap& _bitmap) : bitmap(_bitmap), _transparent(-1) { - pixels = &bitmap.pixels[0]; + pixels = bitmap.pixels; } size_t get_width() { return bitmap.width; } size_t get_height() { return bitmap.height; } @@ -172,7 +172,7 @@ namespace operand_bitmap(lua_bitmap& _bitmap) : bitmap(_bitmap) { - pixels = &bitmap.pixels[0]; + pixels = bitmap.pixels; } size_t get_width() { return bitmap.width; } size_t get_height() { return bitmap.height; } @@ -193,9 +193,9 @@ namespace operand_bitmap_pal(lua_bitmap& _bitmap, lua_palette& _palette) : bitmap(_bitmap), palette(_palette), _transparent(-1) { - pixels = &bitmap.pixels[0]; - limit = palette.colors.size(); - pal = &palette.colors[0]; + pixels = bitmap.pixels; + limit = palette.color_count; + pal = palette.colors; } size_t get_width() { return bitmap.width; } size_t get_height() { return bitmap.height; } @@ -271,8 +271,8 @@ namespace { srcdest_priority(lua_bitmap& dest, lua_bitmap& src) { - darray = &dest.pixels[0]; - sarray = &src.pixels[0]; + darray = dest.pixels; + sarray = src.pixels; swidth = src.width; sheight = src.height; dwidth = dest.width; @@ -525,7 +525,7 @@ namespace lua_palette* p = lua::_class::create(L); for(size_t i = 0; i < bitmap.w * bitmap.h; i++) b->pixels[i] = bitmap.bitmap[i]; - p->colors.resize(bitmap.palette.size()); + p->adjust_palette_size(bitmap.palette.size()); for(size_t i = 0; i < bitmap.palette.size(); i++) p->colors[i] = framebuffer::color(bitmap.palette[i]); return 2; @@ -638,7 +638,7 @@ namespace lua_palette* p = lua::_class::create(L); for(size_t i = 0; i < img.width * img.height; i++) b->pixels[i] = img.data[i]; - p->colors.resize(img.palette.size()); + p->adjust_palette_size(img.palette.size()); for(size_t i = 0; i < img.palette.size(); i++) p->colors[i] = framebuffer::color(mangle_color(img.palette[i])); return 2; @@ -667,18 +667,18 @@ namespace cb = parse_value(r[3]); ca = 256 - parse_value(r[4]); if(ca == 256) - p->colors.push_back(framebuffer::color(-1)); + p->push_back(framebuffer::color(-1)); else - p->colors.push_back(framebuffer::color((ca << 24) | (cr << 16) + p->push_back(framebuffer::color((ca << 24) | (cr << 16) | (cg << 8) | cb)); } else if(r = regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line)) { int64_t cr, cg, cb; cr = parse_value(r[1]); cg = parse_value(r[2]); cb = parse_value(r[3]); - p->colors.push_back(framebuffer::color((cr << 16) | (cg << 8) | cb)); + p->push_back(framebuffer::color((cr << 16) | (cg << 8) | cb)); } else if(r = regex("[ \t]*([^ \t]|[^ \t].*[^ \t])[ \t]*", line)) { - p->colors.push_back(framebuffer::color(r[1])); + p->push_back(framebuffer::color(r[1])); } else throw std::runtime_error("Invalid line format (" + line + ")"); } @@ -753,6 +753,10 @@ namespace /** Palette **/ lua_palette::lua_palette(lua::state& L) { + color_count = 0; + scolors = colors = lua::align_overcommit(this); + for(unsigned i = 0; i < reserved_colors; i++) + scolors[i] = framebuffer::color(-1); } lua_palette::~lua_palette() @@ -761,7 +765,7 @@ lua_palette::~lua_palette() std::string lua_palette::print() { - size_t s = colors.size(); + size_t s = color_count; return (stringfmt() << s << " " << ((s != 1) ? "colors" : "color")).str(); } @@ -805,11 +809,8 @@ int lua_palette::set(lua::state& L, lua::parameters& P) P(P.skipped(), c, nc); - //The lock protects only the internals of colors array. - if(this->colors.size() <= c) { - this->palette_mutex.lock(); - this->colors.resize(static_cast(c) + 1); - this->palette_mutex.unlock(); + if(this->color_count <= c) { + this->adjust_palette_size(static_cast(c) + 1); } this->colors[c] = nc; return 0; @@ -822,7 +823,7 @@ int lua_palette::hash(lua::state& L, lua::parameters& P) int bufferuse = 0; char buf[buffersize]; unsigned realsize = 0; - for(unsigned i = 0; i < this->colors.size(); i++) + for(unsigned i = 0; i < this->color_count; i++) if(this->colors[i].origa) realsize = i + 1; for(unsigned i = 0; i < realsize; i++) { if(bufferuse + 6 > buffersize) { @@ -840,9 +841,8 @@ int lua_palette::hash(lua::state& L, lua::parameters& P) int lua_palette::debug(lua::state& L, lua::parameters& P) { - size_t i = 0; - for(auto c : this->colors) - messages << "Color #" << (i++) << ": " << c.orig << ":" << c.origa << std::endl; + for(size_t i = 0; i < color_count; i++) + messages << "Color #" << i << ": " << colors[i].orig << ":" << colors[i].origa << std::endl; return 0; } @@ -852,18 +852,45 @@ int lua_palette::adjust_transparency(lua::state& L, lua::parameters& P) P(P.skipped(), tadj); - for(auto& c : this->colors) - c = tadjust(c, tadj); + for(size_t i = 0; i < color_count; i++) + colors[i] = tadjust(colors[i], tadj); return 0; } +void lua_palette::adjust_palette_size(size_t newsize) +{ + threads::alock h(palette_mutex); + if(newsize > reserved_colors) { + lcolors.resize(newsize); + if(color_count <= reserved_colors) { + for(unsigned i = 0; i < color_count; i++) + lcolors[i] = colors[i]; + } + colors = &lcolors[0]; + } else { + if(color_count > reserved_colors) { + for(unsigned i = 0; i < color_count; i++) + scolors[i] = lcolors[i]; + } + colors = scolors; + } + color_count = newsize; +} + +void lua_palette::push_back(const framebuffer::color& cx) +{ + size_t c = color_count; + adjust_palette_size(c + 1); + colors[c] = cx; +} + /** BITMAP **/ lua_bitmap::lua_bitmap(lua::state& L, uint32_t w, uint32_t h) { width = w; height = h; - pixels.resize(width * height); - memset(&pixels[0], 0, width * height); + pixels = lua::align_overcommit(this); + memset(pixels, 0, 2 * width * height); } lua_bitmap::~lua_bitmap() @@ -1026,7 +1053,11 @@ lua_dbitmap::lua_dbitmap(lua::state& L, uint32_t w, uint32_t h) { width = w; height = h; - pixels.resize(width * height); + pixels = lua::align_overcommit(this); + //Initialize the bitmap data. + framebuffer::color transparent(-1); + for(size_t i = 0; i < width * height; i++) + new(pixels + i) framebuffer::color(transparent); } lua_dbitmap::~lua_dbitmap() @@ -1206,8 +1237,8 @@ int lua_dbitmap::adjust_transparency(lua::state& L, lua::parameters& P) P(P.skipped(), tadj); - for(auto& c : this->pixels) - c = tadjust(c, tadj); + for(size_t i = 0; i < width * height; i++) + pixels[i] = tadjust(pixels[i], tadj); return 0; } diff --git a/src/lua/gui-tilemap.cpp b/src/lua/gui-tilemap.cpp index 0cd3aaf1..3e739dee 100644 --- a/src/lua/gui-tilemap.cpp +++ b/src/lua/gui-tilemap.cpp @@ -31,7 +31,9 @@ namespace struct tilemap { tilemap(lua::state& L, size_t _width, size_t _height, size_t _cwidth, size_t _cheight); - static size_t overcommit(size_t _width, size_t _height, size_t _cwidth, size_t _cheight) { return 0; } + static size_t overcommit(size_t _width, size_t _height, size_t _cwidth, size_t _cheight) { + return lua::overcommit_std_align + 2 * sizeof(tilemap_entry) * _width * _height; + } ~tilemap() { threads::alock h(lock); @@ -131,8 +133,7 @@ namespace y0 + h < y0) throw std::runtime_error("Scroll window out of range"); if(!ox && !oy) return 0; - std::vector tmp; - tmp.resize(w * h); + tilemap_entry* tmp = tmpmap; for(size_t _y = 0; _y < h; _y++) { size_t y = _y + y0; size_t sy = calcshift(y, oy, h, y0, circy); @@ -161,7 +162,8 @@ namespace size_t height; size_t cwidth; size_t cheight; - std::vector map; + tilemap_entry* map; + tilemap_entry* tmpmap; threads::lock lock; }; @@ -208,8 +210,8 @@ namespace { if(xmin >= xmax || ymin >= ymax) return; p.palette_mutex.lock(); - framebuffer::color* palette = &p.colors[0]; - size_t pallim = p.colors.size(); + framebuffer::color* palette = p.colors; + size_t pallim = p.color_count; for(int32_t r = ymin; r < ymax; r++) { typename framebuffer::fb::element_t* rptr = scr.rowptr(yp + r); @@ -317,6 +319,10 @@ namespace { if(width * height / height != width) throw std::bad_alloc(); - map.resize(width * height); + map = lua::align_overcommit(this); + tmpmap = &map[width * height]; + //Initialize the map! + for(size_t i = 0; i < 2 * width * height; i++) + new(map + i) tilemap_entry(); } }