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
18 changes: 18 additions & 0 deletions assets/asset_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,24 @@ std::unique_ptr<fml::Mapping> AssetManager::GetAsMapping(
return nullptr;
}

// |AssetResolver|
std::vector<std::unique_ptr<fml::Mapping>> AssetManager::GetAsMappings(
const std::string& asset_pattern) const {
std::vector<std::unique_ptr<fml::Mapping>> mappings;
if (asset_pattern.size() == 0) {
return mappings;
}
TRACE_EVENT1("flutter", "AssetManager::GetAsMappings", "pattern",
asset_pattern.c_str());
for (const auto& resolver : resolvers_) {
auto resolver_mappings = resolver->GetAsMappings(asset_pattern);
mappings.insert(mappings.end(),
std::make_move_iterator(resolver_mappings.begin()),
std::make_move_iterator(resolver_mappings.end()));
}
return mappings;
}

// |AssetResolver|
bool AssetManager::IsValid() const {
return resolvers_.size() > 0;
Expand Down
4 changes: 4 additions & 0 deletions assets/asset_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class AssetManager final : public AssetResolver {
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;

// |AssetResolver|
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
const std::string& asset_pattern) const override;

private:
std::deque<std::unique_ptr<AssetResolver>> resolvers_;

Expand Down
7 changes: 7 additions & 0 deletions assets/asset_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ class AssetResolver {
[[nodiscard]] virtual std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const = 0;

// Same as GetAsMapping() but returns mappings for all files who's name
// matches |pattern|. Returns empty vector if no matching assets are found
[[nodiscard]] virtual std::vector<std::unique_ptr<fml::Mapping>>
GetAsMappings(const std::string& asset_pattern) const {
return {};
};

private:
FML_DISALLOW_COPY_AND_ASSIGN(AssetResolver);
};
Expand Down
29 changes: 29 additions & 0 deletions assets/directory_asset_bundle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "flutter/assets/directory_asset_bundle.h"

#include <regex>
#include <utility>

#include "flutter/fml/eintr_wrapper.h"
Expand Down Expand Up @@ -53,4 +54,32 @@ std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping(
return mapping;
}

std::vector<std::unique_ptr<fml::Mapping>> DirectoryAssetBundle::GetAsMappings(
const std::string& asset_pattern) const {
std::vector<std::unique_ptr<fml::Mapping>> mappings;
if (!is_valid_) {
FML_DLOG(WARNING) << "Asset bundle was not valid.";
return mappings;
}

std::regex asset_regex(asset_pattern);
fml::FileVisitor visitor = [&](const fml::UniqueFD& directory,
const std::string& filename) {
if (std::regex_match(filename, asset_regex)) {
auto mapping = std::make_unique<fml::FileMapping>(fml::OpenFile(
directory, filename.c_str(), false, fml::FilePermission::kRead));

if (mapping && mapping->IsValid()) {
mappings.push_back(std::move(mapping));
} else {
FML_LOG(ERROR) << "Mapping " << filename << " failed";
}
}
return true;
};
fml::VisitFilesRecursively(descriptor_, visitor);

return mappings;
}

} // namespace flutter
4 changes: 4 additions & 0 deletions assets/directory_asset_bundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class DirectoryAssetBundle : public AssetResolver {
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;

// |AssetResolver|
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
const std::string& asset_pattern) const override;

FML_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
};

Expand Down
7 changes: 4 additions & 3 deletions fml/concurrent_message_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/task_runner.h"

namespace fml {

Expand Down Expand Up @@ -58,13 +59,13 @@ class ConcurrentMessageLoop
FML_DISALLOW_COPY_AND_ASSIGN(ConcurrentMessageLoop);
};

