diff --git a/include/core/framebuffer.hpp b/include/core/framebuffer.hpp index 8f693ae6..07775cf4 100644 --- a/include/core/framebuffer.hpp +++ b/include/core/framebuffer.hpp @@ -101,5 +101,9 @@ void take_screenshot(const std::string& file) throw(std::bad_alloc, std::runtime * Get scale factors. */ std::pair get_scale_factors(uint32_t width, uint32_t height); +/** + * Kill pending requests associated with object. + */ +void render_kill_request(void* obj); #endif diff --git a/include/library/framebuffer.hpp b/include/library/framebuffer.hpp index 47e97083..1ae4e72a 100644 --- a/include/library/framebuffer.hpp +++ b/include/library/framebuffer.hpp @@ -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; diff --git a/include/lua/bitmap.hpp b/include/lua/bitmap.hpp index 5e0ad635..2a2e394c 100644 --- a/include/lua/bitmap.hpp +++ b/include/lua/bitmap.hpp @@ -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 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 pixels; diff --git a/src/core/framebuffer.cpp b/src/core/framebuffer.cpp index 4bf46531..8e89d744 100644 --- a/src/core/framebuffer.cpp +++ b/src/core/framebuffer.cpp @@ -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); +} \ No newline at end of file diff --git a/src/library/framebuffer.cpp b/src/library/framebuffer.cpp index 7aa5c509..59e56f3f 100644 --- a/src/library/framebuffer.cpp +++ b/src/library/framebuffer.cpp @@ -501,6 +501,7 @@ void render_queue::add(struct render_object& obj) throw(std::bad_alloc) struct node* n = reinterpret_cast(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 void render_queue::run(struct framebuffer& 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 void render_queue::run(struct framebuffer& 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; diff --git a/src/lua/gui-bitmap.cpp b/src/lua/gui-bitmap.cpp index 75cfa94e..024d26bc 100644 --- a/src/lua/gui-bitmap.cpp +++ b/src/lua/gui-bitmap.cpp @@ -1,4 +1,5 @@ #include "lua/internal.hpp" +#include "core/framebuffer.hpp" #include "library/framebuffer.hpp" #include "lua/bitmap.hpp" #include @@ -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* _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 void composite_op(struct framebuffer& scr) throw() { if(p) @@ -111,6 +139,7 @@ namespace lua_obj_pin* b; lua_obj_pin* b2; lua_obj_pin* p; + bool killed; }; function_ptr_luafun gui_bitmap("gui.bitmap_draw", [](lua_State* LS, const std::string& fname) -> int {