diff options
Diffstat (limited to 'thirdparty/etcpak/DataProvider.cpp')
-rw-r--r-- | thirdparty/etcpak/DataProvider.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/thirdparty/etcpak/DataProvider.cpp b/thirdparty/etcpak/DataProvider.cpp new file mode 100644 index 0000000000..6bd4b105ed --- /dev/null +++ b/thirdparty/etcpak/DataProvider.cpp @@ -0,0 +1,77 @@ +#include <assert.h> +#include <utility> + +#include "BitmapDownsampled.hpp" +#include "DataProvider.hpp" +#include "MipMap.hpp" + +DataProvider::DataProvider( const char* fn, bool mipmap, bool bgr ) + : m_offset( 0 ) + , m_mipmap( mipmap ) + , m_done( false ) + , m_lines( 32 ) +{ + m_bmp.emplace_back( new Bitmap( fn, m_lines, bgr ) ); + m_current = m_bmp[0].get(); +} + +DataProvider::~DataProvider() +{ +} + +unsigned int DataProvider::NumberOfParts() const +{ + unsigned int parts = ( ( m_bmp[0]->Size().y / 4 ) + m_lines - 1 ) / m_lines; + + if( m_mipmap ) + { + v2i current = m_bmp[0]->Size(); + int levels = NumberOfMipLevels( current ); + unsigned int lines = m_lines; + for( int i=1; i<levels; i++ ) + { + assert( current.x != 1 || current.y != 1 ); + current.x = std::max( 1, current.x / 2 ); + current.y = std::max( 1, current.y / 2 ); + lines *= 2; + parts += ( ( std::max( 4, current.y ) / 4 ) + lines - 1 ) / lines; + } + assert( current.x == 1 && current.y == 1 ); + } + + return parts; +} + +DataPart DataProvider::NextPart() +{ + assert( !m_done ); + + unsigned int lines = m_lines; + bool done; + + const auto ptr = m_current->NextBlock( lines, done ); + DataPart ret = { + ptr, + std::max<unsigned int>( 4, m_current->Size().x ), + lines, + m_offset + }; + + m_offset += m_current->Size().x / 4 * lines; + + if( done ) + { + if( m_mipmap && ( m_current->Size().x != 1 || m_current->Size().y != 1 ) ) + { + m_lines *= 2; + m_bmp.emplace_back( new BitmapDownsampled( *m_current, m_lines ) ); + m_current = m_bmp[m_bmp.size()-1].get(); + } + else + { + m_done = true; + } + } + + return ret; +} |