OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "android_webview/browser/hardware_renderer.h" | 5 #include "android_webview/browser/hardware_renderer.h" |
6 | 6 |
7 #include "android_webview/browser/aw_gl_surface.h" | 7 #include "android_webview/browser/aw_gl_surface.h" |
8 #include "android_webview/browser/browser_view_renderer_client.h" | 8 #include "android_webview/browser/browser_view_renderer_client.h" |
9 #include "android_webview/browser/scoped_app_gl_state_restore.h" | |
10 #include "android_webview/public/browser/draw_gl.h" | 9 #include "android_webview/public/browser/draw_gl.h" |
11 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
12 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
13 #include "content/public/browser/android/synchronous_compositor.h" | 12 #include "content/public/browser/android/synchronous_compositor.h" |
14 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
15 #include "gpu/command_buffer/service/shader_translator_cache.h" | 14 #include "gpu/command_buffer/service/shader_translator_cache.h" |
16 #include "ui/gfx/geometry/rect_conversions.h" | 15 #include "ui/gfx/geometry/rect_conversions.h" |
17 #include "ui/gfx/geometry/rect_f.h" | 16 #include "ui/gfx/geometry/rect_f.h" |
18 #include "ui/gfx/transform.h" | 17 #include "ui/gfx/transform.h" |
| 18 #include "ui/gl/gl_bindings.h" |
19 | 19 |
20 namespace android_webview { | 20 namespace android_webview { |
21 | 21 |
22 namespace { | |
23 | |
24 base::LazyInstance<scoped_refptr<internal::DeferredGpuCommandService> > | |
25 g_service = LAZY_INSTANCE_INITIALIZER; | |
26 | |
27 } // namespace | |
28 | |
29 HardwareRenderer::HardwareRenderer(SharedRendererState* state) | 22 HardwareRenderer::HardwareRenderer(SharedRendererState* state) |
30 : shared_renderer_state_(state), | 23 : shared_renderer_state_(state), |
31 last_egl_context_(eglGetCurrentContext()), | 24 last_egl_context_(eglGetCurrentContext()) { |
32 renderer_manager_key_(GLViewRendererManager::GetInstance()->PushBack( | |
33 shared_renderer_state_)) { | |
34 DCHECK(last_egl_context_); | 25 DCHECK(last_egl_context_); |
35 if (!g_service.Get()) { | |
36 g_service.Get() = new internal::DeferredGpuCommandService; | |
37 content::SynchronousCompositor::SetGpuService(g_service.Get()); | |
38 } | |
39 | |
40 ScopedAppGLStateRestore state_restore( | |
41 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | |
42 internal::ScopedAllowGL allow_gl; | |
43 | 26 |
44 gl_surface_ = new AwGLSurface; | 27 gl_surface_ = new AwGLSurface; |
45 bool success = | 28 bool success = |
46 shared_renderer_state_->GetCompositor()-> | 29 shared_renderer_state_->GetCompositor()-> |
47 InitializeHwDraw(gl_surface_); | 30 InitializeHwDraw(gl_surface_); |
48 DCHECK(success); | 31 DCHECK(success); |
49 } | 32 } |
50 | 33 |
51 HardwareRenderer::~HardwareRenderer() { | 34 HardwareRenderer::~HardwareRenderer() { |
52 GLViewRendererManager* render_manager = GLViewRendererManager::GetInstance(); | |
53 render_manager->Remove(renderer_manager_key_); | |
54 | |
55 ScopedAppGLStateRestore state_restore( | |
56 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | |
57 internal::ScopedAllowGL allow_gl; | |
58 | |
59 shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); | 35 shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); |
60 gl_surface_ = NULL; | 36 gl_surface_ = NULL; |
61 } | 37 } |
62 | 38 |
63 bool HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info, DrawGLResult* result) { | 39 bool HardwareRenderer::DrawGL(bool stencil_enabled, |
| 40 int framebuffer_binding_ext, |
| 41 AwDrawGLInfo* draw_info, |
| 42 DrawGLResult* result) { |
64 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL"); | 43 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL"); |
65 GLViewRendererManager::GetInstance()->DidDrawGL(renderer_manager_key_); | |
66 | 44 |
67 // We need to watch if the current Android context has changed and enforce | 45 // We need to watch if the current Android context has changed and enforce |
68 // a clean-up in the compositor. | 46 // a clean-up in the compositor. |
69 EGLContext current_context = eglGetCurrentContext(); | 47 EGLContext current_context = eglGetCurrentContext(); |
70 if (!current_context) { | 48 if (!current_context) { |
71 DLOG(ERROR) << "DrawGL called without EGLContext"; | 49 DLOG(ERROR) << "DrawGL called without EGLContext"; |
72 return false; | 50 return false; |
73 } | 51 } |
74 | 52 |
75 // TODO(boliu): Handle context loss. | 53 // TODO(boliu): Handle context loss. |
76 if (last_egl_context_ != current_context) | 54 if (last_egl_context_ != current_context) |
77 DLOG(WARNING) << "EGLContextChanged"; | 55 DLOG(WARNING) << "EGLContextChanged"; |
78 | 56 |
79 ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW); | |
80 internal::ScopedAllowGL allow_gl; | |
81 | |
82 if (draw_info->mode != AwDrawGLInfo::kModeDraw) | 57 if (draw_info->mode != AwDrawGLInfo::kModeDraw) |
83 return false; | 58 return false; |
84 | 59 |
85 // Should only need to access SharedRendererState in kModeDraw and kModeSync. | 60 // Should only need to access SharedRendererState in kModeDraw and kModeSync. |
86 const DrawGLInput input = shared_renderer_state_->GetDrawGLInput(); | 61 const DrawGLInput input = shared_renderer_state_->GetDrawGLInput(); |
87 SetCompositorMemoryPolicy(); | 62 SetCompositorMemoryPolicy(); |
88 | 63 |
89 gl_surface_->SetBackingFrameBufferObject( | 64 gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext); |
90 state_restore.framebuffer_binding_ext()); | |
91 | 65 |
92 gfx::Transform transform; | 66 gfx::Transform transform; |
93 transform.matrix().setColMajorf(draw_info->transform); | 67 transform.matrix().setColMajorf(draw_info->transform); |
94 transform.Translate(input.scroll_offset.x(), input.scroll_offset.y()); | 68 transform.Translate(input.scroll_offset.x(), input.scroll_offset.y()); |
95 gfx::Rect clip_rect(draw_info->clip_left, | 69 gfx::Rect clip_rect(draw_info->clip_left, |
96 draw_info->clip_top, | 70 draw_info->clip_top, |
97 draw_info->clip_right - draw_info->clip_left, | 71 draw_info->clip_right - draw_info->clip_left, |
98 draw_info->clip_bottom - draw_info->clip_top); | 72 draw_info->clip_bottom - draw_info->clip_top); |
99 | 73 |
100 gfx::Rect viewport(draw_info->width, draw_info->height); | 74 gfx::Rect viewport(draw_info->width, draw_info->height); |
101 if (!draw_info->is_layer) { | 75 if (!draw_info->is_layer) { |
102 gfx::RectF view_rect(input.width, input.height); | 76 gfx::RectF view_rect(input.width, input.height); |
103 transform.TransformRect(&view_rect); | 77 transform.TransformRect(&view_rect); |
104 viewport.Intersect(gfx::ToEnclosingRect(view_rect)); | 78 viewport.Intersect(gfx::ToEnclosingRect(view_rect)); |
105 } | 79 } |
106 | 80 |
107 bool did_draw = shared_renderer_state_->GetCompositor()-> | 81 bool did_draw = shared_renderer_state_->GetCompositor()->DemandDrawHw( |
108 DemandDrawHw( | 82 gfx::Size(draw_info->width, draw_info->height), |
109 gfx::Size(draw_info->width, draw_info->height), | 83 transform, |
110 transform, | 84 viewport, |
111 viewport, | 85 clip_rect, |
112 clip_rect, | 86 stencil_enabled); |
113 state_restore.stencil_enabled()); | |
114 gl_surface_->ResetBackingFrameBufferObject(); | 87 gl_surface_->ResetBackingFrameBufferObject(); |
115 | 88 |
116 if (did_draw) { | 89 if (did_draw) { |
117 result->frame_id = input.frame_id; | 90 result->frame_id = input.frame_id; |
118 result->clip_contains_visible_rect = | 91 result->clip_contains_visible_rect = |
119 clip_rect.Contains(input.global_visible_rect); | 92 clip_rect.Contains(input.global_visible_rect); |
120 } | 93 } |
121 return did_draw; | 94 return did_draw; |
122 } | 95 } |
123 | 96 |
124 void HardwareRenderer::SetCompositorMemoryPolicy() { | 97 void HardwareRenderer::SetCompositorMemoryPolicy() { |
125 if (shared_renderer_state_->IsMemoryPolicyDirty()) { | 98 if (shared_renderer_state_->IsMemoryPolicyDirty()) { |
126 content::SynchronousCompositorMemoryPolicy policy = | 99 content::SynchronousCompositorMemoryPolicy policy = |
127 shared_renderer_state_->GetMemoryPolicy(); | 100 shared_renderer_state_->GetMemoryPolicy(); |
128 // Memory policy is set by BrowserViewRenderer on UI thread. | 101 // Memory policy is set by BrowserViewRenderer on UI thread. |
129 shared_renderer_state_->GetCompositor()->SetMemoryPolicy(policy); | 102 shared_renderer_state_->GetCompositor()->SetMemoryPolicy(policy); |
130 shared_renderer_state_->SetMemoryPolicyDirty(false); | 103 shared_renderer_state_->SetMemoryPolicyDirty(false); |
131 } | 104 } |
132 } | 105 } |
133 | 106 |
134 namespace internal { | |
135 | |
136 base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl; | |
137 | |
138 // static | |
139 bool ScopedAllowGL::IsAllowed() { | |
140 return allow_gl.Get().Get(); | |
141 } | |
142 | |
143 ScopedAllowGL::ScopedAllowGL() { | |
144 DCHECK(!allow_gl.Get().Get()); | |
145 allow_gl.Get().Set(true); | |
146 | |
147 if (g_service.Get()) | |
148 g_service.Get()->RunTasks(); | |
149 } | |
150 | |
151 ScopedAllowGL::~ScopedAllowGL() { allow_gl.Get().Set(false); } | |
152 | |
153 DeferredGpuCommandService::DeferredGpuCommandService() {} | |
154 | |
155 DeferredGpuCommandService::~DeferredGpuCommandService() { | |
156 base::AutoLock lock(tasks_lock_); | |
157 DCHECK(tasks_.empty()); | |
158 } | |
159 | |
160 // static | |
161 void DeferredGpuCommandService::RequestProcessGLOnUIThread() { | |
162 SharedRendererState* renderer_state = | |
163 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn(); | |
164 if (!renderer_state) { | |
165 LOG(ERROR) << "No hardware renderer. Deadlock likely"; | |
166 return; | |
167 } | |
168 renderer_state->ClientRequestDrawGL(); | |
169 } | |
170 | |
171 // Called from different threads! | |
172 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { | |
173 { | |
174 base::AutoLock lock(tasks_lock_); | |
175 tasks_.push(task); | |
176 } | |
177 if (ScopedAllowGL::IsAllowed()) { | |
178 RunTasks(); | |
179 } else { | |
180 RequestProcessGLOnUIThread(); | |
181 } | |
182 } | |
183 | |
184 void DeferredGpuCommandService::ScheduleIdleWork( | |
185 const base::Closure& callback) { | |
186 // TODO(sievers): Should this do anything? | |
187 } | |
188 | |
189 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; } | |
190 | |
191 scoped_refptr<gpu::gles2::ShaderTranslatorCache> | |
192 DeferredGpuCommandService::shader_translator_cache() { | |
193 if (!shader_translator_cache_.get()) | |
194 shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache; | |
195 return shader_translator_cache_; | |
196 } | |
197 | |
198 void DeferredGpuCommandService::RunTasks() { | |
199 bool has_more_tasks; | |
200 { | |
201 base::AutoLock lock(tasks_lock_); | |
202 has_more_tasks = tasks_.size() > 0; | |
203 } | |
204 | |
205 while (has_more_tasks) { | |
206 base::Closure task; | |
207 { | |
208 base::AutoLock lock(tasks_lock_); | |
209 task = tasks_.front(); | |
210 tasks_.pop(); | |
211 } | |
212 task.Run(); | |
213 { | |
214 base::AutoLock lock(tasks_lock_); | |
215 has_more_tasks = tasks_.size() > 0; | |
216 } | |
217 } | |
218 } | |
219 | |
220 void DeferredGpuCommandService::AddRef() const { | |
221 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); | |
222 } | |
223 | |
224 void DeferredGpuCommandService::Release() const { | |
225 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); | |
226 } | |
227 | |
228 } // namespace internal | |
229 | |
230 } // namespace android_webview | 107 } // namespace android_webview |
OLD | NEW |