class ConcurrentTaskRunner {
class ConcurrentTaskRunner : public BasicTaskRunner {
public:
ConcurrentTaskRunner(std::weak_ptr<ConcurrentMessageLoop> weak_loop);

~ConcurrentTaskRunner();
virtual ~ConcurrentTaskRunner();

void PostTask(const fml::closure& task);
void PostTask(const fml::closure& task) override;

private:
friend ConcurrentMessageLoop;
Expand Down
10 changes: 8 additions & 2 deletions fml/task_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ namespace fml {

class MessageLoopImpl;

class TaskRunner : public fml::RefCountedThreadSafe<TaskRunner> {
class BasicTaskRunner {
public:
virtual void PostTask(const fml::closure& task) = 0;
};

class TaskRunner : public fml::RefCountedThreadSafe<TaskRunner>,
public BasicTaskRunner {
public:
virtual ~TaskRunner();

virtual void PostTask(const fml::closure& task);
virtual void PostTask(const fml::closure& task) override;

virtual void PostTaskForTime(const fml::closure& task,
fml::TimePoint target_time);
Expand Down
10 changes: 10 additions & 0 deletions shell/common/persistent_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,14 @@ void PersistentCache::SetAssetManager(std::shared_ptr<AssetManager> value) {
asset_manager_ = value;
}

std::vector<std::unique_ptr<fml::Mapping>>
PersistentCache::GetSkpsFromAssetManager() const {
if (!asset_manager_) {
FML_LOG(ERROR)
<< "PersistentCache::GetSkpsFromAssetManager: Asset manager not set!";
return std::vector<std::unique_ptr<fml::Mapping>>();
}
return asset_manager_->GetAsMappings(".*\\.skp$");
}

} // namespace flutter
3 changes: 3 additions & 0 deletions shell/common/persistent_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class PersistentCache : public GrContextOptions::PersistentCache {
/// Load all the SkSL shader caches in the right directory.
std::vector<SkSLCache> LoadSkSLs();

// Return mappings for all skp's accessible through the AssetManager
std::vector<std::unique_ptr<fml::Mapping>> GetSkpsFromAssetManager() const;

/// Set the asset manager from which PersistentCache can load SkLSs. A nullptr
/// can be provided to clear the asset manager.
static void SetAssetManager(std::shared_ptr<AssetManager> value);
Expand Down
1 change: 1 addition & 0 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ static sk_sp<SkData> ScreenshotLayerTreeAsPicture(
#if defined(OS_FUCHSIA)
SkSerialProcs procs = {0};
procs.fImageProc = SerializeImageWithoutData;
procs.fTypefaceProc = SerializeTypefaceWithoutData;
#else
SkSerialProcs procs = {0};
procs.fTypefaceProc = SerializeTypefaceWithData;
Expand Down
9 changes: 8 additions & 1 deletion shell/common/serialization_callbacks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
#include "flutter/fml/logging.h"
#include "include/core/SkImage.h"
#include "include/core/SkPicture.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"

namespace flutter {

sk_sp<SkData> SerializeTypefaceWithoutData(SkTypeface* typeface, void* ctx) {
return typeface->serialize(SkTypeface::SerializeBehavior::kDontIncludeData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why the old line didn't work. I guess they should both save space, so is it because typeface->serialize(SkTypeface::SerializeBehavior::kDontIncludeData) somehow interfered with the Fuchsia typeface while SkData::MakeEmpty() won't?

Is this line also the reason why we need DeserializeTypefaceWithoutData?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit is from a while back so I don't 100% remember. IIRC even serializing typefaces with SerializeBehavior::kDontIncludeData caused the deserialized SkPictures to not be renderable (or maybe failed to deserialize, i dont quite remember) and talking with the Skia people about it I was advised that if all I wanted to do was warm up shaders they could vend be a special standin typeface which warms up all the typeface shaders and had me file https://bugs.chromium.org/p/skia/issues/detail?id=10404 for it. So basically this just serialized nothing and then on the deserialize path creates the default typeface. Once that skia feature is in DeserializeTypefaceWithoutData will return the special warmup typeface rather than the default typeface.

return SkData::MakeEmpty();
}

sk_sp<SkData> SerializeTypefaceWithData(SkTypeface* typeface, void* ctx) {
return typeface->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
}

sk_sp<SkTypeface> DeserializeTypefaceWithoutData(const void* data,
size_t length,
void* ctx) {
return SkTypeface::MakeDefault();
}

struct ImageMetaData {
int32_t width;
int32_t height;
Expand Down
3 changes: 3 additions & 0 deletions shell/common/serialization_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ namespace flutter {

sk_sp<SkData> SerializeTypefaceWithoutData(SkTypeface* typeface, void* ctx);
sk_sp<SkData> SerializeTypefaceWithData(SkTypeface* typeface, void* ctx);
sk_sp<SkTypeface> DeserializeTypefaceWithoutData(const void* data,
size_t length,
void* ctx);

// Serializes only the metadata of the image and not the underlying pixel data.
sk_sp<SkData> SerializeImageWithoutData(SkImage* image, void* ctx);
Expand Down
68 changes: 68 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <future>
#include <memory>

#include "assets/directory_asset_bundle.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/layers/picture_layer.h"
#include "flutter/flow/layers/transform_layer.h"
Expand Down Expand Up @@ -2208,5 +2209,72 @@ TEST_F(ShellTest, EngineRootIsolateLaunchesDontTakeVMDataSettings) {
isolate_create_latch.Wait();
}

TEST_F(ShellTest, AssetManagerSingle) {
fml::ScopedTemporaryDirectory asset_dir;
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
asset_dir.path().c_str(), false, fml::FilePermission::kRead);

std::string filename = "test_name";
std::string content = "test_content";

bool success = fml::WriteAtomically(asset_dir_fd, filename.c_str(),
fml::DataMapping(content));
ASSERT_TRUE(success);

AssetManager asset_manager;
asset_manager.PushBack(
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));

auto mapping = asset_manager.GetAsMapping(filename);
ASSERT_TRUE(mapping != nullptr);

std::string result(reinterpret_cast<const char*>(mapping->GetMapping()),
mapping->GetSize());

ASSERT_TRUE(result == content);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: add a new line here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


TEST_F(ShellTest, AssetManagerMulti) {
fml::ScopedTemporaryDirectory asset_dir;
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
asset_dir.path().c_str(), false, fml::FilePermission::kRead);

std::vector<std::string> filenames = {
"good0",
"bad0",
"good1",
"bad1",
};

for (auto filename : filenames) {
bool success = fml::WriteAtomically(asset_dir_fd, filename.c_str(),
fml::DataMapping(filename));
ASSERT_TRUE(success);
}

AssetManager asset_manager;
asset_manager.PushBack(
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));

auto mappings = asset_manager.GetAsMappings("(.*)");
ASSERT_TRUE(mappings.size() == 4);

std::vector<std::string> expected_results = {
"good0",
"good1",
};

mappings = asset_manager.GetAsMappings("(.*)good(.*)");
ASSERT_TRUE(mappings.size() == expected_results.size());

for (auto& mapping : mappings) {
std::string result(reinterpret_cast<const char*>(mapping->GetMapping()),
mapping->GetSize());
ASSERT_NE(
std::find(expected_results.begin(), expected_results.end(), result),
expected_results.end());
}
}

} // namespace testing
} // namespace flutter
59 changes: 56 additions & 3 deletions shell/common/skp_shader_warmup_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@
#include "flutter/shell/common/switches.h"
#include "flutter/shell/version/version.h"
#include "flutter/testing/testing.h"
#include "include/core/SkFont.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkTextBlob.h"

#if defined(OS_FUCHSIA)
#include "lib/sys/cpp/component_context.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need an #endif here or the namespace declarations are stripped out, this will cause problems on non-fuchsia builds

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this ifdef block wraps basically the entire file including the close braces on the namespace. I'll take an action item to comment the endif with "// defined(OS_FUCHSIA)" though

namespace flutter {
namespace testing {

#if defined(OS_FUCHSIA)

static void WaitForIO(Shell* shell) {
std::promise<bool> io_task_finished;
shell->GetTaskRunners().GetIOTaskRunner()->PostTask(
Expand Down Expand Up @@ -103,8 +107,13 @@ class SkpWarmupTest : public ShellTest {

SkDeserialProcs procs = {0};
procs.fImageProc = DeserializeImageWithoutData;
procs.fTypefaceProc = DeserializeTypefaceWithoutData;
sk_sp<SkPicture> picture =
SkPicture::MakeFromStream(stream.get(), &procs);
if (!picture) {
FML_LOG(ERROR) << "Failed to deserialize " << filename;
return true;
}
pictures.push_back(std::move(picture));
fd.reset();
}
Expand Down Expand Up @@ -242,7 +251,51 @@ TEST_F(SkpWarmupTest, Image) {
TestWarmup(draw_size, builder);
}

#endif
// Re-enable once https://bugs.chromium.org/p/skia/issues/detail?id=10404
// is fixed and integrated, or a workaround is found.
TEST_F(SkpWarmupTest, DISABLED_Text) {
auto context = sys::ComponentContext::Create();
fuchsia::fonts::ProviderSyncPtr sync_font_provider;
context->svc()->Connect(sync_font_provider.NewRequest());
auto font_mgr = SkFontMgr_New_Fuchsia(std::move(sync_font_provider));
auto raw_typeface =
font_mgr->matchFamilyStyle(nullptr, SkFontStyle::Normal());
auto typeface = sk_sp<SkTypeface>(raw_typeface);

SkFont font(typeface, 12);
auto text_blob =
SkTextBlob::MakeFromString("test", font, SkTextEncoding::kUTF8);

SkISize draw_size =
SkISize::Make(text_blob->bounds().width(), text_blob->bounds().height());
// We reuse this builder to draw the same content sever times in this test
LayerTreeBuilder builder = [&draw_size, &text_blob,
this](std::shared_ptr<ContainerLayer> root) {
SkPictureRecorder recorder;

auto canvas =
recorder.beginRecording(draw_size.width(), draw_size.height());

auto color_space = SkColorSpace::MakeSRGB();
auto paint = SkPaint(SkColors::kWhite, color_space.get());
canvas->drawTextBlob(text_blob, draw_size.width() / 2,
draw_size.height() / 2, paint);

auto picture = recorder.finishRecordingAsPicture();

fml::RefPtr<SkiaUnrefQueue> queue = fml::MakeRefCounted<SkiaUnrefQueue>(
this->GetCurrentTaskRunner(), fml::TimeDelta::FromSeconds(0));
auto picture_layer = std::make_shared<PictureLayer>(
SkPoint::Make(0, 0), SkiaGPUObject<SkPicture>(picture, queue),
/* is_complex */ false,
/* will_change */ false);
root->Add(picture_layer);
};

TestWarmup(draw_size, builder);
}

} // namespace testing
} // namespace flutter

#endif // defined(OS_FUCHSIA)
Loading