Skip to content

Commit

Permalink
Extract non-Mojo bits of GpuCompositorFrameSink to CompositorFrameSin…
Browse files Browse the repository at this point in the history
…kSupport

We would like to have all Chrome clients use a single service-side
CompositorFrameSink implementation as an incremental step towards pulling the
display compositor into the gpu process. This CL extract non-mojo-specific
code from GpuCompositorFrameSink in services/ui to CompositorFrameSinkSupport
in a central place: cc/surfaces that can be used by Chrome today. Individual
clients can transition to mojo after we carefully measure the performance
impact of the transition.

BUG=668126, 657959
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel

Review-Url: https://codereview.chromium.org/2543373002
Cr-Commit-Position: refs/heads/master@{#436148}
  • Loading branch information
fsamuel authored and Commit bot committed Dec 3, 2016
1 parent abbafbc commit 932aa65
Show file tree
Hide file tree
Showing 6 changed files with 356 additions and 188 deletions.
3 changes: 3 additions & 0 deletions cc/surfaces/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ cc_source_set("surface_id") {
cc_component("surfaces") {
output_name = "cc_surfaces"
sources = [
"compositor_frame_sink_support.cc",
"compositor_frame_sink_support.h",
"compositor_frame_sink_support_client.h",
"direct_compositor_frame_sink.cc",
"direct_compositor_frame_sink.h",
"display.cc",
Expand Down
173 changes: 173 additions & 0 deletions cc/surfaces/compositor_frame_sink_support.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/surfaces/compositor_frame_sink_support.h"

#include "cc/output/compositor_frame.h"
#include "cc/scheduler/begin_frame_source.h"
#include "cc/surfaces/compositor_frame_sink_support_client.h"
#include "cc/surfaces/display.h"
#include "cc/surfaces/surface_manager.h"

namespace cc {

CompositorFrameSinkSupport::CompositorFrameSinkSupport(
CompositorFrameSinkSupportClient* client,
SurfaceManager* surface_manager,
const FrameSinkId& frame_sink_id,
std::unique_ptr<Display> display)
: client_(client),
surface_manager_(surface_manager),
frame_sink_id_(frame_sink_id),
display_(std::move(display)),
surface_factory_(frame_sink_id_, surface_manager_, this),
weak_factory_(this) {
surface_manager_->RegisterFrameSinkId(frame_sink_id_);
surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this);

if (display_) {
display_->Initialize(this, surface_manager_);
display_->SetVisible(true);
}
}

CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
// SurfaceFactory's destructor will attempt to return resources which will
// call back into here and access |client_| so we should destroy
// |surface_factory_|'s resources early on.
surface_factory_.EvictSurface();
surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
}

void CompositorFrameSinkSupport::EvictFrame() {
surface_factory_.EvictSurface();
}

void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
needs_begin_frame_ = needs_begin_frame;
UpdateNeedsBeginFramesInternal();
}

void CompositorFrameSinkSupport::SubmitCompositorFrame(
const LocalFrameId& local_frame_id,
CompositorFrame frame) {
if (local_frame_id_ != local_frame_id) {
local_frame_id_ = local_frame_id;
if (display_ && !frame.render_pass_list.empty()) {
gfx::Size frame_size = frame.render_pass_list[0]->output_rect.size();
// TODO(piman, fsamuel): We will likely want to revisit this because some
// clients may want finer control over the Display sizing - since it
// really means the actual size of the native window (Linux/Win Aura) or
// display (Ozone). We may need to either prevent or gutter Display frames
// until there is a correctly-sized top-level CompositorFrame available
// (see ui::Compositor::DisableSwapUntilResize). We might want to resize
// Display earlier.
display_->Resize(frame_size);
}
}
++ack_pending_count_;
surface_factory_.SubmitCompositorFrame(
local_frame_id_, std::move(frame),
base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
weak_factory_.GetWeakPtr()));
if (display_) {
display_->SetLocalFrameId(local_frame_id_,
frame.metadata.device_scale_factor);
}
}

void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
DCHECK_GT(ack_pending_count_, 0);
ack_pending_count_--;

if (!client_)
return;
client_->DidReceiveCompositorFrameAck();
if (!surface_returned_resources_.empty()) {
client_->ReclaimResources(surface_returned_resources_);
surface_returned_resources_.clear();
}
}

