Add strings for the upcoming Settings API UI on the chrome://settings page.
[chromium-blink-merge.git] / android_webview / browser / hardware_renderer.cc
blob8042d9d4fff60e94578bca99b34161592a3f8e04
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/gl_view_renderer_manager.h"
10 #include "android_webview/browser/scoped_app_gl_state_restore.h"
11 #include "android_webview/public/browser/draw_gl.h"
12 #include "base/command_line.h"
13 #include "base/debug/trace_event.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/common/content_switches.h"
17 #include "ui/gfx/transform.h"
19 using content::BrowserThread;
21 namespace android_webview {
23 namespace {
25 // Used to calculate memory and resource allocation. Determined experimentally.
26 const size_t g_memory_multiplier = 10;
27 const size_t g_num_gralloc_limit = 150;
28 const size_t kBytesPerPixel = 4;
29 const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
31 base::LazyInstance<scoped_refptr<internal::DeferredGpuCommandService> >
32 g_service = LAZY_INSTANCE_INITIALIZER;
34 } // namespace
36 HardwareRenderer::HardwareRenderer(SharedRendererState* state)
37 : shared_renderer_state_(state),
38 last_egl_context_(eglGetCurrentContext()),
39 manager_key_(GLViewRendererManager::GetInstance()->PushBack(
40 shared_renderer_state_)) {
41 DCHECK(last_egl_context_);
42 if (!g_service.Get()) {
43 g_service.Get() = new internal::DeferredGpuCommandService;
44 content::SynchronousCompositor::SetGpuService(g_service.Get());
47 ScopedAppGLStateRestore state_restore(
48 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
49 internal::ScopedAllowGL allow_gl;
51 gl_surface_ = new AwGLSurface;
52 bool success =
53 shared_renderer_state_->GetCompositor()->
54 InitializeHwDraw(gl_surface_);
55 DCHECK(success);
58 HardwareRenderer::~HardwareRenderer() {
59 GLViewRendererManager* mru = GLViewRendererManager::GetInstance();
60 mru->Remove(manager_key_);
62 ScopedAppGLStateRestore state_restore(
63 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
64 internal::ScopedAllowGL allow_gl;
66 shared_renderer_state_->GetCompositor()->ReleaseHwDraw();
67 gl_surface_ = NULL;
70 bool HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info, DrawGLResult* result) {
71 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL");
72 GLViewRendererManager::GetInstance()->DidDrawGL(manager_key_);
73 const DrawGLInput input = shared_renderer_state_->GetDrawGLInput();
75 // We need to watch if the current Android context has changed and enforce
76 // a clean-up in the compositor.
77 EGLContext current_context = eglGetCurrentContext();
78 if (!current_context) {
79 DLOG(ERROR) << "DrawGL called without EGLContext";
80 return false;
83 // TODO(boliu): Handle context loss.
84 if (last_egl_context_ != current_context)
85 DLOG(WARNING) << "EGLContextChanged";
87 ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW);
88 internal::ScopedAllowGL allow_gl;
90 if (draw_info->mode == AwDrawGLInfo::kModeProcess)
91 return false;
93 // Update memory budget. This will no-op in compositor if the policy has not
94 // changed since last draw.
95 content::SynchronousCompositorMemoryPolicy policy;
96 policy.bytes_limit = g_memory_multiplier * kBytesPerPixel *
97 input.global_visible_rect.width() *
98 input.global_visible_rect.height();
99 // Round up to a multiple of kMemoryAllocationStep.
100 policy.bytes_limit =
101 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
102 policy.num_resources_limit = g_num_gralloc_limit;
103 SetMemoryPolicy(policy);
105 gl_surface_->SetBackingFrameBufferObject(
106 state_restore.framebuffer_binding_ext());
108 gfx::Transform transform;
109 transform.matrix().setColMajorf(draw_info->transform);
110 transform.Translate(input.scroll_offset.x(), input.scroll_offset.y());
111 gfx::Rect clip_rect(draw_info->clip_left,
112 draw_info->clip_top,
113 draw_info->clip_right - draw_info->clip_left,
114 draw_info->clip_bottom - draw_info->clip_top);
116 bool did_draw = shared_renderer_state_->GetCompositor()->
117 DemandDrawHw(
118 gfx::Size(draw_info->width, draw_info->height),
119 transform,
120 clip_rect, // viewport
121 clip_rect,
122 state_restore.stencil_enabled());
123 gl_surface_->ResetBackingFrameBufferObject();
125 if (did_draw) {
126 result->frame_id = input.frame_id;
127 result->clip_contains_visible_rect =
128 clip_rect.Contains(input.global_visible_rect);
130 return did_draw;
133 bool HardwareRenderer::TrimMemory(int level, bool visible) {
134 // Constants from Android ComponentCallbacks2.
135 enum {
136 TRIM_MEMORY_RUNNING_LOW = 10,
137 TRIM_MEMORY_UI_HIDDEN = 20,
138 TRIM_MEMORY_BACKGROUND = 40,
141 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
142 // it does not indicate memory pressure, but merely that the app is
143 // backgrounded.
144 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
145 return false;
147 // Do not release resources on view we expect to get DrawGL soon.
148 if (level < TRIM_MEMORY_BACKGROUND && visible)
149 return false;
151 if (!eglGetCurrentContext()) {
152 NOTREACHED();
153 return false;
156 DCHECK_EQ(last_egl_context_, eglGetCurrentContext());
158 // Just set the memory limit to 0 and drop all tiles. This will be reset to
159 // normal levels in the next DrawGL call.
160 content::SynchronousCompositorMemoryPolicy policy;
161 policy.bytes_limit = 0;
162 policy.num_resources_limit = 0;
163 if (memory_policy_ == policy)
164 return false;
166 TRACE_EVENT0("android_webview", "HardwareRenderer::TrimMemory");
167 ScopedAppGLStateRestore state_restore(
168 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
169 internal::ScopedAllowGL allow_gl;
171 SetMemoryPolicy(policy);
172 return true;
175 void HardwareRenderer::SetMemoryPolicy(
176 content::SynchronousCompositorMemoryPolicy& new_policy) {
177 if (memory_policy_ == new_policy)
178 return;
180 memory_policy_ = new_policy;
181 shared_renderer_state_->GetCompositor()->
182 SetMemoryPolicy(memory_policy_);
185 // static
186 void HardwareRenderer::CalculateTileMemoryPolicy() {
187 CommandLine* cl = CommandLine::ForCurrentProcess();
189 const char kDefaultTileSize[] = "384";
190 if (!cl->HasSwitch(switches::kDefaultTileWidth))
191 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize);
193 if (!cl->HasSwitch(switches::kDefaultTileHeight))
194 cl->AppendSwitchASCII(switches::kDefaultTileHeight, kDefaultTileSize);
197 namespace internal {
199 bool ScopedAllowGL::allow_gl = false;
201 // static
202 bool ScopedAllowGL::IsAllowed() {
203 return GLViewRendererManager::GetInstance()->OnRenderThread() && allow_gl;
206 ScopedAllowGL::ScopedAllowGL() {
207 DCHECK(GLViewRendererManager::GetInstance()->OnRenderThread());
208 DCHECK(!allow_gl);
209 allow_gl = true;
211 if (g_service.Get())
212 g_service.Get()->RunTasks();
215 ScopedAllowGL::~ScopedAllowGL() { allow_gl = false; }
217 DeferredGpuCommandService::DeferredGpuCommandService() {}
219 DeferredGpuCommandService::~DeferredGpuCommandService() {
220 base::AutoLock lock(tasks_lock_);
221 DCHECK(tasks_.empty());
224 // static
225 void DeferredGpuCommandService::RequestProcessGLOnUIThread() {
226 SharedRendererState* renderer_state =
227 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
228 if (!renderer_state) {
229 LOG(ERROR) << "No hardware renderer. Deadlock likely";
230 return;
232 renderer_state->ClientRequestDrawGL();
235 // Called from different threads!
236 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
238 base::AutoLock lock(tasks_lock_);
239 tasks_.push(task);
241 if (ScopedAllowGL::IsAllowed()) {
242 RunTasks();
243 } else {
244 RequestProcessGLOnUIThread();
248 void DeferredGpuCommandService::ScheduleIdleWork(
249 const base::Closure& callback) {
250 // TODO(sievers): Should this do anything?
253 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
255 void DeferredGpuCommandService::RunTasks() {
256 bool has_more_tasks;
258 base::AutoLock lock(tasks_lock_);
259 has_more_tasks = tasks_.size() > 0;
262 while (has_more_tasks) {
263 base::Closure task;
265 base::AutoLock lock(tasks_lock_);
266 task = tasks_.front();
267 tasks_.pop();
269 task.Run();
271 base::AutoLock lock(tasks_lock_);
272 has_more_tasks = tasks_.size() > 0;
277 void DeferredGpuCommandService::AddRef() const {
278 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
281 void DeferredGpuCommandService::Release() const {
282 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
285 } // namespace internal
287 } // namespace android_webview