Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 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/in_process_view_renderer.h" | 5 #include "android_webview/browser/browser_view_renderer.h" |
| 6 | 6 |
| 7 #include "android_webview/browser/aw_gl_surface.h" | 7 #include "android_webview/browser/hardware_renderer.h" |
| 8 #include "android_webview/browser/scoped_app_gl_state_restore.h" | |
| 9 #include "android_webview/common/aw_switches.h" | |
| 10 #include "android_webview/public/browser/draw_gl.h" | 8 #include "android_webview/public/browser/draw_gl.h" |
| 11 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
| 12 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| 13 #include "base/command_line.h" | |
| 14 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 15 #include "base/lazy_instance.h" | |
| 16 #include "base/logging.h" | 12 #include "base/logging.h" |
| 17 #include "base/strings/string_number_conversions.h" | |
| 18 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "content/public/browser/android/synchronous_compositor.h" | |
| 19 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/web_contents.h" | 16 #include "content/public/browser/web_contents.h" |
| 21 #include "content/public/common/content_switches.h" | |
| 22 #include "gpu/command_buffer/service/in_process_command_buffer.h" | |
| 23 #include "third_party/skia/include/core/SkBitmap.h" | 17 #include "third_party/skia/include/core/SkBitmap.h" |
| 24 #include "third_party/skia/include/core/SkBitmapDevice.h" | 18 #include "third_party/skia/include/core/SkBitmapDevice.h" |
| 25 #include "third_party/skia/include/core/SkCanvas.h" | 19 #include "third_party/skia/include/core/SkCanvas.h" |
| 26 #include "third_party/skia/include/core/SkPicture.h" | 20 #include "third_party/skia/include/core/SkPicture.h" |
| 27 #include "ui/gfx/transform.h" | |
| 28 #include "ui/gfx/vector2d_conversions.h" | 21 #include "ui/gfx/vector2d_conversions.h" |
| 29 | 22 |
| 30 using base::android::AttachCurrentThread; | 23 using base::android::AttachCurrentThread; |
| 31 using base::android::JavaRef; | 24 using base::android::JavaRef; |
| 32 using base::android::ScopedJavaLocalRef; | 25 using base::android::ScopedJavaLocalRef; |
| 33 using content::BrowserThread; | 26 using content::BrowserThread; |
| 34 | 27 |
| 35 namespace android_webview { | 28 namespace android_webview { |
| 36 | 29 |
| 37 namespace { | 30 namespace { |
| 38 | 31 |
| 39 const void* kUserDataKey = &kUserDataKey; | |
| 40 | |
| 41 class UserData : public content::WebContents::Data { | |
| 42 public: | |
| 43 UserData(InProcessViewRenderer* ptr) : instance_(ptr) {} | |
| 44 virtual ~UserData() { | |
| 45 instance_->WebContentsGone(); | |
| 46 } | |
| 47 | |
| 48 static InProcessViewRenderer* GetInstance(content::WebContents* contents) { | |
| 49 if (!contents) | |
| 50 return NULL; | |
| 51 UserData* data = reinterpret_cast<UserData*>( | |
| 52 contents->GetUserData(kUserDataKey)); | |
| 53 return data ? data->instance_ : NULL; | |
| 54 } | |
| 55 | |
| 56 private: | |
| 57 InProcessViewRenderer* instance_; | |
| 58 }; | |
| 59 | |
| 60 bool HardwareEnabled() { | |
| 61 static bool g_hw_enabled = !CommandLine::ForCurrentProcess()->HasSwitch( | |
| 62 switches::kDisableWebViewGLMode); | |
| 63 return g_hw_enabled; | |
| 64 } | |
| 65 | |
| 66 const int64 kFallbackTickTimeoutInMilliseconds = 20; | 32 const int64 kFallbackTickTimeoutInMilliseconds = 20; |
| 67 | 33 |
| 68 // Used to calculate memory and resource allocation. Determined experimentally. | |
| 69 size_t g_memory_multiplier = 10; | |
| 70 size_t g_num_gralloc_limit = 150; | |
| 71 const size_t kBytesPerPixel = 4; | |
| 72 const size_t kMemoryAllocationStep = 5 * 1024 * 1024; | |
| 73 | |
| 74 base::LazyInstance<GLViewRendererManager>::Leaky g_view_renderer_manager = | |
| 75 LAZY_INSTANCE_INITIALIZER; | |
| 76 | |
| 77 class ScopedAllowGL { | |
| 78 public: | |
| 79 ScopedAllowGL(); | |
| 80 ~ScopedAllowGL(); | |
| 81 | |
| 82 static bool IsAllowed() { | |
| 83 return g_view_renderer_manager.Get().OnRenderThread() && allow_gl; | |
| 84 } | |
| 85 | |
| 86 private: | |
| 87 static bool allow_gl; | |
| 88 | |
| 89 DISALLOW_COPY_AND_ASSIGN(ScopedAllowGL); | |
| 90 }; | |
| 91 | |
| 92 ScopedAllowGL::ScopedAllowGL() { | |
| 93 DCHECK(g_view_renderer_manager.Get().OnRenderThread()); | |
| 94 DCHECK(!allow_gl); | |
| 95 allow_gl = true; | |
| 96 } | |
| 97 | |
| 98 ScopedAllowGL::~ScopedAllowGL() { | |
| 99 allow_gl = false; | |
| 100 } | |
| 101 | |
| 102 bool ScopedAllowGL::allow_gl = false; | |
| 103 | |
| 104 void RequestProcessGLOnUIThread() { | |
| 105 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 106 BrowserThread::PostTask( | |
| 107 BrowserThread::UI, FROM_HERE, base::Bind(&RequestProcessGLOnUIThread)); | |
| 108 return; | |
| 109 } | |
| 110 | |
| 111 InProcessViewRenderer* renderer = static_cast<InProcessViewRenderer*>( | |
| 112 g_view_renderer_manager.Get().GetMostRecentlyDrawn()); | |
| 113 if (!renderer || !renderer->RequestProcessGL()) { | |
| 114 LOG(ERROR) << "Failed to request GL process. Deadlock likely: " | |
| 115 << !!renderer; | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 class DeferredGpuCommandService | |
| 120 : public gpu::InProcessCommandBuffer::Service, | |
| 121 public base::RefCountedThreadSafe<DeferredGpuCommandService> { | |
| 122 public: | |
| 123 DeferredGpuCommandService(); | |
| 124 | |
| 125 virtual void ScheduleTask(const base::Closure& task) OVERRIDE; | |
| 126 virtual void ScheduleIdleWork(const base::Closure& task) OVERRIDE; | |
| 127 virtual bool UseVirtualizedGLContexts() OVERRIDE; | |
| 128 | |
| 129 void RunTasks(); | |
| 130 | |
| 131 virtual void AddRef() const OVERRIDE { | |
| 132 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); | |
| 133 } | |
| 134 virtual void Release() const OVERRIDE { | |
| 135 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); | |
| 136 } | |
| 137 | |
| 138 protected: | |
| 139 virtual ~DeferredGpuCommandService(); | |
| 140 friend class base::RefCountedThreadSafe<DeferredGpuCommandService>; | |
| 141 | |
| 142 private: | |
| 143 base::Lock tasks_lock_; | |
| 144 std::queue<base::Closure> tasks_; | |
| 145 DISALLOW_COPY_AND_ASSIGN(DeferredGpuCommandService); | |
| 146 }; | |
| 147 | |
| 148 DeferredGpuCommandService::DeferredGpuCommandService() {} | |
| 149 | |
| 150 DeferredGpuCommandService::~DeferredGpuCommandService() { | |
| 151 base::AutoLock lock(tasks_lock_); | |
| 152 DCHECK(tasks_.empty()); | |
| 153 } | |
| 154 | |
| 155 // Called from different threads! | |
| 156 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { | |
| 157 { | |
| 158 base::AutoLock lock(tasks_lock_); | |
| 159 tasks_.push(task); | |
| 160 } | |
| 161 if (ScopedAllowGL::IsAllowed()) { | |
| 162 RunTasks(); | |
| 163 } else { | |
| 164 RequestProcessGLOnUIThread(); | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 void DeferredGpuCommandService::ScheduleIdleWork( | |
| 169 const base::Closure& callback) { | |
| 170 // TODO(sievers): Should this do anything? | |
| 171 } | |
| 172 | |
| 173 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; } | |
| 174 | |
| 175 void DeferredGpuCommandService::RunTasks() { | |
| 176 bool has_more_tasks; | |
| 177 { | |
| 178 base::AutoLock lock(tasks_lock_); | |
| 179 has_more_tasks = tasks_.size() > 0; | |
| 180 } | |
| 181 | |
| 182 while (has_more_tasks) { | |
| 183 base::Closure task; | |
| 184 { | |
| 185 base::AutoLock lock(tasks_lock_); | |
| 186 task = tasks_.front(); | |
| 187 tasks_.pop(); | |
| 188 } | |
| 189 task.Run(); | |
| 190 { | |
| 191 base::AutoLock lock(tasks_lock_); | |
| 192 has_more_tasks = tasks_.size() > 0; | |
| 193 } | |
| 194 | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > g_service = | |
| 199 LAZY_INSTANCE_INITIALIZER; | |
| 200 | |
| 201 } // namespace | 34 } // namespace |
| 202 | 35 |
| 203 InProcessViewRenderer::InProcessViewRenderer( | 36 BrowserViewRenderer::BrowserViewRenderer(BrowserViewRendererClient* client, |
| 204 BrowserViewRenderer::Client* client, | 37 content::WebContents* web_contents) |
| 205 content::WebContents* web_contents) | |
| 206 : client_(client), | 38 : client_(client), |
| 207 web_contents_(web_contents), | 39 web_contents_(web_contents), |
| 208 compositor_(NULL), | 40 compositor_(NULL), |
| 209 is_paused_(false), | 41 is_paused_(false), |
| 210 view_visible_(false), | 42 view_visible_(false), |
| 211 window_visible_(false), | 43 window_visible_(false), |
| 212 attached_to_window_(false), | 44 attached_to_window_(false), |
| 213 dip_scale_(0.0), | 45 dip_scale_(0.0), |
| 214 page_scale_factor_(1.0), | 46 page_scale_factor_(1.0), |
| 215 on_new_picture_enable_(false), | 47 on_new_picture_enable_(false), |
| 216 clear_view_(false), | 48 clear_view_(false), |
| 217 compositor_needs_continuous_invalidate_(false), | 49 compositor_needs_continuous_invalidate_(false), |
| 218 block_invalidates_(false), | 50 block_invalidates_(false), |
| 219 width_(0), | 51 width_(0), |
| 220 height_(0), | 52 height_(0) { |
| 221 hardware_initialized_(false), | |
| 222 hardware_failed_(false), | |
| 223 last_egl_context_(NULL), | |
| 224 manager_key_(g_view_renderer_manager.Get().NullKey()) { | |
| 225 CHECK(web_contents_); | 53 CHECK(web_contents_); |
| 226 web_contents_->SetUserData(kUserDataKey, new UserData(this)); | |
| 227 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this); | 54 content::SynchronousCompositor::SetClientForWebContents(web_contents_, this); |
| 228 | 55 |
| 229 // Currently the logic in this class relies on |compositor_| remaining NULL | 56 // Currently the logic in this class relies on |compositor_| remaining NULL |
| 230 // until the DidInitializeCompositor() call, hence it is not set here. | 57 // until the DidInitializeCompositor() call, hence it is not set here. |
| 231 } | 58 } |
| 232 | 59 |
| 233 InProcessViewRenderer::~InProcessViewRenderer() { | 60 BrowserViewRenderer::~BrowserViewRenderer() { |
| 234 CHECK(web_contents_); | |
| 235 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL); | 61 content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL); |
| 236 web_contents_->SetUserData(kUserDataKey, NULL); | |
| 237 NoLongerExpectsDrawGL(); | |
| 238 DCHECK(web_contents_ == NULL); // WebContentsGone should have been called. | |
| 239 } | 62 } |
| 240 | 63 |
| 241 void InProcessViewRenderer::NoLongerExpectsDrawGL() { | 64 void BrowserViewRenderer::TrimMemory(int level) { |
| 242 GLViewRendererManager& mru = g_view_renderer_manager.Get(); | 65 if (hardware_renderer_) { |
| 243 if (manager_key_ != mru.NullKey()) { | 66 client_->UpdateGlobalVisibleRect(); |
|
sgurun-gerrit only
2014/02/25 06:56:36
seems like we now call updateglobalvisiblerect alw
boliu
2014/02/25 19:02:22
Yes for now. I'm told by frameworks folks that get
| |
| 244 mru.NoLongerExpectsDrawGL(manager_key_); | 67 bool visible = view_visible_ && window_visible_ && |
| 245 manager_key_ = mru.NullKey(); | 68 !cached_global_visible_rect_.IsEmpty(); |
| 69 if (hardware_renderer_->TrimMemory(level, visible)) | |
| 70 ForceFakeCompositeSW(); | |
|
benm (inactive)
2014/02/25 12:48:01
out of interest, why do we do this? maybe worth a
boliu
2014/02/25 19:02:22
Setting memory policy itself does nothing, composi
| |
| 246 } | 71 } |
| 247 } | 72 } |
| 248 | 73 |
| 249 // static | 74 bool BrowserViewRenderer::OnDraw(jobject java_canvas, |
| 250 InProcessViewRenderer* InProcessViewRenderer::FromWebContents( | 75 bool is_hardware_canvas, |
| 251 content::WebContents* contents) { | 76 const gfx::Vector2d& scroll, |
| 252 return UserData::GetInstance(contents); | 77 const gfx::Rect& clip) { |
| 253 } | 78 scroll_at_start_of_frame_ = scroll; |
| 254 | |
| 255 void InProcessViewRenderer::WebContentsGone() { | |
| 256 web_contents_ = NULL; | |
| 257 compositor_ = NULL; | |
| 258 } | |
| 259 | |
| 260 // static | |
| 261 void InProcessViewRenderer::CalculateTileMemoryPolicy() { | |
| 262 CommandLine* cl = CommandLine::ForCurrentProcess(); | |
| 263 if (cl->HasSwitch(switches::kTileMemoryMultiplier)) { | |
| 264 std::string string_value = | |
| 265 cl->GetSwitchValueASCII(switches::kTileMemoryMultiplier); | |
| 266 int int_value = 0; | |
| 267 if (base::StringToInt(string_value, &int_value) && | |
| 268 int_value >= 2 && int_value <= 50) { | |
| 269 g_memory_multiplier = int_value; | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 if (cl->HasSwitch(switches::kNumGrallocBuffersPerWebview)) { | |
| 274 std::string string_value = | |
| 275 cl->GetSwitchValueASCII(switches::kNumGrallocBuffersPerWebview); | |
| 276 int int_value = 0; | |
| 277 if (base::StringToInt(string_value, &int_value) && | |
| 278 int_value >= 50 && int_value <= 500) { | |
| 279 g_num_gralloc_limit = int_value; | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 const char kDefaultTileSize[] = "384"; | |
| 284 if (!cl->HasSwitch(switches::kDefaultTileWidth)) | |
| 285 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize); | |
| 286 | |
| 287 if (!cl->HasSwitch(switches::kDefaultTileHeight)) | |
| 288 cl->AppendSwitchASCII(switches::kDefaultTileHeight, kDefaultTileSize); | |
| 289 } | |
| 290 | |
| 291 bool InProcessViewRenderer::RequestProcessGL() { | |
| 292 return client_->RequestDrawGL(NULL); | |
| 293 } | |
| 294 | |
| 295 void InProcessViewRenderer::TrimMemory(int level) { | |
| 296 // Constants from Android ComponentCallbacks2. | |
| 297 enum { | |
| 298 TRIM_MEMORY_RUNNING_LOW = 10, | |
| 299 TRIM_MEMORY_UI_HIDDEN = 20, | |
| 300 TRIM_MEMORY_BACKGROUND = 40, | |
| 301 }; | |
| 302 | |
| 303 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because | |
| 304 // it does not indicate memory pressure, but merely that the app is | |
| 305 // backgrounded. | |
| 306 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) | |
| 307 return; | |
| 308 | |
| 309 // Nothing to drop. | |
| 310 if (!attached_to_window_ || !hardware_initialized_ || !compositor_) | |
| 311 return; | |
| 312 | |
| 313 // Do not release resources on view we expect to get DrawGL soon. | |
| 314 if (level < TRIM_MEMORY_BACKGROUND) { | |
| 315 client_->UpdateGlobalVisibleRect(); | |
| 316 if (view_visible_ && window_visible_ && | |
| 317 !cached_global_visible_rect_.IsEmpty()) { | |
| 318 return; | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 if (!eglGetCurrentContext()) { | |
| 323 NOTREACHED(); | |
| 324 return; | |
| 325 } | |
| 326 | |
| 327 // Just set the memory limit to 0 and drop all tiles. This will be reset to | |
| 328 // normal levels in the next DrawGL call. | |
| 329 content::SynchronousCompositorMemoryPolicy policy; | |
| 330 policy.bytes_limit = 0; | |
| 331 policy.num_resources_limit = 0; | |
| 332 if (memory_policy_ == policy) | |
| 333 return; | |
| 334 | |
| 335 TRACE_EVENT0("android_webview", "InProcessViewRenderer::TrimMemory"); | |
| 336 ScopedAppGLStateRestore state_restore( | |
| 337 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | |
| 338 g_service.Get()->RunTasks(); | |
| 339 ScopedAllowGL allow_gl; | |
| 340 | |
| 341 SetMemoryPolicy(policy); | |
| 342 ForceFakeCompositeSW(); | |
| 343 } | |
| 344 | |
| 345 void InProcessViewRenderer::SetMemoryPolicy( | |
| 346 content::SynchronousCompositorMemoryPolicy& new_policy) { | |
| 347 if (memory_policy_ == new_policy) | |
| 348 return; | |
| 349 | |
| 350 memory_policy_ = new_policy; | |
| 351 compositor_->SetMemoryPolicy(memory_policy_); | |
| 352 } | |
| 353 | |
| 354 void InProcessViewRenderer::UpdateCachedGlobalVisibleRect() { | |
| 355 client_->UpdateGlobalVisibleRect(); | |
| 356 } | |
| 357 | |
| 358 bool InProcessViewRenderer::OnDraw(jobject java_canvas, | |
| 359 bool is_hardware_canvas, | |
| 360 const gfx::Vector2d& scroll, | |
| 361 const gfx::Rect& clip) { | |
| 362 scroll_at_start_of_frame_ = scroll; | |
| 363 if (clear_view_) | 79 if (clear_view_) |
| 364 return false; | 80 return false; |
| 365 if (is_hardware_canvas && attached_to_window_ && HardwareEnabled()) { | 81 |
|
sgurun-gerrit only
2014/02/25 06:56:36
nit:stale line?
| |
| 82 if (is_hardware_canvas && attached_to_window_) { | |
| 366 // We should be performing a hardware draw here. If we don't have the | 83 // We should be performing a hardware draw here. If we don't have the |
| 367 // comositor yet or if RequestDrawGL fails, it means we failed this draw and | 84 // comositor yet or if RequestDrawGL fails, it means we failed this draw and |
|
sgurun-gerrit only
2014/02/25 06:56:36
nit: compositor
| |
| 368 // thus return false here to clear to background color for this draw. | 85 // thus return false here to clear to background color for this draw. |
| 369 return compositor_ && client_->RequestDrawGL(java_canvas); | 86 return compositor_ && client_->RequestDrawGL(java_canvas); |
| 370 } | 87 } |
| 371 // Perform a software draw | 88 // Perform a software draw |
| 372 return DrawSWInternal(java_canvas, clip); | 89 return DrawSWInternal(java_canvas, clip); |
| 373 } | 90 } |
| 374 | 91 |
| 375 bool InProcessViewRenderer::InitializeHwDraw() { | 92 void BrowserViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { |
| 376 TRACE_EVENT0("android_webview", "InitializeHwDraw"); | 93 if (!attached_to_window_ || !compositor_) |
| 377 DCHECK(!gl_surface_); | 94 return; |
| 378 gl_surface_ = new AwGLSurface; | 95 |
| 379 if (!g_service.Get()) { | 96 client_->UpdateGlobalVisibleRect(); |
| 380 g_service.Get() = new DeferredGpuCommandService; | 97 if (cached_global_visible_rect_.IsEmpty()) |
| 381 content::SynchronousCompositor::SetGpuService(g_service.Get()); | 98 return; |
| 99 | |
| 100 if (!hardware_renderer_) | |
| 101 hardware_renderer_.reset(new HardwareRenderer(compositor_, client_)); | |
| 102 | |
| 103 DrawGLInput input; | |
| 104 input.global_visible_rect = cached_global_visible_rect_; | |
| 105 input.scroll = scroll_at_start_of_frame_; | |
| 106 DrawGLResult result; | |
| 107 { | |
| 108 base::AutoReset<bool> auto_reset(&block_invalidates_, true); | |
| 109 result = hardware_renderer_->DrawGL(draw_info, input); | |
| 382 } | 110 } |
| 383 hardware_failed_ = !compositor_->InitializeHwDraw(gl_surface_); | |
| 384 hardware_initialized_ = true; | |
| 385 | 111 |
| 386 if (hardware_failed_) | 112 if (result.did_draw) { |
| 387 gl_surface_ = NULL; | 113 fallback_tick_.Cancel(); |
| 388 | 114 block_invalidates_ = false; |
| 389 return !hardware_failed_; | 115 EnsureContinuousInvalidation(draw_info, !result.clip_contains_visible_rect); |
| 116 } | |
| 390 } | 117 } |
| 391 | 118 |
| 392 void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { | 119 void BrowserViewRenderer::SetGlobalVisibleRect(const gfx::Rect& visible_rect) { |
| 393 TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL"); | |
| 394 | |
| 395 manager_key_ = g_view_renderer_manager.Get().DidDrawGL(manager_key_, this); | |
| 396 | |
| 397 // We need to watch if the current Android context has changed and enforce | |
| 398 // a clean-up in the compositor. | |
| 399 EGLContext current_context = eglGetCurrentContext(); | |
| 400 if (!current_context) { | |
| 401 TRACE_EVENT_INSTANT0( | |
| 402 "android_webview", "EarlyOut_NullEGLContext", TRACE_EVENT_SCOPE_THREAD); | |
| 403 return; | |
| 404 } | |
| 405 | |
| 406 ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW); | |
| 407 if (g_service.Get()) | |
| 408 g_service.Get()->RunTasks(); | |
| 409 ScopedAllowGL allow_gl; | |
| 410 | |
| 411 if (!attached_to_window_) { | |
| 412 TRACE_EVENT_INSTANT0( | |
| 413 "android_webview", "EarlyOut_NotAttached", TRACE_EVENT_SCOPE_THREAD); | |
| 414 return; | |
| 415 } | |
| 416 | |
| 417 if (draw_info->mode == AwDrawGLInfo::kModeProcess) { | |
| 418 TRACE_EVENT_INSTANT0( | |
| 419 "android_webview", "EarlyOut_ModeProcess", TRACE_EVENT_SCOPE_THREAD); | |
| 420 return; | |
| 421 } | |
| 422 | |
| 423 if (compositor_ && !hardware_initialized_) { | |
| 424 if (InitializeHwDraw()) { | |
| 425 last_egl_context_ = current_context; | |
| 426 } else { | |
| 427 TRACE_EVENT_INSTANT0( | |
| 428 "android_webview", "EarlyOut_HwInitFail", TRACE_EVENT_SCOPE_THREAD); | |
| 429 LOG(ERROR) << "WebView hardware initialization failed"; | |
| 430 return; | |
| 431 } | |
| 432 } | |
| 433 | |
| 434 UpdateCachedGlobalVisibleRect(); | |
| 435 if (cached_global_visible_rect_.IsEmpty()) { | |
| 436 TRACE_EVENT_INSTANT0("android_webview", | |
| 437 "EarlyOut_EmptyVisibleRect", | |
| 438 TRACE_EVENT_SCOPE_THREAD); | |
| 439 return; | |
| 440 } | |
| 441 | |
| 442 if (last_egl_context_ != current_context) { | |
| 443 // TODO(boliu): Handle context lost | |
| 444 TRACE_EVENT_INSTANT0( | |
| 445 "android_webview", "EGLContextChanged", TRACE_EVENT_SCOPE_THREAD); | |
| 446 } | |
| 447 | |
| 448 if (!compositor_) { | |
| 449 TRACE_EVENT_INSTANT0( | |
| 450 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD); | |
| 451 return; | |
| 452 } | |
| 453 | |
| 454 // DrawGL may be called without OnDraw, so cancel |fallback_tick_| here as | |
| 455 // well just to be safe. | |
| 456 fallback_tick_.Cancel(); | |
| 457 | |
| 458 // Update memory budget. This will no-op in compositor if the policy has not | |
| 459 // changed since last draw. | |
| 460 content::SynchronousCompositorMemoryPolicy policy; | |
| 461 policy.bytes_limit = g_memory_multiplier * kBytesPerPixel * | |
| 462 cached_global_visible_rect_.width() * | |
| 463 cached_global_visible_rect_.height(); | |
| 464 // Round up to a multiple of kMemoryAllocationStep. | |
| 465 policy.bytes_limit = | |
| 466 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; | |
| 467 policy.num_resources_limit = g_num_gralloc_limit; | |
| 468 SetMemoryPolicy(policy); | |
| 469 | |
| 470 DCHECK(gl_surface_); | |
| 471 gl_surface_->SetBackingFrameBufferObject( | |
| 472 state_restore.framebuffer_binding_ext()); | |
| 473 | |
| 474 gfx::Transform transform; | |
| 475 transform.matrix().setColMajorf(draw_info->transform); | |
| 476 transform.Translate(scroll_at_start_of_frame_.x(), | |
| 477 scroll_at_start_of_frame_.y()); | |
| 478 gfx::Rect clip_rect(draw_info->clip_left, | |
| 479 draw_info->clip_top, | |
| 480 draw_info->clip_right - draw_info->clip_left, | |
| 481 draw_info->clip_bottom - draw_info->clip_top); | |
| 482 | |
| 483 // Assume we always draw the full visible rect if we are drawing into a layer. | |
| 484 bool drew_full_visible_rect = true; | |
| 485 | |
| 486 gfx::Rect viewport_rect; | |
| 487 if (!draw_info->is_layer) { | |
| 488 viewport_rect = cached_global_visible_rect_; | |
| 489 clip_rect.Intersect(viewport_rect); | |
| 490 drew_full_visible_rect = clip_rect.Contains(viewport_rect); | |
| 491 } else { | |
| 492 viewport_rect = clip_rect; | |
| 493 } | |
| 494 | |
| 495 block_invalidates_ = true; | |
| 496 // TODO(joth): Check return value. | |
| 497 compositor_->DemandDrawHw(gfx::Size(draw_info->width, draw_info->height), | |
| 498 transform, | |
| 499 viewport_rect, | |
| 500 clip_rect, | |
| 501 state_restore.stencil_enabled()); | |
| 502 block_invalidates_ = false; | |
| 503 gl_surface_->ResetBackingFrameBufferObject(); | |
| 504 | |
| 505 EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect); | |
| 506 } | |
| 507 | |
| 508 void InProcessViewRenderer::SetGlobalVisibleRect( | |
| 509 const gfx::Rect& visible_rect) { | |
| 510 cached_global_visible_rect_ = visible_rect; | 120 cached_global_visible_rect_ = visible_rect; |
| 511 } | 121 } |
| 512 | 122 |
| 513 bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas, | 123 bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, |
| 514 const gfx::Rect& clip) { | 124 const gfx::Rect& clip) { |
| 515 if (clip.IsEmpty()) { | 125 if (clip.IsEmpty()) { |
| 516 TRACE_EVENT_INSTANT0( | 126 TRACE_EVENT_INSTANT0( |
| 517 "android_webview", "EarlyOut_EmptyClip", TRACE_EVENT_SCOPE_THREAD); | 127 "android_webview", "EarlyOut_EmptyClip", TRACE_EVENT_SCOPE_THREAD); |
| 518 return true; | 128 return true; |
| 519 } | 129 } |
| 520 | 130 |
| 521 if (!compositor_) { | 131 if (!compositor_) { |
| 522 TRACE_EVENT_INSTANT0( | 132 TRACE_EVENT_INSTANT0( |
| 523 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD); | 133 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD); |
| 524 return false; | 134 return false; |
| 525 } | 135 } |
| 526 | 136 |
| 527 return JavaHelper::GetInstance()->RenderViaAuxilaryBitmapIfNeeded( | 137 return BrowserViewRendererJavaHelper::GetInstance() |
| 528 java_canvas, | 138 ->RenderViaAuxilaryBitmapIfNeeded( |
| 529 scroll_at_start_of_frame_, | 139 java_canvas, |
| 530 clip, | 140 scroll_at_start_of_frame_, |
| 531 base::Bind(&InProcessViewRenderer::CompositeSW, base::Unretained(this))); | 141 clip, |
| 142 base::Bind(&BrowserViewRenderer::CompositeSW, | |
| 143 base::Unretained(this))); | |
| 532 } | 144 } |
| 533 | 145 |
| 534 skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width, | 146 skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width, |
| 535 int height) { | 147 int height) { |
| 536 TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture"); | 148 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture"); |
| 537 | 149 |
| 538 // Return empty Picture objects for empty SkPictures. | 150 // Return empty Picture objects for empty SkPictures. |
| 539 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); | 151 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); |
| 540 if (width <= 0 || height <= 0) { | 152 if (width <= 0 || height <= 0) { |
| 541 return picture; | 153 return picture; |
| 542 } | 154 } |
| 543 | 155 |
| 544 // Reset scroll back to the origin, will go back to the old | 156 // Reset scroll back to the origin, will go back to the old |
| 545 // value when scroll_reset is out of scope. | 157 // value when scroll_reset is out of scope. |
| 546 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_, | 158 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_, |
| 547 gfx::Vector2d()); | 159 gfx::Vector2d()); |
| 548 | 160 |
| 549 SkCanvas* rec_canvas = picture->beginRecording(width, height, 0); | 161 SkCanvas* rec_canvas = picture->beginRecording(width, height, 0); |
| 550 if (compositor_) | 162 if (compositor_) |
| 551 CompositeSW(rec_canvas); | 163 CompositeSW(rec_canvas); |
| 552 picture->endRecording(); | 164 picture->endRecording(); |
| 553 return picture; | 165 return picture; |
| 554 } | 166 } |
| 555 | 167 |
| 556 void InProcessViewRenderer::EnableOnNewPicture(bool enabled) { | 168 void BrowserViewRenderer::EnableOnNewPicture(bool enabled) { |
| 557 on_new_picture_enable_ = enabled; | 169 on_new_picture_enable_ = enabled; |
| 558 EnsureContinuousInvalidation(NULL, false); | 170 EnsureContinuousInvalidation(NULL, false); |
| 559 } | 171 } |
| 560 | 172 |
| 561 void InProcessViewRenderer::ClearView() { | 173 void BrowserViewRenderer::ClearView() { |
| 562 TRACE_EVENT_INSTANT0("android_webview", | 174 TRACE_EVENT_INSTANT0("android_webview", |
| 563 "InProcessViewRenderer::ClearView", | 175 "BrowserViewRenderer::ClearView", |
| 564 TRACE_EVENT_SCOPE_THREAD); | 176 TRACE_EVENT_SCOPE_THREAD); |
| 565 if (clear_view_) | 177 if (clear_view_) |
| 566 return; | 178 return; |
| 567 | 179 |
| 568 clear_view_ = true; | 180 clear_view_ = true; |
| 569 // Always invalidate ignoring the compositor to actually clear the webview. | 181 // Always invalidate ignoring the compositor to actually clear the webview. |
| 570 EnsureContinuousInvalidation(NULL, true); | 182 EnsureContinuousInvalidation(NULL, true); |
| 571 } | 183 } |
| 572 | 184 |
| 573 void InProcessViewRenderer::SetIsPaused(bool paused) { | 185 void BrowserViewRenderer::SetIsPaused(bool paused) { |
| 574 TRACE_EVENT_INSTANT1("android_webview", | 186 TRACE_EVENT_INSTANT1("android_webview", |
| 575 "InProcessViewRenderer::SetIsPaused", | 187 "BrowserViewRenderer::SetIsPaused", |
| 576 TRACE_EVENT_SCOPE_THREAD, | 188 TRACE_EVENT_SCOPE_THREAD, |
| 577 "paused", | 189 "paused", |
| 578 paused); | 190 paused); |
| 579 is_paused_ = paused; | 191 is_paused_ = paused; |
| 580 EnsureContinuousInvalidation(NULL, false); | 192 EnsureContinuousInvalidation(NULL, false); |
| 581 } | 193 } |
| 582 | 194 |
| 583 void InProcessViewRenderer::SetViewVisibility(bool view_visible) { | 195 void BrowserViewRenderer::SetViewVisibility(bool view_visible) { |
| 584 TRACE_EVENT_INSTANT1("android_webview", | 196 TRACE_EVENT_INSTANT1("android_webview", |
| 585 "InProcessViewRenderer::SetViewVisibility", | 197 "BrowserViewRenderer::SetViewVisibility", |
| 586 TRACE_EVENT_SCOPE_THREAD, | 198 TRACE_EVENT_SCOPE_THREAD, |
| 587 "view_visible", | 199 "view_visible", |
| 588 view_visible); | 200 view_visible); |
| 589 view_visible_ = view_visible; | 201 view_visible_ = view_visible; |
| 590 } | 202 } |
| 591 | 203 |
| 592 void InProcessViewRenderer::SetWindowVisibility(bool window_visible) { | 204 void BrowserViewRenderer::SetWindowVisibility(bool window_visible) { |
| 593 TRACE_EVENT_INSTANT1("android_webview", | 205 TRACE_EVENT_INSTANT1("android_webview", |
| 594 "InProcessViewRenderer::SetWindowVisibility", | 206 "BrowserViewRenderer::SetWindowVisibility", |
| 595 TRACE_EVENT_SCOPE_THREAD, | 207 TRACE_EVENT_SCOPE_THREAD, |
| 596 "window_visible", | 208 "window_visible", |
| 597 window_visible); | 209 window_visible); |
| 598 window_visible_ = window_visible; | 210 window_visible_ = window_visible; |
| 599 EnsureContinuousInvalidation(NULL, false); | 211 EnsureContinuousInvalidation(NULL, false); |
| 600 } | 212 } |
| 601 | 213 |
| 602 void InProcessViewRenderer::OnSizeChanged(int width, int height) { | 214 void BrowserViewRenderer::OnSizeChanged(int width, int height) { |
| 603 TRACE_EVENT_INSTANT2("android_webview", | 215 TRACE_EVENT_INSTANT2("android_webview", |
| 604 "InProcessViewRenderer::OnSizeChanged", | 216 "BrowserViewRenderer::OnSizeChanged", |
| 605 TRACE_EVENT_SCOPE_THREAD, | 217 TRACE_EVENT_SCOPE_THREAD, |
| 606 "width", | 218 "width", |
| 607 width, | 219 width, |
| 608 "height", | 220 "height", |
| 609 height); | 221 height); |
| 610 width_ = width; | 222 width_ = width; |
| 611 height_ = height; | 223 height_ = height; |
| 612 } | 224 } |
| 613 | 225 |
| 614 void InProcessViewRenderer::OnAttachedToWindow(int width, int height) { | 226 void BrowserViewRenderer::OnAttachedToWindow(int width, int height) { |
| 615 TRACE_EVENT2("android_webview", | 227 TRACE_EVENT2("android_webview", |
| 616 "InProcessViewRenderer::OnAttachedToWindow", | 228 "BrowserViewRenderer::OnAttachedToWindow", |
| 617 "width", | 229 "width", |
| 618 width, | 230 width, |
| 619 "height", | 231 "height", |
| 620 height); | 232 height); |
| 621 attached_to_window_ = true; | 233 attached_to_window_ = true; |
| 622 width_ = width; | 234 width_ = width; |
| 623 height_ = height; | 235 height_ = height; |
| 624 } | 236 } |
| 625 | 237 |
| 626 void InProcessViewRenderer::OnDetachedFromWindow() { | 238 void BrowserViewRenderer::OnDetachedFromWindow() { |
| 627 TRACE_EVENT0("android_webview", | 239 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow"); |
| 628 "InProcessViewRenderer::OnDetachedFromWindow"); | |
| 629 | |
| 630 NoLongerExpectsDrawGL(); | |
| 631 if (hardware_initialized_) { | |
| 632 DCHECK(compositor_); | |
| 633 | |
| 634 ScopedAppGLStateRestore state_restore( | |
| 635 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | |
| 636 g_service.Get()->RunTasks(); | |
| 637 ScopedAllowGL allow_gl; | |
| 638 compositor_->ReleaseHwDraw(); | |
| 639 hardware_initialized_ = false; | |
| 640 } | |
| 641 | |
| 642 gl_surface_ = NULL; | |
| 643 attached_to_window_ = false; | 240 attached_to_window_ = false; |
| 241 hardware_renderer_.reset(); | |
| 644 } | 242 } |
| 645 | 243 |
| 646 bool InProcessViewRenderer::IsAttachedToWindow() { | 244 bool BrowserViewRenderer::IsAttachedToWindow() const { |
| 647 return attached_to_window_; | 245 return attached_to_window_; |
| 648 } | 246 } |
| 649 | 247 |
| 650 bool InProcessViewRenderer::IsVisible() { | 248 bool BrowserViewRenderer::IsVisible() const { |
| 651 // Ignore |window_visible_| if |attached_to_window_| is false. | 249 // Ignore |window_visible_| if |attached_to_window_| is false. |
| 652 return view_visible_ && (!attached_to_window_ || window_visible_); | 250 return view_visible_ && (!attached_to_window_ || window_visible_); |
| 653 } | 251 } |
| 654 | 252 |
| 655 gfx::Rect InProcessViewRenderer::GetScreenRect() { | 253 gfx::Rect BrowserViewRenderer::GetScreenRect() const { |
| 656 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_)); | 254 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_)); |
| 657 } | 255 } |
| 658 | 256 |
| 659 void InProcessViewRenderer::DidInitializeCompositor( | 257 void BrowserViewRenderer::DidInitializeCompositor( |
| 660 content::SynchronousCompositor* compositor) { | 258 content::SynchronousCompositor* compositor) { |
| 661 TRACE_EVENT0("android_webview", | 259 TRACE_EVENT0("android_webview", |
| 662 "InProcessViewRenderer::DidInitializeCompositor"); | 260 "BrowserViewRenderer::DidInitializeCompositor"); |
| 663 DCHECK(compositor && compositor_ == NULL); | 261 DCHECK(compositor && compositor_ == NULL); |
| 664 compositor_ = compositor; | 262 compositor_ = compositor; |
| 665 hardware_initialized_ = false; | |
| 666 hardware_failed_ = false; | |
| 667 } | 263 } |
| 668 | 264 |
| 669 void InProcessViewRenderer::DidDestroyCompositor( | 265 void BrowserViewRenderer::DidDestroyCompositor( |
| 670 content::SynchronousCompositor* compositor) { | 266 content::SynchronousCompositor* compositor) { |
| 671 TRACE_EVENT0("android_webview", | 267 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); |
| 672 "InProcessViewRenderer::DidDestroyCompositor"); | |
| 673 DCHECK(compositor_ == compositor); | 268 DCHECK(compositor_ == compositor); |
| 674 | 269 DCHECK(!hardware_renderer_.get()); |
|
benm (inactive)
2014/02/25 12:48:01
does this replace the LOG_IF?
boliu
2014/02/25 19:02:22
Yes. We already delay destroy until after onDetach
| |
| 675 // This can fail if Apps call destroy while the webview is still attached | |
| 676 // to the view tree. This is an illegal operation that will lead to leaks. | |
| 677 // Log for now. Consider a proper fix if this becomes a problem. | |
| 678 LOG_IF(ERROR, hardware_initialized_) | |
| 679 << "Destroy called before OnDetachedFromWindow. May Leak GL resources"; | |
| 680 compositor_ = NULL; | 270 compositor_ = NULL; |
| 681 } | 271 } |
| 682 | 272 |
| 683 void InProcessViewRenderer::SetContinuousInvalidate(bool invalidate) { | 273 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { |
| 684 if (compositor_needs_continuous_invalidate_ == invalidate) | 274 if (compositor_needs_continuous_invalidate_ == invalidate) |
| 685 return; | 275 return; |
| 686 | 276 |
| 687 TRACE_EVENT_INSTANT1("android_webview", | 277 TRACE_EVENT_INSTANT1("android_webview", |
| 688 "InProcessViewRenderer::SetContinuousInvalidate", | 278 "BrowserViewRenderer::SetContinuousInvalidate", |
| 689 TRACE_EVENT_SCOPE_THREAD, | 279 TRACE_EVENT_SCOPE_THREAD, |
| 690 "invalidate", | 280 "invalidate", |
| 691 invalidate); | 281 invalidate); |
| 692 compositor_needs_continuous_invalidate_ = invalidate; | 282 compositor_needs_continuous_invalidate_ = invalidate; |
| 693 EnsureContinuousInvalidation(NULL, false); | 283 EnsureContinuousInvalidation(NULL, false); |
| 694 } | 284 } |
| 695 | 285 |
| 696 void InProcessViewRenderer::SetDipScale(float dip_scale) { | 286 void BrowserViewRenderer::SetDipScale(float dip_scale) { |
| 697 dip_scale_ = dip_scale; | 287 dip_scale_ = dip_scale; |
| 698 CHECK(dip_scale_ > 0); | 288 CHECK(dip_scale_ > 0); |
| 699 } | 289 } |
| 700 | 290 |
| 701 gfx::Vector2d InProcessViewRenderer::max_scroll_offset() const { | 291 gfx::Vector2d BrowserViewRenderer::max_scroll_offset() const { |
| 702 DCHECK_GT(dip_scale_, 0); | 292 DCHECK_GT(dip_scale_, 0); |
| 703 return gfx::ToCeiledVector2d(gfx::ScaleVector2d( | 293 return gfx::ToCeiledVector2d(gfx::ScaleVector2d( |
| 704 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_)); | 294 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_)); |
| 705 } | 295 } |
| 706 | 296 |
| 707 void InProcessViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) { | 297 void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) { |
| 708 gfx::Vector2d max_offset = max_scroll_offset(); | 298 gfx::Vector2d max_offset = max_scroll_offset(); |
| 709 gfx::Vector2dF scroll_offset_dip; | 299 gfx::Vector2dF scroll_offset_dip; |
| 710 // To preserve the invariant that scrolling to the maximum physical pixel | 300 // To preserve the invariant that scrolling to the maximum physical pixel |
| 711 // value also scrolls to the maximum dip pixel value we transform the physical | 301 // value also scrolls to the maximum dip pixel value we transform the physical |
| 712 // offset into the dip offset by using a proportion (instead of dividing by | 302 // offset into the dip offset by using a proportion (instead of dividing by |
| 713 // dip_scale * page_scale_factor). | 303 // dip_scale * page_scale_factor). |
| 714 if (max_offset.x()) { | 304 if (max_offset.x()) { |
| 715 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) / | 305 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) / |
| 716 max_offset.x()); | 306 max_offset.x()); |
| 717 } | 307 } |
| 718 if (max_offset.y()) { | 308 if (max_offset.y()) { |
| 719 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) / | 309 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) / |
| 720 max_offset.y()); | 310 max_offset.y()); |
| 721 } | 311 } |
| 722 | 312 |
| 723 DCHECK_LE(0, scroll_offset_dip.x()); | 313 DCHECK_LE(0, scroll_offset_dip.x()); |
| 724 DCHECK_LE(0, scroll_offset_dip.y()); | 314 DCHECK_LE(0, scroll_offset_dip.y()); |
| 725 DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x()); | 315 DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x()); |
| 726 DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y()); | 316 DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y()); |
| 727 | 317 |
| 728 if (scroll_offset_dip_ == scroll_offset_dip) | 318 if (scroll_offset_dip_ == scroll_offset_dip) |
| 729 return; | 319 return; |
| 730 | 320 |
| 731 scroll_offset_dip_ = scroll_offset_dip; | 321 scroll_offset_dip_ = scroll_offset_dip; |
| 732 | 322 |
| 733 if (compositor_) | 323 if (compositor_) |
| 734 compositor_->DidChangeRootLayerScrollOffset(); | 324 compositor_->DidChangeRootLayerScrollOffset(); |
| 735 } | 325 } |
| 736 | 326 |
| 737 void InProcessViewRenderer::DidUpdateContent() { | 327 void BrowserViewRenderer::DidUpdateContent() { |
| 738 TRACE_EVENT_INSTANT0("android_webview", | 328 TRACE_EVENT_INSTANT0("android_webview", |
| 739 "InProcessViewRenderer::DidUpdateContent", | 329 "BrowserViewRenderer::DidUpdateContent", |
| 740 TRACE_EVENT_SCOPE_THREAD); | 330 TRACE_EVENT_SCOPE_THREAD); |
| 741 clear_view_ = false; | 331 clear_view_ = false; |
| 742 EnsureContinuousInvalidation(NULL, false); | 332 EnsureContinuousInvalidation(NULL, false); |
| 743 if (on_new_picture_enable_) | 333 if (on_new_picture_enable_) |
| 744 client_->OnNewPicture(); | 334 client_->OnNewPicture(); |
| 745 } | 335 } |
| 746 | 336 |
| 747 void InProcessViewRenderer::SetMaxRootLayerScrollOffset( | 337 void BrowserViewRenderer::SetMaxRootLayerScrollOffset( |
| 748 gfx::Vector2dF new_value_dip) { | 338 gfx::Vector2dF new_value_dip) { |
| 749 DCHECK_GT(dip_scale_, 0); | 339 DCHECK_GT(dip_scale_, 0); |
| 750 | 340 |
| 751 max_scroll_offset_dip_ = new_value_dip; | 341 max_scroll_offset_dip_ = new_value_dip; |
| 752 DCHECK_LE(0, max_scroll_offset_dip_.x()); | 342 DCHECK_LE(0, max_scroll_offset_dip_.x()); |
| 753 DCHECK_LE(0, max_scroll_offset_dip_.y()); | 343 DCHECK_LE(0, max_scroll_offset_dip_.y()); |
| 754 | 344 |
| 755 client_->SetMaxContainerViewScrollOffset(max_scroll_offset()); | 345 client_->SetMaxContainerViewScrollOffset(max_scroll_offset()); |
| 756 } | 346 } |
| 757 | 347 |
| 758 void InProcessViewRenderer::SetTotalRootLayerScrollOffset( | 348 void BrowserViewRenderer::SetTotalRootLayerScrollOffset( |
| 759 gfx::Vector2dF scroll_offset_dip) { | 349 gfx::Vector2dF scroll_offset_dip) { |
| 760 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during | 350 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during |
| 761 // DrawGl when http://crbug.com/249972 is fixed. | 351 // DrawGl when http://crbug.com/249972 is fixed. |
| 762 if (scroll_offset_dip_ == scroll_offset_dip) | 352 if (scroll_offset_dip_ == scroll_offset_dip) |
| 763 return; | 353 return; |
| 764 | 354 |
| 765 scroll_offset_dip_ = scroll_offset_dip; | 355 scroll_offset_dip_ = scroll_offset_dip; |
| 766 | 356 |
| 767 gfx::Vector2d max_offset = max_scroll_offset(); | 357 gfx::Vector2d max_offset = max_scroll_offset(); |
| 768 gfx::Vector2d scroll_offset; | 358 gfx::Vector2d scroll_offset; |
| 769 // For an explanation as to why this is done this way see the comment in | 359 // For an explanation as to why this is done this way see the comment in |
| 770 // InProcessViewRenderer::ScrollTo. | 360 // BrowserViewRenderer::ScrollTo. |
| 771 if (max_scroll_offset_dip_.x()) { | 361 if (max_scroll_offset_dip_.x()) { |
| 772 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) / | 362 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) / |
| 773 max_scroll_offset_dip_.x()); | 363 max_scroll_offset_dip_.x()); |
| 774 } | 364 } |
| 775 | 365 |
| 776 if (max_scroll_offset_dip_.y()) { | 366 if (max_scroll_offset_dip_.y()) { |
| 777 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) / | 367 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) / |
| 778 max_scroll_offset_dip_.y()); | 368 max_scroll_offset_dip_.y()); |
| 779 } | 369 } |
| 780 | 370 |
| 781 DCHECK(0 <= scroll_offset.x()); | 371 DCHECK(0 <= scroll_offset.x()); |
| 782 DCHECK(0 <= scroll_offset.y()); | 372 DCHECK(0 <= scroll_offset.y()); |
| 783 // Disabled because the conditions are being violated while running | 373 // Disabled because the conditions are being violated while running |
| 784 // AwZoomTest.testMagnification, see http://crbug.com/340648 | 374 // AwZoomTest.testMagnification, see http://crbug.com/340648 |
| 785 // DCHECK(scroll_offset.x() <= max_offset.x()); | 375 // DCHECK(scroll_offset.x() <= max_offset.x()); |
| 786 // DCHECK(scroll_offset.y() <= max_offset.y()); | 376 // DCHECK(scroll_offset.y() <= max_offset.y()); |
| 787 | 377 |
| 788 client_->ScrollContainerViewTo(scroll_offset); | 378 client_->ScrollContainerViewTo(scroll_offset); |
| 789 } | 379 } |
| 790 | 380 |
| 791 gfx::Vector2dF InProcessViewRenderer::GetTotalRootLayerScrollOffset() { | 381 gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() { |
| 792 return scroll_offset_dip_; | 382 return scroll_offset_dip_; |
| 793 } | 383 } |
| 794 | 384 |
| 795 bool InProcessViewRenderer::IsExternalFlingActive() const { | 385 bool BrowserViewRenderer::IsExternalFlingActive() const { |
| 796 return client_->IsFlingActive(); | 386 return client_->IsFlingActive(); |
| 797 } | 387 } |
| 798 | 388 |
| 799 void InProcessViewRenderer::SetRootLayerPageScaleFactorAndLimits( | 389 void BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits( |
| 800 float page_scale_factor, | 390 float page_scale_factor, |
| 801 float min_page_scale_factor, | 391 float min_page_scale_factor, |
| 802 float max_page_scale_factor) { | 392 float max_page_scale_factor) { |
| 803 page_scale_factor_ = page_scale_factor; | 393 page_scale_factor_ = page_scale_factor; |
| 804 DCHECK_GT(page_scale_factor_, 0); | 394 DCHECK_GT(page_scale_factor_, 0); |
| 805 client_->SetPageScaleFactorAndLimits( | 395 client_->SetPageScaleFactorAndLimits( |
| 806 page_scale_factor, min_page_scale_factor, max_page_scale_factor); | 396 page_scale_factor, min_page_scale_factor, max_page_scale_factor); |
| 807 } | 397 } |
| 808 | 398 |
| 809 void InProcessViewRenderer::SetRootLayerScrollableSize( | 399 void BrowserViewRenderer::SetRootLayerScrollableSize( |
| 810 gfx::SizeF scrollable_size) { | 400 gfx::SizeF scrollable_size) { |
| 811 client_->SetContentsSize(scrollable_size); | 401 client_->SetContentsSize(scrollable_size); |
| 812 } | 402 } |
| 813 | 403 |
| 814 void InProcessViewRenderer::DidOverscroll( | 404 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll, |
| 815 gfx::Vector2dF accumulated_overscroll, | 405 gfx::Vector2dF latest_overscroll_delta, |
| 816 gfx::Vector2dF latest_overscroll_delta, | 406 gfx::Vector2dF current_fling_velocity) { |
| 817 gfx::Vector2dF current_fling_velocity) { | |
| 818 const float physical_pixel_scale = dip_scale_ * page_scale_factor_; | 407 const float physical_pixel_scale = dip_scale_ * page_scale_factor_; |
| 819 if (accumulated_overscroll == latest_overscroll_delta) | 408 if (accumulated_overscroll == latest_overscroll_delta) |
| 820 overscroll_rounding_error_ = gfx::Vector2dF(); | 409 overscroll_rounding_error_ = gfx::Vector2dF(); |
| 821 gfx::Vector2dF scaled_overscroll_delta = | 410 gfx::Vector2dF scaled_overscroll_delta = |
| 822 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale); | 411 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale); |
| 823 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d( | 412 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d( |
| 824 scaled_overscroll_delta + overscroll_rounding_error_); | 413 scaled_overscroll_delta + overscroll_rounding_error_); |
| 825 overscroll_rounding_error_ = | 414 overscroll_rounding_error_ = |
| 826 scaled_overscroll_delta - rounded_overscroll_delta; | 415 scaled_overscroll_delta - rounded_overscroll_delta; |
| 827 client_->DidOverscroll(rounded_overscroll_delta); | 416 client_->DidOverscroll(rounded_overscroll_delta); |
| 828 } | 417 } |
| 829 | 418 |
| 830 void InProcessViewRenderer::EnsureContinuousInvalidation( | 419 void BrowserViewRenderer::EnsureContinuousInvalidation( |
| 831 AwDrawGLInfo* draw_info, | 420 AwDrawGLInfo* draw_info, |
| 832 bool invalidate_ignore_compositor) { | 421 bool invalidate_ignore_compositor) { |
| 833 // This method should be called again when any of these conditions change. | 422 // This method should be called again when any of these conditions change. |
| 834 bool need_invalidate = | 423 bool need_invalidate = |
| 835 compositor_needs_continuous_invalidate_ || invalidate_ignore_compositor; | 424 compositor_needs_continuous_invalidate_ || invalidate_ignore_compositor; |
| 836 if (!need_invalidate || block_invalidates_) | 425 if (!need_invalidate || block_invalidates_) |
| 837 return; | 426 return; |
| 838 | 427 |
| 839 // Always call view invalidate. We rely the Android framework to ignore the | 428 // Always call view invalidate. We rely the Android framework to ignore the |
| 840 // invalidate when it's not needed such as when view is not visible. | 429 // invalidate when it's not needed such as when view is not visible. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 856 // "on-screen" but that updates are not needed when in the background. | 445 // "on-screen" but that updates are not needed when in the background. |
| 857 bool throttle_fallback_tick = | 446 bool throttle_fallback_tick = |
| 858 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_); | 447 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_); |
| 859 if (throttle_fallback_tick) | 448 if (throttle_fallback_tick) |
| 860 return; | 449 return; |
| 861 | 450 |
| 862 block_invalidates_ = compositor_needs_continuous_invalidate_; | 451 block_invalidates_ = compositor_needs_continuous_invalidate_; |
| 863 | 452 |
| 864 // Unretained here is safe because the callback is cancelled when | 453 // Unretained here is safe because the callback is cancelled when |
| 865 // |fallback_tick_| is destroyed. | 454 // |fallback_tick_| is destroyed. |
| 866 fallback_tick_.Reset(base::Bind(&InProcessViewRenderer::FallbackTickFired, | 455 fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired, |
| 867 base::Unretained(this))); | 456 base::Unretained(this))); |
| 868 | 457 |
| 869 // No need to reschedule fallback tick if compositor does not need to be | 458 // No need to reschedule fallback tick if compositor does not need to be |
| 870 // ticked. This can happen if this is reached because | 459 // ticked. This can happen if this is reached because |
| 871 // invalidate_ignore_compositor is true. | 460 // invalidate_ignore_compositor is true. |
| 872 if (compositor_needs_continuous_invalidate_) { | 461 if (compositor_needs_continuous_invalidate_) { |
| 873 BrowserThread::PostDelayedTask( | 462 BrowserThread::PostDelayedTask( |
| 874 BrowserThread::UI, | 463 BrowserThread::UI, |
| 875 FROM_HERE, | 464 FROM_HERE, |
| 876 fallback_tick_.callback(), | 465 fallback_tick_.callback(), |
| 877 base::TimeDelta::FromMilliseconds( | 466 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds)); |
| 878 kFallbackTickTimeoutInMilliseconds)); | |
| 879 } | 467 } |
| 880 } | 468 } |
| 881 | 469 |
| 882 void InProcessViewRenderer::FallbackTickFired() { | 470 void BrowserViewRenderer::FallbackTickFired() { |
| 883 TRACE_EVENT1("android_webview", | 471 TRACE_EVENT1("android_webview", |
| 884 "InProcessViewRenderer::FallbackTickFired", | 472 "BrowserViewRenderer::FallbackTickFired", |
| 885 "compositor_needs_continuous_invalidate_", | 473 "compositor_needs_continuous_invalidate_", |
| 886 compositor_needs_continuous_invalidate_); | 474 compositor_needs_continuous_invalidate_); |
| 887 | 475 |
| 888 // This should only be called if OnDraw or DrawGL did not come in time, which | 476 // This should only be called if OnDraw or DrawGL did not come in time, which |
| 889 // means block_invalidates_ must still be true. | 477 // means block_invalidates_ must still be true. |
| 890 DCHECK(block_invalidates_); | 478 DCHECK(block_invalidates_); |
| 891 if (compositor_needs_continuous_invalidate_ && compositor_) | 479 if (compositor_needs_continuous_invalidate_ && compositor_) |
| 892 ForceFakeCompositeSW(); | 480 ForceFakeCompositeSW(); |
| 893 } | 481 } |
| 894 | 482 |
| 895 void InProcessViewRenderer::ForceFakeCompositeSW() { | 483 void BrowserViewRenderer::ForceFakeCompositeSW() { |
| 896 DCHECK(compositor_); | 484 DCHECK(compositor_); |
| 897 SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 1, 1); | 485 SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 1, 1); |
| 898 SkCanvas canvas(&device); | 486 SkCanvas canvas(&device); |
| 899 CompositeSW(&canvas); | 487 CompositeSW(&canvas); |
| 900 } | 488 } |
| 901 | 489 |
| 902 bool InProcessViewRenderer::CompositeSW(SkCanvas* canvas) { | 490 bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) { |
| 903 DCHECK(compositor_); | 491 DCHECK(compositor_); |
| 904 | 492 |
| 905 fallback_tick_.Cancel(); | 493 fallback_tick_.Cancel(); |
| 906 block_invalidates_ = true; | 494 block_invalidates_ = true; |
| 907 bool result = compositor_->DemandDrawSw(canvas); | 495 bool result = compositor_->DemandDrawSw(canvas); |
| 908 block_invalidates_ = false; | 496 block_invalidates_ = false; |
| 909 EnsureContinuousInvalidation(NULL, false); | 497 EnsureContinuousInvalidation(NULL, false); |
| 910 return result; | 498 return result; |
| 911 } | 499 } |
| 912 | 500 |
| 913 std::string InProcessViewRenderer::ToString(AwDrawGLInfo* draw_info) const { | 501 std::string BrowserViewRenderer::ToString(AwDrawGLInfo* draw_info) const { |
| 914 std::string str; | 502 std::string str; |
| 915 base::StringAppendF(&str, "is_paused: %d ", is_paused_); | 503 base::StringAppendF(&str, "is_paused: %d ", is_paused_); |
| 916 base::StringAppendF(&str, "view_visible: %d ", view_visible_); | 504 base::StringAppendF(&str, "view_visible: %d ", view_visible_); |
| 917 base::StringAppendF(&str, "window_visible: %d ", window_visible_); | 505 base::StringAppendF(&str, "window_visible: %d ", window_visible_); |
| 918 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_); | 506 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_); |
| 919 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_); | 507 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_); |
| 920 base::StringAppendF(&str, | 508 base::StringAppendF(&str, |
| 921 "compositor_needs_continuous_invalidate: %d ", | 509 "compositor_needs_continuous_invalidate: %d ", |
| 922 compositor_needs_continuous_invalidate_); | 510 compositor_needs_continuous_invalidate_); |
| 923 base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_); | 511 base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_); |
| 924 base::StringAppendF(&str, "view width height: [%d %d] ", width_, height_); | 512 base::StringAppendF(&str, "view width height: [%d %d] ", width_, height_); |
| 925 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); | 513 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); |
| 926 base::StringAppendF(&str, "hardware_initialized: %d ", hardware_initialized_); | |
| 927 base::StringAppendF(&str, "hardware_failed: %d ", hardware_failed_); | |
| 928 base::StringAppendF(&str, | 514 base::StringAppendF(&str, |
| 929 "global visible rect: %s ", | 515 "global visible rect: %s ", |
| 930 cached_global_visible_rect_.ToString().c_str()); | 516 cached_global_visible_rect_.ToString().c_str()); |
| 931 base::StringAppendF(&str, | 517 base::StringAppendF(&str, |
| 932 "scroll_at_start_of_frame: %s ", | 518 "scroll_at_start_of_frame: %s ", |
| 933 scroll_at_start_of_frame_.ToString().c_str()); | 519 scroll_at_start_of_frame_.ToString().c_str()); |
| 934 base::StringAppendF( | 520 base::StringAppendF( |
| 935 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str()); | 521 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str()); |
| 936 base::StringAppendF(&str, | 522 base::StringAppendF(&str, |
| 937 "overscroll_rounding_error_: %s ", | 523 "overscroll_rounding_error_: %s ", |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 949 base::StringAppendF(&str, | 535 base::StringAppendF(&str, |
| 950 "surface width height: [%d %d] ", | 536 "surface width height: [%d %d] ", |
| 951 draw_info->width, | 537 draw_info->width, |
| 952 draw_info->height); | 538 draw_info->height); |
| 953 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); | 539 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); |
| 954 } | 540 } |
| 955 return str; | 541 return str; |
| 956 } | 542 } |
| 957 | 543 |
| 958 } // namespace android_webview | 544 } // namespace android_webview |
| OLD | NEW |