• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ResetPending();
22   void SetQueuedFunctorOnUi(SharedRendererState* state);
23 
24  private:
25   base::Lock lock_;
26   SharedRendererState* pending_ui_;
27   SharedRendererState* pending_non_ui_;
28 };
29 
RequestDrawGLTracker()30 RequestDrawGLTracker::RequestDrawGLTracker()
31     : pending_ui_(NULL), pending_non_ui_(NULL) {
32 }
33 
ShouldRequestOnNoneUiThread(SharedRendererState * state)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 
ShouldRequestOnUiThread(SharedRendererState * state)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   // At this time, we could have already called RequestDrawGL on the UI thread,
50   // but the corresponding GL mode process hasn't happened yet. In this case,
51   // don't schedule another requestDrawGL on the UI thread.
52   if (pending_ui_)
53     return false;
54   pending_ui_ = state;
55   return true;
56 }
57 
ResetPending()58 void RequestDrawGLTracker::ResetPending() {
59   base::AutoLock lock(lock_);
60   pending_non_ui_ = NULL;
61   pending_ui_ = NULL;
62 }
63 
SetQueuedFunctorOnUi(SharedRendererState * state)64 void RequestDrawGLTracker::SetQueuedFunctorOnUi(SharedRendererState* state) {
65   base::AutoLock lock(lock_);
66   DCHECK(state);
67   DCHECK(pending_ui_ == state || pending_non_ui_ == state);
68   pending_ui_ = state;
69   pending_non_ui_ = NULL;
70 }
71 
72 }  // namespace internal
73 
74 namespace {
75 
76 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker =
77     LAZY_INSTANCE_INITIALIZER;
78 
79 }
80 
SharedRendererState(scoped_refptr<base::MessageLoopProxy> ui_loop,BrowserViewRendererClient * client)81 SharedRendererState::SharedRendererState(
82     scoped_refptr<base::MessageLoopProxy> ui_loop,
83     BrowserViewRendererClient* client)
84     : ui_loop_(ui_loop),
85       client_on_ui_(client),
86       force_commit_(false),
87       inside_hardware_release_(false),
88       needs_force_invalidate_on_next_draw_gl_(false),
89       weak_factory_on_ui_thread_(this) {
90   DCHECK(ui_loop_->BelongsToCurrentThread());
91   DCHECK(client_on_ui_);
92   ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr();
93   ResetRequestDrawGLCallback();
94 }
95 
~SharedRendererState()96 SharedRendererState::~SharedRendererState() {
97   DCHECK(ui_loop_->BelongsToCurrentThread());
98 }
99 
ClientRequestDrawGL()100 void SharedRendererState::ClientRequestDrawGL() {
101   if (ui_loop_->BelongsToCurrentThread()) {
102     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
103       return;
104     ClientRequestDrawGLOnUIThread();
105   } else {
106     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNoneUiThread(this))
107       return;
108     base::Closure callback;
109     {
110       base::AutoLock lock(lock_);
111       callback = request_draw_gl_closure_;
112     }
113     ui_loop_->PostTask(FROM_HERE, callback);
114   }
115 }
116 
DidDrawGLProcess()117 void SharedRendererState::DidDrawGLProcess() {
118   g_request_draw_gl_tracker.Get().ResetPending();
119 }
120 
ResetRequestDrawGLCallback()121 void SharedRendererState::ResetRequestDrawGLCallback() {
122   DCHECK(ui_loop_->BelongsToCurrentThread());
123   base::AutoLock lock(lock_);
124   request_draw_gl_cancelable_closure_.Reset(
125       base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread,
126                  base::Unretained(this)));
127   request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
128 }
129 
ClientRequestDrawGLOnUIThread()130 void SharedRendererState::ClientRequestDrawGLOnUIThread() {
131   DCHECK(ui_loop_->BelongsToCurrentThread());
132   ResetRequestDrawGLCallback();
133   g_request_draw_gl_tracker.Get().SetQueuedFunctorOnUi(this);
134   if (!client_on_ui_->RequestDrawGL(NULL, false)) {
135     g_request_draw_gl_tracker.Get().ResetPending();
136     LOG(ERROR) << "Failed to request GL process. Deadlock likely";
137   }
138 }
139 
UpdateParentDrawConstraintsOnUIThread()140 void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() {
141   DCHECK(ui_loop_->BelongsToCurrentThread());
142   client_on_ui_->UpdateParentDrawConstraints();
143 }
144 
SetScrollOffset(gfx::Vector2d scroll_offset)145 void SharedRendererState::SetScrollOffset(gfx::Vector2d scroll_offset) {
146   base::AutoLock lock(lock_);
147   scroll_offset_ = scroll_offset;
148 }
149 
GetScrollOffset()150 gfx::Vector2d SharedRendererState::GetScrollOffset() {
151   base::AutoLock lock(lock_);
152   return scroll_offset_;
153 }
154 
HasCompositorFrame() const155 bool SharedRendererState::HasCompositorFrame() const {
156   base::AutoLock lock(lock_);
157   return compositor_frame_.get();
158 }
159 
SetCompositorFrame(scoped_ptr<cc::CompositorFrame> frame,bool force_commit)160 void SharedRendererState::SetCompositorFrame(
161     scoped_ptr<cc::CompositorFrame> frame, bool force_commit) {
162   base::AutoLock lock(lock_);
163   DCHECK(!compositor_frame_.get());
164   compositor_frame_ = frame.Pass();
165   force_commit_ = force_commit;
166 }
167 
PassCompositorFrame()168 scoped_ptr<cc::CompositorFrame> SharedRendererState::PassCompositorFrame() {
169   base::AutoLock lock(lock_);
170   return compositor_frame_.Pass();
171 }
172 
ForceCommit() const173 bool SharedRendererState::ForceCommit() const {
174   base::AutoLock lock(lock_);
175   return force_commit_;
176 }
177 
UpdateDrawConstraints(const ParentCompositorDrawConstraints & parent_draw_constraints)178 bool SharedRendererState::UpdateDrawConstraints(
179     const ParentCompositorDrawConstraints& parent_draw_constraints) {
180   base::AutoLock lock(lock_);
181   if (needs_force_invalidate_on_next_draw_gl_ ||
182       !parent_draw_constraints_.Equals(parent_draw_constraints)) {
183     parent_draw_constraints_ = parent_draw_constraints;
184     return true;
185   }
186 
187   return false;
188 }
189 
PostExternalDrawConstraintsToChildCompositor(const ParentCompositorDrawConstraints & parent_draw_constraints)190 void SharedRendererState::PostExternalDrawConstraintsToChildCompositor(
191     const ParentCompositorDrawConstraints& parent_draw_constraints) {
192   if (UpdateDrawConstraints(parent_draw_constraints)) {
193     // No need to hold the lock_ during the post task.
194     ui_loop_->PostTask(
195         FROM_HERE,
196         base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread,
197                    ui_thread_weak_ptr_));
198   }
199 }
200 
DidSkipCommitFrame()201 void SharedRendererState::DidSkipCommitFrame() {
202   ui_loop_->PostTask(
203       FROM_HERE,
204       base::Bind(&SharedRendererState::DidSkipCommitFrameOnUIThread,
205                  ui_thread_weak_ptr_));
206 }
207 
DidSkipCommitFrameOnUIThread()208 void SharedRendererState::DidSkipCommitFrameOnUIThread() {
209   DCHECK(ui_loop_->BelongsToCurrentThread());
210   client_on_ui_->DidSkipCommitFrame();
211 }
212 
213 const ParentCompositorDrawConstraints
ParentDrawConstraints() const214 SharedRendererState::ParentDrawConstraints() const {
215   base::AutoLock lock(lock_);
216   return parent_draw_constraints_;
217 }
218 
SetForceInvalidateOnNextDrawGL(bool needs_force_invalidate_on_next_draw_gl)219 void SharedRendererState::SetForceInvalidateOnNextDrawGL(
220     bool needs_force_invalidate_on_next_draw_gl) {
221   base::AutoLock lock(lock_);
222   needs_force_invalidate_on_next_draw_gl_ =
223       needs_force_invalidate_on_next_draw_gl;
224 }
225 
NeedsForceInvalidateOnNextDrawGL() const226 bool SharedRendererState::NeedsForceInvalidateOnNextDrawGL() const {
227   base::AutoLock lock(lock_);
228   return needs_force_invalidate_on_next_draw_gl_;
229 }
230 
SetInsideHardwareRelease(bool inside)231 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
232   base::AutoLock lock(lock_);
233   inside_hardware_release_ = inside;
234 }
235 
IsInsideHardwareRelease() const236 bool SharedRendererState::IsInsideHardwareRelease() const {
237   base::AutoLock lock(lock_);
238   return inside_hardware_release_;
239 }
240 
InsertReturnedResources(const cc::ReturnedResourceArray & resources)241 void SharedRendererState::InsertReturnedResources(
242     const cc::ReturnedResourceArray& resources) {
243   base::AutoLock lock(lock_);
244   returned_resources_.insert(
245       returned_resources_.end(), resources.begin(), resources.end());
246 }
247 
SwapReturnedResources(cc::ReturnedResourceArray * resources)248 void SharedRendererState::SwapReturnedResources(
249     cc::ReturnedResourceArray* resources) {
250   DCHECK(resources->empty());
251   base::AutoLock lock(lock_);
252   resources->swap(returned_resources_);
253 }
254 
ReturnedResourcesEmpty() const255 bool SharedRendererState::ReturnedResourcesEmpty() const {
256   base::AutoLock lock(lock_);
257   return returned_resources_.empty();
258 }
259 
InsideHardwareReleaseReset(SharedRendererState * shared_renderer_state)260 InsideHardwareReleaseReset::InsideHardwareReleaseReset(
261     SharedRendererState* shared_renderer_state)
262     : shared_renderer_state_(shared_renderer_state) {
263   DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
264   shared_renderer_state_->SetInsideHardwareRelease(true);
265 }
266 
~InsideHardwareReleaseReset()267 InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
268   shared_renderer_state_->SetInsideHardwareRelease(false);
269 }
270 
271 }  // namespace android_webview
272