• 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 DidRequestOnUiThread();
22   void ResetPending();
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   if (pending_ui_)
50     return false;
51   pending_ui_ = state;
52   return true;
53 }
54 
ResetPending()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 
DrawGLInput()70 DrawGLInput::DrawGLInput() : width(0), height(0) {
71 }
72 
~DrawGLInput()73 DrawGLInput::~DrawGLInput() {
74 }
75 
SharedRendererState(scoped_refptr<base::MessageLoopProxy> ui_loop,BrowserViewRendererClient * client)76 SharedRendererState::SharedRendererState(
77     scoped_refptr<base::MessageLoopProxy> ui_loop,
78     BrowserViewRendererClient* client)
79     : ui_loop_(ui_loop),
80       client_on_ui_(client),
81       weak_factory_on_ui_thread_(this),
82       ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
83       inside_hardware_release_(false),
84       needs_force_invalidate_on_next_draw_gl_(false),
85       share_context_(NULL) {
86   DCHECK(ui_loop_->BelongsToCurrentThread());
87   DCHECK(client_on_ui_);
88   ResetRequestDrawGLCallback();
89 }
90 
~SharedRendererState()91 SharedRendererState::~SharedRendererState() {
92   DCHECK(ui_loop_->BelongsToCurrentThread());
93 }
94 
ClientRequestDrawGL()95 void SharedRendererState::ClientRequestDrawGL() {
96   if (ui_loop_->BelongsToCurrentThread()) {
97     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
98       return;
99     ClientRequestDrawGLOnUIThread();
100   } else {
101     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNoneUiThread(this))
102       return;
103     base::Closure callback;
104     {
105       base::AutoLock lock(lock_);
106       callback = request_draw_gl_closure_;
107     }
108     ui_loop_->PostTask(FROM_HERE, callback);
109   }
110 }
111 
DidDrawGLProcess()112 void SharedRendererState::DidDrawGLProcess() {
113   g_request_draw_gl_tracker.Get().ResetPending();
114 }
115 
ResetRequestDrawGLCallback()116 void SharedRendererState::ResetRequestDrawGLCallback() {
117   DCHECK(ui_loop_->BelongsToCurrentThread());
118   base::AutoLock lock(lock_);
119   request_draw_gl_cancelable_closure_.Reset(
120       base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread,
121                  base::Unretained(this)));
122   request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
123 }
124 
ClientRequestDrawGLOnUIThread()125 void SharedRendererState::ClientRequestDrawGLOnUIThread() {
126   DCHECK(ui_loop_->BelongsToCurrentThread());
127   ResetRequestDrawGLCallback();
128   if (!client_on_ui_->RequestDrawGL(NULL, false)) {
129     g_request_draw_gl_tracker.Get().ResetPending();
130     LOG(ERROR) << "Failed to request GL process. Deadlock likely";
131   }
132 }
133 
UpdateParentDrawConstraintsOnUIThread()134 void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() {
135   DCHECK(ui_loop_->BelongsToCurrentThread());
136   client_on_ui_->UpdateParentDrawConstraints();
137 }
138 
SetDrawGLInput(scoped_ptr<DrawGLInput> input)139 void SharedRendererState::SetDrawGLInput(scoped_ptr<DrawGLInput> input) {
140   base::AutoLock lock(lock_);
141   DCHECK(!draw_gl_input_.get());
142   draw_gl_input_ = input.Pass();
143 }
144 
PassDrawGLInput()145 scoped_ptr<DrawGLInput> SharedRendererState::PassDrawGLInput() {
146   base::AutoLock lock(lock_);
147   return draw_gl_input_.Pass();
148 }
149 
UpdateDrawConstraints(const ParentCompositorDrawConstraints & parent_draw_constraints)150 bool SharedRendererState::UpdateDrawConstraints(
151     const ParentCompositorDrawConstraints& parent_draw_constraints) {
152   base::AutoLock lock(lock_);
153   if (needs_force_invalidate_on_next_draw_gl_ ||
154       !parent_draw_constraints_.Equals(parent_draw_constraints)) {
155     parent_draw_constraints_ = parent_draw_constraints;
156     return true;
157   }
158 
159   return false;
160 }
161 
PostExternalDrawConstraintsToChildCompositor(const ParentCompositorDrawConstraints & parent_draw_constraints)162 void SharedRendererState::PostExternalDrawConstraintsToChildCompositor(
163     const ParentCompositorDrawConstraints& parent_draw_constraints) {
164   if (UpdateDrawConstraints(parent_draw_constraints)) {
165     // No need to hold the lock_ during the post task.
166     ui_loop_->PostTask(
167         FROM_HERE,
168         base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread,
169                    ui_thread_weak_ptr_));
170   }
171 }
172 
173 const ParentCompositorDrawConstraints
ParentDrawConstraints() const174 SharedRendererState::ParentDrawConstraints() const {
175   base::AutoLock lock(lock_);
176   return parent_draw_constraints_;
177 }
178 
SetForceInvalidateOnNextDrawGL(bool needs_force_invalidate_on_next_draw_gl)179 void SharedRendererState::SetForceInvalidateOnNextDrawGL(
180     bool needs_force_invalidate_on_next_draw_gl) {
181   base::AutoLock lock(lock_);
182   needs_force_invalidate_on_next_draw_gl_ =
183       needs_force_invalidate_on_next_draw_gl;
184 }
185 
NeedsForceInvalidateOnNextDrawGL() const186 bool SharedRendererState::NeedsForceInvalidateOnNextDrawGL() const {
187   base::AutoLock lock(lock_);
188   return needs_force_invalidate_on_next_draw_gl_;
189 }
190 
SetInsideHardwareRelease(bool inside)191 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
192   base::AutoLock lock(lock_);
193   inside_hardware_release_ = inside;
194 }
195 
IsInsideHardwareRelease() const196 bool SharedRendererState::IsInsideHardwareRelease() const {
197   base::AutoLock lock(lock_);
198   return inside_hardware_release_;
199 }
200 
SetSharedContext(gpu::GLInProcessContext * context)201 void SharedRendererState::SetSharedContext(gpu::GLInProcessContext* context) {
202   base::AutoLock lock(lock_);
203   DCHECK(!share_context_ || !context);
204   share_context_ = context;
205 }
206 
GetSharedContext() const207 gpu::GLInProcessContext* SharedRendererState::GetSharedContext() const {
208   base::AutoLock lock(lock_);
209   DCHECK(share_context_);
210   return share_context_;
211 }
212 
InsertReturnedResources(const cc::ReturnedResourceArray & resources)213 void SharedRendererState::InsertReturnedResources(
214     const cc::ReturnedResourceArray& resources) {
215   base::AutoLock lock(lock_);
216   returned_resources_.insert(
217       returned_resources_.end(), resources.begin(), resources.end());
218 }
219 
SwapReturnedResources(cc::ReturnedResourceArray * resources)220 void SharedRendererState::SwapReturnedResources(
221     cc::ReturnedResourceArray* resources) {
222   DCHECK(resources->empty());
223   base::AutoLock lock(lock_);
224   resources->swap(returned_resources_);
225 }
226 
ReturnedResourcesEmpty() const227 bool SharedRendererState::ReturnedResourcesEmpty() const {
228   base::AutoLock lock(lock_);
229   return returned_resources_.empty();
230 }
231 
InsideHardwareReleaseReset(SharedRendererState * shared_renderer_state)232 InsideHardwareReleaseReset::InsideHardwareReleaseReset(
233     SharedRendererState* shared_renderer_state)
234     : shared_renderer_state_(shared_renderer_state) {
235   DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
236   shared_renderer_state_->SetInsideHardwareRelease(true);
237 }
238 
~InsideHardwareReleaseReset()239 InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
240   shared_renderer_state_->SetInsideHardwareRelease(false);
241 }
242 
243 }  // namespace android_webview
244