Refactor render queue management
[lsnes.git] / src / lua / gui-bitmap.cpp
blob402d4c57cb30f3d4b87633312de1e3301efaf506
1 #include "core/lua-int.hpp"
2 #include "core/render.hpp"
3 #include "lua/bitmap.hpp"
4 #include <vector>
6 lua_bitmap::lua_bitmap(uint32_t w, uint32_t h)
8 width = w;
9 height = h;
10 pixels.resize(width * height);
11 memset(&pixels[0], 0, width * height);
14 lua_dbitmap::lua_dbitmap(uint32_t w, uint32_t h)
16 width = w;
17 height = h;
18 pixels.resize(width * height);
21 namespace
23 struct render_object_bitmap : public render_object
25 render_object_bitmap(int32_t _x, int32_t _y, lua_obj_pin<lua_bitmap>* _bitmap,
26 lua_obj_pin<lua_palette>* _palette) throw()
28 x = _x;
29 y = _y;
30 b = _bitmap;
31 b2 = NULL;
32 p = _palette;
35 render_object_bitmap(int32_t _x, int32_t _y, lua_obj_pin<lua_dbitmap>* _bitmap) throw()
37 x = _x;
38 y = _y;
39 b = NULL;
40 b2 = _bitmap;
41 p = NULL;
44 ~render_object_bitmap() throw()
46 delete b;
47 delete b2;
48 delete p;
51 void operator()(struct screen& scr) throw()
53 size_t pallim = 0;
54 size_t w, h;
55 premultiplied_color* palette;
56 if(b) {
57 palette = &p->object()->colors[0];
58 for(auto& c : p->object()->colors)
59 c.set_palette(scr);
60 pallim = p->object()->colors.size();
61 w = b->object()->width;
62 h = b->object()->height;
63 } else {
64 for(auto& c : b2->object()->pixels)
65 c.set_palette(scr);
66 w = b2->object()->width;
67 h = b2->object()->height;
70 int32_t xmin = 0;
71 int32_t xmax = w;
72 int32_t ymin = 0;
73 int32_t ymax = h;
74 clip_range(scr.originx, scr.width, x, xmin, xmax);
75 clip_range(scr.originy, scr.height, y, ymin, ymax);
76 for(int32_t r = ymin; r < ymax; r++) {
77 uint32_t* rptr = scr.rowptr(y + r + scr.originy);
78 size_t eptr = x + xmin + scr.originx;
79 if(b)
80 for(int32_t c = xmin; c < xmax; c++, eptr++) {
81 uint16_t i = b->object()->pixels[r * b->object()->width + c];
82 if(i < pallim)
83 palette[i].apply(rptr[eptr]);
85 else
86 for(int32_t c = xmin; c < xmax; c++, eptr++)
87 b2->object()->pixels[r * b2->object()->width + c].apply(rptr[eptr]);
90 private:
91 int32_t x;
92 int32_t y;
93 lua_obj_pin<lua_bitmap>* b;
94 lua_obj_pin<lua_dbitmap>* b2;
95 lua_obj_pin<lua_palette>* p;
98 function_ptr_luafun gui_bitmap("gui.bitmap_draw", [](lua_State* LS, const std::string& fname) -> int {
99 if(!lua_render_ctx)
100 return 0;
101 int32_t x = get_numeric_argument<int32_t>(LS, 1, fname.c_str());
102 int32_t y = get_numeric_argument<int32_t>(LS, 2, fname.c_str());
103 if(lua_class<lua_bitmap>::is(LS, 3)) {
104 lua_class<lua_bitmap>::get(LS, 3, fname.c_str());
105 lua_class<lua_palette>::get(LS, 4, fname.c_str());
106 auto b = lua_class<lua_bitmap>::pin(LS, 3, fname.c_str());
107 auto p = lua_class<lua_palette>::pin(LS, 4, fname.c_str());
108 lua_render_ctx->queue->create_add<render_object_bitmap>(x, y, b, p);
109 } else if(lua_class<lua_dbitmap>::is(LS, 3)) {
110 lua_class<lua_dbitmap>::get(LS, 3, fname.c_str());
111 auto b = lua_class<lua_dbitmap>::pin(LS, 3, fname.c_str());
112 lua_render_ctx->queue->create_add<render_object_bitmap>(x, y, b);
113 } else {
114 lua_pushstring(LS, "Expected BITMAP or DBITMAP as argument 3 for gui.bitmap_draw.");
115 lua_error(LS);
117 return 0;
120 function_ptr_luafun gui_cpalette("gui.palette_new", [](lua_State* LS, const std::string& fname) -> int {
121 lua_class<lua_palette>::create(LS);
122 return 1;
125 function_ptr_luafun gui_cbitmap("gui.bitmap_new", [](lua_State* LS, const std::string& fname) -> int {
126 uint32_t w = get_numeric_argument<uint32_t>(LS, 1, fname.c_str());
127 uint32_t h = get_numeric_argument<uint32_t>(LS, 2, fname.c_str());
128 bool d = get_boolean_argument(LS, 3, fname.c_str());
129 if(d)
130 lua_class<lua_dbitmap>::create(LS, w, h);
131 else
132 lua_class<lua_bitmap>::create(LS, w, h);
133 return 1;
136 function_ptr_luafun gui_epalette("gui.palette_set", [](lua_State* LS, const std::string& fname) -> int {
137 lua_palette* p = lua_class<lua_palette>::get(LS, 1, fname.c_str());
138 uint16_t c = get_numeric_argument<uint16_t>(LS, 2, fname.c_str());
139 int64_t nval = get_numeric_argument<int64_t>(LS, 3, fname.c_str());
140 premultiplied_color nc(nval);
141 if(p->colors.size() <= c);
142 p->colors.resize(static_cast<uint32_t>(c) + 1);
143 p->colors[c] = nc;
144 return 0;
147 function_ptr_luafun pset_bitmap("gui.bitmap_pset", [](lua_State* LS, const std::string& fname) -> int {
148 uint32_t x = get_numeric_argument<uint32_t>(LS, 2, fname.c_str());
149 uint32_t y = get_numeric_argument<uint32_t>(LS, 3, fname.c_str());
150 if(lua_class<lua_bitmap>::is(LS, 1)) {
151 lua_bitmap* b = lua_class<lua_bitmap>::get(LS, 1, fname.c_str());
152 uint16_t c = get_numeric_argument<uint16_t>(LS, 4, fname.c_str());
153 if(x >= b->width || y >= b->height)
154 return 0;
155 b->pixels[y * b->width + x] = c;
156 } else if(lua_class<lua_dbitmap>::is(LS, 1)) {
157 lua_dbitmap* b = lua_class<lua_dbitmap>::get(LS, 1, fname.c_str());
158 int64_t c = get_numeric_argument<int64_t>(LS, 4, fname.c_str());
159 if(x >= b->width || y >= b->height)
160 return 0;
161 b->pixels[y * b->width + x] = premultiplied_color(c);
162 } else {
163 lua_pushstring(LS, "Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_pset.");
164 lua_error(LS);
166 return 0;
169 function_ptr_luafun size_bitmap("gui.bitmap_size", [](lua_State* LS, const std::string& fname) -> int {
170 if(lua_class<lua_bitmap>::is(LS, 1)) {
171 lua_bitmap* b = lua_class<lua_bitmap>::get(LS, 1, fname.c_str());
172 lua_pushnumber(LS, b->width);
173 lua_pushnumber(LS, b->height);
174 } else if(lua_class<lua_dbitmap>::is(LS, 1)) {
175 lua_dbitmap* b = lua_class<lua_dbitmap>::get(LS, 1, fname.c_str());
176 lua_pushnumber(LS, b->width);
177 lua_pushnumber(LS, b->height);
178 } else {
179 lua_pushstring(LS, "Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_size.");
180 lua_error(LS);
182 return 2;
185 function_ptr_luafun blit_bitmap("gui.bitmap_blit", [](lua_State* LS, const std::string& fname) -> int {
186 uint32_t dx = get_numeric_argument<uint32_t>(LS, 2, fname.c_str());
187 uint32_t dy = get_numeric_argument<uint32_t>(LS, 3, fname.c_str());
188 uint32_t sx = get_numeric_argument<uint32_t>(LS, 5, fname.c_str());
189 uint32_t sy = get_numeric_argument<uint32_t>(LS, 6, fname.c_str());
190 uint32_t w = get_numeric_argument<uint32_t>(LS, 7, fname.c_str());
191 uint32_t h = get_numeric_argument<uint32_t>(LS, 8, fname.c_str());
192 int64_t ck = 0x100000000ULL;
193 get_numeric_argument<int64_t>(LS, 9, ck, fname.c_str());
194 bool nck = false;
195 premultiplied_color pck(ck);
196 uint32_t ckorig = pck.orig;
197 uint16_t ckoriga = pck.origa;
198 if(ck == 0x100000000ULL)
199 nck = true;
200 if(lua_class<lua_bitmap>::is(LS, 1) && lua_class<lua_bitmap>::is(LS, 4)) {
201 lua_bitmap* db = lua_class<lua_bitmap>::get(LS, 1, fname.c_str());
202 lua_bitmap* sb = lua_class<lua_bitmap>::get(LS, 4, fname.c_str());
203 while((dx + w > db->width || sx + w > sb->width) && w > 0)
204 w--;
205 while((dy + h > db->height || sy + h > sb->height) && h > 0)
206 h--;
207 size_t sidx = sy * sb->width + sx;
208 size_t didx = dy * db->width + dx;
209 size_t srskip = sb->width - w;
210 size_t drskip = db->width - w;
211 for(uint32_t j = 0; j < h; j++) {
212 for(uint32_t i = 0; i < w; i++) {
213 uint16_t pix = sb->pixels[sidx];
214 if(pix != ck) //No need to check nck, as that value is out of range.
215 db->pixels[didx] = pix;
216 sidx++;
217 didx++;
219 sidx += srskip;
220 didx += drskip;
222 } else if(lua_class<lua_dbitmap>::is(LS, 1) && lua_class<lua_dbitmap>::is(LS, 1)) {
223 lua_dbitmap* db = lua_class<lua_dbitmap>::get(LS, 1, fname.c_str());
224 lua_dbitmap* sb = lua_class<lua_dbitmap>::get(LS, 4, fname.c_str());
225 while((dx + w > db->width || sx + w > sb->width) && w > 0)
226 w--;
227 while((dy + h > db->height || sy + h > sb->height) && h > 0)
228 h--;
229 size_t sidx = sy * sb->width + sx;
230 size_t didx = dy * db->width + dx;
231 size_t srskip = sb->width - w;
232 size_t drskip = db->width - w;
233 for(uint32_t j = 0; j < h; j++) {
234 for(uint32_t i = 0; i < w; i++) {
235 premultiplied_color pix = sb->pixels[sidx];
236 if(pix.orig != ckorig || pix.origa != ckoriga || nck)
237 db->pixels[didx] = pix;
238 sidx++;
239 didx++;
241 sidx += srskip;
242 didx += drskip;
244 } else {
245 lua_pushstring(LS, "Expected BITMAP or DBITMAP as arguments 1&4 for gui.bitmap_pset.");
246 lua_error(LS);
248 return 0;
251 function_ptr_luafun gui_loadbitmap("gui.bitmap_load", [](lua_State* LS, const std::string& fname) -> int {
252 std::string name = get_string_argument(LS, 1, fname.c_str());
253 uint32_t w, h;
254 auto bitmap = lua_loaded_bitmap::load(name);
255 if(bitmap.d) {
256 lua_dbitmap* b = lua_class<lua_dbitmap>::create(LS, bitmap.w, bitmap.h);
257 for(size_t i = 0; i < bitmap.w * bitmap.h; i++)
258 b->pixels[i] = premultiplied_color(bitmap.bitmap[i]);
259 return 1;
260 } else {
261 lua_bitmap* b = lua_class<lua_bitmap>::create(LS, bitmap.w, bitmap.h);
262 lua_palette* p = lua_class<lua_palette>::create(LS);
263 for(size_t i = 0; i < bitmap.w * bitmap.h; i++)
264 b->pixels[i] = bitmap.bitmap[i];
265 p->colors.resize(bitmap.palette.size());
266 for(size_t i = 0; i < bitmap.palette.size(); i++)
267 p->colors[i] = premultiplied_color(bitmap.palette[i]);
268 return 2;
272 function_ptr_luafun gui_dpalette("gui.palette_debug", [](lua_State* LS, const std::string& fname) -> int {
273 lua_palette* p = lua_class<lua_palette>::get(LS, 1, fname.c_str());
274 size_t i = 0;
275 for(auto c : p->colors)
276 messages << "Color #" << (i++) << ": " << c.orig << ":" << c.origa << std::endl;
277 return 0;
281 DECLARE_LUACLASS(lua_palette, "PALETTE");
282 DECLARE_LUACLASS(lua_bitmap, "BITMAP");
283 DECLARE_LUACLASS(lua_dbitmap, "DBITMAP");