Lua: CUSTOMFONT: Allow painting with halo
[lsnes.git] / include / library / framebuffer.hpp
blobcf0d9b1f3ec2bf9d8a5bfe14857d15890a965d91
1 #ifndef _library__framebuffer__hpp__included__
2 #define _library__framebuffer__hpp__included__
4 #include <stdexcept>
5 #include <cstdlib>
6 #include <vector>
7 #include <map>
9 template<bool X> struct framebufferelem {};
10 template<> struct framebufferelem<false> { typedef uint32_t t; };
11 template<> struct framebufferelem<true> { typedef uint64_t t; };
13 /**
14 * Pixel format auxillary palette.
16 template<bool X>
17 struct pixel_format_aux_palette
19 typedef typename framebufferelem<X>::t element_t;
20 uint8_t rshift; //Red shift.
21 uint8_t gshift; //Green shift.
22 uint8_t bshift; //Blue shift.
23 std::vector<element_t> pcache; //Palette cache.
26 /**
27 * Pixel format.
29 class pixel_format
31 public:
32 virtual ~pixel_format() throw();
33 /**
34 * Register the pixel format.
36 pixel_format() throw(std::bad_alloc);
37 /**
38 * Decode pixel format data into RGB24 data (R, G, B).
40 virtual void decode(uint8_t* target, const uint8_t* src, size_t width)
41 throw() = 0;
42 /**
43 * Decode pixel format data into RGB (with specified byte order).
45 virtual void decode(uint32_t* target, const uint8_t* src, size_t width,
46 const pixel_format_aux_palette<false>& auxp) throw() = 0;
47 /**
48 * Decode pixel format data into RGB (with specified byte order).
50 virtual void decode(uint64_t* target, const uint8_t* src, size_t width,
51 const pixel_format_aux_palette<true>& auxp) throw() = 0;
52 /**
53 * Create aux palette.
55 virtual void set_palette(pixel_format_aux_palette<false>& auxp, uint8_t rshift, uint8_t gshift,
56 uint8_t bshift) throw(std::bad_alloc) = 0;
57 /**
58 * Create aux palette.
60 virtual void set_palette(pixel_format_aux_palette<true>& auxp, uint8_t rshift, uint8_t gshift,
61 uint8_t bshift) throw(std::bad_alloc) = 0;
62 /**
63 * Bytes per pixel in data.
65 virtual uint8_t get_bpp() throw() = 0;
66 /**
67 * Bytes per pixel in ss data.
69 virtual uint8_t get_ss_bpp() throw() = 0;
70 /**
71 * Screenshot magic (0 for the old format).
73 virtual uint32_t get_magic() throw() = 0;
76 /**
77 * Game framebuffer information.
79 struct framebuffer_info
81 /**
82 * Pixel format of framebuffer.
84 pixel_format* type;
85 /**
86 * The physical memory backing the framebuffer.
88 char* mem;
89 /**
90 * Physical width of framebuffer.
92 size_t physwidth;
93 /**
94 * Physical height of framebuffer.
96 size_t physheight;
97 /**
98 * Physical stride of framebuffer (in bytes).
100 size_t physstride;
102 * Visible width of framebuffer.
104 size_t width;
106 * Visible height of framebuffer.
108 size_t height;
110 * Visible stride of framebuffer (in bytes).
112 size_t stride;
114 * Visible X offset of framebuffer.
116 size_t offset_x;
118 * Visible Y offset of framebuffer.
120 size_t offset_y;
123 template<bool X> struct framebuffer;
126 * Raw framebuffer.
128 * This framebuffer is in system format, and can either be backed either by temporary buffer or memory buffer.
130 * Any copying only preserves the visible part.
132 struct framebuffer_raw
135 * Create a new framebuffer backed by temporary buffer.
137 * The resulting framebuffer is read-only.
139 * Parameter info: The framebuffer info.
141 framebuffer_raw(const framebuffer_info& info) throw(std::bad_alloc);
143 * Create a new framebuffer backed by memory buffer.
145 * The resulting framebuffer can be written to.
147 framebuffer_raw() throw(std::bad_alloc);
149 * Copy a framebuffer.
151 * The resulting copy is writable.
153 * Parameter f: The framebuffer.
155 framebuffer_raw(const framebuffer_raw& f) throw(std::bad_alloc);
157 * Assign a framebuffer.
159 * Parameter f: The framebuffer.
160 * Throws std::runtime_error: The target framebuffer is not writable.
162 framebuffer_raw& operator=(const framebuffer_raw& f) throw(std::bad_alloc, std::runtime_error);
164 * Load contents of framebuffer.
166 * parameter data: The data to load.
167 * throws std::runtime_error: The target framebuffer is not writable.
169 void load(const std::vector<char>& data) throw(std::bad_alloc, std::runtime_error);
171 * Save contents of framebuffer.
173 * parameter data: The vector to write the data to (in format compatible with load()).
175 void save(std::vector<char>& data) throw(std::bad_alloc);
177 * Save contents of framebuffer as a PNG.
179 * parameter file: The filename to save to.
180 * throws std::runtime_error: Can't save the PNG.
182 void save_png(const std::string& file) throw(std::bad_alloc, std::runtime_error);
184 * Get width.
186 * Returns: The width.
188 size_t get_width() const throw();
190 * Get height.
192 * Returns: The height.
194 size_t get_height() const throw();
196 * Destructor.
198 ~framebuffer_raw();
199 private:
200 bool user_memory; //True if allocated in user memory, false if aliases framebuffer.
201 char* addr; //Address of framebuffer start.
202 pixel_format* fmt; //Format of framebuffer.
203 size_t width; //Width of framebuffer.
204 size_t height; //Height of framebuffer.
205 size_t stride; //Stride in pixels.
206 size_t allocated; //Amount of memory allocated (only meaningful if user_memory=true).
207 template<bool X> friend class framebuffer;
211 struct premultiplied_color;
214 * Rendered framebuffer.
216 * This framebuffer is in RGB32/RGB64 format, and is always backed by memory buffer.
218 template<bool X>
219 struct framebuffer
221 typedef typename framebufferelem<X>::t element_t;
223 * Creates framebuffer. The framebuffer dimensions are initially 0x0.
225 framebuffer() throw();
228 * Destructor.
230 ~framebuffer() throw();
233 * Sets the backing memory for framebuffer. The specified memory is not freed if framebuffer is reallocated or
234 * destroyed.
236 * parameter _memory: The memory buffer.
237 * parameter _width: Width of framebuffer.
238 * parameter _height: Height of framebuffer.
239 * parameter _pitch: Distance in bytes between successive scanlines (in pixels).
241 void set(element_t* _memory, size_t _width, size_t _height, size_t _pitch) throw();
244 * Sets the size of the framebuffer. The memory is freed if framebuffer is reallocated or destroyed.
246 * The pitch of resulting framebuffer is the smallest possible.
248 * parameter _width: Width of framebuffer.
249 * parameter _height: Height of framebuffer.
250 * parameter upside_down: If true, image is upside down in memory.
251 * throws std::bad_alloc: Not enough memory.
253 void reallocate(size_t _width, size_t _height, bool upside_down = false) throw(std::bad_alloc);
256 * Set origin
258 * parameter _originx: X coordinate for origin.
259 * parameter _originy: Y coordinate for origin.
261 void set_origin(size_t _originx, size_t _originy) throw();
263 * Get X origin.
265 * Returns: The X origin.
267 size_t get_origin_x() const throw();
269 * Get Y origin.
271 * Returns: The Y origin.
273 size_t get_origin_y() const throw();
275 * Paints raw framebuffer into framebuffer. The upper-left of image will be at origin. Scales the image by given
276 * factors. If the image does not fit with specified scale factors, it is clipped.
278 * parameter scr The framebuffer to paint.
279 * parameter hscale Horizontal scale factor.
280 * parameter vscale Vertical scale factor.
282 void copy_from(framebuffer_raw& scr, size_t hscale, size_t vscale) throw();
285 * Get pointer into specified row.
287 * parameter row: Number of row (must be less than height).
288 * Returns: Pointer into row data.
290 element_t* rowptr(size_t row) throw();
292 * Get pointer into specified row.
294 * parameter row: Number of row (must be less than height).
295 * Returns: Pointer into row data.
297 const element_t* rowptr(size_t row) const throw();
299 * Set palette. Also converts the image data.
301 * parameter r Shift for red component
302 * parameter g Shift for green component
303 * parameter b Shift for blue component
305 void set_palette(uint32_t r, uint32_t g, uint32_t b) throw(std::bad_alloc);
307 * Get width of image.
309 * Returns: The width.
311 size_t get_width() const throw();
313 * Get height of image.
315 * Returns: The height.
317 size_t get_height() const throw();
319 * Get R palette offset.
321 uint8_t get_palette_r() const throw();
323 * Get G palette offset.
325 uint8_t get_palette_g() const throw();
327 * Get B palette offset.
329 uint8_t get_palette_b() const throw();
330 private:
331 framebuffer(const framebuffer& f);
332 framebuffer& operator=(const framebuffer& f);
333 size_t width; //Width of framebuffer.
334 size_t height; //Height of framebuffer.
335 size_t stride; //Stride in pixels.
336 size_t offset_x; //X offset.
337 size_t offset_y; //Y offset.
338 element_t* mem; //The memory of framebuffer.
339 pixel_format* current_fmt; //Current format of framebuffer.
340 pixel_format_aux_palette<X> auxpal; //Aux palette.
341 bool user_mem; //True if internal memory is used.
342 bool upside_down; //Upside down flag.
343 uint8_t active_rshift; //Red shift.
344 uint8_t active_gshift; //Green shift.
345 uint8_t active_bshift; //Blue shift.
346 friend struct premultiplied_color;
350 * Base class for objects to render.
352 struct render_object
355 * Constructor.
357 render_object() throw();
359 * Destructor.
361 virtual ~render_object() throw();
363 * Kill object function. If it returns true, kill the request. Default is to return false.
365 virtual bool kill_request(void* obj) throw();
367 * Return true if myobj and killobj are equal and not NULL.
369 bool kill_request_ifeq(void* myobj, void* killobj);
371 * Draw the object.
373 * parameter scr: The screen to draw it on.
375 virtual void operator()(struct framebuffer<false>& scr) throw() = 0;
376 virtual void operator()(struct framebuffer<true>& scr) throw() = 0;
382 * Premultiplied color.
384 struct premultiplied_color
386 uint32_t hi;
387 uint32_t lo;
388 uint64_t hiHI;
389 uint64_t loHI;
390 uint32_t orig;
391 uint16_t origa;
392 uint16_t inv;
393 uint32_t invHI;
395 operator bool() const throw() { return (origa != 0); }
396 bool operator!() const throw() { return (origa == 0); }
398 premultiplied_color() throw()
400 hi = lo = 0;
401 hiHI = loHI = 0;
402 orig = 0;
403 origa = 0;
404 inv = 256;
405 invHI = 65536;
408 premultiplied_color(int64_t color) throw()
410 if(color < 0) {
411 //Transparent.
412 orig = 0;
413 origa = 0;
414 inv = 256;
415 } else {
416 orig = color & 0xFFFFFF;
417 origa = 256 - ((color >> 24) & 0xFF);;
418 inv = 256 - origa;
420 invHI = 256 * static_cast<uint32_t>(inv);
421 set_palette(16, 8, 0, false);
422 set_palette(32, 16, 0, true);
423 //std::cerr << "Color " << color << " -> hi=" << hi << " lo=" << lo << " inv=" << inv << std::endl;
425 void set_palette(unsigned rshift, unsigned gshift, unsigned bshift, bool X) throw();
426 template<bool X> void set_palette(struct framebuffer<X>& s) throw()
428 set_palette(s.active_rshift, s.active_gshift, s.active_bshift, X);
430 uint32_t blend(uint32_t color) throw()
432 uint32_t a, b;
433 a = color & 0xFF00FF;
434 b = (color & 0xFF00FF00) >> 8;
435 return (((a * inv + hi) >> 8) & 0xFF00FF) | ((b * inv + lo) & 0xFF00FF00);
437 void apply(uint32_t& x) throw()
439 x = blend(x);
441 uint64_t blend(uint64_t color) throw()
443 uint64_t a, b;
444 a = color & 0xFFFF0000FFFFULL;
445 b = (color & 0xFFFF0000FFFF0000ULL) >> 16;
446 return (((a * invHI + hiHI) >> 16) & 0xFFFF0000FFFFULL) | ((b * invHI + loHI) & 0xFFFF0000FFFF0000ULL);
448 void apply(uint64_t& x) throw()
450 x = blend(x);
456 * Bitmap font (8x16).
458 struct bitmap_font
461 * Bitmap font glyph.
463 struct glyph
465 bool wide; //If set, 16 wide instead of 8.
466 uint32_t* data; //Glyph data. Bitpacked with element padding between rows.
467 size_t offset; //Glyph offset.
471 * Bitmap font layout.
473 struct layout
475 size_t x; //X position.
476 size_t y; //Y position.
477 const glyph* dglyph; //The glyph itself.
480 * Constructor.
482 bitmap_font() throw(std::bad_alloc);
484 * Load a .hex format font.
486 * Parameter data: The font data.
487 * Parameter size: The font data size in bytes.
488 * Throws std::runtime_error: Bad font data.
490 void load_hex(const char* data, size_t size) throw(std::bad_alloc, std::runtime_error);
492 * Locate glyph.
494 * Parameter glyph: Number of glyph to locate.
495 * Returns: Glyph parameters.
497 const glyph& get_glyph(uint32_t glyph) throw();
499 * Get metrics of string.
501 * Parameter string: The string to get metrics of.
502 * Returns: A pair. First element is width of string, the second is height of string.
504 std::pair<size_t, size_t> get_metrics(const std::string& string) throw();
506 * Layout a string.
508 * Parameter string: The string to get layout of.
509 * Returns: String layout.
511 std::vector<layout> dolayout(const std::string& string) throw(std::bad_alloc);
513 * Render string to framebuffer.
515 * Parameter framebuffer: The framebuffer to render on.
516 * Parameter x: The x-coordinate to start from.
517 * Parameter y: The y-coordinate to start from.
518 * Parameter text: The text to render.
519 * Parameter fg: The foreground color.
520 * Parameter bg: The background color.
521 * Parameter hdbl: If set, double width horizontally.
522 * Parameter vdbl: If set, double height vertically.
524 template<bool X> void render(struct framebuffer<X>& scr, int32_t x, int32_t y, const std::string& text,
525 premultiplied_color fg, premultiplied_color bg, bool hdbl, bool vdbl) throw();
526 private:
527 glyph bad_glyph;
528 uint32_t bad_glyph_data[4];
529 std::map<uint32_t, glyph> glyphs;
530 size_t tabstop;
531 std::vector<uint32_t> memory;
532 void load_hex_glyph(const char* data, size_t size) throw(std::bad_alloc, std::runtime_error);
536 #define RENDER_PAGE_SIZE 65500
539 * Queue of render operations.
541 struct render_queue
544 * Applies all objects in the queue in order.
546 * parameter scr: The screen to apply queue to.
548 template<bool X> void run(struct framebuffer<X>& scr) throw();
551 * Frees all objects in the queue without applying them.
553 void clear() throw();
555 * Call kill_request on all objects in queue.
557 void kill_request(void* obj) throw();
559 * Get memory from internal allocator.
561 void* alloc(size_t block) throw(std::bad_alloc);
564 * Call object constructor on internal memory.
566 template<class T, typename... U> void create_add(U... args)
568 add(*new(alloc(sizeof(T))) T(args...));
572 * Constructor.
574 render_queue() throw();
576 * Destructor.
578 ~render_queue() throw();
579 private:
580 void add(struct render_object& obj) throw(std::bad_alloc);
581 struct node { struct render_object* obj; struct node* next; bool killed; };
582 struct page { char content[RENDER_PAGE_SIZE]; };
583 struct node* queue_head;
584 struct node* queue_tail;
585 size_t memory_allocated;
586 size_t pages;
587 std::map<size_t, page> memory;
591 * Clip range inside another.
593 * parameter origin: Origin coordinate.
594 * parameter size: Dimension size.
595 * parameter base: Base coordinate.
596 * parameter minc: Minimum coordinate relative to base. Updated.
597 * parameter maxc: Maximum coordinate relative to base. Updated.
599 void clip_range(uint32_t origin, uint32_t size, int32_t base, int32_t& minc, int32_t& maxc) throw();
602 #endif