ProfilePolicyConnectorFactory: Refactoring from Profile to BrowserContext.
[chromium-blink-merge.git] / android_webview / browser / shared_renderer_state.cc
blob119b7fdf184bbc385785d2f957cc1a24f4cf365a
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.
5 #include "android_webview/browser/shared_renderer_state.h"
7 #include "android_webview/browser/browser_view_renderer.h"
8 #include "android_webview/browser/deferred_gpu_command_service.h"
9 #include "android_webview/browser/hardware_renderer.h"
10 #include "android_webview/browser/scoped_app_gl_state_restore.h"
11 #include "android_webview/public/browser/draw_gl.h"
12 #include "base/bind.h"
13 #include "base/lazy_instance.h"
14 #include "base/location.h"
15 #include "base/trace_event/trace_event_argument.h"
17 namespace android_webview {
19 namespace internal {
21 class RequestDrawGLTracker {
22 public:
23 RequestDrawGLTracker();
24 bool ShouldRequestOnNonUiThread(SharedRendererState* state);
25 bool ShouldRequestOnUiThread(SharedRendererState* state);
26 void ResetPending();
27 void SetQueuedFunctorOnUi(SharedRendererState* state);
29 private:
30 base::Lock lock_;
31 SharedRendererState* pending_ui_;
32 SharedRendererState* pending_non_ui_;
35 RequestDrawGLTracker::RequestDrawGLTracker()
36 : pending_ui_(NULL), pending_non_ui_(NULL) {
39 bool RequestDrawGLTracker::ShouldRequestOnNonUiThread(
40 SharedRendererState* state) {
41 base::AutoLock lock(lock_);
42 if (pending_ui_ || pending_non_ui_)
43 return false;
44 pending_non_ui_ = state;
45 return true;
48 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) {
49 base::AutoLock lock(lock_);
50 if (pending_non_ui_) {
51 pending_non_ui_->ResetRequestDrawGLCallback();
52 pending_non_ui_ = NULL;
54 // At this time, we could have already called RequestDrawGL on the UI thread,
55 // but the corresponding GL mode process hasn't happened yet. In this case,
56 // don't schedule another requestDrawGL on the UI thread.
57 if (pending_ui_)
58 return false;
59 pending_ui_ = state;
60 return true;
63 void RequestDrawGLTracker::ResetPending() {
64 base::AutoLock lock(lock_);
65 pending_non_ui_ = NULL;
66 pending_ui_ = NULL;
69 void RequestDrawGLTracker::SetQueuedFunctorOnUi(SharedRendererState* state) {
70 base::AutoLock lock(lock_);
71 DCHECK(state);
72 pending_ui_ = state;
73 pending_non_ui_ = NULL;
76 } // namespace internal
78 namespace {
80 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker =
81 LAZY_INSTANCE_INITIALIZER;
85 SharedRendererState::SharedRendererState(
86 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop,
87 BrowserViewRenderer* browser_view_renderer)
88 : ui_loop_(ui_loop),
89 browser_view_renderer_(browser_view_renderer),
90 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()),
91 force_commit_(false),
92 inside_hardware_release_(false),
93 needs_force_invalidate_on_next_draw_gl_(false),
94 weak_factory_on_ui_thread_(this) {
95 DCHECK(ui_loop_->BelongsToCurrentThread());
96 DCHECK(browser_view_renderer_);
97 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr();
98 ResetRequestDrawGLCallback();
101 SharedRendererState::~SharedRendererState() {
102 DCHECK(ui_loop_->BelongsToCurrentThread());
103 DCHECK(!hardware_renderer_.get());
106 void SharedRendererState::ClientRequestDrawGL() {
107 if (ui_loop_->BelongsToCurrentThread()) {
108 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
109 return;
110 ClientRequestDrawGLOnUI();
111 } else {
112 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNonUiThread(this))
113 return;
114 base::Closure callback;
116 base::AutoLock lock(lock_);
117 callback = request_draw_gl_closure_;
119 ui_loop_->PostTask(FROM_HERE, callback);
123 void SharedRendererState::DidDrawGLProcess() {
124 g_request_draw_gl_tracker.Get().ResetPending();
127 void SharedRendererState::ResetRequestDrawGLCallback() {
128 DCHECK(ui_loop_->BelongsToCurrentThread());
129 base::AutoLock lock(lock_);
130 request_draw_gl_cancelable_closure_.Reset(base::Bind(
131 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this)));
132 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
135 void SharedRendererState::ClientRequestDrawGLOnUI() {
136 DCHECK(ui_loop_->BelongsToCurrentThread());
137 ResetRequestDrawGLCallback();
138 g_request_draw_gl_tracker.Get().SetQueuedFunctorOnUi(this);
139 if (!browser_view_renderer_->RequestDrawGL(false)) {
140 g_request_draw_gl_tracker.Get().ResetPending();
141 LOG(ERROR) << "Failed to request GL process. Deadlock likely";
145 void SharedRendererState::UpdateParentDrawConstraintsOnUI() {
146 DCHECK(ui_loop_->BelongsToCurrentThread());
147 browser_view_renderer_->UpdateParentDrawConstraints();
150 void SharedRendererState::SetScrollOffsetOnUI(gfx::Vector2d scroll_offset) {
151 base::AutoLock lock(lock_);
152 scroll_offset_ = scroll_offset;
155 gfx::Vector2d SharedRendererState::GetScrollOffsetOnRT() {
156 base::AutoLock lock(lock_);
157 return scroll_offset_;
160 bool SharedRendererState::HasCompositorFrameOnUI() const {
161 base::AutoLock lock(lock_);
162 return compositor_frame_.get();
165 void SharedRendererState::SetCompositorFrameOnUI(
166 scoped_ptr<cc::CompositorFrame> frame,
167 bool force_commit) {
168 base::AutoLock lock(lock_);
169 DCHECK(!compositor_frame_.get());
170 compositor_frame_ = frame.Pass();
171 force_commit_ = force_commit;
174 scoped_ptr<cc::CompositorFrame> SharedRendererState::PassCompositorFrameOnRT() {
175 base::AutoLock lock(lock_);
176 return compositor_frame_.Pass();
179 scoped_ptr<cc::CompositorFrame>
180 SharedRendererState::PassUncommittedFrameOnUI() {
181 base::AutoLock lock(lock_);
182 return compositor_frame_.Pass();
185 bool SharedRendererState::ForceCommitOnRT() const {
186 base::AutoLock lock(lock_);
187 return force_commit_;
190 bool SharedRendererState::UpdateDrawConstraintsOnRT(
191 const ParentCompositorDrawConstraints& parent_draw_constraints) {
192 base::AutoLock lock(lock_);
193 if (needs_force_invalidate_on_next_draw_gl_ ||
194 !parent_draw_constraints_.Equals(parent_draw_constraints)) {
195 parent_draw_constraints_ = parent_draw_constraints;
196 return true;
199 return false;
202 void SharedRendererState::PostExternalDrawConstraintsToChildCompositorOnRT(
203 const ParentCompositorDrawConstraints& parent_draw_constraints) {
204 if (UpdateDrawConstraintsOnRT(parent_draw_constraints)) {
205 // No need to hold the lock_ during the post task.
206 ui_loop_->PostTask(
207 FROM_HERE,
208 base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUI,
209 ui_thread_weak_ptr_));
213 void SharedRendererState::DidSkipCommitFrameOnRT() {
214 ui_loop_->PostTask(FROM_HERE,
215 base::Bind(&SharedRendererState::DidSkipCommitFrameOnUI,
216 ui_thread_weak_ptr_));
219 void SharedRendererState::DidSkipCommitFrameOnUI() {
220 DCHECK(ui_loop_->BelongsToCurrentThread());
221 browser_view_renderer_->DidSkipCommitFrame();
224 ParentCompositorDrawConstraints
225 SharedRendererState::GetParentDrawConstraintsOnUI() const {
226 base::AutoLock lock(lock_);
227 return parent_draw_constraints_;
230 void SharedRendererState::SetForceInvalidateOnNextDrawGLOnUI(
231 bool needs_force_invalidate_on_next_draw_gl) {
232 base::AutoLock lock(lock_);
233 needs_force_invalidate_on_next_draw_gl_ =
234 needs_force_invalidate_on_next_draw_gl;
237 bool SharedRendererState::NeedsForceInvalidateOnNextDrawGLOnUI() const {
238 base::AutoLock lock(lock_);
239 return needs_force_invalidate_on_next_draw_gl_;
242 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
243 base::AutoLock lock(lock_);
244 inside_hardware_release_ = inside;
247 bool SharedRendererState::IsInsideHardwareRelease() const {
248 base::AutoLock lock(lock_);
249 return inside_hardware_release_;
252 void SharedRendererState::InsertReturnedResourcesOnRT(
253 const cc::ReturnedResourceArray& resources) {
254 base::AutoLock lock(lock_);
255 returned_resources_.insert(
256 returned_resources_.end(), resources.begin(), resources.end());
259 void SharedRendererState::SwapReturnedResourcesOnUI(
260 cc::ReturnedResourceArray* resources) {
261 DCHECK(resources->empty());
262 base::AutoLock lock(lock_);
263 resources->swap(returned_resources_);
266 bool SharedRendererState::ReturnedResourcesEmptyOnUI() const {
267 base::AutoLock lock(lock_);
268 return returned_resources_.empty();
271 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) {
272 TRACE_EVENT0("android_webview", "DrawFunctor");
273 if (draw_info->mode == AwDrawGLInfo::kModeSync) {
274 TRACE_EVENT_INSTANT0("android_webview", "kModeSync",
275 TRACE_EVENT_SCOPE_THREAD);
276 if (hardware_renderer_)
277 hardware_renderer_->CommitFrame();
278 return;
281 // kModeProcessNoContext should never happen because we tear down hardware
282 // in onTrimMemory. However that guarantee is maintained outside of chromium
283 // code. Not notifying shared state in kModeProcessNoContext can lead to
284 // immediate deadlock, which is slightly more catastrophic than leaks or
285 // corruption.
286 if (draw_info->mode == AwDrawGLInfo::kModeProcess ||
287 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
288 DidDrawGLProcess();
292 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
293 base::AutoLock lock(lock_);
294 if (renderer_manager_key_ != manager->NullKey()) {
295 manager->DidDrawGL(renderer_manager_key_);
299 ScopedAppGLStateRestore state_restore(
300 draw_info->mode == AwDrawGLInfo::kModeDraw
301 ? ScopedAppGLStateRestore::MODE_DRAW
302 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
303 ScopedAllowGL allow_gl;
305 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
306 LOG(ERROR) << "Received unexpected kModeProcessNoContext";
309 if (IsInsideHardwareRelease()) {
310 hardware_renderer_.reset();
311 // Flush the idle queue in tear down.
312 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork();
313 return;
316 if (draw_info->mode != AwDrawGLInfo::kModeDraw) {
317 if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
318 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true);
320 return;
323 if (!hardware_renderer_) {
324 hardware_renderer_.reset(new HardwareRenderer(this));
325 hardware_renderer_->CommitFrame();
328 hardware_renderer_->DrawGL(state_restore.stencil_enabled(),
329 state_restore.framebuffer_binding_ext(),
330 draw_info);
331 DeferredGpuCommandService::GetInstance()->PerformIdleWork(false);
334 void SharedRendererState::ReleaseHardwareDrawIfNeededOnUI() {
335 DCHECK(ui_loop_->BelongsToCurrentThread());
336 InsideHardwareReleaseReset auto_inside_hardware_release_reset(this);
338 browser_view_renderer_->DetachFunctorFromView();
339 bool hardware_initialized = browser_view_renderer_->hardware_enabled();
340 if (hardware_initialized) {
341 bool draw_functor_succeeded = browser_view_renderer_->RequestDrawGL(true);
342 if (!draw_functor_succeeded) {
343 LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
344 // Calling release on wrong thread intentionally.
345 AwDrawGLInfo info;
346 info.mode = AwDrawGLInfo::kModeProcess;
347 DrawGL(&info);
350 browser_view_renderer_->ReleaseHardware();
353 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
356 base::AutoLock lock(lock_);
357 if (renderer_manager_key_ != manager->NullKey()) {
358 manager->Remove(renderer_manager_key_);
359 renderer_manager_key_ = manager->NullKey();
363 if (hardware_initialized) {
364 // Flush any invoke functors that's caused by ReleaseHardware.
365 browser_view_renderer_->RequestDrawGL(true);
369 void SharedRendererState::InitializeHardwareDrawIfNeededOnUI() {
370 DCHECK(ui_loop_->BelongsToCurrentThread());
371 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
373 base::AutoLock lock(lock_);
374 if (renderer_manager_key_ == manager->NullKey()) {
375 renderer_manager_key_ = manager->PushBack(this);
376 DeferredGpuCommandService::SetInstance();
380 SharedRendererState::InsideHardwareReleaseReset::InsideHardwareReleaseReset(
381 SharedRendererState* shared_renderer_state)
382 : shared_renderer_state_(shared_renderer_state) {
383 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
384 shared_renderer_state_->SetInsideHardwareRelease(true);
387 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
388 shared_renderer_state_->SetInsideHardwareRelease(false);
391 } // namespace android_webview