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
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/containers/adapters.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
...@@ -27,7 +28,6 @@ ...@@ -27,7 +28,6 @@
#include "components/viz/common/surfaces/sequence_surface_reference_factory.h" #include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
#include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/aura/env.h"
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/aura/window_targeter.h" #include "ui/aura/window_targeter.h"
#include "ui/base/class_property.h" #include "ui/base/class_property.h"
...@@ -189,42 +189,23 @@ Surface::Surface() : window_(new aura::Window(new CustomWindowDelegate(this))) { ...@@ -189,42 +189,23 @@ Surface::Surface() : window_(new aura::Window(new CustomWindowDelegate(this))) {
window_->SetType(aura::client::WINDOW_TYPE_CONTROL); window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
window_->SetName("ExoSurface"); window_->SetName("ExoSurface");
window_->SetProperty(kSurfaceKey, this); window_->SetProperty(kSurfaceKey, this);
window_->Init(ui::LAYER_SOLID_COLOR); window_->Init(ui::LAYER_NOT_DRAWN);
window_->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter)); window_->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter));
window_->set_owned_by_parent(false); window_->set_owned_by_parent(false);
window_->AddObserver(this);
aura::Env::GetInstance()->context_factory()->AddObserver(this);
layer_tree_frame_sink_holder_ = base::MakeUnique<LayerTreeFrameSinkHolder>(
this, window_->CreateLayerTreeFrameSink());
} }
Surface::~Surface() { Surface::~Surface() {
aura::Env::GetInstance()->context_factory()->RemoveObserver(this);
for (SurfaceObserver& observer : observers_) for (SurfaceObserver& observer : observers_)
observer.OnSurfaceDestroying(this); observer.OnSurfaceDestroying(this);
window_->RemoveObserver(this);
if (window_->layer()->GetCompositor())
window_->layer()->GetCompositor()->vsync_manager()->RemoveObserver(this);
window_->layer()->SetShowSolidColorContent();
frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_);
active_frame_callbacks_.splice(active_frame_callbacks_.end(),
frame_callbacks_);
// Call all frame callbacks with a null frame time to indicate that they // Call all frame callbacks with a null frame time to indicate that they
// have been cancelled. // have been cancelled.
for (const auto& frame_callback : active_frame_callbacks_) for (const auto& frame_callback : pending_frame_callbacks_)
frame_callback.Run(base::TimeTicks()); frame_callback.Run(base::TimeTicks());
presentation_callbacks_.splice(presentation_callbacks_.end(),
pending_presentation_callbacks_);
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 // Call all presentation callbacks with a null presentation time to indicate
// that they have been cancelled. // that they have been cancelled.
for (const auto& presentation_callback : swapped_presentation_callbacks_) for (const auto& presentation_callback : pending_presentation_callbacks_)
presentation_callback.Run(base::TimeTicks(), base::TimeDelta()); presentation_callback.Run(base::TimeTicks(), base::TimeDelta());
} }
...@@ -233,10 +214,6 @@ Surface* Surface::AsSurface(const aura::Window* window) { ...@@ -233,10 +214,6 @@ Surface* Surface::AsSurface(const aura::Window* window) {
return window->GetProperty(kSurfaceKey); return window->GetProperty(kSurfaceKey);
} }
viz::SurfaceId Surface::GetSurfaceId() const {
return window_->GetSurfaceId();
}
void Surface::Attach(Buffer* buffer) { void Surface::Attach(Buffer* buffer) {
TRACE_EVENT1("exo", "Surface::Attach", "buffer", TRACE_EVENT1("exo", "Surface::Attach", "buffer",
buffer ? buffer->GetSize().ToString() : "null"); buffer ? buffer->GetSize().ToString() : "null");
...@@ -290,11 +267,13 @@ void Surface::AddSubSurface(Surface* sub_surface) { ...@@ -290,11 +267,13 @@ void Surface::AddSubSurface(Surface* sub_surface) {
DCHECK(!sub_surface->window()->parent()); DCHECK(!sub_surface->window()->parent());
DCHECK(!sub_surface->window()->IsVisible()); DCHECK(!sub_surface->window()->IsVisible());
sub_surface->window()->SetBounds(
gfx::Rect(sub_surface->window()->bounds().size()));
window_->AddChild(sub_surface->window()); window_->AddChild(sub_surface->window());
DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface)); DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface));
pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point())); pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
has_pending_layer_changes_ = true; sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
} }
void Surface::RemoveSubSurface(Surface* sub_surface) { void Surface::RemoveSubSurface(Surface* sub_surface) {
...@@ -308,7 +287,8 @@ void Surface::RemoveSubSurface(Surface* sub_surface) { ...@@ -308,7 +287,8 @@ void Surface::RemoveSubSurface(Surface* sub_surface) {
DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
pending_sub_surfaces_.erase( pending_sub_surfaces_.erase(
FindListEntry(pending_sub_surfaces_, sub_surface)); FindListEntry(pending_sub_surfaces_, sub_surface));
has_pending_layer_changes_ = true; DCHECK(ListContainsEntry(sub_surfaces_, sub_surface));
sub_surfaces_.erase(FindListEntry(sub_surfaces_, sub_surface));
} }
void Surface::SetSubSurfacePosition(Surface* sub_surface, void Surface::SetSubSurfacePosition(Surface* sub_surface,
...@@ -321,7 +301,7 @@ void Surface::SetSubSurfacePosition(Surface* sub_surface, ...@@ -321,7 +301,7 @@ void Surface::SetSubSurfacePosition(Surface* sub_surface,
if (it->second == position) if (it->second == position)
return; return;
it->second = position; it->second = position;
has_pending_layer_changes_ = true; sub_surfaces_changed_ = true;
} }
void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) { void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
...@@ -353,7 +333,7 @@ void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) { ...@@ -353,7 +333,7 @@ void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
if (it == position_it) if (it == position_it)
return; return;
pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it); pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it);
has_pending_layer_changes_ = true; sub_surfaces_changed_ = true;
} }
void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) { void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
...@@ -378,7 +358,7 @@ void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) { ...@@ -378,7 +358,7 @@ void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
if (it == sibling_it) if (it == sibling_it)
return; return;
pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it); pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it);
has_pending_layer_changes_ = true; sub_surfaces_changed_ = true;
} }
void Surface::SetViewport(const gfx::Size& viewport) { void Surface::SetViewport(const gfx::Size& viewport) {
...@@ -421,46 +401,21 @@ void Surface::Commit() { ...@@ -421,46 +401,21 @@ void Surface::Commit() {
TRACE_EVENT0("exo", "Surface::Commit"); TRACE_EVENT0("exo", "Surface::Commit");
needs_commit_surface_hierarchy_ = true; needs_commit_surface_hierarchy_ = true;
if (delegate_)
if (state_ != pending_state_)
has_pending_layer_changes_ = true;
if (has_pending_contents_) {
if (pending_buffer_.buffer()) {
if (current_resource_.size != pending_buffer_.buffer()->GetSize())
has_pending_layer_changes_ = true;
// Whether layer fills bounds opaquely or not might have changed.
if (current_resource_has_alpha_ !=
FormatHasAlpha(pending_buffer_.buffer()->GetFormat()))
has_pending_layer_changes_ = true;
} else if (!current_resource_.size.IsEmpty()) {
has_pending_layer_changes_ = true;
}
}
if (delegate_) {
delegate_->OnSurfaceCommit(); delegate_->OnSurfaceCommit();
} else {
CommitSurfaceHierarchy();
}
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);
}
} }
void Surface::CommitSurfaceHierarchy() { void Surface::CommitSurfaceHierarchy(
DCHECK(needs_commit_surface_hierarchy_); const gfx::Point& origin,
FrameType frame_type,
LayerTreeFrameSinkHolder* frame_sink_holder,
cc::CompositorFrame* frame,
std::list<FrameCallback>* frame_callbacks,
std::list<PresentationCallback>* presentation_callbacks) {
bool needs_commit =
frame_type == FRAME_TYPE_COMMIT && needs_commit_surface_hierarchy_;
if (needs_commit) {
needs_commit_surface_hierarchy_ = false; needs_commit_surface_hierarchy_ = false;
has_pending_layer_changes_ = false;
state_ = pending_state_; state_ = pending_state_;
pending_state_.only_visible_on_secure_output = false; pending_state_.only_visible_on_secure_output = false;
...@@ -471,47 +426,27 @@ void Surface::CommitSurfaceHierarchy() { ...@@ -471,47 +426,27 @@ void Surface::CommitSurfaceHierarchy() {
current_buffer_ = std::move(pending_buffer_); current_buffer_ = std::move(pending_buffer_);
UpdateResource(true); UpdateResource(frame_sink_holder, true);
} }
// Move pending frame callbacks to the end of frame_callbacks_. // Move pending frame callbacks to the end of frame_callbacks.
frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); frame_callbacks->splice(frame_callbacks->end(), pending_frame_callbacks_);
// Move pending presentation callbacks to the end of presentation_callbacks_. // Move pending presentation callbacks to the end of presentation_callbacks.
presentation_callbacks_.splice(presentation_callbacks_.end(), presentation_callbacks->splice(presentation_callbacks->end(),
pending_presentation_callbacks_); pending_presentation_callbacks_);
UpdateSurface(false); UpdateContentSize();
window_->layer()->SetFillsBoundsOpaquely(
!current_resource_has_alpha_ || state_.blend_mode == SkBlendMode::kSrc ||
state_.opaque_region.contains(
gfx::RectToSkIRect(gfx::Rect(content_size_))));
// Reset damage.
pending_damage_.setEmpty();
DCHECK(!current_resource_.id ||
layer_tree_frame_sink_holder_->HasReleaseCallbackForResource(
current_resource_.id));
// Synchronize window hierarchy. This will position and update the stacking // Synchronize window hierarchy. This will position and update the stacking
// order of all sub-surfaces after committing all pending state of sub-surface // order of all sub-surfaces after committing all pending state of
// descendants. // sub-surface descendants.
if (sub_surfaces_changed_) {
sub_surfaces_.clear();
aura::Window* stacking_target = nullptr; aura::Window* stacking_target = nullptr;
for (auto& sub_surface_entry : pending_sub_surfaces_) { for (const auto& sub_surface_entry : pending_sub_surfaces_) {
Surface* sub_surface = sub_surface_entry.first; Surface* sub_surface = sub_surface_entry.first;
sub_surfaces_.push_back(sub_surface_entry);
// Synchronsouly commit all pending state of the sub-surface and its
// decendents.
if (sub_surface->needs_commit_surface_hierarchy())
sub_surface->CommitSurfaceHierarchy();
// Enable/disable sub-surface based on if it has contents.
if (sub_surface->has_contents())
sub_surface->window()->Show();
else
sub_surface->window()->Hide();
// Move sub-surface to its new position in the stack. // Move sub-surface to its new position in the stack.
if (stacking_target) if (stacking_target)
window_->StackChildAbove(sub_surface->window(), stacking_target); window_->StackChildAbove(sub_surface->window(), stacking_target);
...@@ -520,9 +455,33 @@ void Surface::CommitSurfaceHierarchy() { ...@@ -520,9 +455,33 @@ void Surface::CommitSurfaceHierarchy() {
stacking_target = sub_surface->window(); stacking_target = sub_surface->window();
// Update sub-surface position relative to surface origin. // Update sub-surface position relative to surface origin.
sub_surface->window()->SetBounds( sub_surface->window()->SetBounds(gfx::Rect(
gfx::Rect(sub_surface_entry.second, sub_surface->content_size_)); sub_surface_entry.second, sub_surface->window()->bounds().size()));
} }
sub_surfaces_changed_ = false;
}
}
// The top most sub-surface is at the front of the RenderPass's quad_list,
// so we need composite sub-surface in reversed order.
for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
auto* sub_surface = sub_surface_entry.first;
// Synchronsouly commit all pending state of the sub-surface and its
// decendents.
sub_surface->CommitSurfaceHierarchy(
origin + sub_surface_entry.second.OffsetFromOrigin(), frame_type,
frame_sink_holder, frame, frame_callbacks, presentation_callbacks);
}
AppendContentsToFrame(origin, frame_type, frame);
// Reset damage.
if (needs_commit)
pending_damage_.setEmpty();
DCHECK(
!current_resource_.id ||
frame_sink_holder->HasReleaseCallbackForResource(current_resource_.id));
} }
bool Surface::IsSynchronized() const { bool Surface::IsSynchronized() const {
...@@ -599,49 +558,6 @@ std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { ...@@ -599,49 +558,6 @@ std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const {
return value; return value;
} }
void Surface::DidReceiveCompositorFrameAck() {
active_frame_callbacks_.splice(active_frame_callbacks_.end(),
frame_callbacks_);
swapping_presentation_callbacks_.splice(
swapping_presentation_callbacks_.end(), presentation_callbacks_);
UpdateNeedsBeginFrame();
}
void Surface::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 Surface::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);
}
bool Surface::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;
}
bool Surface::IsStylusOnly() { bool Surface::IsStylusOnly() {
return window_->GetProperty(kStylusOnlyKey); return window_->GetProperty(kStylusOnlyKey);
} }
...@@ -650,48 +566,17 @@ void Surface::SetStylusOnly() { ...@@ -650,48 +566,17 @@ void Surface::SetStylusOnly() {
window_->SetProperty(kStylusOnlyKey, true); window_->SetProperty(kStylusOnlyKey, true);
} }
//////////////////////////////////////////////////////////////////////////////// void Surface::RecreateResources(LayerTreeFrameSinkHolder* frame_sink_holder) {
// ui::ContextFactoryObserver overrides: UpdateResource(frame_sink_holder, false);
for (const auto& sub_surface : sub_surfaces_)
void Surface::OnLostResources() { sub_surface.first->RecreateResources(frame_sink_holder);
if (!window_->GetSurfaceId().is_valid())
return;
UpdateResource(false);
UpdateSurface(true);
}
////////////////////////////////////////////////////////////////////////////////
// aura::WindowObserver overrides:
void Surface::OnWindowAddedToRootWindow(aura::Window* window) {
window->layer()->GetCompositor()->vsync_manager()->AddObserver(this);
}
void Surface::OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) {
window->layer()->GetCompositor()->vsync_manager()->RemoveObserver(this);
} }
//////////////////////////////////////////////////////////////////////////////// bool Surface::FillsBoundsOpaquely() const {
// ui::CompositorVSyncManager::Observer overrides: return !current_resource_has_alpha_ ||
state_.blend_mode == SkBlendMode::kSrc ||
void Surface::OnUpdateVSyncParameters(base::TimeTicks timebase, state_.opaque_region.contains(
base::TimeDelta interval) { gfx::RectToSkIRect(gfx::Rect(content_size_)));
// 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_);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -741,12 +626,11 @@ void Surface::BufferAttachment::Reset(base::WeakPtr<Buffer> buffer) { ...@@ -741,12 +626,11 @@ void Surface::BufferAttachment::Reset(base::WeakPtr<Buffer> buffer) {
buffer_ = buffer; buffer_ = buffer;
} }
void Surface::UpdateResource(bool client_usage) { void Surface::UpdateResource(LayerTreeFrameSinkHolder* frame_sink_holder,
bool client_usage) {
if (current_buffer_.buffer() && if (current_buffer_.buffer() &&
current_buffer_.buffer()->ProduceTransferableResource( current_buffer_.buffer()->ProduceTransferableResource(
layer_tree_frame_sink_holder_.get(), frame_sink_holder, state_.only_visible_on_secure_output, client_usage,
layer_tree_frame_sink_holder_->AllocateResourceId(),
state_.only_visible_on_secure_output, client_usage,
&current_resource_)) { &current_resource_)) {
current_resource_has_alpha_ = current_resource_has_alpha_ =
FormatHasAlpha(current_buffer_.buffer()->GetFormat()); FormatHasAlpha(current_buffer_.buffer()->GetFormat());
...@@ -757,36 +641,39 @@ void Surface::UpdateResource(bool client_usage) { ...@@ -757,36 +641,39 @@ void Surface::UpdateResource(bool client_usage) {
} }
} }
void Surface::UpdateSurface(bool full_damage) { void Surface::AppendContentsToFrame(const gfx::Point& origin,
gfx::Size buffer_size = current_resource_.size; FrameType frame_type,
gfx::SizeF scaled_buffer_size( cc::CompositorFrame* frame) {
gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale)); const std::unique_ptr<cc::RenderPass>& render_pass =
frame->render_pass_list.back();
gfx::Size layer_size; // Size of the output layer, in DIP. gfx::Rect output_rect = gfx::Rect(origin, content_size_);
if (!state_.viewport.IsEmpty()) { gfx::Rect quad_rect = output_rect;
layer_size = state_.viewport; gfx::Rect damage_rect;
} else if (!state_.crop.IsEmpty()) { switch (frame_type) {
DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) || case FRAME_TYPE_COMMIT:
!gfx::IsExpressibleAsInt(state_.crop.height())) // pending_damage_ is in Surface coordinates.
<< "Crop rectangle size (" << state_.crop.size().ToString() damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
<< ") most be expressible using integers when viewport is not set"; damage_rect.set_origin(origin);
layer_size = gfx::ToCeiledSize(state_.crop.size()); damage_rect.Intersect(output_rect);
} else { break;
layer_size = gfx::ToCeiledSize(scaled_buffer_size); case FRAME_TYPE_RECREATED_RESOURCES:
damage_rect = output_rect;
break;
} }
content_size_ = layer_size; render_pass->damage_rect.Union(damage_rect);
// We need update window_'s bounds with content size, because the cc::SharedQuadState* quad_state =
// LayerTreeFrameSink may not update the window's size base the size of render_pass->CreateAndAppendSharedQuadState();
// the lastest submitted CompositorFrame. quad_state->quad_layer_rect = gfx::Rect(content_size_);
window_->SetBounds(gfx::Rect(window_->bounds().origin(), content_size_)); quad_state->visible_quad_layer_rect = quad_rect;
// TODO(jbauman): Figure out how this interacts with the pixel size of quad_state->opacity = state_.alpha;
// CopyOutputRequests on the layer.
gfx::Size contents_surface_size = layer_size;
if (current_resource_.id) {
gfx::PointF uv_top_left(0.f, 0.f); gfx::PointF uv_top_left(0.f, 0.f);
gfx::PointF uv_bottom_right(1.f, 1.f); gfx::PointF uv_bottom_right(1.f, 1.f);
if (!state_.crop.IsEmpty()) { if (!state_.crop.IsEmpty()) {
gfx::SizeF scaled_buffer_size(gfx::ScaleSize(
gfx::SizeF(current_resource_.size), 1.0f / state_.buffer_scale));
uv_top_left = state_.crop.origin(); uv_top_left = state_.crop.origin();
uv_top_left.Scale(1.f / scaled_buffer_size.width(), uv_top_left.Scale(1.f / scaled_buffer_size.width(),
...@@ -795,42 +682,6 @@ void Surface::UpdateSurface(bool full_damage) { ...@@ -795,42 +682,6 @@ void Surface::UpdateSurface(bool full_damage) {
uv_bottom_right.Scale(1.f / scaled_buffer_size.width(), uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
1.f / scaled_buffer_size.height()); 1.f / scaled_buffer_size.height());
} }
gfx::Rect damage_rect;
gfx::Rect output_rect = gfx::Rect(contents_surface_size);
if (full_damage) {
damage_rect = output_rect;
} else {
// pending_damage_ is in Surface coordinates.
damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
damage_rect.Intersect(output_rect);
}
const int kRenderPassId = 1;
std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
render_pass->SetNew(kRenderPassId, output_rect, damage_rect,
gfx::Transform());
gfx::Rect quad_rect = output_rect;
cc::SharedQuadState* quad_state =
render_pass->CreateAndAppendSharedQuadState();
quad_state->quad_layer_rect = gfx::Rect(contents_surface_size);
quad_state->visible_quad_layer_rect = quad_rect;
quad_state->opacity = state_.alpha;
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 = device_scale_factor_;
if (current_resource_.id) {
// Texture quad is only needed if buffer is not fully transparent. // Texture quad is only needed if buffer is not fully transparent.
if (state_.alpha) { if (state_.alpha) {
cc::TextureDrawQuad* texture_quad = cc::TextureDrawQuad* texture_quad =
...@@ -845,23 +696,46 @@ void Surface::UpdateSurface(bool full_damage) { ...@@ -845,23 +696,46 @@ void Surface::UpdateSurface(bool full_damage) {
opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds()); opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds());
} }
texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect, texture_quad->SetNew(
current_resource_.id, true, uv_top_left, quad_state, quad_rect, opaque_rect, quad_rect, current_resource_.id,
uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity, true /* premultiplied_alpha */, uv_top_left, uv_bottom_right,
false, false, state_.only_visible_on_secure_output); SK_ColorTRANSPARENT /* background_color */, vertex_opacity,
false /* y_flipped */, false /* nearest_neighbor */,
state_.only_visible_on_secure_output);
if (current_resource_.is_overlay_candidate) if (current_resource_.is_overlay_candidate)
texture_quad->set_resource_size_in_pixels(current_resource_.size); texture_quad->set_resource_size_in_pixels(current_resource_.size);
frame.resource_list.push_back(current_resource_); frame->resource_list.push_back(current_resource_);
} }
} else { } else {
cc::SolidColorDrawQuad* solid_quad = cc::SolidColorDrawQuad* solid_quad =
render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>(); render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false); solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK,
false /* force_anti_aliasing_off */);
} }
}
void Surface::UpdateContentSize() {
gfx::Size buffer_size = current_resource_.size;
gfx::SizeF scaled_buffer_size(
gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
if (!state_.viewport.IsEmpty()) {
content_size_ = state_.viewport;
} else if (!state_.crop.IsEmpty()) {
DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
!gfx::IsExpressibleAsInt(state_.crop.height()))
<< "Crop rectangle size (" << state_.crop.size().ToString()
<< ") most be expressible using integers when viewport is not set";
content_size_ = gfx::ToCeiledSize(state_.crop.size());
} else {
content_size_ = gfx::ToCeiledSize(scaled_buffer_size);
}
window_->SetBounds(gfx::Rect(window_->bounds().origin(), content_size_));
frame.render_pass_list.push_back(std::move(render_pass)); // Enable/disable sub-surface based on if it has contents.
layer_tree_frame_sink_holder_->frame_sink()->SubmitCompositorFrame( if (has_contents())
std::move(frame)); window_->Show();
else
window_->Hide();
} }
} // namespace exo } // namespace exo
...@@ -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);
}; };
......
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
#include "cc/test/begin_frame_args_test.h" #include "cc/test/begin_frame_args_test.h"
#include "cc/test/fake_external_begin_frame_source.h" #include "cc/test/fake_external_begin_frame_source.h"
#include "components/exo/buffer.h" #include "components/exo/buffer.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"
#include "components/viz/service/frame_sinks/frame_sink_manager.h" #include "components/viz/service/frame_sinks/frame_sink_manager.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/compositor/layer_tree_owner.h" #include "ui/compositor/layer_tree_owner.h"
#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/gpu_memory_buffer.h"
...@@ -99,8 +101,8 @@ TEST_F(SurfaceTest, RequestFrameCallback) { ...@@ -99,8 +101,8 @@ TEST_F(SurfaceTest, RequestFrameCallback) {
EXPECT_TRUE(frame_time.is_null()); EXPECT_TRUE(frame_time.is_null());
} }
const cc::CompositorFrame& GetFrameFromSurface(Surface* surface) { const cc::CompositorFrame& GetFrameFromSurface(ShellSurface* shell_surface) {
viz::SurfaceId surface_id = surface->GetSurfaceId(); viz::SurfaceId surface_id = shell_surface->host_window()->GetSurfaceId();
cc::SurfaceManager* surface_manager = aura::Env::GetInstance() cc::SurfaceManager* surface_manager = aura::Env::GetInstance()
->context_factory_private() ->context_factory_private()
->GetFrameSinkManager() ->GetFrameSinkManager()
...@@ -112,9 +114,10 @@ const cc::CompositorFrame& GetFrameFromSurface(Surface* surface) { ...@@ -112,9 +114,10 @@ const cc::CompositorFrame& GetFrameFromSurface(Surface* surface) {
TEST_F(SurfaceTest, SetOpaqueRegion) { TEST_F(SurfaceTest, SetOpaqueRegion) {
gfx::Size buffer_size(1, 1); gfx::Size buffer_size(1, 1);
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 = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
// Attaching a buffer with alpha channel. // Attaching a buffer with alpha channel.
surface->Attach(buffer.get()); surface->Attach(buffer.get());
...@@ -126,7 +129,7 @@ TEST_F(SurfaceTest, SetOpaqueRegion) { ...@@ -126,7 +129,7 @@ TEST_F(SurfaceTest, SetOpaqueRegion) {
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
{ {
const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get()); const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.size());
ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
EXPECT_FALSE(frame.render_pass_list.back() EXPECT_FALSE(frame.render_pass_list.back()
...@@ -140,7 +143,7 @@ TEST_F(SurfaceTest, SetOpaqueRegion) { ...@@ -140,7 +143,7 @@ TEST_F(SurfaceTest, SetOpaqueRegion) {
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
{ {
const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get()); const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.size());
ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
EXPECT_TRUE(frame.render_pass_list.back() EXPECT_TRUE(frame.render_pass_list.back()
...@@ -159,7 +162,7 @@ TEST_F(SurfaceTest, SetOpaqueRegion) { ...@@ -159,7 +162,7 @@ TEST_F(SurfaceTest, SetOpaqueRegion) {
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
{ {
const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get()); const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.size());
ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
EXPECT_FALSE(frame.render_pass_list.back() EXPECT_FALSE(frame.render_pass_list.back()
...@@ -180,9 +183,10 @@ TEST_F(SurfaceTest, SetInputRegion) { ...@@ -180,9 +183,10 @@ TEST_F(SurfaceTest, SetInputRegion) {
TEST_F(SurfaceTest, SetBufferScale) { TEST_F(SurfaceTest, SetBufferScale) {
gfx::Size buffer_size(512, 512); gfx::Size buffer_size(512, 512);
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 = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
// This will update the bounds of the surface and take the buffer scale into // This will update the bounds of the surface and take the buffer scale into
// account. // account.
...@@ -200,9 +204,10 @@ TEST_F(SurfaceTest, SetBufferScale) { ...@@ -200,9 +204,10 @@ TEST_F(SurfaceTest, SetBufferScale) {
TEST_F(SurfaceTest, MirrorLayers) { TEST_F(SurfaceTest, MirrorLayers) {
gfx::Size buffer_size(512, 512); gfx::Size buffer_size(512, 512);
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 = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
surface->Attach(buffer.get()); surface->Attach(buffer.get());
surface->Commit(); surface->Commit();
...@@ -210,19 +215,20 @@ TEST_F(SurfaceTest, MirrorLayers) { ...@@ -210,19 +215,20 @@ TEST_F(SurfaceTest, MirrorLayers) {
EXPECT_EQ(buffer_size, surface->window()->bounds().size()); EXPECT_EQ(buffer_size, surface->window()->bounds().size());
EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size()); EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size());
std::unique_ptr<ui::LayerTreeOwner> old_layer_owner = std::unique_ptr<ui::LayerTreeOwner> old_layer_owner =
::wm::MirrorLayers(surface->window(), false /* sync_bounds */); ::wm::MirrorLayers(shell_surface->host_window(), false /* sync_bounds */);
EXPECT_EQ(buffer_size, surface->window()->bounds().size()); EXPECT_EQ(buffer_size, surface->window()->bounds().size());
EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size()); EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size());
EXPECT_EQ(buffer_size, old_layer_owner->root()->bounds().size()); EXPECT_EQ(buffer_size, old_layer_owner->root()->bounds().size());
EXPECT_TRUE(surface->window()->layer()->has_external_content()); EXPECT_TRUE(shell_surface->host_window()->layer()->has_external_content());
EXPECT_TRUE(old_layer_owner->root()->has_external_content()); EXPECT_TRUE(old_layer_owner->root()->has_external_content());
} }
TEST_F(SurfaceTest, SetViewport) { TEST_F(SurfaceTest, SetViewport) {
gfx::Size buffer_size(1, 1); gfx::Size buffer_size(1, 1);
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 = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
// This will update the bounds of the surface and take the viewport into // This will update the bounds of the surface and take the viewport into
// account. // account.
...@@ -244,9 +250,10 @@ TEST_F(SurfaceTest, SetViewport) { ...@@ -244,9 +250,10 @@ TEST_F(SurfaceTest, SetViewport) {
TEST_F(SurfaceTest, SetCrop) { TEST_F(SurfaceTest, SetCrop) {
gfx::Size buffer_size(16, 16); gfx::Size buffer_size(16, 16);
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 = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
surface->Attach(buffer.get()); surface->Attach(buffer.get());
gfx::Size crop_size(12, 12); gfx::Size crop_size(12, 12);
...@@ -259,16 +266,17 @@ TEST_F(SurfaceTest, SetCrop) { ...@@ -259,16 +266,17 @@ TEST_F(SurfaceTest, SetCrop) {
TEST_F(SurfaceTest, SetBlendMode) { TEST_F(SurfaceTest, SetBlendMode) {
gfx::Size buffer_size(1, 1); gfx::Size buffer_size(1, 1);
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 = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
surface->Attach(buffer.get()); surface->Attach(buffer.get());
surface->SetBlendMode(SkBlendMode::kSrc); surface->SetBlendMode(SkBlendMode::kSrc);
surface->Commit(); surface->Commit();
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get()); const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.size());
ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
EXPECT_FALSE(frame.render_pass_list.back() EXPECT_FALSE(frame.render_pass_list.back()
...@@ -278,15 +286,17 @@ TEST_F(SurfaceTest, SetBlendMode) { ...@@ -278,15 +286,17 @@ TEST_F(SurfaceTest, SetBlendMode) {
TEST_F(SurfaceTest, OverlayCandidate) { TEST_F(SurfaceTest, OverlayCandidate) {
gfx::Size buffer_size(1, 1); gfx::Size buffer_size(1, 1);
std::unique_ptr<Buffer> buffer(new Buffer( auto buffer = base::MakeUnique<Buffer>(
exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), 0, 0, true, true)); exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
std::unique_ptr<Surface> surface(new Surface); true, true);
auto surface = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
surface->Attach(buffer.get()); surface->Attach(buffer.get());
surface->Commit(); surface->Commit();
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get()); const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.size());
ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
cc::DrawQuad* draw_quad = frame.render_pass_list.back()->quad_list.back(); cc::DrawQuad* draw_quad = frame.render_pass_list.back()->quad_list.back();
...@@ -299,9 +309,11 @@ TEST_F(SurfaceTest, OverlayCandidate) { ...@@ -299,9 +309,11 @@ TEST_F(SurfaceTest, OverlayCandidate) {
TEST_F(SurfaceTest, SetAlpha) { TEST_F(SurfaceTest, SetAlpha) {
gfx::Size buffer_size(1, 1); gfx::Size buffer_size(1, 1);
std::unique_ptr<Buffer> buffer( auto buffer = base::MakeUnique<Buffer>(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
std::unique_ptr<Surface> surface(new Surface); true, true);
auto surface = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
surface->Attach(buffer.get()); surface->Attach(buffer.get());
surface->SetAlpha(0.5f); surface->SetAlpha(0.5f);
...@@ -318,10 +330,12 @@ TEST_F(SurfaceTest, Commit) { ...@@ -318,10 +330,12 @@ TEST_F(SurfaceTest, Commit) {
TEST_F(SurfaceTest, SendsBeginFrameAcks) { TEST_F(SurfaceTest, SendsBeginFrameAcks) {
cc::FakeExternalBeginFrameSource source(0.f, false); cc::FakeExternalBeginFrameSource source(0.f, false);
gfx::Size buffer_size(1, 1); gfx::Size buffer_size(1, 1);
std::unique_ptr<Buffer> buffer( auto buffer = base::MakeUnique<Buffer>(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
std::unique_ptr<Surface> surface(new Surface); true, true);
surface->SetBeginFrameSource(&source); auto surface = base::MakeUnique<Surface>();
auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
shell_surface->SetBeginFrameSource(&source);
surface->Attach(buffer.get()); surface->Attach(buffer.get());
// Request a frame callback so that Surface now needs BeginFrames. // Request a frame callback so that Surface now needs BeginFrames.
...@@ -333,7 +347,7 @@ TEST_F(SurfaceTest, SendsBeginFrameAcks) { ...@@ -333,7 +347,7 @@ TEST_F(SurfaceTest, SendsBeginFrameAcks) {
// Surface should add itself as observer during // Surface should add itself as observer during
// DidReceiveCompositorFrameAck(). // DidReceiveCompositorFrameAck().
surface->DidReceiveCompositorFrameAck(); shell_surface->DidReceiveCompositorFrameAck();
EXPECT_EQ(1u, source.num_observers()); EXPECT_EQ(1u, source.num_observers());
cc::BeginFrameArgs args(source.CreateBeginFrameArgs(BEGINFRAME_FROM_HERE)); cc::BeginFrameArgs args(source.CreateBeginFrameArgs(BEGINFRAME_FROM_HERE));
...@@ -344,7 +358,7 @@ TEST_F(SurfaceTest, SendsBeginFrameAcks) { ...@@ -344,7 +358,7 @@ TEST_F(SurfaceTest, SendsBeginFrameAcks) {
surface->Commit(); // Acknowledges the BeginFrame via CompositorFrame. surface->Commit(); // Acknowledges the BeginFrame via CompositorFrame.
RunAllPendingInMessageLoop(); RunAllPendingInMessageLoop();
const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get()); const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
cc::BeginFrameAck expected_ack(args.source_id, args.sequence_number, true); cc::BeginFrameAck expected_ack(args.source_id, args.sequence_number, true);
EXPECT_EQ(expected_ack, frame.metadata.begin_frame_ack); EXPECT_EQ(expected_ack, frame.metadata.begin_frame_ack);
......
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