Revert "Remove Lua 5.1 support"
[lsnes.git] / src / lua / gui-rqueue.cpp
blob650f4d3b7d65acf34edff9badfcf830dae0a02eb
1 #include "core/framebuffer.hpp"
2 #include "core/instance.hpp"
3 #include "lua/internal.hpp"
4 #include "lua/bitmap.hpp"
6 namespace
8 struct lua_renderqueue
10 lua_renderqueue(lua::state& L, uint32_t width, uint32_t height) throw();
11 static size_t overcommit(uint32_t width, uint32_t height) { return 0; }
12 ~lua_renderqueue() throw() {}
13 lua::render_context* get() { return &lctx; }
14 std::string print()
16 size_t s = rqueue.get_object_count();
17 return (stringfmt() << s << " " << ((s != 1) ? "objects" : "object")).str();
19 static int create(lua::state& L, lua::parameters& P);
20 static int setnull(lua::state& L, lua::parameters& P);
21 int run(lua::state& L, lua::parameters& P)
23 auto& core = CORE();
24 if(!core.lua2->render_ctx) return 0;
26 lua::render_context* ptr = get();
27 if(ptr->top_gap != std::numeric_limits<uint32_t>::max())
28 core.lua2->render_ctx->top_gap = ptr->top_gap;
29 if(ptr->right_gap != std::numeric_limits<uint32_t>::max())
30 core.lua2->render_ctx->right_gap = ptr->right_gap;
31 if(ptr->bottom_gap != std::numeric_limits<uint32_t>::max())
32 core.lua2->render_ctx->bottom_gap = ptr->bottom_gap;
33 if(ptr->left_gap != std::numeric_limits<uint32_t>::max())
34 core.lua2->render_ctx->left_gap = ptr->left_gap;
35 core.lua2->render_ctx->queue->copy_from(*ptr->queue);
36 return 0;
38 int synchronous_repaint(lua::state& L, lua::parameters& P)
40 auto& core = CORE();
41 lua::objpin<lua_renderqueue> q;
43 P(q);
45 core.lua2->synchronous_paint_ctx = &*q;
46 core.fbuf->redraw_framebuffer();
47 core.lua2->synchronous_paint_ctx = NULL;
48 return 0;
50 int clear(lua::state& L, lua::parameters& P)
52 lua::render_context* ptr = get();
53 ptr->top_gap = std::numeric_limits<uint32_t>::max();
54 ptr->right_gap = std::numeric_limits<uint32_t>::max();
55 ptr->bottom_gap = std::numeric_limits<uint32_t>::max();
56 ptr->left_gap = std::numeric_limits<uint32_t>::max();
57 ptr->queue->clear();
58 return 0;
60 int set(lua::state& L, lua::parameters& P)
62 auto& core = CORE();
63 lua::objpin<lua_renderqueue> q;
65 P(q);
67 lua::render_context* ptr = q->get();
68 if(!core.lua2->renderq_redirect || core.lua2->renderq_last != core.lua2->render_ctx)
69 core.lua2->renderq_saved = core.lua2->render_ctx;
70 core.lua2->render_ctx = core.lua2->renderq_last = ptr;
71 core.lua2->renderq_redirect = true;
72 return 0;
74 int render(lua::state& L, lua::parameters& P)
76 uint32_t rwidth = lctx.width + rdgap(lctx.left_gap) + rdgap(lctx.right_gap);
77 uint32_t rheight = lctx.height + rdgap(lctx.top_gap) + rdgap(lctx.bottom_gap);
78 uint32_t xoff = rdgap(lctx.left_gap);
79 uint32_t yoff = rdgap(lctx.top_gap);
80 framebuffer::fb<false> fb;
81 fb.reallocate(rwidth, rheight);
82 fb.set_origin(xoff, yoff);
83 rqueue.run(fb);
84 lua_dbitmap* b = lua::_class<lua_dbitmap>::create(L, rwidth, rheight);
85 for(auto y = 0U; y < rheight; y++) {
86 const uint32_t* rowp = fb.rowptr(y);
87 auto rowt = &b->pixels[y * rwidth];
88 for(auto x = 0U; x < rwidth; x++) {
89 uint32_t v = rowp[x];
90 uint64_t c = -1;
91 if(v >> 24)
92 c = ((256 - (v >> 24) - (v >> 31)) << 24) + (v & 0xFFFFFF);
93 rowt[x] = c;
96 return 1;
98 private:
99 uint32_t rdgap(uint32_t v)
101 return (v + 1) ? v : 0;
103 framebuffer::queue rqueue;
104 lua::render_context lctx;
107 lua_renderqueue::lua_renderqueue(lua::state& L, uint32_t width, uint32_t height) throw()
109 lctx.left_gap = std::numeric_limits<uint32_t>::max();
110 lctx.right_gap = std::numeric_limits<uint32_t>::max();
111 lctx.bottom_gap = std::numeric_limits<uint32_t>::max();
112 lctx.top_gap = std::numeric_limits<uint32_t>::max();
113 lctx.queue = &rqueue;
114 lctx.width = width;
115 lctx.height = height;
118 int lua_renderqueue::create(lua::state& L, lua::parameters& P)
120 int32_t x, y;
122 P(x, y);
124 lua::_class<lua_renderqueue>::create(L, x, y);
125 return 1;
128 int lua_renderqueue::setnull(lua::state& L, lua::parameters& P)
130 auto& core = CORE();
131 if(core.lua2->renderq_redirect && core.lua2->renderq_last == core.lua2->render_ctx)
132 //If there is valid redirect, undo it.
133 core.lua2->render_ctx = core.lua2->renderq_saved;
134 core.lua2->renderq_redirect = false;
135 core.lua2->renderq_last = NULL;
136 core.lua2->renderq_saved = NULL;
137 return 0;
140 lua::_class<lua_renderqueue> LUA_class_lua_renderqueue(lua_class_gui, "RENDERCTX", {
141 {"new", lua_renderqueue::create},
142 {"setnull", lua_renderqueue::setnull},
143 }, {
144 {"run", &lua_renderqueue::run},
145 {"synchronous_repaint", &lua_renderqueue::synchronous_repaint},
146 {"clear", &lua_renderqueue::clear},
147 {"set", &lua_renderqueue::set},
148 {"render", &lua_renderqueue::render},
149 }, &lua_renderqueue::print);
152 void lua_renderq_run(lua::render_context* ctx, void* _sctx)
154 lua_renderqueue* sctx = (lua_renderqueue*)_sctx;
155 lua::render_context* ptr = sctx->get();
156 if(ptr->top_gap != std::numeric_limits<uint32_t>::max())
157 ctx->top_gap = ptr->top_gap;
158 if(ptr->right_gap != std::numeric_limits<uint32_t>::max())
159 ctx->right_gap = ptr->right_gap;
160 if(ptr->bottom_gap != std::numeric_limits<uint32_t>::max())
161 ctx->bottom_gap = ptr->bottom_gap;
162 if(ptr->left_gap != std::numeric_limits<uint32_t>::max())
163 ctx->left_gap = ptr->left_gap;
164 ctx->queue->copy_from(*ptr->queue);