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