Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/gpu/shader_disk_cache.h" | 5 #include "content/browser/gpu/shader_disk_cache.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/memory/ptr_util.h" | |
| 8 #include "base/threading/thread_checker.h" | 9 #include "base/threading/thread_checker.h" |
| 9 #include "content/public/browser/browser_thread.h" | |
| 10 #include "gpu/command_buffer/common/constants.h" | 10 #include "gpu/command_buffer/common/constants.h" |
| 11 #include "net/base/cache_type.h" | 11 #include "net/base/cache_type.h" |
| 12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
| 13 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
| 14 | 14 |
| 15 namespace content { | 15 namespace content { |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 static const base::FilePath::CharType kGpuCachePath[] = | 19 static const base::FilePath::CharType kGpuCachePath[] = |
| 20 FILE_PATH_LITERAL("GPUCache"); | 20 FILE_PATH_LITERAL("GPUCache"); |
| 21 | 21 |
| 22 void EntryCloser(disk_cache::Entry* entry) { | 22 static ShaderCacheFactory* factory_instance = nullptr; |
| 23 entry->Close(); | |
| 24 } | |
| 25 | |
| 26 void FreeDiskCacheIterator( | |
| 27 std::unique_ptr<disk_cache::Backend::Iterator> iterator) {} | |
| 28 | 23 |
| 29 } // namespace | 24 } // namespace |
| 30 | 25 |
| 31 // ShaderDiskCacheEntry handles the work of caching/updating the cached | 26 // ShaderDiskCacheEntry handles the work of caching/updating the cached |
| 32 // shaders. | 27 // shaders. |
| 33 class ShaderDiskCacheEntry | 28 class ShaderDiskCacheEntry : public base::ThreadChecker { |
| 34 : public base::ThreadChecker, | |
| 35 public base::RefCounted<ShaderDiskCacheEntry> { | |
| 36 public: | 29 public: |
| 37 ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache, | 30 ShaderDiskCacheEntry(ShaderDiskCache* cache, |
| 38 const std::string& key, | 31 const std::string& key, |
| 39 const std::string& shader); | 32 const std::string& shader); |
| 33 ~ShaderDiskCacheEntry(); | |
| 34 | |
| 40 void Cache(); | 35 void Cache(); |
| 41 | 36 |
| 42 private: | 37 private: |
| 43 friend class base::RefCounted<ShaderDiskCacheEntry>; | |
| 44 | |
| 45 enum OpType { | 38 enum OpType { |
| 46 TERMINATE, | |
| 47 OPEN_ENTRY, | 39 OPEN_ENTRY, |
| 48 WRITE_DATA, | 40 WRITE_DATA, |
| 49 CREATE_ENTRY, | 41 CREATE_ENTRY, |
| 50 }; | 42 }; |
| 51 | 43 |
| 52 ~ShaderDiskCacheEntry(); | |
| 53 | |
| 54 void OnOpComplete(int rv); | 44 void OnOpComplete(int rv); |
| 55 | 45 |
| 56 int OpenCallback(int rv); | 46 int OpenCallback(int rv); |
| 57 int WriteCallback(int rv); | 47 int WriteCallback(int rv); |
| 58 int IOComplete(int rv); | 48 int IOComplete(int rv); |
| 59 | 49 |
| 60 base::WeakPtr<ShaderDiskCache> cache_; | 50 ShaderDiskCache* cache_; |
| 61 OpType op_type_; | 51 OpType op_type_; |
| 62 std::string key_; | 52 std::string key_; |
| 63 std::string shader_; | 53 std::string shader_; |
| 64 disk_cache::Entry* entry_; | 54 disk_cache::Entry* entry_; |
| 55 base::WeakPtrFactory<ShaderDiskCacheEntry> weak_ptr_factory_; | |
| 65 | 56 |
| 66 DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheEntry); | 57 DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheEntry); |
| 67 }; | 58 }; |
| 68 | 59 |
| 69 // ShaderDiskReadHelper is used to load all of the cached shaders from the | 60 // ShaderDiskReadHelper is used to load all of the cached shaders from the |
| 70 // disk cache and send to the memory cache. | 61 // disk cache and send to the memory cache. |
| 71 class ShaderDiskReadHelper | 62 class ShaderDiskReadHelper : public base::ThreadChecker { |
| 72 : public base::ThreadChecker, | |
| 73 public base::RefCounted<ShaderDiskReadHelper> { | |
| 74 public: | 63 public: |
| 75 using ShaderLoadedCallback = ShaderDiskCache::ShaderLoadedCallback; | 64 using ShaderLoadedCallback = ShaderDiskCache::ShaderLoadedCallback; |
| 76 ShaderDiskReadHelper(base::WeakPtr<ShaderDiskCache> cache, | 65 ShaderDiskReadHelper(ShaderDiskCache* cache, |
| 77 const ShaderLoadedCallback& callback); | 66 const ShaderLoadedCallback& callback); |
| 67 ~ShaderDiskReadHelper(); | |
| 68 | |
| 78 void LoadCache(); | 69 void LoadCache(); |
| 79 | 70 |
| 80 private: | 71 private: |
| 81 friend class base::RefCounted<ShaderDiskReadHelper>; | |
| 82 | |
| 83 enum OpType { | 72 enum OpType { |
| 84 TERMINATE, | 73 TERMINATE, |
| 85 OPEN_NEXT, | 74 OPEN_NEXT, |
| 86 OPEN_NEXT_COMPLETE, | 75 OPEN_NEXT_COMPLETE, |
| 87 READ_COMPLETE, | 76 READ_COMPLETE, |
| 88 ITERATION_FINISHED | 77 ITERATION_FINISHED |
| 89 }; | 78 }; |
| 90 | 79 |
| 91 | 80 |
| 92 ~ShaderDiskReadHelper(); | |
| 93 | |
| 94 void OnOpComplete(int rv); | 81 void OnOpComplete(int rv); |
| 95 | 82 |
| 96 int OpenNextEntry(); | 83 int OpenNextEntry(); |
| 97 int OpenNextEntryComplete(int rv); | 84 int OpenNextEntryComplete(int rv); |
| 98 int ReadComplete(int rv); | 85 int ReadComplete(int rv); |
| 99 int IterationComplete(int rv); | 86 int IterationComplete(int rv); |
| 100 | 87 |
| 101 base::WeakPtr<ShaderDiskCache> cache_; | 88 ShaderDiskCache* cache_; |
| 102 ShaderLoadedCallback shader_loaded_callback_; | 89 ShaderLoadedCallback shader_loaded_callback_; |
| 103 OpType op_type_; | 90 OpType op_type_; |
| 104 std::unique_ptr<disk_cache::Backend::Iterator> iter_; | 91 std::unique_ptr<disk_cache::Backend::Iterator> iter_; |
| 105 scoped_refptr<net::IOBufferWithSize> buf_; | 92 scoped_refptr<net::IOBufferWithSize> buf_; |
| 106 disk_cache::Entry* entry_; | 93 disk_cache::Entry* entry_; |
| 94 base::WeakPtrFactory<ShaderDiskReadHelper> weak_ptr_factory_; | |
| 107 | 95 |
| 108 DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper); | 96 DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper); |
| 109 }; | 97 }; |
| 110 | 98 |
| 111 class ShaderClearHelper | 99 class ShaderClearHelper : public base::RefCounted<ShaderClearHelper>, |
| 112 : public base::RefCounted<ShaderClearHelper>, | 100 public base::SupportsWeakPtr<ShaderClearHelper>, |
| 113 public base::SupportsWeakPtr<ShaderClearHelper> { | 101 public base::ThreadChecker { |
| 114 public: | 102 public: |
| 115 ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache, | 103 ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache, |
| 116 const base::FilePath& path, | 104 const base::FilePath& path, |
| 117 const base::Time& delete_begin, | 105 const base::Time& delete_begin, |
| 118 const base::Time& delete_end, | 106 const base::Time& delete_end, |
| 119 const base::Closure& callback); | 107 const base::Closure& callback); |
| 120 void Clear(); | 108 void Clear(); |
| 121 | 109 |
| 122 private: | 110 private: |
| 123 friend class base::RefCounted<ShaderClearHelper>; | 111 friend class base::RefCounted<ShaderClearHelper>; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 135 scoped_refptr<ShaderDiskCache> cache_; | 123 scoped_refptr<ShaderDiskCache> cache_; |
| 136 OpType op_type_; | 124 OpType op_type_; |
| 137 base::FilePath path_; | 125 base::FilePath path_; |
| 138 base::Time delete_begin_; | 126 base::Time delete_begin_; |
| 139 base::Time delete_end_; | 127 base::Time delete_end_; |
| 140 base::Closure callback_; | 128 base::Closure callback_; |
| 141 | 129 |
| 142 DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper); | 130 DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper); |
| 143 }; | 131 }; |
| 144 | 132 |
| 145 ShaderDiskCacheEntry::ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache, | 133 //////////////////////////////////////////////////////////////////////////////// |
| 134 // ShaderDiskCacheEntry | |
| 135 | |
| 136 ShaderDiskCacheEntry::ShaderDiskCacheEntry(ShaderDiskCache* cache, | |
| 146 const std::string& key, | 137 const std::string& key, |
| 147 const std::string& shader) | 138 const std::string& shader) |
| 148 : cache_(cache), | 139 : cache_(cache), |
| 149 op_type_(OPEN_ENTRY), | 140 op_type_(OPEN_ENTRY), |
| 150 key_(key), | 141 key_(key), |
| 151 shader_(shader), | 142 shader_(shader), |
| 152 entry_(NULL) { | 143 entry_(nullptr), |
| 153 } | 144 weak_ptr_factory_(this) {} |
| 154 | 145 |
| 155 ShaderDiskCacheEntry::~ShaderDiskCacheEntry() { | 146 ShaderDiskCacheEntry::~ShaderDiskCacheEntry() { |
| 147 DCHECK(CalledOnValidThread()); | |
| 156 if (entry_) | 148 if (entry_) |
| 157 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 149 entry_->Close(); |
| 158 base::Bind(&EntryCloser, entry_)); | |
| 159 } | 150 } |
| 160 | 151 |
| 161 void ShaderDiskCacheEntry::Cache() { | 152 void ShaderDiskCacheEntry::Cache() { |
| 162 DCHECK(CalledOnValidThread()); | 153 DCHECK(CalledOnValidThread()); |
| 163 if (!cache_.get()) | |
| 164 return; | |
| 165 | |
| 166 int rv = cache_->backend()->OpenEntry( | 154 int rv = cache_->backend()->OpenEntry( |
| 167 key_, | 155 key_, &entry_, base::Bind(&ShaderDiskCacheEntry::OnOpComplete, |
| 168 &entry_, | 156 weak_ptr_factory_.GetWeakPtr())); |
| 169 base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this)); | |
| 170 if (rv != net::ERR_IO_PENDING) | 157 if (rv != net::ERR_IO_PENDING) |
| 171 OnOpComplete(rv); | 158 OnOpComplete(rv); |
| 172 } | 159 } |
| 173 | 160 |
| 174 void ShaderDiskCacheEntry::OnOpComplete(int rv) { | 161 void ShaderDiskCacheEntry::OnOpComplete(int rv) { |
| 175 DCHECK(CalledOnValidThread()); | 162 DCHECK(CalledOnValidThread()); |
| 176 if (!cache_.get()) | |
| 177 return; | |
| 178 | |
| 179 do { | 163 do { |
| 180 switch (op_type_) { | 164 switch (op_type_) { |
| 181 case OPEN_ENTRY: | 165 case OPEN_ENTRY: |
| 182 rv = OpenCallback(rv); | 166 rv = OpenCallback(rv); |
| 183 break; | 167 break; |
| 184 case CREATE_ENTRY: | 168 case CREATE_ENTRY: |
| 185 rv = WriteCallback(rv); | 169 rv = WriteCallback(rv); |
| 186 break; | 170 break; |
| 187 case WRITE_DATA: | 171 case WRITE_DATA: |
| 188 rv = IOComplete(rv); | 172 rv = IOComplete(rv); |
| 189 break; | 173 break; |
| 190 case TERMINATE: | |
| 191 rv = net::ERR_IO_PENDING; // break the loop. | |
| 192 break; | |
| 193 default: | |
| 194 NOTREACHED(); // Invalid op_type_ provided. | |
| 195 break; | |
| 196 } | 174 } |
| 197 } while (rv != net::ERR_IO_PENDING); | 175 } while (rv != net::ERR_IO_PENDING); |
| 198 } | 176 } |
| 199 | 177 |
| 200 int ShaderDiskCacheEntry::OpenCallback(int rv) { | 178 int ShaderDiskCacheEntry::OpenCallback(int rv) { |
| 201 DCHECK(CalledOnValidThread()); | 179 DCHECK(CalledOnValidThread()); |
| 202 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 203 if (rv == net::OK) { | 180 if (rv == net::OK) { |
| 204 cache_->backend()->OnExternalCacheHit(key_); | 181 cache_->backend()->OnExternalCacheHit(key_); |
| 205 cache_->EntryComplete(this); | 182 cache_->EntryComplete(this); |
| 206 op_type_ = TERMINATE; | 183 return net::ERR_IO_PENDING; |
|
piman
2016/11/02 18:11:15
I'm not a huge fan of this transformation, because
sadrul
2016/11/02 19:24:53
I have reverted this part of the code. Instead of
| |
| 207 return rv; | |
| 208 } | 184 } |
| 209 | 185 |
| 210 op_type_ = CREATE_ENTRY; | 186 op_type_ = CREATE_ENTRY; |
| 211 return cache_->backend()->CreateEntry( | 187 return cache_->backend()->CreateEntry( |
| 212 key_, | 188 key_, &entry_, base::Bind(&ShaderDiskCacheEntry::OnOpComplete, |
| 213 &entry_, | 189 weak_ptr_factory_.GetWeakPtr())); |
| 214 base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this)); | |
| 215 } | 190 } |
| 216 | 191 |
| 217 int ShaderDiskCacheEntry::WriteCallback(int rv) { | 192 int ShaderDiskCacheEntry::WriteCallback(int rv) { |
| 218 DCHECK(CalledOnValidThread()); | 193 DCHECK(CalledOnValidThread()); |
| 219 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 220 if (rv != net::OK) { | 194 if (rv != net::OK) { |
| 221 LOG(ERROR) << "Failed to create shader cache entry: " << rv; | 195 LOG(ERROR) << "Failed to create shader cache entry: " << rv; |
| 222 cache_->EntryComplete(this); | 196 cache_->EntryComplete(this); |
| 223 op_type_ = TERMINATE; | 197 return net::ERR_IO_PENDING; |
| 224 return rv; | |
| 225 } | 198 } |
| 226 | 199 |
| 227 op_type_ = WRITE_DATA; | 200 op_type_ = WRITE_DATA; |
| 228 scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(shader_); | 201 scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(shader_); |
| 229 return entry_->WriteData( | 202 return entry_->WriteData(1, 0, io_buf.get(), shader_.length(), |
| 230 1, | 203 base::Bind(&ShaderDiskCacheEntry::OnOpComplete, |
| 231 0, | 204 weak_ptr_factory_.GetWeakPtr()), |
| 232 io_buf.get(), | 205 false); |
| 233 shader_.length(), | |
| 234 base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this), | |
| 235 false); | |
| 236 } | 206 } |
| 237 | 207 |
| 238 int ShaderDiskCacheEntry::IOComplete(int rv) { | 208 int ShaderDiskCacheEntry::IOComplete(int rv) { |
| 239 DCHECK(CalledOnValidThread()); | 209 DCHECK(CalledOnValidThread()); |
| 240 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 241 cache_->EntryComplete(this); | 210 cache_->EntryComplete(this); |
| 242 op_type_ = TERMINATE; | 211 return net::ERR_IO_PENDING; |
| 243 return rv; | |
| 244 } | 212 } |
| 245 | 213 |
| 246 ShaderDiskReadHelper::ShaderDiskReadHelper(base::WeakPtr<ShaderDiskCache> cache, | 214 //////////////////////////////////////////////////////////////////////////////// |
| 215 // ShaderDiskReadHelper | |
| 216 | |
| 217 ShaderDiskReadHelper::ShaderDiskReadHelper(ShaderDiskCache* cache, | |
| 247 const ShaderLoadedCallback& callback) | 218 const ShaderLoadedCallback& callback) |
| 248 : cache_(cache), | 219 : cache_(cache), |
| 249 shader_loaded_callback_(callback), | 220 shader_loaded_callback_(callback), |
| 250 op_type_(OPEN_NEXT), | 221 op_type_(OPEN_NEXT), |
| 251 buf_(NULL), | 222 buf_(NULL), |
| 252 entry_(NULL) {} | 223 entry_(NULL), |
| 224 weak_ptr_factory_(this) {} | |
| 225 | |
| 226 ShaderDiskReadHelper::~ShaderDiskReadHelper() { | |
| 227 DCHECK(CalledOnValidThread()); | |
| 228 if (entry_) | |
| 229 entry_->Close(); | |
| 230 iter_ = nullptr; | |
| 231 } | |
| 253 | 232 |
| 254 void ShaderDiskReadHelper::LoadCache() { | 233 void ShaderDiskReadHelper::LoadCache() { |
| 255 DCHECK(CalledOnValidThread()); | 234 DCHECK(CalledOnValidThread()); |
| 256 if (!cache_.get()) | |
| 257 return; | |
| 258 OnOpComplete(net::OK); | 235 OnOpComplete(net::OK); |
| 259 } | 236 } |
| 260 | 237 |
| 261 void ShaderDiskReadHelper::OnOpComplete(int rv) { | 238 void ShaderDiskReadHelper::OnOpComplete(int rv) { |
| 262 DCHECK(CalledOnValidThread()); | 239 DCHECK(CalledOnValidThread()); |
| 263 if (!cache_.get()) | |
| 264 return; | |
| 265 | |
| 266 do { | 240 do { |
| 267 switch (op_type_) { | 241 switch (op_type_) { |
| 268 case OPEN_NEXT: | 242 case OPEN_NEXT: |
| 269 rv = OpenNextEntry(); | 243 rv = OpenNextEntry(); |
| 270 break; | 244 break; |
| 271 case OPEN_NEXT_COMPLETE: | 245 case OPEN_NEXT_COMPLETE: |
| 272 rv = OpenNextEntryComplete(rv); | 246 rv = OpenNextEntryComplete(rv); |
| 273 break; | 247 break; |
| 274 case READ_COMPLETE: | 248 case READ_COMPLETE: |
| 275 rv = ReadComplete(rv); | 249 rv = ReadComplete(rv); |
| 276 break; | 250 break; |
| 277 case ITERATION_FINISHED: | 251 case ITERATION_FINISHED: |
| 278 rv = IterationComplete(rv); | 252 rv = IterationComplete(rv); |
| 279 break; | 253 break; |
| 280 case TERMINATE: | 254 case TERMINATE: |
| 281 cache_->ReadComplete(); | 255 cache_->ReadComplete(); |
| 282 rv = net::ERR_IO_PENDING; // break the loop | 256 rv = net::ERR_IO_PENDING; // break the loop |
| 283 break; | 257 break; |
| 284 default: | 258 default: |
| 285 NOTREACHED(); // Invalid state for read helper | 259 NOTREACHED(); // Invalid state for read helper |
| 286 rv = net::ERR_FAILED; | 260 rv = net::ERR_FAILED; |
| 287 break; | 261 break; |
| 288 } | 262 } |
| 289 } while (rv != net::ERR_IO_PENDING); | 263 } while (rv != net::ERR_IO_PENDING); |
| 290 } | 264 } |
| 291 | 265 |
| 292 int ShaderDiskReadHelper::OpenNextEntry() { | 266 int ShaderDiskReadHelper::OpenNextEntry() { |
| 293 DCHECK(CalledOnValidThread()); | 267 DCHECK(CalledOnValidThread()); |
| 294 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 295 op_type_ = OPEN_NEXT_COMPLETE; | 268 op_type_ = OPEN_NEXT_COMPLETE; |
| 296 if (!iter_) | 269 if (!iter_) |
| 297 iter_ = cache_->backend()->CreateIterator(); | 270 iter_ = cache_->backend()->CreateIterator(); |
| 298 return iter_->OpenNextEntry( | 271 return iter_->OpenNextEntry(&entry_, |
| 299 &entry_, base::Bind(&ShaderDiskReadHelper::OnOpComplete, this)); | 272 base::Bind(&ShaderDiskReadHelper::OnOpComplete, |
| 273 weak_ptr_factory_.GetWeakPtr())); | |
| 300 } | 274 } |
| 301 | 275 |
| 302 int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) { | 276 int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) { |
| 303 DCHECK(CalledOnValidThread()); | 277 DCHECK(CalledOnValidThread()); |
| 304 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 305 if (rv == net::ERR_FAILED) { | 278 if (rv == net::ERR_FAILED) { |
| 306 iter_.reset(); | 279 iter_.reset(); |
| 307 op_type_ = ITERATION_FINISHED; | 280 op_type_ = ITERATION_FINISHED; |
| 308 return net::OK; | 281 return net::OK; |
| 309 } | 282 } |
| 310 | 283 |
| 311 if (rv < 0) | 284 if (rv < 0) |
| 312 return rv; | 285 return rv; |
| 313 | 286 |
| 314 op_type_ = READ_COMPLETE; | 287 op_type_ = READ_COMPLETE; |
| 315 buf_ = new net::IOBufferWithSize(entry_->GetDataSize(1)); | 288 buf_ = new net::IOBufferWithSize(entry_->GetDataSize(1)); |
| 316 return entry_->ReadData( | 289 return entry_->ReadData(1, 0, buf_.get(), buf_->size(), |
| 317 1, | 290 base::Bind(&ShaderDiskReadHelper::OnOpComplete, |
| 318 0, | 291 weak_ptr_factory_.GetWeakPtr())); |
| 319 buf_.get(), | |
| 320 buf_->size(), | |
| 321 base::Bind(&ShaderDiskReadHelper::OnOpComplete, this)); | |
| 322 } | 292 } |
| 323 | 293 |
| 324 int ShaderDiskReadHelper::ReadComplete(int rv) { | 294 int ShaderDiskReadHelper::ReadComplete(int rv) { |
| 325 DCHECK(CalledOnValidThread()); | 295 DCHECK(CalledOnValidThread()); |
| 326 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 327 if (rv && rv == buf_->size() && !shader_loaded_callback_.is_null()) { | 296 if (rv && rv == buf_->size() && !shader_loaded_callback_.is_null()) { |
| 328 shader_loaded_callback_.Run(entry_->GetKey(), | 297 shader_loaded_callback_.Run(entry_->GetKey(), |
| 329 std::string(buf_->data(), buf_->size())); | 298 std::string(buf_->data(), buf_->size())); |
| 330 } | 299 } |
| 331 | 300 |
| 332 buf_ = NULL; | 301 buf_ = NULL; |
| 333 entry_->Close(); | 302 entry_->Close(); |
| 334 entry_ = NULL; | 303 entry_ = NULL; |
| 335 | 304 |
| 336 op_type_ = OPEN_NEXT; | 305 op_type_ = OPEN_NEXT; |
| 337 return net::OK; | 306 return net::OK; |
| 338 } | 307 } |
| 339 | 308 |
| 340 int ShaderDiskReadHelper::IterationComplete(int rv) { | 309 int ShaderDiskReadHelper::IterationComplete(int rv) { |
| 341 DCHECK(CalledOnValidThread()); | 310 DCHECK(CalledOnValidThread()); |
| 342 // Called through OnOpComplete, so we know |cache_| is valid. | |
| 343 iter_.reset(); | 311 iter_.reset(); |
| 344 op_type_ = TERMINATE; | 312 op_type_ = TERMINATE; |
| 345 return net::OK; | 313 return net::OK; |
| 346 } | 314 } |
| 347 | 315 |
| 348 ShaderDiskReadHelper::~ShaderDiskReadHelper() { | 316 //////////////////////////////////////////////////////////////////////////////// |
| 349 if (entry_) { | 317 // ShaderClearHelper |
| 350 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 351 base::Bind(&EntryCloser, entry_)); | |
| 352 } | |
| 353 if (iter_) { | |
| 354 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 355 base::Bind(&FreeDiskCacheIterator, | |
| 356 base::Passed(&iter_))); | |
| 357 } | |
| 358 } | |
| 359 | 318 |
| 360 ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache, | 319 ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache, |
| 361 const base::FilePath& path, | 320 const base::FilePath& path, |
| 362 const base::Time& delete_begin, | 321 const base::Time& delete_begin, |
| 363 const base::Time& delete_end, | 322 const base::Time& delete_end, |
| 364 const base::Closure& callback) | 323 const base::Closure& callback) |
| 365 : cache_(cache), | 324 : cache_(cache), |
| 366 op_type_(VERIFY_CACHE_SETUP), | 325 op_type_(VERIFY_CACHE_SETUP), |
| 367 path_(path), | 326 path_(path), |
| 368 delete_begin_(delete_begin), | 327 delete_begin_(delete_begin), |
| 369 delete_end_(delete_end), | 328 delete_end_(delete_end), |
| 370 callback_(callback) { | 329 callback_(callback) { |
| 371 } | 330 } |
| 372 | 331 |
| 373 ShaderClearHelper::~ShaderClearHelper() { | 332 ShaderClearHelper::~ShaderClearHelper() { |
| 374 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 333 DCHECK(CalledOnValidThread()); |
| 375 } | 334 } |
| 376 | 335 |
| 377 void ShaderClearHelper::Clear() { | 336 void ShaderClearHelper::Clear() { |
| 378 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 337 DCHECK(CalledOnValidThread()); |
| 379 DoClearShaderCache(net::OK); | 338 DoClearShaderCache(net::OK); |
| 380 } | 339 } |
| 381 | 340 |
| 382 void ShaderClearHelper::DoClearShaderCache(int rv) { | 341 void ShaderClearHelper::DoClearShaderCache(int rv) { |
| 383 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 342 DCHECK(CalledOnValidThread()); |
| 384 | 343 |
| 385 // Hold a ref to ourselves so when we do the CacheCleared call we don't get | 344 // Hold a ref to ourselves so when we do the CacheCleared call we don't get |
| 386 // auto-deleted when our ref count drops to zero. | 345 // auto-deleted when our ref count drops to zero. |
| 387 scoped_refptr<ShaderClearHelper> helper = this; | 346 scoped_refptr<ShaderClearHelper> helper = this; |
| 388 | 347 |
| 389 while (rv != net::ERR_IO_PENDING) { | 348 while (rv != net::ERR_IO_PENDING) { |
| 390 switch (op_type_) { | 349 switch (op_type_) { |
| 391 case VERIFY_CACHE_SETUP: | 350 case VERIFY_CACHE_SETUP: |
| 392 rv = cache_->SetAvailableCallback( | 351 rv = cache_->SetAvailableCallback( |
| 393 base::Bind(&ShaderClearHelper::DoClearShaderCache, AsWeakPtr())); | 352 base::Bind(&ShaderClearHelper::DoClearShaderCache, AsWeakPtr())); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 405 rv = net::ERR_IO_PENDING; // Break the loop. | 364 rv = net::ERR_IO_PENDING; // Break the loop. |
| 406 break; | 365 break; |
| 407 default: | 366 default: |
| 408 NOTREACHED(); // Invalid state provided. | 367 NOTREACHED(); // Invalid state provided. |
| 409 op_type_ = TERMINATE; | 368 op_type_ = TERMINATE; |
| 410 break; | 369 break; |
| 411 } | 370 } |
| 412 } | 371 } |
| 413 } | 372 } |
| 414 | 373 |
| 374 //////////////////////////////////////////////////////////////////////////////// | |
| 375 // ShaderCacheFactory | |
| 376 | |
| 377 // static | |
| 378 void ShaderCacheFactory::InitInstance( | |
| 379 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 380 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) { | |
| 381 if (task_runner->BelongsToCurrentThread()) { | |
| 382 CreateFactoryInstance(std::move(cache_task_runner)); | |
| 383 } else { | |
| 384 task_runner->PostTask(FROM_HERE, | |
| 385 base::Bind(&ShaderCacheFactory::CreateFactoryInstance, | |
| 386 std::move(cache_task_runner))); | |
| 387 } | |
| 388 } | |
| 389 | |
| 415 // static | 390 // static |
| 416 ShaderCacheFactory* ShaderCacheFactory::GetInstance() { | 391 ShaderCacheFactory* ShaderCacheFactory::GetInstance() { |
| 417 return base::Singleton<ShaderCacheFactory, | 392 factory_instance = |
| 418 base::LeakySingletonTraits<ShaderCacheFactory>>::get(); | 393 base::Singleton<ShaderCacheFactory, |
| 394 base::LeakySingletonTraits<ShaderCacheFactory>>::get(); | |
|
piman
2016/11/02 18:11:15
Can we instantiate the singleton in CreateFactoryI
sadrul
2016/11/02 19:24:53
Done.
sadrul
2016/11/02 20:36:39
This change ended up catching a few places that ca
piman
2016/11/02 20:56:17
I'm ok with returning null from GetInstance() if i
sadrul
2016/11/03 03:57:51
Done.
| |
| 395 DCHECK(factory_instance->CalledOnValidThread()); | |
| 396 return factory_instance; | |
| 419 } | 397 } |
| 420 | 398 |
| 421 ShaderCacheFactory::ShaderCacheFactory() { | 399 ShaderCacheFactory::ShaderCacheFactory() { |
| 422 } | 400 } |
| 423 | 401 |
| 424 ShaderCacheFactory::~ShaderCacheFactory() { | 402 ShaderCacheFactory::~ShaderCacheFactory() { |
| 425 } | 403 } |
| 426 | 404 |
| 405 // static | |
| 406 void ShaderCacheFactory::CreateFactoryInstance( | |
| 407 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) { | |
| 408 DCHECK(!factory_instance); | |
| 409 GetInstance()->cache_task_runner_ = std::move(cache_task_runner); | |
| 410 } | |
| 411 | |
| 427 void ShaderCacheFactory::SetCacheInfo(int32_t client_id, | 412 void ShaderCacheFactory::SetCacheInfo(int32_t client_id, |
| 428 const base::FilePath& path) { | 413 const base::FilePath& path) { |
| 414 DCHECK(CalledOnValidThread()); | |
| 429 client_id_to_path_map_[client_id] = path; | 415 client_id_to_path_map_[client_id] = path; |
| 430 } | 416 } |
| 431 | 417 |
| 432 void ShaderCacheFactory::RemoveCacheInfo(int32_t client_id) { | 418 void ShaderCacheFactory::RemoveCacheInfo(int32_t client_id) { |
| 419 DCHECK(CalledOnValidThread()); | |
| 433 client_id_to_path_map_.erase(client_id); | 420 client_id_to_path_map_.erase(client_id); |
| 434 } | 421 } |
| 435 | 422 |
| 436 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32_t client_id) { | 423 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32_t client_id) { |
| 424 DCHECK(CalledOnValidThread()); | |
| 437 ClientIdToPathMap::iterator iter = | 425 ClientIdToPathMap::iterator iter = |
| 438 client_id_to_path_map_.find(client_id); | 426 client_id_to_path_map_.find(client_id); |
| 439 if (iter == client_id_to_path_map_.end()) | 427 if (iter == client_id_to_path_map_.end()) |
| 440 return NULL; | 428 return NULL; |
| 441 return ShaderCacheFactory::GetByPath(iter->second); | 429 return ShaderCacheFactory::GetByPath(iter->second); |
| 442 } | 430 } |
| 443 | 431 |
| 444 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::GetByPath( | 432 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::GetByPath( |
| 445 const base::FilePath& path) { | 433 const base::FilePath& path) { |
| 434 DCHECK(CalledOnValidThread()); | |
| 446 ShaderCacheMap::iterator iter = shader_cache_map_.find(path); | 435 ShaderCacheMap::iterator iter = shader_cache_map_.find(path); |
| 447 if (iter != shader_cache_map_.end()) | 436 if (iter != shader_cache_map_.end()) |
| 448 return iter->second; | 437 return iter->second; |
| 449 | 438 |
| 450 ShaderDiskCache* cache = new ShaderDiskCache(path); | 439 ShaderDiskCache* cache = new ShaderDiskCache(path); |
| 451 cache->Init(); | 440 cache->Init(cache_task_runner_); |
| 452 return cache; | 441 return cache; |
| 453 } | 442 } |
| 454 | 443 |
| 455 void ShaderCacheFactory::AddToCache(const base::FilePath& key, | 444 void ShaderCacheFactory::AddToCache(const base::FilePath& key, |
| 456 ShaderDiskCache* cache) { | 445 ShaderDiskCache* cache) { |
| 446 DCHECK(CalledOnValidThread()); | |
| 457 shader_cache_map_[key] = cache; | 447 shader_cache_map_[key] = cache; |
| 458 } | 448 } |
| 459 | 449 |
| 460 void ShaderCacheFactory::RemoveFromCache(const base::FilePath& key) { | 450 void ShaderCacheFactory::RemoveFromCache(const base::FilePath& key) { |
| 451 DCHECK(CalledOnValidThread()); | |
| 461 shader_cache_map_.erase(key); | 452 shader_cache_map_.erase(key); |
| 462 } | 453 } |
| 463 | 454 |
| 464 void ShaderCacheFactory::ClearByPath(const base::FilePath& path, | 455 void ShaderCacheFactory::ClearByPath(const base::FilePath& path, |
| 465 const base::Time& delete_begin, | 456 const base::Time& delete_begin, |
| 466 const base::Time& delete_end, | 457 const base::Time& delete_end, |
| 467 const base::Closure& callback) { | 458 const base::Closure& callback) { |
| 468 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 459 DCHECK(CalledOnValidThread()); |
| 469 DCHECK(!callback.is_null()); | 460 DCHECK(!callback.is_null()); |
| 470 | 461 |
| 471 scoped_refptr<ShaderClearHelper> helper = new ShaderClearHelper( | 462 scoped_refptr<ShaderClearHelper> helper = new ShaderClearHelper( |
| 472 GetByPath(path), path, delete_begin, delete_end, callback); | 463 GetByPath(path), path, delete_begin, delete_end, callback); |
| 473 | 464 |
| 474 // We could receive requests to clear the same path with different | 465 // We could receive requests to clear the same path with different |
| 475 // begin/end times. So, we keep a list of requests. If we haven't seen this | 466 // begin/end times. So, we keep a list of requests. If we haven't seen this |
| 476 // path before we kick off the clear and add it to the list. If we have see it | 467 // path before we kick off the clear and add it to the list. If we have see it |
| 477 // already, then we already have a clear running. We add this clear to the | 468 // already, then we already have a clear running. We add this clear to the |
| 478 // list and wait for any previous clears to finish. | 469 // list and wait for any previous clears to finish. |
| 479 ShaderClearMap::iterator iter = shader_clear_map_.find(path); | 470 ShaderClearMap::iterator iter = shader_clear_map_.find(path); |
| 480 if (iter != shader_clear_map_.end()) { | 471 if (iter != shader_clear_map_.end()) { |
| 481 iter->second.push(helper); | 472 iter->second.push(helper); |
| 482 return; | 473 return; |
| 483 } | 474 } |
| 484 | 475 |
| 485 shader_clear_map_.insert( | 476 shader_clear_map_.insert( |
| 486 std::pair<base::FilePath, ShaderClearQueue>(path, ShaderClearQueue())); | 477 std::pair<base::FilePath, ShaderClearQueue>(path, ShaderClearQueue())); |
| 487 shader_clear_map_[path].push(helper); | 478 shader_clear_map_[path].push(helper); |
| 488 helper->Clear(); | 479 helper->Clear(); |
| 489 } | 480 } |
| 490 | 481 |
| 491 void ShaderCacheFactory::CacheCleared(const base::FilePath& path) { | 482 void ShaderCacheFactory::CacheCleared(const base::FilePath& path) { |
| 492 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 483 DCHECK(CalledOnValidThread()); |
| 493 | 484 |
| 494 ShaderClearMap::iterator iter = shader_clear_map_.find(path); | 485 ShaderClearMap::iterator iter = shader_clear_map_.find(path); |
| 495 if (iter == shader_clear_map_.end()) { | 486 if (iter == shader_clear_map_.end()) { |
| 496 LOG(ERROR) << "Completed clear but missing clear helper."; | 487 LOG(ERROR) << "Completed clear but missing clear helper."; |
| 497 return; | 488 return; |
| 498 } | 489 } |
| 499 | 490 |
| 500 iter->second.pop(); | 491 iter->second.pop(); |
| 501 | 492 |
| 502 // If there are remaining items in the list we trigger the Clear on the | 493 // If there are remaining items in the list we trigger the Clear on the |
| 503 // next one. | 494 // next one. |
| 504 if (!iter->second.empty()) { | 495 if (!iter->second.empty()) { |
| 505 iter->second.front()->Clear(); | 496 iter->second.front()->Clear(); |
| 506 return; | 497 return; |
| 507 } | 498 } |
| 508 | 499 |
| 509 shader_clear_map_.erase(path); | 500 shader_clear_map_.erase(path); |
| 510 } | 501 } |
| 511 | 502 |
| 503 //////////////////////////////////////////////////////////////////////////////// | |
| 504 // ShaderDiskCache | |
| 505 | |
| 512 ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path) | 506 ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path) |
| 513 : cache_available_(false), | 507 : cache_available_(false), |
| 514 cache_path_(cache_path), | 508 cache_path_(cache_path), |
| 515 is_initialized_(false) { | 509 is_initialized_(false) { |
| 516 ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this); | 510 ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this); |
| 517 } | 511 } |
| 518 | 512 |
| 519 ShaderDiskCache::~ShaderDiskCache() { | 513 ShaderDiskCache::~ShaderDiskCache() { |
| 520 ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_); | 514 ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_); |
| 521 } | 515 } |
| 522 | 516 |
| 523 void ShaderDiskCache::Init() { | 517 void ShaderDiskCache::Init( |
| 518 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) { | |
| 524 if (is_initialized_) { | 519 if (is_initialized_) { |
| 525 NOTREACHED(); // can't initialize disk cache twice. | 520 NOTREACHED(); // can't initialize disk cache twice. |
| 526 return; | 521 return; |
| 527 } | 522 } |
| 528 is_initialized_ = true; | 523 is_initialized_ = true; |
| 529 | 524 |
| 530 int rv = disk_cache::CreateCacheBackend( | 525 int rv = disk_cache::CreateCacheBackend( |
| 531 net::SHADER_CACHE, net::CACHE_BACKEND_DEFAULT, | 526 net::SHADER_CACHE, net::CACHE_BACKEND_DEFAULT, |
| 532 cache_path_.Append(kGpuCachePath), | 527 cache_path_.Append(kGpuCachePath), |
| 533 gpu::kDefaultMaxProgramCacheMemoryBytes, true, | 528 gpu::kDefaultMaxProgramCacheMemoryBytes, true, cache_task_runner, NULL, |
| 534 BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE).get(), NULL, | |
| 535 &backend_, base::Bind(&ShaderDiskCache::CacheCreatedCallback, this)); | 529 &backend_, base::Bind(&ShaderDiskCache::CacheCreatedCallback, this)); |
| 536 | 530 |
| 537 if (rv == net::OK) | 531 if (rv == net::OK) |
| 538 cache_available_ = true; | 532 cache_available_ = true; |
| 539 } | 533 } |
| 540 | 534 |
| 541 void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) { | 535 void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) { |
| 542 if (!cache_available_) | 536 if (!cache_available_) |
| 543 return; | 537 return; |
| 544 | 538 |
| 545 scoped_refptr<ShaderDiskCacheEntry> shim = | 539 auto shim = base::MakeUnique<ShaderDiskCacheEntry>(this, key, shader); |
| 546 new ShaderDiskCacheEntry(AsWeakPtr(), key, shader); | |
| 547 shim->Cache(); | 540 shim->Cache(); |
| 548 | 541 entries_.push_back(std::move(shim)); |
| 549 entry_map_[shim.get()] = shim; | |
| 550 } | 542 } |
| 551 | 543 |
| 552 int ShaderDiskCache::Clear( | 544 int ShaderDiskCache::Clear( |
| 553 const base::Time begin_time, const base::Time end_time, | 545 const base::Time begin_time, const base::Time end_time, |
| 554 const net::CompletionCallback& completion_callback) { | 546 const net::CompletionCallback& completion_callback) { |
| 555 int rv; | 547 int rv; |
| 556 if (begin_time.is_null()) { | 548 if (begin_time.is_null()) { |
| 557 rv = backend_->DoomAllEntries(completion_callback); | 549 rv = backend_->DoomAllEntries(completion_callback); |
| 558 } else { | 550 } else { |
| 559 rv = backend_->DoomEntriesBetween(begin_time, end_time, | 551 rv = backend_->DoomEntriesBetween(begin_time, end_time, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 574 return net::OK; | 566 return net::OK; |
| 575 available_callback_ = callback; | 567 available_callback_ = callback; |
| 576 return net::ERR_IO_PENDING; | 568 return net::ERR_IO_PENDING; |
| 577 } | 569 } |
| 578 | 570 |
| 579 void ShaderDiskCache::CacheCreatedCallback(int rv) { | 571 void ShaderDiskCache::CacheCreatedCallback(int rv) { |
| 580 if (rv != net::OK) { | 572 if (rv != net::OK) { |
| 581 LOG(ERROR) << "Shader Cache Creation failed: " << rv; | 573 LOG(ERROR) << "Shader Cache Creation failed: " << rv; |
| 582 return; | 574 return; |
| 583 } | 575 } |
| 584 helper_ = new ShaderDiskReadHelper(AsWeakPtr(), shader_loaded_callback_); | 576 helper_ = |
| 577 base::MakeUnique<ShaderDiskReadHelper>(this, shader_loaded_callback_); | |
| 585 helper_->LoadCache(); | 578 helper_->LoadCache(); |
| 586 } | 579 } |
| 587 | 580 |
| 588 void ShaderDiskCache::EntryComplete(void* entry) { | 581 void ShaderDiskCache::EntryComplete(ShaderDiskCacheEntry* entry) { |
| 589 entry_map_.erase(entry); | 582 entries_.erase( |
| 583 std::remove_if(entries_.begin(), entries_.end(), | |
| 584 [entry](const std::unique_ptr<ShaderDiskCacheEntry>& e) { | |
| 585 return e.get() == entry; | |
| 586 })); | |
|
piman
2016/11/02 18:11:15
This changes from O(log n) to O(n) - is it really
sadrul
2016/11/02 19:24:53
I couldn't find a clean way of using std::[unorder
| |
| 590 | 587 |
| 591 if (entry_map_.empty() && !cache_complete_callback_.is_null()) | 588 if (entries_.empty() && !cache_complete_callback_.is_null()) |
| 592 cache_complete_callback_.Run(net::OK); | 589 cache_complete_callback_.Run(net::OK); |
| 593 } | 590 } |
| 594 | 591 |
| 595 void ShaderDiskCache::ReadComplete() { | 592 void ShaderDiskCache::ReadComplete() { |
| 596 helper_ = NULL; | 593 helper_ = nullptr; |
| 597 | 594 |
| 598 // The cache is considered available after we have finished reading any | 595 // The cache is considered available after we have finished reading any |
| 599 // of the old cache values off disk. This prevents a potential race where we | 596 // of the old cache values off disk. This prevents a potential race where we |
| 600 // are reading from disk and execute a cache clear at the same time. | 597 // are reading from disk and execute a cache clear at the same time. |
| 601 cache_available_ = true; | 598 cache_available_ = true; |
| 602 if (!available_callback_.is_null()) { | 599 if (!available_callback_.is_null()) { |
| 603 available_callback_.Run(net::OK); | 600 available_callback_.Run(net::OK); |
| 604 available_callback_.Reset(); | 601 available_callback_.Reset(); |
| 605 } | 602 } |
| 606 } | 603 } |
| 607 | 604 |
| 608 int ShaderDiskCache::SetCacheCompleteCallback( | 605 int ShaderDiskCache::SetCacheCompleteCallback( |
| 609 const net::CompletionCallback& callback) { | 606 const net::CompletionCallback& callback) { |
| 610 if (entry_map_.empty()) { | 607 if (entries_.empty()) { |
| 611 return net::OK; | 608 return net::OK; |
| 612 } | 609 } |
| 613 cache_complete_callback_ = callback; | 610 cache_complete_callback_ = callback; |
| 614 return net::ERR_IO_PENDING; | 611 return net::ERR_IO_PENDING; |
| 615 } | 612 } |
| 616 | 613 |
| 617 } // namespace content | 614 } // namespace content |
| 618 | 615 |
| OLD | NEW |