Commit bab9dddb authored by Dave Tapuska's avatar Dave Tapuska Committed by Commit Bot

Move RenderWidget Swap Time tests to blink.

These histograms are now logged inside blink and the appropriate
tests should move as well.

BUG=1097816

Change-Id: Ic84798cf223bf0dafe73bd813952d6678ba066aa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2461986
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatardanakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816638}
parent 838db947
...@@ -97,23 +97,6 @@ class InteractiveRenderWidget : public RenderWidget { ...@@ -97,23 +97,6 @@ class InteractiveRenderWidget : public RenderWidget {
IPC::TestSink* sink() { return &sink_; } IPC::TestSink* sink() { return &sink_; }
std::unique_ptr<cc::LayerTreeFrameSink> AllocateNewLayerTreeFrameSink()
override {
std::unique_ptr<cc::FakeLayerTreeFrameSink> sink =
cc::FakeLayerTreeFrameSink::Create3d();
last_created_frame_sink_ = sink.get();
return sink;
}
// The returned pointer is valid after RequestNewLayerTreeFrameSink() occurs,
// until another call to RequestNewLayerTreeFrameSink() happens. It's okay to
// use this pointer on the main thread because this class causes the
// compositor to run in single thread mode by returning a null from
// GetCompositorImplThreadTaskRunner().
cc::FakeLayerTreeFrameSink* last_created_frame_sink() {
return last_created_frame_sink_;
}
protected: protected:
bool Send(IPC::Message* msg) override { bool Send(IPC::Message* msg) override {
sink_.OnMessageReceived(*msg); sink_.OnMessageReceived(*msg);
...@@ -124,7 +107,6 @@ class InteractiveRenderWidget : public RenderWidget { ...@@ -124,7 +107,6 @@ class InteractiveRenderWidget : public RenderWidget {
private: private:
IPC::TestSink sink_; IPC::TestSink sink_;
static int next_routing_id_; static int next_routing_id_;
cc::FakeLayerTreeFrameSink* last_created_frame_sink_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget); DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget);
}; };
...@@ -189,16 +171,6 @@ class RenderWidgetUnittest : public testing::Test { ...@@ -189,16 +171,6 @@ class RenderWidgetUnittest : public testing::Test {
InteractiveRenderWidget* widget() const { return widget_.get(); } InteractiveRenderWidget* widget() const { return widget_.get(); }
blink::WebFrameWidget* frame_widget() const { return web_frame_widget_; }
const base::HistogramTester& histogram_tester() const {
return histogram_tester_;
}
cc::FakeLayerTreeFrameSink* GetFrameSink() {
return widget_->last_created_frame_sink();
}
private: private:
base::test::TaskEnvironment task_environment_; base::test::TaskEnvironment task_environment_;
RenderProcess render_process_; RenderProcess render_process_;
...@@ -211,7 +183,6 @@ class RenderWidgetUnittest : public testing::Test { ...@@ -211,7 +183,6 @@ class RenderWidgetUnittest : public testing::Test {
FakeCompositorDependencies compositor_deps_; FakeCompositorDependencies compositor_deps_;
std::unique_ptr<AgentSchedulingGroup> agent_scheduling_group_; std::unique_ptr<AgentSchedulingGroup> agent_scheduling_group_;
std::unique_ptr<InteractiveRenderWidget> widget_; std::unique_ptr<InteractiveRenderWidget> widget_;
base::HistogramTester histogram_tester_;
const bool is_for_nested_main_frame_; const bool is_for_nested_main_frame_;
}; };
...@@ -257,115 +228,4 @@ TEST_F(RenderWidgetUnittest, ForceSendMetadataOnInput) { ...@@ -257,115 +228,4 @@ TEST_F(RenderWidgetUnittest, ForceSendMetadataOnInput) {
} }
#endif // !defined(OS_ANDROID) #endif // !defined(OS_ANDROID)
class NotifySwapTimesRenderWidgetUnittest : public RenderWidgetUnittest {
public:
void SetUp() override {
RenderWidgetUnittest::SetUp();
viz::ParentLocalSurfaceIdAllocator allocator;
// TODO(danakj): This usually happens through
// RenderWidget::UpdateVisualProperties() and we are cutting past that for
// some reason.
allocator.GenerateId();
widget()->layer_tree_host()->SetViewportRectAndScale(
gfx::Rect(200, 100), 1.f, allocator.GetCurrentLocalSurfaceId());
auto root_layer = cc::SolidColorLayer::Create();
root_layer->SetBounds(gfx::Size(200, 100));
root_layer->SetBackgroundColor(SK_ColorGREEN);
widget()->layer_tree_host()->SetRootLayer(root_layer);
auto color_layer = cc::SolidColorLayer::Create();
color_layer->SetBounds(gfx::Size(100, 100));
root_layer->AddChild(color_layer);
color_layer->SetBackgroundColor(SK_ColorRED);
}
// |swap_to_presentation| determines how long after swap should presentation
// happen. This can be negative, positive, or zero. If zero, an invalid (null)
// presentation time is used.
void CompositeAndWaitForPresentation(base::TimeDelta swap_to_presentation) {
base::RunLoop swap_run_loop;
base::RunLoop presentation_run_loop;
// Register callbacks for swap time and presentation time.
base::TimeTicks swap_time;
frame_widget()->NotifySwapAndPresentationTime(
base::BindOnce(
[](base::OnceClosure swap_quit_closure, base::TimeTicks* swap_time,
blink::WebSwapResult result, base::TimeTicks timestamp) {
DCHECK(!timestamp.is_null());
*swap_time = timestamp;
std::move(swap_quit_closure).Run();
},
swap_run_loop.QuitClosure(), &swap_time),
base::BindOnce(
[](base::OnceClosure presentation_quit_closure,
blink::WebSwapResult result, base::TimeTicks timestamp) {
DCHECK(!timestamp.is_null());
std::move(presentation_quit_closure).Run();
},
presentation_run_loop.QuitClosure()));
// Composite and wait for the swap to complete.
widget()->layer_tree_host()->Composite(base::TimeTicks::Now(),
/*raster=*/true);
swap_run_loop.Run();
// Present and wait for it to complete.
viz::FrameTimingDetails timing_details;
if (!swap_to_presentation.is_zero()) {
timing_details.presentation_feedback = gfx::PresentationFeedback(
/*presentation_time=*/swap_time + swap_to_presentation,
base::TimeDelta::FromMilliseconds(16), 0);
}
GetFrameSink()->NotifyDidPresentCompositorFrame(1, timing_details);
presentation_run_loop.Run();
}
};
TEST_F(NotifySwapTimesRenderWidgetUnittest, PresentationTimestampValid) {
base::HistogramTester histograms;
CompositeAndWaitForPresentation(base::TimeDelta::FromMilliseconds(2));
EXPECT_THAT(histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.Valid"),
testing::ElementsAre(base::Bucket(true, 1)));
EXPECT_THAT(
histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
testing::ElementsAre(base::Bucket(2, 1)));
}
TEST_F(NotifySwapTimesRenderWidgetUnittest, PresentationTimestampInvalid) {
base::HistogramTester histograms;
CompositeAndWaitForPresentation(base::TimeDelta());
EXPECT_THAT(histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.Valid"),
testing::ElementsAre(base::Bucket(false, 1)));
EXPECT_THAT(
histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
testing::IsEmpty());
}
TEST_F(NotifySwapTimesRenderWidgetUnittest,
PresentationTimestampEarlierThanSwaptime) {
base::HistogramTester histograms;
CompositeAndWaitForPresentation(base::TimeDelta::FromMilliseconds(-2));
EXPECT_THAT(histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.Valid"),
testing::ElementsAre(base::Bucket(false, 1)));
EXPECT_THAT(
histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
testing::IsEmpty());
}
} // namespace content } // namespace content
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
#include "cc/test/test_ukm_recorder_factory.h" #include "cc/test/test_ukm_recorder_factory.h"
#include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h" #include "cc/trees/layer_tree_settings.h"
...@@ -776,6 +775,11 @@ ScreenInfo TestWebWidgetClient::GetInitialScreenInfo() { ...@@ -776,6 +775,11 @@ ScreenInfo TestWebWidgetClient::GetInitialScreenInfo() {
return ScreenInfo(); return ScreenInfo();
} }
cc::FakeLayerTreeFrameSink* TestWebWidgetClient::LastCreatedFrameSink() {
DCHECK(layer_tree_host_->IsSingleThreaded());
return last_created_frame_sink_;
}
mojo::PendingAssociatedRemote<mojom::blink::WidgetHost> mojo::PendingAssociatedRemote<mojom::blink::WidgetHost>
TestWebWidgetClient::BindNewWidgetHost() { TestWebWidgetClient::BindNewWidgetHost() {
receiver_.reset(); receiver_.reset();
...@@ -792,7 +796,10 @@ viz::FrameSinkId TestWebWidgetClient::GetFrameSinkId() { ...@@ -792,7 +796,10 @@ viz::FrameSinkId TestWebWidgetClient::GetFrameSinkId() {
std::unique_ptr<cc::LayerTreeFrameSink> std::unique_ptr<cc::LayerTreeFrameSink>
TestWebWidgetClient::AllocateNewLayerTreeFrameSink() { TestWebWidgetClient::AllocateNewLayerTreeFrameSink() {
return cc::FakeLayerTreeFrameSink::Create3d(); std::unique_ptr<cc::FakeLayerTreeFrameSink> sink =
cc::FakeLayerTreeFrameSink::Create3d();
last_created_frame_sink_ = sink.get();
return sink;
} }
void TestWebWidgetClient::WillQueueSyntheticEvent( void TestWebWidgetClient::WillQueueSyntheticEvent(
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
#include "cc/test/test_task_graph_runner.h" #include "cc/test/test_task_graph_runner.h"
#include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host.h"
#include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/frame_sink_id.h"
...@@ -222,6 +223,12 @@ class TestWebWidgetClient : public WebWidgetClient, ...@@ -222,6 +223,12 @@ class TestWebWidgetClient : public WebWidgetClient,
layer_tree_host_ = layer_tree_host; layer_tree_host_ = layer_tree_host;
} }
// The returned pointer is valid after AllocateNewLayerTreeFrameSink() occurs,
// until another call to AllocateNewLayerTreeFrameSink() happens. This
// pointer is valid to use from the main thread for tests that use a single
// threaded compositor, such as SimCompositor tests.
cc::FakeLayerTreeFrameSink* LastCreatedFrameSink();
virtual ScreenInfo GetInitialScreenInfo(); virtual ScreenInfo GetInitialScreenInfo();
mojo::PendingAssociatedRemote<mojom::blink::WidgetHost> BindNewWidgetHost(); mojo::PendingAssociatedRemote<mojom::blink::WidgetHost> BindNewWidgetHost();
...@@ -266,6 +273,7 @@ class TestWebWidgetClient : public WebWidgetClient, ...@@ -266,6 +273,7 @@ class TestWebWidgetClient : public WebWidgetClient,
WebFrameWidget* frame_widget_ = nullptr; WebFrameWidget* frame_widget_ = nullptr;
cc::LayerTreeHost* layer_tree_host_ = nullptr; cc::LayerTreeHost* layer_tree_host_ = nullptr;
cc::TestTaskGraphRunner test_task_graph_runner_; cc::TestTaskGraphRunner test_task_graph_runner_;
cc::FakeLayerTreeFrameSink* last_created_frame_sink_ = nullptr;
blink::scheduler::WebFakeThreadScheduler fake_thread_scheduler_; blink::scheduler::WebFakeThreadScheduler fake_thread_scheduler_;
Vector<std::unique_ptr<blink::WebCoalescedInputEvent>> Vector<std::unique_ptr<blink::WebCoalescedInputEvent>>
injected_scroll_events_; injected_scroll_events_;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
#include "cc/layers/solid_color_layer.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h" #include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
...@@ -378,4 +379,113 @@ TEST_F(WebViewFrameWidgetSimTest, SendElasticOverscrollForTouchscreen) { ...@@ -378,4 +379,113 @@ TEST_F(WebViewFrameWidgetSimTest, SendElasticOverscrollForTouchscreen) {
SendInputEvent(scroll, base::DoNothing()); SendInputEvent(scroll, base::DoNothing());
} }
class NotifySwapTimesWebFrameWidgetTest : public SimTest {
public:
void SetUp() override {
SimTest::SetUp();
WebView().StopDeferringMainFrameUpdate();
FrameWidgetBase()->UpdateCompositorViewportRect(gfx::Rect(200, 100));
auto root_layer = cc::SolidColorLayer::Create();
root_layer->SetBounds(gfx::Size(200, 100));
root_layer->SetBackgroundColor(SK_ColorGREEN);
FrameWidgetBase()->LayerTreeHost()->SetRootLayer(root_layer);
auto color_layer = cc::SolidColorLayer::Create();
color_layer->SetBounds(gfx::Size(100, 100));
root_layer->AddChild(color_layer);
color_layer->SetBackgroundColor(SK_ColorRED);
}
WebViewFrameWidget* FrameWidgetBase() {
return static_cast<WebViewFrameWidget*>(MainFrame().FrameWidget());
}
// |swap_to_presentation| determines how long after swap should presentation
// happen. This can be negative, positive, or zero. If zero, an invalid (null)
// presentation time is used.
void CompositeAndWaitForPresentation(base::TimeDelta swap_to_presentation) {
base::RunLoop swap_run_loop;
base::RunLoop presentation_run_loop;
// Register callbacks for swap time and presentation time.
base::TimeTicks swap_time;
MainFrame().FrameWidget()->NotifySwapAndPresentationTime(
base::BindOnce(
[](base::OnceClosure swap_quit_closure, base::TimeTicks* swap_time,
blink::WebSwapResult result, base::TimeTicks timestamp) {
DCHECK(!timestamp.is_null());
*swap_time = timestamp;
std::move(swap_quit_closure).Run();
},
swap_run_loop.QuitClosure(), &swap_time),
base::BindOnce(
[](base::OnceClosure presentation_quit_closure,
blink::WebSwapResult result, base::TimeTicks timestamp) {
DCHECK(!timestamp.is_null());
std::move(presentation_quit_closure).Run();
},
presentation_run_loop.QuitClosure()));
// Composite and wait for the swap to complete.
Compositor().BeginFrame(/*time_delta_in_seconds=*/0.016, /*raster=*/true);
swap_run_loop.Run();
// Present and wait for it to complete.
viz::FrameTimingDetails timing_details;
if (!swap_to_presentation.is_zero()) {
timing_details.presentation_feedback = gfx::PresentationFeedback(
/*presentation_time=*/swap_time + swap_to_presentation,
base::TimeDelta::FromMilliseconds(16), 0);
}
auto* last_frame_sink = WebWidgetClient().LastCreatedFrameSink();
last_frame_sink->NotifyDidPresentCompositorFrame(1, timing_details);
presentation_run_loop.Run();
}
};
TEST_F(NotifySwapTimesWebFrameWidgetTest, PresentationTimestampValid) {
base::HistogramTester histograms;
CompositeAndWaitForPresentation(base::TimeDelta::FromMilliseconds(2));
EXPECT_THAT(histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.Valid"),
testing::ElementsAre(base::Bucket(true, 1)));
EXPECT_THAT(
histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
testing::ElementsAre(base::Bucket(2, 1)));
}
TEST_F(NotifySwapTimesWebFrameWidgetTest, PresentationTimestampInvalid) {
base::HistogramTester histograms;
CompositeAndWaitForPresentation(base::TimeDelta());
EXPECT_THAT(histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.Valid"),
testing::ElementsAre(base::Bucket(false, 1)));
EXPECT_THAT(
histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
testing::IsEmpty());
}
TEST_F(NotifySwapTimesWebFrameWidgetTest,
PresentationTimestampEarlierThanSwaptime) {
base::HistogramTester histograms;
CompositeAndWaitForPresentation(base::TimeDelta::FromMilliseconds(-2));
EXPECT_THAT(histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.Valid"),
testing::ElementsAre(base::Bucket(false, 1)));
EXPECT_THAT(
histograms.GetAllSamples(
"PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"),
testing::IsEmpty());
}
} // namespace blink } // namespace blink
...@@ -579,4 +579,9 @@ void WebViewFrameWidget::UpdateSurfaceAndCompositorRect( ...@@ -579,4 +579,9 @@ void WebViewFrameWidget::UpdateSurfaceAndCompositorRect(
compositor_viewport_pixel_rect); compositor_viewport_pixel_rect);
} }
void WebViewFrameWidget::UpdateCompositorViewportRect(
const gfx::Rect& compositor_viewport_pixel_rect) {
widget_base_->UpdateCompositorViewportRect(compositor_viewport_pixel_rect);
}
} // namespace blink } // namespace blink
...@@ -149,6 +149,8 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase { ...@@ -149,6 +149,8 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
void UpdateSurfaceAndCompositorRect( void UpdateSurfaceAndCompositorRect(
const viz::LocalSurfaceId& new_local_surface_id, const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Rect& compositor_viewport_pixel_rect); const gfx::Rect& compositor_viewport_pixel_rect);
void UpdateCompositorViewportRect(
const gfx::Rect& compositor_viewport_pixel_rect);
void SetIsNestedMainFrameWidget(bool is_nested); void SetIsNestedMainFrameWidget(bool is_nested);
void DidAutoResize(const gfx::Size& size); void DidAutoResize(const gfx::Size& size);
void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space); void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
......
...@@ -34,7 +34,8 @@ void SimCompositor::SetWebView( ...@@ -34,7 +34,8 @@ void SimCompositor::SetWebView(
test_web_view_client_ = &view_client; test_web_view_client_ = &view_client;
} }
SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) { SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds,
bool raster) {
DCHECK(web_view_); DCHECK(web_view_);
DCHECK(!layer_tree_host()->defer_main_frame_update()); DCHECK(!layer_tree_host()->defer_main_frame_update());
// Verify that the need for a BeginMainFrame has been registered, and would // Verify that the need for a BeginMainFrame has been registered, and would
...@@ -49,8 +50,7 @@ SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) { ...@@ -49,8 +50,7 @@ SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) {
SimCanvas::Commands commands; SimCanvas::Commands commands;
paint_commands_ = &commands; paint_commands_ = &commands;
layer_tree_host()->Composite(last_frame_time_, layer_tree_host()->Composite(last_frame_time_, raster);
/*raster=*/false);
paint_commands_ = nullptr; paint_commands_ = nullptr;
return commands; return commands;
......
...@@ -45,7 +45,9 @@ class SimCompositor final : public frame_test_helpers::TestWebWidgetClient { ...@@ -45,7 +45,9 @@ class SimCompositor final : public frame_test_helpers::TestWebWidgetClient {
// Returns all drawing commands that were issued during painting the frame // Returns all drawing commands that were issued during painting the frame
// (including cached ones). // (including cached ones).
// TODO(dcheng): This should take a base::TimeDelta. // TODO(dcheng): This should take a base::TimeDelta.
SimCanvas::Commands BeginFrame(double time_delta_in_seconds = 0.016); // Rasterization of tiles is only performed when |raster| is true.
SimCanvas::Commands BeginFrame(double time_delta_in_seconds = 0.016,
bool raster = false);
// Similar to BeginFrame() but doesn't require NeedsBeginFrame(). This is // Similar to BeginFrame() but doesn't require NeedsBeginFrame(). This is
// useful for testing the painting after a frame is throttled (for which // useful for testing the painting after a frame is throttled (for which
......
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