Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: content/browser/renderer_host/compositor_impl_android.cc

Issue 285373008: Android: Decouple animate from vsync (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/renderer_host/compositor_impl_android.h" 5 #include "content/browser/renderer_host/compositor_impl_android.h"
6 6
7 #include <android/bitmap.h> 7 #include <android/bitmap.h>
8 #include <android/native_window_jni.h> 8 #include <android/native_window_jni.h>
9 9
10 #include "base/android/jni_android.h" 10 #include "base/android/jni_android.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 #include "ui/gl/android/surface_texture_tracker.h" 50 #include "ui/gl/android/surface_texture_tracker.h"
51 #include "webkit/common/gpu/context_provider_in_process.h" 51 #include "webkit/common/gpu/context_provider_in_process.h"
52 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl. h" 52 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl. h"
53 53
54 namespace gfx { 54 namespace gfx {
55 class JavaBitmap; 55 class JavaBitmap;
56 } 56 }
57 57
58 namespace { 58 namespace {
59 59
60 const unsigned int kMaxSwapBuffers = 2U;
61
60 // Used to override capabilities_.adjust_deadline_for_parent to false 62 // Used to override capabilities_.adjust_deadline_for_parent to false
61 class OutputSurfaceWithoutParent : public cc::OutputSurface { 63 class OutputSurfaceWithoutParent : public cc::OutputSurface {
62 public: 64 public:
63 OutputSurfaceWithoutParent(const scoped_refptr< 65 OutputSurfaceWithoutParent(const scoped_refptr<
64 content::ContextProviderCommandBuffer>& context_provider) 66 content::ContextProviderCommandBuffer>& context_provider)
65 : cc::OutputSurface(context_provider) { 67 : cc::OutputSurface(context_provider) {
66 capabilities_.adjust_deadline_for_parent = false; 68 capabilities_.adjust_deadline_for_parent = false;
67 } 69 }
68 70
69 virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE { 71 virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 : root_layer_(cc::Layer::Create()), 237 : root_layer_(cc::Layer::Create()),
236 has_transparent_background_(false), 238 has_transparent_background_(false),
237 device_scale_factor_(1), 239 device_scale_factor_(1),
238 window_(NULL), 240 window_(NULL),
239 surface_id_(0), 241 surface_id_(0),
240 client_(client), 242 client_(client),
241 root_window_(root_window), 243 root_window_(root_window),
242 did_post_swapbuffers_(false), 244 did_post_swapbuffers_(false),
243 ignore_schedule_composite_(false), 245 ignore_schedule_composite_(false),
244 needs_composite_(false), 246 needs_composite_(false),
245 should_composite_on_vsync_(false), 247 needs_animate_(false),
246 did_composite_this_frame_(false), 248 will_composite_immediately_(false),
247 pending_swapbuffers_(0U), 249 composite_on_vsync_trigger_(DO_NOT_COMPOSITE),
248 weak_factory_(this) { 250 pending_swapbuffers_(0U) {
249 DCHECK(client); 251 DCHECK(client);
250 DCHECK(root_window); 252 DCHECK(root_window);
251 ImageTransportFactoryAndroid::AddObserver(this); 253 ImageTransportFactoryAndroid::AddObserver(this);
252 root_window->AttachCompositor(this); 254 root_window->AttachCompositor(this);
253 } 255 }
254 256
255 CompositorImpl::~CompositorImpl() { 257 CompositorImpl::~CompositorImpl() {
256 root_window_->DetachCompositor(); 258 root_window_->DetachCompositor();
257 ImageTransportFactoryAndroid::RemoveObserver(this); 259 ImageTransportFactoryAndroid::RemoveObserver(this);
258 // Clean-up any surface references. 260 // Clean-up any surface references.
259 SetSurface(NULL); 261 SetSurface(NULL);
260 } 262 }
261 263
262 void CompositorImpl::PostComposite(base::TimeDelta delay) { 264 void CompositorImpl::PostComposite(CompositingTrigger trigger) {
265 DCHECK(needs_composite_);
266 DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
267
268 if (will_composite_immediately_ ||
269 (trigger == COMPOSITE_EVENTUALLY && WillComposite())) {
270 // We will already composite soon enough.
271 DCHECK(WillComposite());
272 return;
273 }
274
275 if (DidCompositeThisFrame()) {
276 DCHECK(!WillCompositeThisFrame());
277 if (!WillComposite()) {
278 if (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) {
279 composite_on_vsync_trigger_ = trigger;
280 root_window_->RequestVSyncUpdate();
281 }
282 DCHECK(WillComposite());
brianderson 2014/05/23 22:34:25 The value of WillComposite() will only change if c
no sievers 2014/05/27 18:20:45 Thanks, I think line 277 is actually wrong because
283 }
284 return;
285 }
286
287 base::TimeDelta delay;
288 if (trigger == COMPOSITE_IMMEDIATELY) {
289 will_composite_immediately_ = true;
290 } else {
291 DCHECK(!WillComposite());
292 const base::TimeDelta estimated_composite_time = vsync_period_ / 4;
293 const base::TimeTicks now = base::TimeTicks::Now();
294
295 if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) {
296 base::TimeTicks next_composite =
297 last_vsync_ + vsync_period_ - estimated_composite_time;
298 if (next_composite < now) {
299 // It's too late, we will reschedule composite as needed on the next
300 // vsync.
no sievers 2014/05/23 18:27:22 You think we should do this for COMPOSITE_IMMEDIAT
brianderson 2014/05/23 22:34:25 No, I think we should just composite the Renderer
301 composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
302 root_window_->RequestVSyncUpdate();
303 DCHECK(WillComposite());
304 return;
305 }
306
307 delay = next_composite - now;
308 }
309 }
310 TRACE_EVENT2("cc", "CompositorImpl::PostComposite",
311 "trigger", trigger,
312 "delay", delay.InMillisecondsF());
313
314 if (current_composite_task_)
315 current_composite_task_->Cancel();
316
317 // Unretained because we cancel the task on shutdown.
318 current_composite_task_.reset(new base::CancelableClosure(
319 base::Bind(&CompositorImpl::Composite, base::Unretained(this), trigger)));
263 base::MessageLoop::current()->PostDelayedTask( 320 base::MessageLoop::current()->PostDelayedTask(
264 FROM_HERE, 321 FROM_HERE, current_composite_task_->callback(), delay);
265 base::Bind(&CompositorImpl::Composite,
266 weak_factory_.GetWeakPtr(),
267 COMPOSITE_IMMEDIATELY),
268 delay);
269 } 322 }
270 323
271 void CompositorImpl::Composite(CompositingTrigger trigger) { 324 void CompositorImpl::Composite(CompositingTrigger trigger) {
272 if (!host_) 325 DCHECK(host_);
273 return; 326 DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
327 DCHECK(needs_composite_);
328 DCHECK(!DidCompositeThisFrame());
329 DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE);
274 330
275 if (!needs_composite_) 331 if (trigger == COMPOSITE_IMMEDIATELY)
276 return; 332 will_composite_immediately_ = false;
277 333
278 if (trigger != COMPOSITE_ON_VSYNC && should_composite_on_vsync_) {
279 TRACE_EVENT0("compositor", "CompositorImpl_DeferCompositeToVSync");
280 root_window_->RequestVSyncUpdate();
281 return;
282 }
283
284 // Don't Composite more than once in between vsync ticks.
285 if (did_composite_this_frame_) {
286 TRACE_EVENT0("compositor", "CompositorImpl_ThrottleComposite");
287 if (should_composite_on_vsync_)
288 root_window_->RequestVSyncUpdate();
289 else
290 PostComposite(vsync_period_);
291 return;
292 }
293
294 const unsigned int kMaxSwapBuffers = 2U;
295 DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers); 334 DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers);
296 if (pending_swapbuffers_ == kMaxSwapBuffers) { 335 if (pending_swapbuffers_ == kMaxSwapBuffers) {
297 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); 336 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit");
298 if (should_composite_on_vsync_)
299 root_window_->RequestVSyncUpdate();
300 else
301 PostComposite(vsync_period_);
302 return; 337 return;
303 } 338 }
304 339
305 // Reset state before Layout+Composite since that might create more 340 // Reset state before Layout+Composite since that might create more
306 // requests to Composite that we need to respect. 341 // requests to Composite that we need to respect.
307 needs_composite_ = false; 342 needs_composite_ = false;
308 should_composite_on_vsync_ = false;
309 343
310 // Ignore ScheduleComposite() from layer tree changes during Layout. 344 // Only allow compositing once per vsync.
345 current_composite_task_->Cancel();
346 DCHECK(DidCompositeThisFrame() && !WillCompositeThisFrame());
347
348 // Ignore ScheduleComposite() from layer tree changes during layout and
349 // animation updates that will already be reflected in the current frame
350 // we are about to draw.
311 ignore_schedule_composite_ = true; 351 ignore_schedule_composite_ = true;
312 client_->Layout(); 352 client_->Layout();
353
354 if (needs_animate_) {
355 needs_animate_ = false;
356 root_window_->Animate(gfx::FrameTime::Now());
357 }
313 ignore_schedule_composite_ = false; 358 ignore_schedule_composite_ = false;
314 359
315 did_post_swapbuffers_ = false; 360 did_post_swapbuffers_ = false;
316 host_->Composite(gfx::FrameTime::Now()); 361 host_->Composite(gfx::FrameTime::Now());
317 if (did_post_swapbuffers_) 362 if (did_post_swapbuffers_)
318 pending_swapbuffers_++; 363 pending_swapbuffers_++;
319 364
320 if (trigger != COMPOSITE_ON_VSYNC) { 365 // Need to track vsync to avoid compositing more than once per frame.
321 // Need to track vsync to avoid compositing more than once per frame. 366 root_window_->RequestVSyncUpdate();
322 root_window_->RequestVSyncUpdate();
323 }
324 did_composite_this_frame_ = true;
325 } 367 }
326 368
327 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { 369 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
328 root_layer_->RemoveAllChildren(); 370 root_layer_->RemoveAllChildren();
329 if (root_layer) 371 if (root_layer)
330 root_layer_->AddChild(root_layer); 372 root_layer_->AddChild(root_layer);
331 } 373 }
332 374
333 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { 375 void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
334 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); 376 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 } 414 }
373 if (window) { 415 if (window) {
374 SetWindowSurface(window); 416 SetWindowSurface(window);
375 ANativeWindow_release(window); 417 ANativeWindow_release(window);
376 content::RegisterViewSurface(surface_id_, j_surface.obj()); 418 content::RegisterViewSurface(surface_id_, j_surface.obj());
377 } 419 }
378 } 420 }
379 421
380 void CompositorImpl::SetVisible(bool visible) { 422 void CompositorImpl::SetVisible(bool visible) {
381 if (!visible) { 423 if (!visible) {
424 if (WillComposite())
425 CancelComposite();
382 ui_resource_map_.clear(); 426 ui_resource_map_.clear();
383 host_.reset(); 427 host_.reset();
384 client_->UIResourcesAreInvalid(); 428 client_->UIResourcesAreInvalid();
385 } else if (!host_) { 429 } else if (!host_) {
430 DCHECK(!WillComposite());
386 needs_composite_ = false; 431 needs_composite_ = false;
387 did_composite_this_frame_ = false; 432 needs_animate_ = false;
388 should_composite_on_vsync_ = false;
389 pending_swapbuffers_ = 0; 433 pending_swapbuffers_ = 0;
390 cc::LayerTreeSettings settings; 434 cc::LayerTreeSettings settings;
391 settings.refresh_rate = 60.0; 435 settings.refresh_rate = 60.0;
392 settings.impl_side_painting = false; 436 settings.impl_side_painting = false;
393 settings.allow_antialiasing = false; 437 settings.allow_antialiasing = false;
394 settings.calculate_top_controls_position = false; 438 settings.calculate_top_controls_position = false;
395 settings.top_controls_height = 0.f; 439 settings.top_controls_height = 0.f;
396 settings.highp_threshold_min = 2048; 440 settings.highp_threshold_min = 2048;
397 441
398 CommandLine* command_line = CommandLine::ForCurrentProcess(); 442 CommandLine* command_line = CommandLine::ForCurrentProcess();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 has_transparent_background_ = flag; 480 has_transparent_background_ = flag;
437 if (host_) 481 if (host_)
438 host_->set_has_transparent_background(flag); 482 host_->set_has_transparent_background(flag);
439 } 483 }
440 484
441 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { 485 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
442 return false; 486 return false;
443 } 487 }
444 488
445 void CompositorImpl::SetNeedsComposite() { 489 void CompositorImpl::SetNeedsComposite() {
446 if (!host_.get() || needs_composite_) 490 if (!host_.get())
447 return; 491 return;
492 DCHECK(!needs_composite_ || WillComposite());
448 493
449 needs_composite_ = true; 494 needs_composite_ = true;
450 495 PostComposite(COMPOSITE_EVENTUALLY);
451 // For explicit requests we try to composite regularly on vsync.
452 should_composite_on_vsync_ = true;
453 root_window_->RequestVSyncUpdate();
454 } 496 }
455 497
456 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( 498 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap(
457 const cc::UIResourceBitmap& bitmap, 499 const cc::UIResourceBitmap& bitmap,
458 bool is_transient) { 500 bool is_transient) {
459 if (!host_) 501 if (!host_)
460 return 0; 502 return 0;
461 503
462 cc::UIResourceId id = 0; 504 cc::UIResourceId id = 0;
463 scoped_ptr<cc::UIResourceClient> resource; 505 scoped_ptr<cc::UIResourceClient> resource;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 615
574 return scoped_ptr<cc::OutputSurface>( 616 return scoped_ptr<cc::OutputSurface>(
575 new OutputSurfaceWithoutParent(context_provider)); 617 new OutputSurfaceWithoutParent(context_provider));
576 } 618 }
577 619
578 void CompositorImpl::OnLostResources() { 620 void CompositorImpl::OnLostResources() {
579 client_->DidLoseResources(); 621 client_->DidLoseResources();
580 } 622 }
581 623
582 void CompositorImpl::ScheduleComposite() { 624 void CompositorImpl::ScheduleComposite() {
583 if (needs_composite_ || ignore_schedule_composite_) 625 DCHECK(!needs_composite_ || WillComposite());
626 if (ignore_schedule_composite_)
584 return; 627 return;
585 628
586 needs_composite_ = true; 629 needs_composite_ = true;
587
588 // We currently expect layer tree invalidations at most once per frame 630 // We currently expect layer tree invalidations at most once per frame
589 // during normal operation and therefore try to composite immediately 631 // during normal operation and therefore try to composite immediately
590 // to minimize latency. 632 // to minimize latency.
591 PostComposite(base::TimeDelta()); 633 PostComposite(COMPOSITE_IMMEDIATELY);
592 } 634 }
593 635
594 void CompositorImpl::ScheduleAnimation() { 636 void CompositorImpl::ScheduleAnimation() {
595 ScheduleComposite(); 637 ScheduleComposite();
596 } 638 }
597 639
598 void CompositorImpl::DidPostSwapBuffers() { 640 void CompositorImpl::DidPostSwapBuffers() {
599 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); 641 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
600 did_post_swapbuffers_ = true; 642 did_post_swapbuffers_ = true;
601 } 643 }
602 644
603 void CompositorImpl::DidCompleteSwapBuffers() { 645 void CompositorImpl::DidCompleteSwapBuffers() {
604 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); 646 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
605 DCHECK_GT(pending_swapbuffers_, 0U); 647 DCHECK_GT(pending_swapbuffers_, 0U);
606 client_->OnSwapBuffersCompleted(--pending_swapbuffers_); 648 if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
649 PostComposite(COMPOSITE_IMMEDIATELY);
650 client_->OnSwapBuffersCompleted(pending_swapbuffers_);
607 } 651 }
608 652
609 void CompositorImpl::DidAbortSwapBuffers() { 653 void CompositorImpl::DidAbortSwapBuffers() {
610 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); 654 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
611 DCHECK_GT(pending_swapbuffers_, 0U); 655 DCHECK_GT(pending_swapbuffers_, 0U);
612 client_->OnSwapBuffersCompleted(--pending_swapbuffers_); 656 if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
657 PostComposite(COMPOSITE_IMMEDIATELY);
658 client_->OnSwapBuffersCompleted(pending_swapbuffers_);
613 } 659 }
614 660
615 void CompositorImpl::DidCommit() { 661 void CompositorImpl::DidCommit() {
616 root_window_->OnCompositingDidCommit(); 662 root_window_->OnCompositingDidCommit();
617 } 663 }
618 664
619 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { 665 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
620 root_layer_->AddChild(layer); 666 root_layer_->AddChild(layer);
621 } 667 }
622 668
623 void CompositorImpl::RequestCopyOfOutputOnRootLayer( 669 void CompositorImpl::RequestCopyOfOutputOnRootLayer(
624 scoped_ptr<cc::CopyOutputRequest> request) { 670 scoped_ptr<cc::CopyOutputRequest> request) {
625 root_layer_->RequestCopyOfOutput(request.Pass()); 671 root_layer_->RequestCopyOfOutput(request.Pass());
626 } 672 }
627 673
628 void CompositorImpl::OnVSync(base::TimeTicks frame_time, 674 void CompositorImpl::OnVSync(base::TimeTicks frame_time,
629 base::TimeDelta vsync_period) { 675 base::TimeDelta vsync_period) {
630 vsync_period_ = vsync_period; 676 vsync_period_ = vsync_period;
631 did_composite_this_frame_ = false; 677 last_vsync_ = frame_time;
632 678
633 if (should_composite_on_vsync_) 679 if (WillCompositeThisFrame()) {
634 Composite(COMPOSITE_ON_VSYNC); 680 // We somehow missed the last vsync interval, so reschedule immediately.
681 CancelComposite();
682 composite_on_vsync_trigger_ = COMPOSITE_IMMEDIATELY;
683 } else {
684 current_composite_task_.reset();
685 }
686
687 DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame());
688 if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) {
689 CompositingTrigger trigger = composite_on_vsync_trigger_;
690 composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
691 PostComposite(trigger);
692 }
693 }
694
695 void CompositorImpl::SetNeedsAnimate() {
696 DCHECK(!needs_animate_ || needs_composite_);
697 DCHECK(!needs_composite_ || WillComposite());
698 needs_animate_ = true;
699
700 if (needs_composite_)
701 return;
702
703 TRACE_EVENT0("cc", "CompositorImpl::SetNeedsAnimate");
704 needs_composite_ = true;
705 PostComposite(COMPOSITE_EVENTUALLY);
635 } 706 }
636 707
637 } // namespace content 708 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698