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

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: rebase Created 6 years, 6 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 (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) {
278 composite_on_vsync_trigger_ = trigger;
279 root_window_->RequestVSyncUpdate();
280 }
281 DCHECK(WillComposite());
282 return;
283 }
284
285 base::TimeDelta delay;
286 if (trigger == COMPOSITE_IMMEDIATELY) {
287 will_composite_immediately_ = true;
288 composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
289 } else {
290 DCHECK(!WillComposite());
291 const base::TimeDelta estimated_composite_time = vsync_period_ / 4;
292 const base::TimeTicks now = base::TimeTicks::Now();
293
294 if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) {
295 base::TimeTicks next_composite =
296 last_vsync_ + vsync_period_ - estimated_composite_time;
297 if (next_composite < now) {
298 // It's too late, we will reschedule composite as needed on the next
299 // vsync.
300 composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
301 root_window_->RequestVSyncUpdate();
302 DCHECK(WillComposite());
303 return;
304 }
305
306 delay = next_composite - now;
307 }
308 }
309 TRACE_EVENT2("cc", "CompositorImpl::PostComposite",
310 "trigger", trigger,
311 "delay", delay.InMillisecondsF());
312
313 DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE);
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());
274 329
275 if (!needs_composite_) 330 if (trigger == COMPOSITE_IMMEDIATELY)
276 return; 331 will_composite_immediately_ = false;
277 332
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); 333 DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers);
296 if (pending_swapbuffers_ == kMaxSwapBuffers) { 334 if (pending_swapbuffers_ == kMaxSwapBuffers) {
297 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); 335 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit");
298 if (should_composite_on_vsync_)
299 root_window_->RequestVSyncUpdate();
300 else
301 PostComposite(vsync_period_);
302 return; 336 return;
303 } 337 }
304 338
305 // Reset state before Layout+Composite since that might create more 339 // Reset state before Layout+Composite since that might create more
306 // requests to Composite that we need to respect. 340 // requests to Composite that we need to respect.
307 needs_composite_ = false; 341 needs_composite_ = false;
308 should_composite_on_vsync_ = false;
309 342
310 // Ignore ScheduleComposite() from layer tree changes during Layout. 343 // Only allow compositing once per vsync.
344 current_composite_task_->Cancel();
345 DCHECK(DidCompositeThisFrame() && !WillComposite());
346
347 // Ignore ScheduleComposite() from layer tree changes during layout and
348 // animation updates that will already be reflected in the current frame
349 // we are about to draw.
311 ignore_schedule_composite_ = true; 350 ignore_schedule_composite_ = true;
312 client_->Layout(); 351 client_->Layout();
352
353 if (needs_animate_) {
354 needs_animate_ = false;
355 root_window_->Animate(gfx::FrameTime::Now());
Sami 2014/05/27 19:54:05 Should we use the same gfx::FrameTime::Now() for a
no sievers 2014/05/27 20:05:17 Done.
356 }
313 ignore_schedule_composite_ = false; 357 ignore_schedule_composite_ = false;
314 358
315 did_post_swapbuffers_ = false; 359 did_post_swapbuffers_ = false;
316 host_->Composite(gfx::FrameTime::Now()); 360 host_->Composite(gfx::FrameTime::Now());
317 if (did_post_swapbuffers_) 361 if (did_post_swapbuffers_)
318 pending_swapbuffers_++; 362 pending_swapbuffers_++;
319 363
320 if (trigger != COMPOSITE_ON_VSYNC) { 364 // 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. 365 root_window_->RequestVSyncUpdate();
322 root_window_->RequestVSyncUpdate();
323 }
324 did_composite_this_frame_ = true;
325 } 366 }
326 367
327 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { 368 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
328 root_layer_->RemoveAllChildren(); 369 root_layer_->RemoveAllChildren();
329 if (root_layer) 370 if (root_layer)
330 root_layer_->AddChild(root_layer); 371 root_layer_->AddChild(root_layer);
331 } 372 }
332 373
333 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { 374 void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
334 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); 375 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 } 413 }
373 if (window) { 414 if (window) {
374 SetWindowSurface(window); 415 SetWindowSurface(window);
375 ANativeWindow_release(window); 416 ANativeWindow_release(window);
376 content::RegisterViewSurface(surface_id_, j_surface.obj()); 417 content::RegisterViewSurface(surface_id_, j_surface.obj());
377 } 418 }
378 } 419 }
379 420
380 void CompositorImpl::SetVisible(bool visible) { 421 void CompositorImpl::SetVisible(bool visible) {
381 if (!visible) { 422 if (!visible) {
423 if (WillComposite())
424 CancelComposite();
382 ui_resource_map_.clear(); 425 ui_resource_map_.clear();
383 host_.reset(); 426 host_.reset();
384 client_->UIResourcesAreInvalid(); 427 client_->UIResourcesAreInvalid();
385 } else if (!host_) { 428 } else if (!host_) {
429 DCHECK(!WillComposite());
386 needs_composite_ = false; 430 needs_composite_ = false;
387 did_composite_this_frame_ = false; 431 needs_animate_ = false;
388 should_composite_on_vsync_ = false;
389 pending_swapbuffers_ = 0; 432 pending_swapbuffers_ = 0;
390 cc::LayerTreeSettings settings; 433 cc::LayerTreeSettings settings;
391 settings.refresh_rate = 60.0; 434 settings.refresh_rate = 60.0;
392 settings.impl_side_painting = false; 435 settings.impl_side_painting = false;
393 settings.allow_antialiasing = false; 436 settings.allow_antialiasing = false;
394 settings.calculate_top_controls_position = false; 437 settings.calculate_top_controls_position = false;
395 settings.top_controls_height = 0.f; 438 settings.top_controls_height = 0.f;
396 settings.highp_threshold_min = 2048; 439 settings.highp_threshold_min = 2048;
397 440
398 CommandLine* command_line = CommandLine::ForCurrentProcess(); 441 CommandLine* command_line = CommandLine::ForCurrentProcess();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 has_transparent_background_ = flag; 479 has_transparent_background_ = flag;
437 if (host_) 480 if (host_)
438 host_->set_has_transparent_background(flag); 481 host_->set_has_transparent_background(flag);
439 } 482 }
440 483
441 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { 484 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
442 return false; 485 return false;
443 } 486 }
444 487
445 void CompositorImpl::SetNeedsComposite() { 488 void CompositorImpl::SetNeedsComposite() {
446 if (!host_.get() || needs_composite_) 489 if (!host_.get())
447 return; 490 return;
491 DCHECK(!needs_composite_ || WillComposite());
448 492
449 needs_composite_ = true; 493 needs_composite_ = true;
450 494 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 } 495 }
455 496
456 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( 497 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap(
457 const cc::UIResourceBitmap& bitmap, 498 const cc::UIResourceBitmap& bitmap,
458 bool is_transient) { 499 bool is_transient) {
459 if (!host_) 500 if (!host_)
460 return 0; 501 return 0;
461 502
462 cc::UIResourceId id = 0; 503 cc::UIResourceId id = 0;
463 scoped_ptr<cc::UIResourceClient> resource; 504 scoped_ptr<cc::UIResourceClient> resource;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 614
574 return scoped_ptr<cc::OutputSurface>( 615 return scoped_ptr<cc::OutputSurface>(
575 new OutputSurfaceWithoutParent(context_provider)); 616 new OutputSurfaceWithoutParent(context_provider));
576 } 617 }
577 618
578 void CompositorImpl::OnLostResources() { 619 void CompositorImpl::OnLostResources() {
579 client_->DidLoseResources(); 620 client_->DidLoseResources();
580 } 621 }
581 622
582 void CompositorImpl::ScheduleComposite() { 623 void CompositorImpl::ScheduleComposite() {
583 if (needs_composite_ || ignore_schedule_composite_) 624 DCHECK(!needs_composite_ || WillComposite());
625 if (ignore_schedule_composite_)
584 return; 626 return;
585 627
586 needs_composite_ = true; 628 needs_composite_ = true;
587
588 // We currently expect layer tree invalidations at most once per frame 629 // We currently expect layer tree invalidations at most once per frame
589 // during normal operation and therefore try to composite immediately 630 // during normal operation and therefore try to composite immediately
590 // to minimize latency. 631 // to minimize latency.
591 PostComposite(base::TimeDelta()); 632 PostComposite(COMPOSITE_IMMEDIATELY);
592 } 633 }
593 634
594 void CompositorImpl::ScheduleAnimation() { 635 void CompositorImpl::ScheduleAnimation() {
595 ScheduleComposite(); 636 DCHECK(!needs_animate_ || needs_composite_);
637 DCHECK(!needs_composite_ || WillComposite());
638 needs_animate_ = true;
639
640 if (needs_composite_)
641 return;
642
643 TRACE_EVENT0("cc", "CompositorImpl::ScheduleAnimation");
644 needs_composite_ = true;
645 PostComposite(COMPOSITE_EVENTUALLY);
596 } 646 }
597 647
598 void CompositorImpl::DidPostSwapBuffers() { 648 void CompositorImpl::DidPostSwapBuffers() {
599 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); 649 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
600 did_post_swapbuffers_ = true; 650 did_post_swapbuffers_ = true;
601 } 651 }
602 652
603 void CompositorImpl::DidCompleteSwapBuffers() { 653 void CompositorImpl::DidCompleteSwapBuffers() {
604 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); 654 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
605 DCHECK_GT(pending_swapbuffers_, 0U); 655 DCHECK_GT(pending_swapbuffers_, 0U);
606 client_->OnSwapBuffersCompleted(--pending_swapbuffers_); 656 if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
657 PostComposite(COMPOSITE_IMMEDIATELY);
658 client_->OnSwapBuffersCompleted(pending_swapbuffers_);
607 } 659 }
608 660
609 void CompositorImpl::DidAbortSwapBuffers() { 661 void CompositorImpl::DidAbortSwapBuffers() {
610 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); 662 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
611 DCHECK_GT(pending_swapbuffers_, 0U); 663 DCHECK_GT(pending_swapbuffers_, 0U);
612 client_->OnSwapBuffersCompleted(--pending_swapbuffers_); 664 if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
665 PostComposite(COMPOSITE_IMMEDIATELY);
666 client_->OnSwapBuffersCompleted(pending_swapbuffers_);
613 } 667 }
614 668
615 void CompositorImpl::DidCommit() { 669 void CompositorImpl::DidCommit() {
616 root_window_->OnCompositingDidCommit(); 670 root_window_->OnCompositingDidCommit();
617 } 671 }
618 672
619 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { 673 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
620 root_layer_->AddChild(layer); 674 root_layer_->AddChild(layer);
621 } 675 }
622 676
623 void CompositorImpl::RequestCopyOfOutputOnRootLayer( 677 void CompositorImpl::RequestCopyOfOutputOnRootLayer(
624 scoped_ptr<cc::CopyOutputRequest> request) { 678 scoped_ptr<cc::CopyOutputRequest> request) {
625 root_layer_->RequestCopyOfOutput(request.Pass()); 679 root_layer_->RequestCopyOfOutput(request.Pass());
626 } 680 }
627 681
628 void CompositorImpl::OnVSync(base::TimeTicks frame_time, 682 void CompositorImpl::OnVSync(base::TimeTicks frame_time,
629 base::TimeDelta vsync_period) { 683 base::TimeDelta vsync_period) {
630 vsync_period_ = vsync_period; 684 vsync_period_ = vsync_period;
631 did_composite_this_frame_ = false; 685 last_vsync_ = frame_time;
632 686
633 if (should_composite_on_vsync_) 687 if (WillCompositeThisFrame()) {
634 Composite(COMPOSITE_ON_VSYNC); 688 // We somehow missed the last vsync interval, so reschedule immediately.
689 CancelComposite();
690 composite_on_vsync_trigger_ = COMPOSITE_IMMEDIATELY;
691 } else {
692 current_composite_task_.reset();
693 }
694
695 DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame());
696 if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) {
697 CompositingTrigger trigger = composite_on_vsync_trigger_;
698 composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
699 PostComposite(trigger);
700 }
701 }
702
703 void CompositorImpl::SetNeedsAnimate() {
704 if (!host_)
705 return;
706
707 host_->SetNeedsAnimate();
635 } 708 }
636 709
637 } // namespace content 710 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698