Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions display_list/dl_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ class DisplayListBuilder final : public virtual DlCanvas,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
using DlCanvas::DrawImageRect;
// |DlCanvas|
void DrawImageNine(const sk_sp<DlImage>& image,
const SkIRect& center,
Expand Down
70 changes: 49 additions & 21 deletions flow/layers/texture_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/flow/testing/mock_texture.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
#include "flutter/testing/display_list_testing.h"

namespace flutter {
namespace testing {
Expand All @@ -28,8 +28,8 @@ TEST_F(TextureLayerTest, InvalidTexture) {
.makeOffset(layer_offset.fX, layer_offset.fY)));
EXPECT_TRUE(layer->needs_painting(paint_context()));

layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(), std::vector<MockCanvas::DrawCall>());
layer->Paint(display_list_paint_context());
EXPECT_TRUE(display_list()->Equals(DisplayList()));
}

#ifndef NDEBUG
Expand Down Expand Up @@ -72,26 +72,28 @@ TEST_F(TextureLayerTest, PaintBeforePrerollDies) {
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;
auto mock_texture = std::make_shared<MockTexture>(texture_id);
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(),
(SkRect::MakeSize(layer_size)
.makeOffset(layer_offset.fX, layer_offset.fY)));
EXPECT_EQ(layer->paint_bounds(), layer_bounds);
EXPECT_TRUE(layer->needs_painting(paint_context()));

