OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "android_webview/browser/shared_renderer_state.h" | |
6 | |
7 #include "android_webview/browser/browser_view_renderer_client.h" | |
8 #include "base/bind.h" | |
9 #include "base/lazy_instance.h" | |
10 #include "base/location.h" | |
11 | |
12 namespace android_webview { | |
13 | |
14 namespace internal { | |
15 | |
16 class RequestDrawGLTracker { | |
17 public: | |
18 RequestDrawGLTracker(); | |
19 bool ShouldRequestOnNoneUiThread(SharedRendererState* state); | |
20 bool ShouldRequestOnUiThread(SharedRendererState* state); | |
21 void DidRequestOnUiThread(); | |
22 void ResetPending(); | |
23 | |
24 private: | |
25 base::Lock lock_; | |
26 SharedRendererState* pending_ui_; | |
27 SharedRendererState* pending_non_ui_; | |
28 }; | |
29 | |
30 RequestDrawGLTracker::RequestDrawGLTracker() | |
31 : pending_ui_(NULL), pending_non_ui_(NULL) { | |
32 } | |
33 | |
34 bool RequestDrawGLTracker::ShouldRequestOnNoneUiThread( | |
35 SharedRendererState* state) { | |
36 base::AutoLock lock(lock_); | |
37 if (pending_ui_ || pending_non_ui_) | |
38 return false; | |
39 pending_non_ui_ = state; | |
40 return true; | |
41 } | |
42 | |
43 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) { | |
44 base::AutoLock lock(lock_); | |
45 if (pending_non_ui_) { | |
46 pending_non_ui_->ResetRequestDrawGLCallback(); | |
47 pending_non_ui_ = NULL; | |
48 } | |
49 if (pending_ui_) | |
50 return false; | |
51 pending_ui_ = state; | |
52 return true; | |
53 } | |
54 | |
55 void RequestDrawGLTracker::ResetPending() { | |
56 base::AutoLock lock(lock_); | |
57 pending_non_ui_ = NULL; | |
58 pending_ui_ = NULL; | |
59 } | |
60 | |
61 } // namespace internal | |
62 | |
63 namespace { | |
64 | |
65 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker = | |
66 LAZY_INSTANCE_INITIALIZER; | |
67 | |
68 } | |
69 | |
70 SharedRendererState::SharedRendererState( | |
71 scoped_refptr<base::MessageLoopProxy> ui_loop, | |
72 BrowserViewRendererClient* client) | |
73 : ui_loop_(ui_loop), | |
74 client_on_ui_(client), | |
75 force_commit_(false), | |
76 inside_hardware_release_(false), | |
77 needs_force_invalidate_on_next_draw_gl_(false), | |
78 weak_factory_on_ui_thread_(this) { | |
79 DCHECK(ui_loop_->BelongsToCurrentThread()); | |
80 DCHECK(client_on_ui_); | |
81 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr(); | |
82 ResetRequestDrawGLCallback(); | |
83 } | |
84 | |
85 SharedRendererState::~SharedRendererState() { | |
86 DCHECK(ui_loop_->BelongsToCurrentThread()); | |
87 } | |
88 | |
89 void SharedRendererState::ClientRequestDrawGL() { | |
90 if (ui_loop_->BelongsToCurrentThread()) { | |
91 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this)) | |
92 return; | |
93 ClientRequestDrawGLOnUIThread(); | |
94 } else { | |
95 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNoneUiThread(this)) | |
96 return; | |
97 base::Closure callback; | |
98 { | |
99 base::AutoLock lock(lock_); | |
100 callback = request_draw_gl_closure_; | |
101 } | |
102 ui_loop_->PostTask(FROM_HERE, callback); | |
103 } | |
104 } | |
105 | |
106 void SharedRendererState::DidDrawGLProcess() { | |
107 g_request_draw_gl_tracker.Get().ResetPending(); | |
108 } | |
109 | |
110 void SharedRendererState::ResetRequestDrawGLCallback() { | |
111 DCHECK(ui_loop_->BelongsToCurrentThread()); | |
112 base::AutoLock lock(lock_); | |
113 request_draw_gl_cancelable_closure_.Reset( | |
114 base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread, | |
115 base::Unretained(this))); | |
116 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback(); | |
117 } | |
118 | |
119 void SharedRendererState::ClientRequestDrawGLOnUIThread() { | |
120 DCHECK(ui_loop_->BelongsToCurrentThread()); | |
121 ResetRequestDrawGLCallback(); | |
122 if (!client_on_ui_->RequestDrawGL(NULL, false)) { | |
123 g_request_draw_gl_tracker.Get().ResetPending(); | |
124 LOG(ERROR) << "Failed to request GL process. Deadlock likely"; | |
125 } | |
126 } | |
127 | |
128 void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() { | |
129 DCHECK(ui_loop_->BelongsToCurrentThread()); | |
130 client_on_ui_->UpdateParentDrawConstraints(); | |
131 } | |
132 | |
133 void SharedRendererState::SetScrollOffset(gfx::Vector2d scroll_offset) { | |
134 base::AutoLock lock(lock_); | |
135 scroll_offset_ = scroll_offset; | |
136 } | |
137 | |
138 gfx::Vector2d SharedRendererState::GetScrollOffset() { | |
139 base::AutoLock lock(lock_); | |
140 return scroll_offset_; | |
141 } | |
142 | |
143 bool SharedRendererState::HasCompositorFrame() const { | |
144 base::AutoLock lock(lock_); | |
145 return compositor_frame_.get(); | |
146 } | |
147 | |
148 void SharedRendererState::SetCompositorFrame( | |
149 scoped_ptr<cc::CompositorFrame> frame, bool force_commit) { | |
150 base::AutoLock lock(lock_); | |
151 DCHECK(!compositor_frame_.get()); | |
152 compositor_frame_ = frame.Pass(); | |
153 force_commit_ = force_commit; | |
154 } | |
155 | |
156 scoped_ptr<cc::CompositorFrame> SharedRendererState::PassCompositorFrame() { | |
157 base::AutoLock lock(lock_); | |
158 return compositor_frame_.Pass(); | |
159 } | |
160 | |
161 bool SharedRendererState::ForceCommit() const { | |
162 base::AutoLock lock(lock_); | |
163 return force_commit_; | |
164 } | |
165 | |
166 bool SharedRendererState::UpdateDrawConstraints( | |
167 const ParentCompositorDrawConstraints& parent_draw_constraints) { | |
168 base::AutoLock lock(lock_); | |
169 if (needs_force_invalidate_on_next_draw_gl_ || | |
170 !parent_draw_constraints_.Equals(parent_draw_constraints)) { | |
171 parent_draw_constraints_ = parent_draw_constraints; | |
172 return true; | |
173 } | |
174 | |
175 return false; | |
176 } | |
177 | |
178 void SharedRendererState::PostExternalDrawConstraintsToChildCompositor( | |
179 const ParentCompositorDrawConstraints& parent_draw_constraints) { | |
180 if (UpdateDrawConstraints(parent_draw_constraints)) { | |
181 // No need to hold the lock_ during the post task. | |
182 ui_loop_->PostTask( | |
183 FROM_HERE, | |
184 base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread, | |
185 ui_thread_weak_ptr_)); | |
186 } | |
187 } | |
188 | |
189 void SharedRendererState::DidSkipCommitFrame() { | |
190 ui_loop_->PostTask( | |
191 FROM_HERE, | |
192 base::Bind(&SharedRendererState::DidSkipCommitFrameOnUIThread, | |
193 ui_thread_weak_ptr_)); | |
194 } | |
195 | |
196 void SharedRendererState::DidSkipCommitFrameOnUIThread() { | |
197 DCHECK(ui_loop_->BelongsToCurrentThread()); | |
198 client_on_ui_->DidSkipCommitFrame(); | |
199 } | |
200 | |
201 const ParentCompositorDrawConstraints | |
202 SharedRendererState::ParentDrawConstraints() const { | |
203 base::AutoLock lock(lock_); | |
204 return parent_draw_constraints_; | |
205 } | |
206 | |
207 void SharedRendererState::SetForceInvalidateOnNextDrawGL( | |
208 bool needs_force_invalidate_on_next_draw_gl) { | |
209 base::AutoLock lock(lock_); | |
210 needs_force_invalidate_on_next_draw_gl_ = | |
211 needs_force_invalidate_on_next_draw_gl; | |
212 } | |
213 | |
214 bool SharedRendererState::NeedsForceInvalidateOnNextDrawGL() const { | |
215 base::AutoLock lock(lock_); | |
216 return needs_force_invalidate_on_next_draw_gl_; | |
217 } | |
218 | |
219 void SharedRendererState::SetInsideHardwareRelease(bool inside) { | |
220 base::AutoLock lock(lock_); | |
221 inside_hardware_release_ = inside; | |
222 } | |
223 | |
224 bool SharedRendererState::IsInsideHardwareRelease() const { | |
225 base::AutoLock lock(lock_); | |
226 return inside_hardware_release_; | |
227 } | |
228 | |
229 void SharedRendererState::InsertReturnedResources( | |
230 const cc::ReturnedResourceArray& resources) { | |
231 base::AutoLock lock(lock_); | |
232 returned_resources_.insert( | |
233 returned_resources_.end(), resources.begin(), resources.end()); | |
234 } | |
235 | |
236 void SharedRendererState::SwapReturnedResources( | |
237 cc::ReturnedResourceArray* resources) { | |
238 DCHECK(resources->empty()); | |
239 base::AutoLock lock(lock_); | |
240 resources->swap(returned_resources_); | |
241 } | |
242 | |
243 bool SharedRendererState::ReturnedResourcesEmpty() const { | |
244 base::AutoLock lock(lock_); | |
245 return returned_resources_.empty(); | |
246 } | |
247 | |
248 InsideHardwareReleaseReset::InsideHardwareReleaseReset( | |
249 SharedRendererState* shared_renderer_state) | |
250 : shared_renderer_state_(shared_renderer_state) { | |
251 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease()); | |
252 shared_renderer_state_->SetInsideHardwareRelease(true); | |
253 } | |
254 | |
255 InsideHardwareReleaseReset::~InsideHardwareReleaseReset() { | |
256 shared_renderer_state_->SetInsideHardwareRelease(false); | |
257 } | |
258 | |
259 } // namespace android_webview | |
OLD | NEW |