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