Fix crash with bitmaps and resetting Lua VM
Kill requests depending on bitmaps and palettes going away, to avoid having the emulator crash if there is a request using those bitmaps and palettes in flight while Lua VM is reset. Noticed by FatRatKnight.
This commit is contained in:
parent
615d525fa6
commit
80c9dcee2d
6 changed files with 77 additions and 5 deletions
|
@ -101,5 +101,9 @@ void take_screenshot(const std::string& file) throw(std::bad_alloc, std::runtime
|
|||
* Get scale factors.
|
||||
*/
|
||||
std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height);
|
||||
/**
|
||||
* Kill pending requests associated with object.
|
||||
*/
|
||||
void render_kill_request(void* obj);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -355,7 +355,10 @@ struct render_object
|
|||
* Destructor.
|
||||
*/
|
||||
virtual ~render_object() throw();
|
||||
|
||||
/**
|
||||
* Kill object function. If it returns true, kill the request. Default is to return false.
|
||||
*/
|
||||
virtual bool kill_request(void* obj) throw();
|
||||
/**
|
||||
* Draw the object.
|
||||
*
|
||||
|
@ -537,7 +540,10 @@ struct render_queue
|
|||
* Frees all objects in the queue without applying them.
|
||||
*/
|
||||
void clear() throw();
|
||||
|
||||
/**
|
||||
* Call kill_request on all objects in queue.
|
||||
*/
|
||||
void kill_request(void* obj) throw();
|
||||
/**
|
||||
* Get memory from internal allocator.
|
||||
*/
|
||||
|
@ -561,7 +567,7 @@ struct render_queue
|
|||
~render_queue() throw();
|
||||
private:
|
||||
void add(struct render_object& obj) throw(std::bad_alloc);
|
||||
struct node { struct render_object* obj; struct node* next; };
|
||||
struct node { struct render_object* obj; struct node* next; bool killed; };
|
||||
struct page { char content[RENDER_PAGE_SIZE]; };
|
||||
struct node* queue_head;
|
||||
struct node* queue_tail;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
struct lua_bitmap
|
||||
{
|
||||
lua_bitmap(uint32_t w, uint32_t h);
|
||||
~lua_bitmap();
|
||||
size_t width;
|
||||
size_t height;
|
||||
std::vector<uint16_t> pixels;
|
||||
|
@ -18,6 +19,7 @@ struct lua_bitmap
|
|||
struct lua_dbitmap
|
||||
{
|
||||
lua_dbitmap(uint32_t w, uint32_t h);
|
||||
~lua_dbitmap();
|
||||
size_t width;
|
||||
size_t height;
|
||||
std::vector<premultiplied_color> pixels;
|
||||
|
|
|
@ -326,3 +326,10 @@ void triplebuffer_logic::end_read() throw()
|
|||
mutex::holder h(*mut);
|
||||
read_active--;
|
||||
}
|
||||
|
||||
void render_kill_request(void* obj)
|
||||
{
|
||||
buffer1.rq.kill_request(obj);
|
||||
buffer2.rq.kill_request(obj);
|
||||
buffer3.rq.kill_request(obj);
|
||||
}
|
|
@ -501,6 +501,7 @@ void render_queue::add(struct render_object& obj) throw(std::bad_alloc)
|
|||
struct node* n = reinterpret_cast<struct node*>(alloc(sizeof(node)));
|
||||
n->obj = &obj;
|
||||
n->next = NULL;
|
||||
n->killed = false;
|
||||
if(queue_tail)
|
||||
queue_tail = queue_tail->next = n;
|
||||
else
|
||||
|
@ -512,7 +513,8 @@ template<bool X> void render_queue::run(struct framebuffer<X>& scr) throw()
|
|||
struct node* tmp = queue_head;
|
||||
while(tmp) {
|
||||
try {
|
||||
(*(tmp->obj))(scr);
|
||||
if(!tmp->killed)
|
||||
(*(tmp->obj))(scr);
|
||||
tmp = tmp->next;
|
||||
} catch(...) {
|
||||
}
|
||||
|
@ -522,7 +524,8 @@ template<bool X> void render_queue::run(struct framebuffer<X>& scr) throw()
|
|||
void render_queue::clear() throw()
|
||||
{
|
||||
while(queue_head) {
|
||||
queue_head->obj->~render_object();
|
||||
if(!queue_head->killed)
|
||||
queue_head->obj->~render_object();
|
||||
queue_head = queue_head->next;
|
||||
}
|
||||
//Release all memory for reuse.
|
||||
|
@ -545,6 +548,22 @@ void* render_queue::alloc(size_t block) throw(std::bad_alloc)
|
|||
return mem;
|
||||
}
|
||||
|
||||
void render_queue::kill_request(void* obj) throw()
|
||||
{
|
||||
struct node* tmp = queue_head;
|
||||
while(tmp) {
|
||||
try {
|
||||
if(!tmp->killed && tmp->obj->kill_request(obj)) {
|
||||
//Kill this request.
|
||||
tmp->killed = true;
|
||||
tmp->obj->~render_object();
|
||||
}
|
||||
tmp = tmp->next;
|
||||
} catch(...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render_queue::render_queue() throw()
|
||||
{
|
||||
queue_head = NULL;
|
||||
|
@ -562,6 +581,11 @@ render_object::~render_object() throw()
|
|||
{
|
||||
}
|
||||
|
||||
bool render_object::kill_request(void* obj) throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bitmap_font::bitmap_font() throw(std::bad_alloc)
|
||||
{
|
||||
bad_glyph_data[0] = 0x018001AAU;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "lua/internal.hpp"
|
||||
#include "core/framebuffer.hpp"
|
||||
#include "library/framebuffer.hpp"
|
||||
#include "lua/bitmap.hpp"
|
||||
#include <vector>
|
||||
|
@ -11,6 +12,11 @@ lua_bitmap::lua_bitmap(uint32_t w, uint32_t h)
|
|||
memset(&pixels[0], 0, width * height);
|
||||
}
|
||||
|
||||
lua_bitmap::~lua_bitmap()
|
||||
{
|
||||
render_kill_request(this);
|
||||
}
|
||||
|
||||
lua_dbitmap::lua_dbitmap(uint32_t w, uint32_t h)
|
||||
{
|
||||
width = w;
|
||||
|
@ -18,6 +24,11 @@ lua_dbitmap::lua_dbitmap(uint32_t w, uint32_t h)
|
|||
pixels.resize(width * height);
|
||||
}
|
||||
|
||||
lua_dbitmap::~lua_dbitmap()
|
||||
{
|
||||
render_kill_request(this);
|
||||
}
|
||||
|
||||
lua_palette::lua_palette()
|
||||
{
|
||||
palette_mutex = &mutex::aquire();
|
||||
|
@ -40,6 +51,7 @@ namespace
|
|||
b = _bitmap;
|
||||
b2 = NULL;
|
||||
p = _palette;
|
||||
killed = false;
|
||||
}
|
||||
|
||||
render_object_bitmap(int32_t _x, int32_t _y, lua_obj_pin<lua_dbitmap>* _bitmap) throw()
|
||||
|
@ -49,15 +61,31 @@ namespace
|
|||
b = NULL;
|
||||
b2 = _bitmap;
|
||||
p = NULL;
|
||||
killed = false;
|
||||
}
|
||||
|
||||
~render_object_bitmap() throw()
|
||||
{
|
||||
if(killed)
|
||||
return;
|
||||
delete b;
|
||||
delete b2;
|
||||
delete p;
|
||||
}
|
||||
|
||||
bool kill_request(void* obj) throw()
|
||||
{
|
||||
if(!obj)
|
||||
return false; //Can't kill on NULL object.
|
||||
if(p && p->object() == obj)
|
||||
return killed = true;
|
||||
if(b && b->object() == obj)
|
||||
return killed = true;
|
||||
if(b2 && b2->object() == obj)
|
||||
return killed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<bool T> void composite_op(struct framebuffer<T>& scr) throw()
|
||||
{
|
||||
if(p)
|
||||
|
@ -111,6 +139,7 @@ namespace
|
|||
lua_obj_pin<lua_bitmap>* b;
|
||||
lua_obj_pin<lua_dbitmap>* b2;
|
||||
lua_obj_pin<lua_palette>* p;
|
||||
bool killed;
|
||||
};
|
||||
|
||||
function_ptr_luafun gui_bitmap("gui.bitmap_draw", [](lua_State* LS, const std::string& fname) -> int {
|
||||
|
|
Loading…
Add table
Reference in a new issue