OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 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/renderer_host/software_frame_manager.h" | |
6 | |
7 #include <list> | |
8 #include <set> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/callback_helpers.h" | |
12 #include "base/memory/singleton.h" | |
13 #include "base/sys_info.h" | |
14 #include "content/browser/renderer_host/dip_util.h" | |
15 | |
16 namespace { | |
17 | |
18 size_t MaxNumberOfSavedFrames() { | |
19 return std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256)); | |
20 } | |
21 | |
22 void ReleaseMailbox(scoped_refptr<content::SoftwareFrame> frame, | |
23 unsigned sync_point, | |
24 bool lost_resource) {} | |
25 | |
26 } // namespace | |
27 | |
28 namespace content { | |
29 | |
30 //////////////////////////////////////////////////////////////////////////////// | |
31 // SoftwareFrameMemoryManager | |
32 | |
33 class SoftwareFrameMemoryManager { | |
34 public: | |
35 static SoftwareFrameMemoryManager* GetInstance(); | |
36 | |
37 void AddFrame(SoftwareFrameManager*, bool visible); | |
38 void RemoveFrame(SoftwareFrameManager*); | |
39 void SetFrameVisibility(SoftwareFrameManager*, bool visible); | |
40 | |
41 private: | |
42 SoftwareFrameMemoryManager(); | |
43 ~SoftwareFrameMemoryManager(); | |
44 void CullHiddenFrames(); | |
45 friend struct DefaultSingletonTraits<SoftwareFrameMemoryManager>; | |
46 | |
47 std::set<SoftwareFrameManager*> visible_frames_; | |
48 std::list<SoftwareFrameManager*> hidden_frames_; | |
49 | |
50 DISALLOW_COPY_AND_ASSIGN(SoftwareFrameMemoryManager); | |
51 }; | |
52 | |
53 SoftwareFrameMemoryManager* SoftwareFrameMemoryManager::GetInstance() { | |
54 return Singleton<SoftwareFrameMemoryManager>::get(); | |
55 } | |
56 | |
57 void SoftwareFrameMemoryManager::AddFrame(SoftwareFrameManager* frame, | |
58 bool visible) { | |
59 RemoveFrame(frame); | |
60 if (visible) | |
61 visible_frames_.insert(frame); | |
62 else | |
63 hidden_frames_.push_front(frame); | |
64 CullHiddenFrames(); | |
65 } | |
66 | |
67 void SoftwareFrameMemoryManager::RemoveFrame(SoftwareFrameManager* frame) { | |
68 visible_frames_.erase(frame); | |
69 hidden_frames_.remove(frame); | |
70 } | |
71 | |
72 void SoftwareFrameMemoryManager::SetFrameVisibility(SoftwareFrameManager* frame, | |
73 bool visible) { | |
74 if (visible) { | |
75 hidden_frames_.remove(frame); | |
76 visible_frames_.insert(frame); | |
77 } else { | |
78 visible_frames_.erase(frame); | |
79 hidden_frames_.push_front(frame); | |
80 CullHiddenFrames(); | |
81 } | |
82 } | |
83 | |
84 SoftwareFrameMemoryManager::SoftwareFrameMemoryManager() {} | |
85 | |
86 SoftwareFrameMemoryManager::~SoftwareFrameMemoryManager() {} | |
87 | |
88 void SoftwareFrameMemoryManager::CullHiddenFrames() { | |
89 while (!hidden_frames_.empty() && | |
90 hidden_frames_.size() + visible_frames_.size() > | |
91 MaxNumberOfSavedFrames()) { | |
piman
2013/10/22 22:32:48
nit: MaxNumberOfSavedFrames() is a constant, right
ccameron
2013/10/23 01:05:58
Done.
| |
92 size_t old_size = hidden_frames_.size(); | |
93 // Should remove self from list. | |
94 hidden_frames_.back()->EvictCurrentFrame(); | |
95 DCHECK_EQ(hidden_frames_.size() + 1, old_size); | |
96 } | |
97 } | |
98 | |
99 //////////////////////////////////////////////////////////////////////////////// | |
100 // SoftwareFrame | |
101 | |
102 class SoftwareFrame : public base::RefCounted<SoftwareFrame> { | |
103 public: | |
104 SoftwareFrame( | |
105 base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client, | |
106 uint32 output_surface_id, | |
107 unsigned frame_id, | |
108 gfx::Size frame_size_dip, | |
109 gfx::Size frame_size_pixels, | |
110 scoped_ptr<base::SharedMemory> shared_memory) | |
111 : frame_manager_client_(frame_manager_client), | |
112 output_surface_id_(output_surface_id), | |
113 frame_id_(frame_id), | |
114 frame_size_dip_(frame_size_dip), | |
115 frame_size_pixels_(frame_size_pixels), | |
116 shared_memory_(shared_memory.Pass()) {} | |
117 | |
118 void GetMailbox(cc::TextureMailbox* mailbox, | |
119 scoped_ptr<cc::SingleReleaseCallback>* callback) { | |
120 *mailbox = cc::TextureMailbox(shared_memory_.get(), frame_size_pixels_); | |
121 *callback = cc::SingleReleaseCallback::Create( | |
122 base::Bind(ReleaseMailbox, make_scoped_refptr(this))); | |
123 } | |
124 const void* GetPixels() const { return shared_memory_->memory(); } | |
125 gfx::Size GetSizeInDIP() const { return frame_size_dip_; } | |
126 gfx::Size GetSizeInPixels() const { return frame_size_pixels_; } | |
127 | |
128 private: | |
129 friend class base::RefCounted<SoftwareFrame>; | |
130 | |
131 ~SoftwareFrame() { | |
132 if (frame_manager_client_) { | |
133 frame_manager_client_->SoftwareFrameWasFreed( | |
134 output_surface_id_, frame_id_); | |
135 } | |
136 } | |
137 | |
138 base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client_; | |
139 const uint32 output_surface_id_; | |
140 const unsigned frame_id_; | |
141 const gfx::Size frame_size_dip_; | |
142 const gfx::Size frame_size_pixels_; | |
143 scoped_ptr<base::SharedMemory> shared_memory_; | |
144 }; | |
145 | |
146 //////////////////////////////////////////////////////////////////////////////// | |
147 // SoftwareFrameManager | |
148 | |
149 SoftwareFrameManager::SoftwareFrameManager( | |
150 base::WeakPtr<SoftwareFrameManagerClient> client) | |
151 : client_(client) {} | |
152 | |
153 SoftwareFrameManager::~SoftwareFrameManager() {} | |
154 | |
155 bool SoftwareFrameManager::SwapToNewFrame( | |
156 uint32 output_surface_id, | |
157 const cc::SoftwareFrameData* frame_data, | |
158 float frame_device_scale_factor, | |
159 base::ProcessHandle process_handle) { | |
160 const size_t size_in_bytes = 4 * frame_data->size.GetArea(); | |
161 #ifdef OS_WIN | |
162 scoped_ptr<base::SharedMemory> shared_memory( | |
163 new base::SharedMemory(frame_data->handle, true, process_handle)); | |
164 #else | |
165 scoped_ptr<base::SharedMemory> shared_memory( | |
166 new base::SharedMemory(frame_data->handle, true)); | |
167 #endif | |
168 if (!shared_memory->Map(size_in_bytes)) { | |
169 return false; | |
170 } | |
171 | |
172 scoped_refptr<SoftwareFrame> next_frame(new SoftwareFrame( | |
173 client_, | |
174 output_surface_id, | |
175 frame_data->id, | |
176 ConvertSizeToDIP(frame_device_scale_factor, frame_data->size), | |
177 frame_data->size, | |
178 shared_memory.Pass())); | |
179 current_frame_.swap(next_frame); | |
180 return true; | |
181 } | |
182 | |
183 bool SoftwareFrameManager::HasCurrentFrame() const { | |
184 return current_frame_; | |
185 } | |
186 | |
187 void SoftwareFrameManager::DiscardCurrentFrame() { | |
188 if (!HasCurrentFrame()) | |
189 return; | |
190 current_frame_ = NULL; | |
191 SoftwareFrameMemoryManager::GetInstance()->RemoveFrame(this); | |
192 } | |
193 | |
194 void SoftwareFrameManager::SwapToNewFrameComplete(bool visible) { | |
195 DCHECK(HasCurrentFrame()); | |
196 SoftwareFrameMemoryManager::GetInstance()->AddFrame(this, visible); | |
197 } | |
198 | |
199 void SoftwareFrameManager::SetVisibility(bool visible) { | |
200 if (HasCurrentFrame()) { | |
201 SoftwareFrameMemoryManager::GetInstance()->SetFrameVisibility(this, | |
202 visible); | |
203 } | |
204 } | |
205 | |
206 void SoftwareFrameManager::GetCurrentFrameMailbox( | |
207 cc::TextureMailbox* mailbox, | |
208 scoped_ptr<cc::SingleReleaseCallback>* callback) { | |
209 DCHECK(HasCurrentFrame()); | |
210 current_frame_->GetMailbox(mailbox, callback); | |
211 } | |
212 | |
213 const void* SoftwareFrameManager::GetCurrentFramePixels() const { | |
214 DCHECK(HasCurrentFrame()); | |
215 return current_frame_->GetPixels(); | |
216 } | |
217 | |
218 gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const { | |
219 DCHECK(HasCurrentFrame()); | |
220 return current_frame_->GetSizeInPixels(); | |
221 } | |
222 | |
223 gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const { | |
224 DCHECK(HasCurrentFrame()); | |
225 return current_frame_->GetSizeInDIP(); | |
226 } | |
227 | |
228 void SoftwareFrameManager::EvictCurrentFrame() { | |
229 DCHECK(HasCurrentFrame()); | |
230 DiscardCurrentFrame(); | |
231 if (client_) | |
232 client_->CurrentSoftwareFrameWasEvicted(); | |
233 } | |
234 | |
235 } // namespace content | |
OLD | NEW |