OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |