| 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 |