layer->Paint(paint_context());
EXPECT_EQ(mock_texture->paint_calls(),
std::vector({MockTexture::PaintCall{
mock_canvas(), layer->paint_bounds(), false, nullptr,
DlImageSampling::kLinear}}));
EXPECT_EQ(mock_canvas().draw_calls(), std::vector<MockCanvas::DrawCall>());
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;
Expand All @@ -118,24 +120,50 @@ TEST_F(TextureLayerDiffTest, TextureInRetainedLayer) {
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;
auto mock_texture = std::make_shared<MockTexture>(texture_id);
auto layer = std::make_shared<TextureLayer>(
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.
preroll_context()->texture_registry->RegisterTexture(mock_texture);

// The texture layer always reports opacity compatibility.
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);

// MockTexture has no actual textur to render into the
// PaintContext canvas so we have no way to verify its
// rendering.
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
Expand Down
46 changes: 30 additions & 16 deletions flow/testing/mock_texture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,41 @@
namespace flutter {
namespace testing {

MockTexture::MockTexture(int64_t textureId) : Texture(textureId) {}
sk_sp<DlImage> MockTexture::MakeTestTexture(int w, int h, int checker_size) {
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(w, h);
SkCanvas* canvas = surface->getCanvas();
SkPaint p0, p1;
p0.setStyle(SkPaint::kFill_Style);
p0.setColor(SK_ColorGREEN);
p1.setStyle(SkPaint::kFill_Style);
p1.setColor(SK_ColorBLUE);
p1.setAlpha(128);
for (int y = 0; y < w; y += checker_size) {
for (int x = 0; x < h; x += checker_size) {
SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1;
canvas->drawRect(SkRect::MakeXYWH(x, y, checker_size, checker_size),
cellp);
}
}
return DlImage::Make(surface->makeImageSnapshot());
}

MockTexture::MockTexture(int64_t textureId, const sk_sp<DlImage>& texture)
: Texture(textureId), texture_(texture) {}

void MockTexture::Paint(PaintContext& context,
const SkRect& bounds,
bool freeze,
const DlImageSampling sampling) {
paint_calls_.emplace_back(PaintCall{*(context.canvas), bounds, freeze,
context.gr_context, sampling,
context.paint});
}

bool operator==(const MockTexture::PaintCall& a,
const MockTexture::PaintCall& b) {
return &a.canvas == &b.canvas && a.bounds == b.bounds &&
a.context == b.context && a.freeze == b.freeze &&
a.sampling == b.sampling && a.paint == b.paint;
}

std::ostream& operator<<(std::ostream& os, const MockTexture::PaintCall& data) {
return os << &data.canvas << " " << data.bounds << " " << data.context << " "
<< data.freeze << " " << data.sampling << " " << data.paint;
// MockTexture objects that are not painted are allowed to have a null
// texture, but when we get to this method we must have a non-null texture.
FML_DCHECK(texture_ != nullptr);
SkRect src = SkRect::Make(texture_->bounds());
if (freeze) {
FML_DCHECK(src.width() > 2.0f && src.height() > 2.0f);
src = src.makeInset(1.0f, 1.0f);
}
context.canvas->DrawImageRect(texture_, src, bounds, sampling, context.paint);
}

} // namespace testing
Expand Down
20 changes: 4 additions & 16 deletions flow/testing/mock_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,10 @@ namespace testing {
// later verify them against expected data.
class MockTexture : public Texture {
public:
struct PaintCall {
DlCanvas& canvas;
SkRect bounds;
bool freeze;
GrDirectContext* context;
DlImageSampling sampling;
const DlPaint* paint;
};
static sk_sp<DlImage> MakeTestTexture(int w, int h, int checker_size);

explicit MockTexture(int64_t textureId);
explicit MockTexture(int64_t textureId,
const sk_sp<DlImage>& texture = nullptr);

// Called from raster thread.
void Paint(PaintContext& context,
Expand All @@ -41,23 +35,17 @@ class MockTexture : public Texture {
void MarkNewFrameAvailable() override {}
void OnTextureUnregistered() override { unregistered_ = true; }

const std::vector<PaintCall>& paint_calls() { return paint_calls_; }
bool gr_context_created() { return gr_context_created_; }
bool gr_context_destroyed() { return gr_context_destroyed_; }
bool unregistered() { return unregistered_; }

private:
std::vector<PaintCall> paint_calls_;
sk_sp<DlImage> texture_;
bool gr_context_created_ = false;
bool gr_context_destroyed_ = false;
bool unregistered_ = false;
};

extern bool operator==(const MockTexture::PaintCall& a,
const MockTexture::PaintCall& b);
extern std::ostream& operator<<(std::ostream& os,
const MockTexture::PaintCall& data);

} // namespace testing
} // namespace flutter

Expand Down
45 changes: 30 additions & 15 deletions flow/testing/mock_texture_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

#include "flutter/flow/testing/mock_texture.h"

#include "flutter/testing/mock_canvas.h"
#include "flutter/display_list/dl_builder.h"
#include "flutter/testing/display_list_testing.h"
#include "gtest/gtest.h"

namespace flutter {
Expand All @@ -27,37 +28,51 @@ TEST(MockTextureTest, Callbacks) {
}

TEST(MockTextureTest, PaintCalls) {
MockCanvas canvas;
DisplayListBuilder builder;
const SkRect paint_bounds1 = SkRect::MakeWH(1.0f, 1.0f);
const SkRect paint_bounds2 = SkRect::MakeWH(2.0f, 2.0f);
const DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
const auto expected_paint_calls = std::vector{
MockTexture::PaintCall{canvas, paint_bounds1, false, nullptr, sampling},
MockTexture::PaintCall{canvas, paint_bounds2, true, nullptr, sampling}};
auto texture = std::make_shared<MockTexture>(0);
const auto texture_image = MockTexture::MakeTestTexture(20, 20, 5);
auto texture = std::make_shared<MockTexture>(0, texture_image);

Texture::PaintContext context{
.canvas = &canvas,
.canvas = &builder,
};
texture->Paint(context, paint_bounds1, false, sampling);
texture->Paint(context, paint_bounds2, true, sampling);
EXPECT_EQ(texture->paint_calls(), expected_paint_calls);

SkRect src1 = SkRect::Make(texture_image->bounds());
SkRect src2 = src1.makeInset(1.0, 1.0f);

DisplayListBuilder expected_builder;
expected_builder.DrawImageRect(texture_image, src1, paint_bounds1, sampling);
expected_builder.DrawImageRect(texture_image, src2, paint_bounds2, sampling);
EXPECT_TRUE(
DisplayListsEQ_Verbose(builder.Build(), expected_builder.Build()));
}

TEST(MockTextureTest, PaintCallsWithLinearSampling) {
MockCanvas canvas;
DisplayListBuilder builder;
const SkRect paint_bounds1 = SkRect::MakeWH(1.0f, 1.0f);
const SkRect paint_bounds2 = SkRect::MakeWH(2.0f, 2.0f);
const auto sampling = DlImageSampling::kLinear;
const auto expected_paint_calls = std::vector{
MockTexture::PaintCall{canvas, paint_bounds1, false, nullptr, sampling},
MockTexture::PaintCall{canvas, paint_bounds2, true, nullptr, sampling}};
auto texture = std::make_shared<MockTexture>(0);
const auto texture_image = MockTexture::MakeTestTexture(20, 20, 5);
auto texture = std::make_shared<MockTexture>(0, texture_image);

Texture::PaintContext context{
.canvas = &canvas,
.canvas = &builder,
};
texture->Paint(context, paint_bounds1, false, sampling);
texture->Paint(context, paint_bounds2, true, sampling);
EXPECT_EQ(texture->paint_calls(), expected_paint_calls);

SkRect src1 = SkRect::Make(texture_image->bounds());
SkRect src2 = src1.makeInset(1.0, 1.0f);

DisplayListBuilder expected_builder;
expected_builder.DrawImageRect(texture_image, src1, paint_bounds1, sampling);
expected_builder.DrawImageRect(texture_image, src2, paint_bounds2, sampling);
EXPECT_TRUE(
DisplayListsEQ_Verbose(builder.Build(), expected_builder.Build()));
}

} // namespace testing
Expand Down