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