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 "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "base/trace_event/trace_event_argument.h" | 10 #include "base/trace_event/trace_event_argument.h" |
11 #include "cc/resources/single_release_callback.h" | 11 #include "cc/resources/single_release_callback.h" |
12 #include "components/exo/buffer.h" | 12 #include "components/exo/buffer.h" |
13 #include "components/exo/surface_delegate.h" | 13 #include "components/exo/surface_delegate.h" |
| 14 #include "components/exo/surface_observer.h" |
14 #include "ui/compositor/layer.h" | 15 #include "ui/compositor/layer.h" |
15 #include "ui/gfx/buffer_format_util.h" | 16 #include "ui/gfx/buffer_format_util.h" |
16 #include "ui/gfx/gpu_memory_buffer.h" | 17 #include "ui/gfx/gpu_memory_buffer.h" |
17 | 18 |
18 namespace exo { | 19 namespace exo { |
| 20 namespace { |
| 21 |
| 22 // Helper function that returns an iterator to the first entry in |list| |
| 23 // with |key|. |
| 24 template <typename T, typename U> |
| 25 typename T::iterator FindListEntry(T& list, U key) { |
| 26 return std::find_if(list.begin(), list.end(), |
| 27 [key](const typename T::value_type& entry) { |
| 28 return entry.first == key; |
| 29 }); |
| 30 } |
| 31 |
| 32 // Helper function that returns true if |list| contains an entry with |key|. |
| 33 template <typename T, typename U> |
| 34 bool ListContainsEntry(T& list, U key) { |
| 35 return FindListEntry(list, key) != list.end(); |
| 36 } |
| 37 |
| 38 } // namespace |
19 | 39 |
20 //////////////////////////////////////////////////////////////////////////////// | 40 //////////////////////////////////////////////////////////////////////////////// |
21 // Surface, public: | 41 // Surface, public: |
22 | 42 |
23 Surface::Surface() : compositor_(nullptr), delegate_(nullptr) { | 43 Surface::Surface() |
| 44 : needs_commit_surface_hierarchy_(false), |
| 45 has_contents_(false), |
| 46 compositor_(nullptr), |
| 47 delegate_(nullptr) { |
24 SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); | 48 SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); |
25 set_owned_by_client(); | 49 set_owned_by_client(); |
| 50 SetVisible(false); |
| 51 SetEnabled(false); |
26 } | 52 } |
27 | 53 |
28 Surface::~Surface() { | 54 Surface::~Surface() { |
29 if (delegate_) | 55 FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this)); |
30 delegate_->OnSurfaceDestroying(); | |
31 | 56 |
32 layer()->SetShowSolidColorContent(); | 57 layer()->SetShowSolidColorContent(); |
33 | 58 |
34 if (compositor_) | 59 if (compositor_) |
35 compositor_->RemoveObserver(this); | 60 compositor_->RemoveObserver(this); |
36 | 61 |
37 // Call pending frame callbacks with a null frame time to indicate that they | 62 // Call pending frame callbacks with a null frame time to indicate that they |
38 // have been cancelled. | 63 // have been cancelled. |
39 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); | 64 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
40 active_frame_callbacks_.splice(active_frame_callbacks_.end(), | 65 active_frame_callbacks_.splice(active_frame_callbacks_.end(), |
(...skipping 21 matching lines...) Expand all Loading... |
62 pending_frame_callbacks_.push_back(callback); | 87 pending_frame_callbacks_.push_back(callback); |
63 } | 88 } |
64 | 89 |
65 void Surface::SetOpaqueRegion(const SkRegion& region) { | 90 void Surface::SetOpaqueRegion(const SkRegion& region) { |
66 TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region", | 91 TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region", |
67 gfx::SkIRectToRect(region.getBounds()).ToString()); | 92 gfx::SkIRectToRect(region.getBounds()).ToString()); |
68 | 93 |
69 pending_opaque_region_ = region; | 94 pending_opaque_region_ = region; |
70 } | 95 } |
71 | 96 |
| 97 void Surface::AddSubSurface(Surface* sub_surface) { |
| 98 TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface", |
| 99 sub_surface->AsTracedValue()); |
| 100 |
| 101 DCHECK(!sub_surface->parent()); |
| 102 DCHECK(!sub_surface->visible()); |
| 103 DCHECK(!sub_surface->enabled()); |
| 104 DCHECK(sub_surface->bounds().origin() == gfx::Point()); |
| 105 AddChildView(sub_surface); |
| 106 |
| 107 DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
| 108 pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point())); |
| 109 } |
| 110 |
| 111 void Surface::RemoveSubSurface(Surface* sub_surface) { |
| 112 TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface", |
| 113 sub_surface->AsTracedValue()); |
| 114 |
| 115 RemoveChildView(sub_surface); |
| 116 |
| 117 DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
| 118 pending_sub_surfaces_.erase( |
| 119 FindListEntry(pending_sub_surfaces_, sub_surface)); |
| 120 } |
| 121 |
| 122 void Surface::SetSubSurfacePosition(Surface* sub_surface, |
| 123 const gfx::Point& position) { |
| 124 TRACE_EVENT2("exo", "Surface::SetSubSurfacePosition", "sub_surface", |
| 125 sub_surface->AsTracedValue(), "position", position.ToString()); |
| 126 |
| 127 auto it = FindListEntry(pending_sub_surfaces_, sub_surface); |
| 128 DCHECK(it != pending_sub_surfaces_.end()); |
| 129 it->second = position; |
| 130 } |
| 131 |
| 132 void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) { |
| 133 TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceAbove", "sub_surface", |
| 134 sub_surface->AsTracedValue(), "reference", |
| 135 reference->AsTracedValue()); |
| 136 |
| 137 if (sub_surface == reference) { |
| 138 DLOG(WARNING) << "Client tried to place sub-surface above itself"; |
| 139 return; |
| 140 } |
| 141 |
| 142 auto position_it = pending_sub_surfaces_.begin(); |
| 143 if (reference != this) { |
| 144 position_it = FindListEntry(pending_sub_surfaces_, reference); |
| 145 if (position_it == pending_sub_surfaces_.end()) { |
| 146 DLOG(WARNING) << "Client tried to place sub-surface above a reference " |
| 147 "surface that is neither a parent nor a sibling"; |
| 148 return; |
| 149 } |
| 150 |
| 151 // Advance iterator to have |position_it| point to the sibling surface |
| 152 // above |reference|. |
| 153 ++position_it; |
| 154 } |
| 155 |
| 156 DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
| 157 pending_sub_surfaces_.splice( |
| 158 position_it, pending_sub_surfaces_, |
| 159 FindListEntry(pending_sub_surfaces_, sub_surface)); |
| 160 } |
| 161 |
| 162 void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) { |
| 163 TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceBelow", "sub_surface", |
| 164 sub_surface->AsTracedValue(), "sibling", |
| 165 sibling->AsTracedValue()); |
| 166 |
| 167 if (sub_surface == sibling) { |
| 168 DLOG(WARNING) << "Client tried to place sub-surface below itself"; |
| 169 return; |
| 170 } |
| 171 |
| 172 auto sibling_it = FindListEntry(pending_sub_surfaces_, sibling); |
| 173 if (sibling_it == pending_sub_surfaces_.end()) { |
| 174 DLOG(WARNING) << "Client tried to place sub-surface below a surface that " |
| 175 "is not a sibling"; |
| 176 return; |
| 177 } |
| 178 |
| 179 DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
| 180 pending_sub_surfaces_.splice( |
| 181 sibling_it, pending_sub_surfaces_, |
| 182 FindListEntry(pending_sub_surfaces_, sub_surface)); |
| 183 } |
| 184 |
72 void Surface::Commit() { | 185 void Surface::Commit() { |
73 TRACE_EVENT0("exo", "Surface::Commit"); | 186 TRACE_EVENT0("exo", "Surface::Commit"); |
74 | 187 |
| 188 needs_commit_surface_hierarchy_ = true; |
| 189 |
75 if (delegate_) | 190 if (delegate_) |
76 delegate_->OnSurfaceCommit(); | 191 delegate_->OnSurfaceCommit(); |
| 192 else |
| 193 CommitSurfaceHierarchy(); |
| 194 } |
| 195 |
| 196 void Surface::CommitSurfaceHierarchy() { |
| 197 DCHECK(needs_commit_surface_hierarchy_); |
| 198 needs_commit_surface_hierarchy_ = false; |
77 | 199 |
78 cc::TextureMailbox texture_mailbox; | 200 cc::TextureMailbox texture_mailbox; |
79 scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; | 201 scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; |
80 if (pending_buffer_) { | 202 if (pending_buffer_) { |
81 texture_mailbox_release_callback = | 203 texture_mailbox_release_callback = |
82 pending_buffer_->AcquireTextureMailbox(&texture_mailbox); | 204 pending_buffer_->AcquireTextureMailbox(&texture_mailbox); |
83 pending_buffer_.reset(); | 205 pending_buffer_.reset(); |
| 206 has_contents_ = true; |
84 } else { | 207 } else { |
85 // Show solid color content if there is no pending buffer. | 208 // Show solid color content if there is no pending buffer. |
86 layer()->SetShowSolidColorContent(); | 209 layer()->SetShowSolidColorContent(); |
| 210 has_contents_ = false; |
87 } | 211 } |
88 | 212 |
89 if (texture_mailbox_release_callback) { | 213 if (texture_mailbox_release_callback) { |
90 // Update layer with the new contents. | 214 // Update layer with the new contents. |
91 layer()->SetTextureMailbox(texture_mailbox, | 215 layer()->SetTextureMailbox(texture_mailbox, |
92 texture_mailbox_release_callback.Pass(), | 216 texture_mailbox_release_callback.Pass(), |
93 texture_mailbox.size_in_pixels()); | 217 texture_mailbox.size_in_pixels()); |
94 layer()->SetTextureFlipped(false); | 218 layer()->SetTextureFlipped(false); |
95 layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), | 219 layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), |
96 texture_mailbox.size_in_pixels())); | 220 texture_mailbox.size_in_pixels())); |
97 layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains( | 221 layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains( |
98 gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels())))); | 222 gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels())))); |
99 } | 223 } |
100 | 224 |
101 // Schedule redraw of the damage region. | 225 // Schedule redraw of the damage region. |
102 layer()->SchedulePaint(pending_damage_); | 226 layer()->SchedulePaint(pending_damage_); |
103 pending_damage_ = gfx::Rect(); | 227 pending_damage_ = gfx::Rect(); |
104 | 228 |
105 ui::Compositor* compositor = layer()->GetCompositor(); | 229 ui::Compositor* compositor = layer()->GetCompositor(); |
106 if (compositor && !pending_frame_callbacks_.empty()) { | 230 if (compositor && !pending_frame_callbacks_.empty()) { |
107 // Start observing the compositor for frame callbacks. | 231 // Start observing the compositor for frame callbacks. |
108 if (!compositor_) { | 232 if (!compositor_) { |
109 compositor->AddObserver(this); | 233 compositor->AddObserver(this); |
110 compositor_ = compositor; | 234 compositor_ = compositor; |
111 } | 235 } |
112 | 236 |
113 // Move pending frame callbacks to the end of |frame_callbacks_|. | 237 // Move pending frame callbacks to the end of |frame_callbacks_|. |
114 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); | 238 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
115 } | 239 } |
| 240 |
| 241 // Synchronize view hierarchy. This will position and update the stacking |
| 242 // order of all sub-surfaces after committing all pending state of sub-surface |
| 243 // descendants. |
| 244 int index = 0; |
| 245 for (auto& sub_surface_entry : pending_sub_surfaces_) { |
| 246 Surface* sub_surface = sub_surface_entry.first; |
| 247 |
| 248 // Synchronsouly commit all pending state of the sub-surface and its |
| 249 // decendents. |
| 250 if (sub_surface->needs_commit_surface_hierarchy()) |
| 251 sub_surface->CommitSurfaceHierarchy(); |
| 252 |
| 253 // Enable/disable sub-surface based on if it has contents. |
| 254 sub_surface->SetVisible(sub_surface->has_contents()); |
| 255 sub_surface->SetEnabled(sub_surface->has_contents()); |
| 256 |
| 257 // Move sub-surface to its new position in the stack. |
| 258 DCHECK_LT(index, child_count()); |
| 259 ReorderChildView(sub_surface, index); |
| 260 |
| 261 // Update sub-surface position relative to surface origin. |
| 262 sub_surface->SetPosition(sub_surface_entry.second); |
| 263 |
| 264 ++index; |
| 265 } |
| 266 } |
| 267 |
| 268 bool Surface::IsSynchronized() const { |
| 269 return delegate_ ? delegate_->IsSurfaceSynchronized() : false; |
116 } | 270 } |
117 | 271 |
118 void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { | 272 void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { |
119 DCHECK(!delegate_ || !delegate); | 273 DCHECK(!delegate_ || !delegate); |
120 delegate_ = delegate; | 274 delegate_ = delegate; |
121 } | 275 } |
122 | 276 |
| 277 bool Surface::HasSurfaceDelegate() const { |
| 278 return !!delegate_; |
| 279 } |
| 280 |
| 281 void Surface::AddSurfaceObserver(SurfaceObserver* observer) { |
| 282 observers_.AddObserver(observer); |
| 283 } |
| 284 |
| 285 void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) { |
| 286 observers_.RemoveObserver(observer); |
| 287 } |
| 288 |
| 289 bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const { |
| 290 return observers_.HasObserver(observer); |
| 291 } |
| 292 |
123 scoped_refptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { | 293 scoped_refptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { |
124 scoped_refptr<base::trace_event::TracedValue> value = | 294 scoped_refptr<base::trace_event::TracedValue> value = |
125 new base::trace_event::TracedValue; | 295 new base::trace_event::TracedValue; |
126 value->SetString("name", layer()->name()); | 296 value->SetString("name", layer()->name()); |
127 return value; | 297 return value; |
128 } | 298 } |
129 | 299 |
130 //////////////////////////////////////////////////////////////////////////////// | 300 //////////////////////////////////////////////////////////////////////////////// |
131 // views::Views overrides: | 301 // views::Views overrides: |
132 | 302 |
(...skipping 18 matching lines...) Expand all Loading... |
151 active_frame_callbacks_.pop_front(); | 321 active_frame_callbacks_.pop_front(); |
152 } | 322 } |
153 } | 323 } |
154 | 324 |
155 void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { | 325 void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { |
156 compositor->RemoveObserver(this); | 326 compositor->RemoveObserver(this); |
157 compositor_ = nullptr; | 327 compositor_ = nullptr; |
158 } | 328 } |
159 | 329 |
160 } // namespace exo | 330 } // namespace exo |
OLD | NEW |