OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/exo/surface.h" | 5 #include "components/exo/surface.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 TRACE_EVENT0("exo", "Surface::Commit"); | 422 TRACE_EVENT0("exo", "Surface::Commit"); |
423 | 423 |
424 needs_commit_surface_hierarchy_ = true; | 424 needs_commit_surface_hierarchy_ = true; |
425 | 425 |
426 if (delegate_) | 426 if (delegate_) |
427 delegate_->OnSurfaceCommit(); | 427 delegate_->OnSurfaceCommit(); |
428 else | 428 else |
429 CommitSurfaceHierarchy(); | 429 CommitSurfaceHierarchy(); |
430 } | 430 } |
431 | 431 |
| 432 void Surface::CommitSurfaceHierarchy() { |
| 433 DCHECK(needs_commit_surface_hierarchy_); |
| 434 needs_commit_surface_hierarchy_ = false; |
| 435 |
| 436 // TODO(dcastagna): Make secure_output_only a layer property instead of a |
| 437 // texture mailbox flag so this can be changed without have to provide |
| 438 // new contents. |
| 439 only_visible_on_secure_output_ = pending_only_visible_on_secure_output_; |
| 440 pending_only_visible_on_secure_output_ = false; |
| 441 |
| 442 // Update current alpha. |
| 443 alpha_ = pending_alpha_; |
| 444 |
| 445 // Update current crop rectangle. |
| 446 crop_ = pending_crop_; |
| 447 |
| 448 if (factory_owner_) { |
| 449 CommitSurfaceContents(); |
| 450 } else { |
| 451 CommitTextureContents(); |
| 452 } |
| 453 |
| 454 // Update current input region. |
| 455 input_region_ = pending_input_region_; |
| 456 |
| 457 // Synchronize window hierarchy. This will position and update the stacking |
| 458 // order of all sub-surfaces after committing all pending state of sub-surface |
| 459 // descendants. |
| 460 aura::Window* stacking_target = nullptr; |
| 461 for (auto& sub_surface_entry : pending_sub_surfaces_) { |
| 462 Surface* sub_surface = sub_surface_entry.first; |
| 463 |
| 464 // Synchronsouly commit all pending state of the sub-surface and its |
| 465 // decendents. |
| 466 if (sub_surface->needs_commit_surface_hierarchy()) |
| 467 sub_surface->CommitSurfaceHierarchy(); |
| 468 |
| 469 // Enable/disable sub-surface based on if it has contents. |
| 470 if (sub_surface->has_contents()) |
| 471 sub_surface->Show(); |
| 472 else |
| 473 sub_surface->Hide(); |
| 474 |
| 475 // Move sub-surface to its new position in the stack. |
| 476 if (stacking_target) |
| 477 StackChildAbove(sub_surface, stacking_target); |
| 478 |
| 479 // Stack next sub-surface above this sub-surface. |
| 480 stacking_target = sub_surface; |
| 481 |
| 482 // Update sub-surface position relative to surface origin. |
| 483 sub_surface->SetBounds( |
| 484 gfx::Rect(sub_surface_entry.second, sub_surface->layer()->size())); |
| 485 } |
| 486 } |
| 487 |
| 488 bool Surface::IsSynchronized() const { |
| 489 return delegate_ ? delegate_->IsSurfaceSynchronized() : false; |
| 490 } |
| 491 |
| 492 gfx::Rect Surface::GetHitTestBounds() const { |
| 493 SkIRect bounds = input_region_.getBounds(); |
| 494 if (!bounds.intersect(gfx::RectToSkIRect(gfx::Rect(layer()->size())))) |
| 495 return gfx::Rect(); |
| 496 return gfx::SkIRectToRect(bounds); |
| 497 } |
| 498 |
| 499 bool Surface::HitTestRect(const gfx::Rect& rect) const { |
| 500 if (HasHitTestMask()) |
| 501 return input_region_.intersects(gfx::RectToSkIRect(rect)); |
| 502 |
| 503 return rect.Intersects(gfx::Rect(layer()->size())); |
| 504 } |
| 505 |
| 506 bool Surface::HasHitTestMask() const { |
| 507 return !input_region_.contains( |
| 508 gfx::RectToSkIRect(gfx::Rect(layer()->size()))); |
| 509 } |
| 510 |
| 511 void Surface::GetHitTestMask(gfx::Path* mask) const { |
| 512 input_region_.getBoundaryPath(mask); |
| 513 } |
| 514 |
| 515 void Surface::RegisterCursorProvider(Pointer* provider) { |
| 516 cursor_providers_.insert(provider); |
| 517 } |
| 518 |
| 519 void Surface::UnregisterCursorProvider(Pointer* provider) { |
| 520 cursor_providers_.erase(provider); |
| 521 } |
| 522 |
| 523 bool Surface::HasCursorProvider() const { |
| 524 return !cursor_providers_.empty(); |
| 525 } |
| 526 |
| 527 void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { |
| 528 DCHECK(!delegate_ || !delegate); |
| 529 delegate_ = delegate; |
| 530 } |
| 531 |
| 532 bool Surface::HasSurfaceDelegate() const { |
| 533 return !!delegate_; |
| 534 } |
| 535 |
| 536 void Surface::AddSurfaceObserver(SurfaceObserver* observer) { |
| 537 observers_.AddObserver(observer); |
| 538 } |
| 539 |
| 540 void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) { |
| 541 observers_.RemoveObserver(observer); |
| 542 } |
| 543 |
| 544 bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const { |
| 545 return observers_.HasObserver(observer); |
| 546 } |
| 547 |
| 548 std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { |
| 549 std::unique_ptr<base::trace_event::TracedValue> value( |
| 550 new base::trace_event::TracedValue()); |
| 551 value->SetString("name", layer()->name()); |
| 552 return value; |
| 553 } |
| 554 |
| 555 //////////////////////////////////////////////////////////////////////////////// |
| 556 // aura::WindowObserver overrides: |
| 557 |
| 558 void Surface::OnWindowAddedToRootWindow(aura::Window* window) { |
| 559 DCHECK(!compositor_); |
| 560 DCHECK(!factory_owner_); |
| 561 compositor_ = layer()->GetCompositor(); |
| 562 compositor_->AddObserver(this); |
| 563 } |
| 564 |
| 565 void Surface::OnWindowRemovingFromRootWindow(aura::Window* window, |
| 566 aura::Window* new_root) { |
| 567 DCHECK(compositor_); |
| 568 compositor_->RemoveObserver(this); |
| 569 compositor_ = nullptr; |
| 570 } |
| 571 |
| 572 //////////////////////////////////////////////////////////////////////////////// |
| 573 // ui::LayerOwnerDelegate overrides: |
| 574 |
| 575 void Surface::OnLayerRecreated(ui::Layer* old_layer, ui::Layer* new_layer) { |
| 576 if (!current_buffer_) |
| 577 return; |
| 578 |
| 579 // TODO(reveman): Give the client a chance to provide new contents. |
| 580 if (factory_owner_) { |
| 581 SetSurfaceLayerContents(new_layer); |
| 582 } else { |
| 583 SetTextureLayerContents(new_layer); |
| 584 } |
| 585 } |
| 586 |
| 587 //////////////////////////////////////////////////////////////////////////////// |
| 588 // ui::CompositorObserver overrides: |
| 589 |
| 590 void Surface::OnCompositingDidCommit(ui::Compositor* compositor) { |
| 591 DCHECK(!factory_owner_); |
| 592 // Move frame callbacks to the end of |active_frame_callbacks_|. |
| 593 active_frame_callbacks_.splice(active_frame_callbacks_.end(), |
| 594 frame_callbacks_); |
| 595 } |
| 596 |
| 597 void Surface::OnCompositingStarted(ui::Compositor* compositor, |
| 598 base::TimeTicks start_time) { |
| 599 last_compositing_start_time_ = start_time; |
| 600 } |
| 601 |
| 602 void Surface::OnCompositingEnded(ui::Compositor* compositor) { |
| 603 // Run all frame callbacks associated with the compositor's active tree. |
| 604 while (!active_frame_callbacks_.empty()) { |
| 605 active_frame_callbacks_.front().Run(last_compositing_start_time_); |
| 606 active_frame_callbacks_.pop_front(); |
| 607 } |
| 608 |
| 609 // Nothing more to do in here unless this has been set. |
| 610 if (!update_contents_after_successful_compositing_) |
| 611 return; |
| 612 |
| 613 update_contents_after_successful_compositing_ = false; |
| 614 |
| 615 // Early out if no contents is currently assigned to the surface. |
| 616 if (!current_buffer_) |
| 617 return; |
| 618 |
| 619 // Update contents by producing a new texture mailbox for the current buffer. |
| 620 SetTextureLayerContents(layer()); |
| 621 } |
| 622 |
| 623 void Surface::OnCompositingAborted(ui::Compositor* compositor) { |
| 624 // The contents of this surface might be lost if compositing aborted because |
| 625 // of a lost graphics context. We recover from this by updating the contents |
| 626 // of the surface next time the compositor successfully ends compositing. |
| 627 update_contents_after_successful_compositing_ = true; |
| 628 } |
| 629 |
| 630 void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { |
| 631 compositor->RemoveObserver(this); |
| 632 compositor_ = nullptr; |
| 633 } |
| 634 |
| 635 void Surface::WillDraw(cc::SurfaceId id) { |
| 636 while (!active_frame_callbacks_.empty()) { |
| 637 active_frame_callbacks_.front().Run(base::TimeTicks::Now()); |
| 638 active_frame_callbacks_.pop_front(); |
| 639 } |
| 640 } |
| 641 |
432 void Surface::CommitTextureContents() { | 642 void Surface::CommitTextureContents() { |
433 // We update contents if Attach() has been called since last commit. | 643 // We update contents if Attach() has been called since last commit. |
434 if (has_pending_contents_) { | 644 if (has_pending_contents_) { |
435 has_pending_contents_ = false; | 645 has_pending_contents_ = false; |
436 | 646 |
437 current_buffer_ = pending_buffer_; | 647 current_buffer_ = pending_buffer_; |
438 pending_buffer_.reset(); | 648 pending_buffer_.reset(); |
439 | 649 |
440 cc::TextureMailbox texture_mailbox; | 650 cc::TextureMailbox texture_mailbox; |
441 std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; | 651 std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 layer()->SetFillsBoundsOpaquely(alpha_ == 1.0f && frame_is_opaque); | 850 layer()->SetFillsBoundsOpaquely(alpha_ == 1.0f && frame_is_opaque); |
641 | 851 |
642 // Reset damage. | 852 // Reset damage. |
643 pending_damage_.setEmpty(); | 853 pending_damage_.setEmpty(); |
644 } | 854 } |
645 // Move pending frame callbacks to the end of active_frame_callbacks_ | 855 // Move pending frame callbacks to the end of active_frame_callbacks_ |
646 active_frame_callbacks_.splice(active_frame_callbacks_.end(), | 856 active_frame_callbacks_.splice(active_frame_callbacks_.end(), |
647 pending_frame_callbacks_); | 857 pending_frame_callbacks_); |
648 } | 858 } |
649 | 859 |
650 void Surface::CommitSurfaceHierarchy() { | |
651 DCHECK(needs_commit_surface_hierarchy_); | |
652 needs_commit_surface_hierarchy_ = false; | |
653 | |
654 // TODO(dcastagna): Make secure_output_only a layer property instead of a | |
655 // texture mailbox flag so this can be changed without have to provide | |
656 // new contents. | |
657 only_visible_on_secure_output_ = pending_only_visible_on_secure_output_; | |
658 pending_only_visible_on_secure_output_ = false; | |
659 | |
660 // Update current alpha. | |
661 alpha_ = pending_alpha_; | |
662 | |
663 // Update current crop rectangle. | |
664 crop_ = pending_crop_; | |
665 | |
666 if (factory_owner_) { | |
667 CommitSurfaceContents(); | |
668 } else { | |
669 CommitTextureContents(); | |
670 } | |
671 | |
672 // Update current input region. | |
673 input_region_ = pending_input_region_; | |
674 | |
675 // Synchronize window hierarchy. This will position and update the stacking | |
676 // order of all sub-surfaces after committing all pending state of sub-surface | |
677 // descendants. | |
678 aura::Window* stacking_target = nullptr; | |
679 for (auto& sub_surface_entry : pending_sub_surfaces_) { | |
680 Surface* sub_surface = sub_surface_entry.first; | |
681 | |
682 // Synchronsouly commit all pending state of the sub-surface and its | |
683 // decendents. | |
684 if (sub_surface->needs_commit_surface_hierarchy()) | |
685 sub_surface->CommitSurfaceHierarchy(); | |
686 | |
687 // Enable/disable sub-surface based on if it has contents. | |
688 if (sub_surface->has_contents()) | |
689 sub_surface->Show(); | |
690 else | |
691 sub_surface->Hide(); | |
692 | |
693 // Move sub-surface to its new position in the stack. | |
694 if (stacking_target) | |
695 StackChildAbove(sub_surface, stacking_target); | |
696 | |
697 // Stack next sub-surface above this sub-surface. | |
698 stacking_target = sub_surface; | |
699 | |
700 // Update sub-surface position relative to surface origin. | |
701 sub_surface->SetBounds( | |
702 gfx::Rect(sub_surface_entry.second, sub_surface->layer()->size())); | |
703 } | |
704 } | |
705 | |
706 bool Surface::IsSynchronized() const { | |
707 return delegate_ ? delegate_->IsSurfaceSynchronized() : false; | |
708 } | |
709 | |
710 gfx::Rect Surface::GetHitTestBounds() const { | |
711 SkIRect bounds = input_region_.getBounds(); | |
712 if (!bounds.intersect(gfx::RectToSkIRect(gfx::Rect(layer()->size())))) | |
713 return gfx::Rect(); | |
714 return gfx::SkIRectToRect(bounds); | |
715 } | |
716 | |
717 bool Surface::HitTestRect(const gfx::Rect& rect) const { | |
718 if (HasHitTestMask()) | |
719 return input_region_.intersects(gfx::RectToSkIRect(rect)); | |
720 | |
721 return rect.Intersects(gfx::Rect(layer()->size())); | |
722 } | |
723 | |
724 bool Surface::HasHitTestMask() const { | |
725 return !input_region_.contains( | |
726 gfx::RectToSkIRect(gfx::Rect(layer()->size()))); | |
727 } | |
728 | |
729 void Surface::GetHitTestMask(gfx::Path* mask) const { | |
730 input_region_.getBoundaryPath(mask); | |
731 } | |
732 | |
733 void Surface::RegisterCursorProvider(Pointer* provider) { | |
734 cursor_providers_.insert(provider); | |
735 } | |
736 | |
737 void Surface::UnregisterCursorProvider(Pointer* provider) { | |
738 cursor_providers_.erase(provider); | |
739 } | |
740 | |
741 bool Surface::HasCursorProvider() const { | |
742 return !cursor_providers_.empty(); | |
743 } | |
744 | |
745 void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { | |
746 DCHECK(!delegate_ || !delegate); | |
747 delegate_ = delegate; | |
748 } | |
749 | |
750 bool Surface::HasSurfaceDelegate() const { | |
751 return !!delegate_; | |
752 } | |
753 | |
754 void Surface::AddSurfaceObserver(SurfaceObserver* observer) { | |
755 observers_.AddObserver(observer); | |
756 } | |
757 | |
758 void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) { | |
759 observers_.RemoveObserver(observer); | |
760 } | |
761 | |
762 bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const { | |
763 return observers_.HasObserver(observer); | |
764 } | |
765 | |
766 std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { | |
767 std::unique_ptr<base::trace_event::TracedValue> value( | |
768 new base::trace_event::TracedValue()); | |
769 value->SetString("name", layer()->name()); | |
770 return value; | |
771 } | |
772 | |
773 //////////////////////////////////////////////////////////////////////////////// | |
774 // aura::WindowObserver overrides: | |
775 | |
776 void Surface::OnWindowAddedToRootWindow(aura::Window* window) { | |
777 DCHECK(!compositor_); | |
778 DCHECK(!factory_owner_); | |
779 compositor_ = layer()->GetCompositor(); | |
780 compositor_->AddObserver(this); | |
781 } | |
782 | |
783 void Surface::OnWindowRemovingFromRootWindow(aura::Window* window, | |
784 aura::Window* new_root) { | |
785 DCHECK(compositor_); | |
786 compositor_->RemoveObserver(this); | |
787 compositor_ = nullptr; | |
788 } | |
789 | |
790 //////////////////////////////////////////////////////////////////////////////// | |
791 // ui::LayerOwnerDelegate overrides: | |
792 | |
793 void Surface::OnLayerRecreated(ui::Layer* old_layer, ui::Layer* new_layer) { | |
794 if (!current_buffer_) | |
795 return; | |
796 | |
797 // TODO(reveman): Give the client a chance to provide new contents. | |
798 if (factory_owner_) { | |
799 SetSurfaceLayerContents(new_layer); | |
800 } else { | |
801 SetTextureLayerContents(new_layer); | |
802 } | |
803 } | |
804 | |
805 //////////////////////////////////////////////////////////////////////////////// | |
806 // ui::CompositorObserver overrides: | |
807 | |
808 void Surface::OnCompositingDidCommit(ui::Compositor* compositor) { | |
809 DCHECK(!factory_owner_); | |
810 // Move frame callbacks to the end of |active_frame_callbacks_|. | |
811 active_frame_callbacks_.splice(active_frame_callbacks_.end(), | |
812 frame_callbacks_); | |
813 } | |
814 | |
815 void Surface::OnCompositingStarted(ui::Compositor* compositor, | |
816 base::TimeTicks start_time) { | |
817 last_compositing_start_time_ = start_time; | |
818 } | |
819 | |
820 void Surface::OnCompositingEnded(ui::Compositor* compositor) { | |
821 // Run all frame callbacks associated with the compositor's active tree. | |
822 while (!active_frame_callbacks_.empty()) { | |
823 active_frame_callbacks_.front().Run(last_compositing_start_time_); | |
824 active_frame_callbacks_.pop_front(); | |
825 } | |
826 | |
827 // Nothing more to do in here unless this has been set. | |
828 if (!update_contents_after_successful_compositing_) | |
829 return; | |
830 | |
831 update_contents_after_successful_compositing_ = false; | |
832 | |
833 // Early out if no contents is currently assigned to the surface. | |
834 if (!current_buffer_) | |
835 return; | |
836 | |
837 // Update contents by producing a new texture mailbox for the current buffer. | |
838 SetTextureLayerContents(layer()); | |
839 } | |
840 | |
841 void Surface::OnCompositingAborted(ui::Compositor* compositor) { | |
842 // The contents of this surface might be lost if compositing aborted because | |
843 // of a lost graphics context. We recover from this by updating the contents | |
844 // of the surface next time the compositor successfully ends compositing. | |
845 update_contents_after_successful_compositing_ = true; | |
846 } | |
847 | |
848 void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { | |
849 compositor->RemoveObserver(this); | |
850 compositor_ = nullptr; | |
851 } | |
852 | |
853 void Surface::WillDraw(cc::SurfaceId id) { | |
854 while (!active_frame_callbacks_.empty()) { | |
855 active_frame_callbacks_.front().Run(base::TimeTicks::Now()); | |
856 active_frame_callbacks_.pop_front(); | |
857 } | |
858 } | |
859 | |
860 void Surface::SetTextureLayerContents(ui::Layer* layer) { | 860 void Surface::SetTextureLayerContents(ui::Layer* layer) { |
861 DCHECK(current_buffer_); | 861 DCHECK(current_buffer_); |
862 | 862 |
863 cc::TextureMailbox texture_mailbox; | 863 cc::TextureMailbox texture_mailbox; |
864 std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback = | 864 std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback = |
865 current_buffer_->ProduceTextureMailbox(&texture_mailbox, | 865 current_buffer_->ProduceTextureMailbox(&texture_mailbox, |
866 only_visible_on_secure_output_, | 866 only_visible_on_secure_output_, |
867 false /* client_usage */); | 867 false /* client_usage */); |
868 if (!texture_mailbox_release_callback) | 868 if (!texture_mailbox_release_callback) |
869 return; | 869 return; |
(...skipping 11 matching lines...) Expand all Loading... |
881 } | 881 } |
882 | 882 |
883 void Surface::SetSurfaceLayerContents(ui::Layer* layer) { | 883 void Surface::SetSurfaceLayerContents(ui::Layer* layer) { |
884 // TODO(jbauman): Implement this. | 884 // TODO(jbauman): Implement this. |
885 NOTIMPLEMENTED(); | 885 NOTIMPLEMENTED(); |
886 } | 886 } |
887 | 887 |
888 bool Surface::use_surface_layer_ = false; | 888 bool Surface::use_surface_layer_ = false; |
889 | 889 |
890 } // namespace exo | 890 } // namespace exo |
OLD | NEW |