blob: eabe1909a4f4443cdc0b40fd2e3e00c4c92497db [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 <stddef.h>
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_op_buffer.h"
#include "cc/test/layer_tree_pixel_test.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/test/test_layer_tree_frame_sink.h"
#include "gpu/command_buffer/client/raster_interface.h"
#if !defined(OS_ANDROID)
namespace cc {
namespace {
enum RasterMode {
PARTIAL_ONE_COPY,
FULL_ONE_COPY,
PARTIAL_GPU,
FULL_GPU,
PARTIAL_GPU_LOW_BIT_DEPTH,
FULL_GPU_LOW_BIT_DEPTH,
PARTIAL_BITMAP,
FULL_BITMAP,
};
class LayerTreeHostTilesPixelTest : public LayerTreePixelTest {
protected:
void InitializeSettings(LayerTreeSettings* settings) override {
LayerTreePixelTest::InitializeSettings(settings);
switch (raster_mode_) {
case PARTIAL_ONE_COPY:
settings->use_zero_copy = false;
settings->use_partial_raster = true;
break;
case FULL_ONE_COPY:
settings->use_zero_copy = false;
settings->use_partial_raster = false;
break;
case PARTIAL_BITMAP:
settings->use_partial_raster = true;
break;
case FULL_BITMAP:
settings->use_partial_raster = false;
break;
case PARTIAL_GPU:
settings->gpu_rasterization_forced = true;
settings->use_partial_raster = true;
break;
case FULL_GPU:
settings->gpu_rasterization_forced = true;
settings->use_partial_raster = false;
break;
case PARTIAL_GPU_LOW_BIT_DEPTH:
settings->gpu_rasterization_forced = true;
settings->use_partial_raster = true;
settings->use_rgba_4444 = true;
settings->unpremultiply_and_dither_low_bit_depth_tiles = true;
break;
case FULL_GPU_LOW_BIT_DEPTH:
settings->gpu_rasterization_forced = true;
settings->use_partial_raster = false;
settings->use_rgba_4444 = true;
settings->unpremultiply_and_dither_low_bit_depth_tiles = true;
break;
}
}
void BeginTest() override {
// Don't set up a readback target at the start of the test.
PostSetNeedsCommitToMainThread();
}
void DoReadback() {
Layer* target =
readback_target_ ? readback_target_ : layer_tree_host()->root_layer();
target->RequestCopyOfOutput(CreateCopyOutputRequest());
}
void RunRasterPixelTest(bool threaded,
RasterMode mode,
scoped_refptr<Layer> content_root,
base::FilePath file_name) {
raster_mode_ = mode;
PixelTestType test_type = PIXEL_TEST_SOFTWARE;
switch (mode) {
case PARTIAL_ONE_COPY:
case FULL_ONE_COPY:
case PARTIAL_GPU:
case FULL_GPU:
case PARTIAL_GPU_LOW_BIT_DEPTH:
case FULL_GPU_LOW_BIT_DEPTH:
test_type = PIXEL_TEST_GL;
break;
case PARTIAL_BITMAP:
case FULL_BITMAP:
test_type = PIXEL_TEST_SOFTWARE;
}
if (threaded)
RunPixelTest(test_type, content_root, file_name);
else
RunSingleThreadedPixelTest(test_type, content_root, file_name);
}
base::FilePath ref_file_;
std::unique_ptr<SkBitmap> result_bitmap_;
RasterMode raster_mode_;
};
class BlueYellowClient : public ContentLayerClient {
public:
explicit BlueYellowClient(const gfx::Size& size)
: size_(size), blue_top_(true) {}
gfx::Rect PaintableRegion() override { return gfx::Rect(size_); }
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
PaintingControlSetting painting_status) override {
auto display_list = base::MakeRefCounted<DisplayItemList>();
display_list->StartPaint();
gfx::Rect top(0, 0, size_.width(), size_.height() / 2);
gfx::Rect bottom(0, size_.height() / 2, size_.width(), size_.height() / 2);
gfx::Rect blue_rect = blue_top_ ? top : bottom;
gfx::Rect yellow_rect = blue_top_ ? bottom : top;
PaintFlags flags;
flags.setStyle(PaintFlags::kFill_Style);
// Use custom colors with 0xF2 rather than the default blue/yellow (which
// use 0xFF), as the default won't show dither patterns as it exactly maps
// to a 16-bit color.
flags.setColor(SkColorSetRGB(0x00, 0x00, 0xF2));
display_list->push<DrawRectOp>(gfx::RectToSkRect(blue_rect), flags);
flags.setColor(SkColorSetRGB(0xF2, 0xF2, 0x00));
display_list->push<DrawRectOp>(gfx::RectToSkRect(yellow_rect), flags);
display_list->EndPaintOfUnpaired(PaintableRegion());
display_list->Finalize();
return display_list;
}
bool FillsBoundsCompletely() const override { return true; }
size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
void set_blue_top(bool b) { blue_top_ = b; }
private:
gfx::Size size_;
bool blue_top_;
};
class LayerTreeHostTilesTestPartialInvalidation
: public LayerTreeHostTilesPixelTest {
public:
LayerTreeHostTilesTestPartialInvalidation()
: client_(gfx::Size(200, 200)),
picture_layer_(PictureLayer::Create(&client_)) {
picture_layer_->SetBounds(gfx::Size(200, 200));
picture_layer_->SetIsDrawable(true);
}
void DidCommitAndDrawFrame() override {
switch (layer_tree_host()->SourceFrameNumber()) {
case 1:
// We have done one frame, but the resource may not be available for
// partial raster yet. Force a second frame.
picture_layer_->SetNeedsDisplayRect(gfx::Rect(50, 50, 100, 100));
break;
case 2:
// We have done two frames, so the layer's content has been rastered
// twice and the first frame's resource is available for partial
// raster. Now we change the picture behind it to record something
// completely different, but we give a smaller invalidation rect. The
// layer should only re-raster the stuff in the rect. If it doesn't do
// partial raster it would re-raster the whole thing instead.
client_.set_blue_top(false);
Finish();
picture_layer_->SetNeedsDisplayRect(gfx::Rect(50, 50, 100, 100));
// Add a copy request to see what happened!
DoReadback();
break;
}
}
void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override {
// Issue a GL finish before preparing tiles to ensure resources become
// available for use in a timely manner. Needed for the one-copy path.
viz::RasterContextProvider* context_provider =
host_impl->layer_tree_frame_sink()->worker_context_provider();
if (!context_provider)
return;
viz::RasterContextProvider::ScopedRasterContextLock lock(context_provider);
lock.RasterInterface()->Finish();
}
protected:
BlueYellowClient client_;
scoped_refptr<PictureLayer> picture_layer_;
};
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
PartialRaster_SingleThread_OneCopy) {
RunRasterPixelTest(
false, PARTIAL_ONE_COPY, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
FullRaster_SingleThread_OneCopy) {
RunRasterPixelTest(
false, FULL_ONE_COPY, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
PartialRaster_MultiThread_OneCopy) {
RunRasterPixelTest(
true, PARTIAL_ONE_COPY, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
FullRaster_MultiThread_OneCopy) {
RunRasterPixelTest(
true, FULL_ONE_COPY, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
PartialRaster_SingleThread_Software) {
RunRasterPixelTest(
false, PARTIAL_BITMAP, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
FulllRaster_SingleThread_Software) {
RunRasterPixelTest(
false, FULL_BITMAP, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
PartialRaster_SingleThread_GpuRaster) {
RunRasterPixelTest(
false, PARTIAL_GPU, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
FullRaster_SingleThread_GpuRaster) {
RunRasterPixelTest(
false, FULL_GPU, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
PartialRaster_SingleThread_GpuRaster_LowBitDepth) {
RunRasterPixelTest(false, PARTIAL_GPU_LOW_BIT_DEPTH, picture_layer_,
base::FilePath(FILE_PATH_LITERAL(
"blue_yellow_partial_flipped_dither.png")));
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
FullRaster_SingleThread_GpuRaster_LowBitDepth) {
RunRasterPixelTest(
false, FULL_GPU_LOW_BIT_DEPTH, picture_layer_,
base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped_dither.png")));
}
} // namespace
} // namespace cc
#endif // !defined(OS_ANDROID)