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