Line data Source code
1 :
2 : /* Copyright (C) 2013-2014, Stefan.Eilemann@epfl.ch
3 : *
4 : * This file is part of Pression <https://github.com/Eyescale/Pression>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "downloader.h"
21 :
22 : #include "log.h"
23 : #include "plugin.h"
24 : #include "pluginInstance.h"
25 : #include "pluginRegistry.h"
26 : #include "pluginVisitor.h"
27 :
28 : #include <limits>
29 :
30 : namespace pression
31 : {
32 : namespace detail
33 : {
34 : class Downloader : public PluginInstance
35 : {
36 : public:
37 0 : Downloader() {}
38 :
39 0 : Downloader( pression::PluginRegistry& from, const uint32_t name,
40 : const GLEWContext* gl )
41 0 : {
42 0 : LBCHECK( setup( from, name, gl ));
43 0 : }
44 :
45 0 : ~Downloader()
46 0 : {
47 0 : clear();
48 0 : }
49 :
50 0 : void clear()
51 : {
52 0 : if( plugin && instance )
53 0 : plugin->deleteDecompressor( instance );
54 0 : PluginInstance::clear();
55 0 : }
56 :
57 0 : bool setup( pression::PluginRegistry& from, const uint32_t name,
58 : const GLEWContext* gl )
59 : {
60 0 : if( name == info.name )
61 : {
62 0 : LBASSERT( isGood() && instance );
63 0 : return true;
64 : }
65 :
66 0 : clear();
67 :
68 0 : if( name <= EQ_COMPRESSOR_NONE )
69 : {
70 0 : LBASSERT( isGood() && instance );
71 0 : return true;
72 : }
73 :
74 0 : plugin = from.findPlugin( name );
75 0 : LBASSERT( plugin );
76 0 : if( !plugin )
77 : {
78 0 : LBWARN << "Plugin for downloader 0x" << std::hex << name << std::dec
79 0 : << " not found" << std::endl;
80 0 : return false;
81 : }
82 :
83 0 : if( !gl )
84 0 : LBWARN << "Can't verify plugin compatibility, no GLEWContext given"
85 0 : << std::endl;
86 0 : else if( !plugin->isCompatible( name, gl ))
87 : {
88 0 : LBWARN << "Plugin for downloader 0x" << std::hex << name << std::dec
89 0 : << " not compatible with OpenGL implementation" << std::endl;
90 0 : return false;
91 : }
92 :
93 0 : instance = plugin->newDecompressor( name );
94 0 : info = plugin->findInfo( name );
95 0 : LBASSERT( isGood( ));
96 0 : LBASSERT( instance );
97 0 : LBASSERT( info.name == name );
98 0 : LBLOG( LOG_PLUGIN ) << "Instantiated downloader " << info << std::endl;
99 0 : return instance;
100 : }
101 :
102 : };
103 : }
104 :
105 0 : Downloader::Downloader()
106 0 : : impl_( new detail::Downloader )
107 : {
108 0 : LB_TS_THREAD( _thread );
109 0 : }
110 :
111 0 : Downloader::Downloader( PluginRegistry& from, const uint32_t name,
112 0 : const GLEWContext* gl )
113 0 : : impl_( new detail::Downloader( from, name, gl ))
114 : {
115 0 : LB_TS_THREAD( _thread );
116 0 : }
117 :
118 0 : Downloader::~Downloader()
119 : {
120 0 : LBASSERTINFO( impl_->plugin == 0,
121 : "Clear downloader while GL context is still active" );
122 0 : delete impl_;
123 0 : }
124 :
125 0 : bool Downloader::isGood() const
126 : {
127 0 : LB_TS_SCOPED( _thread );
128 0 : return impl_->isGood() && impl_->instance;
129 : }
130 :
131 0 : bool Downloader::uses( const uint32_t name ) const
132 : {
133 0 : return isGood() && impl_->info.name == name;
134 : }
135 :
136 0 : bool Downloader::supports( const uint32_t inputToken, const bool noAlpha,
137 : const uint64_t capabilities ) const
138 : {
139 0 : return isGood() && impl_->info.tokenType == inputToken &&
140 0 : (impl_->info.capabilities & capabilities) == capabilities &&
141 0 : ( noAlpha ||
142 0 : !(impl_->info.capabilities & EQ_COMPRESSOR_IGNORE_ALPHA) );
143 : }
144 :
145 : namespace
146 : {
147 0 : class Finder : public ConstPluginVisitor
148 : {
149 : public:
150 0 : Finder( const uint32_t internalFormat, const float minQuality,
151 : const bool ignoreAlpha, const uint64_t capabilities,
152 : const GLEWContext* gl )
153 0 : : internalFormat_( internalFormat )
154 : , minQuality_( minQuality )
155 : , ignoreAlpha_( ignoreAlpha )
156 : , capabilities_( capabilities )
157 0 : , gl_( gl )
158 : {
159 0 : LBASSERT( gl );
160 0 : current.name = EQ_COMPRESSOR_NONE;
161 0 : current.speed = 0.f;
162 0 : current.ratio = std::numeric_limits< float >::max();
163 0 : }
164 :
165 0 : virtual VisitorResult visit( const Plugin& plugin,
166 : const EqCompressorInfo& info )
167 : {
168 0 : if(( (info.capabilities & capabilities_) == capabilities_ ) &&
169 0 : info.tokenType == internalFormat_ && info.quality >= minQuality_ &&
170 0 : ( ignoreAlpha_ ||
171 0 : !(info.capabilities & EQ_COMPRESSOR_IGNORE_ALPHA) ) &&
172 0 : plugin.isCompatible( info.name, gl_ ) &&
173 0 : ( current.ratio > info.ratio ||
174 0 : ( current.ratio == info.ratio && current.speed < info.speed )))
175 : {
176 0 : LBLOG( LOG_PLUGIN ) << "Pick " << info << std::endl;
177 0 : current = info;
178 : }
179 0 : return TRAVERSE_CONTINUE;
180 : }
181 :
182 : EqCompressorInfo current;
183 :
184 : private:
185 : const uint32_t internalFormat_;
186 : const float minQuality_;
187 : const bool ignoreAlpha_;
188 : const uint64_t capabilities_;
189 : const GLEWContext* gl_;
190 : };
191 : }
192 :
193 0 : uint32_t Downloader::choose( const PluginRegistry& from,
194 : const uint32_t internalFormat,
195 : const float minQuality, const bool ignoreAlpha,
196 : const uint64_t capabilities,
197 : const GLEWContext* gl )
198 : {
199 0 : Finder finder( internalFormat, minQuality, ignoreAlpha, capabilities, gl );
200 0 : from.accept( finder );
201 0 : return finder.current.name;
202 : }
203 :
204 0 : const EqCompressorInfo& Downloader::getInfo() const
205 : {
206 0 : return impl_->info;
207 : }
208 :
209 0 : bool Downloader::setup( PluginRegistry& from, const uint32_t name,
210 : const GLEWContext* gl )
211 : {
212 0 : return impl_->setup( from, name, gl );
213 : }
214 :
215 0 : bool Downloader::setup( PluginRegistry& from,const uint32_t internalFormat,
216 : const float minQuality, const bool ignoreAlpha,
217 : const uint64_t capabilities,const GLEWContext* gl)
218 : {
219 0 : return impl_->setup( from, choose( from, internalFormat, minQuality,
220 0 : ignoreAlpha, capabilities, gl ), gl );
221 : }
222 :
223 0 : void Downloader::clear()
224 : {
225 0 : impl_->clear();
226 0 : }
227 :
228 0 : bool Downloader::start( void** buffer, const uint64_t inDims[4],
229 : const uint64_t flags, uint64_t outDims[4],
230 : const unsigned source, const GLEWContext* gl )
231 : {
232 0 : LBASSERT( gl );
233 0 : if( impl_->info.capabilities & EQ_COMPRESSOR_USE_ASYNC_DOWNLOAD )
234 : {
235 0 : impl_->plugin->startDownload( impl_->instance, impl_->info.name, gl,
236 : inDims, source,
237 0 : flags | EQ_COMPRESSOR_USE_ASYNC_DOWNLOAD);
238 0 : return true;
239 : }
240 :
241 0 : impl_->plugin->download( impl_->instance, impl_->info.name, gl, inDims,
242 0 : source, flags, outDims, buffer );
243 0 : return false;
244 : }
245 :
246 0 : void Downloader::finish( void** buffer, const uint64_t inDims[4],
247 : const uint64_t flags, uint64_t outDims[4],
248 : const GLEWContext* gl )
249 : {
250 0 : LBASSERT( impl_->plugin );
251 0 : LBASSERT( impl_->instance );
252 0 : LBASSERT( gl );
253 0 : if( !impl_->plugin )
254 0 : return;
255 :
256 0 : if( impl_->info.capabilities & EQ_COMPRESSOR_USE_ASYNC_DOWNLOAD )
257 : {
258 0 : impl_->plugin->finishDownload( impl_->instance, impl_->info.name, gl,
259 : inDims,
260 : flags | EQ_COMPRESSOR_USE_ASYNC_DOWNLOAD,
261 0 : outDims, buffer );
262 : }
263 : }
264 :
265 3 : }
|