Skip to content

Commit

Permalink
[Impeller] Supply a text backend to the AiksContext at runtime. (flut…
Browse files Browse the repository at this point in the history
…ter#44884)

Resolves flutter/flutter#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.
  • Loading branch information
bdero authored Aug 22, 2023
1 parent 454e0e3 commit fd52779
Show file tree
Hide file tree
Showing 31 changed files with 231 additions and 152 deletions.
7 changes: 5 additions & 2 deletions impeller/aiks/aiks_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
13 changes: 12 additions & 1 deletion impeller/aiks/aiks_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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();

Expand Down
15 changes: 12 additions & 3 deletions impeller/aiks/aiks_playground.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions impeller/aiks/aiks_playground.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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);
};

Expand Down
14 changes: 7 additions & 7 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion impeller/display_list/dl_playground.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -29,7 +30,7 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) {
return true;
}

AiksContext context(GetContext());
AiksContext context(GetContext(), TextRenderContextSkia::Make());
if (!context.IsValid()) {
return false;
}
Expand Down
8 changes: 6 additions & 2 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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>(
Expand Down
5 changes: 4 additions & 1 deletion impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();

Expand Down
10 changes: 4 additions & 6 deletions impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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;
Expand Down Expand Up @@ -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.";
Expand Down
4 changes: 2 additions & 2 deletions impeller/entity/contents/text_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down
16 changes: 11 additions & 5 deletions impeller/entity/entity_playground.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
10 changes: 8 additions & 2 deletions impeller/entity/entity_playground.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -22,13 +23,18 @@ class EntityPlayground : public PlaygroundTest {

~EntityPlayground();

void SetTextRenderContext(
std::shared_ptr<TextRenderContext> text_render_context);

bool OpenPlaygroundHere(Entity entity);

bool OpenPlaygroundHere(EntityPass& entity_pass);

bool OpenPlaygroundHere(EntityPlaygroundCallback callback);

private:
std::shared_ptr<TextRenderContext> text_render_context_;

FML_DISALLOW_COPY_AND_ASSIGN(EntityPlayground);
};

Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/entity_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand Down
Loading

0 comments on commit fd52779

Please sign in to comment.