1 #ifndef _library__framebuffer__hpp__included__
2 #define _library__framebuffer__hpp__included__
10 #include "framebuffer-pixfmt.hpp"
11 #include "threads.hpp"
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
;
24 * Pixel format auxillary palette.
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.
37 * Game framebuffer information.
42 * Pixel format of framebuffer.
46 * The physical memory backing the framebuffer.
50 * Physical width of framebuffer.
54 * Physical height of framebuffer.
58 * Physical stride of framebuffer (in bytes).
62 * Visible width of framebuffer.
66 * Visible height of framebuffer.
70 * Visible stride of framebuffer (in bytes).
74 * Visible X offset of framebuffer.
78 * Visible Y offset of framebuffer.
83 template<bool X
> struct 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.
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
);
146 * Returns: The width.
148 size_t get_width() const throw();
152 * Returns: The height.
154 size_t get_height() const throw();
158 size_t get_stride() const throw();
160 * Get starting address.
162 unsigned char* get_start() const throw();
166 pixfmt
* get_format() const throw();
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
;
186 * Rendered framebuffer.
188 * This framebuffer is in RGB32/RGB64 format, and is always backed by memory buffer.
193 typedef typename elem
<X
>::t element_t
;
195 * Creates framebuffer. The framebuffer dimensions are initially 0x0.
205 * Sets the backing memory for framebuffer. The specified memory is not freed if framebuffer is reallocated or
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
);
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();
239 * Returns: The X origin.
241 size_t get_origin_x() const throw();
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();
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.
346 * Base class for objects to render.
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
);
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;
376 virtual void clone(struct queue
& q
) const throw(std::bad_alloc
) = 0;
380 * Premultiplied color.
393 operator bool() const throw() { return (origa
!= 0); }
394 bool operator!() const throw() { return (origa
== 0); }
406 color(int64_t color
) throw()
414 orig
= color
& 0xFFFFFF;
415 origa
= 256 - ((color
>> 24) & 0xFF);;
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()
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()
441 uint64_t blend(uint64_t color
) throw()
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()
453 int64_t asnumber() const throw()
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
);
471 basecolor(const std::string
& name
, int64_t value
);
479 color_mod(const std::string
& name
, std::function
<void(int64_t&)> fn
);
483 * Bitmap font (8x16).
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.
495 uint32_t get_width() const throw() { return wide
? 16 : 8; }
496 uint32_t get_height() const throw() { return 16; }
497 bool read_pixel(uint32_t x
, uint32_t y
) const throw()
500 return ((data
[y
>> 1] >> (31 - (((y
& 1) << 4) + x
))) & 1) != 0;
502 return ((data
[y
>> 2] >> (31 - (((y
& 3) << 3) + x
))) & 1) != 0;
508 * Bitmap font layout.
512 size_t x
; //X position.
513 size_t y
; //Y position.
514 const glyph
* dglyph
; //The glyph itself.
519 font() throw(std::bad_alloc
);
521 * Load a .hex format font.
523 * Parameter data: The font data.
524 * Parameter size: The font data size in bytes.
525 * Throws std::runtime_error: Bad font data.
527 void load_hex(const char* data
, size_t size
) throw(std::bad_alloc
, std::runtime_error
);
531 * Parameter glyph: Number of glyph to locate.
532 * Returns: Glyph parameters.
534 const glyph
& get_glyph(uint32_t glyph
) throw();
536 * Get metrics of string.
538 * Parameter string: The string to get metrics of.
539 * Returns: A pair. First element is width of string, the second is height of string.
541 std::pair
<size_t, size_t> get_metrics(const std::string
& string
, uint32_t xalign
, bool xdbl
, bool ydbl
)
546 * Parameter string: The string to get layout of.
547 * Returns: String layout.
549 std::vector
<layout
> dolayout(const std::string
& string
) throw(std::bad_alloc
);
551 * Get width of string.
553 * Parameter string: The string to get width of.
554 * Returns: The width.
556 uint32_t get_width(const std::string
& string
);
558 * Get set of all glyph numbers.
560 std::set
<uint32_t> get_glyphs_set();
564 const glyph
& get_bad_glyph() throw();
566 * Render string to framebuffer.
568 * Parameter framebuffer: The framebuffer to render on.
569 * Parameter x: The x-coordinate to start from.
570 * Parameter y: The y-coordinate to start from.
571 * Parameter text: The text to render.
572 * Parameter fg: The foreground color.
573 * Parameter bg: The background color.
574 * Parameter hdbl: If set, double width horizontally.
575 * Parameter vdbl: If set, double height vertically.
577 template<bool X
> void render(struct fb
<X
>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
578 color fg
, color bg
, bool hdbl
, bool vdbl
) throw();
580 * Call function on every glyph.
582 * Parameter str: The string to call on.
583 * Parameter alignx: The x alignment.
584 * Parameter cb: The callback to call.
586 void for_each_glyph(const std::string
& str
, uint32_t alignx
, bool xdbl
, bool ydbl
,
587 std::function
<void(uint32_t x
, uint32_t y
, const glyph
& g
, bool xdbl
, bool ydbl
)> cb
);
591 * Parameter buf: The bufer to render on.
592 * Parameter stride: The stride on buffer.
593 * Parameter str: The string to render.
594 * Parameter alignx: The x alignment.
595 * Parameter hdbl: If set, double width horizontally.
596 * Parameter vdbl: If set, double height vertically.
598 void render(uint8_t* buf
, size_t stride
, const std::string
& str
, uint32_t alignx
, bool hdbl
, bool vdbl
);
601 uint32_t bad_glyph_data
[4];
602 std::map
<uint32_t, glyph
> glyphs
;
604 std::vector
<uint32_t> memory
;
605 void load_hex_glyph(const char* data
, size_t size
) throw(std::bad_alloc
, std::runtime_error
);
609 #define RENDER_PAGE_SIZE 65500
612 * Queue of render operations.
617 * Applies all objects in the queue in order.
619 * parameter scr: The screen to apply queue to.
621 template<bool X
> void run(struct fb
<X
>& scr
) throw();
624 * Frees all objects in the queue without applying them.
626 void clear() throw();
628 * Call kill_request on all objects in queue.
630 void kill_request(void* obj
) throw();
632 * Get memory from internal allocator.
634 void* alloc(size_t block
) throw(std::bad_alloc
);
637 * Call object constructor on internal memory.
639 template<class T
, typename
... U
> void create_add(U
... args
)
641 add(*new(alloc(sizeof(T
))) T(args
...));
644 * Copy objects from another render queue.
646 void copy_from(queue
& q
) throw(std::bad_alloc
);
650 template<typename T
> void clone_helper(const T
* obj
)
655 * Get number of objects.
657 size_t get_object_count()
660 struct node
* n
= queue_head
;
676 void add(struct object
& obj
) throw(std::bad_alloc
);
677 struct node
{ struct object
* obj
; struct node
* next
; bool killed
; };
678 struct page
{ char content
[RENDER_PAGE_SIZE
]; };
679 struct node
* queue_head
;
680 struct node
* queue_tail
;
681 size_t memory_allocated
;
683 threads::lock display_mutex
; //Synchronize display and kill.
684 std::map
<size_t, page
> memory
;
688 * Drop every fourth byte of specified buffer.
690 * Parameter dest: Destination buffer, should be 16-byte aligned.
691 * Parameter src: Source buffer, should be 16-byte aligned.
692 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
694 void copy_drop4(uint8_t* dest
, const uint32_t* src
, size_t units
);
697 * Drop every fourth byte of specified buffer and swap first and third.
699 * Parameter dest: Destination buffer, should be 16-byte aligned.
700 * Parameter src: Source buffer, should be 16-byte aligned.
701 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
703 void copy_drop4s(uint8_t* dest
, const uint32_t* src
, size_t units
);
706 * Swap every first and third byte out of four
708 * Parameter dest: Destination buffer, should be 16-byte aligned.
709 * Parameter src: Source buffer, should be 16-byte aligned.
710 * Parameter units: Number of 4 byte units to copy. Must be multiple of 4.
712 void copy_swap4(uint8_t* dest
, const uint32_t* src
, size_t units
);
715 * Drop every fourth word of specified buffer.
717 * Parameter dest: Destination buffer, should be 16-byte aligned.
718 * Parameter src: Source buffer, should be 16-byte aligned.
719 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
721 void copy_drop4(uint16_t* dest
, const uint64_t* src
, size_t units
);
724 * Drop every fourth byte of specified buffer and swap first and third.
726 * Parameter dest: Destination buffer, should be 16-byte aligned.
727 * Parameter src: Source buffer, should be 16-byte aligned.
728 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
730 void copy_drop4s(uint16_t* dest
, const uint64_t* src
, size_t units
);
733 * Swap every first and third byte out of four
735 * Parameter dest: Destination buffer, should be 16-byte aligned.
736 * Parameter src: Source buffer, should be 16-byte aligned.
737 * Parameter units: Number of 8 byte units to copy. Must be multiple of 2.
739 void copy_swap4(uint16_t* dest
, const uint64_t* src
, size_t units
);