Line data Source code
1 :
2 : /* Copyright (c) 2007-2013, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2009-2010, Cedric Stalder <cedric.stalder@gmail.com>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #include "dataIStream.h"
22 :
23 : #include "global.h"
24 : #include "log.h"
25 : #include "node.h"
26 :
27 : #include <lunchbox/buffer.h>
28 : #include <lunchbox/debug.h>
29 : #include <lunchbox/decompressor.h>
30 : #include <lunchbox/plugins/compressor.h>
31 :
32 : #include <string.h>
33 :
34 : namespace co
35 : {
36 : namespace detail
37 : {
38 4287632 : class DataIStream
39 : {
40 : public:
41 4323723 : DataIStream( const bool swap_ )
42 : : input( 0 )
43 : , inputSize( 0 )
44 : , position( 0 )
45 4323723 : , swap( swap_ )
46 4319774 : {}
47 :
48 : /** The current input buffer */
49 : const uint8_t* input;
50 :
51 : /** The size of the input buffer */
52 : uint64_t inputSize;
53 :
54 : /** The current read position in the buffer */
55 : uint64_t position;
56 :
57 : lunchbox::Decompressor decompressor; //!< current decompressor
58 : lunchbox::Bufferb data; //!< decompressed buffer
59 : bool swap; //!< Invoke endian conversion
60 : };
61 : }
62 :
63 1551878 : DataIStream::DataIStream( const bool swap_ )
64 1551878 : : _impl( new detail::DataIStream( swap_ ))
65 1550422 : {}
66 :
67 2775405 : DataIStream::DataIStream( const DataIStream& rhs )
68 2775405 : : _impl( new detail::DataIStream( rhs._impl->swap ))
69 2775411 : {}
70 :
71 4317288 : DataIStream::~DataIStream()
72 : {
73 4317288 : _reset();
74 4286166 : delete _impl;
75 4321818 : }
76 :
77 1063247 : DataIStream& DataIStream::operator = ( const DataIStream& rhs )
78 : {
79 1063247 : _reset();
80 1063279 : setSwapping( rhs.isSwapping( ));
81 1063284 : return *this;
82 : }
83 :
84 1063437 : void DataIStream::setSwapping( const bool onOff )
85 : {
86 1063437 : _impl->swap = onOff;
87 1063437 : }
88 :
89 4294949 : bool DataIStream::isSwapping() const
90 : {
91 4294949 : return _impl->swap;
92 : }
93 :
94 5374237 : void DataIStream::_reset()
95 : {
96 5374237 : _impl->input = 0;
97 5374237 : _impl->inputSize = 0;
98 5374237 : _impl->position = 0;
99 5374237 : _impl->swap = false;
100 5374237 : }
101 :
102 3231544 : void DataIStream::_read( void* data, uint64_t size )
103 : {
104 3231544 : if( !_checkBuffer( ))
105 : {
106 0 : LBUNREACHABLE;
107 0 : LBERROR << "No more input data" << std::endl;
108 0 : return;
109 : }
110 :
111 3231545 : LBASSERT( _impl->input );
112 3231544 : if( size > _impl->inputSize - _impl->position )
113 : {
114 0 : LBERROR << "Not enough data in input buffer: need " << size
115 0 : << " bytes, " << _impl->inputSize - _impl->position << " left "
116 0 : << std::endl;
117 0 : LBUNREACHABLE;
118 : // TODO: Allow reads which are asymmetric to writes by reading from
119 : // multiple blocks here?
120 0 : return;
121 : }
122 :
123 3231544 : memcpy( data, _impl->input + _impl->position, size );
124 3231544 : _impl->position += size;
125 : }
126 :
127 3777156 : const void* DataIStream::getRemainingBuffer( const uint64_t size )
128 : {
129 3777156 : if( !_checkBuffer( ))
130 0 : return 0;
131 :
132 3774890 : LBASSERT( _impl->position + size <= _impl->inputSize );
133 3774812 : if( _impl->position + size > _impl->inputSize )
134 0 : return 0;
135 :
136 3774812 : _impl->position += size;
137 3774812 : return _impl->input + _impl->position - size;
138 : }
139 :
140 3785684 : uint64_t DataIStream::getRemainingBufferSize()
141 : {
142 3785684 : if( !_checkBuffer( ))
143 109 : return 0;
144 :
145 3780134 : return _impl->inputSize - _impl->position;
146 : }
147 :
148 0 : bool DataIStream::wasUsed() const
149 : {
150 0 : return _impl->input != 0;
151 : }
152 :
153 10742140 : bool DataIStream::_checkBuffer()
154 : {
155 25405988 : while( _impl->position >= _impl->inputSize )
156 : {
157 3927211 : uint32_t compressor = EQ_COMPRESSOR_NONE;
158 3927211 : uint32_t nChunks = 0;
159 3927211 : const void* data = 0;
160 :
161 3927211 : _impl->position = 0;
162 3927211 : _impl->input = 0;
163 3927211 : _impl->inputSize = 0;
164 :
165 3927211 : if( !getNextBuffer( compressor, nChunks, &data, _impl->inputSize ))
166 158 : return false;
167 :
168 : _impl->input = _decompress( data, compressor, nChunks,
169 3921895 : _impl->inputSize );
170 : }
171 10736637 : return true;
172 : }
173 :
174 3921163 : const uint8_t* DataIStream::_decompress( const void* data, const uint32_t name,
175 : const uint32_t nChunks,
176 : const uint64_t dataSize )
177 : {
178 3921163 : const uint8_t* src = reinterpret_cast< const uint8_t* >( data );
179 3921163 : if( name == EQ_COMPRESSOR_NONE )
180 3921163 : return src;
181 :
182 0 : LBASSERT( name > EQ_COMPRESSOR_NONE );
183 : #ifndef CO_AGGRESSIVE_CACHING
184 0 : _impl->data.clear();
185 : #endif
186 0 : _impl->data.reset( dataSize );
187 :
188 0 : _impl->decompressor.setup( Global::getPluginRegistry(), name );
189 0 : LBASSERT( _impl->decompressor.uses( name ));
190 :
191 0 : uint64_t outDim[2] = { 0, dataSize };
192 : uint64_t* chunkSizes = static_cast< uint64_t* >(
193 0 : alloca( nChunks * sizeof( uint64_t )));
194 : void** chunks = static_cast< void ** >(
195 0 : alloca( nChunks * sizeof( void* )));
196 :
197 0 : for( uint32_t i = 0; i < nChunks; ++i )
198 : {
199 0 : const uint64_t size = *reinterpret_cast< const uint64_t* >( src );
200 0 : chunkSizes[ i ] = size;
201 0 : src += sizeof( uint64_t );
202 :
203 : // The plugin API uses non-const source buffers for in-place operations
204 0 : chunks[ i ] = const_cast< uint8_t* >( src );
205 0 : src += size;
206 : }
207 :
208 : _impl->decompressor.decompress( chunks, chunkSizes, nChunks,
209 0 : _impl->data.getData(), outDim );
210 0 : return _impl->data.getData();
211 : }
212 :
213 60 : }
|