Chromium Code Reviews| Index: components/exo/surface.cc |
| diff --git a/components/exo/surface.cc b/components/exo/surface.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..22723515014ebf4bde1f4d0bfdf03f9a4e7738d5 |
| --- /dev/null |
| +++ b/components/exo/surface.cc |
| @@ -0,0 +1,169 @@ |
| +// 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() : compositor_(nullptr), 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 (compositor_) |
| + compositor_->RemoveObserver(this); |
| + |
| + // Call pending frame callbacks with a null frame time to indicate that they |
| + // have been cancelled. |
| + frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
| + active_frame_callbacks_.splice(active_frame_callbacks_.end(), |
| + frame_callbacks_); |
| + std::for_each(active_frame_callbacks_.begin(), active_frame_callbacks_.end(), |
| + [](const FrameCallback& frame_callback) { |
| + frame_callback.Run(base::TimeTicks()); |
| + }); |
|
piman
2015/11/17 02:43:53
nit:
for (const auto& frame_callback : active_fram
reveman
2015/11/17 18:04:04
Done.
|
| +} |
| + |
| +void Surface::Attach(Buffer* buffer, const gfx::Point& point) { |
|
piman
2015/11/17 02:43:53
What is |point| used for?
reveman
2015/11/17 18:04:04
This was supposed to be an offset and not a 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 && !pending_frame_callbacks_.empty()) { |
| + // Start observing the compositor for frame callbacks. |
| + if (!compositor_) { |
| + compositor->AddObserver(this); |
| + compositor_ = compositor; |
| + } |
| + |
| + // Move pending frame callbacks to the end of |frame_callbacks_|. |
| + frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
| + } |
| +} |
| + |
| +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(); |
| + } |
| +} |
| + |
| +void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { |
| + compositor->RemoveObserver(this); |
| + compositor_ = nullptr; |
| +} |
| + |
| +} // namespace exo |