Line data Source code
1 :
2 : /* Copyright (c) 2009-2010, Cedric Stalder <cedric.stalder@gmail.com>
3 : * 2009-2014, Stefan Eilemann <eile@equalizergraphics.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 "plugin.h"
22 :
23 : #include "compressorInfo.h"
24 : #include "debug.h"
25 : #include "log.h"
26 : #include "os.h"
27 : #include "pluginRegistry.h"
28 : #include "pluginVisitor.h"
29 : #include <cmath>
30 :
31 : namespace lunchbox
32 : {
33 : typedef void ( *GetInfo_t ) ( const size_t, EqCompressorInfo* const );
34 : namespace detail
35 : {
36 2 : class Plugin
37 : {
38 : public:
39 : CompressorInfos infos;
40 : };
41 : }
42 :
43 1 : Plugin::Plugin( const std::string& libraryName )
44 : : DSO( libraryName )
45 : , getNumCompressors( getFunctionPointer< GetNumCompressors_t >(
46 2 : "EqCompressorGetNumCompressors" ))
47 : , newCompressor( getFunctionPointer< NewCompressor_t >(
48 2 : "EqCompressorNewCompressor" ))
49 : , newDecompressor( getFunctionPointer< NewDecompressor_t >(
50 2 : "EqCompressorNewDecompressor" ))
51 : , deleteCompressor( getFunctionPointer< DeleteCompressor_t >(
52 2 : "EqCompressorDeleteCompressor" ))
53 : , deleteDecompressor( getFunctionPointer< DeleteDecompressor_t >(
54 2 : "EqCompressorDeleteDecompressor" ))
55 2 : , compress( getFunctionPointer< Compress_t >( "EqCompressorCompress" ))
56 2 : , decompress( getFunctionPointer< Decompress_t >( "EqCompressorDecompress"))
57 : , getNumResults( getFunctionPointer< GetNumResults_t >(
58 2 : "EqCompressorGetNumResults" ))
59 2 : , getResult( getFunctionPointer< GetResult_t >( "EqCompressorGetResult" ))
60 : , isCompatible( getFunctionPointer< IsCompatible_t >(
61 2 : "EqCompressorIsCompatible" ))
62 2 : , download( getFunctionPointer< Download_t >( "EqCompressorDownload" ))
63 2 : , upload( getFunctionPointer< Upload_t >( "EqCompressorUpload" ))
64 : , startDownload( getFunctionPointer< StartDownload_t >(
65 2 : "EqCompressorStartDownload" ))
66 : , finishDownload( getFunctionPointer< FinishDownload_t >(
67 2 : "EqCompressorFinishDownload" ))
68 16 : , impl_( new detail::Plugin )
69 : {
70 1 : if( !isOpen( ))
71 0 : return;
72 :
73 : const GetInfo_t getInfo =
74 1 : getFunctionPointer< GetInfo_t >( "EqCompressorGetInfo" );
75 :
76 1 : const bool hasBase = newDecompressor && newCompressor && deleteCompressor &&
77 2 : deleteDecompressor && getInfo && getNumCompressors;
78 1 : const bool hasCPU = getResult && getNumResults && decompress && compress;
79 1 : const bool hasGPU = isCompatible && download && upload;
80 1 : if( !hasBase || ( !hasCPU && !hasGPU ))
81 : {
82 0 : LBWARN << "Initializing compression DSO " << libraryName
83 0 : << " failed, at least one entry point missing" << std::endl;
84 0 : return;
85 : }
86 :
87 1 : const size_t nCompressors = getNumCompressors();
88 1 : if( nCompressors == 0 )
89 : {
90 0 : LBWARN << "Initializing compression DSO " << libraryName
91 0 : << " failed, 0 compression engines reported" << std::endl;
92 0 : return;
93 : }
94 :
95 1 : impl_->infos.resize( nCompressors );
96 40 : for( size_t i = 0; i < nCompressors; ++i )
97 : {
98 39 : CompressorInfo& info = impl_->infos[ i ];
99 39 : info.version = EQ_COMPRESSOR_VERSION;
100 39 : info.outputTokenType = EQ_COMPRESSOR_DATATYPE_NONE;
101 39 : info.outputTokenSize = 0;
102 39 : getInfo( i, &info );
103 :
104 39 : if(( info.capabilities & EQ_COMPRESSOR_USE_ASYNC_DOWNLOAD ) &&
105 0 : ( !startDownload || !finishDownload ))
106 : {
107 0 : LBWARN << "Download plugin claims to support async readback " <<
108 0 : "but corresponding functions are missing" << std::endl;
109 0 : impl_->infos.clear();
110 0 : return;
111 : }
112 39 : info.ratingAlpha = powf( info.speed, .3f ) / info.ratio;
113 39 : info.ratingNoAlpha = info.ratingAlpha;
114 :
115 39 : if( info.capabilities & EQ_COMPRESSOR_IGNORE_ALPHA )
116 : {
117 28 : switch( info.tokenType )
118 : {
119 : case EQ_COMPRESSOR_DATATYPE_4_BYTE:
120 : case EQ_COMPRESSOR_DATATYPE_4_HALF_FLOAT:
121 : case EQ_COMPRESSOR_DATATYPE_4_FLOAT:
122 9 : info.ratingNoAlpha /= .75f;
123 9 : break;
124 :
125 : case EQ_COMPRESSOR_DATATYPE_RGB10_A2:
126 1 : info.ratingNoAlpha /= .9375f; // 30/32
127 1 : break;
128 :
129 : default:
130 18 : break;
131 : }
132 : }
133 :
134 39 : if( !( info.capabilities & EQ_COMPRESSOR_TRANSFER ))
135 : {
136 39 : if( info.outputTokenType == EQ_COMPRESSOR_DATATYPE_NONE )
137 : {
138 : // Set up CPU compressor output to be input type
139 33 : info.outputTokenType = info.tokenType;
140 33 : LBASSERT( info.outputTokenSize == 0 );
141 : }
142 : else
143 : {
144 6 : LBASSERT( info.outputTokenSize != 0 );
145 : }
146 : }
147 : #ifndef NDEBUG // Check that each compressor exist once
148 780 : for( size_t j = 0; j < i; ++j )
149 : {
150 741 : LBASSERTINFO( info.name != impl_->infos[j].name,
151 : "Compressors " << i << " and " << j << " in '" <<
152 : libraryName << "' use the same name" );
153 : }
154 : #endif
155 : }
156 :
157 3 : LBINFO << "Loaded " << nCompressors << " plugins from " << libraryName
158 3 : << std::endl;
159 : }
160 :
161 3 : Plugin::~Plugin()
162 : {
163 1 : delete impl_;
164 2 : }
165 :
166 1 : bool Plugin::isGood() const
167 : {
168 1 : return !impl_->infos.empty();
169 : }
170 :
171 304 : VisitorResult Plugin::accept( PluginVisitor& visitor )
172 : {
173 304 : switch( visitor.visit( *this ))
174 : {
175 : case TRAVERSE_TERMINATE:
176 0 : return TRAVERSE_TERMINATE;
177 : case TRAVERSE_PRUNE:
178 0 : return TRAVERSE_PRUNE;
179 : case TRAVERSE_CONTINUE:
180 304 : break;
181 : }
182 :
183 304 : VisitorResult result = TRAVERSE_CONTINUE;
184 12312 : for( CompressorInfosIter i = impl_->infos.begin();
185 8208 : i != impl_->infos.end(); ++i )
186 : {
187 4104 : switch( visitor.visit( *this, *i ))
188 : {
189 : case TRAVERSE_TERMINATE:
190 304 : return TRAVERSE_TERMINATE;
191 : case TRAVERSE_PRUNE:
192 0 : result = TRAVERSE_PRUNE;
193 : case TRAVERSE_CONTINUE:
194 3800 : break;
195 : }
196 : }
197 0 : return result;
198 : }
199 :
200 0 : VisitorResult Plugin::accept( ConstPluginVisitor& visitor ) const
201 : {
202 0 : switch( visitor.visit( *this ))
203 : {
204 : case TRAVERSE_TERMINATE:
205 0 : return TRAVERSE_TERMINATE;
206 : case TRAVERSE_PRUNE:
207 0 : return TRAVERSE_PRUNE;
208 : case TRAVERSE_CONTINUE:
209 0 : break;
210 : }
211 :
212 0 : VisitorResult result = TRAVERSE_CONTINUE;
213 0 : for( CompressorInfosIter i = impl_->infos.begin();
214 0 : i != impl_->infos.end(); ++i )
215 : {
216 0 : switch( visitor.visit( *this, *i ))
217 : {
218 : case TRAVERSE_TERMINATE:
219 0 : return TRAVERSE_TERMINATE;
220 : case TRAVERSE_PRUNE:
221 0 : result = TRAVERSE_PRUNE;
222 : case TRAVERSE_CONTINUE:
223 0 : break;
224 : }
225 : }
226 0 : return result;
227 : }
228 :
229 0 : bool Plugin::implementsType( const uint32_t name ) const
230 : {
231 0 : for( CompressorInfos::const_iterator i = impl_->infos.begin();
232 0 : i != impl_->infos.end(); ++i )
233 : {
234 0 : if ( i->name == name )
235 0 : return true;
236 : }
237 :
238 0 : return false;
239 : }
240 :
241 304 : EqCompressorInfo Plugin::findInfo( const uint32_t name ) const
242 : {
243 12312 : for( CompressorInfos::const_iterator i = impl_->infos.begin();
244 8208 : i != impl_->infos.end(); ++i )
245 : {
246 4104 : if( i->name == name )
247 304 : return (*i);
248 : }
249 :
250 0 : LBUNREACHABLE;
251 : EqCompressorInfo info;
252 0 : setZero( &info, sizeof( info ));
253 0 : return info;
254 : }
255 :
256 3 : const CompressorInfos& Plugin::getInfos() const
257 : {
258 3 : return impl_->infos;
259 : }
260 90 : }
|