lsnes rr2-β24
[lsnes.git] / src / lua / gui-rqueue.cpp
blob13b63037adb10cc43a01d6e9ea7428d5eecf16c5
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()
110 lctx.left_gap = std::numeric_limits<uint32_t>::max();
111 lctx.right_gap = std::numeric_limits<uint32_t>::max();
112 lctx.bottom_gap = std::numeric_limits<uint32_t>::max();
113 lctx.top_gap = std::numeric_limits<uint32_t>::max();
114 lctx.queue = &rqueue;
115 lctx.width = width;
116 lctx.height = height;
119 int lua_renderqueue::create(lua::state& L, lua::parameters& P)
121 int32_t x, y;
123 P(x, y);
125 lua::_class<lua_renderqueue>::create(L, x, y);
126 return 1;
129 int lua_renderqueue::setnull(lua::state& L, lua::parameters& P)
131 auto& core = CORE();
132 if(core.lua2->renderq_redirect && core.lua2->renderq_last == core.lua2->render_ctx)
133 //If there is valid redirect, undo it.
134 core.lua2->render_ctx = core.lua2->renderq_saved;
135 core.lua2->renderq_redirect = false;
136 core.lua2->renderq_last = NULL;
137 core.lua2->renderq_saved = NULL;
138 return 0;
141 lua::_class<lua_renderqueue> LUA_class_lua_renderqueue(lua_class_gui, "RENDERCTX", {
142 {"new", lua_renderqueue::create},
143 {"setnull", lua_renderqueue::setnull},
144 }, {
145 {"run", &lua_renderqueue::run},
146 {"synchronous_repaint", &lua_renderqueue::synchronous_repaint},
147 {"clear", &lua_renderqueue::clear},
148 {"set", &lua_renderqueue::set},
149 {"render", &lua_renderqueue::render},
150 }, &lua_renderqueue::print);
153 void lua_renderq_run(lua::render_context* ctx, void* _sctx)
155 lua_renderqueue* sctx = (lua_renderqueue*)_sctx;
156 lua::render_context* ptr = sctx->get();
157 if(ptr->top_gap != std::numeric_limits<uint32_t>::max())
158 ctx->top_gap = ptr->top_gap;
159 if(ptr->right_gap != std::numeric_limits<uint32_t>::max())
160 ctx->right_gap = ptr->right_gap;
161 if(ptr->bottom_gap != std::numeric_limits<uint32_t>::max())
162 ctx->bottom_gap = ptr->bottom_gap;
163 if(ptr->left_gap != std::numeric_limits<uint32_t>::max())
164 ctx->left_gap = ptr->left_gap;
165 ctx->queue->copy_from(*ptr->queue);