Commit 4f19a78b authored by Kazuhiro Inaba's avatar Kazuhiro Inaba Committed by Commit Bot

Revert "exo: Use one LayerTreeFrameSink per toplevel window"

This reverts commit 5f933e80.

Reason for revert: crbug.com/744235 All ARC apps are broken (black screen.)

Original change's description:
> 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: David Reveman <reveman@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#486788}

TBR=penghuang@chromium.org,reveman@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

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