void CompositorFrameSinkSupport::AddChildFrameSink(
const FrameSinkId& child_frame_sink_id) {
surface_manager_->RegisterFrameSinkHierarchy(frame_sink_id_,
child_frame_sink_id);
}

void CompositorFrameSinkSupport::RemoveChildFrameSink(
const FrameSinkId& child_frame_sink_id) {
surface_manager_->UnregisterFrameSinkHierarchy(frame_sink_id_,
child_frame_sink_id);
}

void CompositorFrameSinkSupport::DisplayOutputSurfaceLost() {}

void CompositorFrameSinkSupport::DisplayWillDrawAndSwap(
bool will_draw_and_swap,
const RenderPassList& render_passes) {}

void CompositorFrameSinkSupport::DisplayDidDrawAndSwap() {}

void CompositorFrameSinkSupport::ReturnResources(
const ReturnedResourceArray& resources) {
if (resources.empty())
return;

if (!ack_pending_count_ && client_) {
client_->ReclaimResources(resources);
return;
}

std::copy(resources.begin(), resources.end(),
std::back_inserter(surface_returned_resources_));
}

void CompositorFrameSinkSupport::SetBeginFrameSource(
BeginFrameSource* begin_frame_source) {
if (begin_frame_source_ && added_frame_observer_) {
begin_frame_source_->RemoveObserver(this);
added_frame_observer_ = false;
}
begin_frame_source_ = begin_frame_source;
UpdateNeedsBeginFramesInternal();
}

void CompositorFrameSinkSupport::WillDrawSurface(
const LocalFrameId& local_frame_id,
const gfx::Rect& damage_rect) {
if (client_)
client_->WillDrawSurface();
}

void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
UpdateNeedsBeginFramesInternal();
last_begin_frame_args_ = args;
if (client_)
client_->OnBeginFrame(args);
}

const BeginFrameArgs& CompositorFrameSinkSupport::LastUsedBeginFrameArgs()
const {
return last_begin_frame_args_;
}

void CompositorFrameSinkSupport::OnBeginFrameSourcePausedChanged(bool paused) {}

void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
if (!begin_frame_source_)
return;

if (needs_begin_frame_ == added_frame_observer_)
return;

added_frame_observer_ = needs_begin_frame_;
if (needs_begin_frame_)
begin_frame_source_->AddObserver(this);
else
begin_frame_source_->RemoveObserver(this);
}

} // namespace cc
104 changes: 104 additions & 0 deletions cc/surfaces/compositor_frame_sink_support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_SURFACES_COMPOSITOR_FRAME_SINK_SUPPORT_H_
#define CC_SURFACES_COMPOSITOR_FRAME_SINK_SUPPORT_H_

#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "cc/output/compositor_frame.h"
#include "cc/scheduler/begin_frame_source.h"
#include "cc/surfaces/display.h"
#include "cc/surfaces/display_client.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surfaces_export.h"

