Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(530)

Side by Side Diff: android_webview/browser/shared_renderer_state.cc

Issue 1858853002: Rename SharedRendererState to RenderThreadManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <utility>
8
9 #include "android_webview/browser/child_frame.h"
10 #include "android_webview/browser/deferred_gpu_command_service.h"
11 #include "android_webview/browser/hardware_renderer.h"
12 #include "android_webview/browser/scoped_app_gl_state_restore.h"
13 #include "android_webview/browser/shared_renderer_state_client.h"
14 #include "android_webview/public/browser/draw_gl.h"
15 #include "base/bind.h"
16 #include "base/lazy_instance.h"
17 #include "base/location.h"
18 #include "base/time/time.h"
19 #include "base/trace_event/trace_event_argument.h"
20
21 namespace android_webview {
22
23 namespace internal {
24
25 class RequestDrawGLTracker {
26 public:
27 RequestDrawGLTracker();
28 bool ShouldRequestOnNonUiThread(SharedRendererState* state);
29 bool ShouldRequestOnUiThread(SharedRendererState* state);
30 void ResetPending();
31 void SetQueuedFunctorOnUi(SharedRendererState* state);
32
33 private:
34 base::Lock lock_;
35 SharedRendererState* pending_ui_;
36 SharedRendererState* pending_non_ui_;
37 };
38
39 RequestDrawGLTracker::RequestDrawGLTracker()
40 : pending_ui_(NULL), pending_non_ui_(NULL) {
41 }
42
43 bool RequestDrawGLTracker::ShouldRequestOnNonUiThread(
44 SharedRendererState* state) {
45 base::AutoLock lock(lock_);
46 if (pending_ui_ || pending_non_ui_)
47 return false;
48 pending_non_ui_ = state;
49 return true;
50 }
51
52 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) {
53 base::AutoLock lock(lock_);
54 if (pending_non_ui_) {
55 pending_non_ui_->ResetRequestDrawGLCallback();
56 pending_non_ui_ = NULL;
57 }
58 // At this time, we could have already called RequestDrawGL on the UI thread,
59 // but the corresponding GL mode process hasn't happened yet. In this case,
60 // don't schedule another requestDrawGL on the UI thread.
61 if (pending_ui_)
62 return false;
63 pending_ui_ = state;
64 return true;
65 }
66
67 void RequestDrawGLTracker::ResetPending() {
68 base::AutoLock lock(lock_);
69 pending_non_ui_ = NULL;
70 pending_ui_ = NULL;
71 }
72
73 void RequestDrawGLTracker::SetQueuedFunctorOnUi(SharedRendererState* state) {
74 base::AutoLock lock(lock_);
75 DCHECK(state);
76 pending_ui_ = state;
77 pending_non_ui_ = NULL;
78 }
79
80 } // namespace internal
81
82 namespace {
83
84 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker =
85 LAZY_INSTANCE_INITIALIZER;
86
87 }
88
89 SharedRendererState::SharedRendererState(
90 SharedRendererStateClient* client,
91 const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop)
92 : ui_loop_(ui_loop),
93 client_(client),
94 renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()),
95 hardware_renderer_has_frame_(false),
96 inside_hardware_release_(false),
97 weak_factory_on_ui_thread_(this) {
98 DCHECK(ui_loop_->BelongsToCurrentThread());
99 DCHECK(client_);
100 ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr();
101 ResetRequestDrawGLCallback();
102 }
103
104 SharedRendererState::~SharedRendererState() {
105 DCHECK(ui_loop_->BelongsToCurrentThread());
106 DCHECK(!hardware_renderer_.get());
107 }
108
109 void SharedRendererState::ClientRequestDrawGL(bool for_idle) {
110 if (ui_loop_->BelongsToCurrentThread()) {
111 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
112 return;
113 ClientRequestDrawGLOnUI();
114 } else {
115 if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNonUiThread(this))
116 return;
117 base::Closure callback;
118 {
119 base::AutoLock lock(lock_);
120 callback = request_draw_gl_closure_;
121 }
122 // 17ms is slightly longer than a frame, hoping that it will come
123 // after the next frame so that the idle work is taken care off by
124 // the next frame instead.
125 ui_loop_->PostDelayedTask(
126 FROM_HERE, callback,
127 for_idle ? base::TimeDelta::FromMilliseconds(17) : base::TimeDelta());
128 }
129 }
130
131 void SharedRendererState::DidDrawGLProcess() {
132 g_request_draw_gl_tracker.Get().ResetPending();
133 }
134
135 void SharedRendererState::ResetRequestDrawGLCallback() {
136 DCHECK(ui_loop_->BelongsToCurrentThread());
137 base::AutoLock lock(lock_);
138 request_draw_gl_cancelable_closure_.Reset(base::Bind(
139 &SharedRendererState::ClientRequestDrawGLOnUI, base::Unretained(this)));
140 request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
141 }
142
143 void SharedRendererState::ClientRequestDrawGLOnUI() {
144 DCHECK(ui_loop_->BelongsToCurrentThread());
145 ResetRequestDrawGLCallback();
146 g_request_draw_gl_tracker.Get().SetQueuedFunctorOnUi(this);
147 if (!client_->RequestDrawGL(false)) {
148 g_request_draw_gl_tracker.Get().ResetPending();
149 LOG(ERROR) << "Failed to request GL process. Deadlock likely";
150 }
151 }
152
153 void SharedRendererState::UpdateParentDrawConstraintsOnUI() {
154 DCHECK(ui_loop_->BelongsToCurrentThread());
155 client_->OnParentDrawConstraintsUpdated();
156 }
157
158 void SharedRendererState::SetScrollOffsetOnUI(gfx::Vector2d scroll_offset) {
159 base::AutoLock lock(lock_);
160 scroll_offset_ = scroll_offset;
161 }
162
163 gfx::Vector2d SharedRendererState::GetScrollOffsetOnRT() {
164 base::AutoLock lock(lock_);
165 return scroll_offset_;
166 }
167
168 void SharedRendererState::SetFrameOnUI(std::unique_ptr<ChildFrame> frame) {
169 base::AutoLock lock(lock_);
170 DCHECK(!child_frame_.get());
171 child_frame_ = std::move(frame);
172 }
173
174 std::unique_ptr<ChildFrame> SharedRendererState::PassFrameOnRT() {
175 base::AutoLock lock(lock_);
176 hardware_renderer_has_frame_ =
177 hardware_renderer_has_frame_ || child_frame_.get();
178 return std::move(child_frame_);
179 }
180
181 std::unique_ptr<ChildFrame> SharedRendererState::PassUncommittedFrameOnUI() {
182 base::AutoLock lock(lock_);
183 return std::move(child_frame_);
184 }
185
186 void SharedRendererState::PostExternalDrawConstraintsToChildCompositorOnRT(
187 const ParentCompositorDrawConstraints& parent_draw_constraints) {
188 {
189 base::AutoLock lock(lock_);
190 parent_draw_constraints_ = parent_draw_constraints;
191 }
192
193 // No need to hold the lock_ during the post task.
194 ui_loop_->PostTask(
195 FROM_HERE,
196 base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUI,
197 ui_thread_weak_ptr_));
198 }
199
200 ParentCompositorDrawConstraints
201 SharedRendererState::GetParentDrawConstraintsOnUI() const {
202 base::AutoLock lock(lock_);
203 return parent_draw_constraints_;
204 }
205
206 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
207 base::AutoLock lock(lock_);
208 inside_hardware_release_ = inside;
209 }
210
211 bool SharedRendererState::IsInsideHardwareRelease() const {
212 base::AutoLock lock(lock_);
213 return inside_hardware_release_;
214 }
215
216 SharedRendererState::ReturnedResources::ReturnedResources()
217 : output_surface_id(0u) {}
218
219 SharedRendererState::ReturnedResources::~ReturnedResources() {}
220
221 void SharedRendererState::InsertReturnedResourcesOnRT(
222 const cc::ReturnedResourceArray& resources,
223 uint32_t compositor_id,
224 uint32_t output_surface_id) {
225 base::AutoLock lock(lock_);
226 ReturnedResources& returned_resources =
227 returned_resources_map_[compositor_id];
228 if (returned_resources.output_surface_id != output_surface_id) {
229 returned_resources.resources.clear();
230 }
231 returned_resources.resources.insert(returned_resources.resources.end(),
232 resources.begin(), resources.end());
233 returned_resources.output_surface_id = output_surface_id;
234 }
235
236 void SharedRendererState::SwapReturnedResourcesOnUI(
237 ReturnedResourcesMap* returned_resource_map) {
238 DCHECK(returned_resource_map->empty());
239 base::AutoLock lock(lock_);
240 returned_resource_map->swap(returned_resources_map_);
241 }
242
243 bool SharedRendererState::ReturnedResourcesEmptyOnUI() const {
244 base::AutoLock lock(lock_);
245 return returned_resources_map_.empty();
246 }
247
248 void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) {
249 TRACE_EVENT0("android_webview", "DrawFunctor");
250 if (draw_info->mode == AwDrawGLInfo::kModeSync) {
251 TRACE_EVENT_INSTANT0("android_webview", "kModeSync",
252 TRACE_EVENT_SCOPE_THREAD);
253 if (hardware_renderer_)
254 hardware_renderer_->CommitFrame();
255 return;
256 }
257
258 // kModeProcessNoContext should never happen because we tear down hardware
259 // in onTrimMemory. However that guarantee is maintained outside of chromium
260 // code. Not notifying shared state in kModeProcessNoContext can lead to
261 // immediate deadlock, which is slightly more catastrophic than leaks or
262 // corruption.
263 if (draw_info->mode == AwDrawGLInfo::kModeProcess ||
264 draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
265 DidDrawGLProcess();
266 }
267
268 {
269 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
270 base::AutoLock lock(lock_);
271 if (renderer_manager_key_ != manager->NullKey()) {
272 manager->DidDrawGL(renderer_manager_key_);
273 }
274 }
275
276 ScopedAppGLStateRestore state_restore(
277 draw_info->mode == AwDrawGLInfo::kModeDraw
278 ? ScopedAppGLStateRestore::MODE_DRAW
279 : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
280 // Set the correct FBO before kModeDraw. The GL commands run in kModeDraw
281 // require a correctly bound FBO. The FBO remains until the next kModeDraw.
282 // So kModeProcess between kModeDraws has correctly bound FBO, too.
283 if (draw_info->mode == AwDrawGLInfo::kModeDraw) {
284 if (!hardware_renderer_) {
285 hardware_renderer_.reset(new HardwareRenderer(this));
286 hardware_renderer_->CommitFrame();
287 }
288 hardware_renderer_->SetBackingFrameBufferObject(
289 state_restore.framebuffer_binding_ext());
290 }
291
292 ScopedAllowGL allow_gl;
293
294 if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
295 LOG(ERROR) << "Received unexpected kModeProcessNoContext";
296 }
297
298 if (IsInsideHardwareRelease()) {
299 hardware_renderer_has_frame_ = false;
300 hardware_renderer_.reset();
301 // Flush the idle queue in tear down.
302 DeferredGpuCommandService::GetInstance()->PerformAllIdleWork();
303 return;
304 }
305
306 if (draw_info->mode != AwDrawGLInfo::kModeDraw) {
307 if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
308 DeferredGpuCommandService::GetInstance()->PerformIdleWork(true);
309 }
310 return;
311 }
312
313 hardware_renderer_->DrawGL(draw_info, state_restore);
314 DeferredGpuCommandService::GetInstance()->PerformIdleWork(false);
315 }
316
317 void SharedRendererState::DeleteHardwareRendererOnUI() {
318 DCHECK(ui_loop_->BelongsToCurrentThread());
319
320 InsideHardwareReleaseReset auto_inside_hardware_release_reset(this);
321
322 client_->DetachFunctorFromView();
323
324 // If the WebView gets onTrimMemory >= MODERATE twice in a row, the 2nd
325 // onTrimMemory will result in an unnecessary Render Thread DrawGL call.
326 bool hardware_initialized = HasFrameOnUI();
327 if (hardware_initialized) {
328 bool draw_functor_succeeded = client_->RequestDrawGL(true);
329 if (!draw_functor_succeeded) {
330 LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
331 // Calling release on wrong thread intentionally.
332 AwDrawGLInfo info;
333 info.mode = AwDrawGLInfo::kModeProcess;
334 DrawGL(&info);
335 }
336 }
337
338 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
339
340 {
341 base::AutoLock lock(lock_);
342 if (renderer_manager_key_ != manager->NullKey()) {
343 manager->Remove(renderer_manager_key_);
344 renderer_manager_key_ = manager->NullKey();
345 }
346 }
347
348 if (hardware_initialized) {
349 // Flush any invoke functors that's caused by ReleaseHardware.
350 client_->RequestDrawGL(true);
351 }
352 }
353
354 bool SharedRendererState::HasFrameOnUI() const {
355 base::AutoLock lock(lock_);
356 return hardware_renderer_has_frame_ || child_frame_.get();
357 }
358
359 void SharedRendererState::InitializeHardwareDrawIfNeededOnUI() {
360 DCHECK(ui_loop_->BelongsToCurrentThread());
361 GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
362
363 base::AutoLock lock(lock_);
364 if (renderer_manager_key_ == manager->NullKey()) {
365 renderer_manager_key_ = manager->PushBack(this);
366 }
367 }
368
369 SharedRendererState::InsideHardwareReleaseReset::InsideHardwareReleaseReset(
370 SharedRendererState* shared_renderer_state)
371 : shared_renderer_state_(shared_renderer_state) {
372 DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
373 shared_renderer_state_->SetInsideHardwareRelease(true);
374 }
375
376 SharedRendererState::InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
377 shared_renderer_state_->SetInsideHardwareRelease(false);
378 }
379
380 } // namespace android_webview
OLDNEW
« no previous file with comments | « android_webview/browser/shared_renderer_state.h ('k') | android_webview/browser/shared_renderer_state_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698