Hicolor raw dumping

Support hi-color (16bits/channel RGB) raw dumping, since 8 bits
per channel are not enough to resolve all the colors.
This commit is contained in:
Ilari Liusvaara 2012-02-16 22:58:06 +02:00
parent 61f86a8796
commit 228d6a7851
18 changed files with 186 additions and 113 deletions

View file

@ -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<bool X> void render_video_hud(struct screen<X>& 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)());

View file

@ -378,11 +378,11 @@ public:
*
* parameter scr: The render buffer object.
*/
virtual void on_set_screen(screen& scr);
virtual void on_set_screen(screen<false>& scr);
/**
* Call on_set_screen on all objects.
*/
static void do_set_screen(screen& scr) throw();
static void do_set_screen(screen<false>& scr) throw();
/**
* Notify that new frame is available.
*

View file

@ -18,7 +18,7 @@ extern lcscreen screen_corrupt;
/**
* The main screen to draw on.
*/
extern screen main_screen;
extern screen<false> main_screen;
/**
* Initialize special screens.
*

View file

@ -116,11 +116,17 @@ struct lcscreen
size_t allocated;
};
template<bool X> struct screenelem {};
template<> struct screenelem<false> { typedef uint32_t t; };
template<> struct screenelem<true> { typedef uint64_t t; };
/**
* Hicolor modifiable screen.
*/
template<bool X>
struct screen
{
typedef typename screenelem<X>::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<X>&);
screen& operator=(const screen<X>&);
};
/**
@ -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<false>& scr) throw() = 0;
virtual void operator()(struct screen<true>& 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<uint32_t>(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<bool X> void set_palette(struct screen<X>& 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<bool X> void run(struct screen<X>& scr) throw();
/**
* Frees all objects in the queue without applying them.
@ -393,7 +399,8 @@ std::pair<uint32_t, const uint32_t*> 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<bool X> void render_text(struct screen<X>& 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

View file

@ -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<bool X> void render_video_hud(struct screen<X>& 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<false>& 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<true>& 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)());

View file

@ -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<false>& scr)
{
//Do nothing.
}
void information_dispatch::do_set_screen(screen& scr) throw()
void information_dispatch::do_set_screen(screen<false>& scr) throw()
{
for(auto& i : dispatch()) {
START_EH_BLOCK

View file

@ -149,7 +149,7 @@ namespace
bool last_redraw_no_lua = true;
}
screen main_screen;
screen<false> main_screen;
void take_screenshot(const std::string& file) throw(std::bad_alloc, std::runtime_error)
{

View file

@ -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<uint32_t>(origa) * 256);
loHI *= (static_cast<uint32_t>(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<bool X> void render_text(struct screen<X>& 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<X>::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<X>::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<bool X> void render_queue::run(struct screen<X>& 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<bool X> void screen<X>::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<X>::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<X>::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<X>::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<X>::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<X>::element_t) * hscale * copyable_width);
}
}
void screen::reallocate(uint32_t _width, uint32_t _height, bool upside_down) throw(std::bad_alloc)
template<bool X> void screen<X>::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<X>::element_t* newmem = new typename screen<X>::element_t[_width * _height];
width = _width;
height = _height;
pitch = 4 * _width;
pitch = sizeof(typename screen<X>::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<bool X> void screen<X>::set(typename screen<X>::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<bool X> void screen<X>::set_origin(uint32_t _originx, uint32_t _originy) throw()
{
originx = _originx;
originy = _originy;
}
uint32_t* screen::rowptr(uint32_t row) throw()
template<bool X> typename screen<X>::element_t* screen<X>::rowptr(uint32_t row) throw()
{
if(flipped)
row = height - row - 1;
return reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(memory) + row * pitch);
return reinterpret_cast<typename screen<X>::element_t*>(reinterpret_cast<uint8_t*>(memory) + row * pitch);
}
screen::screen() throw()
template<bool X> screen<X>::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<bool X> screen<X>::~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<bool X> void screen<X>::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<size_t>(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<double>(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<false>;
template struct screen<true>;
template void render_queue::run(screen<false>&);
template void render_queue::run(screen<true>&);
template void render_text(struct screen<false>& 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<true>& 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);

View file

@ -509,7 +509,7 @@ void platform::run_queues() throw()
namespace
{
mutex* _msgbuf_lock;
screen* our_screen;
screen<false>* 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<false>& 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<false>& scr)
{
our_screen = &scr;
}

View file

@ -18,7 +18,7 @@ namespace
(_radius - _thickness);
}
~render_object_circle() throw() {}
void operator()(struct screen& scr) throw()
template<bool X> void op(struct screen<X>& 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<int64_t>(r) * r;
uint32_t* rptr = scr.rowptr(y + r + scr.originy);
typename screen<X>::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<int64_t>(c) * c;
@ -43,6 +43,8 @@ namespace
}
}
}
void operator()(struct screen<true>& scr) throw() { op(scr); }
void operator()(struct screen<false>& scr) throw() { op(scr); }
private:
int32_t x;
int32_t y;

View file

@ -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<bool X> void op(struct screen<X>& scr) throw()
{
color.set_palette(scr);
int32_t xmin = -static_cast<int32_t>(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<true>& scr) throw() { op(scr); }
void operator()(struct screen<false>& scr) throw() { op(scr); }
private:
int32_t x;
int32_t y;

View file

@ -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<bool X> void op(struct screen<X>& scr) throw()
{
color.set_palette(scr);
int32_t xdiff = x2 - x1;
@ -72,6 +72,8 @@ nodraw2:
}
}
}
void operator()(struct screen<true>& scr) throw() { op(scr); }
void operator()(struct screen<false>& scr) throw() { op(scr); }
private:
int32_t x1;
int32_t y1;

View file

@ -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<bool X> void op(struct screen<X>& 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<true>& scr) throw() { op(scr); }
void operator()(struct screen<false>& scr) throw() { op(scr); }
private:
int32_t x;
int32_t y;

View file

@ -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<bool X> void op(struct screen<X>& 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<X>::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<true>& scr) throw() { op(scr); }
void operator()(struct screen<false>& scr) throw() { op(scr); }
private:
int32_t x;
int32_t y;

View file

@ -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<bool X> void op(struct screen<X>& scr) throw()
{
fg.set_palette(scr);
bg.set_palette(scr);
render_text(scr, x, y, text, fg, bg, hdbl, vdbl);
}
void operator()(struct screen<true>& scr) throw() { op(scr); }
void operator()(struct screen<false>& scr) throw() { op(scr); }
private:
int32_t x;
int32_t y;

View file

@ -257,7 +257,7 @@ namespace
avi_worker* worker;
private:
sox_dumper* soxdumper;
screen dscr;
screen<false> dscr;
unsigned dcounter;
bool have_dumped_frame;
std::pair<uint32_t, uint32_t> soundrate;

View file

@ -159,7 +159,7 @@ namespace
return ret;
}
screen dscr;
screen<false> dscr;
unsigned dcounter;
bool have_dumped_frame;
uint64_t audio_w;

View file

@ -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<unsigned char*>(&magic))[2];
unsigned magic;
if(bits64)
magic = 0x30201000U;
else
magic = 0x18100800U;
unsigned r = (reinterpret_cast<unsigned char*>(&magic))[swap ? 2 : 0];
unsigned g = (reinterpret_cast<unsigned char*>(&magic))[1];
unsigned b = (reinterpret_cast<unsigned char*>(&magic))[0];
unsigned b = (reinterpret_cast<unsigned char*>(&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<char*>(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<char*>(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<char*>(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<false> dscr;
struct screen<true> dscr2;
bool swap;
bool bits64;
};
raw_avsnoop* vid_dumper;
@ -86,6 +103,10 @@ namespace
std::set<std::string> list_submodes() throw(std::bad_alloc)
{
std::set<std::string> 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) {