Redo text rendering (adds halo support to gui.text())
[lsnes.git] / include / library / framebuffer.hpp
blobb01db50eb7d67a120aafe75aa45ef3ba5d993853
1 #ifndef _library__framebuffer__hpp__included__
2 #define _library__framebuffer__hpp__included__
4 #include <stdexcept>
5 #include <functional>
6 #include <cstdlib>
7 #include <vector>
8 #include <map>
9 #include <set>
10 #include "framebuffer-pixfmt.hpp"
11 #include "threads.hpp"
13 namespace framebuffer
15 template<bool X> struct elem {};
16 template<> struct elem<false> { typedef uint32_t t; };
17 template<> struct elem<true> { typedef uint64_t t; };
19 extern unsigned default_shift_r;
20 extern unsigned default_shift_g;
21 extern unsigned default_shift_b;
23 /**
24 * Pixel format auxillary palette.
26 template<bool X>
27 struct auxpalette
29 typedef typename elem<X>::t element_t;
30 uint8_t rshift; //Red shift.
31 uint8_t gshift; //Green shift.
32 uint8_t bshift; //Blue shift.
33 std::vector<element_t> pcache; //Palette cache.
36 /**
37 * Game framebuffer information.
39 struct info
41 /**
42 * Pixel format of framebuffer.
44 pixfmt* type;
45 /**
46 * The physical memory backing the framebuffer.
48 char* mem;
49 /**
50 * Physical width of framebuffer.
52 size_t physwidth;
53 /**
54 * Physical height of framebuffer.
56 size_t physheight;
57 /**
58 * Physical stride of framebuffer (in bytes).
60 size_t physstride;
61 /**
62 * Visible width of framebuffer.
64 size_t width;
65 /**
66 * Visible height of framebuffer.
68 size_t height;
69 /**
70 * Visible stride of framebuffer (in bytes).
72 size_t stride;
73 /**
74 * Visible X offset of framebuffer.
76 size_t offset_x;
77 /**
78 * Visible Y offset of framebuffer.
80 size_t offset_y;
83 template<bool X> struct framebuffer;
85 /**
86 * Raw framebuffer.
88 * This framebuffer is in system format, and can either be backed either by temporary buffer or memory buffer.
90 * Any copying only preserves the visible part.
92 struct raw
94 /**
95 * Create a new framebuffer backed by temporary buffer.
97 * The resulting framebuffer is read-only.
99 * Parameter info: The framebuffer info.
101 raw(const info& finfo) throw(std::bad_alloc);
103 * Create a new framebuffer backed by memory buffer.
105 * The resulting framebuffer can be written to.
107 raw() throw(std::bad_alloc);
109 * Copy a framebuffer.
111 * The resulting copy is writable.
113 * Parameter f: The framebuffer.
115 raw(const raw& f) throw(std::bad_alloc);
117 * Assign a framebuffer.
119 * Parameter f: The framebuffer.
120 * Throws std::runtime_error: The target framebuffer is not writable.
122 raw& operator=(const raw& f) throw(std::bad_alloc, std::runtime_error);
124 * Load contents of framebuffer.
126 * parameter data: The data to load.
127 * throws std::runtime_error: The target framebuffer is not writable.
129 void load(const std::vector<char>& data) throw(std::bad_alloc, std::runtime_error);
131 * Save contents of framebuffer.
133 * parameter data: The vector to write the data to (in format compatible with load()).
135 void save(std::vector<char>& data) throw(std::bad_alloc);
137 * Save contents of framebuffer as a PNG.
139 * parameter file: The filename to save to.
140 * throws std::runtime_error: Can't save the PNG.
142 void save_png(const std::string& file) throw(std::bad_alloc, std::runtime_error);
144 * Get width.
146 * Returns: The width.
148 size_t get_width() const throw();
150 * Get height.
152 * Returns: The height.
154 size_t get_height() const throw();
156 * Get stride.
158 size_t get_stride() const throw();
160 * Get starting address.
162 unsigned char* get_start() const throw();
164 * Get pixel format.
166 pixfmt* get_format() const throw();
168 * Destructor.
170 ~raw();
171 private:
172 bool user_memory; //True if allocated in user memory, false if aliases framebuffer.
173 char* addr; //Address of framebuffer start.
174 pixfmt* fmt; //Format of framebuffer.
175 size_t width; //Width of framebuffer.
176 size_t height; //Height of framebuffer.
177 size_t stride; //Stride in pixels.
178 size_t allocated; //Amount of memory allocated (only meaningful if user_memory=true).
179 template<bool X> friend class fb;
183 struct color;
186 * Rendered framebuffer.
188 * This framebuffer is in RGB32/RGB64 format, and is always backed by memory buffer.
190 template<bool X>
191 struct fb
193 typedef typename elem<X>::t element_t;
195 * Creates framebuffer. The framebuffer dimensions are initially 0x0.
197 fb() throw();
200 * Destructor.
202 ~fb() throw();
205 * Sets the backing memory for framebuffer. The specified memory is not freed if framebuffer is reallocated or
206 * destroyed.
208 * parameter _memory: The memory buffer.
209 * parameter _width: Width of framebuffer.
210 * parameter _height: Height of framebuffer.
211 * parameter _pitch: Distance in bytes between successive scanlines (in pixels).
213 * Note: The _pitch should be multiple of 4, and _memory aligned to 16 bytes.
215 void set(element_t* _memory, size_t _width, size_t _height, size_t _pitch) throw();
218 * Sets the size of the framebuffer. The memory is freed if framebuffer is reallocated or destroyed.
220 * The pitch of resulting framebuffer is the smallest possible.
222 * parameter _width: Width of framebuffer.
223 * parameter _height: Height of framebuffer.
224 * parameter upside_down: If true, image is upside down in memory.
225 * throws std::bad_alloc: Not enough memory.
227 void reallocate(size_t _width, size_t _height, bool upside_down = false) throw(std::bad_alloc);
230 * Set origin
232 * parameter _originx: X coordinate for origin.
233 * parameter _originy: Y coordinate for origin.
235 void set_origin(size_t _originx, size_t _originy) throw();
237 * Get X origin.
239 * Returns: The X origin.
241 size_t get_origin_x() const throw();
243 * Get Y origin.
245 * Returns: The Y origin.
247 size_t get_origin_y() const throw();
249 * Paints raw framebuffer into framebuffer. The upper-left of image will be at origin. Scales the image by given
250 * factors. If the image does not fit with specified scale factors, it is clipped.
252 * parameter scr The framebuffer to paint.
253 * parameter hscale Horizontal scale factor.
254 * parameter vscale Vertical scale factor.
256 void copy_from(raw& scr, size_t hscale, size_t vscale) throw();
259 * Get pointer into specified row.
261 * parameter row: Number of row (must be less than height).
262 * Returns: Pointer into row data.
264 element_t* rowptr(size_t row) throw();
266 * Get pointer into specified row.
268 * parameter row: Number of row (must be less than height).
269 * Returns: Pointer into row data.
271 const element_t* rowptr(size_t row) const throw();
273 * Set palette. Also converts the image data.
275 * parameter r Shift for red component
276 * parameter g Shift for green component
277 * parameter b Shift for blue component
279 void set_palette(uint32_t r, uint32_t g, uint32_t b) throw(std::bad_alloc);
281 * Get stride of image.
283 * Returns: The stride.
285 size_t get_stride() const throw() { return stride; }
287 * Get width of image.
289 * Returns: The width.
291 size_t get_width() const throw() { return width; }
293 * Get height of image.
295 * Returns: The height.
297 size_t get_height() const throw() { return height; }
299 * Get last blit width
301 * Returns: The width.
303 size_t get_last_blit_width() const throw() { return last_blit_w; }
305 * Get last blit height
307 * Returns: The height.
309 size_t get_last_blit_height() const throw() { return last_blit_h; }
311 * Get R palette offset.
313 uint8_t get_palette_r() const throw();
315 * Get G palette offset.
317 uint8_t get_palette_g() const throw();
319 * Get B palette offset.
321 uint8_t get_palette_b() const throw();
322 private:
323 fb(const fb& f);
324 fb& operator=(const fb& f);
325 size_t width; //Width of framebuffer.
326 size_t height; //Height of framebuffer.
327 size_t stride; //Stride in pixels.
328 size_t offset_x; //X offset.
329 size_t offset_y; //Y offset.
330 size_t last_blit_w; //Width of last blit.
331 size_t last_blit_h; //Height of last blit.
332 element_t* mem; //The memory of framebuffer.
333 pixfmt* current_fmt; //Current format of framebuffer.
334 auxpalette<X> auxpal; //Aux palette.
335 bool user_mem; //True if internal memory is used.
336 bool upside_down; //Upside down flag.
337 uint8_t active_rshift; //Red shift.
338 uint8_t active_gshift; //Green shift.
339 uint8_t active_bshift; //Blue shift.
340 friend struct color;
343 struct queue;
346 * Base class for objects to render.
348 struct object
351 * Constructor.
353 object() throw();
355 * Destructor.
357 virtual ~object() throw();
359 * Kill object function. If it returns true, kill the request. Default is to return false.
361 virtual bool kill_request(void* obj) throw();
363 * Return true if myobj and killobj are equal and not NULL.
365 bool kill_request_ifeq(void* myobj, void* killobj);
367 * Draw the object.
369 * parameter scr: The screen to draw it on.
371 virtual void operator()(struct fb<false>& scr) throw() = 0;
372 virtual void operator()(struct fb<true>& scr) throw() = 0;
374 * Clone the object.
376 virtual void clone(struct queue& q) const throw(std::bad_alloc) = 0;
380 * Premultiplied color.
382 struct color
384 uint32_t hi;
385 uint32_t lo;
386 uint64_t hiHI;
387 uint64_t loHI;
388 uint32_t orig;
389 uint16_t origa;
390 uint16_t inv;
391 uint32_t invHI;
393 operator bool() const throw() { return (origa != 0); }
394 bool operator!() const throw() { return (origa == 0); }
396 color() throw()
398 hi = lo = 0;
399 hiHI = loHI = 0;
400 orig = 0;
401 origa = 0;
402 inv = 256;
403 invHI = 65536;
406 color(int64_t color) throw()
408 if(color < 0) {
409 //Transparent.
410 orig = 0;
411 origa = 0;
412 inv = 256;
413 } else {
414 orig = color & 0xFFFFFF;
415 origa = 256 - ((color >> 24) & 0xFF);;
416 inv = 256 - origa;
418 invHI = 256 * static_cast<uint32_t>(inv);
419 set_palette(default_shift_r, default_shift_g, default_shift_b, false);
420 set_palette(default_shift_r << 1, default_shift_g << 1, default_shift_b << 1, true);
421 //std::cerr << "Color " << color << " -> hi=" << hi << " lo=" << lo << " inv=" << inv << std::endl;
423 color(const std::string& color) throw(std::bad_alloc, std::runtime_error);
424 static std::string stringify(int64_t number);
425 void set_palette(unsigned rshift, unsigned gshift, unsigned bshift, bool X) throw();
426 template<bool X> void set_palette(struct fb<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) &
447 0xFFFF0000FFFF0000ULL);
449 void apply(uint64_t& x) throw()
451 x = blend(x);
453 int64_t asnumber() const throw()
455 if(!origa)
456 return -1;
457 else
458 return orig | ((uint32_t)(256 - origa) << 24);
462 int64_t color_rotate_hue(int64_t color, int count, int steps);
463 int64_t color_adjust_saturation(int64_t color, double adjust);
464 int64_t color_adjust_lightness(int64_t color, double adjust);
467 * Base color name.
469 struct basecolor
471 basecolor(const std::string& name, int64_t value);
475 * Color modifier.
477 struct color_mod
479 color_mod(const std::string& name, std::function<void(int64_t&)> fn);
483 * Bitmap font (8x16).
485 struct font
488 * Bitmap font glyph.
490 struct glyph
492 bool wide; //If set, 16 wide instead of 8.
493 uint32_t* data; //Glyph data. Bitpacked with element padding between rows.
494 size_t offset; //Glyph offset.
498 * Bitmap font layout.
500 struct layout
502 size_t x; //X position.
503 size_t y; //Y position.
504 const glyph* dglyph; //The glyph itself.
507 * Constructor.
509 font() throw(std::bad_alloc);
511 * Load a .hex format font.
513 * Parameter data: The font data.
514 * Parameter size: The font data size in bytes.
515 * Throws std::runtime_error: Bad font data.
517 void load_hex(const char* data, size_t size) throw(std::bad_alloc, std::runtime_error);
519 * Locate glyph.
521 * Parameter glyph: Number of glyph to locate.
522 * Returns: Glyph parameters.
524 const glyph& get_glyph(uint32_t glyph) throw();
526 * Get metrics of string.
528 * Parameter string: The string to get metrics of.
529 * Returns: A pair. First element is width of string, the second is height of string.
531 std::pair<size_t, size_t> get_metrics(const std::string& string, uint32_t xalign, bool xdbl, bool ydbl)
532 throw();
534 * Layout a string.
536 * Parameter string: The string to get layout of.
537 * Returns: String layout.
539 std::vector<layout> dolayout(const std::string& string) throw(std::bad_alloc);
541 * Get width of string.
543 * Parameter string: The string to get width of.
544 * Returns: The width.
546 uint32_t get_width(const std::string& string);
548 * Get set of all glyph numbers.
550 std::set<uint32_t> get_glyphs_set();
552 * Get bad glyph.
554 const glyph& get_bad_glyph() throw();
556 * Render string to framebuffer.
558 * Parameter framebuffer: The framebuffer to render on.
559 * Parameter x: The x-coordinate to start from.
560 * Parameter y: The y-coordinate to start from.
561 * Parameter text: The text to render.
562 * Parameter fg: The foreground color.
563 * Parameter bg: The background color.
564 * Parameter hdbl: If set, double width horizontally.
565 * Parameter vdbl: If set, double height vertically.
567 template<bool X> void render(struct fb<X>& scr, int32_t x, int32_t y, const std::string& text,
568 color fg, color bg, bool hdbl, bool vdbl) throw();
570 * Call function on every glyph.
572 * Parameter str: The string to call on.
573 * Parameter alignx: The x alignment.
574 * Parameter cb: The callback to call.
576 void for_each_glyph(const std::string& str, uint32_t alignx, bool xdbl, bool ydbl,
577 std::function<void(uint32_t x, uint32_t y, const glyph& g, bool xdbl, bool ydbl)> cb);
579 * Render to bitmap.
581 * Parameter buf: The bufer to render on.
582 * Parameter stride: The stride on buffer.
583 * Parameter str: The string to render.
584 * Parameter alignx: The x alignment.
585 * Parameter hdbl: If set, double width horizontally.
586 * Parameter vdbl: If set, double height vertically.
588 void render(uint8_t* buf, size_t stride, const std::string& str, uint32_t alignx, bool hdbl, bool vdbl);
589 private:
590 glyph bad_glyph;
591 uint32_t bad_glyph_data[4];
592 std::map<uint32_t, glyph> glyphs;
593 size_t tabstop;
594 std::vector<uint32_t> memory;
595 void load_hex_glyph(const char* data, size_t size) throw(std::bad_alloc, std::runtime_error);
599 #define RENDER_PAGE_SIZE 65500
602 * Queue of render operations.
604 struct queue
607 * Applies all objects in the queue in order.
609 * parameter scr: The screen to apply queue to.
611 template<bool X> void run(struct fb<X>& scr) throw();
614 * Frees all objects in the queue without applying them.
616 void clear() throw();
618 * Call kill_request on all objects in queue.
620 void kill_request(void* obj) throw();
622 * Get memory from internal allocator.
624 void* alloc(size_t block) throw(std::bad_alloc);
627 * Call object constructor on internal memory.
629 template<class T, typename... U> void create_add(U... args)
631 add(*new(alloc(sizeof(T))) T(args...));
634 * Copy objects from another render queue.
636 void copy_from(queue& q) throw(std::bad_alloc);
638 * Helper for clone.
640 template<typename T> void clone_helper(const T* obj)
642 create_add<T>(*obj);
645 * Get number of objects.
647 size_t get_object_count()
649 size_t c = 0;
650 struct node* n = queue_head;
651 while(n != NULL) {
652 n = n->next;
653 c++;
655 return c;
658 * Constructor.
660 queue() throw();
662 * Destructor.
664 ~queue() throw();
665 private:
666 void add(struct object& obj) throw(std::bad_alloc);
667 struct node { struct object* obj; struct node* next; bool killed; };
668 struct page { char content[RENDER_PAGE_SIZE]; };
669 struct node* queue_head;
670 struct node* queue_tail;
671 size_t memory_allocated;
672 size_t pages;
673 threads::lock display_mutex; //Synchronize display and kill.
674 std::map<size_t, page> memory;
678 * Drop every fourth byte of specified buffer.
680 * Parameter dest: Destination buffer, should be 16-byte aligned.
681 * Parameter src: Source buffer, should be 16-byte aligned.
682 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
684 void copy_drop4(uint8_t* dest, const uint32_t* src, size_t units);
687 * Drop every fourth byte of specified buffer and swap first and third.
689 * Parameter dest: Destination buffer, should be 16-byte aligned.
690 * Parameter src: Source buffer, should be 16-byte aligned.
691 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
693 void copy_drop4s(uint8_t* dest, const uint32_t* src, size_t units);
696 * Swap every first and third byte out of four
698 * Parameter dest: Destination buffer, should be 16-byte aligned.
699 * Parameter src: Source buffer, should be 16-byte aligned.
700 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
702 void copy_swap4(uint8_t* dest, const uint32_t* src, size_t units);
705 * Drop every fourth word of specified buffer.
707 * Parameter dest: Destination buffer, should be 16-byte aligned.
708 * Parameter src: Source buffer, should be 16-byte aligned.
709 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
711 void copy_drop4(uint16_t* dest, const uint64_t* src, size_t units);
714 * Drop every fourth byte of specified buffer and swap first and third.
716 * Parameter dest: Destination buffer, should be 16-byte aligned.
717 * Parameter src: Source buffer, should be 16-byte aligned.
718 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
720 void copy_drop4s(uint16_t* dest, const uint64_t* src, size_t units);
723 * Swap every first and third byte out of four
725 * Parameter dest: Destination buffer, should be 16-byte aligned.
726 * Parameter src: Source buffer, should be 16-byte aligned.
727 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
729 void copy_swap4(uint16_t* dest, const uint64_t* src, size_t units);
733 #endif