Commit 3372217a authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

[cc] Add a way to control the compositor's BeginFrames externally.

Exposes a setting and an interface for enabling externally-controlled
BeginFrames in ui::Compositor and adds a command line flag for the
full-pipeline scheduling mode.

Bug: 646774
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_site_isolation
Change-Id: I923b5ab66652c65c1384b9fe5075c0a427559fc6
Reviewed-on: https://chromium-review.googlesource.com/558252
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarFady Samuel <fsamuel@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490719}
parent 16d3c5dc
...@@ -49,6 +49,11 @@ const char kEnableTileCompression[] = "enable-tile-compression"; ...@@ -49,6 +49,11 @@ const char kEnableTileCompression[] = "enable-tile-compression";
// Enables the GPU benchmarking extension // Enables the GPU benchmarking extension
const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking"; const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking";
// Effectively disables pipelining of compositor frame production stages by
// waiting for each stage to finish before completing a frame.
const char kRunAllCompositorStagesBeforeDraw[] =
"run-all-compositor-stages-before-draw";
// Renders a border around compositor layers to help debug and study // Renders a border around compositor layers to help debug and study
// layer compositing. // layer compositing.
const char kShowCompositedLayerBorders[] = "show-composited-layer-borders"; const char kShowCompositedLayerBorders[] = "show-composited-layer-borders";
......
...@@ -30,6 +30,7 @@ CC_BASE_EXPORT extern const char kEnableTileCompression[]; ...@@ -30,6 +30,7 @@ CC_BASE_EXPORT extern const char kEnableTileCompression[];
// Switches for both the renderer and ui compositors. // Switches for both the renderer and ui compositors.
CC_BASE_EXPORT extern const char kEnableGpuBenchmarking[]; CC_BASE_EXPORT extern const char kEnableGpuBenchmarking[];
CC_BASE_EXPORT extern const char kRunAllCompositorStagesBeforeDraw[];
// Debug visualizations. // Debug visualizations.
CC_BASE_EXPORT extern const char kShowCompositedLayerBorders[]; CC_BASE_EXPORT extern const char kShowCompositedLayerBorders[];
......
...@@ -35,6 +35,8 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const { ...@@ -35,6 +35,8 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const {
scheduler_settings.enable_latency_recovery = enable_latency_recovery; scheduler_settings.enable_latency_recovery = enable_latency_recovery;
scheduler_settings.background_frame_interval = scheduler_settings.background_frame_interval =
base::TimeDelta::FromSecondsD(1.0 / background_animation_rate); base::TimeDelta::FromSecondsD(1.0 / background_animation_rate);
scheduler_settings.wait_for_all_pipeline_stages_before_draw =
wait_for_all_pipeline_stages_before_draw;
return scheduler_settings; return scheduler_settings;
} }
......
...@@ -115,6 +115,12 @@ class CC_EXPORT LayerTreeSettings { ...@@ -115,6 +115,12 @@ class CC_EXPORT LayerTreeSettings {
// in ResourcePool. Only used for layout or pixel tests, as non-deterministic // in ResourcePool. Only used for layout or pixel tests, as non-deterministic
// resource sizes can lead to floating point error and noise in these tests. // resource sizes can lead to floating point error and noise in these tests.
bool disallow_non_exact_resource_reuse = false; bool disallow_non_exact_resource_reuse = false;
// Whether the Scheduler should wait for all pipeline stages before attempting
// to draw. If |true|, they will block indefinitely until all stages have
// completed the current BeginFrame before triggering their own BeginFrame
// deadlines.
bool wait_for_all_pipeline_stages_before_draw = false;
}; };
} // namespace cc } // namespace cc
......
...@@ -95,6 +95,14 @@ void Display::Initialize(DisplayClient* client, ...@@ -95,6 +95,14 @@ void Display::Initialize(DisplayClient* client,
} }
} }
void Display::AddObserver(DisplayObserver* observer) {
observers_.AddObserver(observer);
}
void Display::RemoveObserver(DisplayObserver* observer) {
observers_.RemoveObserver(observer);
}
void Display::SetLocalSurfaceId(const LocalSurfaceId& id, void Display::SetLocalSurfaceId(const LocalSurfaceId& id,
float device_scale_factor) { float device_scale_factor) {
if (current_surface_id_.local_surface_id() == id && if (current_surface_id_.local_surface_id() == id &&
...@@ -422,6 +430,11 @@ bool Display::SurfaceHasUndrawnFrame(const SurfaceId& surface_id) const { ...@@ -422,6 +430,11 @@ bool Display::SurfaceHasUndrawnFrame(const SurfaceId& surface_id) const {
return surface->HasUndrawnActiveFrame(); return surface->HasUndrawnActiveFrame();
} }
void Display::DidFinishFrame(const BeginFrameAck& ack) {
for (auto& observer : observers_)
observer.OnDisplayDidFinishFrame(ack);
}
const SurfaceId& Display::CurrentSurfaceId() { const SurfaceId& Display::CurrentSurfaceId() {
return current_surface_id_; return current_surface_id_;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h"
#include "cc/output/output_surface_client.h" #include "cc/output/output_surface_client.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/returned_resource.h"
...@@ -44,6 +45,13 @@ namespace viz { ...@@ -44,6 +45,13 @@ namespace viz {
class DisplayClient; class DisplayClient;
class SharedBitmapManager; class SharedBitmapManager;
class VIZ_SERVICE_EXPORT DisplayObserver {
public:
virtual ~DisplayObserver() {}
virtual void OnDisplayDidFinishFrame(const BeginFrameAck& ack) = 0;
};
// A Display produces a surface that can be used to draw to a physical display // A Display produces a surface that can be used to draw to a physical display
// (OutputSurface). The client is responsible for creating and sizing the // (OutputSurface). The client is responsible for creating and sizing the
// surface IDs used to draw into the display and deciding when to draw. // surface IDs used to draw into the display and deciding when to draw.
...@@ -64,6 +72,9 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient, ...@@ -64,6 +72,9 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
void Initialize(DisplayClient* client, SurfaceManager* surface_manager); void Initialize(DisplayClient* client, SurfaceManager* surface_manager);
void AddObserver(DisplayObserver* observer);
void RemoveObserver(DisplayObserver* observer);
// device_scale_factor is used to communicate to the external window system // device_scale_factor is used to communicate to the external window system
// what scale this was rendered at. // what scale this was rendered at.
void SetLocalSurfaceId(const LocalSurfaceId& id, float device_scale_factor); void SetLocalSurfaceId(const LocalSurfaceId& id, float device_scale_factor);
...@@ -81,6 +92,7 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient, ...@@ -81,6 +92,7 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
bool SurfaceDamaged(const SurfaceId& surface_id, bool SurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) override; const BeginFrameAck& ack) override;
void SurfaceDiscarded(const SurfaceId& surface_id) override; void SurfaceDiscarded(const SurfaceId& surface_id) override;
void DidFinishFrame(const BeginFrameAck& ack) override;
// OutputSurfaceClient implementation. // OutputSurfaceClient implementation.
void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override; void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override;
...@@ -106,6 +118,7 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient, ...@@ -106,6 +118,7 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
const RendererSettings settings_; const RendererSettings settings_;
DisplayClient* client_ = nullptr; DisplayClient* client_ = nullptr;
base::ObserverList<DisplayObserver> observers_;
SurfaceManager* surface_manager_ = nullptr; SurfaceManager* surface_manager_ = nullptr;
const FrameSinkId frame_sink_id_; const FrameSinkId frame_sink_id_;
SurfaceId current_surface_id_; SurfaceId current_surface_id_;
......
...@@ -471,8 +471,11 @@ void DisplayScheduler::OnBeginFrameDeadline() { ...@@ -471,8 +471,11 @@ void DisplayScheduler::OnBeginFrameDeadline() {
void DisplayScheduler::DidFinishFrame(bool did_draw) { void DisplayScheduler::DidFinishFrame(bool did_draw) {
DCHECK(begin_frame_source_); DCHECK(begin_frame_source_);
// TODO(eseckler): Let client know that frame was completed.
begin_frame_source_->DidFinishFrame(this); begin_frame_source_->DidFinishFrame(this);
BeginFrameAck ack(current_begin_frame_args_.source_id,
current_begin_frame_args_.sequence_number, did_draw);
client_->DidFinishFrame(ack);
} }
void DisplayScheduler::DidSwapBuffers() { void DisplayScheduler::DidSwapBuffers() {
......
...@@ -32,6 +32,7 @@ class VIZ_SERVICE_EXPORT DisplaySchedulerClient { ...@@ -32,6 +32,7 @@ class VIZ_SERVICE_EXPORT DisplaySchedulerClient {
virtual bool SurfaceDamaged(const SurfaceId& surface_id, virtual bool SurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) = 0; const BeginFrameAck& ack) = 0;
virtual void SurfaceDiscarded(const SurfaceId& surface_id) = 0; virtual void SurfaceDiscarded(const SurfaceId& surface_id) = 0;
virtual void DidFinishFrame(const BeginFrameAck& ack) = 0;
}; };
class VIZ_SERVICE_EXPORT DisplayScheduler : public BeginFrameObserverBase, class VIZ_SERVICE_EXPORT DisplayScheduler : public BeginFrameObserverBase,
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/surfaces/surface_info.h" #include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/display/display.h" #include "components/viz/service/display/display.h"
#include "components/viz/test/begin_frame_args_test.h"
#include "components/viz/test/fake_external_begin_frame_source.h" #include "components/viz/test/fake_external_begin_frame_source.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -52,6 +53,10 @@ class FakeDisplaySchedulerClient : public DisplaySchedulerClient { ...@@ -52,6 +53,10 @@ class FakeDisplaySchedulerClient : public DisplaySchedulerClient {
void SurfaceDiscarded(const SurfaceId& surface_id) override {} void SurfaceDiscarded(const SurfaceId& surface_id) override {}
void DidFinishFrame(const BeginFrameAck& ack) override {
last_begin_frame_ack_ = ack;
}
int draw_and_swap_count() const { return draw_and_swap_count_; } int draw_and_swap_count() const { return draw_and_swap_count_; }
void SetNextDrawAndSwapFails() { next_draw_and_swap_fails_ = true; } void SetNextDrawAndSwapFails() { next_draw_and_swap_fails_ = true; }
...@@ -60,10 +65,13 @@ class FakeDisplaySchedulerClient : public DisplaySchedulerClient { ...@@ -60,10 +65,13 @@ class FakeDisplaySchedulerClient : public DisplaySchedulerClient {
undrawn_surfaces_.insert(surface_id); undrawn_surfaces_.insert(surface_id);
} }
const BeginFrameAck& last_begin_frame_ack() { return last_begin_frame_ack_; }
protected: protected:
int draw_and_swap_count_; int draw_and_swap_count_;
bool next_draw_and_swap_fails_; bool next_draw_and_swap_fails_;
std::set<SurfaceId> undrawn_surfaces_; std::set<SurfaceId> undrawn_surfaces_;
BeginFrameAck last_begin_frame_ack_;
}; };
class TestDisplayScheduler : public DisplayScheduler { class TestDisplayScheduler : public DisplayScheduler {
...@@ -261,9 +269,11 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) { ...@@ -261,9 +269,11 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
scheduler_.SetVisible(true); scheduler_.SetVisible(true);
scheduler_.SetNewRootSurface(root_surface_id); scheduler_.SetNewRootSurface(root_surface_id);
EXPECT_EQ(BeginFrameAck(), client_.last_begin_frame_ack());
// Set surface1 as active via SurfaceDamageExpected(). // Set surface1 as active via SurfaceDamageExpected().
AdvanceTimeAndBeginFrameForTest({sid1}); AdvanceTimeAndBeginFrameForTest({sid1});
EXPECT_EQ(BeginFrameAck(), client_.last_begin_frame_ack());
// Damage only from surface 2 (inactive) does not trigger deadline early. // Damage only from surface 2 (inactive) does not trigger deadline early.
SurfaceDamaged(sid2); SurfaceDamaged(sid2);
...@@ -277,6 +287,9 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) { ...@@ -277,6 +287,9 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
EXPECT_GE(now_src().NowTicks(), EXPECT_GE(now_src().NowTicks(),
scheduler_.DesiredBeginFrameDeadlineTimeForTest()); scheduler_.DesiredBeginFrameDeadlineTimeForTest());
scheduler_.BeginFrameDeadlineForTest(); scheduler_.BeginFrameDeadlineForTest();
EXPECT_EQ(BeginFrameAck(last_begin_frame_args_.source_id,
last_begin_frame_args_.sequence_number, true),
client_.last_begin_frame_ack());
// Set both surface 1 and 2 as active via SurfaceDamageExpected(). // Set both surface 1 and 2 as active via SurfaceDamageExpected().
AdvanceTimeAndBeginFrameForTest({sid1, sid2}); AdvanceTimeAndBeginFrameForTest({sid1, sid2});
...@@ -291,6 +304,9 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) { ...@@ -291,6 +304,9 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
EXPECT_GE(now_src().NowTicks(), EXPECT_GE(now_src().NowTicks(),
scheduler_.DesiredBeginFrameDeadlineTimeForTest()); scheduler_.DesiredBeginFrameDeadlineTimeForTest());
scheduler_.BeginFrameDeadlineForTest(); scheduler_.BeginFrameDeadlineForTest();
EXPECT_EQ(BeginFrameAck(last_begin_frame_args_.source_id,
last_begin_frame_args_.sequence_number, true),
client_.last_begin_frame_ack());
// Surface damage with |!has_damage| triggers early deadline if other damage // Surface damage with |!has_damage| triggers early deadline if other damage
// exists. // exists.
...@@ -318,6 +334,9 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) { ...@@ -318,6 +334,9 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
EXPECT_LT(now_src().NowTicks(), EXPECT_LT(now_src().NowTicks(),
scheduler_.DesiredBeginFrameDeadlineTimeForTest()); scheduler_.DesiredBeginFrameDeadlineTimeForTest());
scheduler_.BeginFrameDeadlineForTest(); scheduler_.BeginFrameDeadlineForTest();
EXPECT_EQ(BeginFrameAck(last_begin_frame_args_.source_id,
last_begin_frame_args_.sequence_number, false),
client_.last_begin_frame_ack());
// System should be idle now. // System should be idle now.
AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>()); AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "cc/output/vulkan_in_process_context_provider.h" #include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/raster/single_thread_task_graph_runner.h" #include "cc/raster/single_thread_task_graph_runner.h"
#include "cc/raster/task_graph_runner.h" #include "cc/raster/task_graph_runner.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/delay_based_time_source.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "components/viz/common/gl_helper.h" #include "components/viz/common/gl_helper.h"
...@@ -186,13 +187,44 @@ bool IsCALayersDisabledFromCommandLine() { ...@@ -186,13 +187,44 @@ bool IsCALayersDisabledFromCommandLine() {
namespace content { namespace content {
class ExternalBeginFrameController : public viz::ExternalBeginFrameSourceClient,
public viz::DisplayObserver {
public:
explicit ExternalBeginFrameController(ui::Compositor* compositor)
: begin_frame_source_(this), compositor_(compositor) {}
~ExternalBeginFrameController() override {}
// Issue a BeginFrame with the given |args|.
void IssueExternalBeginFrame(const viz::BeginFrameArgs& args) {
begin_frame_source_.OnBeginFrame(args);
}
viz::BeginFrameSource* begin_frame_source() { return &begin_frame_source_; }
private:
// viz::ExternalBeginFrameSourceClient implementation.
void OnNeedsBeginFrames(bool needs_begin_frames) override {
compositor_->OnNeedsExternalBeginFrames(needs_begin_frames);
}
// viz::DisplayObserver implementation.
void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override {
compositor_->OnDisplayDidFinishFrame(ack);
}
viz::ExternalBeginFrameSource begin_frame_source_;
ui::Compositor* compositor_ = nullptr;
};
struct GpuProcessTransportFactory::PerCompositorData { struct GpuProcessTransportFactory::PerCompositorData {
gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle; gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
BrowserCompositorOutputSurface* display_output_surface = nullptr; BrowserCompositorOutputSurface* display_output_surface = nullptr;
// Either |synthetic_begin_frame_source| or |gpu_vsync_begin_frame_source| is // Exactly one of |synthetic_begin_frame_source|,
// valid but not both at the same time. // |gpu_vsync_begin_frame_source|, and |external_begin_frame_source| is valid
// at the same time.
std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source; std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source; std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source;
std::unique_ptr<ExternalBeginFrameController> external_begin_frame_controller;
ReflectorImpl* reflector = nullptr; ReflectorImpl* reflector = nullptr;
std::unique_ptr<viz::Display> display; std::unique_ptr<viz::Display> display;
bool output_is_secure = false; bool output_is_secure = false;
...@@ -220,6 +252,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory( ...@@ -220,6 +252,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory(
} }
} }
if (command_line->HasSwitch(cc::switches::kRunAllCompositorStagesBeforeDraw))
wait_for_all_pipeline_stages_before_draw_ = true;
task_graph_runner_->Start("CompositorTileWorker1", task_graph_runner_->Start("CompositorTileWorker1",
base::SimpleThread::Options()); base::SimpleThread::Options());
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -486,7 +521,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ...@@ -486,7 +521,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
BrowserCompositorOutputSurface::UpdateVSyncParametersCallback vsync_callback = BrowserCompositorOutputSurface::UpdateVSyncParametersCallback vsync_callback =
base::Bind(&ui::Compositor::SetDisplayVSyncParameters, compositor); base::Bind(&ui::Compositor::SetDisplayVSyncParameters, compositor);
viz::BeginFrameSource* begin_frame_source = nullptr;
GpuVSyncControl* gpu_vsync_control = nullptr; GpuVSyncControl* gpu_vsync_control = nullptr;
std::unique_ptr<BrowserCompositorOutputSurface> display_output_surface; std::unique_ptr<BrowserCompositorOutputSurface> display_output_surface;
...@@ -560,9 +594,14 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ...@@ -560,9 +594,14 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source; std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source; std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source;
std::unique_ptr<ExternalBeginFrameController> external_begin_frame_controller;
if (!begin_frame_source) { viz::BeginFrameSource* begin_frame_source = nullptr;
if (!disable_display_vsync_) { if (compositor->external_begin_frames_enabled()) {
external_begin_frame_controller =
base::MakeUnique<ExternalBeginFrameController>(compositor.get());
begin_frame_source = external_begin_frame_controller->begin_frame_source();
} else if (!disable_display_vsync_) {
if (gpu_vsync_control && IsGpuVSyncSignalSupported()) { if (gpu_vsync_control && IsGpuVSyncSignalSupported()) {
gpu_vsync_begin_frame_source = gpu_vsync_begin_frame_source =
base::MakeUnique<GpuVSyncBeginFrameSource>(gpu_vsync_control); base::MakeUnique<GpuVSyncBeginFrameSource>(gpu_vsync_control);
...@@ -581,7 +620,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ...@@ -581,7 +620,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
compositor->task_runner().get())); compositor->task_runner().get()));
begin_frame_source = synthetic_begin_frame_source.get(); begin_frame_source = synthetic_begin_frame_source.get();
} }
}
#if defined(OS_WIN) #if defined(OS_WIN)
gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild( gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild(
...@@ -593,11 +631,16 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ...@@ -593,11 +631,16 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
} else if (data->gpu_vsync_begin_frame_source) { } else if (data->gpu_vsync_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource( GetFrameSinkManager()->UnregisterBeginFrameSource(
data->gpu_vsync_begin_frame_source.get()); data->gpu_vsync_begin_frame_source.get());
} else if (data->external_begin_frame_controller) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->external_begin_frame_controller->begin_frame_source());
data->display->RemoveObserver(data->external_begin_frame_controller.get());
} }
auto scheduler = base::MakeUnique<viz::DisplayScheduler>( auto scheduler = base::MakeUnique<viz::DisplayScheduler>(
begin_frame_source, compositor->task_runner().get(), begin_frame_source, compositor->task_runner().get(),
display_output_surface->capabilities().max_frames_pending); display_output_surface->capabilities().max_frames_pending,
wait_for_all_pipeline_stages_before_draw_);
// The Display owns and uses the |display_output_surface| created above. // The Display owns and uses the |display_output_surface| created above.
data->display = base::MakeUnique<viz::Display>( data->display = base::MakeUnique<viz::Display>(
...@@ -612,6 +655,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ...@@ -612,6 +655,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// until we have reset |data->display|. // until we have reset |data->display|.
data->synthetic_begin_frame_source = std::move(synthetic_begin_frame_source); data->synthetic_begin_frame_source = std::move(synthetic_begin_frame_source);
data->gpu_vsync_begin_frame_source = std::move(gpu_vsync_begin_frame_source); data->gpu_vsync_begin_frame_source = std::move(gpu_vsync_begin_frame_source);
data->external_begin_frame_controller =
std::move(external_begin_frame_controller);
if (data->external_begin_frame_controller)
data->display->AddObserver(data->external_begin_frame_controller.get());
// The |delegated_output_surface| is given back to the compositor, it // The |delegated_output_surface| is given back to the compositor, it
// delegates to the Display as its root surface. Importantly, it shares the // delegates to the Display as its root surface. Importantly, it shares the
...@@ -673,6 +721,10 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) { ...@@ -673,6 +721,10 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
} else if (data->gpu_vsync_begin_frame_source) { } else if (data->gpu_vsync_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource( GetFrameSinkManager()->UnregisterBeginFrameSource(
data->gpu_vsync_begin_frame_source.get()); data->gpu_vsync_begin_frame_source.get());
} else if (data->external_begin_frame_controller) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->external_begin_frame_controller->begin_frame_source());
data->display->RemoveObserver(data->external_begin_frame_controller.get());
} }
per_compositor_data_.erase(it); per_compositor_data_.erase(it);
if (per_compositor_data_.empty()) { if (per_compositor_data_.empty()) {
...@@ -797,6 +849,18 @@ void GpuProcessTransportFactory::SetDisplayVSyncParameters( ...@@ -797,6 +849,18 @@ void GpuProcessTransportFactory::SetDisplayVSyncParameters(
} }
} }
void GpuProcessTransportFactory::IssueExternalBeginFrame(
ui::Compositor* compositor,
const viz::BeginFrameArgs& args) {
PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
DCHECK(data);
if (data->external_begin_frame_controller)
data->external_begin_frame_controller->IssueExternalBeginFrame(args);
}
void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor, void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
bool secure) { bool secure) {
PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor); PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
......
...@@ -81,6 +81,8 @@ class GpuProcessTransportFactory : public ui::ContextFactory, ...@@ -81,6 +81,8 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void SetDisplayVSyncParameters(ui::Compositor* compositor, void SetDisplayVSyncParameters(ui::Compositor* compositor,
base::TimeTicks timebase, base::TimeTicks timebase,
base::TimeDelta interval) override; base::TimeDelta interval) override;
void IssueExternalBeginFrame(ui::Compositor* compositor,
const viz::BeginFrameArgs& args) override;
void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override; void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override;
// ImageTransportFactory implementation. // ImageTransportFactory implementation.
...@@ -135,6 +137,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory, ...@@ -135,6 +137,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
shared_worker_context_provider_; shared_worker_context_provider_;
bool disable_display_vsync_ = false; bool disable_display_vsync_ = false;
bool wait_for_all_pipeline_stages_before_draw_ = false;
bool shared_vulkan_context_provider_initialized_ = false; bool shared_vulkan_context_provider_initialized_ = false;
scoped_refptr<cc::VulkanInProcessContextProvider> scoped_refptr<cc::VulkanInProcessContextProvider>
shared_vulkan_context_provider_; shared_vulkan_context_provider_;
......
...@@ -2598,6 +2598,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( ...@@ -2598,6 +2598,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kSlowDownRasterScaleFactor, cc::switches::kSlowDownRasterScaleFactor,
cc::switches::kBrowserControlsHideThreshold, cc::switches::kBrowserControlsHideThreshold,
cc::switches::kBrowserControlsShowThreshold, cc::switches::kBrowserControlsShowThreshold,
cc::switches::kRunAllCompositorStagesBeforeDraw,
switches::kEnableSurfaceReferences, switches::kEnableSurfaceReferences,
switches::kEnableSurfaceSynchronization, switches::kEnableSurfaceSynchronization,
......
...@@ -551,6 +551,9 @@ cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings( ...@@ -551,6 +551,9 @@ cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
settings.disallow_non_exact_resource_reuse = settings.disallow_non_exact_resource_reuse =
cmd.HasSwitch(cc::switches::kDisallowNonExactResourceReuse); cmd.HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
settings.wait_for_all_pipeline_stages_before_draw =
cmd.HasSwitch(cc::switches::kRunAllCompositorStagesBeforeDraw);
return settings; return settings;
} }
......
...@@ -35,6 +35,7 @@ component("compositor") { ...@@ -35,6 +35,7 @@ component("compositor") {
"debug_utils.h", "debug_utils.h",
"dip_util.cc", "dip_util.cc",
"dip_util.h", "dip_util.h",
"external_begin_frame_client.h",
"float_animation_curve_adapter.cc", "float_animation_curve_adapter.cc",
"float_animation_curve_adapter.h", "float_animation_curve_adapter.h",
"layer.cc", "layer.cc",
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "ui/compositor/compositor_switches.h" #include "ui/compositor/compositor_switches.h"
#include "ui/compositor/compositor_vsync_manager.h" #include "ui/compositor/compositor_vsync_manager.h"
#include "ui/compositor/dip_util.h" #include "ui/compositor/dip_util.h"
#include "ui/compositor/external_begin_frame_client.h"
#include "ui/compositor/layer.h" #include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator_collection.h" #include "ui/compositor/layer_animator_collection.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h"
...@@ -58,12 +59,14 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id, ...@@ -58,12 +59,14 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
ui::ContextFactory* context_factory, ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private, ui::ContextFactoryPrivate* context_factory_private,
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
bool enable_surface_synchronization) bool enable_surface_synchronization,
bool external_begin_frames_enabled)
: context_factory_(context_factory), : context_factory_(context_factory),
context_factory_private_(context_factory_private), context_factory_private_(context_factory_private),
frame_sink_id_(frame_sink_id), frame_sink_id_(frame_sink_id),
task_runner_(task_runner), task_runner_(task_runner),
vsync_manager_(new CompositorVSyncManager()), vsync_manager_(new CompositorVSyncManager()),
external_begin_frames_enabled_(external_begin_frames_enabled),
layer_animator_collection_(this), layer_animator_collection_(this),
scheduled_timeout_(base::TimeTicks()), scheduled_timeout_(base::TimeTicks()),
allow_locks_to_extend_timeout_(false), allow_locks_to_extend_timeout_(false),
...@@ -165,6 +168,9 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id, ...@@ -165,6 +168,9 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
settings.disallow_non_exact_resource_reuse = settings.disallow_non_exact_resource_reuse =
command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse); command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
settings.wait_for_all_pipeline_stages_before_draw =
command_line->HasSwitch(cc::switches::kRunAllCompositorStagesBeforeDraw);
base::TimeTicks before_create = base::TimeTicks::Now(); base::TimeTicks before_create = base::TimeTicks::Now();
animation_host_ = cc::AnimationHost::CreateMainInstance(); animation_host_ = cc::AnimationHost::CreateMainInstance();
...@@ -438,6 +444,34 @@ scoped_refptr<CompositorVSyncManager> Compositor::vsync_manager() const { ...@@ -438,6 +444,34 @@ scoped_refptr<CompositorVSyncManager> Compositor::vsync_manager() const {
return vsync_manager_; return vsync_manager_;
} }
void Compositor::IssueExternalBeginFrame(const viz::BeginFrameArgs& args) {
DCHECK(external_begin_frames_enabled_);
if (context_factory_private_)
context_factory_private_->IssueExternalBeginFrame(this, args);
}
void Compositor::SetExternalBeginFrameClient(ExternalBeginFrameClient* client) {
DCHECK(external_begin_frames_enabled_);
external_begin_frame_client_ = client;
if (needs_external_begin_frames_)
external_begin_frame_client_->OnNeedsExternalBeginFrames(true);
}
void Compositor::OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) {
DCHECK(external_begin_frames_enabled_);
if (external_begin_frame_client_)
external_begin_frame_client_->OnDisplayDidFinishFrame(ack);
}
void Compositor::OnNeedsExternalBeginFrames(bool needs_begin_frames) {
DCHECK(external_begin_frames_enabled_);
if (external_begin_frame_client_) {
external_begin_frame_client_->OnNeedsExternalBeginFrames(
needs_begin_frames);
}
needs_external_begin_frames_ = needs_begin_frames;
}
void Compositor::AddObserver(CompositorObserver* observer) { void Compositor::AddObserver(CompositorObserver* observer) {
observer_list_.AddObserver(observer); observer_list_.AddObserver(observer);
} }
......
...@@ -69,6 +69,7 @@ namespace ui { ...@@ -69,6 +69,7 @@ namespace ui {
class Compositor; class Compositor;
class CompositorVSyncManager; class CompositorVSyncManager;
class ExternalBeginFrameClient;
class LatencyInfo; class LatencyInfo;
class Layer; class Layer;
class Reflector; class Reflector;
...@@ -133,6 +134,8 @@ class COMPOSITOR_EXPORT ContextFactoryPrivate { ...@@ -133,6 +134,8 @@ class COMPOSITOR_EXPORT ContextFactoryPrivate {
virtual void SetDisplayVSyncParameters(ui::Compositor* compositor, virtual void SetDisplayVSyncParameters(ui::Compositor* compositor,
base::TimeTicks timebase, base::TimeTicks timebase,
base::TimeDelta interval) = 0; base::TimeDelta interval) = 0;
virtual void IssueExternalBeginFrame(ui::Compositor* compositor,
const viz::BeginFrameArgs& args) = 0;
virtual void SetOutputIsSecure(Compositor* compositor, bool secure) = 0; virtual void SetOutputIsSecure(Compositor* compositor, bool secure) = 0;
}; };
...@@ -188,7 +191,8 @@ class COMPOSITOR_EXPORT Compositor ...@@ -188,7 +191,8 @@ class COMPOSITOR_EXPORT Compositor
ui::ContextFactory* context_factory, ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private, ui::ContextFactoryPrivate* context_factory_private,
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
bool enable_surface_synchronization); bool enable_surface_synchronization,
bool external_begin_frames_enabled = false);
~Compositor() override; ~Compositor() override;
ui::ContextFactory* context_factory() { return context_factory_; } ui::ContextFactory* context_factory() { return context_factory_; }
...@@ -291,6 +295,24 @@ class COMPOSITOR_EXPORT Compositor ...@@ -291,6 +295,24 @@ class COMPOSITOR_EXPORT Compositor
// Returns the vsync manager for this compositor. // Returns the vsync manager for this compositor.
scoped_refptr<CompositorVSyncManager> vsync_manager() const; scoped_refptr<CompositorVSyncManager> vsync_manager() const;
bool external_begin_frames_enabled() {
return external_begin_frames_enabled_;
}
void SetExternalBeginFrameClient(ExternalBeginFrameClient* client);
// The ExternalBeginFrameClient calls this to issue a BeginFrame with the
// given |args|.
void IssueExternalBeginFrame(const viz::BeginFrameArgs& args);
// Called by the ContextFactory when a BeginFrame was completed by the Display
// if the enable_external_begin_frames setting is true.
void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack);
// Called by the ContextFactory to signal whether BeginFrames are needed by
// the compositor if the enable_external_begin_frames setting is true.
void OnNeedsExternalBeginFrames(bool needs_begin_frames);
// Returns the main thread task runner this compositor uses. Users of the // Returns the main thread task runner this compositor uses. Users of the
// compositor generally shouldn't use this. // compositor generally shouldn't use this.
scoped_refptr<base::SingleThreadTaskRunner> task_runner() const { scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
...@@ -421,6 +443,10 @@ class COMPOSITOR_EXPORT Compositor ...@@ -421,6 +443,10 @@ class COMPOSITOR_EXPORT Compositor
// The manager of vsync parameters for this compositor. // The manager of vsync parameters for this compositor.
scoped_refptr<CompositorVSyncManager> vsync_manager_; scoped_refptr<CompositorVSyncManager> vsync_manager_;
bool external_begin_frames_enabled_;
ExternalBeginFrameClient* external_begin_frame_client_ = nullptr;
bool needs_external_begin_frames_ = false;
// The device scale factor of the monitor that this compositor is compositing // The device scale factor of the monitor that this compositor is compositing
// layers on. // layers on.
float device_scale_factor_ = 0.f; float device_scale_factor_ = 0.f;
......
// Copyright (c) 2017 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 UI_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CLIENT_H_
#define UI_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CLIENT_H_
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "ui/compositor/compositor_export.h"
namespace ui {
class COMPOSITOR_EXPORT ExternalBeginFrameClient {
public:
virtual ~ExternalBeginFrameClient() {}
virtual void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) = 0;
virtual void OnNeedsExternalBeginFrames(bool needs_begin_frames) = 0;
};
} // namespace ui
#endif // UI_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CLIENT_H_
...@@ -83,6 +83,8 @@ class InProcessContextFactory : public ContextFactory, ...@@ -83,6 +83,8 @@ class InProcessContextFactory : public ContextFactory,
void SetDisplayVSyncParameters(ui::Compositor* compositor, void SetDisplayVSyncParameters(ui::Compositor* compositor,
base::TimeTicks timebase, base::TimeTicks timebase,
base::TimeDelta interval) override {} base::TimeDelta interval) override {}
void IssueExternalBeginFrame(ui::Compositor* compositor,
const viz::BeginFrameArgs& args) override {}
void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override {} void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override {}
const viz::ResourceSettings& GetResourceSettings() const override; const viz::ResourceSettings& GetResourceSettings() const override;
void AddObserver(ContextFactoryObserver* observer) override; void AddObserver(ContextFactoryObserver* observer) override;
......
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