Index: components/exo/surface.cc |
diff --git a/components/exo/surface.cc b/components/exo/surface.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..87e0f28c9ab1414833447fb6b1b33b819a45e984 |
--- /dev/null |
+++ b/components/exo/surface.cc |
@@ -0,0 +1,163 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/exo/surface.h" |
+ |
+#include "base/callback_helpers.h" |
+#include "base/logging.h" |
+#include "base/trace_event/trace_event.h" |
+#include "base/trace_event/trace_event_argument.h" |
+#include "cc/resources/single_release_callback.h" |
+#include "components/exo/buffer.h" |
+#include "components/exo/surface_delegate.h" |
+#include "ui/compositor/layer.h" |
+#include "ui/gfx/buffer_format_util.h" |
+#include "ui/gfx/gpu_memory_buffer.h" |
+ |
+namespace exo { |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Surface, public: |
+ |
+Surface::Surface() : delegate_(nullptr) { |
+ SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); |
+ set_owned_by_client(); |
+} |
+ |
+Surface::~Surface() { |
+ if (delegate_) |
+ delegate_->OnSurfaceDestroying(); |
+ |
+ if (pending_mailbox_release_callback_) |
+ pending_mailbox_release_callback_->Run(gpu::SyncToken(), false); |
+ |
+ layer()->SetShowSolidColorContent(); |
+ |
+ // If we are observing the compositor for frame callbacks, stop now. |
+ if (!frame_callbacks_.empty() || !active_frame_callbacks_.empty()) |
+ layer()->GetCompositor()->RemoveObserver(this); |
+} |
+ |
+void Surface::Attach(Buffer* buffer, const gfx::Point& point) { |
+ TRACE_EVENT2("exo", "Surface::Attach", "buffer", buffer->AsTracedValue(), |
+ "point", point.ToString()); |
+ |
+ // If Attach() is called twice without calling Commit(), run the release |
+ // callback for the previous buffer now. |
+ if (pending_mailbox_release_callback_) { |
+ pending_mailbox_release_callback_->Run(gpu::SyncToken(), false); |
+ pending_mailbox_release_callback_ = nullptr; |
+ } |
+ |
+ // If |buffer| is null, the following Commit() call will remove the surface |
+ // content. |
+ if (buffer) { |
+ pending_mailbox_release_callback_ = |
+ buffer->GetTextureMailbox(&pending_mailbox_); |
+ } |
+} |
+ |
+void Surface::Damage(const gfx::Rect& damage) { |
+ TRACE_EVENT1("exo", "Surface::Damage", "damage", damage.ToString()); |
+ |
+ pending_damage_.Union(damage); |
+} |
+ |
+void Surface::RequestFrameCallback(const FrameCallback& callback) { |
+ TRACE_EVENT0("exo", "Surface::RequestFrameCallback"); |
+ |
+ pending_frame_callbacks_.push_back(callback); |
+} |
+ |
+void Surface::SetOpaqueRegion(const cc::Region& region) { |
+ TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region", region.ToString()); |
+ |
+ pending_opaque_region_ = region; |
+} |
+ |
+void Surface::Commit() { |
+ TRACE_EVENT0("exo", "Surface::Commit"); |
+ |
+ if (delegate_) |
+ delegate_->OnSurfaceCommit(); |
+ |
+ if (pending_mailbox_release_callback_) { |
+ // Update layer with the new contents. |
+ layer()->SetTextureMailbox(pending_mailbox_, |
+ pending_mailbox_release_callback_.Pass(), |
+ pending_mailbox_.size_in_pixels()); |
+ layer()->SetTextureFlipped(false); |
+ layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), |
+ pending_mailbox_.size_in_pixels())); |
+ layer()->SetFillsBoundsOpaquely(pending_opaque_region_.Contains( |
+ gfx::Rect(pending_mailbox_.size_in_pixels()))); |
+ } else { |
+ // Show solid color content if there is no pending buffer. |
+ layer()->SetShowSolidColorContent(); |
+ } |
+ |
+ // Schedule redraw of the damage region. |
+ layer()->SchedulePaint(pending_damage_); |
+ pending_damage_ = gfx::Rect(); |
+ |
+ ui::Compositor* compositor = layer()->GetCompositor(); |
+ if (compositor) { |
+ // Start observing the compositor for frame callbacks. |
+ if (frame_callbacks_.empty() && active_frame_callbacks_.empty()) |
lpique
2015/11/05 21:25:00
Shouldn't you also check "&& !frame_callbacks_.emp
|
+ compositor->AddObserver(this); |
+ |
+ // Move pending frame callbacks to the end of |frame_callbacks_|. |
+ frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
lpique
2015/11/05 21:25:00
Under the calling sequence:
Surface::RequestFra
|
+ } |
+} |
+ |
+void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { |
+ DCHECK(!delegate_ || !delegate); |
+ delegate_ = delegate; |
+} |
+ |
+scoped_refptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { |
+ scoped_refptr<base::trace_event::TracedValue> value = |
+ new base::trace_event::TracedValue; |
+ value->SetString("name", layer()->name()); |
+ return value; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// views::Views overrides: |
+ |
+gfx::Size Surface::GetPreferredSize() const { |
+ return pending_mailbox_release_callback_ ? pending_mailbox_.size_in_pixels() |
+ : layer()->size(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ui::CompositorObserver overrides: |
+ |
+void Surface::OnCompositingDidCommit(ui::Compositor* compositor) { |
+ // Move frame callbacks to the end of |active_frame_callbacks_|. |
+ active_frame_callbacks_.splice(active_frame_callbacks_.end(), |
+ frame_callbacks_); |
+} |
+ |
+void Surface::OnCompositingStarted(ui::Compositor* compositor, |
+ base::TimeTicks start_time) { |
+ // Run all frame callbacks associated with the compositor's active tree. |
+ while (!active_frame_callbacks_.empty()) { |
+ active_frame_callbacks_.front().Run(start_time); |
+ active_frame_callbacks_.pop_front(); |
+ } |
+ |
+ // Stop observing the compositor if we have processed all frame callbacks. |
+ if (frame_callbacks_.empty()) |
+ compositor->RemoveObserver(this); |
+} |
+ |
+void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { |
+ compositor->RemoveObserver(this); |
+ active_frame_callbacks_.clear(); |
+ frame_callbacks_.clear(); |
+} |
+ |
+} // namespace exo |