Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: content/browser/gpu/shader_disk_cache.cc

Issue 12500009: Add the ability to clear the shader disk cache. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/gpu/shader_disk_cache.h"
6
7 #include "base/threading/thread_checker.h"
8 #include "content/browser/gpu/gpu_process_host.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12
13 namespace content {
14
15 namespace {
16
17 static const base::FilePath::CharType kGpuCachePath[] =
18 FILE_PATH_LITERAL("GPUCache");
19
20 void EntryCloser(disk_cache::Entry* entry) {
21 entry->Close();
22 }
23
24 } // namespace
25
26 // ShaderDiskCacheEntry handles the work of caching/updating the cached
27 // shaders.
28 class ShaderDiskCacheEntry
29 : public base::ThreadChecker,
30 public base::RefCounted<ShaderDiskCacheEntry> {
31 public:
32 ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache,
33 const std::string& key,
34 const std::string& shader);
35 void Cache();
36
37 private:
38 friend class base::RefCounted<ShaderDiskCacheEntry>;
39
40 enum OpType {
41 TERMINATE,
42 OPEN_ENTRY,
43 WRITE_DATA,
44 CREATE_ENTRY,
45 };
46
47 ~ShaderDiskCacheEntry();
48
49 void OnOpComplete(int rv);
50
51 int OpenCallback(int rv);
52 int WriteCallback(int rv);
53 int IOComplete(int rv);
54
55 base::WeakPtr<ShaderDiskCache> cache_;
56 OpType op_type_;
57 std::string key_;
58 std::string shader_;
59 disk_cache::Entry* entry_;
60
61 DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheEntry);
62 };
63
64 // ShaderDiskReadHelper is used to load all of the cached shaders from the
65 // disk cache and send to the memory cache.
66 class ShaderDiskReadHelper
67 : public base::ThreadChecker,
68 public base::RefCounted<ShaderDiskReadHelper> {
69 public:
70 ShaderDiskReadHelper(base::WeakPtr<ShaderDiskCache> cache, int host_id);
71 void LoadCache();
72
73 private:
74 friend class base::RefCounted<ShaderDiskReadHelper>;
75
76 enum OpType {
77 TERMINATE,
78 OPEN_NEXT,
79 OPEN_NEXT_COMPLETE,
80 READ_COMPLETE,
81 ITERATION_FINISHED
82 };
83
84
85 ~ShaderDiskReadHelper();
86
87 void OnOpComplete(int rv);
88
89 int OpenNextEntry();
90 int OpenNextEntryComplete(int rv);
91 int ReadComplete(int rv);
92 int IterationComplete(int rv);
93
94 base::WeakPtr<ShaderDiskCache> cache_;
95 OpType op_type_;
96 void* iter_;
97 scoped_refptr<net::IOBufferWithSize> buf_;
98 int host_id_;
99 disk_cache::Entry* entry_;
100
101 DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper);
102 };
103
104 ShaderDiskCacheEntry::ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache,
105 const std::string& key,
106 const std::string& shader)
107 : cache_(cache),
108 op_type_(OPEN_ENTRY),
109 key_(key),
110 shader_(shader),
111 entry_(NULL) {
112 }
113
114 ShaderDiskCacheEntry::~ShaderDiskCacheEntry() {
115 if (entry_)
116 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
117 base::Bind(&EntryCloser, entry_));
118 }
119
120 void ShaderDiskCacheEntry::Cache() {
121 DCHECK(CalledOnValidThread());
122 if (!cache_)
123 return;
124
125 int rv = cache_->backend()->OpenEntry(
126 key_,
127 &entry_,
128 base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this));
129 if (rv != net::ERR_IO_PENDING)
130 OnOpComplete(rv);
131 }
132
133 void ShaderDiskCacheEntry::OnOpComplete(int rv) {
134 DCHECK(CalledOnValidThread());
135 if (!cache_)
136 return;
137
138 do {
139 switch (op_type_) {
140 case OPEN_ENTRY:
141 rv = OpenCallback(rv);
142 break;
143 case CREATE_ENTRY:
144 rv = WriteCallback(rv);
145 break;
146 case WRITE_DATA:
147 rv = IOComplete(rv);
148 break;
149 case TERMINATE:
150 rv = net::ERR_IO_PENDING; // break the loop.
151 break;
152 default:
153 NOTREACHED(); // Invalid op_type_ provided.
154 break;
155 }
156 } while (rv != net::ERR_IO_PENDING);
157 }
158
159 int ShaderDiskCacheEntry::OpenCallback(int rv) {
160 DCHECK(CalledOnValidThread());
161 // Called through OnOpComplete, so we know |cache_| is valid.
162 if (rv == net::OK) {
163 cache_->backend()->OnExternalCacheHit(key_);
164 cache_->EntryComplete(this);
165 op_type_ = TERMINATE;
166 return rv;
167 }
168
169 op_type_ = CREATE_ENTRY;
170 return cache_->backend()->CreateEntry(
171 key_,
172 &entry_,
173 base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this));
174 }
175
176 int ShaderDiskCacheEntry::WriteCallback(int rv) {
177 DCHECK(CalledOnValidThread());
178 // Called through OnOpComplete, so we know |cache_| is valid.
179 if (rv != net::OK) {
180 LOG(ERROR) << "Failed to create shader cache entry: " << rv;
181 cache_->EntryComplete(this);
182 op_type_ = TERMINATE;
183 return rv;
184 }
185
186 op_type_ = WRITE_DATA;
187 scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(shader_);
188 return entry_->WriteData(1, 0, io_buf, shader_.length(),
189 base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
190 this),
191 false);
192 }
193
194 int ShaderDiskCacheEntry::IOComplete(int rv) {
195 DCHECK(CalledOnValidThread());
196 // Called through OnOpComplete, so we know |cache_| is valid.
197 cache_->EntryComplete(this);
198 op_type_ = TERMINATE;
199 return rv;
200 }
201
202 ShaderDiskReadHelper::ShaderDiskReadHelper(
203 base::WeakPtr<ShaderDiskCache> cache,
204 int host_id)
205 : cache_(cache),
206 op_type_(OPEN_NEXT),
207 iter_(NULL),
208 buf_(NULL),
209 host_id_(host_id),
210 entry_(NULL) {
211 }
212
213 void ShaderDiskReadHelper::LoadCache() {
214 DCHECK(CalledOnValidThread());
215 if (!cache_)
216 return;
217 OnOpComplete(net::OK);
218 }
219
220 void ShaderDiskReadHelper::OnOpComplete(int rv) {
221 DCHECK(CalledOnValidThread());
222 if (!cache_)
223 return;
224
225 do {
226 switch (op_type_) {
227 case OPEN_NEXT:
228 rv = OpenNextEntry();
229 break;
230 case OPEN_NEXT_COMPLETE:
231 rv = OpenNextEntryComplete(rv);
232 break;
233 case READ_COMPLETE:
234 rv = ReadComplete(rv);
235 break;
236 case ITERATION_FINISHED:
237 rv = IterationComplete(rv);
238 break;
239 case TERMINATE:
240 cache_->ReadComplete();
241 rv = net::ERR_IO_PENDING; // break the loop
242 break;
243 default:
244 NOTREACHED(); // Invalid state for read helper
245 rv = net::ERR_FAILED;
246 break;
247 }
248 } while (rv != net::ERR_IO_PENDING);
249 }
250
251 int ShaderDiskReadHelper::OpenNextEntry() {
252 DCHECK(CalledOnValidThread());
253 // Called through OnOpComplete, so we know |cache_| is valid.
254 op_type_ = OPEN_NEXT_COMPLETE;
255 return cache_->backend()->OpenNextEntry(
256 &iter_,
257 &entry_,
258 base::Bind(&ShaderDiskReadHelper::OnOpComplete, this));
259 }
260
261 int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) {
262 DCHECK(CalledOnValidThread());
263 // Called through OnOpComplete, so we know |cache_| is valid.
264 if (rv == net::ERR_FAILED) {
265 op_type_ = ITERATION_FINISHED;
266 return net::OK;
267 }
268
269 if (rv < 0)
270 return rv;
271
272 op_type_ = READ_COMPLETE;
273 buf_ = new net::IOBufferWithSize(entry_->GetDataSize(1));
274 return entry_->ReadData(1, 0, buf_, buf_->size(),
275 base::Bind(&ShaderDiskReadHelper::OnOpComplete,
276 this));
277 }
278
279 int ShaderDiskReadHelper::ReadComplete(int rv) {
280 DCHECK(CalledOnValidThread());
281 // Called through OnOpComplete, so we know |cache_| is valid.
282 if (rv && rv == buf_->size()) {
283 GpuProcessHost* host = GpuProcessHost::FromID(host_id_);
284 if (host)
285 host->LoadedShader(entry_->GetKey(), std::string(buf_->data(),
286 buf_->size()));
287 }
288
289 buf_ = NULL;
290 entry_->Close();
291 entry_ = NULL;
292
293 op_type_ = OPEN_NEXT;
294 return net::OK;
295 }
296
297 int ShaderDiskReadHelper::IterationComplete(int rv) {
298 DCHECK(CalledOnValidThread());
299 // Called through OnOpComplete, so we know |cache_| is valid.
300 cache_->backend()->EndEnumeration(&iter_);
301 iter_ = NULL;
302 op_type_ = TERMINATE;
303 return net::OK;
304 }
305
306 ShaderDiskReadHelper::~ShaderDiskReadHelper() {
307 if (entry_)
308 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
309 base::Bind(&EntryCloser, entry_));
310 }
311
312 ShaderCacheFactory* ShaderCacheFactory::GetInstance() {
313 return Singleton<ShaderCacheFactory,
314 LeakySingletonTraits<ShaderCacheFactory> >::get();
315 }
316
317 ShaderCacheFactory::ShaderCacheFactory() {
318 }
319
320 ShaderCacheFactory::~ShaderCacheFactory() {
321 }
322
323 void ShaderCacheFactory::SetCacheInfo(int32 client_id,
324 const base::FilePath& path) {
325 client_id_to_path_map_[client_id] = path.Append(kGpuCachePath);
326 }
327
328 void ShaderCacheFactory::RemoveCacheInfo(int32 client_id) {
329 client_id_to_path_map_.erase(client_id);
330 }
331
332 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32 client_id) {
333 ClientIdToPathMap::iterator client_iter =
334 client_id_to_path_map_.find(client_id);
335 if (client_iter == client_id_to_path_map_.end())
336 return NULL;
337
338 ShaderCacheMap::iterator iter = shader_cache_map_.find(client_iter->second);
339 if (iter != shader_cache_map_.end())
340 return iter->second;
341
342 ShaderDiskCache* cache = new ShaderDiskCache(client_iter->second);
343 cache->Init();
344
345 return cache;
346 }
347
348 void ShaderCacheFactory::AddToCache(const base::FilePath& key,
349 ShaderDiskCache* cache) {
350 shader_cache_map_[key] = cache;
351 }
352
353 void ShaderCacheFactory::RemoveFromCache(const base::FilePath& key) {
354 shader_cache_map_.erase(key);
355 }
356
357 ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path)
358 : cache_available_(false),
359 max_cache_size_(0),
360 host_id_(0),
361 cache_path_(cache_path),
362 is_initialized_(false),
363 backend_(NULL) {
364 ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this);
365 }
366
367 ShaderDiskCache::~ShaderDiskCache() {
368 ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_);
369 }
370
371 void ShaderDiskCache::Init() {
372 if (is_initialized_) {
373 NOTREACHED(); // can't initialize disk cache twice.
374 return;
375 }
376 is_initialized_ = true;
377
378 int rv = disk_cache::CreateCacheBackend(
379 net::SHADER_CACHE,
380 cache_path_,
381 max_cache_size_,
382 true,
383 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE),
384 NULL,
385 &backend_,
386 base::Bind(&ShaderDiskCache::CacheCreatedCallback, this));
387
388 if (rv == net::OK)
389 cache_available_ = true;
390 }
391
392 void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) {
393 if (!cache_available_)
394 return;
395
396 ShaderDiskCacheEntry* shim =
397 new ShaderDiskCacheEntry(AsWeakPtr(), key, shader);
398 shim->Cache();
399
400 entry_map_[shim] = shim;
401 }
402
403 void ShaderDiskCache::CacheCreatedCallback(int rv) {
404 if (rv != net::OK) {
405 LOG(ERROR) << "Shader Cache Creation failed: " << rv;
406 return;
407 }
408
409 cache_available_ = true;
410
411 helper_ = new ShaderDiskReadHelper(AsWeakPtr(), host_id_);
412 helper_->LoadCache();
413 }
414
415 void ShaderDiskCache::EntryComplete(void* entry) {
416 entry_map_.erase(entry);
417 }
418
419 void ShaderDiskCache::ReadComplete() {
420 helper_ = NULL;
421 }
422
423 } // namespace content
424
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698