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.
This commit is contained in:
Ilari Liusvaara 2014-03-31 12:42:33 +03:00
parent e0827ce54f
commit 7ba7fc24f6
5 changed files with 109 additions and 49 deletions

View file

@ -204,6 +204,17 @@ private:
bool registered;
};
static const size_t overcommit_std_align = 32;
/**
* Align a overcommit pointer.
*/
template<typename T, typename U> U* align_overcommit(T* th)
{
size_t ptr = reinterpret_cast<size_t>(th) + sizeof(T);
return reinterpret_cast<U*>(ptr + (overcommit_std_align - ptr % overcommit_std_align) % overcommit_std_align);
}
/**
* The type of Lua classes.
*/

View file

@ -14,9 +14,15 @@
struct lua_palette
{
std::vector<framebuffer::color> colors;
std::vector<framebuffer::color> 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<uint16_t> pixels;
uint16_t* pixels;
std::vector<char> 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<framebuffer::color> pixels;
framebuffer::color* pixels;
std::vector<char> save_png() const;
std::string print();
static int create(lua::state& L, lua::parameters& P);

View file

@ -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<lua_palette>::create(L);
p->colors.resize(ps);
p->adjust_palette_size(ps);
}
uint8_t* mem = reinterpret_cast<uint8_t*>(lsnes_memory.get_physical_mapping(addr, 2 * ps));
if(mem) {

View file

@ -41,11 +41,11 @@ std::vector<char> 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<lua_palette>::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<lua_palette>::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<uint8_t>(r[3]);
ca = 256 - parse_value<uint16_t>(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<uint8_t>(r[1]);
cg = parse_value<uint8_t>(r[2]);
cb = parse_value<uint8_t>(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<lua_palette, framebuffer::color>(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<uint32_t>(c) + 1);
this->palette_mutex.unlock();
if(this->color_count <= c) {
this->adjust_palette_size(static_cast<uint32_t>(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<lua_bitmap, uint16_t>(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<lua_dbitmap, framebuffer::color>(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;
}

View file

@ -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<tilemap_entry> 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<tilemap_entry> 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<T>::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<tilemap, tilemap_entry>(this);
tmpmap = &map[width * height];
//Initialize the map!
for(size_t i = 0; i < 2 * width * height; i++)
new(map + i) tilemap_entry();
}
}