[Impeller] Supply a text backend to the AiksContext at runtime. (flutter/engine#44884)
Resolves https://github.com/flutter/flutter/issues/130947. - Allow for setting the text renderer (`TextRenderContext`) when the `AiksContext` is built. Previously, the text renderer was selected at build time through linking a `TextRenderContext::Create` symbol. - Support using Impeller without a text backend. Throw a clear error when trying to render text if no text backend is present. - Don't track the Impeller context in `TextRenderContext`. Just let the renderer supply its context when generating atlases. - Allow for overriding the `TextRenderContext` for individual Aiks playground tests/goldens.
This commit is contained in:
@@ -5,16 +5,19 @@
|
||||
#include "impeller/aiks/aiks_context.h"
|
||||
|
||||
#include "impeller/aiks/picture.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
AiksContext::AiksContext(std::shared_ptr<Context> context)
|
||||
AiksContext::AiksContext(std::shared_ptr<Context> context,
|
||||
std::shared_ptr<TextRenderContext> text_render_context)
|
||||
: context_(std::move(context)) {
|
||||
if (!context_ || !context_->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
content_context_ = std::make_unique<ContentContext>(context_);
|
||||
content_context_ = std::make_unique<ContentContext>(
|
||||
context_, std::move(text_render_context));
|
||||
if (!content_context_->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/renderer/render_target.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@@ -18,7 +19,17 @@ class RenderPass;
|
||||
|
||||
class AiksContext {
|
||||
public:
|
||||
AiksContext(std::shared_ptr<Context> context);
|
||||
/// Construct a new AiksContext.
|
||||
///
|
||||
/// @param context The Impeller context that Aiks should use for
|
||||
/// allocating resources and executing device
|
||||
/// commands. Required.
|
||||
/// @param text_render_context The text backend to use for rendering text. If
|
||||
/// `nullptr` is supplied, then attempting to draw
|
||||
/// text with Aiks will result in validation
|
||||
/// errors.
|
||||
AiksContext(std::shared_ptr<Context> context,
|
||||
std::shared_ptr<TextRenderContext> text_render_context);
|
||||
|
||||
~AiksContext();
|
||||
|
||||
|
||||
@@ -4,16 +4,25 @@
|
||||
|
||||
#include "impeller/aiks/aiks_playground.h"
|
||||
|
||||
#include "impeller/aiks/aiks_context.h"
|
||||
#include <memory>
|
||||
|
||||
#include "impeller/aiks/aiks_context.h"
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
#include "third_party/imgui/imgui.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
AiksPlayground::AiksPlayground() = default;
|
||||
AiksPlayground::AiksPlayground()
|
||||
: text_render_context_(TextRenderContextSkia::Make()) {}
|
||||
|
||||
AiksPlayground::~AiksPlayground() = default;
|
||||
|
||||
void AiksPlayground::SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context) {
|
||||
text_render_context_ = std::move(text_render_context);
|
||||
}
|
||||
|
||||
bool AiksPlayground::OpenPlaygroundHere(const Picture& picture) {
|
||||
return OpenPlaygroundHere(
|
||||
[&picture](AiksContext& renderer, RenderTarget& render_target) -> bool {
|
||||
@@ -26,7 +35,7 @@ bool AiksPlayground::OpenPlaygroundHere(AiksPlaygroundCallback callback) {
|
||||
return true;
|
||||
}
|
||||
|
||||
AiksContext renderer(GetContext());
|
||||
AiksContext renderer(GetContext(), text_render_context_);
|
||||
|
||||
if (!renderer.IsValid()) {
|
||||
return false;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "impeller/aiks/aiks_context.h"
|
||||
#include "impeller/aiks/picture.h"
|
||||
#include "impeller/playground/playground_test.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@@ -20,11 +21,16 @@ class AiksPlayground : public PlaygroundTest {
|
||||
|
||||
~AiksPlayground();
|
||||
|
||||
void SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context);
|
||||
|
||||
bool OpenPlaygroundHere(const Picture& picture);
|
||||
|
||||
bool OpenPlaygroundHere(AiksPlaygroundCallback callback);
|
||||
|
||||
private:
|
||||
std::shared_ptr<TextRenderContext> text_render_context_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(AiksPlayground);
|
||||
};
|
||||
|
||||
|
||||
@@ -1002,7 +1002,7 @@ TEST_P(AiksTest, CanPictureConvertToImage) {
|
||||
recorder_canvas.DrawRect({200.0, 200.0, 600, 600}, paint);
|
||||
|
||||
Canvas canvas;
|
||||
AiksContext renderer(GetContext());
|
||||
AiksContext renderer(GetContext(), nullptr);
|
||||
paint.color = Color::BlackTransparent();
|
||||
canvas.DrawPaint(paint);
|
||||
Picture picture = recorder_canvas.EndRecordingAsPicture();
|
||||
@@ -2139,7 +2139,7 @@ TEST_P(AiksTest, DrawPaintAbsorbsClears) {
|
||||
std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
|
||||
std::shared_ptr<Context> real_context = GetContext();
|
||||
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
|
||||
AiksContext renderer(mock_context);
|
||||
AiksContext renderer(mock_context, nullptr);
|
||||
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
|
||||
|
||||
ASSERT_EQ(spy->render_passes_.size(), 1llu);
|
||||
@@ -2159,7 +2159,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClears) {
|
||||
Picture picture = canvas.EndRecordingAsPicture();
|
||||
std::shared_ptr<Context> real_context = GetContext();
|
||||
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
|
||||
AiksContext renderer(mock_context);
|
||||
AiksContext renderer(mock_context, nullptr);
|
||||
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
|
||||
|
||||
ASSERT_EQ(spy->render_passes_.size(), 1llu);
|
||||
@@ -2179,7 +2179,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRRect) {
|
||||
Picture picture = canvas.EndRecordingAsPicture();
|
||||
std::shared_ptr<Context> real_context = GetContext();
|
||||
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
|
||||
AiksContext renderer(mock_context);
|
||||
AiksContext renderer(mock_context, nullptr);
|
||||
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
|
||||
|
||||
ASSERT_EQ(spy->render_passes_.size(), 1llu);
|
||||
@@ -2199,7 +2199,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRotation) {
|
||||
Picture picture = canvas.EndRecordingAsPicture();
|
||||
std::shared_ptr<Context> real_context = GetContext();
|
||||
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
|
||||
AiksContext renderer(mock_context);
|
||||
AiksContext renderer(mock_context, nullptr);
|
||||
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
|
||||
|
||||
ASSERT_EQ(spy->render_passes_.size(), 1llu);
|
||||
@@ -2219,7 +2219,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegative) {
|
||||
Picture picture = canvas.EndRecordingAsPicture();
|
||||
std::shared_ptr<Context> real_context = GetContext();
|
||||
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
|
||||
AiksContext renderer(mock_context);
|
||||
AiksContext renderer(mock_context, nullptr);
|
||||
std::shared_ptr<Image> image = picture.ToImage(renderer, {301, 301});
|
||||
|
||||
ASSERT_EQ(spy->render_passes_.size(), 1llu);
|
||||
@@ -2243,7 +2243,7 @@ TEST_P(AiksTest, ClipRectElidesNoOpClips) {
|
||||
std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
|
||||
std::shared_ptr<Context> real_context = GetContext();
|
||||
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
|
||||
AiksContext renderer(mock_context);
|
||||
AiksContext renderer(mock_context, nullptr);
|
||||
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
|
||||
|
||||
ASSERT_EQ(spy->render_passes_.size(), 1llu);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "impeller/aiks/aiks_context.h"
|
||||
#include "impeller/display_list/dl_dispatcher.h"
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
#include "third_party/imgui/imgui.h"
|
||||
#include "third_party/skia/include/core/SkData.h"
|
||||
|
||||
@@ -29,7 +30,7 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) {
|
||||
return true;
|
||||
}
|
||||
|
||||
AiksContext context(GetContext());
|
||||
AiksContext context(GetContext(), TextRenderContextSkia::Make());
|
||||
if (!context.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
#include "impeller/renderer/render_target.h"
|
||||
#include "impeller/tessellator/tessellator.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@@ -159,9 +160,12 @@ static std::unique_ptr<PipelineT> CreateDefaultPipeline(
|
||||
return std::make_unique<PipelineT>(context, desc);
|
||||
}
|
||||
|
||||
ContentContext::ContentContext(std::shared_ptr<Context> context)
|
||||
ContentContext::ContentContext(
|
||||
std::shared_ptr<Context> context,
|
||||
std::shared_ptr<TextRenderContext> text_render_context)
|
||||
: context_(std::move(context)),
|
||||
lazy_glyph_atlas_(std::make_shared<LazyGlyphAtlas>()),
|
||||
lazy_glyph_atlas_(
|
||||
std::make_shared<LazyGlyphAtlas>(std::move(text_render_context))),
|
||||
tessellator_(std::make_shared<Tessellator>()),
|
||||
scene_context_(std::make_shared<scene::SceneContext>(context_)),
|
||||
render_target_cache_(std::make_shared<RenderTargetCache>(
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "impeller/renderer/pipeline.h"
|
||||
#include "impeller/renderer/render_target.h"
|
||||
#include "impeller/scene/scene_context.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
#ifdef IMPELLER_DEBUG
|
||||
#include "impeller/entity/checkerboard.frag.h"
|
||||
@@ -339,7 +340,9 @@ class RenderTargetCache;
|
||||
|
||||
class ContentContext {
|
||||
public:
|
||||
explicit ContentContext(std::shared_ptr<Context> context);
|
||||
explicit ContentContext(
|
||||
std::shared_ptr<Context> context,
|
||||
std::shared_ptr<TextRenderContext> text_render_context);
|
||||
|
||||
~ContentContext();
|
||||
|
||||
|
||||
@@ -12,10 +12,8 @@
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
#include "impeller/renderer/sampler_library.h"
|
||||
#include "impeller/tessellator/tessellator.h"
|
||||
#include "impeller/typographer/glyph_atlas.h"
|
||||
#include "impeller/typographer/lazy_glyph_atlas.h"
|
||||
|
||||
@@ -30,12 +28,12 @@ void TextContents::SetTextFrame(const TextFrame& frame) {
|
||||
}
|
||||
|
||||
std::shared_ptr<GlyphAtlas> TextContents::ResolveAtlas(
|
||||
Context& context,
|
||||
GlyphAtlas::Type type,
|
||||
const std::shared_ptr<LazyGlyphAtlas>& lazy_atlas,
|
||||
std::shared_ptr<Context> context) const {
|
||||
const std::shared_ptr<LazyGlyphAtlas>& lazy_atlas) const {
|
||||
FML_DCHECK(lazy_atlas);
|
||||
if (lazy_atlas) {
|
||||
return lazy_atlas->CreateOrGetGlyphAtlas(type, std::move(context));
|
||||
return lazy_atlas->CreateOrGetGlyphAtlas(context, type);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -90,7 +88,7 @@ bool TextContents::Render(const ContentContext& renderer,
|
||||
|
||||
auto type = frame_.GetAtlasType();
|
||||
auto atlas =
|
||||
ResolveAtlas(type, renderer.GetLazyGlyphAtlas(), renderer.GetContext());
|
||||
ResolveAtlas(*renderer.GetContext(), type, renderer.GetLazyGlyphAtlas());
|
||||
|
||||
if (!atlas || !atlas->IsValid()) {
|
||||
VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
|
||||
|
||||
@@ -63,9 +63,9 @@ class TextContents final : public Contents {
|
||||
Vector2 offset_;
|
||||
|
||||
std::shared_ptr<GlyphAtlas> ResolveAtlas(
|
||||
Context& context,
|
||||
GlyphAtlas::Type type,
|
||||
const std::shared_ptr<LazyGlyphAtlas>& lazy_atlas,
|
||||
std::shared_ptr<Context> context) const;
|
||||
const std::shared_ptr<LazyGlyphAtlas>& lazy_atlas) const;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(TextContents);
|
||||
};
|
||||
|
||||
@@ -5,21 +5,27 @@
|
||||
#include "impeller/entity/entity_playground.h"
|
||||
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
#include "third_party/imgui/imgui.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
EntityPlayground::EntityPlayground() = default;
|
||||
EntityPlayground::EntityPlayground()
|
||||
: text_render_context_(TextRenderContextSkia::Make()) {}
|
||||
|
||||
EntityPlayground::~EntityPlayground() = default;
|
||||
|
||||
void EntityPlayground::SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context) {
|
||||
text_render_context_ = std::move(text_render_context);
|
||||
}
|
||||
|
||||
bool EntityPlayground::OpenPlaygroundHere(EntityPass& entity_pass) {
|
||||
if (!switches_.enable_playground) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ContentContext content_context(GetContext());
|
||||
ContentContext content_context(GetContext(), text_render_context_);
|
||||
if (!content_context.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@@ -35,7 +41,7 @@ bool EntityPlayground::OpenPlaygroundHere(Entity entity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ContentContext content_context(GetContext());
|
||||
ContentContext content_context(GetContext(), text_render_context_);
|
||||
if (!content_context.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@@ -50,7 +56,7 @@ bool EntityPlayground::OpenPlaygroundHere(EntityPlaygroundCallback callback) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ContentContext content_context(GetContext());
|
||||
ContentContext content_context(GetContext(), text_render_context_);
|
||||
if (!content_context.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "impeller/playground/playground_test.h"
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/entity/entity_pass.h"
|
||||
|
||||
#include "impeller/playground/playground_test.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@@ -22,6 +23,9 @@ class EntityPlayground : public PlaygroundTest {
|
||||
|
||||
~EntityPlayground();
|
||||
|
||||
void SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context);
|
||||
|
||||
bool OpenPlaygroundHere(Entity entity);
|
||||
|
||||
bool OpenPlaygroundHere(EntityPass& entity_pass);
|
||||
@@ -29,6 +33,8 @@ class EntityPlayground : public PlaygroundTest {
|
||||
bool OpenPlaygroundHere(EntityPlaygroundCallback callback);
|
||||
|
||||
private:
|
||||
std::shared_ptr<TextRenderContext> text_render_context_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(EntityPlayground);
|
||||
};
|
||||
|
||||
|
||||
@@ -2175,7 +2175,8 @@ TEST_P(EntityTest, InheritOpacityTest) {
|
||||
font.setSize(30);
|
||||
auto blob = SkTextBlob::MakeFromString("A", font);
|
||||
auto frame = TextFrameFromTextBlob(blob);
|
||||
auto lazy_glyph_atlas = std::make_shared<LazyGlyphAtlas>();
|
||||
auto lazy_glyph_atlas =
|
||||
std::make_shared<LazyGlyphAtlas>(TextRenderContextSkia::Make());
|
||||
lazy_glyph_atlas->AddTextFrame(frame, 1.0f);
|
||||
|
||||
auto text_contents = std::make_shared<TextContents>();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "flutter/impeller/playground/playground.h"
|
||||
#include "flutter/impeller/renderer/render_target.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
#if FML_OS_MACOSX
|
||||
#include "flutter/fml/platform/darwin/scoped_nsautorelease_pool.h"
|
||||
@@ -26,12 +27,17 @@ class GoldenPlaygroundTest
|
||||
|
||||
GoldenPlaygroundTest();
|
||||
|
||||
~GoldenPlaygroundTest() override;
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
|
||||
PlaygroundBackend GetBackend() const;
|
||||
|
||||
void SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context);
|
||||
|
||||
bool OpenPlaygroundHere(const Picture& picture);
|
||||
|
||||
bool OpenPlaygroundHere(const AiksPlaygroundCallback& callback);
|
||||
@@ -58,6 +64,8 @@ class GoldenPlaygroundTest
|
||||
fml::ScopedNSAutoreleasePool autorelease_pool_;
|
||||
#endif
|
||||
|
||||
std::shared_ptr<TextRenderContext> text_render_context_;
|
||||
|
||||
struct GoldenPlaygroundTestImpl;
|
||||
// This is only a shared_ptr so it can work with a forward declared type.
|
||||
std::shared_ptr<GoldenPlaygroundTestImpl> pimpl_;
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/impeller/golden_tests/golden_playground_test.h"
|
||||
|
||||
#include "flutter/impeller/aiks/picture.h"
|
||||
#include "flutter/impeller/golden_tests/golden_digest.h"
|
||||
#include "flutter/impeller/golden_tests/metal_screenshoter.h"
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@@ -85,7 +88,15 @@ struct GoldenPlaygroundTest::GoldenPlaygroundTestImpl {
|
||||
};
|
||||
|
||||
GoldenPlaygroundTest::GoldenPlaygroundTest()
|
||||
: pimpl_(new GoldenPlaygroundTest::GoldenPlaygroundTestImpl()) {}
|
||||
: text_render_context_(TextRenderContextSkia::Make()),
|
||||
pimpl_(new GoldenPlaygroundTest::GoldenPlaygroundTestImpl()) {}
|
||||
|
||||
GoldenPlaygroundTest::~GoldenPlaygroundTest() = default;
|
||||
|
||||
void GoldenPlaygroundTest::SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context) {
|
||||
text_render_context_ = std::move(text_render_context);
|
||||
};
|
||||
|
||||
void GoldenPlaygroundTest::TearDown() {
|
||||
ASSERT_FALSE(dlopen("/usr/local/lib/libMoltenVK.dylib", RTLD_NOLOAD));
|
||||
@@ -124,8 +135,10 @@ PlaygroundBackend GoldenPlaygroundTest::GetBackend() const {
|
||||
}
|
||||
|
||||
bool GoldenPlaygroundTest::OpenPlaygroundHere(const Picture& picture) {
|
||||
auto screenshot =
|
||||
pimpl_->screenshoter->MakeScreenshot(picture, pimpl_->window_size);
|
||||
AiksContext renderer(GetContext(), text_render_context_);
|
||||
|
||||
auto screenshot = pimpl_->screenshoter->MakeScreenshot(renderer, picture,
|
||||
pimpl_->window_size);
|
||||
return SaveScreenshot(std::move(screenshot));
|
||||
}
|
||||
|
||||
@@ -161,7 +174,7 @@ std::shared_ptr<RuntimeStage> GoldenPlaygroundTest::OpenAssetAsRuntimeStage(
|
||||
}
|
||||
|
||||
std::shared_ptr<Context> GoldenPlaygroundTest::GetContext() const {
|
||||
return pimpl_->screenshoter->GetContext().GetContext();
|
||||
return pimpl_->screenshoter->GetPlayground().GetContext();
|
||||
}
|
||||
|
||||
Point GoldenPlaygroundTest::GetContentScale() const {
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
GoldenPlaygroundTest::GoldenPlaygroundTest() {}
|
||||
GoldenPlaygroundTest::GoldenPlaygroundTest() = default;
|
||||
|
||||
GoldenPlaygroundTest::~GoldenPlaygroundTest() = default;
|
||||
|
||||
void GoldenPlaygroundTest::SetTextRenderContext(
|
||||
std::shared_ptr<TextRenderContext> text_render_context) {
|
||||
text_render_context_ = std::move(text_render_context);
|
||||
};
|
||||
|
||||
void GoldenPlaygroundTest::TearDown() {}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "flutter/fml/platform/darwin/scoped_nsautorelease_pool.h"
|
||||
#include "impeller/aiks/aiks_context.h"
|
||||
#include "impeller/aiks/canvas.h"
|
||||
#include "impeller/entity/contents/conical_gradient_contents.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
@@ -56,7 +57,7 @@ class GoldenTests : public ::testing::Test {
|
||||
void SetUp() override {
|
||||
testing::GoldenDigest::Instance()->AddDimension(
|
||||
"gpu_string",
|
||||
Screenshoter().GetContext().GetContext()->DescribeGpuModel());
|
||||
Screenshoter().GetPlayground().GetContext()->DescribeGpuModel());
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -79,7 +80,10 @@ TEST_F(GoldenTests, ConicalGradient) {
|
||||
paint.style = Paint::Style::kFill;
|
||||
canvas.DrawRect(Rect(10, 10, 250, 250), paint);
|
||||
Picture picture = canvas.EndRecordingAsPicture();
|
||||
auto screenshot = Screenshoter().MakeScreenshot(picture);
|
||||
|
||||
auto aiks_context =
|
||||
AiksContext(Screenshoter().GetPlayground().GetContext(), nullptr);
|
||||
auto screenshot = Screenshoter().MakeScreenshot(aiks_context, picture);
|
||||
ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
|
||||
}
|
||||
} // namespace testing
|
||||
|
||||
@@ -12,24 +12,20 @@
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
|
||||
/// Converts `Picture`'s to `MetalScreenshot`'s with the playground backend.
|
||||
/// Converts `Picture`s to `MetalScreenshot`s with the playground backend.
|
||||
class MetalScreenshoter {
|
||||
public:
|
||||
MetalScreenshoter();
|
||||
|
||||
std::unique_ptr<MetalScreenshot> MakeScreenshot(const Picture& picture,
|
||||
std::unique_ptr<MetalScreenshot> MakeScreenshot(AiksContext& aiks_context,
|
||||
const Picture& picture,
|
||||
const ISize& size = {300,
|
||||
300});
|
||||
|
||||
AiksContext& GetContext() { return *aiks_context_; }
|
||||
|
||||
const AiksContext& GetContext() const { return *aiks_context_; }
|
||||
|
||||
const PlaygroundImpl& GetPlayground() const { return *playground_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<PlaygroundImpl> playground_;
|
||||
std::unique_ptr<AiksContext> aiks_context_;
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@@ -17,15 +17,15 @@ MetalScreenshoter::MetalScreenshoter() {
|
||||
FML_CHECK(::glfwInit() == GLFW_TRUE);
|
||||
playground_ =
|
||||
PlaygroundImpl::Create(PlaygroundBackend::kMetal, PlaygroundSwitches{});
|
||||
aiks_context_.reset(new AiksContext(playground_->GetContext()));
|
||||
}
|
||||
|
||||
std::unique_ptr<MetalScreenshot> MetalScreenshoter::MakeScreenshot(
|
||||
AiksContext& aiks_context,
|
||||
const Picture& picture,
|
||||
const ISize& size) {
|
||||
Vector2 content_scale = playground_->GetContentScale();
|
||||
std::shared_ptr<Image> image = picture.ToImage(
|
||||
*aiks_context_,
|
||||
aiks_context,
|
||||
ISize(size.width * content_scale.x, size.height * content_scale.y));
|
||||
std::shared_ptr<Texture> texture = image->GetTexture();
|
||||
id<MTLTexture> metal_texture =
|
||||
|
||||
@@ -125,7 +125,7 @@ TEST_P(ComputeSubgroupTest, PathPlayground) {
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ContentContext renderer(context);
|
||||
ContentContext renderer(context, nullptr);
|
||||
if (!renderer.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@@ -329,7 +329,7 @@ TEST_P(ComputeSubgroupTest, LargePath) {
|
||||
->count;
|
||||
});
|
||||
|
||||
ContentContext renderer(context);
|
||||
ContentContext renderer(context, nullptr);
|
||||
if (!renderer.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@@ -413,7 +413,7 @@ TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) {
|
||||
ASSERT_EQ(status, ComputeTessellator::Status::kOk);
|
||||
|
||||
auto callback = [&](RenderPass& pass) -> bool {
|
||||
ContentContext renderer(context);
|
||||
ContentContext renderer(context, nullptr);
|
||||
if (!renderer.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
#include "impeller/core/allocator.h"
|
||||
#include "impeller/typographer/backends/skia/typeface_skia.h"
|
||||
#include "impeller/typographer/rectangle_packer.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkFont.h"
|
||||
#include "third_party/skia/include/core/SkFontMetrics.h"
|
||||
#include "third_party/skia/include/core/SkRSXform.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
|
||||
namespace impeller {
|
||||
@@ -24,19 +23,16 @@ namespace impeller {
|
||||
using FontGlyphPairRefVector =
|
||||
std::vector<std::reference_wrapper<const FontGlyphPair>>;
|
||||
|
||||
std::unique_ptr<TextRenderContext> TextRenderContext::Create(
|
||||
std::shared_ptr<Context> context) {
|
||||
// There is only one backend today.
|
||||
return std::make_unique<TextRenderContextSkia>(std::move(context));
|
||||
}
|
||||
|
||||
// TODO(bdero): We might be able to remove this per-glyph padding if we fix
|
||||
// the underlying causes of the overlap.
|
||||
// https://github.com/flutter/flutter/issues/114563
|
||||
constexpr auto kPadding = 2;
|
||||
|
||||
TextRenderContextSkia::TextRenderContextSkia(std::shared_ptr<Context> context)
|
||||
: TextRenderContext(std::move(context)) {}
|
||||
std::shared_ptr<TextRenderContext> TextRenderContextSkia::Make() {
|
||||
return std::make_shared<TextRenderContextSkia>();
|
||||
}
|
||||
|
||||
TextRenderContextSkia::TextRenderContextSkia() = default;
|
||||
|
||||
TextRenderContextSkia::~TextRenderContextSkia() = default;
|
||||
|
||||
@@ -310,6 +306,7 @@ static std::shared_ptr<Texture> UploadGlyphTextureAtlas(
|
||||
}
|
||||
|
||||
std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
|
||||
Context& context,
|
||||
GlyphAtlas::Type type,
|
||||
std::shared_ptr<GlyphAtlasContext> atlas_context,
|
||||
const FontGlyphPair::Set& font_glyph_pairs) const {
|
||||
@@ -429,8 +426,8 @@ std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
|
||||
format = PixelFormat::kR8G8B8A8UNormInt;
|
||||
break;
|
||||
}
|
||||
auto texture = UploadGlyphTextureAtlas(GetContext()->GetResourceAllocator(),
|
||||
bitmap, atlas_size, format);
|
||||
auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(), bitmap,
|
||||
atlas_size, format);
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -11,12 +11,15 @@ namespace impeller {
|
||||
|
||||
class TextRenderContextSkia : public TextRenderContext {
|
||||
public:
|
||||
TextRenderContextSkia(std::shared_ptr<Context> context);
|
||||
static std::shared_ptr<TextRenderContext> Make();
|
||||
|
||||
TextRenderContextSkia();
|
||||
|
||||
~TextRenderContextSkia() override;
|
||||
|
||||
// |TextRenderContext|
|
||||
std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
|
||||
Context& context,
|
||||
GlyphAtlas::Type type,
|
||||
std::shared_ptr<GlyphAtlasContext> atlas_context,
|
||||
const FontGlyphPair::Set& font_glyph_pairs) const override;
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
LazyGlyphAtlas::LazyGlyphAtlas()
|
||||
: alpha_context_(std::make_shared<GlyphAtlasContext>()),
|
||||
LazyGlyphAtlas::LazyGlyphAtlas(
|
||||
std::shared_ptr<TextRenderContext> text_render_context)
|
||||
: text_render_context_(std::move(text_render_context)),
|
||||
alpha_context_(std::make_shared<GlyphAtlasContext>()),
|
||||
color_context_(std::make_shared<GlyphAtlasContext>()) {}
|
||||
|
||||
LazyGlyphAtlas::~LazyGlyphAtlas() = default;
|
||||
@@ -33,8 +35,8 @@ void LazyGlyphAtlas::ResetTextFrames() {
|
||||
}
|
||||
|
||||
std::shared_ptr<GlyphAtlas> LazyGlyphAtlas::CreateOrGetGlyphAtlas(
|
||||
GlyphAtlas::Type type,
|
||||
std::shared_ptr<Context> context) const {
|
||||
Context& context,
|
||||
GlyphAtlas::Type type) const {
|
||||
{
|
||||
auto atlas_it = atlas_map_.find(type);
|
||||
if (atlas_it != atlas_map_.end()) {
|
||||
@@ -42,14 +44,22 @@ std::shared_ptr<GlyphAtlas> LazyGlyphAtlas::CreateOrGetGlyphAtlas(
|
||||
}
|
||||
}
|
||||
|
||||
auto text_context = TextRenderContext::Create(std::move(context));
|
||||
if (!text_context || !text_context->IsValid()) {
|
||||
if (!text_render_context_) {
|
||||
VALIDATION_LOG << "Unable to render text because a TextRenderContext has "
|
||||
"not been set.";
|
||||
return nullptr;
|
||||
}
|
||||
if (!text_render_context_->IsValid()) {
|
||||
VALIDATION_LOG
|
||||
<< "Unable to render text because the TextRenderContext is invalid.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto& set = type == GlyphAtlas::Type::kAlphaBitmap ? alpha_set_ : color_set_;
|
||||
auto atlas_context =
|
||||
type == GlyphAtlas::Type::kAlphaBitmap ? alpha_context_ : color_context_;
|
||||
auto atlas = text_context->CreateGlyphAtlas(type, atlas_context, set);
|
||||
auto atlas =
|
||||
text_render_context_->CreateGlyphAtlas(context, type, atlas_context, set);
|
||||
if (!atlas || !atlas->IsValid()) {
|
||||
VALIDATION_LOG << "Could not create valid atlas.";
|
||||
return nullptr;
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/typographer/glyph_atlas.h"
|
||||
#include "impeller/typographer/text_frame.h"
|
||||
#include "impeller/typographer/text_render_context.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
class LazyGlyphAtlas {
|
||||
public:
|
||||
LazyGlyphAtlas();
|
||||
explicit LazyGlyphAtlas(
|
||||
std::shared_ptr<TextRenderContext> text_render_context);
|
||||
|
||||
~LazyGlyphAtlas();
|
||||
|
||||
@@ -24,10 +26,12 @@ class LazyGlyphAtlas {
|
||||
void ResetTextFrames();
|
||||
|
||||
std::shared_ptr<GlyphAtlas> CreateOrGetGlyphAtlas(
|
||||
GlyphAtlas::Type type,
|
||||
std::shared_ptr<Context> context) const;
|
||||
Context& context,
|
||||
GlyphAtlas::Type type) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<TextRenderContext> text_render_context_;
|
||||
|
||||
FontGlyphPair::Set alpha_set_;
|
||||
FontGlyphPair::Set color_set_;
|
||||
std::shared_ptr<GlyphAtlasContext> alpha_context_;
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
TextRenderContext::TextRenderContext(std::shared_ptr<Context> context)
|
||||
: context_(std::move(context)) {
|
||||
if (!context_ || !context_->IsValid()) {
|
||||
return;
|
||||
}
|
||||
TextRenderContext::TextRenderContext() {
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
@@ -22,8 +18,4 @@ bool TextRenderContext::IsValid() const {
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Context>& TextRenderContext::GetContext() const {
|
||||
return context_;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/typographer/glyph_atlas.h"
|
||||
#include "impeller/typographer/text_frame.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@@ -23,24 +22,15 @@ namespace impeller {
|
||||
///
|
||||
class TextRenderContext {
|
||||
public:
|
||||
static std::unique_ptr<TextRenderContext> Create(
|
||||
std::shared_ptr<Context> context);
|
||||
|
||||
virtual ~TextRenderContext();
|
||||
|
||||
virtual bool IsValid() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Get the underlying graphics context.
|
||||
///
|
||||
/// @return The context.
|
||||
///
|
||||
const std::shared_ptr<Context>& GetContext() const;
|
||||
|
||||
// TODO(dnfield): Callers should not need to know which type of atlas to
|
||||
// create. https://github.com/flutter/flutter/issues/111640
|
||||
|
||||
virtual std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
|
||||
Context& context,
|
||||
GlyphAtlas::Type type,
|
||||
std::shared_ptr<GlyphAtlasContext> atlas_context,
|
||||
const FontGlyphPair::Set& font_glyph_pairs) const = 0;
|
||||
@@ -50,12 +40,9 @@ class TextRenderContext {
|
||||
/// @brief Create a new context to render text that talks to an
|
||||
/// underlying graphics context.
|
||||
///
|
||||
/// @param[in] context The graphics context
|
||||
///
|
||||
TextRenderContext(std::shared_ptr<Context> context);
|
||||
TextRenderContext();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Context> context_;
|
||||
bool is_valid_ = false;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(TextRenderContext);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
#include "impeller/typographer/lazy_glyph_atlas.h"
|
||||
#include "impeller/typographer/rectangle_packer.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkData.h"
|
||||
#include "third_party/skia/include/core/SkFontMgr.h"
|
||||
#include "third_party/skia/include/core/SkRect.h"
|
||||
@@ -24,14 +23,16 @@ using TypographerTest = PlaygroundTest;
|
||||
INSTANTIATE_PLAYGROUND_SUITE(TypographerTest);
|
||||
|
||||
static std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
|
||||
const TextRenderContext* context,
|
||||
Context& context,
|
||||
const TextRenderContext* text_render_context,
|
||||
GlyphAtlas::Type type,
|
||||
Scalar scale,
|
||||
const std::shared_ptr<GlyphAtlasContext>& atlas_context,
|
||||
const TextFrame& frame) {
|
||||
FontGlyphPair::Set set;
|
||||
frame.CollectUniqueFontGlyphPairs(set, scale);
|
||||
return context->CreateGlyphAtlas(type, atlas_context, set);
|
||||
return text_render_context->CreateGlyphAtlas(context, type, atlas_context,
|
||||
set);
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, CanConvertTextBlob) {
|
||||
@@ -48,20 +49,20 @@ TEST_P(TypographerTest, CanConvertTextBlob) {
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, CanCreateRenderContext) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, CanCreateGlyphAtlas) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
auto atlas_context = std::make_shared<GlyphAtlasContext>();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
SkFont sk_font;
|
||||
auto blob = SkTextBlob::MakeFromString("hello", sk_font);
|
||||
ASSERT_TRUE(blob);
|
||||
auto atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto atlas = CreateGlyphAtlas(*GetContext(), context.get(),
|
||||
GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
ASSERT_NE(atlas, nullptr);
|
||||
ASSERT_NE(atlas->GetTexture(), nullptr);
|
||||
ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
|
||||
@@ -111,7 +112,7 @@ TEST_P(TypographerTest, LazyAtlasTracksColor) {
|
||||
|
||||
ASSERT_FALSE(frame.GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
|
||||
|
||||
LazyGlyphAtlas lazy_atlas;
|
||||
LazyGlyphAtlas lazy_atlas(TextRenderContextSkia::Make());
|
||||
|
||||
lazy_atlas.AddTextFrame(frame, 1.0f);
|
||||
|
||||
@@ -123,24 +124,24 @@ TEST_P(TypographerTest, LazyAtlasTracksColor) {
|
||||
|
||||
// Creates different atlases for color and alpha bitmap.
|
||||
auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
|
||||
GlyphAtlas::Type::kColorBitmap, GetContext());
|
||||
*GetContext(), GlyphAtlas::Type::kColorBitmap);
|
||||
|
||||
auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
|
||||
GlyphAtlas::Type::kAlphaBitmap, GetContext());
|
||||
*GetContext(), GlyphAtlas::Type::kAlphaBitmap);
|
||||
|
||||
ASSERT_FALSE(color_atlas == bitmap_atlas);
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, GlyphAtlasWithOddUniqueGlyphSize) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
auto atlas_context = std::make_shared<GlyphAtlasContext>();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
SkFont sk_font;
|
||||
auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
|
||||
ASSERT_TRUE(blob);
|
||||
auto atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto atlas = CreateGlyphAtlas(*GetContext(), context.get(),
|
||||
GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
ASSERT_NE(atlas, nullptr);
|
||||
ASSERT_NE(atlas->GetTexture(), nullptr);
|
||||
|
||||
@@ -149,30 +150,30 @@ TEST_P(TypographerTest, GlyphAtlasWithOddUniqueGlyphSize) {
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, GlyphAtlasIsRecycledIfUnchanged) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
auto atlas_context = std::make_shared<GlyphAtlasContext>();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
SkFont sk_font;
|
||||
auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
|
||||
ASSERT_TRUE(blob);
|
||||
auto atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto atlas = CreateGlyphAtlas(*GetContext(), context.get(),
|
||||
GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
ASSERT_NE(atlas, nullptr);
|
||||
ASSERT_NE(atlas->GetTexture(), nullptr);
|
||||
ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
|
||||
|
||||
// now attempt to re-create an atlas with the same text blob.
|
||||
|
||||
auto next_atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto next_atlas = CreateGlyphAtlas(
|
||||
*GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
ASSERT_EQ(atlas, next_atlas);
|
||||
ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
auto atlas_context = std::make_shared<GlyphAtlasContext>();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
|
||||
@@ -191,8 +192,9 @@ TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
|
||||
for (size_t index = 0; index < size_count; index += 1) {
|
||||
TextFrameFromTextBlob(blob).CollectUniqueFontGlyphPairs(set, 0.6 * index);
|
||||
};
|
||||
auto atlas = context->CreateGlyphAtlas(GlyphAtlas::Type::kAlphaBitmap,
|
||||
std::move(atlas_context), set);
|
||||
auto atlas =
|
||||
context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
|
||||
std::move(atlas_context), set);
|
||||
ASSERT_NE(atlas, nullptr);
|
||||
ASSERT_NE(atlas->GetTexture(), nullptr);
|
||||
|
||||
@@ -213,15 +215,15 @@ TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
auto atlas_context = std::make_shared<GlyphAtlasContext>();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
SkFont sk_font;
|
||||
auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
|
||||
ASSERT_TRUE(blob);
|
||||
auto atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto atlas = CreateGlyphAtlas(*GetContext(), context.get(),
|
||||
GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto old_packer = atlas_context->GetRectPacker();
|
||||
|
||||
ASSERT_NE(atlas, nullptr);
|
||||
@@ -233,9 +235,9 @@ TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) {
|
||||
// Now create a new glyph atlas with a nearly identical blob.
|
||||
|
||||
auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
|
||||
auto next_atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob2));
|
||||
auto next_atlas = CreateGlyphAtlas(
|
||||
*GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob2));
|
||||
ASSERT_EQ(atlas, next_atlas);
|
||||
auto* second_texture = next_atlas->GetTexture().get();
|
||||
|
||||
@@ -246,15 +248,15 @@ TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) {
|
||||
}
|
||||
|
||||
TEST_P(TypographerTest, GlyphAtlasTextureIsRecreatedIfTypeChanges) {
|
||||
auto context = TextRenderContext::Create(GetContext());
|
||||
auto context = TextRenderContextSkia::Make();
|
||||
auto atlas_context = std::make_shared<GlyphAtlasContext>();
|
||||
ASSERT_TRUE(context && context->IsValid());
|
||||
SkFont sk_font;
|
||||
auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
|
||||
ASSERT_TRUE(blob);
|
||||
auto atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto atlas = CreateGlyphAtlas(*GetContext(), context.get(),
|
||||
GlyphAtlas::Type::kAlphaBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob));
|
||||
auto old_packer = atlas_context->GetRectPacker();
|
||||
|
||||
ASSERT_NE(atlas, nullptr);
|
||||
@@ -267,9 +269,9 @@ TEST_P(TypographerTest, GlyphAtlasTextureIsRecreatedIfTypeChanges) {
|
||||
// but change the type.
|
||||
|
||||
auto blob2 = SkTextBlob::MakeFromString("spooky 1", sk_font);
|
||||
auto next_atlas =
|
||||
CreateGlyphAtlas(context.get(), GlyphAtlas::Type::kColorBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob2));
|
||||
auto next_atlas = CreateGlyphAtlas(
|
||||
*GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 1.0f,
|
||||
atlas_context, TextFrameFromTextBlob(blob2));
|
||||
ASSERT_NE(atlas, next_atlas);
|
||||
auto* second_texture = next_atlas->GetTexture().get();
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@
|
||||
#include "flutter/fml/time/time_point.h"
|
||||
#if IMPELLER_SUPPORTS_RENDERING
|
||||
// GN is having trouble understanding how this works in the Fuchsia builds.
|
||||
#include "flutter/impeller/aiks/aiks_context.h" // nogncheck
|
||||
#include "flutter/impeller/renderer/context.h" // nogncheck
|
||||
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||
#include "impeller/aiks/aiks_context.h" // nogncheck
|
||||
#include "impeller/renderer/context.h" // nogncheck
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h" // nogncheck
|
||||
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||
#include "flutter/lib/ui/snapshot_delegate.h"
|
||||
#include "flutter/shell/common/pipeline.h"
|
||||
#include "flutter/shell/common/snapshot_controller.h"
|
||||
@@ -544,7 +545,8 @@ class Rasterizer final : public SnapshotDelegate,
|
||||
return surface_->GetAiksContext();
|
||||
}
|
||||
if (auto context = impeller_context_.lock()) {
|
||||
return std::make_shared<impeller::AiksContext>(context);
|
||||
return std::make_shared<impeller::AiksContext>(
|
||||
context, impeller::TextRenderContextSkia::Make());
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
#include "flutter/shell/gpu/gpu_surface_gl_impeller.h"
|
||||
|
||||
#include "flutter/fml/make_copyable.h"
|
||||
#include "flutter/impeller/display_list/dl_dispatcher.h"
|
||||
#include "flutter/impeller/renderer/backend/gles/surface_gles.h"
|
||||
#include "flutter/impeller/renderer/renderer.h"
|
||||
#include "impeller/display_list/dl_dispatcher.h"
|
||||
#include "impeller/renderer/backend/gles/surface_gles.h"
|
||||
#include "impeller/renderer/renderer.h"
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -28,7 +29,8 @@ GPUSurfaceGLImpeller::GPUSurfaceGLImpeller(
|
||||
return;
|
||||
}
|
||||
|
||||
auto aiks_context = std::make_shared<impeller::AiksContext>(context);
|
||||
auto aiks_context = std::make_shared<impeller::AiksContext>(
|
||||
context, impeller::TextRenderContextSkia::Make());
|
||||
|
||||
if (!aiks_context->IsValid()) {
|
||||
return;
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "flutter/fml/make_copyable.h"
|
||||
#include "flutter/fml/mapping.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "flutter/impeller/display_list/dl_dispatcher.h"
|
||||
#include "flutter/impeller/renderer/backend/metal/surface_mtl.h"
|
||||
#include "impeller/display_list/dl_dispatcher.h"
|
||||
#include "impeller/renderer/backend/metal/surface_mtl.h"
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
|
||||
static_assert(!__has_feature(objc_arc), "ARC must be disabled.");
|
||||
|
||||
@@ -35,7 +36,8 @@ GPUSurfaceMetalImpeller::GPUSurfaceMetalImpeller(GPUSurfaceMetalDelegate* delega
|
||||
render_target_type_(delegate->GetRenderTargetType()),
|
||||
impeller_renderer_(CreateImpellerRenderer(context)),
|
||||
aiks_context_(
|
||||
std::make_shared<impeller::AiksContext>(impeller_renderer_ ? context : nullptr)),
|
||||
std::make_shared<impeller::AiksContext>(impeller_renderer_ ? context : nullptr,
|
||||
impeller::TextRenderContextSkia::Make())),
|
||||
render_to_surface_(render_to_surface) {
|
||||
// If this preference is explicitly set, we allow for disabling partial repaint.
|
||||
NSNumber* disablePartialRepaint =
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
#include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h"
|
||||
|
||||
#include "flutter/fml/make_copyable.h"
|
||||
#include "flutter/impeller/display_list/dl_dispatcher.h"
|
||||
#include "flutter/impeller/renderer/renderer.h"
|
||||
#include "impeller/display_list/dl_dispatcher.h"
|
||||
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
|
||||
#include "impeller/renderer/renderer.h"
|
||||
#include "impeller/renderer/surface.h"
|
||||
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -23,7 +24,8 @@ GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller(
|
||||
return;
|
||||
}
|
||||
|
||||
auto aiks_context = std::make_shared<impeller::AiksContext>(context);
|
||||
auto aiks_context = std::make_shared<impeller::AiksContext>(
|
||||
context, impeller::TextRenderContextSkia::Make());
|
||||
if (!aiks_context->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user