| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- // ================================================================================
- // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
- // == See tb_core.h for more information. ==
- // ================================================================================
- #ifndef TB_BITMAP_FRAGMENT_H
- #define TB_BITMAP_FRAGMENT_H
- #include "tb_core.h"
- #include "tb_geometry.h"
- #include "tb_hashtable.h"
- #include "tb_list.h"
- #include "tb_id.h"
- #include "tb_linklist.h"
- namespace tb {
- class TBBitmapFragment;
- class TBBitmap;
- /** Return the nearest power of two from val.
- F.ex 110 -> 128, 256->256, 257->512 etc. */
- int TBGetNearestPowerOfTwo(int val);
- /** TBImageloader is a class used to load skin images. It can be implemented
- in any way the system wants, but the system has to provide a image loader
- capable of handling all image formats used in the skin. */
- class TBImageLoader
- {
- public:
- /** Static method used to create an image loader. The system must implement this
- function and create an implementation of the TBImageLoader interface. */
- static TBImageLoader *CreateFromFile(const char *filename);
- virtual ~TBImageLoader() {}
- /** Return the width of the loaded bitmap. */
- virtual int Width() = 0;
- /** Return the height of the loaded bitmap. */
- virtual int Height() = 0;
- /** Return the data of the loaded bitmap.
- This data should always be in 32bit RGBA format. */
- virtual uint32 *Data() = 0;
- };
- /** Allocator of space out of a given available space. */
- class TBSpaceAllocator
- {
- public:
- /** A chunk of space */
- class Space : public TBLinkOf<Space>
- {
- public:
- int x, width;
- };
- TBSpaceAllocator(int available_space)
- : m_available_space(available_space) { }
- /** Return true if no allocations are currently live using this allocator. */
- bool IsAllAvailable() const { return !m_used_space_list.HasLinks(); }
- /** Return true if the given width is currently available. */
- bool HasSpace(int needed_w) const;
- /** Allocate the given space and return the Space, or nullptr on error. */
- Space *AllocSpace(int needed_w);
- /** Free the given space so it is available for new allocations. */
- void FreeSpace(Space *space);
- private:
- Space *GetSmallestAvailableSpace(int needed_w);
- int m_available_space;
- TBLinkListAutoDeleteOf<Space> m_free_space_list;
- TBLinkListAutoDeleteOf<Space> m_used_space_list;
- };
- /** Allocates space for TBBitmapFragment in a row (used in TBBitmapFragmentMap). */
- class TBFragmentSpaceAllocator : public TBSpaceAllocator
- {
- public:
- TBFragmentSpaceAllocator(int y, int width, int height)
- : TBSpaceAllocator(width), y(y), height(height) {}
- int y, height;
- };
- /** Specify when the bitmap should be validated when calling TBBitmapFragmentMap::GetBitmap. */
- enum TB_VALIDATE_TYPE {
- /** Always validate the bitmap (The bitmap is updated if needed) */
- TB_VALIDATE_ALWAYS,
- /** Only validate if the bitmap does not yet exist (Make sure there is
- a valid bitmap pointer, but the data is not necessarily updated) */
- TB_VALIDATE_FIRST_TIME
- };
- /** TBBitmapFragmentMap is used to pack multiple bitmaps into a single TBBitmap.
- When initialized (in a size suitable for a TBBitmap) is also creates a software buffer
- that will make up the TBBitmap when all fragments have been added. */
- class TBBitmapFragmentMap
- {
- public:
- TBBitmapFragmentMap();
- ~TBBitmapFragmentMap();
- /** Initialize the map with the given size. The size should be a power of two since
- it will be used to create a TBBitmap (texture memory). */
- bool Init(int bitmap_w, int bitmap_h);
- /** Create a new fragment with the given size and data in this map.
- Returns nullptr if there is not enough room in this map or on any other fail. */
- TBBitmapFragment *CreateNewFragment(int frag_w, int frag_h, int data_stride, uint32 *frag_data, bool add_border);
- /** Free up the space used by the given fragment, so that other fragments can take its place. */
- void FreeFragmentSpace(TBBitmapFragment *frag);
- /** Return the bitmap for this map.
- By default, the bitmap is validated if needed before returning (See TB_VALIDATE_TYPE) */
- TBBitmap *GetBitmap(TB_VALIDATE_TYPE validate_type = TB_VALIDATE_ALWAYS);
- private:
- friend class TBBitmapFragmentManager;
- bool ValidateBitmap();
- void DeleteBitmap();
- void CopyData(TBBitmapFragment *frag, int data_stride, uint32 *frag_data, int border);
- TBListAutoDeleteOf<TBFragmentSpaceAllocator> m_rows;
- int m_bitmap_w, m_bitmap_h;
- uint32 *m_bitmap_data;
- TBBitmap *m_bitmap;
- bool m_need_update;
- int m_allocated_pixels;
- };
- /** TBBitmapFragment represents a sub part of a TBBitmap.
- It's owned by TBBitmapFragmentManager which pack multiple
- TBBitmapFragment within TBBitmaps to reduce texture switching. */
- class TBBitmapFragment
- {
- public:
- /** Return the width of the bitmap fragment. */
- int Width() const { return m_rect.w; }
- /** Return the height of the bitmap fragment. */
- int Height() const { return m_rect.h; }
- /** Return the bitmap for this fragment.
- By default, the bitmap is validated if needed before returning (See TB_VALIDATE_TYPE) */
- TBBitmap *GetBitmap(TB_VALIDATE_TYPE validate_type = TB_VALIDATE_ALWAYS) { return m_map->GetBitmap(validate_type); }
- /** Return the height allocated to this fragment. This may be larger than Height() depending
- of the internal allocation of fragments in a map. It should rarely be used. */
- int GetAllocatedHeight() const { return m_row_height; }
- public:
- TBBitmapFragmentMap *m_map;
- TBRect m_rect;
- TBFragmentSpaceAllocator *m_row;
- TBFragmentSpaceAllocator::Space *m_space;
- TBID m_id;
- int m_row_height;
- /** This uint32 is reserved for batching renderer backends. It's not used
- internally, but always initialized to 0xffffffff for all new fragments. */
- uint32 m_batch_id;
- };
- /** TBBitmapFragmentManager manages loading bitmaps of arbitrary size,
- pack as many of them into as few TBBitmap as possible.
- It also makes sure that only one instance of each file is loaded,
- so f.ex loading "foo.png" many times still load and allocate one
- TBBitmapFragment. */
- class TBBitmapFragmentManager
- {
- public:
- TBBitmapFragmentManager();
- ~TBBitmapFragmentManager();
- /** Set to true if a 1px border should be added to new fragments so stretched
- drawing won't get filtering artifacts at the edges (default is disabled). */
- void SetAddBorder(bool add_border) { m_add_border = add_border; }
- bool GetAddBorder() const { return m_add_border; }
- /** Get the fragment with the given image filename. If it's not already loaded,
- it will be loaded into a new fragment with the filename as id.
- returns nullptr on fail. */
- TBBitmapFragment *GetFragmentFromFile(const char *filename, bool dedicated_map);
- /** Get the fragment with the given id, or nullptr if it doesn't exist. */
- TBBitmapFragment *GetFragment(const TBID &id) const;
- /** Create a new fragment from the given data.
- @param id The id that should be used to identify the fragment.
- @param dedicated_map if true, it will get a dedicated map.
- @param data_w the width of the data.
- @param data_h the height of the data.
- @param data_stride the number of pixels in a row of the input data.
- @param data pointer to the data in BGRA32 format. */
- TBBitmapFragment *CreateNewFragment(const TBID &id, bool dedicated_map,
- int data_w, int data_h, int data_stride,
- uint32 *data);
- /** Delete the given fragment and free the space it used in its map,
- so that other fragments can take its place. */
- void FreeFragment(TBBitmapFragment *frag);
- /** Clear all loaded bitmaps and all created bitmap fragments and maps.
- After this call, do not keep any pointers to any TBBitmapFragment created
- by this fragment manager. */
- void Clear();
- /** Validate bitmaps on fragment maps that has changed. */
- bool ValidateBitmaps();
- /** Delete all bitmaps in all fragment maps in this manager.
- The bitmaps will be recreated automatically when needed, or when
- calling ValidateBitmaps. You do not need to call this, except when
- the context is lost and all bitmaps must be forgotten. */
- void DeleteBitmaps();
- /** Get number of fragment maps that is currently used. */
- int GetNumMaps() const { return m_fragment_maps.GetNumItems(); }
- /** Set the number of maps (TBBitmaps) this manager should be allowed to create.
- If a new fragment can't fit into any existing bitmap and the limit is reached,
- the fragment creation will fail. Set to 0 for unlimited (default). */
- void SetNumMapsLimit(int num_maps_limit);
- /** Set the default size of new fragment maps. These must be power of two. */
- void SetDefaultMapSize(int w, int h);
- /** Get the amount (in percent) of space that is currently occupied by all maps
- in this fragment manager. */
- int GetUseRatio() const;
- #ifdef TB_RUNTIME_DEBUG_INFO
- /** Render the maps on screen, to analyze fragment positioning. */
- void Debug();
- #endif
- private:
- TBListOf<TBBitmapFragmentMap> m_fragment_maps;
- TBHashTableOf<TBBitmapFragment> m_fragments;
- int m_num_maps_limit;
- bool m_add_border;
- int m_default_map_w;
- int m_default_map_h;
- };
- }; // namespace tb
- #endif // TB_BITMAP_FRAGMENT_H
|