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