blob: d9037435f2bc3cf4e7f6b26d5eeb7a2b87fb9b7e [file] [log] [blame]
// Copyright 2015 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 "base/memory/ptr_util.h"
#include "cc/debug/lap_timer.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/delegated_frame_data.h"
#include "cc/quads/surface_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/surfaces/surface_aggregator.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_manager.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
namespace cc {
namespace {
class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
public:
void ReturnResources(const ReturnedResourceArray& resources) override {}
void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {}
};
class SurfaceAggregatorPerfTest : public testing::Test {
public:
SurfaceAggregatorPerfTest() : factory_(&manager_, &empty_client_) {
output_surface_ = FakeOutputSurface::CreateSoftware(
base::WrapUnique(new SoftwareOutputDevice));
output_surface_->BindToClient(&output_surface_client_);
shared_bitmap_manager_.reset(new TestSharedBitmapManager);
resource_provider_ = FakeResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get());
}
void RunTest(int num_surfaces,
int num_textures,
float opacity,
bool optimize_damage,
bool full_damage,
const std::string& name) {
aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(),
optimize_damage));
for (int i = 1; i <= num_surfaces; i++) {
factory_.Create(SurfaceId(0, i, 0));
std::unique_ptr<RenderPass> pass(RenderPass::Create());
std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
for (int j = 0; j < num_textures; j++) {
TransferableResource resource;
resource.id = j;
resource.is_software = true;
frame_data->resource_list.push_back(resource);
TextureDrawQuad* quad =
pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
const gfx::Rect rect(0, 0, 1, 1);
const gfx::Rect opaque_rect;
// Half of rects should be visible with partial damage.
gfx::Rect visible_rect =
j % 2 == 0 ? gfx::Rect(0, 0, 1, 1) : gfx::Rect(1, 1, 1, 1);
bool needs_blending = false;
bool premultiplied_alpha = false;
const gfx::PointF uv_top_left;
const gfx::PointF uv_bottom_right;
SkColor background_color = SK_ColorGREEN;
const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f};
bool flipped = false;
bool nearest_neighbor = false;
quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, j,
gfx::Size(), premultiplied_alpha, uv_top_left,
uv_bottom_right, background_color, vertex_opacity, flipped,
nearest_neighbor, false);
}
sqs = pass->CreateAndAppendSharedQuadState();
sqs->opacity = opacity;
if (i > 1) {
SurfaceDrawQuad* surface_quad =
pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
SurfaceId(0, i - 1, 0));
}
frame_data->render_pass_list.push_back(std::move(pass));
CompositorFrame frame;
frame.delegated_frame_data = std::move(frame_data);
factory_.SubmitCompositorFrame(SurfaceId(0, i, 0), std::move(frame),
SurfaceFactory::DrawCallback());
}
factory_.Create(SurfaceId(0, num_surfaces + 1, 0));
timer_.Reset();
do {
std::unique_ptr<RenderPass> pass(RenderPass::Create());
std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
SurfaceDrawQuad* surface_quad =
pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(sqs, gfx::Rect(0, 0, 100, 100),
gfx::Rect(0, 0, 100, 100),
SurfaceId(0, num_surfaces, 0));
if (full_damage)
pass->damage_rect = gfx::Rect(0, 0, 100, 100);
else
pass->damage_rect = gfx::Rect(0, 0, 1, 1);
frame_data->render_pass_list.push_back(std::move(pass));
CompositorFrame frame;
frame.delegated_frame_data = std::move(frame_data);
factory_.SubmitCompositorFrame(SurfaceId(0, num_surfaces + 1, 0),
std::move(frame),
SurfaceFactory::DrawCallback());
CompositorFrame aggregated =
aggregator_->Aggregate(SurfaceId(0, num_surfaces + 1, 0));
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
perf_test::PrintResult("aggregator_speed", "", name, timer_.LapsPerSecond(),
"runs/s", true);
factory_.Destroy(SurfaceId(0, num_surfaces + 1, 0));
for (int i = 1; i <= num_surfaces; i++)
factory_.Destroy(SurfaceId(0, i, 0));
}
protected:
SurfaceManager manager_;
EmptySurfaceFactoryClient empty_client_;
SurfaceFactory factory_;
FakeOutputSurfaceClient output_surface_client_;
std::unique_ptr<OutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<ResourceProvider> resource_provider_;
std::unique_ptr<SurfaceAggregator> aggregator_;
LapTimer timer_;
};
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque) {
RunTest(20, 100, 1.f, false, true, "many_surfaces_opaque");
}
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparent) {
RunTest(20, 100, .5f, false, true, "many_surfaces_transparent");
}
TEST_F(SurfaceAggregatorPerfTest, FewSurfaces) {
RunTest(3, 1000, 1.f, false, true, "few_surfaces");
}
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaqueDamageCalc) {
RunTest(20, 100, 1.f, true, true, "many_surfaces_opaque_damage_calc");
}
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparentDamageCalc) {
RunTest(20, 100, .5f, true, true, "many_surfaces_transparent_damage_calc");
}
TEST_F(SurfaceAggregatorPerfTest, FewSurfacesDamageCalc) {
RunTest(3, 1000, 1.f, true, true, "few_surfaces_damage_calc");
}
TEST_F(SurfaceAggregatorPerfTest, FewSurfacesAggregateDamaged) {
RunTest(3, 1000, 1.f, true, false, "few_surfaces_aggregate_damaged");
}
} // namespace
} // namespace cc