Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / android_webview / browser / shared_renderer_state.cc
blob825843e6942256f33bfae5ed4fd5dca9332923fb
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/child_frame.h"
9 #include "android_webview/browser/deferred_gpu_command_service.h"
10 #include "android_webview/browser/hardware_renderer.h"
11 #include "android_webview/browser/scoped_app_gl_state_restore.h"
12 #include "android_webview/public/browser/draw_gl.h"
13 #include "base/bind.h"
14 #include "base/lazy_instance.h"
15 #include "base/location.h"
16 #include "base/trace_event/trace_event_argument.h"
18 namespace android_webview {
20 namespace internal {
22 class RequestDrawGLTracker {
23 public:
24 RequestDrawGLTracker();
25 bool ShouldRequestOnNonUiThread(SharedRendererState* state);
26 bool ShouldRequestOnUiThread(SharedRendererState* state);
27 void ResetPending();
28 void SetQueuedFunctorOnUi(SharedRendererState* state);
30 private:
31 base::Lock lock_;
32 SharedRendererState* pending_ui_;
33 SharedRendererState* pending_non_ui_;
36 RequestDrawGLTracker::RequestDrawGLTracker()
37 : pending_ui_(NULL), pending_non_ui_(NULL) {
40 bool RequestDrawGLTracker::ShouldRequestOnNonUiThread(
41 SharedRendererState* state) {
42 base::AutoLock lock(lock_);
43 if (pending_ui_ || pending_non_ui_)
44 return false;
45 pending_non_ui_ = state;
46 return true;
49 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) {
50 base::AutoLock lock(lock_);
51 if (pending_non_ui_) {
52 pending_non_ui_->ResetRequestDrawGLCallback();
53 pending_non_ui_ = NULL;
55 // At this time, we could have already called RequestDrawGL on the UI thread,
56 // but the corresponding GL mode process hasn't happened yet. In this case,
57 // don't schedule another requestDrawGL on the UI thread.
58 if (pending_ui_)
59 return false;
60 pending_ui_ = state;
61 return true;
64 void RequestDrawGLTracker::ResetPending() {
65 base::AutoLock lock(lock_);
66 pending_non_ui_ = NULL;
67 pending_ui_ = NULL;
70 void RequestDrawGLTracker::SetQueuedFunctorOnUi(SharedRendererState* state) {
71 base::AutoLock lock(lock_);
72 DCHECK(state);
73 pending_ui_ = state;
74 pending_non_ui_ = NULL;
77 } // namespace internal
79 namespace {
81 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker =
82 LAZY_INSTANCE_INITIALIZER;
86 SharedRendererState::SharedRendererState(
87 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop,
88 BrowserViewRenderer* browser_view_renderer)
89 : ui_loop_(ui_loop),
90 browser_view_renderer_(browser_view_renderer),
91 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()),
92 inside_hardware_release_(false),
93 weak_factory_on_ui_thread_(this) {
94 DCHECK(ui_loop_->BelongsToCurrentThread());
95 DCHECK(browser_view_renderer_);
96 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr();
97 ResetRequestDrawGLCallback();
100 SharedRendererState::~SharedRendererState() {
101 DCHECK(ui_loop_->BelongsToCurrentThread());
102 DCHECK(!hardware_renderer_.get());
105 void SharedRendererState::ClientRequestDrawGL() {
106 if (ui_loop_->BelongsToCurrentThread()) {
107 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
108 return;
109 ClientRequestDrawGLOnUI();
110 } else {
111 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNonUiThread(this))
112 return;
113 base::Closure callback;
115 base::AutoLock lock(lock_);
116 callback = request_draw_gl_closure_;
118 ui_loop_->PostTask(FROM_HERE, callback);
122 void SharedRendererState::DidDrawGLProcess() {
123 g_request_draw_gl_tracker.Get().ResetPending();
126 void SharedRendererState::ResetRequestDrawGLCallback() {
127 DCHECK(ui_loop_->BelongsToCurrentThread());
128 base::AutoLock lock(lock_);
129 request_draw_gl_cancelable_closure_.Reset(base::Bind(
130 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this)));
131 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
134 void SharedRendererState::ClientRequestDrawGLOnUI() {
135 DCHECK(ui_loop_->BelongsToCurrentThread());
136 ResetRequestDrawGLCallback();
137 g_request_draw_gl_tracker.Get().SetQueuedFunctorOnUi(this);
138 if (!browser_view_renderer_->RequestDrawGL(false)) {
139 g_request_draw_gl_tracker.Get().ResetPending();
140 LOG(ERROR) << "Failed to request GL process. Deadlock likely";
144 void SharedRendererState::UpdateParentDrawConstraintsOnUI() {
145 DCHECK(ui_loop_->BelongsToCurrentThread());
146 browser_view_renderer_->UpdateParentDrawConstraints();
149 void SharedRendererState::SetScrollOffsetOnUI(gfx::Vector2d scroll_offset) {
150 base::AutoLock lock(lock_);
151 scroll_offset_ = scroll_offset;
154 gfx::Vector2d SharedRendererState::GetScrollOffsetOnRT() {
155 base::AutoLock lock(lock_);
156 return scroll_offset_;
159 void SharedRendererState::SetCompositorFrameOnUI(scoped_ptr<ChildFrame> frame) {
160 base::AutoLock lock(lock_);
161 DCHECK(!child_frame_.get());
162 child_frame_ = frame.Pass();
165 scoped_ptr<ChildFrame> SharedRendererState::PassCompositorFrameOnRT() {
166 base::AutoLock lock(lock_);
167 return child_frame_.Pass();
170 scoped_ptr<ChildFrame> SharedRendererState::PassUncommittedFrameOnUI() {
171 base::AutoLock lock(lock_);
172 return child_frame_.Pass();
175 void SharedRendererState::PostExternalDrawConstraintsToChildCompositorOnRT(
176 const ParentCompositorDrawConstraints& parent_draw_constraints) {
178 base::AutoLock lock(lock_);
179 parent_draw_constraints_ = parent_draw_constraints;
182 // No need to hold the lock_ during the post task.
183 ui_loop_->PostTask(
184 FROM_HERE,
185 base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUI,
186 ui_thread_weak_ptr_));
189 ParentCompositorDrawConstraints
190 SharedRendererState::GetParentDrawConstraintsOnUI() const {
191 base::AutoLock lock(lock_);
192 return parent_draw_constraints_;
195 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
196 base::AutoLock lock(lock_);
197 inside_hardware_release_ = inside;
200 bool SharedRendererState::IsInsideHardwareRelease() const {
201 base::AutoLock lock(lock_);
202 return inside_hardware_release_;
205 void SharedRendererState::InsertReturnedResourcesOnRT(
206 const cc::ReturnedResourceArray& resources) {
207 base::AutoLock lock(lock_);
208 returned_resources_.insert(
209 returned_resources_.end(), resources.begin(), resources.end());
212 void SharedRendererState::SwapReturnedResourcesOnUI(
213 cc::ReturnedResourceArray* resources) {
214 DCHECK(resources->empty());
215 base::AutoLock lock(lock_);
216 resources->swap(returned_resources_);
219 bool SharedRendererState::ReturnedResourcesEmptyOnUI() const {
220 base::AutoLock lock(lock_);
221 return returned_resources_.empty();
224 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) {
225 TRACE_EVENT0("android_webview", "DrawFunctor");
226 if (draw_info->mode == AwDrawGLInfo::kModeSync) {
227 TRACE_EVENT_INSTANT0("android_webview", "kModeSync",
228 TRACE_EVENT_SCOPE_THREAD);
229 if (hardware_renderer_)
230 hardware_renderer_->CommitFrame();
231 return;
234 // kModeProcessNoContext should never happen because we tear down hardware
235 // in onTrimMemory. However that guarantee is maintained outside of chromium
236 // code. Not notifying shared state in kModeProcessNoContext can lead to
237 // immediate deadlock, which is slightly more catastrophic than leaks or
238 // corruption.
239 if (draw_info->mode == AwDrawGLInfo::kModeProcess ||
240 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
241 DidDrawGLProcess();
245 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
246 base::AutoLock lock(lock_);
247 if (renderer_manager_key_ != manager->NullKey()) {
248 manager->DidDrawGL(renderer_manager_key_);
252 ScopedAppGLStateRestore state_restore(
253 draw_info->mode == AwDrawGLInfo::kModeDraw
254 ? ScopedAppGLStateRestore::MODE_DRAW
255 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
256 ScopedAllowGL allow_gl;
258 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
259 LOG(ERROR) << "Received unexpected kModeProcessNoContext";
262 if (IsInsideHardwareRelease()) {
263 hardware_renderer_.reset();
264 // Flush the idle queue in tear down.
265 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork();
266 return;
269 if (draw_info->mode != AwDrawGLInfo::kModeDraw) {
270 if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
271 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true);
273 return;
276 if (!hardware_renderer_) {
277 hardware_renderer_.reset(new HardwareRenderer(this));
278 hardware_renderer_->CommitFrame();
281 hardware_renderer_->DrawGL(state_restore.stencil_enabled(),
282 state_restore.framebuffer_binding_ext(),
283 draw_info);
284 DeferredGpuCommandService::GetInstance()->PerformIdleWork(false);
287 void SharedRendererState::ReleaseHardwareDrawIfNeededOnUI() {
288 ReleaseCompositorResourcesIfNeededOnUI(true);
291 void SharedRendererState::DeleteHardwareRendererOnUI() {
292 ReleaseCompositorResourcesIfNeededOnUI(false);
295 void SharedRendererState::ReleaseCompositorResourcesIfNeededOnUI(
296 bool release_hardware_draw) {
297 DCHECK(ui_loop_->BelongsToCurrentThread());
298 InsideHardwareReleaseReset auto_inside_hardware_release_reset(this);
300 browser_view_renderer_->DetachFunctorFromView();
301 bool hardware_initialized = browser_view_renderer_->hardware_enabled();
302 // If the WebView gets onTrimMemory >= MODERATE twice in a row, the 2nd
303 // onTrimMemory will result in an unnecessary Render Thread DrawGL call.
304 if (hardware_initialized) {
305 bool draw_functor_succeeded = browser_view_renderer_->RequestDrawGL(true);
306 if (!draw_functor_succeeded) {
307 LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
308 // Calling release on wrong thread intentionally.
309 AwDrawGLInfo info;
310 info.mode = AwDrawGLInfo::kModeProcess;
311 DrawGL(&info);
314 if (release_hardware_draw)
315 browser_view_renderer_->ReleaseHardware();
318 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
321 base::AutoLock lock(lock_);
322 if (renderer_manager_key_ != manager->NullKey()) {
323 manager->Remove(renderer_manager_key_);
324 renderer_manager_key_ = manager->NullKey();
328 if (hardware_initialized) {
329 // Flush any invoke functors that's caused by ReleaseHardware.
330 browser_view_renderer_->RequestDrawGL(true);
334 void SharedRendererState::InitializeHardwareDrawIfNeededOnUI() {
335 DCHECK(ui_loop_->BelongsToCurrentThread());
336 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
338 base::AutoLock lock(lock_);
339 if (renderer_manager_key_ == manager->NullKey()) {
340 renderer_manager_key_ = manager->PushBack(this);
341 DeferredGpuCommandService::SetInstance();
345 SharedRendererState::InsideHardwareReleaseReset::InsideHardwareReleaseReset(
346 SharedRendererState* shared_renderer_state)
347 : shared_renderer_state_(shared_renderer_state) {
348 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
349 shared_renderer_state_->SetInsideHardwareRelease(true);
352 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
353 shared_renderer_state_->SetInsideHardwareRelease(false);
356 } // namespace android_webview