summaryrefslogtreecommitdiff
path: root/thirdparty/etcpak/DataProvider.cpp
blob: 6bd4b105edd36c2ea21087f50572298242567557 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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;
}