Memory tracker: Add tracking of render objects
[lsnes.git] / src / lua / gui-rqueue.cpp
blob83344cf58f669c8905efd4c81a8a38f1565bb328
1 #include "core/framebuffer.hpp"
2 #include "core/instance.hpp"
3 #include "core/misc.hpp"
4 #include "lua/internal.hpp"
5 #include "lua/bitmap.hpp"
7 namespace
9 struct lua_renderqueue
11 lua_renderqueue(lua::state& L, uint32_t width, uint32_t height) throw();
12 static size_t overcommit(uint32_t width, uint32_t height) { return 0; }
13 ~lua_renderqueue() throw() {}
14 lua::render_context* get() { return &lctx; }
15 std::string print()
17 size_t s = rqueue.get_object_count();
18 return (stringfmt() << s << " " << ((s != 1) ? "objects" : "object")).str();
20 static int create(lua::state& L, lua::parameters& P);
21 static int setnull(lua::state& L, lua::parameters& P);
22 int run(lua::state& L, lua::parameters& P)
24 auto& core = CORE();
25 if(!core.lua2->render_ctx) return 0;
27 lua::render_context* ptr = get();
28 if(ptr->top_gap != std::numeric_limits<uint32_t>::max())
29 core.lua2->render_ctx->top_gap = ptr->top_gap;
30 if(ptr->right_gap != std::numeric_limits<uint32_t>::max())
31 core.lua2->render_ctx->right_gap = ptr->right_gap;
32 if(ptr->bottom_gap != std::numeric_limits<uint32_t>::max())
33 core.lua2->render_ctx->bottom_gap = ptr->bottom_gap;
34 if(ptr->left_gap != std::numeric_limits<uint32_t>::max())
35 core.lua2->render_ctx->left_gap = ptr->left_gap;
36 core.lua2->render_ctx->queue->copy_from(*ptr->queue);
37 return 0;
39 int synchronous_repaint(lua::state& L, lua::parameters& P)
41 auto& core = CORE();
42 lua::objpin<lua_renderqueue> q;
44 P(q);
46 core.lua2->synchronous_paint_ctx = &*q;
47 core.fbuf->redraw_framebuffer();
48 core.lua2->synchronous_paint_ctx = NULL;
49 return 0;
51 int clear(lua::state& L, lua::parameters& P)
53 lua::render_context* ptr = get();
54 ptr->top_gap = std::numeric_limits<uint32_t>::max();
55 ptr->right_gap = std::numeric_limits<uint32_t>::max();
56 ptr->bottom_gap = std::numeric_limits<uint32_t>::max();
57 ptr->left_gap = std::numeric_limits<uint32_t>::max();
58 ptr->queue->clear();
59 return 0;
61 int set(lua::state& L, lua::parameters& P)
63 auto& core = CORE();
64 lua::objpin<lua_renderqueue> q;
66 P(q);
68 lua::render_context* ptr = q->get();
69 if(!core.lua2->renderq_redirect || core.lua2->renderq_last != core.lua2->render_ctx)
70 core.lua2->renderq_saved = core.lua2->render_ctx;
71 core.lua2->render_ctx = core.lua2->renderq_last = ptr;
72 core.lua2->renderq_redirect = true;
73 return 0;
75 int render(lua::state& L, lua::parameters& P)
77 uint32_t rwidth = lctx.width + rdgap(lctx.left_gap) + rdgap(lctx.right_gap);
78 uint32_t rheight = lctx.height + rdgap(lctx.top_gap) + rdgap(lctx.bottom_gap);
79 uint32_t xoff = rdgap(lctx.left_gap);
80 uint32_t yoff = rdgap(lctx.top_gap);
81 framebuffer::fb<false> fb;
82 fb.reallocate(rwidth, rheight);
83 fb.set_origin(xoff, yoff);
84 rqueue.run(fb);
85 lua_dbitmap* b = lua::_class<lua_dbitmap>::create(L, rwidth, rheight);
86 for(auto y = 0U; y < rheight; y++) {
87 const uint32_t* rowp = fb.rowptr(y);
88 auto rowt = &b->pixels[y * rwidth];
89 for(auto x = 0U; x < rwidth; x++) {
90 uint32_t v = rowp[x];
91 uint64_t c = -1;
92 if(v >> 24)
93 c = ((256 - (v >> 24) - (v >> 31)) << 24) + (v & 0xFFFFFF);
94 rowt[x] = c;
97 return 1;
99 private:
100 uint32_t rdgap(uint32_t v)
102 return (v + 1) ? v : 0;
104 framebuffer::queue rqueue;
105 lua::render_context lctx;
108 lua_renderqueue::lua_renderqueue(lua::state& L, uint32_t width, uint32_t height) throw()
109 : rqueue(mem_tracker())
111 lctx.left_gap = std::numeric_limits<uint32_t>::max();
112 lctx.right_gap = std::numeric_limits<uint32_t>::max();
113 lctx.bottom_gap = std::numeric_limits<uint32_t>::max();
114 lctx.top_gap = std::numeric_limits<uint32_t>::max();
115 lctx.queue = &rqueue;
116 lctx.width = width;
117 lctx.height = height;
120 int lua_renderqueue::create(lua::state& L, lua::parameters& P)
122 int32_t x, y;
124 P(x, y);
126 lua::_class<lua_renderqueue>::create(L, x, y);
127 return 1;
130 int lua_renderqueue::setnull(lua::state& L, lua::parameters& P)
132 auto& core = CORE();
133 if(core.lua2->renderq_redirect && core.lua2->renderq_last == core.lua2->render_ctx)
134 //If there is valid redirect, undo it.
135 core.lua2->render_ctx = core.lua2->renderq_saved;
136 core.lua2->renderq_redirect = false;
137 core.lua2->renderq_last = NULL;
138 core.lua2->renderq_saved = NULL;
139 return 0;
142 lua::_class<lua_renderqueue> LUA_class_lua_renderqueue(lua_class_gui, "RENDERCTX", {
143 {"new", lua_renderqueue::create},
144 {"setnull", lua_renderqueue::setnull},
145 }, {
146 {"run", &lua_renderqueue::run},
147 {"synchronous_repaint", &lua_renderqueue::synchronous_repaint},
148 {"clear", &lua_renderqueue::clear},
149 {"set", &lua_renderqueue::set},
150 {"render", &lua_renderqueue::render},
151 }, &lua_renderqueue::print);
154 void lua_renderq_run(lua::render_context* ctx, void* _sctx)
156 lua_renderqueue* sctx = (lua_renderqueue*)_sctx;
157 lua::render_context* ptr = sctx->get();
158 if(ptr->top_gap != std::numeric_limits<uint32_t>::max())
159 ctx->top_gap = ptr->top_gap;
160 if(ptr->right_gap != std::numeric_limits<uint32_t>::max())
161 ctx->right_gap = ptr->right_gap;
162 if(ptr->bottom_gap != std::numeric_limits<uint32_t>::max())
163 ctx->bottom_gap = ptr->bottom_gap;
164 if(ptr->left_gap != std::numeric_limits<uint32_t>::max())
165 ctx->left_gap = ptr->left_gap;
166 ctx->queue->copy_from(*ptr->queue);