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/hardware_renderer.h"
7 #include "android_webview/browser/aw_gl_surface.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"
11 #include "base/debug/trace_event.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "content/public/browser/android/synchronous_compositor.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "gpu/command_buffer/service/shader_translator_cache.h"
16 #include "ui/gfx/geometry/rect_conversions.h"
17 #include "ui/gfx/geometry/rect_f.h"
18 #include "ui/gfx/transform.h"
20 namespace android_webview
{
24 base::LazyInstance
<scoped_refptr
<internal::DeferredGpuCommandService
> >
25 g_service
= LAZY_INSTANCE_INITIALIZER
;
29 HardwareRenderer::HardwareRenderer(SharedRendererState
* state
)
30 : shared_renderer_state_(state
),
31 last_egl_context_(eglGetCurrentContext()),
32 renderer_manager_key_(GLViewRendererManager::GetInstance()->PushBack(
33 shared_renderer_state_
)) {
34 DCHECK(last_egl_context_
);
35 if (!g_service
.Get()) {
36 g_service
.Get() = new internal::DeferredGpuCommandService
;
37 content::SynchronousCompositor::SetGpuService(g_service
.Get());
40 ScopedAppGLStateRestore
state_restore(
41 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT
);
42 internal::ScopedAllowGL allow_gl
;
44 gl_surface_
= new AwGLSurface
;
46 shared_renderer_state_
->GetCompositor()->
47 InitializeHwDraw(gl_surface_
);
51 HardwareRenderer::~HardwareRenderer() {
52 GLViewRendererManager
* render_manager
= GLViewRendererManager::GetInstance();
53 render_manager
->Remove(renderer_manager_key_
);
55 ScopedAppGLStateRestore
state_restore(
56 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT
);
57 internal::ScopedAllowGL allow_gl
;
59 shared_renderer_state_
->GetCompositor()->ReleaseHwDraw();
63 bool HardwareRenderer::DrawGL(AwDrawGLInfo
* draw_info
, DrawGLResult
* result
) {
64 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL");
65 GLViewRendererManager::GetInstance()->DidDrawGL(renderer_manager_key_
);
67 // We need to watch if the current Android context has changed and enforce
68 // a clean-up in the compositor.
69 EGLContext current_context
= eglGetCurrentContext();
70 if (!current_context
) {
71 DLOG(ERROR
) << "DrawGL called without EGLContext";
75 // TODO(boliu): Handle context loss.
76 if (last_egl_context_
!= current_context
)
77 DLOG(WARNING
) << "EGLContextChanged";
79 ScopedAppGLStateRestore
state_restore(ScopedAppGLStateRestore::MODE_DRAW
);
80 internal::ScopedAllowGL allow_gl
;
82 if (draw_info
->mode
!= AwDrawGLInfo::kModeDraw
)
85 // Should only need to access SharedRendererState in kModeDraw and kModeSync.
86 const DrawGLInput input
= shared_renderer_state_
->GetDrawGLInput();
87 SetCompositorMemoryPolicy();
89 gl_surface_
->SetBackingFrameBufferObject(
90 state_restore
.framebuffer_binding_ext());
92 gfx::Transform transform
;
93 transform
.matrix().setColMajorf(draw_info
->transform
);
94 transform
.Translate(input
.scroll_offset
.x(), input
.scroll_offset
.y());
95 gfx::Rect
clip_rect(draw_info
->clip_left
,
97 draw_info
->clip_right
- draw_info
->clip_left
,
98 draw_info
->clip_bottom
- draw_info
->clip_top
);
100 gfx::Rect
viewport(draw_info
->width
, draw_info
->height
);
101 if (!draw_info
->is_layer
) {
102 gfx::RectF
view_rect(input
.width
, input
.height
);
103 transform
.TransformRect(&view_rect
);
104 viewport
.Intersect(gfx::ToEnclosingRect(view_rect
));
107 bool did_draw
= shared_renderer_state_
->GetCompositor()->
109 gfx::Size(draw_info
->width
, draw_info
->height
),
113 state_restore
.stencil_enabled());
114 gl_surface_
->ResetBackingFrameBufferObject();
117 result
->frame_id
= input
.frame_id
;
118 result
->clip_contains_visible_rect
=
119 clip_rect
.Contains(input
.global_visible_rect
);
124 void HardwareRenderer::SetCompositorMemoryPolicy() {
125 if (shared_renderer_state_
->IsMemoryPolicyDirty()) {
126 content::SynchronousCompositorMemoryPolicy policy
=
127 shared_renderer_state_
->GetMemoryPolicy();
128 // Memory policy is set by BrowserViewRenderer on UI thread.
129 shared_renderer_state_
->GetCompositor()->SetMemoryPolicy(policy
);
130 shared_renderer_state_
->SetMemoryPolicyDirty(false);
136 base::LazyInstance
<base::ThreadLocalBoolean
> ScopedAllowGL::allow_gl
;
139 bool ScopedAllowGL::IsAllowed() {
140 return allow_gl
.Get().Get();
143 ScopedAllowGL::ScopedAllowGL() {
144 DCHECK(!allow_gl
.Get().Get());
145 allow_gl
.Get().Set(true);
148 g_service
.Get()->RunTasks();
151 ScopedAllowGL::~ScopedAllowGL() { allow_gl
.Get().Set(false); }
153 DeferredGpuCommandService::DeferredGpuCommandService() {}
155 DeferredGpuCommandService::~DeferredGpuCommandService() {
156 base::AutoLock
lock(tasks_lock_
);
157 DCHECK(tasks_
.empty());
161 void DeferredGpuCommandService::RequestProcessGLOnUIThread() {
162 SharedRendererState
* renderer_state
=
163 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
164 if (!renderer_state
) {
165 LOG(ERROR
) << "No hardware renderer. Deadlock likely";
168 renderer_state
->ClientRequestDrawGL();
171 // Called from different threads!
172 void DeferredGpuCommandService::ScheduleTask(const base::Closure
& task
) {
174 base::AutoLock
lock(tasks_lock_
);
177 if (ScopedAllowGL::IsAllowed()) {
180 RequestProcessGLOnUIThread();
184 void DeferredGpuCommandService::ScheduleIdleWork(
185 const base::Closure
& callback
) {
186 // TODO(sievers): Should this do anything?
189 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
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_
;
198 void DeferredGpuCommandService::RunTasks() {
201 base::AutoLock
lock(tasks_lock_
);
202 has_more_tasks
= tasks_
.size() > 0;
205 while (has_more_tasks
) {
208 base::AutoLock
lock(tasks_lock_
);
209 task
= tasks_
.front();
214 base::AutoLock
lock(tasks_lock_
);
215 has_more_tasks
= tasks_
.size() > 0;
220 void DeferredGpuCommandService::AddRef() const {
221 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::AddRef();
224 void DeferredGpuCommandService::Release() const {
225 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::Release();
228 } // namespace internal
230 } // namespace android_webview