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" |
(...skipping 23 matching lines...) Expand all Loading... |
34 bool ListContainsEntry(T& list, U key) { | 34 bool ListContainsEntry(T& list, U key) { |
35 return FindListEntry(list, key) != list.end(); | 35 return FindListEntry(list, key) != list.end(); |
36 } | 36 } |
37 | 37 |
38 } // namespace | 38 } // namespace |
39 | 39 |
40 //////////////////////////////////////////////////////////////////////////////// | 40 //////////////////////////////////////////////////////////////////////////////// |
41 // Surface, public: | 41 // Surface, public: |
42 | 42 |
43 Surface::Surface() | 43 Surface::Surface() |
44 : needs_commit_surface_hierarchy_(false), | 44 : has_pending_contents_(false), |
45 has_contents_(false), | 45 needs_commit_surface_hierarchy_(false), |
| 46 update_contents_after_successful_compositing_(false), |
46 compositor_(nullptr), | 47 compositor_(nullptr), |
47 delegate_(nullptr) { | 48 delegate_(nullptr) { |
48 SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); | 49 SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); |
49 set_owned_by_client(); | 50 set_owned_by_client(); |
50 SetVisible(false); | 51 SetVisible(false); |
51 SetEnabled(false); | 52 SetEnabled(false); |
52 } | 53 } |
53 | 54 |
54 Surface::~Surface() { | 55 Surface::~Surface() { |
55 FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this)); | 56 FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this)); |
56 | 57 |
57 layer()->SetShowSolidColorContent(); | 58 layer()->SetShowSolidColorContent(); |
58 | 59 |
59 if (compositor_) | 60 if (compositor_) |
60 compositor_->RemoveObserver(this); | 61 compositor_->RemoveObserver(this); |
61 | 62 |
62 // Call pending frame callbacks with a null frame time to indicate that they | 63 // Call pending frame callbacks with a null frame time to indicate that they |
63 // have been cancelled. | 64 // have been cancelled. |
64 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); | 65 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
65 active_frame_callbacks_.splice(active_frame_callbacks_.end(), | 66 active_frame_callbacks_.splice(active_frame_callbacks_.end(), |
66 frame_callbacks_); | 67 frame_callbacks_); |
67 for (const auto& frame_callback : active_frame_callbacks_) | 68 for (const auto& frame_callback : active_frame_callbacks_) |
68 frame_callback.Run(base::TimeTicks()); | 69 frame_callback.Run(base::TimeTicks()); |
69 } | 70 } |
70 | 71 |
71 void Surface::Attach(Buffer* buffer) { | 72 void Surface::Attach(Buffer* buffer) { |
72 TRACE_EVENT1("exo", "Surface::Attach", "buffer", buffer->AsTracedValue()); | 73 TRACE_EVENT1("exo", "Surface::Attach", "buffer", buffer->AsTracedValue()); |
73 | 74 |
| 75 has_pending_contents_ = true; |
74 pending_buffer_ = buffer ? buffer->AsWeakPtr() : base::WeakPtr<Buffer>(); | 76 pending_buffer_ = buffer ? buffer->AsWeakPtr() : base::WeakPtr<Buffer>(); |
75 PreferredSizeChanged(); | 77 PreferredSizeChanged(); |
76 } | 78 } |
77 | 79 |
78 void Surface::Damage(const gfx::Rect& damage) { | 80 void Surface::Damage(const gfx::Rect& damage) { |
79 TRACE_EVENT1("exo", "Surface::Damage", "damage", damage.ToString()); | 81 TRACE_EVENT1("exo", "Surface::Damage", "damage", damage.ToString()); |
80 | 82 |
81 pending_damage_.Union(damage); | 83 pending_damage_.Union(damage); |
82 } | 84 } |
83 | 85 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 if (delegate_) | 192 if (delegate_) |
191 delegate_->OnSurfaceCommit(); | 193 delegate_->OnSurfaceCommit(); |
192 else | 194 else |
193 CommitSurfaceHierarchy(); | 195 CommitSurfaceHierarchy(); |
194 } | 196 } |
195 | 197 |
196 void Surface::CommitSurfaceHierarchy() { | 198 void Surface::CommitSurfaceHierarchy() { |
197 DCHECK(needs_commit_surface_hierarchy_); | 199 DCHECK(needs_commit_surface_hierarchy_); |
198 needs_commit_surface_hierarchy_ = false; | 200 needs_commit_surface_hierarchy_ = false; |
199 | 201 |
200 cc::TextureMailbox texture_mailbox; | 202 // We update contents if Attach() has been called since last commit. |
201 scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; | 203 if (has_pending_contents_) { |
202 if (pending_buffer_) { | 204 has_pending_contents_ = false; |
203 texture_mailbox_release_callback = | 205 |
204 pending_buffer_->AcquireTextureMailbox(&texture_mailbox); | 206 current_buffer_ = pending_buffer_; |
205 pending_buffer_.reset(); | 207 pending_buffer_.reset(); |
206 has_contents_ = true; | 208 |
207 } else { | 209 cc::TextureMailbox texture_mailbox; |
208 // Show solid color content if there is no pending buffer. | 210 scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; |
209 layer()->SetShowSolidColorContent(); | 211 if (current_buffer_) { |
210 has_contents_ = false; | 212 texture_mailbox_release_callback = |
| 213 current_buffer_->ProduceTextureMailbox(&texture_mailbox); |
| 214 } |
| 215 |
| 216 if (texture_mailbox_release_callback) { |
| 217 // Update layer with the new contents. |
| 218 layer()->SetTextureMailbox(texture_mailbox, |
| 219 texture_mailbox_release_callback.Pass(), |
| 220 texture_mailbox.size_in_pixels()); |
| 221 layer()->SetTextureFlipped(false); |
| 222 layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), |
| 223 texture_mailbox.size_in_pixels())); |
| 224 layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains( |
| 225 gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels())))); |
| 226 } else { |
| 227 // Show solid color content if no buffer is attached or we failed |
| 228 // to produce a texture mailbox for the currently attached buffer. |
| 229 layer()->SetShowSolidColorContent(); |
| 230 layer()->SetColor(SK_ColorBLACK); |
| 231 } |
| 232 |
| 233 // Schedule redraw of the damage region. |
| 234 layer()->SchedulePaint(pending_damage_); |
| 235 pending_damage_ = gfx::Rect(); |
211 } | 236 } |
212 | 237 |
213 if (texture_mailbox_release_callback) { | |
214 // Update layer with the new contents. | |
215 layer()->SetTextureMailbox(texture_mailbox, | |
216 texture_mailbox_release_callback.Pass(), | |
217 texture_mailbox.size_in_pixels()); | |
218 layer()->SetTextureFlipped(false); | |
219 layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), | |
220 texture_mailbox.size_in_pixels())); | |
221 layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains( | |
222 gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels())))); | |
223 } | |
224 | |
225 // Schedule redraw of the damage region. | |
226 layer()->SchedulePaint(pending_damage_); | |
227 pending_damage_ = gfx::Rect(); | |
228 | |
229 ui::Compositor* compositor = layer()->GetCompositor(); | 238 ui::Compositor* compositor = layer()->GetCompositor(); |
230 if (compositor && !pending_frame_callbacks_.empty()) { | 239 if (compositor && !pending_frame_callbacks_.empty()) { |
231 // Start observing the compositor for frame callbacks. | 240 // Start observing the compositor for frame callbacks. |
232 if (!compositor_) { | 241 if (!compositor_) { |
233 compositor->AddObserver(this); | 242 compositor->AddObserver(this); |
234 compositor_ = compositor; | 243 compositor_ = compositor; |
235 } | 244 } |
236 | 245 |
237 // Move pending frame callbacks to the end of |frame_callbacks_|. | 246 // Move pending frame callbacks to the end of |frame_callbacks_|. |
238 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); | 247 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 | 324 |
316 void Surface::OnCompositingStarted(ui::Compositor* compositor, | 325 void Surface::OnCompositingStarted(ui::Compositor* compositor, |
317 base::TimeTicks start_time) { | 326 base::TimeTicks start_time) { |
318 // Run all frame callbacks associated with the compositor's active tree. | 327 // Run all frame callbacks associated with the compositor's active tree. |
319 while (!active_frame_callbacks_.empty()) { | 328 while (!active_frame_callbacks_.empty()) { |
320 active_frame_callbacks_.front().Run(start_time); | 329 active_frame_callbacks_.front().Run(start_time); |
321 active_frame_callbacks_.pop_front(); | 330 active_frame_callbacks_.pop_front(); |
322 } | 331 } |
323 } | 332 } |
324 | 333 |
| 334 void Surface::OnCompositingEnded(ui::Compositor* compositor) { |
| 335 // Nothing to do in here unless this has been set. |
| 336 if (!update_contents_after_successful_compositing_) |
| 337 return; |
| 338 |
| 339 update_contents_after_successful_compositing_ = false; |
| 340 |
| 341 // Early out if no contents is currently assigned to the surface. |
| 342 if (!current_buffer_) |
| 343 return; |
| 344 |
| 345 // Update contents by producing a new texture mailbox for the current buffer. |
| 346 cc::TextureMailbox texture_mailbox; |
| 347 scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback = |
| 348 current_buffer_->ProduceTextureMailbox(&texture_mailbox); |
| 349 if (texture_mailbox_release_callback) { |
| 350 layer()->SetTextureMailbox(texture_mailbox, |
| 351 texture_mailbox_release_callback.Pass(), |
| 352 texture_mailbox.size_in_pixels()); |
| 353 layer()->SetTextureFlipped(false); |
| 354 layer()->SchedulePaint(gfx::Rect(texture_mailbox.size_in_pixels())); |
| 355 } |
| 356 } |
| 357 |
| 358 void Surface::OnCompositingAborted(ui::Compositor* compositor) { |
| 359 // The contents of this surface might be lost if compositing aborted because |
| 360 // of a lost graphics context. We recover from this by updating the contents |
| 361 // of the surface next time the compositor successfully ends compositing. |
| 362 update_contents_after_successful_compositing_ = true; |
| 363 } |
| 364 |
325 void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { | 365 void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { |
326 compositor->RemoveObserver(this); | 366 compositor->RemoveObserver(this); |
327 compositor_ = nullptr; | 367 compositor_ = nullptr; |
328 } | 368 } |
329 | 369 |
330 } // namespace exo | 370 } // namespace exo |
OLD | NEW |