[Impeller] invalidate cached atlas data, take 2. (flutter/engine#56925)

Fixes https://github.com/flutter/flutter/issues/159704, but for real this time.
This commit is contained in:
Jonah Williams 2024-12-03 11:09:53 -08:00 committed by GitHub
parent 6f6e5611c2
commit 7dbe2f50a8
4 changed files with 21 additions and 14 deletions

View File

@ -5,6 +5,7 @@
#include "impeller/typographer/backends/skia/typographer_context_skia.h" #include "impeller/typographer/backends/skia/typographer_context_skia.h"
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <memory> #include <memory>
#include <numeric> #include <numeric>
#include <utility> #include <utility>
@ -414,14 +415,17 @@ TypographerContextSkia::CollectNewGlyphs(
std::vector<FontGlyphPair> new_glyphs; std::vector<FontGlyphPair> new_glyphs;
std::vector<Rect> glyph_sizes; std::vector<Rect> glyph_sizes;
size_t generation_id = atlas->GetAtlasGeneration(); size_t generation_id = atlas->GetAtlasGeneration();
intptr_t atlas_id = reinterpret_cast<intptr_t>(atlas.get());
for (const auto& frame : text_frames) { for (const auto& frame : text_frames) {
auto [frame_generation_id, frame_atlas_id] =
frame->GetAtlasGenerationAndID();
if (atlas->IsValid() && frame->IsFrameComplete() && if (atlas->IsValid() && frame->IsFrameComplete() &&
frame->GetAtlasGeneration() == generation_id && frame_generation_id == generation_id && frame_atlas_id == atlas_id &&
!frame->GetFrameBounds(0).is_placeholder) { !frame->GetFrameBounds(0).is_placeholder) {
continue; continue;
} }
frame->ClearFrameBounds(); frame->ClearFrameBounds();
frame->SetAtlasGeneration(generation_id); frame->SetAtlasGeneration(generation_id, atlas_id);
for (const auto& run : frame->GetRuns()) { for (const auto& run : frame->GetRuns()) {
auto metrics = run.GetFont().GetMetrics(); auto metrics = run.GetFont().GetMetrics();

View File

@ -144,12 +144,13 @@ const FrameBounds& TextFrame::GetFrameBounds(size_t index) const {
return bound_values_[index]; return bound_values_[index];
} }
size_t TextFrame::GetAtlasGeneration() const { std::pair<size_t, intptr_t> TextFrame::GetAtlasGenerationAndID() const {
return generation_; return std::make_pair(generation_, atlas_id_);
} }
void TextFrame::SetAtlasGeneration(size_t value) { void TextFrame::SetAtlasGeneration(size_t value, intptr_t atlas_id) {
generation_ = value; generation_ = value;
atlas_id_ = atlas_id;
} }
} // namespace impeller } // namespace impeller

View File

@ -5,6 +5,7 @@
#ifndef FLUTTER_IMPELLER_TYPOGRAPHER_TEXT_FRAME_H_ #ifndef FLUTTER_IMPELLER_TYPOGRAPHER_TEXT_FRAME_H_
#define FLUTTER_IMPELLER_TYPOGRAPHER_TEXT_FRAME_H_ #define FLUTTER_IMPELLER_TYPOGRAPHER_TEXT_FRAME_H_
#include <cstdint>
#include "impeller/typographer/glyph_atlas.h" #include "impeller/typographer/glyph_atlas.h"
#include "impeller/typographer/text_run.h" #include "impeller/typographer/text_run.h"
@ -88,7 +89,7 @@ class TextFrame {
// with. As long as the frame generation matches the atlas generation, // with. As long as the frame generation matches the atlas generation,
// the contents are guaranteed to be populated and do not need to be // the contents are guaranteed to be populated and do not need to be
// processed. // processed.
size_t GetAtlasGeneration() const; std::pair<size_t, intptr_t> GetAtlasGenerationAndID() const;
TextFrame& operator=(TextFrame&& other) = default; TextFrame& operator=(TextFrame&& other) = default;
@ -108,7 +109,7 @@ class TextFrame {
void ClearFrameBounds(); void ClearFrameBounds();
void SetAtlasGeneration(size_t value); void SetAtlasGeneration(size_t value, intptr_t atlas_id);
std::vector<TextRun> runs_; std::vector<TextRun> runs_;
Rect bounds_; Rect bounds_;
@ -119,6 +120,7 @@ class TextFrame {
std::vector<FrameBounds> bound_values_; std::vector<FrameBounds> bound_values_;
Scalar scale_ = 0; Scalar scale_ = 0;
size_t generation_ = 0; size_t generation_ = 0;
intptr_t atlas_id_ = 0;
Point offset_; Point offset_;
std::optional<GlyphProperties> properties_; std::optional<GlyphProperties> properties_;
}; };

View File

@ -585,9 +585,9 @@ TEST_P(TypographerTest, TextFrameAtlasGenerationTracksState) {
EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder); EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
if (GetBackend() == PlaygroundBackend::kOpenGLES) { if (GetBackend() == PlaygroundBackend::kOpenGLES) {
// OpenGLES must always increase the atlas backend if the texture grows. // OpenGLES must always increase the atlas backend if the texture grows.
EXPECT_EQ(frame->GetAtlasGeneration(), 1u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
} else { } else {
EXPECT_EQ(frame->GetAtlasGeneration(), 0u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
} }
atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer, atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
@ -598,9 +598,9 @@ TEST_P(TypographerTest, TextFrameAtlasGenerationTracksState) {
EXPECT_TRUE(frame->IsFrameComplete()); EXPECT_TRUE(frame->IsFrameComplete());
EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder); EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
if (GetBackend() == PlaygroundBackend::kOpenGLES) { if (GetBackend() == PlaygroundBackend::kOpenGLES) {
EXPECT_EQ(frame->GetAtlasGeneration(), 1u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
} else { } else {
EXPECT_EQ(frame->GetAtlasGeneration(), 0u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
} }
// Force increase the generation. // Force increase the generation.
@ -609,7 +609,7 @@ TEST_P(TypographerTest, TextFrameAtlasGenerationTracksState) {
GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f, GlyphAtlas::Type::kAlphaBitmap, /*scale=*/1.0f,
atlas_context, frame); atlas_context, frame);
EXPECT_EQ(frame->GetAtlasGeneration(), 2u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 2u);
} }
TEST_P(TypographerTest, InvalidAtlasForcesRepopulation) { TEST_P(TypographerTest, InvalidAtlasForcesRepopulation) {
@ -637,9 +637,9 @@ TEST_P(TypographerTest, InvalidAtlasForcesRepopulation) {
EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder); EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
if (GetBackend() == PlaygroundBackend::kOpenGLES) { if (GetBackend() == PlaygroundBackend::kOpenGLES) {
// OpenGLES must always increase the atlas backend if the texture grows. // OpenGLES must always increase the atlas backend if the texture grows.
EXPECT_EQ(frame->GetAtlasGeneration(), 1u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
} else { } else {
EXPECT_EQ(frame->GetAtlasGeneration(), 0u); EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
} }
auto second_context = TypographerContextSkia::Make(); auto second_context = TypographerContextSkia::Make();