Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6e4a9b3

Browse files
author
Jonah Williams
authored
[Impeller] remove SDF code paths. (#41754)
From my investigations, we're not likely to be able to use SDF in the near term. To make planned refactors of the text rendering easier to land, I've moved the primary piece of code for generating the SDFs into a new TU for testing. The shader itself has been deleted so that we don't ship + register it.
1 parent d25dd74 commit 6e4a9b3

File tree

7 files changed

+11
-214
lines changed

7 files changed

+11
-214
lines changed

impeller/entity/contents/content_context.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,6 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
286286
CreateDefaultPipeline<SrgbToLinearFilterPipeline>(*context_);
287287
glyph_atlas_pipelines_[{}] =
288288
CreateDefaultPipeline<GlyphAtlasPipeline>(*context_);
289-
glyph_atlas_sdf_pipelines_[{}] =
290-
CreateDefaultPipeline<GlyphAtlasSdfPipeline>(*context_);
291289
geometry_color_pipelines_[{}] =
292290
CreateDefaultPipeline<GeometryColorPipeline>(*context_);
293291
yuv_to_rgb_filter_pipelines_[{}] =

impeller/entity/contents/content_context.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
#include "impeller/entity/conical_gradient_fill.frag.h"
3333
#include "impeller/entity/glyph_atlas.frag.h"
3434
#include "impeller/entity/glyph_atlas.vert.h"
35-
#include "impeller/entity/glyph_atlas_sdf.frag.h"
36-
#include "impeller/entity/glyph_atlas_sdf.vert.h"
3735
#include "impeller/entity/gradient_fill.vert.h"
3836
#include "impeller/entity/linear_gradient_fill.frag.h"
3937
#include "impeller/entity/linear_to_srgb_filter.frag.h"
@@ -173,8 +171,6 @@ using SrgbToLinearFilterPipeline =
173171
SrgbToLinearFilterFragmentShader>;
174172
using GlyphAtlasPipeline =
175173
RenderPipelineT<GlyphAtlasVertexShader, GlyphAtlasFragmentShader>;
176-
using GlyphAtlasSdfPipeline =
177-
RenderPipelineT<GlyphAtlasSdfVertexShader, GlyphAtlasSdfFragmentShader>;
178174
using PorterDuffBlendPipeline =
179175
RenderPipelineT<BlendVertexShader, PorterDuffBlendFragmentShader>;
180176
// Instead of requiring new shaders for clips, the solid fill stages are used
@@ -473,11 +469,6 @@ class ContentContext {
473469
return GetPipeline(glyph_atlas_pipelines_, opts);
474470
}
475471

476-
std::shared_ptr<Pipeline<PipelineDescriptor>> GetGlyphAtlasSdfPipeline(
477-
ContentContextOptions opts) const {
478-
return GetPipeline(glyph_atlas_sdf_pipelines_, opts);
479-
}
480-
481472
std::shared_ptr<Pipeline<PipelineDescriptor>> GetGeometryColorPipeline(
482473
ContentContextOptions opts) const {
483474
return GetPipeline(geometry_color_pipelines_, opts);
@@ -731,7 +722,6 @@ class ContentContext {
731722
mutable Variants<SrgbToLinearFilterPipeline> srgb_to_linear_filter_pipelines_;
732723
mutable Variants<ClipPipeline> clip_pipelines_;
733724
mutable Variants<GlyphAtlasPipeline> glyph_atlas_pipelines_;
734-
mutable Variants<GlyphAtlasSdfPipeline> glyph_atlas_sdf_pipelines_;
735725
mutable Variants<GeometryColorPipeline> geometry_color_pipelines_;
736726
mutable Variants<YUVToRGBFilterPipeline> yuv_to_rgb_filter_pipelines_;
737727
mutable Variants<PorterDuffBlendPipeline> porter_duff_blend_pipelines_;

impeller/entity/contents/text_contents.cc

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ std::optional<Rect> TextContents::GetCoverage(const Entity& entity) const {
7474
return bounds->TransformBounds(entity.GetTransformation());
7575
}
7676

77-
template <class TPipeline>
7877
static bool CommonRender(
7978
const ContentContext& renderer,
8079
const Entity& entity,
@@ -85,11 +84,11 @@ static bool CommonRender(
8584
std::shared_ptr<GlyphAtlas>
8685
atlas, // NOLINT(performance-unnecessary-value-param)
8786
Command& cmd) {
88-
using VS = typename TPipeline::VertexShader;
89-
using FS = typename TPipeline::FragmentShader;
87+
using VS = GlyphAtlasPipeline::VertexShader;
88+
using FS = GlyphAtlasPipeline::FragmentShader;
9089

9190
// Common vertex uniforms for all glyphs.
92-
typename VS::FrameInfo frame_info;
91+
VS::FrameInfo frame_info;
9392

9493
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize());
9594
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
@@ -109,7 +108,7 @@ static bool CommonRender(
109108
}
110109
sampler_desc.mip_filter = MipFilter::kNearest;
111110

112-
typename FS::FragInfo frag_info;
111+
FS::FragInfo frag_info;
113112
frag_info.text_color = ToVector(color.Premultiply());
114113
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
115114

@@ -183,7 +182,7 @@ static bool CommonRender(
183182
.Round();
184183

185184
for (const auto& point : unit_points) {
186-
typename VS::PerVertexData vtx;
185+
VS::PerVertexData vtx;
187186

188187
if (entity.GetTransformation().IsTranslationScaleOnly()) {
189188
// Rouding up here prevents the bounds from becoming 1 pixel too small
@@ -199,19 +198,16 @@ static bool CommonRender(
199198
point * glyph_position.glyph.bounds.size);
200199
}
201200
vtx.uv = uv_origin + point * uv_size;
201+
vtx.has_color =
202+
glyph_position.glyph.type == Glyph::Type::kBitmap ? 1.0 : 0.0;
202203

203-
if constexpr (std::is_same_v<TPipeline, GlyphAtlasPipeline>) {
204-
vtx.has_color =
205-
glyph_position.glyph.type == Glyph::Type::kBitmap ? 1.0 : 0.0;
206-
}
207-
208-
vertex_builder.AppendVertex(std::move(vtx));
204+
vertex_builder.AppendVertex(vtx);
209205
}
210206
}
211207
}
212208
auto vertex_buffer =
213209
vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer());
214-
cmd.BindVertices(std::move(vertex_buffer));
210+
cmd.BindVertices(vertex_buffer);
215211

216212
if (!pass.AddCommand(cmd)) {
217213
return false;
@@ -220,30 +216,6 @@ static bool CommonRender(
220216
return true;
221217
}
222218

223-
bool TextContents::RenderSdf(const ContentContext& renderer,
224-
const Entity& entity,
225-
RenderPass& pass) const {
226-
auto atlas =
227-
ResolveAtlas(GlyphAtlas::Type::kSignedDistanceField,
228-
renderer.GetGlyphAtlasContext(), renderer.GetContext());
229-
230-
if (!atlas || !atlas->IsValid()) {
231-
VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
232-
return false;
233-
}
234-
235-
// Information shared by all glyph draw calls.
236-
Command cmd;
237-
cmd.label = "TextFrameSDF";
238-
auto opts = OptionsFromPassAndEntity(pass, entity);
239-
opts.primitive_type = PrimitiveType::kTriangle;
240-
cmd.pipeline = renderer.GetGlyphAtlasSdfPipeline(opts);
241-
cmd.stencil_reference = entity.GetStencilDepth();
242-
243-
return CommonRender<GlyphAtlasSdfPipeline>(renderer, entity, pass, GetColor(),
244-
frame_, offset_, atlas, cmd);
245-
}
246-
247219
bool TextContents::Render(const ContentContext& renderer,
248220
const Entity& entity,
249221
RenderPass& pass) const {
@@ -276,8 +248,8 @@ bool TextContents::Render(const ContentContext& renderer,
276248
cmd.pipeline = renderer.GetGlyphAtlasPipeline(opts);
277249
cmd.stencil_reference = entity.GetStencilDepth();
278250

279-
return CommonRender<GlyphAtlasPipeline>(renderer, entity, pass, color, frame_,
280-
offset_, atlas, cmd);
251+
return CommonRender(renderer, entity, pass, color, frame_, offset_, atlas,
252+
cmd);
281253
}
282254

283255
} // namespace impeller

impeller/entity/contents/text_contents.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,6 @@ class TextContents final : public Contents {
4848
const Entity& entity,
4949
RenderPass& pass) const override;
5050

51-
// TODO(dnfield): remove this https://github.com/flutter/flutter/issues/111640
52-
bool RenderSdf(const ContentContext& renderer,
53-
const Entity& entity,
54-
RenderPass& pass) const;
55-
5651
private:
5752
TextFrame frame_;
5853
Color color_;

impeller/entity/entity_unittests.cc

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,34 +2151,6 @@ TEST_P(EntityTest, TTTBlendColor) {
21512151
}
21522152
}
21532153

2154-
TEST_P(EntityTest, SdfText) {
2155-
auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2156-
SkFont font;
2157-
font.setSize(30);
2158-
auto blob = SkTextBlob::MakeFromString(
2159-
"the quick brown fox jumped over the lazy dog (but with sdf).", font);
2160-
auto frame = TextFrameFromTextBlob(blob);
2161-
auto lazy_glyph_atlas = std::make_shared<LazyGlyphAtlas>();
2162-
lazy_glyph_atlas->AddTextFrame(frame);
2163-
2164-
EXPECT_FALSE(lazy_glyph_atlas->HasColor());
2165-
2166-
auto text_contents = std::make_shared<TextContents>();
2167-
text_contents->SetTextFrame(frame);
2168-
text_contents->SetGlyphAtlas(std::move(lazy_glyph_atlas));
2169-
text_contents->SetColor(Color(1.0, 0.0, 0.0, 1.0));
2170-
Entity entity;
2171-
entity.SetTransformation(
2172-
Matrix::MakeTranslation(Vector3{200.0, 200.0, 0.0}) *
2173-
Matrix::MakeScale(GetContentScale()));
2174-
entity.SetContents(text_contents);
2175-
2176-
// Force SDF rendering.
2177-
return text_contents->RenderSdf(context, entity, pass);
2178-
};
2179-
ASSERT_TRUE(OpenPlaygroundHere(callback));
2180-
}
2181-
21822154
TEST_P(EntityTest, AtlasContentsSubAtlas) {
21832155
auto boston = CreateTextureForFixture("boston.jpg");
21842156

impeller/typographer/backends/skia/text_render_context_skia.cc

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ static FontGlyphPair::Set CollectUniqueFontGlyphPairs(
4949
while (const TextFrame* frame = frame_iterator()) {
5050
for (const TextRun& run : frame->GetRuns()) {
5151
const Font& font = run.GetFont();
52-
// TODO(dnfield): If we're doing SDF here, we should be using a consistent
53-
// point size.
54-
// https://github.com/flutter/flutter/issues/112016
5552
for (const TextRun::GlyphPosition& glyph_position :
5653
run.GetGlyphPositions()) {
5754
set.insert({font, glyph_position.glyph});
@@ -171,121 +168,6 @@ ISize OptimumAtlasSizeForFontGlyphPairs(
171168
}
172169
} // namespace
173170

174-
/// Compute signed-distance field for an 8-bpp grayscale image (values greater
175-
/// than 127 are considered "on") For details of this algorithm, see "The 'dead
176-
/// reckoning' signed distance transform" [Grevera 2004]
177-
static void ConvertBitmapToSignedDistanceField(uint8_t* pixels,
178-
uint16_t width,
179-
uint16_t height) {
180-
if (!pixels || width == 0 || height == 0) {
181-
return;
182-
}
183-
184-
using ShortPoint = TPoint<uint16_t>;
185-
186-
// distance to nearest boundary point map
187-
std::vector<Scalar> distance_map(width * height);
188-
// nearest boundary point map
189-
std::vector<ShortPoint> boundary_point_map(width * height);
190-
191-
// Some helpers for manipulating the above arrays
192-
#define image(_x, _y) (pixels[(_y)*width + (_x)] > 0x7f)
193-
#define distance(_x, _y) distance_map[(_y)*width + (_x)]
194-
#define nearestpt(_x, _y) boundary_point_map[(_y)*width + (_x)]
195-
196-
const Scalar maxDist = hypot(width, height);
197-
const Scalar distUnit = 1;
198-
const Scalar distDiag = sqrt(2);
199-
200-
// Initialization phase: set all distances to "infinity"; zero out nearest
201-
// boundary point map
202-
for (uint16_t y = 0; y < height; ++y) {
203-
for (uint16_t x = 0; x < width; ++x) {
204-
distance(x, y) = maxDist;
205-
nearestpt(x, y) = ShortPoint{0, 0};
206-
}
207-
}
208-
209-
// Immediate interior/exterior phase: mark all points along the boundary as
210-
// such
211-
for (uint16_t y = 1; y < height - 1; ++y) {
212-
for (uint16_t x = 1; x < width - 1; ++x) {
213-
bool inside = image(x, y);
214-
if (image(x - 1, y) != inside || image(x + 1, y) != inside ||
215-
image(x, y - 1) != inside || image(x, y + 1) != inside) {
216-
distance(x, y) = 0;
217-
nearestpt(x, y) = ShortPoint{x, y};
218-
}
219-
}
220-
}
221-
222-
// Forward dead-reckoning pass
223-
for (uint16_t y = 1; y < height - 2; ++y) {
224-
for (uint16_t x = 1; x < width - 2; ++x) {
225-
if (distance_map[(y - 1) * width + (x - 1)] + distDiag < distance(x, y)) {
226-
nearestpt(x, y) = nearestpt(x - 1, y - 1);
227-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
228-
}
229-
if (distance(x, y - 1) + distUnit < distance(x, y)) {
230-
nearestpt(x, y) = nearestpt(x, y - 1);
231-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
232-
}
233-
if (distance(x + 1, y - 1) + distDiag < distance(x, y)) {
234-
nearestpt(x, y) = nearestpt(x + 1, y - 1);
235-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
236-
}
237-
if (distance(x - 1, y) + distUnit < distance(x, y)) {
238-
nearestpt(x, y) = nearestpt(x - 1, y);
239-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
240-
}
241-
}
242-
}
243-
244-
// Backward dead-reckoning pass
245-
for (uint16_t y = height - 2; y >= 1; --y) {
246-
for (uint16_t x = width - 2; x >= 1; --x) {
247-
if (distance(x + 1, y) + distUnit < distance(x, y)) {
248-
nearestpt(x, y) = nearestpt(x + 1, y);
249-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
250-
}
251-
if (distance(x - 1, y + 1) + distDiag < distance(x, y)) {
252-
nearestpt(x, y) = nearestpt(x - 1, y + 1);
253-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
254-
}
255-
if (distance(x, y + 1) + distUnit < distance(x, y)) {
256-
nearestpt(x, y) = nearestpt(x, y + 1);
257-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
258-
}
259-
if (distance(x + 1, y + 1) + distDiag < distance(x, y)) {
260-
nearestpt(x, y) = nearestpt(x + 1, y + 1);
261-
distance(x, y) = hypot(x - nearestpt(x, y).x, y - nearestpt(x, y).y);
262-
}
263-
}
264-
}
265-
266-
// Interior distance negation pass; distances outside the figure are
267-
// considered negative
268-
// Also does final quantization.
269-
for (uint16_t y = 0; y < height; ++y) {
270-
for (uint16_t x = 0; x < width; ++x) {
271-
if (!image(x, y)) {
272-
distance(x, y) = -distance(x, y);
273-
}
274-
275-
float norm_factor = 13.5;
276-
float dist = distance(x, y);
277-
float clamped_dist = fmax(-norm_factor, fmin(dist, norm_factor));
278-
float scaled_dist = clamped_dist / norm_factor;
279-
uint8_t quantized_value = ((scaled_dist + 1) / 2) * UINT8_MAX;
280-
pixels[y * width + x] = quantized_value;
281-
}
282-
}
283-
284-
#undef image
285-
#undef distance
286-
#undef nearestpt
287-
}
288-
289171
static void DrawGlyph(SkCanvas* canvas,
290172
const FontGlyphPair& font_glyph,
291173
const Rect& location,
@@ -353,7 +235,6 @@ static std::shared_ptr<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
353235
SkImageInfo image_info;
354236

355237
switch (atlas.GetType()) {
356-
case GlyphAtlas::Type::kSignedDistanceField:
357238
case GlyphAtlas::Type::kAlphaBitmap:
358239
image_info = SkImageInfo::MakeA8(atlas_size.width, atlas_size.height);
359240
break;
@@ -563,10 +444,6 @@ std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
563444
// ---------------------------------------------------------------------------
564445
PixelFormat format;
565446
switch (type) {
566-
case GlyphAtlas::Type::kSignedDistanceField:
567-
ConvertBitmapToSignedDistanceField(
568-
reinterpret_cast<uint8_t*>(bitmap->getPixels()), atlas_size.width,
569-
atlas_size.height);
570447
case GlyphAtlas::Type::kAlphaBitmap:
571448
format = PixelFormat::kA8UNormInt;
572449
break;

impeller/typographer/glyph_atlas.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@ class GlyphAtlas {
3232
//----------------------------------------------------------------------------
3333
/// @brief Describes how the glyphs are represented in the texture.
3434
enum class Type {
35-
//--------------------------------------------------------------------------
36-
/// The glyphs are represented at a fixed size in an 8-bit grayscale texture
37-
/// where the value of each pixel represents a signed-distance field that
38-
/// stores the glyph outlines.
39-
///
40-
kSignedDistanceField,
41-
4235
//--------------------------------------------------------------------------
4336
/// The glyphs are reprsented at their requested size using only an 8-bit
4437
/// alpha channel.

0 commit comments

Comments
 (0)