namespace cc {

class CompositorFrameSinkSupportClient;
class Display;
class SurfaceManager;

class CC_SURFACES_EXPORT CompositorFrameSinkSupport
: public NON_EXPORTED_BASE(DisplayClient),
public SurfaceFactoryClient,
public BeginFrameObserver {
public:
CompositorFrameSinkSupport(CompositorFrameSinkSupportClient* client,
SurfaceManager* surface_manager,
const FrameSinkId& frame_sink_id,
std::unique_ptr<Display> display);

~CompositorFrameSinkSupport() override;

const FrameSinkId& frame_sink_id() const { return frame_sink_id_; }

void EvictFrame();
void SetNeedsBeginFrame(bool needs_begin_frame);
void SubmitCompositorFrame(const LocalFrameId& local_frame_id,
CompositorFrame frame);
void AddChildFrameSink(const FrameSinkId& child_frame_sink_id);
void RemoveChildFrameSink(const FrameSinkId& child_frame_sink_id);

private:
void DidReceiveCompositorFrameAck();

// DisplayClient implementation.
void DisplayOutputSurfaceLost() override;
void DisplayWillDrawAndSwap(bool will_draw_and_swap,
const RenderPassList& render_passes) override;
void DisplayDidDrawAndSwap() override;

// SurfaceFactoryClient implementation.
void ReturnResources(const ReturnedResourceArray& resources) override;
void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override;
void WillDrawSurface(const LocalFrameId& local_frame_id,
const gfx::Rect& damage_rect) override;

// BeginFrameObserver implementation.
void OnBeginFrame(const BeginFrameArgs& args) override;
const BeginFrameArgs& LastUsedBeginFrameArgs() const override;
void OnBeginFrameSourcePausedChanged(bool paused) override;

void UpdateNeedsBeginFramesInternal();

CompositorFrameSinkSupportClient* const client_;

SurfaceManager* const surface_manager_;

const FrameSinkId frame_sink_id_;

// GpuCompositorFrameSink holds a Display if it created with
// non-null gpu::SurfaceHandle. In the window server, the display root
// window's CompositorFrameSink will have a valid gpu::SurfaceHandle.
std::unique_ptr<Display> display_;

LocalFrameId local_frame_id_;
SurfaceFactory surface_factory_;
// Counts the number of CompositorFrames that have been submitted and have not
// yet received an ACK.
int ack_pending_count_ = 0;
ReturnedResourceArray surface_returned_resources_;

// The begin frame source being observered. Null if none.
BeginFrameSource* begin_frame_source_ = nullptr;

// The last begin frame args generated by the begin frame source.
BeginFrameArgs last_begin_frame_args_;

// Whether a request for begin frames has been issued.
bool needs_begin_frame_ = false;

// Whether or not a frame observer has been added.
bool added_frame_observer_ = false;

base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupport);
};

} // namespace cc

#endif // CC_SURFACES_COMPOSITOR_FRAME_SINK_SUPPORT_H_
40 changes: 40 additions & 0 deletions cc/surfaces/compositor_frame_sink_support_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_SURFACES_COMPOSITOR_FRAME_SINK_SUPPORT_CLIENT_H_
#define CC_SURFACES_COMPOSITOR_FRAME_SINK_SUPPORT_CLIENT_H_

#include "cc/resources/returned_resource.h"

namespace cc {

struct BeginFrameArgs;

class CompositorFrameSinkSupportClient {
public:
// Notification that the previous CompositorFrame given to
// SubmitCompositorFrame() has been processed and that another frame
// can be submitted. This provides backpressure from the display compositor
// so that frames are submitted only at the rate it can handle them.
// TODO(fsamuel): This method ought not be necessary with unified BeginFrame.
// However, there's a fair amount of cleanup and refactoring necessary to get
// rid of it.
virtual void DidReceiveCompositorFrameAck() = 0;

// Notification for the client to generate a CompositorFrame.
virtual void OnBeginFrame(const BeginFrameArgs& args) = 0;

// Returns resources sent to SubmitCompositorFrame to be reused or freed.
virtual void ReclaimResources(const ReturnedResourceArray& resources) = 0;

// Called when surface is being scheduled for a draw.
virtual void WillDrawSurface() = 0;

protected:
virtual ~CompositorFrameSinkSupportClient() {}
};

} // namespace cc

#endif // CC_SURFACES_COMPOSITOR_FRAME_SINK_SUPPORT_CLIENT_H_
Loading

0 comments on commit 932aa65

Please sign in to comment.