diff --git a/include/core/advdumper.hpp b/include/core/advdumper.hpp index 00cfa41e..b9888032 100644 --- a/include/core/advdumper.hpp +++ b/include/core/advdumper.hpp @@ -102,7 +102,7 @@ private: * Parameter bgap: Bottom gap. * Parameter fn: Function to call between running lua hooks and actually rendering. */ -void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t hscl, uint32_t vscl, +template void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t hscl, uint32_t vscl, uint32_t roffset, uint32_t goffset, uint32_t boffset, uint32_t lgap, uint32_t tgap, uint32_t rgap, uint32_t bgap, void(*fn)()); diff --git a/include/core/dispatch.hpp b/include/core/dispatch.hpp index ffd6055a..0ad3ac14 100644 --- a/include/core/dispatch.hpp +++ b/include/core/dispatch.hpp @@ -378,11 +378,11 @@ public: * * parameter scr: The render buffer object. */ - virtual void on_set_screen(screen& scr); + virtual void on_set_screen(screen& scr); /** * Call on_set_screen on all objects. */ - static void do_set_screen(screen& scr) throw(); + static void do_set_screen(screen& scr) throw(); /** * Notify that new frame is available. * diff --git a/include/core/framebuffer.hpp b/include/core/framebuffer.hpp index 96ca0c4e..9f47d8b1 100644 --- a/include/core/framebuffer.hpp +++ b/include/core/framebuffer.hpp @@ -18,7 +18,7 @@ extern lcscreen screen_corrupt; /** * The main screen to draw on. */ -extern screen main_screen; +extern screen main_screen; /** * Initialize special screens. * diff --git a/include/core/render.hpp b/include/core/render.hpp index b8c3a797..042dab74 100644 --- a/include/core/render.hpp +++ b/include/core/render.hpp @@ -116,11 +116,17 @@ struct lcscreen size_t allocated; }; +template struct screenelem {}; +template<> struct screenelem { typedef uint32_t t; }; +template<> struct screenelem { typedef uint64_t t; }; + /** * Hicolor modifiable screen. */ +template struct screen { + typedef typename screenelem::t element_t; /** * Creates screen. The screen dimensions are initially 0x0. */ @@ -139,7 +145,7 @@ struct screen * parameter _height: Height of screen. * parameter _pitch: Distance in bytes between successive scanlines. */ - void set(uint32_t* _memory, uint32_t _width, uint32_t _height, uint32_t _pitch) throw(); + void set(element_t* _memory, uint32_t _width, uint32_t _height, uint32_t _pitch) throw(); /** * Sets the size of the screen. The memory is freed if screen is reallocated or destroyed. @@ -174,7 +180,7 @@ struct screen * * parameter row: Number of row (must be less than height). */ - uint32_t* rowptr(uint32_t row) throw(); + element_t* rowptr(uint32_t row) throw(); /** * Set palette. Also converts the image data. @@ -188,7 +194,7 @@ struct screen /** * Active palette */ - uint32_t* palette; + element_t* palette; uint32_t palette_r; uint32_t palette_g; uint32_t palette_b; @@ -196,7 +202,7 @@ struct screen /** * Backing memory for this screen. */ - uint32_t* memory; + element_t* memory; /** * True if memory is given by user and must not be freed. @@ -232,19 +238,9 @@ struct screen * Y-coordinate of origin. */ uint32_t originy; - -/** - * Returns color value with specified (r,g,b) values (scale 0-255). - * - * parameter r: Red component. - * parameter g: Green component. - * parameter b: Blue component. - * returns: color element value. - */ - uint32_t make_color(uint8_t r, uint8_t g, uint8_t b) throw(); private: - screen(const screen&); - screen& operator=(const screen&); + screen(const screen&); + screen& operator=(const screen&); }; /** @@ -262,7 +258,8 @@ struct render_object * * parameter scr: The screen to draw it on. */ - virtual void operator()(struct screen& scr) throw() = 0; + virtual void operator()(struct screen& scr) throw() = 0; + virtual void operator()(struct screen& scr) throw() = 0; }; @@ -274,35 +271,33 @@ struct premultiplied_color { uint32_t hi; uint32_t lo; + uint64_t hiHI; + uint64_t loHI; uint32_t orig; uint16_t origa; uint16_t inv; + uint32_t invHI; premultiplied_color(int64_t color) throw() { if(color < 0) { //Transparent. - hi = 0; - lo = 0; orig = 0; origa = 0; inv = 256; } else { - uint32_t c = (color & 0xFFFFFF); - uint16_t a = 256 - ((color >> 24) & 0xFF); - hi = c & 0xFF00FF; - lo = (c & 0x00FF00) >> 8; - hi *= a; - lo *= a; orig = color & 0xFFFFFF; - origa = a; - inv = 256 - a; + origa = 256 - ((color >> 24) & 0xFF);; + inv = 256 - origa; } + invHI = 256 * static_cast(inv); + set_palette(16, 8, 0, false); + set_palette(32, 16, 0, true); //std::cerr << "Color " << color << " -> hi=" << hi << " lo=" << lo << " inv=" << inv << std::endl; } - void set_palette(unsigned rshift, unsigned gshift, unsigned bshift) throw(); - void set_palette(struct screen& s) throw() + void set_palette(unsigned rshift, unsigned gshift, unsigned bshift, bool X) throw(); + template void set_palette(struct screen& s) throw() { - set_palette(s.palette_r, s.palette_g, s.palette_b); + set_palette(s.palette_r, s.palette_g, s.palette_b, X); } uint32_t blend(uint32_t color) throw() { @@ -315,6 +310,17 @@ struct premultiplied_color { x = blend(x); } + uint64_t blend(uint64_t color) throw() + { + uint64_t a, b; + a = color & 0xFFFF0000FFFFULL; + b = (color & 0xFFFF0000FFFF0000ULL) >> 16; + return (((a * invHI + hiHI) >> 16) & 0xFFFF0000FFFFULL) | ((b * invHI + loHI) & 0xFFFF0000FFFF0000ULL); + } + void apply(uint64_t& x) throw() + { + x = blend(x); + } }; /** @@ -335,7 +341,7 @@ struct render_queue * * parameter scr: The screen to apply queue to. */ - void run(struct screen& scr) throw(); + template void run(struct screen& scr) throw(); /** * Frees all objects in the queue without applying them. @@ -393,7 +399,8 @@ std::pair find_glyph(uint32_t codepoint, int32_t x, i * parameter _vdbl: If true, draw text using double height. * throws std::bad_alloc: Not enough memory. */ -void render_text(struct screen& scr, int32_t _x, int32_t _y, const std::string& _text, premultiplied_color _fg, - premultiplied_color _bg, bool _hdbl = false, bool _vdbl = false) throw(std::bad_alloc); +template void render_text(struct screen& scr, int32_t _x, int32_t _y, const std::string& _text, + premultiplied_color _fg, premultiplied_color _bg, bool _hdbl = false, bool _vdbl = false) + throw(std::bad_alloc); #endif diff --git a/src/core/advdumper.cpp b/src/core/advdumper.cpp index f9f3c605..199051cb 100644 --- a/src/core/advdumper.cpp +++ b/src/core/advdumper.cpp @@ -104,7 +104,7 @@ adv_dumper::adv_dumper(const std::string& id) throw(std::bad_alloc) dumpers()[d_id] = this; } -void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t hscl, uint32_t vscl, +template void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t hscl, uint32_t vscl, uint32_t roffset, uint32_t goffset, uint32_t boffset, uint32_t lgap, uint32_t tgap, uint32_t rgap, uint32_t bgap, void(*fn)()) { @@ -127,3 +127,10 @@ void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t h target.copy_from(source, hscl, vscl); rq.run(target); } + +template void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t hscl, uint32_t vscl, + uint32_t roffset, uint32_t goffset, uint32_t boffset, uint32_t lgap, uint32_t tgap, uint32_t rgap, + uint32_t bgap, void(*fn)()); +template void render_video_hud(struct screen& target, struct lcscreen& source, uint32_t hscl, uint32_t vscl, + uint32_t roffset, uint32_t goffset, uint32_t boffset, uint32_t lgap, uint32_t tgap, uint32_t rgap, + uint32_t bgap, void(*fn)()); diff --git a/src/core/dispatch.cpp b/src/core/dispatch.cpp index 3513fcab..89657801 100644 --- a/src/core/dispatch.cpp +++ b/src/core/dispatch.cpp @@ -476,12 +476,12 @@ void information_dispatch::update_dumpers(bool nocalls) throw() } } -void information_dispatch::on_set_screen(screen& scr) +void information_dispatch::on_set_screen(screen& scr) { //Do nothing. } -void information_dispatch::do_set_screen(screen& scr) throw() +void information_dispatch::do_set_screen(screen& scr) throw() { for(auto& i : dispatch()) { START_EH_BLOCK diff --git a/src/core/framebuffer.cpp b/src/core/framebuffer.cpp index 39ed56d6..dff50c25 100644 --- a/src/core/framebuffer.cpp +++ b/src/core/framebuffer.cpp @@ -149,7 +149,7 @@ namespace bool last_redraw_no_lua = true; } -screen main_screen; +screen main_screen; void take_screenshot(const std::string& file) throw(std::bad_alloc, std::runtime_error) { diff --git a/src/core/render.cpp b/src/core/render.cpp index 76ce2883..a5e9e79c 100644 --- a/src/core/render.cpp +++ b/src/core/render.cpp @@ -167,6 +167,28 @@ skip_line: } } +void premultiplied_color::set_palette(unsigned rshift, unsigned gshift, unsigned bshift, bool X) throw() +{ + if(X) { + uint64_t r = ((orig >> 16) & 0xFF) * 257; + uint64_t g = ((orig >> 8) & 0xFF) * 257; + uint64_t b = (orig & 0xFF) * 257; + uint64_t color = (r << rshift) | (g << gshift) | (b << bshift); + hiHI = color & 0xFFFF0000FFFFULL; + loHI = (color & 0xFFFF0000FFFF0000ULL) >> 16; + hiHI *= (static_cast(origa) * 256); + loHI *= (static_cast(origa) * 256); + } else { + uint32_t r = (orig >> 16) & 0xFF; + uint32_t g = (orig >> 8) & 0xFF; + uint32_t b = orig & 0xFF; + uint32_t color = (r << rshift) | (g << gshift) | (b << bshift); + hi = color & 0xFF00FF; + lo = (color & 0xFF00FF00) >> 8; + hi *= origa; + lo *= origa; + } +} void do_init_font() { @@ -190,8 +212,8 @@ render_object::~render_object() throw() { } -void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& text, premultiplied_color fg, - premultiplied_color bg, bool hdbl, bool vdbl) throw(std::bad_alloc) +template void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& text, + premultiplied_color fg, premultiplied_color bg, bool hdbl, bool vdbl) throw(std::bad_alloc) { int32_t orig_x = x; uint32_t unicode_code = 0; @@ -254,14 +276,14 @@ void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& te if(p.second == NULL) { //Blank glyph. for(uint32_t j = 0; j < dh; j++) { - uint32_t* base = scr.rowptr(cy + j) + cx; + typename screen::element_t* base = scr.rowptr(cy + j) + cx; for(uint32_t i = 0; i < dw; i++) bg.apply(base[i]); } } else { for(uint32_t j = 0; j < dh; j++) { uint32_t dataword = p.second[(dy + j) >> rshift]; - uint32_t* base = scr.rowptr(cy + j) + cx; + typename screen::element_t* base = scr.rowptr(cy + j) + cx; uint32_t rbit = (~((dy + j) >> yshift << rishift) & 31) - (dx >> xshift); if(hdbl) { for(uint32_t i = 0; i < dw; i++) @@ -288,7 +310,7 @@ void render_queue::add(struct render_object& obj) throw(std::bad_alloc) q.push_back(&obj); } -void render_queue::run(struct screen& scr) throw() +template void render_queue::run(struct screen& scr) throw() { for(auto i : q) { try { @@ -310,14 +332,6 @@ render_queue::~render_queue() throw() clear(); } -uint32_t screen::make_color(uint8_t r, uint8_t g, uint8_t b) throw() -{ - uint32_t _r = r; - uint32_t _g = g; - uint32_t _b = b; - return (_r << 16) + (_g << 8) + _b; -} - lcscreen::lcscreen(const uint32_t* mem, bool hires, bool interlace, bool overscan, bool region) throw() { uint32_t dataoffset = 0; @@ -457,12 +471,12 @@ void lcscreen::save_png(const std::string& file) throw(std::bad_alloc, std::runt } } -void screen::copy_from(lcscreen& scr, uint32_t hscale, uint32_t vscale) throw() +template void screen::copy_from(lcscreen& scr, uint32_t hscale, uint32_t vscale) throw() { if(width < originx || height < originy) { //Just clear the screen. for(uint32_t y = 0; y < height; y++) - memset(rowptr(y), 0, 4 * width); + memset(rowptr(y), 0, sizeof(typename screen::element_t) * width); return; } uint32_t copyable_width = 0, copyable_height = 0; @@ -473,22 +487,23 @@ void screen::copy_from(lcscreen& scr, uint32_t hscale, uint32_t vscale) throw() copyable_width = (copyable_width > scr.width) ? scr.width : copyable_width; copyable_height = (copyable_height > scr.height) ? scr.height : copyable_height; for(uint32_t y = 0; y < height; y++) - memset(rowptr(y), 0, 4 * width); + memset(rowptr(y), 0, sizeof(typename screen::element_t) * width); for(uint32_t y = 0; y < copyable_height; y++) { uint32_t line = y * vscale + originy; - uint32_t* ptr = rowptr(line) + originx; + typename screen::element_t* ptr = rowptr(line) + originx; const uint32_t* sbase = scr.memory + y * scr.pitch; for(uint32_t x = 0; x < copyable_width; x++) { - uint32_t c = palette[sbase[x] & 0x7FFFF]; + typename screen::element_t c = palette[sbase[x] & 0x7FFFF]; for(uint32_t i = 0; i < hscale; i++) *(ptr++) = c; } for(uint32_t j = 1; j < vscale; j++) - memcpy(rowptr(line + j) + originx, rowptr(line) + originx, 4 * hscale * copyable_width); + memcpy(rowptr(line + j) + originx, rowptr(line) + originx, + sizeof(typename screen::element_t) * hscale * copyable_width); } } -void screen::reallocate(uint32_t _width, uint32_t _height, bool upside_down) throw(std::bad_alloc) +template void screen::reallocate(uint32_t _width, uint32_t _height, bool upside_down) throw(std::bad_alloc) { if(_width == width && _height == height) return; @@ -501,10 +516,10 @@ void screen::reallocate(uint32_t _width, uint32_t _height, bool upside_down) thr flipped = upside_down; return; } - uint32_t* newmem = new uint32_t[_width * _height]; + typename screen::element_t* newmem = new typename screen::element_t[_width * _height]; width = _width; height = _height; - pitch = 4 * _width; + pitch = sizeof(typename screen::element_t) * _width; if(memory && !user_memory) delete[] memory; memory = newmem; @@ -512,7 +527,8 @@ void screen::reallocate(uint32_t _width, uint32_t _height, bool upside_down) thr flipped = upside_down; } -void screen::set(uint32_t* _memory, uint32_t _width, uint32_t _height, uint32_t _pitch) throw() +template void screen::set(typename screen::element_t* _memory, uint32_t _width, uint32_t _height, + uint32_t _pitch) throw() { if(memory && !user_memory) delete[] memory; @@ -524,21 +540,20 @@ void screen::set(uint32_t* _memory, uint32_t _width, uint32_t _height, uint32_t flipped = false; } -void screen::set_origin(uint32_t _originx, uint32_t _originy) throw() +template void screen::set_origin(uint32_t _originx, uint32_t _originy) throw() { originx = _originx; originy = _originy; } - -uint32_t* screen::rowptr(uint32_t row) throw() +template typename screen::element_t* screen::rowptr(uint32_t row) throw() { if(flipped) row = height - row - 1; - return reinterpret_cast(reinterpret_cast(memory) + row * pitch); + return reinterpret_cast::element_t*>(reinterpret_cast(memory) + row * pitch); } -screen::screen() throw() +template screen::screen() throw() { memory = NULL; width = height = originx = originy = pitch = 0; @@ -548,7 +563,7 @@ screen::screen() throw() set_palette(16, 8, 0); } -screen::~screen() throw() +template screen::~screen() throw() { if(memory && !user_memory) delete[] memory; @@ -577,26 +592,26 @@ void clip_range(uint32_t origin, uint32_t size, int32_t base, int32_t& minc, int } } -void screen::set_palette(uint32_t r, uint32_t g, uint32_t b) +template void screen::set_palette(uint32_t r, uint32_t g, uint32_t b) { if(!palette) - palette = new uint32_t[0x80000]; + palette = new element_t[0x80000]; else if(r == palette_r && g == palette_g && b == palette_b) return; for(size_t i = 0; i < static_cast(width) * height; i++) { uint32_t word = memory[i]; - uint32_t R = (word >> palette_r) & 0xFF; - uint32_t G = (word >> palette_g) & 0xFF; - uint32_t B = (word >> palette_b) & 0xFF; + uint32_t R = (word >> palette_r) & (X ? 0xFFFF : 0xFF); + uint32_t G = (word >> palette_g) & (X ? 0xFFFF : 0xFF); + uint32_t B = (word >> palette_b) & (X ? 0xFFFF : 0xFF); memory[i] = (R << r) | (G << g) | (B << b); } for(unsigned i = 0; i < 0x80000; i++) { unsigned l = 1 + ((i >> 15) & 0xF); - unsigned R = (i >> 0) & 0x1F; - unsigned G = (i >> 5) & 0x1F; - unsigned B = (i >> 10) & 0x1F; + element_t R = (i >> 0) & 0x1F; + element_t G = (i >> 5) & 0x1F; + element_t B = (i >> 10) & 0x1F; double _l = static_cast(l); - double m = 255.0 / 496.0; + double m = (X ? 65535.0 : 255.0) / 496.0; R = floor(m * R * _l + 0.5); G = floor(m * G * _l + 0.5); B = floor(m * B * _l + 0.5); @@ -607,14 +622,12 @@ void screen::set_palette(uint32_t r, uint32_t g, uint32_t b) palette_b = b; } -void premultiplied_color::set_palette(unsigned rshift, unsigned gshift, unsigned bshift) throw() -{ - uint32_t r = (orig >> 16) & 0xFF; - uint32_t g = (orig >> 8) & 0xFF; - uint32_t b = orig & 0xFF; - uint32_t color = (r << rshift) | (g << gshift) | (b << bshift); - hi = color & 0xFF00FF; - lo = (color & 0xFF00FF00) >> 8; - hi *= origa; - lo *= origa; -} + +template struct screen; +template struct screen; +template void render_queue::run(screen&); +template void render_queue::run(screen&); +template void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& text, + premultiplied_color fg, premultiplied_color bg, bool hdbl, bool vdbl) throw(std::bad_alloc); +template void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& text, + premultiplied_color fg, premultiplied_color bg, bool hdbl, bool vdbl) throw(std::bad_alloc); diff --git a/src/core/window.cpp b/src/core/window.cpp index 7aea724d..d5418f20 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -509,7 +509,7 @@ void platform::run_queues() throw() namespace { mutex* _msgbuf_lock; - screen* our_screen; + screen* our_screen; void trigger_repaint() { @@ -519,14 +519,14 @@ namespace struct painter_listener : public information_dispatch { painter_listener(); - void on_set_screen(screen& scr); + void on_set_screen(screen& scr); void on_screen_update(); void on_status_update(); } x; painter_listener::painter_listener() : information_dispatch("painter-listener") {} - void painter_listener::on_set_screen(screen& scr) + void painter_listener::on_set_screen(screen& scr) { our_screen = &scr; } diff --git a/src/lua/gui-circle.cpp b/src/lua/gui-circle.cpp index a489122c..12d2ac3a 100644 --- a/src/lua/gui-circle.cpp +++ b/src/lua/gui-circle.cpp @@ -18,7 +18,7 @@ namespace (_radius - _thickness); } ~render_object_circle() throw() {} - void operator()(struct screen& scr) throw() + template void op(struct screen& scr) throw() { outline.set_palette(scr); fill.set_palette(scr); @@ -30,7 +30,7 @@ namespace clip_range(scr.originy, scr.height, y, ymin, ymax); for(int32_t r = ymin; r < ymax; r++) { uint64_t pd2 = static_cast(r) * r; - uint32_t* rptr = scr.rowptr(y + r + scr.originy); + typename screen::element_t* rptr = scr.rowptr(y + r + scr.originy); size_t eptr = x + xmin + scr.originx; for(int32_t c = xmin; c < xmax; c++, eptr++) { uint64_t fd2 = pd2 + static_cast(c) * c; @@ -43,6 +43,8 @@ namespace } } } + void operator()(struct screen& scr) throw() { op(scr); } + void operator()(struct screen& scr) throw() { op(scr); } private: int32_t x; int32_t y; diff --git a/src/lua/gui-crosshair.cpp b/src/lua/gui-crosshair.cpp index 32d18b29..3b5c7274 100644 --- a/src/lua/gui-crosshair.cpp +++ b/src/lua/gui-crosshair.cpp @@ -8,7 +8,7 @@ namespace render_object_crosshair(int32_t _x, int32_t _y, premultiplied_color _color, uint32_t _length) throw() : x(_x), y(_y), color(_color), length(_length) {} ~render_object_crosshair() throw() {} - void operator()(struct screen& scr) throw() + template void op(struct screen& scr) throw() { color.set_palette(scr); int32_t xmin = -static_cast(length); @@ -24,6 +24,8 @@ namespace for(int32_t r = xmin; r < xmax; r++) color.apply(scr.rowptr(y + scr.originy)[x + r + scr.originx]); } + void operator()(struct screen& scr) throw() { op(scr); } + void operator()(struct screen& scr) throw() { op(scr); } private: int32_t x; int32_t y; diff --git a/src/lua/gui-line.cpp b/src/lua/gui-line.cpp index 2d903ba8..5a5d9d0d 100644 --- a/src/lua/gui-line.cpp +++ b/src/lua/gui-line.cpp @@ -9,7 +9,7 @@ namespace throw() : x1(_x1), y1(_y1), x2(_x2), y2(_y2), color(_color) {} ~render_object_line() throw() {} - void operator()(struct screen& scr) throw() + template void op(struct screen& scr) throw() { color.set_palette(scr); int32_t xdiff = x2 - x1; @@ -72,6 +72,8 @@ nodraw2: } } } + void operator()(struct screen& scr) throw() { op(scr); } + void operator()(struct screen& scr) throw() { op(scr); } private: int32_t x1; int32_t y1; diff --git a/src/lua/gui-pixel.cpp b/src/lua/gui-pixel.cpp index c2fee788..94ea1956 100644 --- a/src/lua/gui-pixel.cpp +++ b/src/lua/gui-pixel.cpp @@ -8,7 +8,7 @@ namespace render_object_pixel(int32_t _x, int32_t _y, premultiplied_color _color) throw() : x(_x), y(_y), color(_color) {} ~render_object_pixel() throw() {} - void operator()(struct screen& scr) throw() + template void op(struct screen& scr) throw() { color.set_palette(scr); int32_t _x = x + scr.originx; @@ -19,6 +19,8 @@ namespace return; color.apply(scr.rowptr(_y)[_x]); } + void operator()(struct screen& scr) throw() { op(scr); } + void operator()(struct screen& scr) throw() { op(scr); } private: int32_t x; int32_t y; diff --git a/src/lua/gui-rectangle.cpp b/src/lua/gui-rectangle.cpp index b0d3dc82..24e58910 100644 --- a/src/lua/gui-rectangle.cpp +++ b/src/lua/gui-rectangle.cpp @@ -10,7 +10,7 @@ namespace : x(_x), y(_y), width(_width), height(_height), outline(_outline), fill(_fill), thickness(_thickness) {} ~render_object_rectangle() throw() {} - void operator()(struct screen& scr) throw() + template void op(struct screen& scr) throw() { outline.set_palette(scr); fill.set_palette(scr); @@ -21,7 +21,7 @@ namespace clip_range(scr.originx, scr.width, x, xmin, xmax); clip_range(scr.originy, scr.height, y, ymin, ymax); for(int32_t r = ymin; r < ymax; r++) { - uint32_t* rptr = scr.rowptr(y + r + scr.originy); + typename screen::element_t* rptr = scr.rowptr(y + r + scr.originy); size_t eptr = x + xmin + scr.originx; for(int32_t c = xmin; c < xmax; c++, eptr++) if(r < thickness || c < thickness || r >= height - thickness || @@ -31,6 +31,8 @@ namespace fill.apply(rptr[eptr]); } } + void operator()(struct screen& scr) throw() { op(scr); } + void operator()(struct screen& scr) throw() { op(scr); } private: int32_t x; int32_t y; diff --git a/src/lua/gui-text.cpp b/src/lua/gui-text.cpp index c4afdd73..d470a62b 100644 --- a/src/lua/gui-text.cpp +++ b/src/lua/gui-text.cpp @@ -9,12 +9,14 @@ namespace premultiplied_color _bg, bool _hdbl = false, bool _vdbl = false) throw() : x(_x), y(_y), text(_text), fg(_fg), bg(_bg), hdbl(_hdbl), vdbl(_vdbl) {} ~render_object_text() throw() {} - void operator()(struct screen& scr) throw() + template void op(struct screen& scr) throw() { fg.set_palette(scr); bg.set_palette(scr); render_text(scr, x, y, text, fg, bg, hdbl, vdbl); } + void operator()(struct screen& scr) throw() { op(scr); } + void operator()(struct screen& scr) throw() { op(scr); } private: int32_t x; int32_t y; diff --git a/src/video/avi.cpp b/src/video/avi.cpp index bdb111a6..4cdb78b0 100644 --- a/src/video/avi.cpp +++ b/src/video/avi.cpp @@ -257,7 +257,7 @@ namespace avi_worker* worker; private: sox_dumper* soxdumper; - screen dscr; + screen dscr; unsigned dcounter; bool have_dumped_frame; std::pair soundrate; diff --git a/src/video/jmd.cpp b/src/video/jmd.cpp index de80527b..8b945f3d 100644 --- a/src/video/jmd.cpp +++ b/src/video/jmd.cpp @@ -159,7 +159,7 @@ namespace return ret; } - screen dscr; + screen dscr; unsigned dcounter; bool have_dumped_frame; uint64_t audio_w; diff --git a/src/video/raw.cpp b/src/video/raw.cpp index 1310ea02..355079fb 100644 --- a/src/video/raw.cpp +++ b/src/video/raw.cpp @@ -14,7 +14,7 @@ namespace class raw_avsnoop : public information_dispatch { public: - raw_avsnoop(const std::string& prefix) throw(std::bad_alloc) + raw_avsnoop(const std::string& prefix, bool _swap, bool _bits64) throw(std::bad_alloc) : information_dispatch("dump-raw") { enable_send_sound(); @@ -23,6 +23,8 @@ namespace if(!*video || !*audio) throw std::runtime_error("Can't open output files"); have_dumped_frame = false; + swap = _swap; + bits64 = _bits64; } ~raw_avsnoop() throw() @@ -35,15 +37,27 @@ namespace { if(!video) return; - unsigned magic = 0x18100800U; - unsigned r = (reinterpret_cast(&magic))[2]; + unsigned magic; + if(bits64) + magic = 0x30201000U; + else + magic = 0x18100800U; + unsigned r = (reinterpret_cast(&magic))[swap ? 2 : 0]; unsigned g = (reinterpret_cast(&magic))[1]; - unsigned b = (reinterpret_cast(&magic))[0]; + unsigned b = (reinterpret_cast(&magic))[swap ? 0 : 2]; uint32_t hscl = (_frame.width < 400) ? 2 : 1; uint32_t vscl = (_frame.height < 400) ? 2 : 1; - render_video_hud(dscr, _frame, hscl, vscl, r, g, b, 0, 0, 0, 0, NULL); - for(size_t i = 0; i < dscr.height; i++) - video->write(reinterpret_cast(dscr.rowptr(i)), 4 * dscr.width); + if(bits64) { + render_video_hud(dscr2, _frame, hscl, vscl, r, g, b, 0, 0, 0, 0, NULL); + for(size_t i = 0; i < dscr2.height; i++) + video->write(reinterpret_cast(dscr2.rowptr(i)), 8 * dscr2.width); + } else { + render_video_hud(dscr, _frame, hscl, vscl, r, g, b, 0, 0, 0, 0, NULL); + for(size_t i = 0; i < dscr.height; i++) + video->write(reinterpret_cast(dscr.rowptr(i)), 4 * dscr.width); + } + if(!*video) + messages << "Video write error" << std::endl; have_dumped_frame = true; } @@ -73,7 +87,10 @@ namespace std::ofstream* audio; std::ofstream* video; bool have_dumped_frame; - struct screen dscr; + struct screen dscr; + struct screen dscr2; + bool swap; + bool bits64; }; raw_avsnoop* vid_dumper; @@ -86,6 +103,10 @@ namespace std::set list_submodes() throw(std::bad_alloc) { std::set x; + x.insert("rgb32"); + x.insert("rgb64"); + x.insert("bgr32"); + x.insert("bgr64"); return x; } @@ -101,7 +122,14 @@ namespace std::string modename(const std::string& mode) throw(std::bad_alloc) { - return ""; + if(mode == "rgb32") + return "RGB 32-bit"; + if(mode == "bgr32") + return "BGR 32-bit"; + if(mode == "rgb64") + return "RGB 64-bit"; + if(mode == "bgr64") + return "BGR 64-bit"; } bool busy() @@ -112,12 +140,18 @@ namespace void start(const std::string& mode, const std::string& prefix) throw(std::bad_alloc, std::runtime_error) { + bool bits64 = false; + bool swap = false; + if(mode == "bgr32" || mode == "bgr64") + swap = true; + if(mode == "rgb64" || mode == "bgr64") + bits64 = true; if(prefix == "") throw std::runtime_error("Expected prefix"); if(vid_dumper) throw std::runtime_error("RAW dumping already in progress"); try { - vid_dumper = new raw_avsnoop(prefix); + vid_dumper = new raw_avsnoop(prefix, swap, bits64); } catch(std::bad_alloc& e) { throw; } catch(std::exception& e) {