Rework how memory tracking works
[lsnes.git] / include / library / framebuffer.hpp
blob3c94832d4a54cc5b795b214eb3e2e33ced00396f
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"
12 #include "memtracker.hpp"
14 namespace framebuffer
16 extern const char* render_page_id;
17 template<bool X> struct elem {};
18 template<> struct elem<false> { typedef uint32_t t; };
19 template<> struct elem<true> { typedef uint64_t t; };
21 extern unsigned default_shift_r;
22 extern unsigned default_shift_g;
23 extern unsigned default_shift_b;
25 /**
26 * Pixel format auxillary palette.
28 template<bool X>
29 struct auxpalette
31 typedef typename elem<X>::t element_t;
32 uint8_t rshift; //Red shift.
33 uint8_t gshift; //Green shift.
34 uint8_t bshift; //Blue shift.
35 std::vector<element_t> pcache; //Palette cache.
38 /**
39 * Game framebuffer information.
41 struct info
43 /**
44 * Pixel format of framebuffer.
46 pixfmt* type;
47 /**
48 * The physical memory backing the framebuffer.
50 char* mem;
51 /**
52 * Physical width of framebuffer.
54 size_t physwidth;
55 /**
56 * Physical height of framebuffer.
58 size_t physheight;
59 /**
60 * Physical stride of framebuffer (in bytes).
62 size_t physstride;
63 /**
64 * Visible width of framebuffer.
66 size_t width;
67 /**
68 * Visible height of framebuffer.
70 size_t height;
71 /**
72 * Visible stride of framebuffer (in bytes).
74 size_t stride;
75 /**
76 * Visible X offset of framebuffer.
78 size_t offset_x;
79 /**
80 * Visible Y offset of framebuffer.
82 size_t offset_y;
85 template<bool X> struct framebuffer;
87 /**
88 * Raw framebuffer.
90 * This framebuffer is in system format, and can either be backed either by temporary buffer or memory buffer.
92 * Any copying only preserves the visible part.
94 struct raw
96 /**
97 * Create a new framebuffer backed by temporary buffer.
99 * The resulting framebuffer is read-only.
101 * Parameter info: The framebuffer info.
103 raw(const info& finfo) throw(std::bad_alloc);
105 * Create a new framebuffer backed by memory buffer.
107 * The resulting framebuffer can be written to.
109 raw() throw(std::bad_alloc);
111 * Copy a framebuffer.
113 * The resulting copy is writable.
115 * Parameter f: The framebuffer.
117 raw(const raw& f) throw(std::bad_alloc);
119 * Assign a framebuffer.
121 * Parameter f: The framebuffer.
122 * Throws std::runtime_error: The target framebuffer is not writable.
124 raw& operator=(const raw& f) throw(std::bad_alloc, std::runtime_error);
126 * Load contents of framebuffer.
128 * parameter data: The data to load.
129 * throws std::runtime_error: The target framebuffer is not writable.
131 void load(const std::vector<char>& data) throw(std::bad_alloc, std::runtime_error);
133 * Save contents of framebuffer.
135 * parameter data: The vector to write the data to (in format compatible with load()).
137 void save(std::vector<char>& data) throw(std::bad_alloc);
139 * Save contents of framebuffer as a PNG.
141 * parameter file: The filename to save to.
142 * throws std::runtime_error: Can't save the PNG.
144 void save_png(const std::string& file) throw(std::bad_alloc, std::runtime_error);
146 * Get width.
148 * Returns: The width.
150 size_t get_width() const throw();
152 * Get height.
154 * Returns: The height.
156 size_t get_height() const throw();
158 * Get stride.
160 size_t get_stride() const throw();
162 * Get starting address.
164 unsigned char* get_start() const throw();
166 * Get pixel format.
168 pixfmt* get_format() const throw();
170 * Destructor.
172 ~raw();
173 private:
174 bool user_memory; //True if allocated in user memory, false if aliases framebuffer.
175 char* addr; //Address of framebuffer start.
176 pixfmt* fmt; //Format of framebuffer.
177 size_t width; //Width of framebuffer.
178 size_t height; //Height of framebuffer.
179 size_t stride; //Stride in pixels.
180 size_t allocated; //Amount of memory allocated (only meaningful if user_memory=true).
181 template<bool X> friend class fb;
185 struct color;
188 * Rendered framebuffer.
190 * This framebuffer is in RGB32/RGB64 format, and is always backed by memory buffer.
192 template<bool X>
193 struct fb
195 typedef typename elem<X>::t element_t;
197 * Creates framebuffer. The framebuffer dimensions are initially 0x0.
199 fb() throw();
202 * Destructor.
204 ~fb() throw();
207 * Sets the backing memory for framebuffer. The specified memory is not freed if framebuffer is reallocated or
208 * destroyed.
210 * parameter _memory: The memory buffer.
211 * parameter _width: Width of framebuffer.
212 * parameter _height: Height of framebuffer.
213 * parameter _pitch: Distance in bytes between successive scanlines (in pixels).
215 * Note: The _pitch should be multiple of 4, and _memory aligned to 16 bytes.
217 void set(element_t* _memory, size_t _width, size_t _height, size_t _pitch) throw();
220 * Sets the size of the framebuffer. The memory is freed if framebuffer is reallocated or destroyed.
222 * The pitch of resulting framebuffer is the smallest possible.
224 * parameter _width: Width of framebuffer.
225 * parameter _height: Height of framebuffer.
226 * parameter upside_down: If true, image is upside down in memory.
227 * throws std::bad_alloc: Not enough memory.
229 void reallocate(size_t _width, size_t _height, bool upside_down = false) throw(std::bad_alloc);
232 * Set origin
234 * parameter _originx: X coordinate for origin.
235 * parameter _originy: Y coordinate for origin.
237 void set_origin(size_t _originx, size_t _originy) throw();
239 * Get X origin.
241 * Returns: The X origin.
243 size_t get_origin_x() const throw();
245 * Get Y origin.
247 * Returns: The Y origin.
249 size_t get_origin_y() const throw();
251 * Paints raw framebuffer into framebuffer. The upper-left of image will be at origin. Scales the image by given
252 * factors. If the image does not fit with specified scale factors, it is clipped.
254 * parameter scr The framebuffer to paint.
255 * parameter hscale Horizontal scale factor.
256 * parameter vscale Vertical scale factor.
258 void copy_from(raw& scr, size_t hscale, size_t vscale) throw();
261 * Get pointer into specified row.
263 * parameter row: Number of row (must be less than height).
264 * Returns: Pointer into row data.
266 element_t* rowptr(size_t row) throw();
268 * Get pointer into specified row.
270 * parameter row: Number of row (must be less than height).
271 * Returns: Pointer into row data.
273 const element_t* rowptr(size_t row) const throw();
275 * Set palette. Also converts the image data.
277 * parameter r Shift for red component
278 * parameter g Shift for green component
279 * parameter b Shift for blue component
281 void set_palette(uint32_t r, uint32_t g, uint32_t b) throw(std::bad_alloc);
283 * Get stride of image.
285 * Returns: The stride.
287 size_t get_stride() const throw() { return stride; }
289 * Get width of image.
291 * Returns: The width.
293 size_t get_width() const throw() { return width; }
295 * Get height of image.
297 * Returns: The height.
299 size_t get_height() const throw() { return height; }
301 * Get last blit width
303 * Returns: The width.
305 size_t get_last_blit_width() const throw() { return last_blit_w; }
307 * Get last blit height
309 * Returns: The height.
311 size_t get_last_blit_height() const throw() { return last_blit_h; }
313 * Get R palette offset.
315 uint8_t get_palette_r() const throw();
317 * Get G palette offset.
319 uint8_t get_palette_g() const throw();
321 * Get B palette offset.
323 uint8_t get_palette_b() const throw();
324 private:
325 fb(const fb& f);
326 fb& operator=(const fb& f);
327 size_t width; //Width of framebuffer.
328 size_t height; //Height of framebuffer.
329 size_t stride; //Stride in pixels.
330 size_t offset_x; //X offset.
331 size_t offset_y; //Y offset.
332 size_t last_blit_w; //Width of last blit.
333 size_t last_blit_h; //Height of last blit.
334 element_t* mem; //The memory of framebuffer.
335 pixfmt* current_fmt; //Current format of framebuffer.
336 auxpalette<X> auxpal; //Aux palette.
337 bool user_mem; //True if internal memory is used.
338 bool upside_down; //Upside down flag.
339 uint8_t active_rshift; //Red shift.
340 uint8_t active_gshift; //Green shift.
341 uint8_t active_bshift; //Blue shift.
342 friend struct color;
345 struct queue;
348 * Base class for objects to render.
350 struct object
353 * Constructor.
355 object() throw();
357 * Destructor.
359 virtual ~object() throw();
361 * Kill object function. If it returns true, kill the request. Default is to return false.
363 virtual bool kill_request(void* obj) throw();
365 * Return true if myobj and killobj are equal and not NULL.
367 bool kill_request_ifeq(void* myobj, void* killobj);
369 * Draw the object.
371 * parameter scr: The screen to draw it on.
373 virtual void operator()(struct fb<false>& scr) throw() = 0;
374 virtual void operator()(struct fb<true>& scr) throw() = 0;
376 * Clone the object.
378 virtual void clone(struct queue& q) const throw(std::bad_alloc) = 0;
382 * Premultiplied color.
384 struct 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 color() throw()
400 hi = lo = 0;
401 hiHI = loHI = 0;
402 orig = 0;
403 origa = 0;
404 inv = 256;
405 invHI = 65536;
408 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(default_shift_r, default_shift_g, default_shift_b, false);
422 set_palette(default_shift_r << 1, default_shift_g << 1, default_shift_b << 1, true);
423 //std::cerr << "Color " << color << " -> hi=" << hi << " lo=" << lo << " inv=" << inv << std::endl;
425 color(const std::string& color) throw(std::bad_alloc, std::runtime_error);
426 static std::string stringify(int64_t number);
427 void set_palette(unsigned rshift, unsigned gshift, unsigned bshift, bool X) throw();
428 template<bool X> void set_palette(struct fb<X>& s) throw()
430 set_palette(s.active_rshift, s.active_gshift, s.active_bshift, X);
432 uint32_t blend(uint32_t color) throw()
434 uint32_t a, b;
435 a = color & 0xFF00FF;
436 b = (color & 0xFF00FF00) >> 8;
437 return (((a * inv + hi) >> 8) & 0xFF00FF) | ((b * inv + lo) & 0xFF00FF00);
439 void apply(uint32_t& x) throw()
441 x = blend(x);
443 uint64_t blend(uint64_t color) throw()
445 uint64_t a, b;
446 a = color & 0xFFFF0000FFFFULL;
447 b = (color & 0xFFFF0000FFFF0000ULL) >> 16;
448 return (((a * invHI + hiHI) >> 16) & 0xFFFF0000FFFFULL) | ((b * invHI + loHI) &
449 0xFFFF0000FFFF0000ULL);
451 void apply(uint64_t& x) throw()
453 x = blend(x);
455 int64_t asnumber() const throw()
457 if(!origa)
458 return -1;
459 else
460 return orig | ((uint32_t)(256 - origa) << 24);
464 int64_t color_rotate_hue(int64_t color, int count, int steps);
465 int64_t color_adjust_saturation(int64_t color, double adjust);
466 int64_t color_adjust_lightness(int64_t color, double adjust);
469 * Base color name.
471 struct basecolor
473 basecolor(const std::string& name, int64_t value);
477 * Color modifier.
479 struct color_mod
481 color_mod(const std::string& name, std::function<void(int64_t&)> fn);
485 * Bitmap font (8x16).
487 struct font
490 * Bitmap font glyph.
492 struct glyph
494 bool wide; //If set, 16 wide instead of 8.
495 uint32_t* data; //Glyph data. Bitpacked with element padding between rows.
496 size_t offset; //Glyph offset.
497 uint32_t get_width() const throw() { return wide ? 16 : 8; }
498 uint32_t get_height() const throw() { return 16; }
499 bool read_pixel(uint32_t x, uint32_t y) const throw()
501 if(wide) {
502 return ((data[y >> 1] >> (31 - (((y & 1) << 4) + x))) & 1) != 0;
503 } else {
504 return ((data[y >> 2] >> (31 - (((y & 3) << 3) + x))) & 1) != 0;
510 * Bitmap font layout.
512 struct layout
514 size_t x; //X position.
515 size_t y; //Y position.
516 const glyph* dglyph; //The glyph itself.
519 * Constructor.
521 font() throw(std::bad_alloc);
523 * Load a .hex format font.
525 * Parameter data: The font data.
526 * Parameter size: The font data size in bytes.
527 * Throws std::runtime_error: Bad font data.
529 void load_hex(const char* data, size_t size) throw(std::bad_alloc, std::runtime_error);
531 * Locate glyph.
533 * Parameter glyph: Number of glyph to locate.
534 * Returns: Glyph parameters.
536 const glyph& get_glyph(uint32_t glyph) throw();
538 * Get metrics of string.
540 * Parameter string: The string to get metrics of.
541 * Returns: A pair. First element is width of string, the second is height of string.
543 std::pair<size_t, size_t> get_metrics(const std::string& string, uint32_t xalign, bool xdbl, bool ydbl)
544 throw();
546 * Layout a string.
548 * Parameter string: The string to get layout of.
549 * Returns: String layout.
551 std::vector<layout> dolayout(const std::string& string) throw(std::bad_alloc);
553 * Get width of string.
555 * Parameter string: The string to get width of.
556 * Returns: The width.
558 uint32_t get_width(const std::string& string);
560 * Get set of all glyph numbers.
562 std::set<uint32_t> get_glyphs_set();
564 * Get bad glyph.
566 const glyph& get_bad_glyph() throw();
568 * Render string to framebuffer.
570 * Parameter framebuffer: The framebuffer to render on.
571 * Parameter x: The x-coordinate to start from.
572 * Parameter y: The y-coordinate to start from.
573 * Parameter text: The text to render.
574 * Parameter fg: The foreground color.
575 * Parameter bg: The background color.
576 * Parameter hdbl: If set, double width horizontally.
577 * Parameter vdbl: If set, double height vertically.
579 template<bool X> void render(struct fb<X>& scr, int32_t x, int32_t y, const std::string& text,
580 color fg, color bg, bool hdbl, bool vdbl) throw();
582 * Call function on every glyph.
584 * Parameter str: The string to call on.
585 * Parameter alignx: The x alignment.
586 * Parameter cb: The callback to call.
588 void for_each_glyph(const std::string& str, uint32_t alignx, bool xdbl, bool ydbl,
589 std::function<void(uint32_t x, uint32_t y, const glyph& g, bool xdbl, bool ydbl)> cb);
591 * Render to bitmap.
593 * Parameter buf: The bufer to render on.
594 * Parameter stride: The stride on buffer.
595 * Parameter str: The string to render.
596 * Parameter alignx: The x alignment.
597 * Parameter hdbl: If set, double width horizontally.
598 * Parameter vdbl: If set, double height vertically.
600 void render(uint8_t* buf, size_t stride, const std::string& str, uint32_t alignx, bool hdbl, bool vdbl);
601 private:
602 glyph bad_glyph;
603 uint32_t bad_glyph_data[4];
604 std::map<uint32_t, glyph> glyphs;
605 size_t tabstop;
606 std::vector<uint32_t> memory;
607 void load_hex_glyph(const char* data, size_t size) throw(std::bad_alloc, std::runtime_error);
611 #define RENDER_PAGE_SIZE 65500
614 * Queue of render operations.
616 struct queue
619 * Applies all objects in the queue in order.
621 * parameter scr: The screen to apply queue to.
623 template<bool X> void run(struct fb<X>& scr) throw();
626 * Frees all objects in the queue without applying them.
628 void clear() throw();
630 * Call kill_request on all objects in queue.
632 void kill_request(void* obj) throw();
634 * Get memory from internal allocator.
636 void* alloc(size_t block) throw(std::bad_alloc);
639 * Call object constructor on internal memory.
641 template<class T, typename... U> void create_add(U... args)
643 add(*new(alloc(sizeof(T))) T(args...));
646 * Copy objects from another render queue.
648 void copy_from(queue& q) throw(std::bad_alloc);
650 * Helper for clone.
652 template<typename T> void clone_helper(const T* obj)
654 create_add<T>(*obj);
657 * Get number of objects.
659 size_t get_object_count()
661 size_t c = 0;
662 struct node* n = queue_head;
663 while(n != NULL) {
664 n = n->next;
665 c++;
667 return c;
670 * Constructor.
672 queue() throw();
674 * Destructor.
676 ~queue() throw();
677 private:
678 void add(struct object& obj) throw(std::bad_alloc);
679 struct node { struct object* obj; struct node* next; bool killed; };
680 struct page {
681 char content[RENDER_PAGE_SIZE];
682 page() { memtracker::singleton()(render_page_id, RENDER_PAGE_SIZE + 36); }
683 ~page() { memtracker::singleton()(render_page_id, -RENDER_PAGE_SIZE - 36); }
685 struct node* queue_head;
686 struct node* queue_tail;
687 size_t memory_allocated;
688 size_t pages;
689 threads::lock display_mutex; //Synchronize display and kill.
690 std::map<size_t, page> memory;
691 memtracker::autorelease tracker;
695 * Drop every fourth byte of specified buffer.
697 * Parameter dest: Destination buffer, should be 16-byte aligned.
698 * Parameter src: Source buffer, should be 16-byte aligned.
699 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
701 void copy_drop4(uint8_t* dest, const uint32_t* src, size_t units);
704 * Drop every fourth byte of specified buffer and swap first and third.
706 * Parameter dest: Destination buffer, should be 16-byte aligned.
707 * Parameter src: Source buffer, should be 16-byte aligned.
708 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
710 void copy_drop4s(uint8_t* dest, const uint32_t* src, size_t units);
713 * Swap every first and third byte out of four
715 * Parameter dest: Destination buffer, should be 16-byte aligned.
716 * Parameter src: Source buffer, should be 16-byte aligned.
717 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
719 void copy_swap4(uint8_t* dest, const uint32_t* src, size_t units);
722 * Drop every fourth word of specified buffer.
724 * Parameter dest: Destination buffer, should be 16-byte aligned.
725 * Parameter src: Source buffer, should be 16-byte aligned.
726 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
728 void copy_drop4(uint16_t* dest, const uint64_t* src, size_t units);
731 * Drop every fourth byte of specified buffer and swap first and third.
733 * Parameter dest: Destination buffer, should be 16-byte aligned.
734 * Parameter src: Source buffer, should be 16-byte aligned.
735 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
737 void copy_drop4s(uint16_t* dest, const uint64_t* src, size_t units);
740 * Swap every first and third byte out of four
742 * Parameter dest: Destination buffer, should be 16-byte aligned.
743 * Parameter src: Source buffer, should be 16-byte aligned.
744 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
746 void copy_swap4(uint16_t* dest, const uint64_t* src, size_t units);
750 #endif