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 #ifndef GPU_IPC_HOST_SHADER_DISK_CACHE_H_
6 #define GPU_IPC_HOST_SHADER_DISK_CACHE_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <string>
12 #include <unordered_map>
13 
14 #include "base/containers/queue.h"
15 #include "base/files/file_path.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/threading/thread_checker.h"
19 #include "net/base/completion_once_callback.h"
20 #include "net/disk_cache/disk_cache.h"
21 
22 namespace gpu {
23 
24 class ShaderCacheFactory;
25 class ShaderDiskCacheEntry;
26 class ShaderDiskReadHelper;
27 class ShaderClearHelper;
28 
29 // ShaderDiskCache is the interface to the on disk cache for
30 // GL shaders.
31 class ShaderDiskCache : public base::RefCounted<ShaderDiskCache> {
32  public:
33   using ShaderLoadedCallback =
34       base::RepeatingCallback<void(const std::string&, const std::string&)>;
35 
set_shader_loaded_callback(const ShaderLoadedCallback & callback)36   void set_shader_loaded_callback(const ShaderLoadedCallback& callback) {
37     shader_loaded_callback_ = callback;
38   }
39 
40   // Store the |shader| into the cache under |key|.
41   void Cache(const std::string& key, const std::string& shader);
42 
43   // Clear a range of entries. This supports unbounded deletes in either
44   // direction by using null Time values for either |begin_time| or |end_time|.
45   // The return value is a net error code. If this method returns
46   // ERR_IO_PENDING, the |completion_callback| will be invoked when the
47   // operation completes.
48   int Clear(const base::Time begin_time,
49             const base::Time end_time,
50             net::CompletionOnceCallback completion_callback);
51 
52   // Sets a callback for when the cache is available. If the cache is
53   // already available the callback will not be called and net::OK is returned.
54   // If the callback is set net::ERR_IO_PENDING is returned and the callback
55   // will be executed when the cache is available.
56   int SetAvailableCallback(net::CompletionOnceCallback callback);
57 
58   // Returns the number of elements currently in the cache.
59   int32_t Size();
60 
61   // Set a callback notification for when all current entries have been
62   // written to the cache.
63   // The return value is a net error code. If this method returns
64   // ERR_IO_PENDING, the |callback| will be invoked when all entries have
65   // been written to the cache.
66   int SetCacheCompleteCallback(net::CompletionOnceCallback callback);
67 
68   // Returns the size which should be used for the shader disk cache.
69   static size_t CacheSizeBytes();
70 
71  private:
72   friend class base::RefCounted<ShaderDiskCache>;
73   friend class ShaderDiskCacheEntry;
74   friend class ShaderDiskReadHelper;
75   friend class ShaderCacheFactory;
76 
77   ShaderDiskCache(ShaderCacheFactory* factory,
78                   const base::FilePath& cache_path);
79   ~ShaderDiskCache();
80 
81   void Init();
82   void CacheCreatedCallback(int rv);
83 
backend()84   disk_cache::Backend* backend() { return backend_.get(); }
85 
86   void EntryComplete(ShaderDiskCacheEntry* entry);
87   void ReadComplete();
88 
89   ShaderCacheFactory* factory_;
90   bool cache_available_;
91   base::FilePath cache_path_;
92   bool is_initialized_;
93   net::CompletionOnceCallback available_callback_;
94   net::CompletionOnceCallback cache_complete_callback_;
95   ShaderLoadedCallback shader_loaded_callback_;
96 
97   std::unique_ptr<disk_cache::Backend> backend_;
98 
99   std::unique_ptr<ShaderDiskReadHelper> helper_;
100   std::unordered_map<ShaderDiskCacheEntry*,
101                      std::unique_ptr<ShaderDiskCacheEntry>>
102       entries_;
103 
104   DISALLOW_COPY_AND_ASSIGN(ShaderDiskCache);
105 };
106 
107 // ShaderCacheFactory maintains a cache of ShaderDiskCache objects
108 // so we only create one per profile directory.
109 class ShaderCacheFactory : public base::ThreadChecker {
110  public:
111   ShaderCacheFactory();
112   ~ShaderCacheFactory();
113 
114   // Clear the shader disk cache for the given |path|. This supports unbounded
115   // deletes in either direction by using null Time values for either
116   // |begin_time| or |end_time|. The |callback| will be executed when the
117   // clear is complete.
118   void ClearByPath(const base::FilePath& path,
119                    const base::Time& begin_time,
120                    const base::Time& end_time,
121                    base::OnceClosure callback);
122 
123   // Same as ClearByPath, but looks up the cache by |client_id|. The |callback|
124   // will be executed when the clear is complete.
125   void ClearByClientId(int32_t client_id,
126                        const base::Time& begin_time,
127                        const base::Time& end_time,
128                        base::OnceClosure callback);
129 
130   // Retrieve the shader disk cache for the provided |client_id|.
131   scoped_refptr<ShaderDiskCache> Get(int32_t client_id);
132 
133   // Set the |path| to be used for the disk cache for |client_id|.
134   void SetCacheInfo(int32_t client_id, const base::FilePath& path);
135 
136   // Remove the path mapping for |client_id|.
137   void RemoveCacheInfo(int32_t client_id);
138 
139   // Set the provided |cache| into the cache map for the given |path|.
140   void AddToCache(const base::FilePath& path, ShaderDiskCache* cache);
141 
142   // Remove the provided |path| from our cache map.
143   void RemoveFromCache(const base::FilePath& path);
144 
145  private:
146   friend class ShaderClearHelper;
147 
148   scoped_refptr<ShaderDiskCache> GetByPath(const base::FilePath& path);
149   void CacheCleared(const base::FilePath& path);
150 
151   using ShaderCacheMap = std::map<base::FilePath, ShaderDiskCache*>;
152   ShaderCacheMap shader_cache_map_;
153 
154   using ClientIdToPathMap = std::map<int32_t, base::FilePath>;
155   ClientIdToPathMap client_id_to_path_map_;
156 
157   using ShaderClearQueue = base::queue<std::unique_ptr<ShaderClearHelper>>;
158   using ShaderClearMap = std::map<base::FilePath, ShaderClearQueue>;
159   ShaderClearMap shader_clear_map_;
160 
161   DISALLOW_COPY_AND_ASSIGN(ShaderCacheFactory);
162 };
163 
164 }  // namespace gpu
165 
166 #endif  // GPU_IPC_HOST_SHADER_DISK_CACHE_H_
167