Commit 5f933e80 authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

exo: Use one LayerTreeFrameSink per toplevel window

Having one LayerTreeFrameSink for every sub-surface
causes synchronizing problem between sub-surfaces, so
we decide to only have one LayerTreeFrameSink per
toplevel window.

Bug: 731742
Change-Id: I6f3e09c33f6f98aab281ce2fab032f9df29f1e7d
Reviewed-on: https://chromium-review.googlesource.com/552719
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarDavid Reveman <reveman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#486788}
parent 947acc07
...@@ -411,7 +411,6 @@ Buffer::~Buffer() {} ...@@ -411,7 +411,6 @@ Buffer::~Buffer() {}
bool Buffer::ProduceTransferableResource( bool Buffer::ProduceTransferableResource(
LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder, LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder,
cc::ResourceId resource_id,
bool secure_output_only, bool secure_output_only,
bool client_usage, bool client_usage,
cc::TransferableResource* resource) { cc::TransferableResource* resource) {
...@@ -439,7 +438,7 @@ bool Buffer::ProduceTransferableResource( ...@@ -439,7 +438,7 @@ bool Buffer::ProduceTransferableResource(
return false; return false;
} }
resource->id = resource_id; resource->id = layer_tree_frame_sink_holder->AllocateResourceId();
resource->format = viz::RGBA_8888; resource->format = viz::RGBA_8888;
resource->filter = GL_LINEAR; resource->filter = GL_LINEAR;
resource->size = gpu_memory_buffer_->GetSize(); resource->size = gpu_memory_buffer_->GetSize();
...@@ -473,7 +472,7 @@ bool Buffer::ProduceTransferableResource( ...@@ -473,7 +472,7 @@ bool Buffer::ProduceTransferableResource(
// The contents texture will be released when no longer used by the // The contents texture will be released when no longer used by the
// compositor. // compositor.
layer_tree_frame_sink_holder->SetResourceReleaseCallback( layer_tree_frame_sink_holder->SetResourceReleaseCallback(
resource_id, resource->id,
base::Bind(&Buffer::Texture::ReleaseTexImage, base::Bind(&Buffer::Texture::ReleaseTexImage,
base::Unretained(contents_texture), base::Unretained(contents_texture),
base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(), base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(),
...@@ -503,7 +502,7 @@ bool Buffer::ProduceTransferableResource( ...@@ -503,7 +502,7 @@ bool Buffer::ProduceTransferableResource(
// The mailbox texture will be released when no longer used by the // The mailbox texture will be released when no longer used by the
// compositor. // compositor.
layer_tree_frame_sink_holder->SetResourceReleaseCallback( layer_tree_frame_sink_holder->SetResourceReleaseCallback(
resource_id, resource->id,
base::Bind(&Buffer::Texture::Release, base::Unretained(texture), base::Bind(&Buffer::Texture::Release, base::Unretained(texture),
base::Bind(&Buffer::ReleaseTexture, AsWeakPtr(), base::Bind(&Buffer::ReleaseTexture, AsWeakPtr(),
base::Passed(&texture_)))); base::Passed(&texture_))));
......
...@@ -54,7 +54,6 @@ class Buffer : public base::SupportsWeakPtr<Buffer> { ...@@ -54,7 +54,6 @@ class Buffer : public base::SupportsWeakPtr<Buffer> {
// |non_client_usage| is true. // |non_client_usage| is true.
bool ProduceTransferableResource( bool ProduceTransferableResource(
LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder, LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder,
cc::ResourceId resource_id,
bool secure_output_only, bool secure_output_only,
bool client_usage, bool client_usage,
cc::TransferableResource* resource); cc::TransferableResource* resource);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "cc/output/context_provider.h" #include "cc/output/context_provider.h"
#include "cc/resources/single_release_callback.h" #include "cc/resources/single_release_callback.h"
#include "components/exo/buffer.h" #include "components/exo/buffer.h"
#include "components/exo/surface.h" #include "components/exo/surface_tree_host.h"
#include "components/exo/test/exo_test_base.h" #include "components/exo/test/exo_test_base.h"
#include "components/exo/test/exo_test_helper.h" #include "components/exo/test/exo_test_helper.h"
#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gles2_interface.h"
...@@ -29,12 +29,12 @@ void Release(int* release_call_count) { ...@@ -29,12 +29,12 @@ void Release(int* release_call_count) {
TEST_F(BufferTest, ReleaseCallback) { TEST_F(BufferTest, ReleaseCallback) {
gfx::Size buffer_size(256, 256); gfx::Size buffer_size(256, 256);
std::unique_ptr<Buffer> buffer( auto buffer = base::MakeUnique<Buffer>(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
std::unique_ptr<Surface> surface(new Surface); auto surface_tree_host =
const viz::FrameSinkId arbitrary_frame_sink_id(1, 1); base::MakeUnique<SurfaceTreeHost>("BufferTest", nullptr);
LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder = LayerTreeFrameSinkHolder* frame_sink_holder =
surface->layer_tree_frame_sink_holder(); surface_tree_host->layer_tree_frame_sink_holder();
// Set the release callback. // Set the release callback.
int release_call_count = 0; int release_call_count = 0;
...@@ -44,8 +44,8 @@ TEST_F(BufferTest, ReleaseCallback) { ...@@ -44,8 +44,8 @@ TEST_F(BufferTest, ReleaseCallback) {
buffer->OnAttach(); buffer->OnAttach();
cc::TransferableResource resource; cc::TransferableResource resource;
// Produce a transferable resource for the contents of the buffer. // Produce a transferable resource for the contents of the buffer.
bool rv = buffer->ProduceTransferableResource(layer_tree_frame_sink_holder, 0, bool rv = buffer->ProduceTransferableResource(frame_sink_holder, false, true,
false, true, &resource); &resource);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
// Release buffer. // Release buffer.
...@@ -54,7 +54,7 @@ TEST_F(BufferTest, ReleaseCallback) { ...@@ -54,7 +54,7 @@ TEST_F(BufferTest, ReleaseCallback) {
returned_resource.sync_token = resource.mailbox_holder.sync_token; returned_resource.sync_token = resource.mailbox_holder.sync_token;
returned_resource.lost = false; returned_resource.lost = false;
std::vector<cc::ReturnedResource> resources = {returned_resource}; std::vector<cc::ReturnedResource> resources = {returned_resource};
layer_tree_frame_sink_holder->ReclaimResources(resources); frame_sink_holder->ReclaimResources(resources);
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
ASSERT_EQ(release_call_count, 0); ASSERT_EQ(release_call_count, 0);
...@@ -67,19 +67,18 @@ TEST_F(BufferTest, ReleaseCallback) { ...@@ -67,19 +67,18 @@ TEST_F(BufferTest, ReleaseCallback) {
TEST_F(BufferTest, IsLost) { TEST_F(BufferTest, IsLost) {
gfx::Size buffer_size(256, 256); gfx::Size buffer_size(256, 256);
std::unique_ptr<Buffer> buffer( auto buffer = base::MakeUnique<Buffer>(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
const viz::FrameSinkId arbitrary_frame_sink_id(1, 1); auto surface_tree_host =
std::unique_ptr<Surface> surface(new Surface); base::MakeUnique<SurfaceTreeHost>("BufferTest", nullptr);
LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder = LayerTreeFrameSinkHolder* frame_sink_holder =
surface->layer_tree_frame_sink_holder(); surface_tree_host->layer_tree_frame_sink_holder();
cc::ResourceId resource_id = 0;
buffer->OnAttach(); buffer->OnAttach();
// Acquire a texture transferable resource for the contents of the buffer. // Acquire a texture transferable resource for the contents of the buffer.
cc::TransferableResource resource; cc::TransferableResource resource;
bool rv = buffer->ProduceTransferableResource( bool rv = buffer->ProduceTransferableResource(frame_sink_holder, false, true,
layer_tree_frame_sink_holder, resource_id, false, true, &resource); &resource);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
scoped_refptr<cc::ContextProvider> context_provider = scoped_refptr<cc::ContextProvider> context_provider =
...@@ -95,28 +94,27 @@ TEST_F(BufferTest, IsLost) { ...@@ -95,28 +94,27 @@ TEST_F(BufferTest, IsLost) {
// Release buffer. // Release buffer.
bool is_lost = true; bool is_lost = true;
cc::ReturnedResource returned_resource; cc::ReturnedResource returned_resource;
returned_resource.id = resource_id; returned_resource.id = resource.id;
returned_resource.sync_token = gpu::SyncToken(); returned_resource.sync_token = gpu::SyncToken();
returned_resource.lost = is_lost; returned_resource.lost = is_lost;
std::vector<cc::ReturnedResource> resources = {returned_resource}; std::vector<cc::ReturnedResource> resources = {returned_resource};
layer_tree_frame_sink_holder->ReclaimResources(resources); frame_sink_holder->ReclaimResources(resources);
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
// Producing a new texture transferable resource for the contents of the // Producing a new texture transferable resource for the contents of the
// buffer. // buffer.
++resource_id;
cc::TransferableResource new_resource; cc::TransferableResource new_resource;
rv = buffer->ProduceTransferableResource( rv = buffer->ProduceTransferableResource(frame_sink_holder, false, false,
layer_tree_frame_sink_holder, resource_id, false, false, &new_resource); &new_resource);
ASSERT_TRUE(rv); ASSERT_TRUE(rv);
buffer->OnDetach(); buffer->OnDetach();
cc::ReturnedResource returned_resource2; cc::ReturnedResource returned_resource2;
returned_resource2.id = resource_id; returned_resource2.id = new_resource.id;
returned_resource2.sync_token = gpu::SyncToken(); returned_resource2.sync_token = gpu::SyncToken();
returned_resource2.lost = false; returned_resource2.lost = false;
std::vector<cc::ReturnedResource> resources2 = {returned_resource2}; std::vector<cc::ReturnedResource> resources2 = {returned_resource2};
layer_tree_frame_sink_holder->ReclaimResources(resources2); frame_sink_holder->ReclaimResources(resources2);
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include "cc/output/layer_tree_frame_sink.h" #include "cc/output/layer_tree_frame_sink.h"
#include "cc/resources/returned_resource.h" #include "cc/resources/returned_resource.h"
#include "components/exo/surface.h" #include "components/exo/surface_tree_host.h"
namespace exo { namespace exo {
...@@ -14,19 +14,16 @@ namespace exo { ...@@ -14,19 +14,16 @@ namespace exo {
// LayerTreeFrameSinkHolder, public: // LayerTreeFrameSinkHolder, public:
LayerTreeFrameSinkHolder::LayerTreeFrameSinkHolder( LayerTreeFrameSinkHolder::LayerTreeFrameSinkHolder(
Surface* surface, SurfaceTreeHost* surface_tree_host,
std::unique_ptr<cc::LayerTreeFrameSink> frame_sink) std::unique_ptr<cc::LayerTreeFrameSink> frame_sink)
: surface_(surface), : surface_tree_host_(surface_tree_host),
frame_sink_(std::move(frame_sink)), frame_sink_(std::move(frame_sink)),
weak_factory_(this) { weak_factory_(this) {
surface_->AddSurfaceObserver(this);
frame_sink_->BindToClient(this); frame_sink_->BindToClient(this);
} }
LayerTreeFrameSinkHolder::~LayerTreeFrameSinkHolder() { LayerTreeFrameSinkHolder::~LayerTreeFrameSinkHolder() {
frame_sink_->DetachFromClient(); frame_sink_->DetachFromClient();
if (surface_)
surface_->RemoveSurfaceObserver(this);
// Release all resources which aren't returned from LayerTreeFrameSink. // Release all resources which aren't returned from LayerTreeFrameSink.
for (auto& callback : release_callbacks_) for (auto& callback : release_callbacks_)
...@@ -58,8 +55,7 @@ base::WeakPtr<LayerTreeFrameSinkHolder> LayerTreeFrameSinkHolder::GetWeakPtr() { ...@@ -58,8 +55,7 @@ base::WeakPtr<LayerTreeFrameSinkHolder> LayerTreeFrameSinkHolder::GetWeakPtr() {
void LayerTreeFrameSinkHolder::SetBeginFrameSource( void LayerTreeFrameSinkHolder::SetBeginFrameSource(
cc::BeginFrameSource* source) { cc::BeginFrameSource* source) {
if (surface_) surface_tree_host_->SetBeginFrameSource(source);
surface_->SetBeginFrameSource(source);
} }
void LayerTreeFrameSinkHolder::ReclaimResources( void LayerTreeFrameSinkHolder::ReclaimResources(
...@@ -75,16 +71,7 @@ void LayerTreeFrameSinkHolder::ReclaimResources( ...@@ -75,16 +71,7 @@ void LayerTreeFrameSinkHolder::ReclaimResources(
} }
void LayerTreeFrameSinkHolder::DidReceiveCompositorFrameAck() { void LayerTreeFrameSinkHolder::DidReceiveCompositorFrameAck() {
if (surface_) surface_tree_host_->DidReceiveCompositorFrameAck();
surface_->DidReceiveCompositorFrameAck();
}
////////////////////////////////////////////////////////////////////////////////
// SurfaceObserver overrides:
void LayerTreeFrameSinkHolder::OnSurfaceDestroying(Surface* surface) {
surface_->RemoveSurfaceObserver(this);
surface_ = nullptr;
} }
} // namespace exo } // namespace exo
...@@ -10,23 +10,19 @@ ...@@ -10,23 +10,19 @@
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "cc/output/layer_tree_frame_sink_client.h" #include "cc/output/layer_tree_frame_sink_client.h"
#include "cc/resources/release_callback.h" #include "cc/resources/release_callback.h"
#include "components/exo/surface_observer.h"
namespace cc { namespace cc {
class LayerTreeFrameSink; class LayerTreeFrameSink;
} }
namespace exo { namespace exo {
class Surface; class SurfaceTreeHost;
// This class talks to CompositorFrameSink and keeps track of references to // This class talks to CompositorFrameSink and keeps track of references to
// the contents of Buffers. It's keeped alive by references from // the contents of Buffers.
// release_callbacks_. It's destroyed when its owning Surface is destroyed and class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient {
// the last outstanding release callback is called.
class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient,
public SurfaceObserver {
public: public:
LayerTreeFrameSinkHolder(Surface* surface, LayerTreeFrameSinkHolder(SurfaceTreeHost* surface_tree_host,
std::unique_ptr<cc::LayerTreeFrameSink> frame_sink); std::unique_ptr<cc::LayerTreeFrameSink> frame_sink);
~LayerTreeFrameSinkHolder() override; ~LayerTreeFrameSinkHolder() override;
...@@ -53,15 +49,12 @@ class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient, ...@@ -53,15 +49,12 @@ class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient,
const gfx::Rect& viewport_rect, const gfx::Rect& viewport_rect,
const gfx::Transform& transform) override {} const gfx::Transform& transform) override {}
// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
private: private:
// A collection of callbacks used to release resources. // A collection of callbacks used to release resources.
using ResourceReleaseCallbackMap = base::flat_map<int, cc::ReleaseCallback>; using ResourceReleaseCallbackMap = base::flat_map<int, cc::ReleaseCallback>;
ResourceReleaseCallbackMap release_callbacks_; ResourceReleaseCallbackMap release_callbacks_;
Surface* surface_; SurfaceTreeHost* surface_tree_host_;
std::unique_ptr<cc::LayerTreeFrameSink> frame_sink_; std::unique_ptr<cc::LayerTreeFrameSink> frame_sink_;
// The next resource id the buffer is attached to. // The next resource id the buffer is attached to.
......
...@@ -956,6 +956,9 @@ void ShellSurface::OnPostWindowStateTypeChange( ...@@ -956,6 +956,9 @@ void ShellSurface::OnPostWindowStateTypeChange(
void ShellSurface::OnWindowBoundsChanged(aura::Window* window, void ShellSurface::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds, const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) { const gfx::Rect& new_bounds) {
if (window == host_window())
return;
// TODO(domlaskowski): For BoundsMode::CLIENT, the configure callback does not // TODO(domlaskowski): For BoundsMode::CLIENT, the configure callback does not
// yet support resizing. See crbug.com/699746. // yet support resizing. See crbug.com/699746.
if (bounds_mode_ == BoundsMode::CLIENT) if (bounds_mode_ == BoundsMode::CLIENT)
...@@ -987,7 +990,23 @@ void ShellSurface::OnWindowBoundsChanged(aura::Window* window, ...@@ -987,7 +990,23 @@ void ShellSurface::OnWindowBoundsChanged(aura::Window* window,
} }
} }
void ShellSurface::OnWindowAddedToRootWindow(aura::Window* window) {
if (window == host_window())
SurfaceTreeHost::OnWindowAddedToRootWindow(window);
}
void ShellSurface::OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) {
if (window == host_window())
SurfaceTreeHost::OnWindowRemovingFromRootWindow(window, new_root);
}
void ShellSurface::OnWindowDestroying(aura::Window* window) { void ShellSurface::OnWindowDestroying(aura::Window* window) {
if (window == host_window()) {
SurfaceTreeHost::OnWindowDestroying(window);
return;
}
if (window == parent_) { if (window == parent_) {
parent_ = nullptr; parent_ = nullptr;
// |parent_| being set to null effects the ability to maximize the window. // |parent_| being set to null effects the ability to maximize the window.
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "components/exo/surface_observer.h" #include "components/exo/surface_observer.h"
#include "components/exo/surface_tree_host.h" #include "components/exo/surface_tree_host.h"
#include "components/exo/wm_helper.h" #include "components/exo/wm_helper.h"
#include "ui/aura/window_observer.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -47,7 +46,6 @@ class ShellSurface : public SurfaceTreeHost, ...@@ -47,7 +46,6 @@ class ShellSurface : public SurfaceTreeHost,
public views::WidgetDelegate, public views::WidgetDelegate,
public views::View, public views::View,
public ash::wm::WindowStateObserver, public ash::wm::WindowStateObserver,
public aura::WindowObserver,
public WMHelper::ActivationObserver, public WMHelper::ActivationObserver,
public WMHelper::DisplayConfigurationObserver { public WMHelper::DisplayConfigurationObserver {
public: public:
...@@ -258,6 +256,9 @@ class ShellSurface : public SurfaceTreeHost, ...@@ -258,6 +256,9 @@ class ShellSurface : public SurfaceTreeHost,
void OnWindowBoundsChanged(aura::Window* window, void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds, const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) override; const gfx::Rect& new_bounds) override;
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
void OnWindowDestroying(aura::Window* window) override; void OnWindowDestroying(aura::Window* window) override;
// Overridden from WMHelper::ActivationObserver: // Overridden from WMHelper::ActivationObserver:
......
...@@ -96,7 +96,8 @@ void SubSurface::OnSurfaceCommit() { ...@@ -96,7 +96,8 @@ void SubSurface::OnSurfaceCommit() {
if (IsSurfaceSynchronized()) if (IsSurfaceSynchronized())
return; return;
surface_->CommitSurfaceHierarchy(); // TODO(penghuang): http://crbug.com/740110 Support async mode.
NOTIMPLEMENTED() << "Async subsurface is not supported!";
} }
bool SubSurface::IsSurfaceSynchronized() const { bool SubSurface::IsSurfaceSynchronized() const {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "components/exo/sub_surface.h" #include "components/exo/sub_surface.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface.h" #include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h" #include "components/exo/test/exo_test_base.h"
#include "components/exo/test/exo_test_helper.h" #include "components/exo/test/exo_test_helper.h"
...@@ -16,10 +17,10 @@ namespace { ...@@ -16,10 +17,10 @@ namespace {
using SubSurfaceTest = test::ExoTestBase; using SubSurfaceTest = test::ExoTestBase;
TEST_F(SubSurfaceTest, SetPosition) { TEST_F(SubSurfaceTest, SetPosition) {
std::unique_ptr<Surface> parent(new Surface); auto parent = base::MakeUnique<Surface>();
std::unique_ptr<Surface> surface(new Surface); auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
std::unique_ptr<SubSurface> sub_surface( auto surface = base::MakeUnique<Surface>();
new SubSurface(surface.get(), parent.get())); auto sub_surface = base::MakeUnique<SubSurface>(surface.get(), parent.get());
// Initial position is at the origin. // Initial position is at the origin.
EXPECT_EQ(gfx::Point().ToString(), EXPECT_EQ(gfx::Point().ToString(),
...@@ -49,14 +50,15 @@ TEST_F(SubSurfaceTest, SetPosition) { ...@@ -49,14 +50,15 @@ TEST_F(SubSurfaceTest, SetPosition) {
} }
TEST_F(SubSurfaceTest, PlaceAbove) { TEST_F(SubSurfaceTest, PlaceAbove) {
std::unique_ptr<Surface> parent(new Surface); auto parent = base::MakeUnique<Surface>();
std::unique_ptr<Surface> surface1(new Surface); auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
std::unique_ptr<Surface> surface2(new Surface); auto surface1 = base::MakeUnique<Surface>();
std::unique_ptr<Surface> non_sibling_surface(new Surface); auto surface2 = base::MakeUnique<Surface>();
std::unique_ptr<SubSurface> sub_surface1( auto non_sibling_surface = base::MakeUnique<Surface>();
new SubSurface(surface1.get(), parent.get())); auto sub_surface1 =
std::unique_ptr<SubSurface> sub_surface2( base::MakeUnique<SubSurface>(surface1.get(), parent.get());
new SubSurface(surface2.get(), parent.get())); auto sub_surface2 =
base::MakeUnique<SubSurface>(surface2.get(), parent.get());
ASSERT_EQ(2u, parent->window()->children().size()); ASSERT_EQ(2u, parent->window()->children().size());
EXPECT_EQ(surface1->window(), parent->window()->children()[0]); EXPECT_EQ(surface1->window(), parent->window()->children()[0]);
...@@ -80,14 +82,15 @@ TEST_F(SubSurfaceTest, PlaceAbove) { ...@@ -80,14 +82,15 @@ TEST_F(SubSurfaceTest, PlaceAbove) {
} }
TEST_F(SubSurfaceTest, PlaceBelow) { TEST_F(SubSurfaceTest, PlaceBelow) {
std::unique_ptr<Surface> parent(new Surface); auto parent = base::MakeUnique<Surface>();
std::unique_ptr<Surface> surface1(new Surface); auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
std::unique_ptr<Surface> surface2(new Surface); auto surface1 = base::MakeUnique<Surface>();
std::unique_ptr<Surface> non_sibling_surface(new Surface); auto surface2 = base::MakeUnique<Surface>();
std::unique_ptr<SubSurface> sub_surface1( auto non_sibling_surface = base::MakeUnique<Surface>();
new SubSurface(surface1.get(), parent.get())); auto sub_surface1 =
std::unique_ptr<SubSurface> sub_surface2( base::MakeUnique<SubSurface>(surface1.get(), parent.get());
new SubSurface(surface2.get(), parent.get())); auto sub_surface2 =
base::MakeUnique<SubSurface>(surface2.get(), parent.get());
ASSERT_EQ(2u, parent->window()->children().size()); ASSERT_EQ(2u, parent->window()->children().size());
EXPECT_EQ(surface1->window(), parent->window()->children()[0]); EXPECT_EQ(surface1->window(), parent->window()->children()[0]);
...@@ -111,13 +114,14 @@ TEST_F(SubSurfaceTest, PlaceBelow) { ...@@ -111,13 +114,14 @@ TEST_F(SubSurfaceTest, PlaceBelow) {
} }
TEST_F(SubSurfaceTest, SetCommitBehavior) { TEST_F(SubSurfaceTest, SetCommitBehavior) {
std::unique_ptr<Surface> parent(new Surface); auto parent = base::MakeUnique<Surface>();
std::unique_ptr<Surface> child(new Surface); auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
std::unique_ptr<Surface> grandchild(new Surface); auto child = base::MakeUnique<Surface>();
std::unique_ptr<SubSurface> child_sub_surface( auto grandchild = base::MakeUnique<Surface>();
new SubSurface(child.get(), parent.get())); auto child_sub_surface =
std::unique_ptr<SubSurface> grandchild_sub_surface( base::MakeUnique<SubSurface>(child.get(), parent.get());
new SubSurface(grandchild.get(), child.get())); auto grandchild_sub_surface =
base::MakeUnique<SubSurface>(grandchild.get(), child.get());
// Initial position is at the origin. // Initial position is at the origin.
EXPECT_EQ(gfx::Point().ToString(), EXPECT_EQ(gfx::Point().ToString(),
...@@ -141,19 +145,20 @@ TEST_F(SubSurfaceTest, SetCommitBehavior) { ...@@ -141,19 +145,20 @@ TEST_F(SubSurfaceTest, SetCommitBehavior) {
EXPECT_EQ(position1.ToString(), EXPECT_EQ(position1.ToString(),
grandchild->window()->bounds().origin().ToString()); grandchild->window()->bounds().origin().ToString());
// TODO(penghuang): http://crbug.com/740110 Support async mode.
// Disable synchronous commit behavior. // Disable synchronous commit behavior.
bool synchronized = false; // bool synchronized = false;
child_sub_surface->SetCommitBehavior(synchronized); // child_sub_surface->SetCommitBehavior(synchronized);
// Set position to 20, 20. // Set position to 20, 20.
gfx::Point position2(20, 20); // gfx::Point position2(20, 20);
grandchild_sub_surface->SetPosition(position2); // grandchild_sub_surface->SetPosition(position2);
child->Commit(); // child->Commit();
// A Commit() call on child should be sufficient for the position of // A Commit() call on child should be sufficient for the position of
// grandchild to take effect when synchronous is disabled. // grandchild to take effect when synchronous is disabled.
EXPECT_EQ(position2.ToString(), // EXPECT_EQ(position2.ToString(),
grandchild->window()->bounds().origin().ToString()); // grandchild->window()->bounds().origin().ToString());
} }
} // namespace } // namespace
......
This diff is collapsed.
...@@ -15,13 +15,10 @@ ...@@ -15,13 +15,10 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "cc/resources/transferable_resource.h" #include "cc/resources/transferable_resource.h"
#include "cc/scheduler/begin_frame_source.h"
#include "components/exo/layer_tree_frame_sink_holder.h" #include "components/exo/layer_tree_frame_sink_holder.h"
#include "third_party/skia/include/core/SkBlendMode.h" #include "third_party/skia/include/core/SkBlendMode.h"
#include "third_party/skia/include/core/SkRegion.h" #include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -31,12 +28,17 @@ class TracedValue; ...@@ -31,12 +28,17 @@ class TracedValue;
} }
} }
namespace cc {
class CompositorFrame;
}
namespace gfx { namespace gfx {
class Path; class Path;
} }
namespace exo { namespace exo {
class Buffer; class Buffer;
class LayerTreeFrameSinkHolder;
class Pointer; class Pointer;
class SurfaceDelegate; class SurfaceDelegate;
class SurfaceObserver; class SurfaceObserver;
...@@ -52,28 +54,18 @@ using CursorProvider = Pointer; ...@@ -52,28 +54,18 @@ using CursorProvider = Pointer;
// This class represents a rectangular area that is displayed on the screen. // This class represents a rectangular area that is displayed on the screen.
// It has a location, size and pixel contents. // It has a location, size and pixel contents.
class Surface : public ui::ContextFactoryObserver, class Surface : public ui::PropertyHandler {
public aura::WindowObserver,
public ui::PropertyHandler,
public ui::CompositorVSyncManager::Observer,
public cc::BeginFrameObserverBase {
public: public:
using PropertyDeallocator = void (*)(int64_t value); using PropertyDeallocator = void (*)(int64_t value);
Surface(); Surface();
~Surface() override; ~Surface();
// Type-checking downcast routine. // Type-checking downcast routine.
static Surface* AsSurface(const aura::Window* window); static Surface* AsSurface(const aura::Window* window);
aura::Window* window() { return window_.get(); } aura::Window* window() { return window_.get(); }
viz::SurfaceId GetSurfaceId() const;
LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder() {
return layer_tree_frame_sink_holder_.get();
}
// Set a buffer as the content of this surface. A buffer can only be attached // Set a buffer as the content of this surface. A buffer can only be attached
// to one surface at a time. // to one surface at a time.
void Attach(Buffer* buffer); void Attach(Buffer* buffer);
...@@ -144,7 +136,17 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -144,7 +136,17 @@ class Surface : public ui::ContextFactoryObserver,
// This will synchronously commit all pending state of the surface and its // This will synchronously commit all pending state of the surface and its
// descendants by recursively calling CommitSurfaceHierarchy() for each // descendants by recursively calling CommitSurfaceHierarchy() for each
// sub-surface with pending state. // sub-surface with pending state.
void CommitSurfaceHierarchy(); enum FrameType {
FRAME_TYPE_COMMIT,
FRAME_TYPE_RECREATED_RESOURCES,
};
void CommitSurfaceHierarchy(
const gfx::Point& origin,
FrameType frame_type,
LayerTreeFrameSinkHolder* frame_sink_holder,
cc::CompositorFrame* frame,
std::list<FrameCallback>* frame_callbacks,
std::list<PresentationCallback>* presentation_callbacks);
// Returns true if surface is in synchronized mode. // Returns true if surface is in synchronized mode.
bool IsSynchronized() const; bool IsSynchronized() const;
...@@ -186,10 +188,6 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -186,10 +188,6 @@ class Surface : public ui::ContextFactoryObserver,
// Returns a trace value representing the state of the surface. // Returns a trace value representing the state of the surface.
std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const; std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
// Call this to indicate that the previous CompositorFrame is processed and
// the surface is being scheduled for a draw.
void DidReceiveCompositorFrameAck();
// Called when the begin frame source has changed. // Called when the begin frame source has changed.
void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source); void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
...@@ -202,26 +200,16 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -202,26 +200,16 @@ class Surface : public ui::ContextFactoryObserver,
// Enables 'stylus-only' mode for the associated window. // Enables 'stylus-only' mode for the associated window.
void SetStylusOnly(); void SetStylusOnly();
// Overridden from ui::ContextFactoryObserver: // Recreates resources for the surface and sub surfaces.
void OnLostResources() override; void RecreateResources(LayerTreeFrameSinkHolder* frame_sink_holder);
// Overridden from aura::WindowObserver:
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
// Overridden from ui::CompositorVSyncManager::Observer: // Returns true if the surface's bounds should be filled opaquely.
void OnUpdateVSyncParameters(base::TimeTicks timebase, bool FillsBoundsOpaquely() const;
base::TimeDelta interval) override;
bool HasPendingDamageForTesting(const gfx::Rect& damage) const { bool HasPendingDamageForTesting(const gfx::Rect& damage) const {
return pending_damage_.contains(gfx::RectToSkIRect(damage)); return pending_damage_.contains(gfx::RectToSkIRect(damage));
} }
// Overridden from cc::BeginFrameObserverBase:
bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
void OnBeginFrameSourcePausedChanged(bool paused) override {}
private: private:
struct State { struct State {
State(); State();
...@@ -269,14 +257,16 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -269,14 +257,16 @@ class Surface : public ui::ContextFactoryObserver,
// contents of the attached buffer (or id 0, if no buffer is attached). // contents of the attached buffer (or id 0, if no buffer is attached).
// UpdateSurface must be called afterwards to ensure the release callback // UpdateSurface must be called afterwards to ensure the release callback
// will be called. // will be called.
void UpdateResource(bool client_usage); void UpdateResource(LayerTreeFrameSinkHolder* frame_sink_holder,
bool client_usage);
// Updates the current Surface with a new frame referring to the resource in // Puts the current surface into a draw quad, and appends the draw quads into
// current_resource_. // the |frame|.
void UpdateSurface(bool full_damage); void AppendContentsToFrame(const gfx::Point& origin,
FrameType frame_type,
cc::CompositorFrame* frame);
// Adds/Removes begin frame observer based on state. void UpdateContentSize();
void UpdateNeedsBeginFrame();
// This returns true when the surface has some contents assigned to it. // This returns true when the surface has some contents assigned to it.
bool has_contents() const { return !!current_buffer_.buffer(); } bool has_contents() const { return !!current_buffer_.buffer(); }
...@@ -284,10 +274,8 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -284,10 +274,8 @@ class Surface : public ui::ContextFactoryObserver,
// This window has the layer which contains the Surface contents. // This window has the layer which contains the Surface contents.
std::unique_ptr<aura::Window> window_; std::unique_ptr<aura::Window> window_;
// This is true if it's possible that the layer properties (size, opacity, // This true, if sub_surfaces_ has changes (order, position, etc).
// etc.) may have been modified since the last commit. Attaching a new bool sub_surfaces_changed_ = false;
// buffer with the same size as the old shouldn't set this to true.
bool has_pending_layer_changes_ = true;
// This is the size of the last committed contents. // This is the size of the last committed contents.
gfx::Size content_size_; gfx::Size content_size_;
...@@ -302,8 +290,6 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -302,8 +290,6 @@ class Surface : public ui::ContextFactoryObserver,
// The device scale factor sent in CompositorFrames. // The device scale factor sent in CompositorFrames.
float device_scale_factor_ = 1.0f; float device_scale_factor_ = 1.0f;
std::unique_ptr<LayerTreeFrameSinkHolder> layer_tree_frame_sink_holder_;
// The damage region to schedule paint for when Commit() is called. // The damage region to schedule paint for when Commit() is called.
SkRegion pending_damage_; SkRegion pending_damage_;
...@@ -313,8 +299,6 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -313,8 +299,6 @@ class Surface : public ui::ContextFactoryObserver,
// |active_frame_callbacks_| when the effect of the Commit() is scheduled to // |active_frame_callbacks_| when the effect of the Commit() is scheduled to
// be drawn. They fire at the first begin frame notification after this. // be drawn. They fire at the first begin frame notification after this.
std::list<FrameCallback> pending_frame_callbacks_; std::list<FrameCallback> pending_frame_callbacks_;
std::list<FrameCallback> frame_callbacks_;
std::list<FrameCallback> active_frame_callbacks_;
// These lists contains the callbacks to notify the client when surface // These lists contains the callbacks to notify the client when surface
// contents have been presented. These callbacks move to // contents have been presented. These callbacks move to
...@@ -324,9 +308,6 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -324,9 +308,6 @@ class Surface : public ui::ContextFactoryObserver,
// after receiving VSync parameters update for the previous frame. They fire // after receiving VSync parameters update for the previous frame. They fire
// at the next VSync parameters update after that. // at the next VSync parameters update after that.
std::list<PresentationCallback> pending_presentation_callbacks_; std::list<PresentationCallback> pending_presentation_callbacks_;
std::list<PresentationCallback> presentation_callbacks_;
std::list<PresentationCallback> swapping_presentation_callbacks_;
std::list<PresentationCallback> swapped_presentation_callbacks_;
// This is the state that has yet to be committed. // This is the state that has yet to be committed.
State pending_state_; State pending_state_;
...@@ -340,6 +321,7 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -340,6 +321,7 @@ class Surface : public ui::ContextFactoryObserver,
using SubSurfaceEntry = std::pair<Surface*, gfx::Point>; using SubSurfaceEntry = std::pair<Surface*, gfx::Point>;
using SubSurfaceEntryList = std::list<SubSurfaceEntry>; using SubSurfaceEntryList = std::list<SubSurfaceEntry>;
SubSurfaceEntryList pending_sub_surfaces_; SubSurfaceEntryList pending_sub_surfaces_;
SubSurfaceEntryList sub_surfaces_;
// The buffer that is currently set as content of surface. // The buffer that is currently set as content of surface.
BufferAttachment current_buffer_; BufferAttachment current_buffer_;
...@@ -369,11 +351,6 @@ class Surface : public ui::ContextFactoryObserver, ...@@ -369,11 +351,6 @@ class Surface : public ui::ContextFactoryObserver,
// Surface observer list. Surface does not own the observers. // Surface observer list. Surface does not own the observers.
base::ObserverList<SurfaceObserver, true> observers_; base::ObserverList<SurfaceObserver, true> observers_;
// The begin frame source being observed.
cc::BeginFrameSource* begin_frame_source_ = nullptr;
bool needs_begin_frame_ = false;
cc::BeginFrameAck current_begin_frame_ack_;
DISALLOW_COPY_AND_ASSIGN(Surface); DISALLOW_COPY_AND_ASSIGN(Surface);
}; };
......
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/layer_tree_frame_sink.h"
#include "components/exo/layer_tree_frame_sink_holder.h"
#include "components/exo/surface.h" #include "components/exo/surface.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_event_dispatcher.h"
...@@ -73,15 +77,20 @@ SurfaceTreeHost::SurfaceTreeHost(const std::string& window_name, ...@@ -73,15 +77,20 @@ SurfaceTreeHost::SurfaceTreeHost(const std::string& window_name,
host_window_ = base::MakeUnique<aura::Window>(window_delegate); host_window_ = base::MakeUnique<aura::Window>(window_delegate);
host_window_->SetType(aura::client::WINDOW_TYPE_CONTROL); host_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
host_window_->SetName(window_name); host_window_->SetName(window_name);
host_window_->Init(ui::LAYER_NOT_DRAWN); host_window_->Init(ui::LAYER_SOLID_COLOR);
host_window_->set_owned_by_parent(false); host_window_->set_owned_by_parent(false);
host_window_->SetEventTargeter(base::MakeUnique<CustomWindowTargeter>(this)); host_window_->SetEventTargeter(base::MakeUnique<CustomWindowTargeter>(this));
layer_tree_frame_sink_holder_ = base::MakeUnique<LayerTreeFrameSinkHolder>(
this, host_window_->CreateLayerTreeFrameSink());
aura::Env::GetInstance()->context_factory()->AddObserver(this);
} }
SurfaceTreeHost::~SurfaceTreeHost() { SurfaceTreeHost::~SurfaceTreeHost() {
if (root_surface_) { aura::Env::GetInstance()->context_factory()->RemoveObserver(this);
root_surface_->window()->Hide(); SetRootSurface(nullptr);
root_surface_->SetSurfaceDelegate(nullptr); if (host_window_->layer()->GetCompositor()) {
host_window_->layer()->GetCompositor()->vsync_manager()->RemoveObserver(
this);
} }
} }
...@@ -96,6 +105,28 @@ void SurfaceTreeHost::SetRootSurface(Surface* root_surface) { ...@@ -96,6 +105,28 @@ void SurfaceTreeHost::SetRootSurface(Surface* root_surface) {
gfx::Rect(host_window_->bounds().origin(), gfx::Size())); gfx::Rect(host_window_->bounds().origin(), gfx::Size()));
root_surface_->SetSurfaceDelegate(nullptr); root_surface_->SetSurfaceDelegate(nullptr);
root_surface_ = nullptr; root_surface_ = nullptr;
active_frame_callbacks_.splice(active_frame_callbacks_.end(),
frame_callbacks_);
// Call all frame callbacks with a null frame time to indicate that they
// have been cancelled.
while (!active_frame_callbacks_.empty()) {
active_frame_callbacks_.front().Run(base::TimeTicks());
active_frame_callbacks_.pop_front();
}
swapping_presentation_callbacks_.splice(
swapping_presentation_callbacks_.end(), presentation_callbacks_);
swapped_presentation_callbacks_.splice(
swapped_presentation_callbacks_.end(),
swapping_presentation_callbacks_);
// Call all presentation callbacks with a null presentation time to indicate
// that they have been cancelled.
while (!swapped_presentation_callbacks_.empty()) {
swapped_presentation_callbacks_.front().Run(base::TimeTicks(),
base::TimeDelta());
swapped_presentation_callbacks_.pop_front();
}
} }
if (root_surface) { if (root_surface) {
...@@ -125,14 +156,43 @@ gfx::NativeCursor SurfaceTreeHost::GetCursor(const gfx::Point& point) const { ...@@ -125,14 +156,43 @@ gfx::NativeCursor SurfaceTreeHost::GetCursor(const gfx::Point& point) const {
return root_surface_ ? root_surface_->GetCursor() : ui::CursorType::kNull; return root_surface_ ? root_surface_->GetCursor() : ui::CursorType::kNull;
} }
void SurfaceTreeHost::DidReceiveCompositorFrameAck() {
active_frame_callbacks_.splice(active_frame_callbacks_.end(),
frame_callbacks_);
swapping_presentation_callbacks_.splice(
swapping_presentation_callbacks_.end(), presentation_callbacks_);
UpdateNeedsBeginFrame();
}
void SurfaceTreeHost::SetBeginFrameSource(
cc::BeginFrameSource* begin_frame_source) {
if (needs_begin_frame_) {
DCHECK(begin_frame_source_);
begin_frame_source_->RemoveObserver(this);
needs_begin_frame_ = false;
}
begin_frame_source_ = begin_frame_source;
UpdateNeedsBeginFrame();
}
void SurfaceTreeHost::UpdateNeedsBeginFrame() {
if (!begin_frame_source_)
return;
bool needs_begin_frame = !active_frame_callbacks_.empty();
if (needs_begin_frame == needs_begin_frame_)
return;
needs_begin_frame_ = needs_begin_frame;
if (needs_begin_frame_)
begin_frame_source_->AddObserver(this);
else
begin_frame_source_->RemoveObserver(this);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SurfaceDelegate overrides: // SurfaceDelegate overrides:
void SurfaceTreeHost::OnSurfaceCommit() { void SurfaceTreeHost::OnSurfaceCommit() {
DCHECK(root_surface_); SubmitCompositorFrame(Surface::FRAME_TYPE_COMMIT);
root_surface_->CommitSurfaceHierarchy();
host_window_->SetBounds(gfx::Rect(host_window_->bounds().origin(),
root_surface_->content_size()));
} }
bool SurfaceTreeHost::IsSurfaceSynchronized() const { bool SurfaceTreeHost::IsSurfaceSynchronized() const {
...@@ -141,4 +201,111 @@ bool SurfaceTreeHost::IsSurfaceSynchronized() const { ...@@ -141,4 +201,111 @@ bool SurfaceTreeHost::IsSurfaceSynchronized() const {
return false; return false;
} }
////////////////////////////////////////////////////////////////////////////////
// aura::WindowObserver overrides:
void SurfaceTreeHost::OnWindowAddedToRootWindow(aura::Window* window) {
DCHECK_EQ(window, host_window());
window->layer()->GetCompositor()->vsync_manager()->AddObserver(this);
}
void SurfaceTreeHost::OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) {
DCHECK_EQ(window, host_window());
window->layer()->GetCompositor()->vsync_manager()->RemoveObserver(this);
}
void SurfaceTreeHost::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(window, host_window());
window->RemoveObserver(this);
}
////////////////////////////////////////////////////////////////////////////////
// cc::BeginFrameObserverBase overrides:
bool SurfaceTreeHost::OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) {
current_begin_frame_ack_ =
cc::BeginFrameAck(args.source_id, args.sequence_number, false);
while (!active_frame_callbacks_.empty()) {
active_frame_callbacks_.front().Run(args.frame_time);
active_frame_callbacks_.pop_front();
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// ui::CompositorVSyncManager::Observer overrides:
void SurfaceTreeHost::OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) {
// Use current time if platform doesn't provide an accurate timebase.
if (timebase.is_null())
timebase = base::TimeTicks::Now();
while (!swapped_presentation_callbacks_.empty()) {
swapped_presentation_callbacks_.front().Run(timebase, interval);
swapped_presentation_callbacks_.pop_front();
}
// VSync parameters updates are generated at the start of a new swap. Move
// the swapping presentation callbacks to swapped callbacks so they fire
// at the next VSync parameters update as that will contain the presentation
// time for the previous frame.
swapped_presentation_callbacks_.splice(swapped_presentation_callbacks_.end(),
swapping_presentation_callbacks_);
}
////////////////////////////////////////////////////////////////////////////////
// ui::ContextFactoryObserver overrides:
void SurfaceTreeHost::OnLostResources() {
if (!host_window_->GetSurfaceId().is_valid())
return;
root_surface_->RecreateResources(layer_tree_frame_sink_holder_.get());
SubmitCompositorFrame(Surface::FRAME_TYPE_RECREATED_RESOURCES);
}
void SurfaceTreeHost::SubmitCompositorFrame(Surface::FrameType frame_type) {
DCHECK(root_surface_);
cc::CompositorFrame frame;
// If we commit while we don't have an active BeginFrame, we acknowledge a
// manual one.
if (current_begin_frame_ack_.sequence_number ==
cc::BeginFrameArgs::kInvalidFrameNumber) {
current_begin_frame_ack_ = cc::BeginFrameAck::CreateManualAckWithDamage();
} else {
current_begin_frame_ack_.has_damage = true;
}
frame.metadata.begin_frame_ack = current_begin_frame_ack_;
frame.metadata.device_scale_factor =
host_window_->layer()->device_scale_factor();
const int kRenderPassId = 1;
std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
render_pass->SetNew(kRenderPassId, gfx::Rect(), gfx::Rect(),
gfx::Transform());
frame.render_pass_list.push_back(std::move(render_pass));
root_surface_->CommitSurfaceHierarchy(
gfx::Point(), frame_type, layer_tree_frame_sink_holder_.get(), &frame,
&frame_callbacks_, &presentation_callbacks_);
frame.render_pass_list.back()->output_rect =
gfx::Rect(root_surface_->content_size());
layer_tree_frame_sink_holder_->frame_sink()->SubmitCompositorFrame(
std::move(frame));
host_window_->SetBounds(gfx::Rect(host_window_->bounds().origin(),
root_surface_->content_size()));
host_window_->layer()->SetFillsBoundsOpaquely(
root_surface_->FillsBoundsOpaquely());
if (current_begin_frame_ack_.sequence_number !=
cc::BeginFrameArgs::kInvalidFrameNumber) {
if (!current_begin_frame_ack_.has_damage) {
layer_tree_frame_sink_holder_->frame_sink()->DidNotProduceFrame(
current_begin_frame_ack_);
}
current_begin_frame_ack_.sequence_number =
cc::BeginFrameArgs::kInvalidFrameNumber;
if (begin_frame_source_)
begin_frame_source_->DidFinishFrame(this);
}
}
} // namespace exo } // namespace exo
...@@ -8,8 +8,12 @@ ...@@ -8,8 +8,12 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "cc/scheduler/begin_frame_source.h"
#include "components/exo/layer_tree_frame_sink_holder.h"
#include "components/exo/surface.h" #include "components/exo/surface.h"
#include "components/exo/surface_delegate.h" #include "components/exo/surface_delegate.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
namespace aura { namespace aura {
...@@ -17,15 +21,24 @@ class Window; ...@@ -17,15 +21,24 @@ class Window;
class WindowDelegate; class WindowDelegate;
} // namespace aura } // namespace aura
namespace cc {
class BeginFrameSource;
} // namespace cc
namespace gfx { namespace gfx {
class Path; class Path;
} // namespace gfx } // namespace gfx
namespace exo { namespace exo {
class LayerTreeFrameSinkHolder;
// This class provides functionality for hosting a surface tree. The surface // This class provides functionality for hosting a surface tree. The surface
// tree is hosted in the |host_window_|. // tree is hosted in the |host_window_|.
class SurfaceTreeHost : public SurfaceDelegate { class SurfaceTreeHost : public SurfaceDelegate,
public aura::WindowObserver,
public cc::BeginFrameObserverBase,
public ui::CompositorVSyncManager::Observer,
public ui::ContextFactoryObserver {
public: public:
SurfaceTreeHost(const std::string& window_name, SurfaceTreeHost(const std::string& window_name,
aura::WindowDelegate* window_delegate); aura::WindowDelegate* window_delegate);
...@@ -48,19 +61,77 @@ class SurfaceTreeHost : public SurfaceDelegate { ...@@ -48,19 +61,77 @@ class SurfaceTreeHost : public SurfaceDelegate {
// registered then CursorType::kNull is returned. // registered then CursorType::kNull is returned.
gfx::NativeCursor GetCursor(const gfx::Point& point) const; gfx::NativeCursor GetCursor(const gfx::Point& point) const;
// Call this to indicate that the previous CompositorFrame is processed and
// the surface is being scheduled for a draw.
void DidReceiveCompositorFrameAck();
// Called when the begin frame source has changed.
void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
// Adds/Removes begin frame observer based on state.
void UpdateNeedsBeginFrame();
aura::Window* host_window() { return host_window_.get(); } aura::Window* host_window() { return host_window_.get(); }
const aura::Window* host_window() const { return host_window_.get(); } const aura::Window* host_window() const { return host_window_.get(); }
Surface* root_surface() { return root_surface_; } Surface* root_surface() { return root_surface_; }
const Surface* root_surface() const { return root_surface_; } const Surface* root_surface() const { return root_surface_; }
LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder() {
return layer_tree_frame_sink_holder_.get();
}
// Overridden from SurfaceDelegate: // Overridden from SurfaceDelegate:
void OnSurfaceCommit() override; void OnSurfaceCommit() override;
bool IsSurfaceSynchronized() const override; bool IsSurfaceSynchronized() const override;
// Overridden from aura::WindowObserver:
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
void OnWindowDestroying(aura::Window* window) override;
// Overridden from cc::BeginFrameObserverBase:
bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
void OnBeginFrameSourcePausedChanged(bool paused) override {}
// Overridden from ui::CompositorVSyncManager::Observer:
void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) override;
// Overridden from ui::ContextFactoryObserver:
void OnLostResources() override;
private: private:
void SubmitCompositorFrame(Surface::FrameType frame_type);
Surface* root_surface_ = nullptr; Surface* root_surface_ = nullptr;
std::unique_ptr<aura::Window> host_window_; std::unique_ptr<aura::Window> host_window_;
std::unique_ptr<LayerTreeFrameSinkHolder> layer_tree_frame_sink_holder_;
// The begin frame source being observed.
cc::BeginFrameSource* begin_frame_source_ = nullptr;
bool needs_begin_frame_ = false;
cc::BeginFrameAck current_begin_frame_ack_;
// These lists contain the callbacks to notify the client when it is a good
// time to start producing a new frame. These callbacks move to
// |frame_callbacks_| when Commit() is called. Later they are moved to
// |active_frame_callbacks_| when the effect of the Commit() is scheduled to
// be drawn. They fire at the first begin frame notification after this.
std::list<Surface::FrameCallback> frame_callbacks_;
std::list<Surface::FrameCallback> active_frame_callbacks_;
// These lists contains the callbacks to notify the client when surface
// contents have been presented. These callbacks move to
// |presentation_callbacks_| when Commit() is called. Later they are moved to
// |swapping_presentation_callbacks_| when the effect of the Commit() is
// scheduled to be drawn and then moved to |swapped_presentation_callbacks_|
// after receiving VSync parameters update for the previous frame. They fire
// at the next VSync parameters update after that.
std::list<Surface::PresentationCallback> presentation_callbacks_;
std::list<Surface::PresentationCallback> swapping_presentation_callbacks_;
std::list<Surface::PresentationCallback> swapped_presentation_callbacks_;
DISALLOW_COPY_AND_ASSIGN(SurfaceTreeHost); DISALLOW_COPY_AND_ASSIGN(SurfaceTreeHost);
}; };
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment