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_client.h"
9 #include "base/lazy_instance.h"
10 #include "base/location.h"
12 namespace android_webview
{
16 class RequestDrawGLTracker
{
18 RequestDrawGLTracker();
19 bool ShouldRequestOnNoneUiThread(SharedRendererState
* state
);
20 bool ShouldRequestOnUiThread(SharedRendererState
* state
);
21 void DidRequestOnUiThread();
26 SharedRendererState
* pending_ui_
;
27 SharedRendererState
* pending_non_ui_
;
30 RequestDrawGLTracker::RequestDrawGLTracker()
31 : pending_ui_(NULL
), pending_non_ui_(NULL
) {
34 bool RequestDrawGLTracker::ShouldRequestOnNoneUiThread(
35 SharedRendererState
* state
) {
36 base::AutoLock
lock(lock_
);
37 if (pending_ui_
|| pending_non_ui_
)
39 pending_non_ui_
= 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
;
55 void RequestDrawGLTracker::ResetPending() {
56 base::AutoLock
lock(lock_
);
57 pending_non_ui_
= NULL
;
61 } // namespace internal
65 base::LazyInstance
<internal::RequestDrawGLTracker
> g_request_draw_gl_tracker
=
66 LAZY_INSTANCE_INITIALIZER
;
70 DrawGLInput::DrawGLInput() : width(0), height(0) {
73 DrawGLInput::~DrawGLInput() {
76 SharedRendererState::SharedRendererState(
77 scoped_refptr
<base::MessageLoopProxy
> ui_loop
,
78 BrowserViewRendererClient
* client
)
80 client_on_ui_(client
),
81 inside_hardware_release_(false),
82 weak_factory_on_ui_thread_(this){
83 DCHECK(ui_loop_
->BelongsToCurrentThread());
84 DCHECK(client_on_ui_
);
85 ui_thread_weak_ptr_
= weak_factory_on_ui_thread_
.GetWeakPtr();
86 ResetRequestDrawGLCallback();
89 SharedRendererState::~SharedRendererState() {
90 DCHECK(ui_loop_
->BelongsToCurrentThread());
93 void SharedRendererState::ClientRequestDrawGL() {
94 if (ui_loop_
->BelongsToCurrentThread()) {
95 if (!g_request_draw_gl_tracker
.Get().ShouldRequestOnUiThread(this))
97 ClientRequestDrawGLOnUIThread();
99 if (!g_request_draw_gl_tracker
.Get().ShouldRequestOnNoneUiThread(this))
101 base::Closure callback
;
103 base::AutoLock
lock(lock_
);
104 callback
= request_draw_gl_closure_
;
106 ui_loop_
->PostTask(FROM_HERE
, callback
);
110 void SharedRendererState::DidDrawGLProcess() {
111 g_request_draw_gl_tracker
.Get().ResetPending();
114 void SharedRendererState::ResetRequestDrawGLCallback() {
115 DCHECK(ui_loop_
->BelongsToCurrentThread());
116 base::AutoLock
lock(lock_
);
117 request_draw_gl_cancelable_closure_
.Reset(
118 base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread
,
119 base::Unretained(this)));
120 request_draw_gl_closure_
= request_draw_gl_cancelable_closure_
.callback();
123 void SharedRendererState::ClientRequestDrawGLOnUIThread() {
124 DCHECK(ui_loop_
->BelongsToCurrentThread());
125 ResetRequestDrawGLCallback();
126 if (!client_on_ui_
->RequestDrawGL(NULL
, false)) {
127 g_request_draw_gl_tracker
.Get().ResetPending();
128 LOG(ERROR
) << "Failed to request GL process. Deadlock likely";
132 void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() {
133 DCHECK(ui_loop_
->BelongsToCurrentThread());
134 client_on_ui_
->UpdateParentDrawConstraints();
137 void SharedRendererState::SetDrawGLInput(scoped_ptr
<DrawGLInput
> input
) {
138 base::AutoLock
lock(lock_
);
139 DCHECK(!draw_gl_input_
.get());
140 draw_gl_input_
= input
.Pass();
143 scoped_ptr
<DrawGLInput
> SharedRendererState::PassDrawGLInput() {
144 base::AutoLock
lock(lock_
);
145 return draw_gl_input_
.Pass();
148 void SharedRendererState::UpdateDrawConstraints(
149 const ParentCompositorDrawConstraints
& parent_draw_constraints
) {
150 base::AutoLock
lock(lock_
);
151 parent_draw_constraints_
= parent_draw_constraints
;
154 void SharedRendererState::PostExternalDrawConstraintsToChildCompositor(
155 const ParentCompositorDrawConstraints
& parent_draw_constraints
) {
156 UpdateDrawConstraints(parent_draw_constraints
);
158 // No need to hold the lock_ during the post task.
161 base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread
,
162 ui_thread_weak_ptr_
));
165 const ParentCompositorDrawConstraints
166 SharedRendererState::ParentDrawConstraints() const {
167 base::AutoLock
lock(lock_
);
168 return parent_draw_constraints_
;
171 void SharedRendererState::SetInsideHardwareRelease(bool inside
) {
172 base::AutoLock
lock(lock_
);
173 inside_hardware_release_
= inside
;
176 bool SharedRendererState::IsInsideHardwareRelease() const {
177 base::AutoLock
lock(lock_
);
178 return inside_hardware_release_
;
181 void SharedRendererState::InsertReturnedResources(
182 const cc::ReturnedResourceArray
& resources
) {
183 base::AutoLock
lock(lock_
);
184 returned_resources_
.insert(
185 returned_resources_
.end(), resources
.begin(), resources
.end());
188 void SharedRendererState::SwapReturnedResources(
189 cc::ReturnedResourceArray
* resources
) {
190 DCHECK(resources
->empty());
191 base::AutoLock
lock(lock_
);
192 resources
->swap(returned_resources_
);
195 bool SharedRendererState::ReturnedResourcesEmpty() const {
196 base::AutoLock
lock(lock_
);
197 return returned_resources_
.empty();
200 InsideHardwareReleaseReset::InsideHardwareReleaseReset(
201 SharedRendererState
* shared_renderer_state
)
202 : shared_renderer_state_(shared_renderer_state
) {
203 DCHECK(!shared_renderer_state_
->IsInsideHardwareRelease());
204 shared_renderer_state_
->SetInsideHardwareRelease(true);
207 InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
208 shared_renderer_state_
->SetInsideHardwareRelease(false);
211 } // namespace android_webview