Chromium Code Reviews| Index: components/exo/surface.cc |
| diff --git a/components/exo/surface.cc b/components/exo/surface.cc |
| index 6e21edc3b10fe86422022d86413811c2a64b2d0f..1fc1ca64d842c3ad18a560913e1783de9baeecab 100644 |
| --- a/components/exo/surface.cc |
| +++ b/components/exo/surface.cc |
| @@ -11,6 +11,7 @@ |
| #include "cc/resources/single_release_callback.h" |
| #include "components/exo/buffer.h" |
| #include "components/exo/surface_delegate.h" |
| +#include "components/exo/surface_observer.h" |
| #include "ui/compositor/layer.h" |
| #include "ui/gfx/buffer_format_util.h" |
| #include "ui/gfx/gpu_memory_buffer.h" |
| @@ -20,14 +21,19 @@ namespace exo { |
| //////////////////////////////////////////////////////////////////////////////// |
| // Surface, public: |
| -Surface::Surface() : compositor_(nullptr), delegate_(nullptr) { |
| +Surface::Surface() |
| + : needs_commit_surface_hierarchy_(false), |
| + has_contents_(false), |
| + compositor_(nullptr), |
| + delegate_(nullptr) { |
| SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); |
| set_owned_by_client(); |
| + SetVisible(false); |
| + SetEnabled(false); |
| } |
| Surface::~Surface() { |
| - if (delegate_) |
| - delegate_->OnSurfaceDestroying(); |
| + FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this)); |
| layer()->SetShowSolidColorContent(); |
| @@ -69,11 +75,121 @@ void Surface::SetOpaqueRegion(const SkRegion& region) { |
| pending_opaque_region_ = region; |
| } |
| +void Surface::AddSubSurface(Surface* sub_surface) { |
| + TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface", |
| + sub_surface->AsTracedValue()); |
| + |
| + DCHECK(!sub_surface->parent()); |
| + DCHECK(!sub_surface->visible()); |
| + DCHECK(!sub_surface->enabled()); |
| + DCHECK(sub_surface->bounds().origin() == gfx::Point()); |
| + AddChildView(sub_surface); |
| + |
| + pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point())); |
|
piman
2015/11/19 21:59:10
nit: DCHECK that the sub_surface is not already in
reveman
2015/11/20 05:19:48
Done.
|
| +} |
| + |
| +void Surface::RemoveSubSurface(Surface* sub_surface) { |
| + TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface", |
| + sub_surface->AsTracedValue()); |
| + |
| + RemoveChildView(sub_surface); |
| + |
| + SubSurfaceEntryList::iterator it = |
| + std::find_if(pending_sub_surfaces_.begin(), pending_sub_surfaces_.end(), |
| + [sub_surface](const SubSurfaceEntry& entry) { |
| + return entry.first == sub_surface; |
| + }); |
|
piman
2015/11/19 21:59:10
nit: worth a helper function SubSurfaceEntryList::
reveman
2015/11/20 05:19:49
Done.
|
| + DCHECK(it != pending_sub_surfaces_.end()); |
| + pending_sub_surfaces_.erase(it); |
| +} |
| + |
| +void Surface::SetSubSurfacePosition(Surface* sub_surface, |
| + const gfx::Point& position) { |
| + TRACE_EVENT2("exo", "Surface::SetSubSurfacePosition", "sub_surface", |
| + sub_surface->AsTracedValue(), "position", position.ToString()); |
| + |
| + SubSurfaceEntryList::iterator it = |
| + std::find_if(pending_sub_surfaces_.begin(), pending_sub_surfaces_.end(), |
| + [sub_surface](const SubSurfaceEntry& entry) { |
| + return entry.first == sub_surface; |
| + }); |
| + DCHECK(it != pending_sub_surfaces_.end()); |
| + it->second = position; |
| +} |
| + |
| +void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) { |
| + TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceAbove", "sub_surface", |
| + sub_surface->AsTracedValue(), "reference", |
| + reference->AsTracedValue()); |
|
piman
2015/11/19 21:59:10
nit: can you add a DCHECK_NE(sub_surface, referenc
reveman
2015/11/20 05:19:48
I added proper checking here in latest patch inste
|
| + |
| + SubSurfaceEntryList::iterator position_it; |
| + if (reference == this) { |
| + position_it = pending_sub_surfaces_.begin(); |
| + } else { |
| + position_it = |
| + std::find_if(pending_sub_surfaces_.begin(), pending_sub_surfaces_.end(), |
| + [reference](const SubSurfaceEntry& entry) { |
| + return entry.first == reference; |
| + }); |
| + if (position_it == pending_sub_surfaces_.end()) { |
| + DLOG(WARNING) << "Client tried to place sub-surface above a reference " |
| + "surface that is neither a parent nor s sibling"; |
|
piman
2015/11/19 21:59:10
nit: typo 's sibling'->'a sibling'
reveman
2015/11/20 05:19:49
Done.
|
| + return; |
| + } |
| + |
| + // Advance iterator to have |position_it| point to the sibling surface |
| + // above |reference|. |
| + std::advance(position_it, 1); |
|
piman
2015/11/19 21:59:10
nit: ++position_it ?
reveman
2015/11/20 05:19:48
Done.
|
| + } |
| + |
| + SubSurfaceEntryList::iterator it = |
| + std::find_if(pending_sub_surfaces_.begin(), pending_sub_surfaces_.end(), |
| + [sub_surface](const SubSurfaceEntry& entry) { |
| + return entry.first == sub_surface; |
| + }); |
| + DCHECK(it != pending_sub_surfaces_.end()); |
| + pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it); |
| +} |
| + |
| +void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) { |
| + TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceBelow", "sub_surface", |
| + sub_surface->AsTracedValue(), "sibling", |
| + sibling->AsTracedValue()); |
| + |
| + SubSurfaceEntryList::iterator sibling_it = |
| + std::find_if(pending_sub_surfaces_.begin(), pending_sub_surfaces_.end(), |
| + [sibling](const SubSurfaceEntry& entry) { |
| + return entry.first == sibling; |
| + }); |
| + if (sibling_it == pending_sub_surfaces_.end()) { |
| + DLOG(WARNING) << "Client tried to place sub-surface below a surface that " |
| + "is not a sibling"; |
| + return; |
| + } |
| + |
| + SubSurfaceEntryList::iterator it = |
| + std::find_if(pending_sub_surfaces_.begin(), pending_sub_surfaces_.end(), |
| + [sub_surface](const SubSurfaceEntry& entry) { |
| + return entry.first == sub_surface; |
| + }); |
| + DCHECK(it != pending_sub_surfaces_.end()); |
| + pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it); |
| +} |
| + |
| void Surface::Commit() { |
| TRACE_EVENT0("exo", "Surface::Commit"); |
| + needs_commit_surface_hierarchy_ = true; |
| + |
| if (delegate_) |
| delegate_->OnSurfaceCommit(); |
| + else |
| + CommitSurfaceHierarchy(); |
| +} |
| + |
| +void Surface::CommitSurfaceHierarchy() { |
| + DCHECK(needs_commit_surface_hierarchy_); |
| + needs_commit_surface_hierarchy_ = false; |
| cc::TextureMailbox texture_mailbox; |
| scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; |
| @@ -81,9 +197,11 @@ void Surface::Commit() { |
| texture_mailbox_release_callback = |
| pending_buffer_->AcquireTextureMailbox(&texture_mailbox); |
| pending_buffer_.reset(); |
| + has_contents_ = true; |
| } else { |
| // Show solid color content if there is no pending buffer. |
| layer()->SetShowSolidColorContent(); |
| + has_contents_ = false; |
| } |
| if (texture_mailbox_release_callback) { |
| @@ -113,6 +231,36 @@ void Surface::Commit() { |
| // Move pending frame callbacks to the end of |frame_callbacks_|. |
| frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
| } |
| + |
| + // Synchronize view hierarchy. This will position and update the stacking |
| + // order of all sub-surfaces after committing all pending state of sub-surface |
| + // descendants. |
| + int index = 0; |
| + for (auto& sub_surface_entry : pending_sub_surfaces_) { |
| + Surface* sub_surface = sub_surface_entry.first; |
| + |
| + // Synchronsouly commit all pending state of the sub-surface and its |
| + // decendents. |
| + if (sub_surface->needs_commit_surface_hierarchy()) |
| + sub_surface->CommitSurfaceHierarchy(); |
| + |
| + // Enable/disable sub-surface based on if it has contents. |
| + sub_surface->SetVisible(sub_surface->has_contents()); |
| + sub_surface->SetEnabled(sub_surface->has_contents()); |
| + |
| + // Move sub-surface to its new position in the stack. |
| + DCHECK_LT(index, child_count()); |
| + ReorderChildView(sub_surface, index); |
| + |
| + // Update sub-surface position relative to surface origin. |
| + sub_surface->SetPosition(sub_surface_entry.second); |
| + |
| + ++index; |
| + } |
| +} |
| + |
| +bool Surface::IsSynchronized() const { |
| + return delegate_ ? delegate_->IsSurfaceSynchronized() : false; |
| } |
| void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { |
| @@ -120,6 +268,22 @@ void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { |
| delegate_ = delegate; |
| } |
| +bool Surface::HasSurfaceDelegate() const { |
| + return !!delegate_; |
| +} |
| + |
| +void Surface::AddSurfaceObserver(SurfaceObserver* observer) { |
| + observers_.AddObserver(observer); |
| +} |
| + |
| +void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) { |
| + observers_.RemoveObserver(observer); |
| +} |
| + |
| +bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const { |
| + return observers_.HasObserver(observer); |
| +} |
| + |
| scoped_refptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { |
| scoped_refptr<base::trace_event::TracedValue> value = |
| new base::trace_event::TracedValue; |