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