blob: 01da461eb77c4fb31d5ad3eed940c418001f8669 [file] [log] [blame]
// Copyright 2013 The Flutter 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 "flutter/flow/layers/texture_layer.h"
#include "flutter/flow/testing/diff_context_test.h"
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/flow/testing/mock_texture.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/display_list_testing.h"
namespace flutter {
namespace testing {
using TextureLayerTest = LayerTest;
TEST_F(TextureLayerTest, InvalidTexture) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize layer_size = SkSize::Make(8.0f, 8.0f);
auto layer = std::make_shared<TextureLayer>(
layer_offset, layer_size, 0, false, DlImageSampling::kNearestNeighbor);
layer->Preroll(preroll_context());
EXPECT_EQ(layer->paint_bounds(),
(SkRect::MakeSize(layer_size)
.makeOffset(layer_offset.fX, layer_offset.fY)));
EXPECT_TRUE(layer->needs_painting(paint_context()));
layer->Paint(display_list_paint_context());
EXPECT_TRUE(display_list()->Equals(DisplayList()));
}
#ifndef NDEBUG
TEST_F(TextureLayerTest, PaintingEmptyLayerDies) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize layer_size = SkSize::Make(0.0f, 0.0f);
const int64_t texture_id = 0;
auto mock_texture = std::make_shared<MockTexture>(texture_id);
auto layer =
std::make_shared<TextureLayer>(layer_offset, layer_size, texture_id,
false, DlImageSampling::kNearestNeighbor);
// Ensure the texture is located by the Layer.
preroll_context()->texture_registry->RegisterTexture(mock_texture);
layer->Preroll(preroll_context());
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
EXPECT_FALSE(layer->needs_painting(paint_context()));
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
"needs_painting\\(context\\)");
}
TEST_F(TextureLayerTest, PaintBeforePrerollDies) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize layer_size = SkSize::Make(8.0f, 8.0f);
const int64_t texture_id = 0;
auto mock_texture = std::make_shared<MockTexture>(texture_id);
auto layer = std::make_shared<TextureLayer>(
layer_offset, layer_size, texture_id, false, DlImageSampling::kLinear);
// Ensure the texture is located by the Layer.
preroll_context()->texture_registry->RegisterTexture(mock_texture);
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
"needs_painting\\(context\\)");
}
#endif
TEST_F(TextureLayerTest, PaintingWithLinearSampling) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize layer_size = SkSize::Make(8.0f, 8.0f);
const SkRect layer_bounds =
SkRect::MakeSize(layer_size).makeOffset(layer_offset.fX, layer_offset.fY);
const int64_t texture_id = 0;
const auto texture_image = MockTexture::MakeTestTexture(20, 20, 5);
auto mock_texture = std::make_shared<MockTexture>(texture_id, texture_image);
auto layer = std::make_shared<TextureLayer>(
layer_offset, layer_size, texture_id, false, DlImageSampling::kLinear);
// Ensure the texture is located by the Layer.
preroll_context()->texture_registry->RegisterTexture(mock_texture);
layer->Preroll(preroll_context());
EXPECT_EQ(layer->paint_bounds(), layer_bounds);
EXPECT_TRUE(layer->needs_painting(paint_context()));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Texture)layer::Paint */ {
expected_builder.DrawImageRect(texture_image, layer_bounds,
DlImageSampling::kLinear);
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
using TextureLayerDiffTest = DiffContextTest;
TEST_F(TextureLayerDiffTest, TextureInRetainedLayer) {
MockLayerTree tree1;
auto container = std::make_shared<ContainerLayer>();
tree1.root()->Add(container);
auto layer = std::make_shared<TextureLayer>(SkPoint::Make(0, 0),
SkSize::Make(100, 100), 0, false,
DlImageSampling::kLinear);
container->Add(layer);
MockLayerTree tree2;
tree2.root()->Add(container); // retained layer
auto damage = DiffLayerTree(tree1, MockLayerTree());
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 100, 100));
damage = DiffLayerTree(tree2, tree1);
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 100, 100));
}
TEST_F(TextureLayerTest, OpacityInheritance) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize layer_size = SkSize::Make(8.0f, 8.0f);
const SkRect layer_bounds =
SkRect::MakeSize(layer_size).makeOffset(layer_offset.fX, layer_offset.fY);
const int64_t texture_id = 0;
const auto texture_image = MockTexture::MakeTestTexture(20, 20, 5);
auto mock_texture = std::make_shared<MockTexture>(texture_id, texture_image);
SkAlpha alpha = 0x7f;
auto texture_layer = std::make_shared<TextureLayer>(
layer_offset, layer_size, texture_id, false, DlImageSampling::kLinear);
auto layer = std::make_shared<OpacityLayer>(alpha, SkPoint::Make(0.0f, 0.0f));
layer->Add(texture_layer);
// Ensure the texture is located by the Layer.
PrerollContext* context = preroll_context();
context->texture_registry->RegisterTexture(mock_texture);
// The texture layer always reports opacity compatibility.
texture_layer->Preroll(context);
EXPECT_EQ(context->renderable_state_flags,
LayerStateStack::kCallerCanApplyOpacity);
// Reset has_texture_layer since it is not supposed to be sent as we
// descend a tree in Preroll, but it was set by the previous test.
context->has_texture_layer = false;
layer->Preroll(context);
EXPECT_EQ(context->renderable_state_flags,
LayerStateStack::kCallerCanApplyOpacity);
DlPaint texture_paint;
texture_paint.setAlpha(alpha);
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Opacity)layer::Paint */ {
expected_builder.Save();
{
/* texture_layer::Paint */ {
expected_builder.DrawImageRect(texture_image, layer_bounds,
DlImageSampling::kLinear,
&texture_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
} // namespace testing
} // namespace flutter