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 <pression/decompressor.h>
30 : #include <pression/plugins/compressor.h>
31 :
32 : #include <string.h>
33 :
34 : namespace co
35 : {
36 : namespace detail
37 : {
38 3021688 : class DataIStream
39 : {
40 : public:
41 3021253 : explicit DataIStream( const bool swap_ )
42 : : input( 0 )
43 : , inputSize( 0 )
44 : , position( 0 )
45 3021253 : , swap( swap_ )
46 3021261 : {}
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 : pression::Decompressor decompressor; //!< current decompressor
58 : lunchbox::Bufferb data; //!< decompressed buffer
59 : bool swap; //!< Invoke endian conversion
60 : };
61 : }
62 :
63 1104295 : DataIStream::DataIStream( const bool swap_ )
64 1104295 : : _impl( new detail::DataIStream( swap_ ))
65 1104348 : {}
66 :
67 1917471 : DataIStream::DataIStream( const DataIStream& rhs )
68 1917471 : : _impl( new detail::DataIStream( rhs._impl->swap ))
69 1917470 : {}
70 :
71 3021728 : DataIStream::~DataIStream()
72 : {
73 3021728 : _reset();
74 3021677 : delete _impl;
75 3021540 : }
76 :
77 625397 : DataIStream& DataIStream::operator = ( const DataIStream& rhs )
78 : {
79 625397 : _reset();
80 625419 : setSwapping( rhs.isSwapping( ));
81 625421 : return *this;
82 : }
83 :
84 625583 : void DataIStream::setSwapping( const bool onOff )
85 : {
86 625583 : _impl->swap = onOff;
87 625583 : }
88 :
89 3946540 : bool DataIStream::isSwapping() const
90 : {
91 3946540 : return _impl->swap;
92 : }
93 :
94 3637110 : void DataIStream::_reset()
95 : {
96 3637110 : _impl->input = 0;
97 3637110 : _impl->inputSize = 0;
98 3637110 : _impl->position = 0;
99 3637110 : _impl->swap = false;
100 3637110 : }
101 :
102 3320984 : void DataIStream::_read( void* data, uint64_t size )
103 : {
104 3320984 : if( !_checkBuffer( ))
105 : {
106 0 : LBUNREACHABLE;
107 0 : LBERROR << "No more input data" << std::endl;
108 0 : return;
109 : }
110 :
111 3320980 : LBASSERT( _impl->input );
112 3320979 : 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 3320979 : memcpy( data, _impl->input + _impl->position, size );
124 3320979 : _impl->position += size;
125 : }
126 :
127 2507120 : const void* DataIStream::getRemainingBuffer( const uint64_t size )
128 : {
129 2507120 : if( !_checkBuffer( ))
130 0 : return 0;
131 :
132 2511489 : LBASSERT( _impl->position + size <= _impl->inputSize );
133 2511363 : if( _impl->position + size > _impl->inputSize )
134 0 : return 0;
135 :
136 2511363 : _impl->position += size;
137 2511363 : return _impl->input + _impl->position - size;
138 : }
139 :
140 2516106 : uint64_t DataIStream::getRemainingBufferSize()
141 : {
142 2516106 : if( !_checkBuffer( ))
143 110 : return 0;
144 :
145 2504578 : return _impl->inputSize - _impl->position;
146 : }
147 :
148 0 : bool DataIStream::wasUsed() const
149 : {
150 0 : return _impl->input != 0;
151 : }
152 :
153 8242402 : bool DataIStream::_checkBuffer()
154 : {
155 19090877 : while( _impl->position >= _impl->inputSize )
156 : {
157 2623291 : uint32_t compressor = EQ_COMPRESSOR_NONE;
158 2623291 : uint32_t nChunks = 0;
159 2623291 : const void* data = 0;
160 :
161 2623291 : _impl->position = 0;
162 2623291 : _impl->input = 0;
163 2623291 : _impl->inputSize = 0;
164 :
165 2623291 : if( !getNextBuffer( compressor, nChunks, &data, _impl->inputSize ))
166 161 : return false;
167 :
168 : _impl->input = _decompress( data, compressor, nChunks,
169 2607382 : _impl->inputSize );
170 : }
171 8225184 : return true;
172 : }
173 :
174 2609784 : const uint8_t* DataIStream::_decompress( const void* data, const uint32_t name,
175 : const uint32_t nChunks,
176 : const uint64_t dataSize )
177 : {
178 2609784 : const uint8_t* src = reinterpret_cast< const uint8_t* >( data );
179 2609784 : if( name == EQ_COMPRESSOR_NONE )
180 2609784 : 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 66 : }
|