Re-land "Support multiple shells in a single process. (#4932)" (flutter/engine#4977)
This reverts commit a1befb4f30.
This commit is contained in:
2
DEPS
2
DEPS
@@ -115,7 +115,7 @@ allowed_hosts = [
|
||||
]
|
||||
|
||||
deps = {
|
||||
'src': 'https://github.com/flutter/buildroot.git' + '@' + '8dddd90bf943a8174913564353b30a3b11ee0f7a',
|
||||
'src': 'https://github.com/flutter/buildroot.git' + '@' + '3cf97e01cdbd4bb920fa3d40282a56c4b2d62a58',
|
||||
|
||||
# Fuchsia compatibility
|
||||
#
|
||||
|
||||
@@ -10,14 +10,12 @@ group("flutter") {
|
||||
public_deps = [
|
||||
"$flutter_root/lib/snapshot:generate_snapshot_bin",
|
||||
"$flutter_root/lib/snapshot:kernel_platform_files",
|
||||
"$flutter_root/shell/testing",
|
||||
"$flutter_root/sky",
|
||||
"$flutter_root/third_party/txt",
|
||||
]
|
||||
|
||||
if (flutter_runtime_mode != "debug") {
|
||||
public_deps += [
|
||||
"$flutter_root/lib/snapshot:entry_points_json_files",
|
||||
]
|
||||
public_deps += [ "$flutter_root/lib/snapshot:entry_points_json_files" ]
|
||||
}
|
||||
|
||||
if (!is_fuchsia && !is_fuchsia_host) {
|
||||
@@ -45,20 +43,24 @@ group("flutter") {
|
||||
"$flutter_root/shell/platform/embedder:flutter_embedder_framework",
|
||||
]
|
||||
}
|
||||
|
||||
public_deps += [
|
||||
"$flutter_root/flow:flow_unittests",
|
||||
"$flutter_root/fml:fml_unittests",
|
||||
"$flutter_root/runtime:runtime_unittests",
|
||||
"$flutter_root/shell/common:shell_unittests",
|
||||
"$flutter_root/sky/engine/wtf:wtf_unittests",
|
||||
"$flutter_root/synchronization:synchronization_unittests",
|
||||
"$flutter_root/third_party/txt:txt_unittests",
|
||||
"//garnet/public/lib/fxl:fxl_unittests",
|
||||
]
|
||||
|
||||
if (!is_win) {
|
||||
public_deps += [
|
||||
"$flutter_root/shell/platform/embedder:embedder_unittests",
|
||||
"$flutter_root/shell/platform/embedder:flutter_engine",
|
||||
]
|
||||
}
|
||||
public_deps += [
|
||||
"$flutter_root/flow:flow_unittests",
|
||||
"$flutter_root/fml:fml_unittests",
|
||||
"$flutter_root/sky/engine/wtf:wtf_unittests",
|
||||
"$flutter_root/synchronization:synchronization_unittests",
|
||||
"$flutter_root/third_party/txt:txt_unittests",
|
||||
"//garnet/public/lib/fxl:fxl_unittests",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,29 +76,23 @@ if (is_fuchsia) {
|
||||
"$flutter_root/content_handler:aot",
|
||||
]
|
||||
if (flutter_runtime_mode != "release") {
|
||||
deps += [
|
||||
"//third_party/dart/runtime/observatory:embedded_archive_observatory",
|
||||
]
|
||||
deps += [ "//third_party/dart/runtime/observatory:embedded_archive_observatory" ]
|
||||
}
|
||||
|
||||
binary = "flutter_aot_runner"
|
||||
|
||||
if (flutter_runtime_mode != "release") {
|
||||
resources = [
|
||||
{
|
||||
path = rebase_path(
|
||||
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
|
||||
dest = "observatory.tar"
|
||||
},
|
||||
]
|
||||
resources = [ {
|
||||
path = rebase_path(
|
||||
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
|
||||
dest = "observatory.tar"
|
||||
} ]
|
||||
}
|
||||
|
||||
meta = [
|
||||
{
|
||||
path = rebase_path("content_handler/meta/sandbox")
|
||||
dest = "sandbox"
|
||||
},
|
||||
]
|
||||
meta = [ {
|
||||
path = rebase_path("content_handler/meta/sandbox")
|
||||
dest = "sandbox"
|
||||
} ]
|
||||
}
|
||||
|
||||
package("flutter_jit_runner") {
|
||||
@@ -104,29 +100,23 @@ if (is_fuchsia) {
|
||||
"$flutter_root/content_handler:jit",
|
||||
]
|
||||
if (flutter_runtime_mode != "release") {
|
||||
deps += [
|
||||
"//third_party/dart/runtime/observatory:embedded_archive_observatory",
|
||||
]
|
||||
deps += [ "//third_party/dart/runtime/observatory:embedded_archive_observatory" ]
|
||||
}
|
||||
|
||||
binary = "flutter_jit_runner"
|
||||
|
||||
if (flutter_runtime_mode != "release") {
|
||||
resources = [
|
||||
{
|
||||
path = rebase_path(
|
||||
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
|
||||
dest = "observatory.tar"
|
||||
},
|
||||
]
|
||||
resources = [ {
|
||||
path = rebase_path(
|
||||
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
|
||||
dest = "observatory.tar"
|
||||
} ]
|
||||
}
|
||||
|
||||
meta = [
|
||||
{
|
||||
path = rebase_path("content_handler/meta/sandbox")
|
||||
dest = "sandbox"
|
||||
},
|
||||
]
|
||||
meta = [ {
|
||||
path = rebase_path("content_handler/meta/sandbox")
|
||||
dest = "sandbox"
|
||||
} ]
|
||||
}
|
||||
} else {
|
||||
group("dist") {
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
|
||||
source_set("assets") {
|
||||
sources = [
|
||||
"asset_provider.h",
|
||||
"asset_manager.cc",
|
||||
"asset_manager.h",
|
||||
"asset_resolver.h",
|
||||
"directory_asset_bundle.cc",
|
||||
"directory_asset_bundle.h",
|
||||
"unzipper_provider.cc",
|
||||
"unzipper_provider.h",
|
||||
"zip_asset_store.cc",
|
||||
"zip_asset_store.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$flutter_root/common",
|
||||
"$flutter_root/fml",
|
||||
"$flutter_root/glue",
|
||||
"//garnet/public/lib/fxl",
|
||||
"//garnet/public/lib/zip",
|
||||
@@ -23,7 +25,5 @@ source_set("assets") {
|
||||
"//third_party/zlib:minizip",
|
||||
]
|
||||
|
||||
public_configs = [
|
||||
"$flutter_root:config",
|
||||
]
|
||||
public_configs = [ "$flutter_root:config" ]
|
||||
}
|
||||
|
||||
59
engine/src/flutter/assets/asset_manager.cc
Normal file
59
engine/src/flutter/assets/asset_manager.cc
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/assets/asset_manager.h"
|
||||
|
||||
#include "flutter/assets/directory_asset_bundle.h"
|
||||
#include "flutter/assets/zip_asset_store.h"
|
||||
#include "flutter/glue/trace_event.h"
|
||||
#include "lib/fxl/files/path.h"
|
||||
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
|
||||
namespace blink {
|
||||
|
||||
AssetManager::AssetManager() = default;
|
||||
|
||||
AssetManager::~AssetManager() = default;
|
||||
|
||||
void AssetManager::PushFront(std::unique_ptr<AssetResolver> resolver) {
|
||||
if (resolver == nullptr || !resolver->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
resolvers_.push_front(std::move(resolver));
|
||||
}
|
||||
|
||||
void AssetManager::PushBack(std::unique_ptr<AssetResolver> resolver) {
|
||||
if (resolver == nullptr || !resolver->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
resolvers_.push_back(std::move(resolver));
|
||||
}
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool AssetManager::GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) const {
|
||||
if (asset_name.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
TRACE_EVENT0("flutter", "AssetManager::GetAsBuffer");
|
||||
for (const auto& resolver : resolvers_) {
|
||||
if (resolver->GetAsBuffer(asset_name, data)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
FXL_DLOG(ERROR) << "Could not find asset: " << asset_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool AssetManager::IsValid() const {
|
||||
return resolvers_.size() > 0;
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
47
engine/src/flutter/assets/asset_manager.h
Normal file
47
engine/src/flutter/assets/asset_manager.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_ASSETS_ASSET_MANAGER_H_
|
||||
#define FLUTTER_ASSETS_ASSET_MANAGER_H_
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "flutter/assets/asset_resolver.h"
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class AssetManager final : public AssetResolver,
|
||||
public fxl::RefCountedThreadSafe<AssetManager> {
|
||||
public:
|
||||
void PushFront(std::unique_ptr<AssetResolver> resolver);
|
||||
|
||||
void PushBack(std::unique_ptr<AssetResolver> resolver);
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool IsValid() const override;
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) const override;
|
||||
|
||||
private:
|
||||
std::deque<std::unique_ptr<AssetResolver>> resolvers_;
|
||||
|
||||
AssetManager();
|
||||
|
||||
~AssetManager();
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(AssetManager);
|
||||
FRIEND_MAKE_REF_COUNTED(AssetManager);
|
||||
FRIEND_REF_COUNTED_THREAD_SAFE(AssetManager);
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif // FLUTTER_ASSETS_ASSET_MANAGER_H_
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_ASSETS_ASSET_PROVIDER_H_
|
||||
#define FLUTTER_ASSETS_ASSET_PROVIDER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class AssetProvider
|
||||
: public fxl::RefCountedThreadSafe<AssetProvider>
|
||||
{
|
||||
public:
|
||||
virtual bool GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) = 0;
|
||||
virtual ~AssetProvider() = default;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
#endif // FLUTTER_ASSETS_ASSET_PROVIDER_H
|
||||
32
engine/src/flutter/assets/asset_resolver.h
Normal file
32
engine/src/flutter/assets/asset_resolver.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_ASSETS_ASSET_RESOLVER_H_
|
||||
#define FLUTTER_ASSETS_ASSET_RESOLVER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class AssetResolver {
|
||||
public:
|
||||
AssetResolver() = default;
|
||||
|
||||
virtual ~AssetResolver() = default;
|
||||
|
||||
virtual bool IsValid() const = 0;
|
||||
|
||||
virtual bool GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) const = 0;
|
||||
|
||||
private:
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(AssetResolver);
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif // FLUTTER_ASSETS_ASSET_RESOLVER_H_
|
||||
@@ -3,73 +3,54 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/assets/directory_asset_bundle.h"
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/fml/file.h"
|
||||
#include "flutter/fml/mapping.h"
|
||||
#include "lib/fxl/files/eintr_wrapper.h"
|
||||
#include "lib/fxl/files/file.h"
|
||||
#include "lib/fxl/files/path.h"
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "lib/fxl/portable_unistd.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) {
|
||||
if (fd_.is_valid()) {
|
||||
#if defined(OS_WIN)
|
||||
// This code path is not valid in a Windows environment.
|
||||
return false;
|
||||
#else
|
||||
fxl::UniqueFD asset_file(openat(fd_.get(), asset_name.c_str(), O_RDONLY));
|
||||
if (!asset_file.is_valid())
|
||||
return false;
|
||||
|
||||
constexpr size_t kBufferSize = 1 << 16;
|
||||
size_t offset = 0;
|
||||
ssize_t bytes_read = 0;
|
||||
do {
|
||||
offset += bytes_read;
|
||||
data->resize(offset + kBufferSize);
|
||||
bytes_read = read(asset_file.get(), &(*data)[offset], kBufferSize);
|
||||
} while (bytes_read > 0);
|
||||
|
||||
if (bytes_read < 0) {
|
||||
FXL_LOG(ERROR) << "Reading " << asset_name << " failed";
|
||||
data->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
data->resize(offset + bytes_read);
|
||||
return true;
|
||||
#endif
|
||||
DirectoryAssetBundle::DirectoryAssetBundle(fml::UniqueFD descriptor)
|
||||
: descriptor_(std::move(descriptor)) {
|
||||
if (!fml::IsDirectory(descriptor_)) {
|
||||
return;
|
||||
}
|
||||
std::string asset_path = GetPathForAsset(asset_name);
|
||||
if (asset_path.empty())
|
||||
return false;
|
||||
return files::ReadFileToVector(asset_path, data);
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
DirectoryAssetBundle::~DirectoryAssetBundle() {}
|
||||
DirectoryAssetBundle::~DirectoryAssetBundle() = default;
|
||||
|
||||
DirectoryAssetBundle::DirectoryAssetBundle(std::string directory)
|
||||
: directory_(std::move(directory)), fd_() {}
|
||||
// |blink::AssetResolver|
|
||||
bool DirectoryAssetBundle::IsValid() const {
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
DirectoryAssetBundle::DirectoryAssetBundle(fxl::UniqueFD fd)
|
||||
: fd_(std::move(fd)) {}
|
||||
|
||||
std::string DirectoryAssetBundle::GetPathForAsset(
|
||||
const std::string& asset_name) {
|
||||
std::string asset_path = files::SimplifyPath(directory_ + "/" + asset_name);
|
||||
if (asset_path.find(directory_) != 0u) {
|
||||
FXL_LOG(ERROR) << "Asset name '" << asset_name
|
||||
<< "' attempted to traverse outside asset bundle.";
|
||||
return std::string();
|
||||
// |blink::AssetResolver|
|
||||
bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) const {
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return asset_path;
|
||||
|
||||
if (!is_valid_) {
|
||||
FXL_DLOG(WARNING) << "Asset bundle was not valid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
fml::FileMapping mapping(
|
||||
fml::OpenFile(descriptor_, asset_name.c_str(), fml::OpenPermission::kRead,
|
||||
false /* directory */),
|
||||
false /* executable */);
|
||||
|
||||
if (mapping.GetMapping() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data->resize(mapping.GetSize());
|
||||
memmove(data->data(), mapping.GetMapping(), mapping.GetSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -5,31 +5,31 @@
|
||||
#ifndef FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
|
||||
#define FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/assets/asset_provider.h"
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "flutter/assets/asset_resolver.h"
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class DirectoryAssetBundle
|
||||
: public AssetProvider {
|
||||
class DirectoryAssetBundle : public AssetResolver {
|
||||
public:
|
||||
explicit DirectoryAssetBundle(std::string directory);
|
||||
// Expects fd to be valid, otherwise the file descriptor is ignored.
|
||||
explicit DirectoryAssetBundle(fxl::UniqueFD fd);
|
||||
virtual ~DirectoryAssetBundle();
|
||||
explicit DirectoryAssetBundle(fml::UniqueFD descriptor);
|
||||
|
||||
virtual bool GetAsBuffer(const std::string& asset_name, std::vector<uint8_t>* data);
|
||||
|
||||
std::string GetPathForAsset(const std::string& asset_name);
|
||||
~DirectoryAssetBundle() override;
|
||||
|
||||
private:
|
||||
const std::string directory_;
|
||||
fxl::UniqueFD fd_;
|
||||
const fml::UniqueFD descriptor_;
|
||||
bool is_valid_ = false;
|
||||
|
||||
std::string GetPathForAsset(const std::string& asset_name) const;
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool IsValid() const override;
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) const override;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/assets/unzipper_provider.h"
|
||||
|
||||
#include "lib/fxl/logging.h"
|
||||
#include "third_party/zlib/contrib/minizip/unzip.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
UnzipperProvider GetUnzipperProviderForPath(std::string zip_path) {
|
||||
return [zip_path]() {
|
||||
zip::UniqueUnzipper unzipper(unzOpen2(zip_path.c_str(), nullptr));
|
||||
if (!unzipper.is_valid())
|
||||
FXL_LOG(ERROR) << "Unable to open zip file: " << zip_path;
|
||||
return unzipper;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_ASSETS_UNZIP_PROVIDER_H_
|
||||
#define FLUTTER_ASSETS_UNZIP_PROVIDER_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "lib/zip/unique_unzipper.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
using UnzipperProvider = std::function<zip::UniqueUnzipper()>;
|
||||
|
||||
UnzipperProvider GetUnzipperProviderForPath(std::string zip_path);
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif // FLUTTER_ASSETS_UNZIP_PROVIDER_H_
|
||||
@@ -15,21 +15,28 @@
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/glue/trace_event.h"
|
||||
#include "lib/fxl/files/eintr_wrapper.h"
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "lib/zip/unique_unzipper.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
ZipAssetStore::ZipAssetStore(UnzipperProvider unzipper_provider)
|
||||
: unzipper_provider_(std::move(unzipper_provider)) {
|
||||
ZipAssetStore::ZipAssetStore(std::string file_path)
|
||||
: file_path_(std::move(file_path)) {
|
||||
BuildStatCache();
|
||||
}
|
||||
|
||||
ZipAssetStore::~ZipAssetStore() = default;
|
||||
|
||||
zip::UniqueUnzipper ZipAssetStore::CreateUnzipper() const {
|
||||
return zip::UniqueUnzipper{::unzOpen2(file_path_.c_str(), nullptr)};
|
||||
}
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool ZipAssetStore::IsValid() const {
|
||||
return stat_cache_.size() > 0;
|
||||
}
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) {
|
||||
std::vector<uint8_t>* data) const {
|
||||
TRACE_EVENT0("flutter", "ZipAssetStore::GetAsBuffer");
|
||||
auto found = stat_cache_.find(asset_name);
|
||||
|
||||
@@ -37,7 +44,7 @@ bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
|
||||
return false;
|
||||
}
|
||||
|
||||
auto unzipper = unzipper_provider_();
|
||||
auto unzipper = CreateUnzipper();
|
||||
|
||||
if (!unzipper.is_valid()) {
|
||||
return false;
|
||||
@@ -73,7 +80,8 @@ bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
|
||||
|
||||
void ZipAssetStore::BuildStatCache() {
|
||||
TRACE_EVENT0("flutter", "ZipAssetStore::BuildStatCache");
|
||||
auto unzipper = unzipper_provider_();
|
||||
|
||||
auto unzipper = CreateUnzipper();
|
||||
|
||||
if (!unzipper.is_valid()) {
|
||||
return;
|
||||
|
||||
@@ -6,21 +6,20 @@
|
||||
#define FLUTTER_ASSETS_ZIP_ASSET_STORE_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/assets/unzipper_provider.h"
|
||||
#include "flutter/assets/asset_resolver.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
#include "lib/zip/unique_unzipper.h"
|
||||
#include "third_party/zlib/contrib/minizip/unzip.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class ZipAssetStore : public fxl::RefCountedThreadSafe<ZipAssetStore> {
|
||||
class ZipAssetStore final : public AssetResolver {
|
||||
public:
|
||||
explicit ZipAssetStore(UnzipperProvider unzipper_provider);
|
||||
~ZipAssetStore();
|
||||
ZipAssetStore(std::string file_path);
|
||||
|
||||
bool GetAsBuffer(const std::string& asset_name, std::vector<uint8_t>* data);
|
||||
~ZipAssetStore() override;
|
||||
|
||||
private:
|
||||
struct CacheEntry {
|
||||
@@ -30,11 +29,20 @@ class ZipAssetStore : public fxl::RefCountedThreadSafe<ZipAssetStore> {
|
||||
: file_pos(p_file_pos), uncompressed_size(p_uncompressed_size) {}
|
||||
};
|
||||
|
||||
UnzipperProvider unzipper_provider_;
|
||||
std::map<std::string, CacheEntry> stat_cache_;
|
||||
std::string file_path_;
|
||||
mutable std::map<std::string, CacheEntry> stat_cache_;
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool IsValid() const override;
|
||||
|
||||
// |blink::AssetResolver|
|
||||
bool GetAsBuffer(const std::string& asset_name,
|
||||
std::vector<uint8_t>* data) const override;
|
||||
|
||||
void BuildStatCache();
|
||||
|
||||
zip::UniqueUnzipper CreateUnzipper() const;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(ZipAssetStore);
|
||||
};
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@ source_set("common") {
|
||||
sources = [
|
||||
"settings.cc",
|
||||
"settings.h",
|
||||
"threads.cc",
|
||||
"threads.h",
|
||||
"task_runners.cc",
|
||||
"task_runners.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$flutter_root/fml",
|
||||
"//garnet/public/lib/fxl",
|
||||
]
|
||||
|
||||
|
||||
@@ -4,26 +4,50 @@
|
||||
|
||||
#include "flutter/common/settings.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "lib/fxl/logging.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace blink {
|
||||
namespace {
|
||||
|
||||
Settings* g_settings = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
const Settings& Settings::Get() {
|
||||
FXL_CHECK(g_settings);
|
||||
return *g_settings;
|
||||
}
|
||||
|
||||
void Settings::Set(const Settings& settings) {
|
||||
FXL_CHECK(!g_settings);
|
||||
g_settings = new Settings();
|
||||
*g_settings = settings;
|
||||
std::string Settings::ToString() const {
|
||||
std::stringstream stream;
|
||||
stream << "Settings: " << std::endl;
|
||||
stream << "aot_snapshot_path: " << aot_snapshot_path << std::endl;
|
||||
stream << "script_snapshot_path: " << script_snapshot_path << std::endl;
|
||||
stream << "aot_vm_snapshot_data_filename: " << aot_vm_snapshot_data_filename
|
||||
<< std::endl;
|
||||
stream << "aot_vm_snapshot_instr_filename: " << aot_vm_snapshot_instr_filename
|
||||
<< std::endl;
|
||||
stream << "aot_isolate_snapshot_data_filename: "
|
||||
<< aot_isolate_snapshot_data_filename << std::endl;
|
||||
stream << "aot_isolate_snapshot_instr_filename: "
|
||||
<< aot_isolate_snapshot_instr_filename << std::endl;
|
||||
stream << "application_library_path: " << application_library_path
|
||||
<< std::endl;
|
||||
stream << "main_dart_file_path: " << main_dart_file_path << std::endl;
|
||||
stream << "packages_file_path: " << packages_file_path << std::endl;
|
||||
stream << "temp_directory_path: " << temp_directory_path << std::endl;
|
||||
stream << "dart_flags:" << std::endl;
|
||||
for (const auto& dart_flag : dart_flags) {
|
||||
stream << " " << dart_flag << std::endl;
|
||||
}
|
||||
stream << "start_paused: " << start_paused << std::endl;
|
||||
stream << "trace_skia: " << trace_skia << std::endl;
|
||||
stream << "trace_startup: " << trace_startup << std::endl;
|
||||
stream << "endless_trace_buffer: " << endless_trace_buffer << std::endl;
|
||||
stream << "enable_dart_profiling: " << enable_dart_profiling << std::endl;
|
||||
stream << "dart_non_checked_mode: " << dart_non_checked_mode << std::endl;
|
||||
stream << "enable_observatory: " << enable_observatory << std::endl;
|
||||
stream << "observatory_port: " << observatory_port << std::endl;
|
||||
stream << "ipv6: " << ipv6 << std::endl;
|
||||
stream << "use_test_fonts: " << use_test_fonts << std::endl;
|
||||
stream << "enable_software_rendering: " << enable_software_rendering
|
||||
<< std::endl;
|
||||
stream << "using_blink: " << using_blink << std::endl;
|
||||
stream << "log_tag: " << log_tag << std::endl;
|
||||
stream << "icu_data_path: " << icu_data_path << std::endl;
|
||||
stream << "assets_dir: " << assets_dir << std::endl;
|
||||
stream << "assets_path: " << assets_path << std::endl;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -5,40 +5,82 @@
|
||||
#ifndef FLUTTER_COMMON_SETTINGS_H_
|
||||
#define FLUTTER_COMMON_SETTINGS_H_
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "lib/fxl/functional/closure.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
using TaskObserverAdd =
|
||||
std::function<void(intptr_t /* key */, fxl::Closure /* callback */)>;
|
||||
using TaskObserverRemove = std::function<void(intptr_t /* key */)>;
|
||||
|
||||
struct Settings {
|
||||
bool enable_observatory = false;
|
||||
// Port on target will be auto selected by the OS. A message will be printed
|
||||
// on the target with the port after it has been selected.
|
||||
uint32_t observatory_port = 0;
|
||||
bool ipv6 = false;
|
||||
bool start_paused = false;
|
||||
bool trace_startup = false;
|
||||
bool endless_trace_buffer = false;
|
||||
bool enable_dart_profiling = false;
|
||||
bool use_test_fonts = false;
|
||||
bool dart_non_checked_mode = false;
|
||||
bool enable_software_rendering = false;
|
||||
bool using_blink = true;
|
||||
std::string aot_shared_library_path;
|
||||
// VM settings
|
||||
std::string script_snapshot_path;
|
||||
std::string kernel_snapshot_path;
|
||||
|
||||
std::string aot_snapshot_path;
|
||||
std::string aot_vm_snapshot_data_filename;
|
||||
std::string aot_vm_snapshot_instr_filename;
|
||||
std::string aot_isolate_snapshot_data_filename;
|
||||
std::string aot_isolate_snapshot_instr_filename;
|
||||
|
||||
std::string application_library_path;
|
||||
std::string application_kernel_asset;
|
||||
|
||||
std::string main_dart_file_path;
|
||||
std::string packages_file_path;
|
||||
|
||||
std::string temp_directory_path;
|
||||
std::vector<std::string> dart_flags;
|
||||
std::string log_tag = "flutter";
|
||||
|
||||
static const Settings& Get();
|
||||
static void Set(const Settings& settings);
|
||||
// Isolate settings
|
||||
bool start_paused = false;
|
||||
bool trace_skia = false;
|
||||
bool trace_startup = false;
|
||||
bool endless_trace_buffer = false;
|
||||
bool enable_dart_profiling = false;
|
||||
bool dart_non_checked_mode = false;
|
||||
|
||||
// Observatory settings
|
||||
bool enable_observatory = false;
|
||||
// Port on target will be auto selected by the OS. A message will be printed
|
||||
// on the target with the port after it has been selected.
|
||||
uint32_t observatory_port = 0;
|
||||
bool ipv6 = false;
|
||||
|
||||
// Font settings
|
||||
bool use_test_fonts = false;
|
||||
|
||||
// Engine settings
|
||||
TaskObserverAdd task_observer_add;
|
||||
TaskObserverRemove task_observer_remove;
|
||||
// The main isolate is current when this callback is made. This is a good spot
|
||||
// to perform native Dart bindings for libraries not built in.
|
||||
fxl::Closure root_isolate_create_callback;
|
||||
// The isolate is not current and may have already been destroyed when this
|
||||
// call is made.
|
||||
fxl::Closure root_isolate_shutdown_callback;
|
||||
bool enable_software_rendering = false;
|
||||
bool using_blink = false;
|
||||
bool skia_deterministic_rendering_on_cpu = false;
|
||||
std::string log_tag = "flutter";
|
||||
std::string icu_data_path;
|
||||
|
||||
// Assets settings
|
||||
fml::UniqueFD::element_type assets_dir =
|
||||
fml::UniqueFD::traits_type::InvalidValue();
|
||||
std::string assets_path;
|
||||
std::string flx_path;
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
48
engine/src/flutter/common/task_runners.cc
Normal file
48
engine/src/flutter/common/task_runners.cc
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/common/task_runners.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace blink {
|
||||
|
||||
TaskRunners::TaskRunners(std::string label,
|
||||
fxl::RefPtr<fxl::TaskRunner> platform,
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui,
|
||||
fxl::RefPtr<fxl::TaskRunner> io)
|
||||
: label_(std::move(label)),
|
||||
platform_(std::move(platform)),
|
||||
gpu_(std::move(gpu)),
|
||||
ui_(std::move(ui)),
|
||||
io_(std::move(io)) {}
|
||||
|
||||
TaskRunners::~TaskRunners() = default;
|
||||
|
||||
const std::string& TaskRunners::GetLabel() const {
|
||||
return label_;
|
||||
}
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetPlatformTaskRunner() const {
|
||||
return platform_;
|
||||
}
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetUITaskRunner() const {
|
||||
return ui_;
|
||||
}
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetIOTaskRunner() const {
|
||||
return io_;
|
||||
}
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetGPUTaskRunner() const {
|
||||
return gpu_;
|
||||
}
|
||||
|
||||
bool TaskRunners::IsValid() const {
|
||||
return platform_ && gpu_ && ui_ && io_;
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
46
engine/src/flutter/common/task_runners.h
Normal file
46
engine/src/flutter/common/task_runners.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_COMMON_TASK_RUNNERS_H_
|
||||
#define FLUTTER_COMMON_TASK_RUNNERS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/tasks/task_runner.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class TaskRunners {
|
||||
public:
|
||||
TaskRunners(std::string label,
|
||||
fxl::RefPtr<fxl::TaskRunner> platform,
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui,
|
||||
fxl::RefPtr<fxl::TaskRunner> io);
|
||||
|
||||
~TaskRunners();
|
||||
|
||||
const std::string& GetLabel() const;
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> GetPlatformTaskRunner() const;
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> GetUITaskRunner() const;
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> GetIOTaskRunner() const;
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> GetGPUTaskRunner() const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
private:
|
||||
const std::string label_;
|
||||
fxl::RefPtr<fxl::TaskRunner> platform_;
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu_;
|
||||
fxl::RefPtr<fxl::TaskRunner> ui_;
|
||||
fxl::RefPtr<fxl::TaskRunner> io_;
|
||||
};
|
||||
} // namespace blink
|
||||
|
||||
#endif // FLUTTER_COMMON_TASK_RUNNERS_H_
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace blink {
|
||||
namespace {
|
||||
|
||||
Threads* g_threads = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
Threads::Threads() {}
|
||||
|
||||
Threads::Threads(fxl::RefPtr<fxl::TaskRunner> platform,
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui,
|
||||
fxl::RefPtr<fxl::TaskRunner> io)
|
||||
: platform_(std::move(platform)),
|
||||
gpu_(std::move(gpu)),
|
||||
ui_(std::move(ui)),
|
||||
io_(std::move(io)) {}
|
||||
|
||||
Threads::~Threads() {}
|
||||
|
||||
const fxl::RefPtr<fxl::TaskRunner>& Threads::Platform() {
|
||||
return Get().platform_;
|
||||
}
|
||||
|
||||
const fxl::RefPtr<fxl::TaskRunner>& Threads::Gpu() {
|
||||
return Get().gpu_;
|
||||
}
|
||||
|
||||
const fxl::RefPtr<fxl::TaskRunner>& Threads::UI() {
|
||||
return Get().ui_;
|
||||
}
|
||||
|
||||
const fxl::RefPtr<fxl::TaskRunner>& Threads::IO() {
|
||||
return Get().io_;
|
||||
}
|
||||
|
||||
const Threads& Threads::Get() {
|
||||
FXL_CHECK(g_threads);
|
||||
return *g_threads;
|
||||
}
|
||||
|
||||
void Threads::Set(const Threads& threads) {
|
||||
FXL_CHECK(!g_threads);
|
||||
g_threads = new Threads();
|
||||
*g_threads = threads;
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_COMMON_THREADS_H_
|
||||
#define FLUTTER_COMMON_THREADS_H_
|
||||
|
||||
#include "lib/fxl/tasks/task_runner.h"
|
||||
|
||||
#define ASSERT_IS_PLATFORM_THREAD \
|
||||
FXL_DCHECK(::blink::Threads::Platform()->RunsTasksOnCurrentThread());
|
||||
#define ASSERT_IS_GPU_THREAD \
|
||||
FXL_DCHECK(::blink::Threads::Gpu()->RunsTasksOnCurrentThread());
|
||||
#define ASSERT_IS_UI_THREAD \
|
||||
FXL_DCHECK(::blink::Threads::UI()->RunsTasksOnCurrentThread());
|
||||
#define ASSERT_IS_IO_THREAD \
|
||||
FXL_DCHECK(::blink::Threads::IO()->RunsTasksOnCurrentThread());
|
||||
|
||||
namespace blink {
|
||||
|
||||
class Threads {
|
||||
public:
|
||||
Threads();
|
||||
Threads(fxl::RefPtr<fxl::TaskRunner> platform,
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui,
|
||||
fxl::RefPtr<fxl::TaskRunner> io);
|
||||
~Threads();
|
||||
|
||||
static const fxl::RefPtr<fxl::TaskRunner>& Platform();
|
||||
static const fxl::RefPtr<fxl::TaskRunner>& Gpu();
|
||||
static const fxl::RefPtr<fxl::TaskRunner>& UI();
|
||||
static const fxl::RefPtr<fxl::TaskRunner>& IO();
|
||||
|
||||
static void Set(const Threads& settings);
|
||||
|
||||
private:
|
||||
static const Threads& Get();
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> platform_;
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu_;
|
||||
fxl::RefPtr<fxl::TaskRunner> ui_;
|
||||
fxl::RefPtr<fxl::TaskRunner> io_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif // FLUTTER_COMMON_THREADS_H_
|
||||
@@ -48,11 +48,12 @@ source_set("flow") {
|
||||
"matrix_decomposition.h",
|
||||
"paint_utils.cc",
|
||||
"paint_utils.h",
|
||||
"process_info.h",
|
||||
"raster_cache.cc",
|
||||
"raster_cache.h",
|
||||
"raster_cache_key.cc",
|
||||
"raster_cache_key.h",
|
||||
"skia_gpu_object.cc",
|
||||
"skia_gpu_object.h",
|
||||
"texture.cc",
|
||||
"texture.h",
|
||||
]
|
||||
@@ -61,12 +62,11 @@ source_set("flow") {
|
||||
"//garnet/public/lib/fxl",
|
||||
]
|
||||
|
||||
public_configs = [
|
||||
"$flutter_root:config",
|
||||
]
|
||||
public_configs = [ "$flutter_root:config" ]
|
||||
|
||||
deps = [
|
||||
"$flutter_root/common",
|
||||
"$flutter_root/fml",
|
||||
"$flutter_root/glue",
|
||||
"$flutter_root/synchronization",
|
||||
"//third_party/skia",
|
||||
@@ -103,8 +103,8 @@ executable("flow_unittests") {
|
||||
|
||||
deps = [
|
||||
":flow",
|
||||
"//third_party/dart/runtime:libdart_jit", # for tracing
|
||||
"$flutter_root/testing",
|
||||
"//third_party/dart/runtime:libdart_jit", # for tracing
|
||||
"//third_party/skia",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
#include "flutter/flow/compositor_context.h"
|
||||
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
CompositorContext::CompositorContext(std::unique_ptr<ProcessInfo> info)
|
||||
: process_info_(std::move(info)) {}
|
||||
CompositorContext::CompositorContext() = default;
|
||||
|
||||
CompositorContext::~CompositorContext() = default;
|
||||
|
||||
@@ -18,10 +18,6 @@ void CompositorContext::BeginFrame(ScopedFrame& frame,
|
||||
if (enable_instrumentation) {
|
||||
frame_count_.Increment();
|
||||
frame_time_.Start();
|
||||
|
||||
if (process_info_ && process_info_->SampleNow()) {
|
||||
memory_usage_.Add(process_info_->GetResidentMemorySize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +29,12 @@ void CompositorContext::EndFrame(ScopedFrame& frame,
|
||||
}
|
||||
}
|
||||
|
||||
CompositorContext::ScopedFrame CompositorContext::AcquireFrame(
|
||||
std::unique_ptr<CompositorContext::ScopedFrame> CompositorContext::AcquireFrame(
|
||||
GrContext* gr_context,
|
||||
SkCanvas* canvas,
|
||||
bool instrumentation_enabled) {
|
||||
return ScopedFrame(*this, gr_context, canvas, instrumentation_enabled);
|
||||
return std::make_unique<ScopedFrame>(*this, gr_context, canvas,
|
||||
instrumentation_enabled);
|
||||
}
|
||||
|
||||
CompositorContext::ScopedFrame::ScopedFrame(CompositorContext& context,
|
||||
@@ -51,18 +48,23 @@ CompositorContext::ScopedFrame::ScopedFrame(CompositorContext& context,
|
||||
context_.BeginFrame(*this, instrumentation_enabled_);
|
||||
}
|
||||
|
||||
CompositorContext::ScopedFrame::ScopedFrame(ScopedFrame&& frame) = default;
|
||||
|
||||
CompositorContext::ScopedFrame::~ScopedFrame() {
|
||||
context_.EndFrame(*this, instrumentation_enabled_);
|
||||
}
|
||||
|
||||
bool CompositorContext::ScopedFrame::Raster(flow::LayerTree& layer_tree,
|
||||
bool ignore_raster_cache) {
|
||||
layer_tree.Preroll(*this, ignore_raster_cache);
|
||||
layer_tree.Paint(*this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompositorContext::OnGrContextCreated() {
|
||||
texture_registry_->OnGrContextCreated();
|
||||
texture_registry_.OnGrContextCreated();
|
||||
}
|
||||
|
||||
void CompositorContext::OnGrContextDestroyed() {
|
||||
texture_registry_->OnGrContextDestroyed();
|
||||
texture_registry_.OnGrContextDestroyed();
|
||||
raster_cache_.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <string>
|
||||
|
||||
#include "flutter/flow/instrumentation.h"
|
||||
#include "flutter/flow/process_info.h"
|
||||
#include "flutter/flow/raster_cache.h"
|
||||
#include "flutter/flow/texture.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
@@ -18,19 +17,26 @@
|
||||
|
||||
namespace flow {
|
||||
|
||||
class LayerTree;
|
||||
|
||||
class CompositorContext {
|
||||
public:
|
||||
class ScopedFrame {
|
||||
public:
|
||||
ScopedFrame(CompositorContext& context,
|
||||
GrContext* gr_context,
|
||||
SkCanvas* canvas,
|
||||
bool instrumentation_enabled);
|
||||
|
||||
virtual ~ScopedFrame();
|
||||
|
||||
SkCanvas* canvas() { return canvas_; }
|
||||
|
||||
CompositorContext& context() const { return context_; }
|
||||
|
||||
GrContext* gr_context() const { return gr_context_; }
|
||||
|
||||
ScopedFrame(ScopedFrame&& frame);
|
||||
|
||||
~ScopedFrame();
|
||||
virtual bool Raster(LayerTree& layer_tree, bool ignore_raster_cache);
|
||||
|
||||
private:
|
||||
CompositorContext& context_;
|
||||
@@ -38,23 +44,17 @@ class CompositorContext {
|
||||
SkCanvas* canvas_;
|
||||
const bool instrumentation_enabled_;
|
||||
|
||||
ScopedFrame(CompositorContext& context,
|
||||
GrContext* gr_context,
|
||||
SkCanvas* canvas,
|
||||
bool instrumentation_enabled);
|
||||
|
||||
friend class CompositorContext;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(ScopedFrame);
|
||||
};
|
||||
|
||||
CompositorContext(std::unique_ptr<ProcessInfo> info);
|
||||
CompositorContext();
|
||||
|
||||
~CompositorContext();
|
||||
virtual ~CompositorContext();
|
||||
|
||||
ScopedFrame AcquireFrame(GrContext* gr_context,
|
||||
SkCanvas* canvas,
|
||||
bool instrumentation_enabled = true);
|
||||
virtual std::unique_ptr<ScopedFrame> AcquireFrame(
|
||||
GrContext* gr_context,
|
||||
SkCanvas* canvas,
|
||||
bool instrumentation_enabled);
|
||||
|
||||
void OnGrContextCreated();
|
||||
|
||||
@@ -62,7 +62,7 @@ class CompositorContext {
|
||||
|
||||
RasterCache& raster_cache() { return raster_cache_; }
|
||||
|
||||
TextureRegistry& texture_registry() { return *texture_registry_; }
|
||||
TextureRegistry& texture_registry() { return texture_registry_; }
|
||||
|
||||
const Counter& frame_count() const { return frame_count_; }
|
||||
|
||||
@@ -70,20 +70,12 @@ class CompositorContext {
|
||||
|
||||
Stopwatch& engine_time() { return engine_time_; }
|
||||
|
||||
const CounterValues& memory_usage() const { return memory_usage_; }
|
||||
|
||||
void SetTextureRegistry(TextureRegistry* textureRegistry) {
|
||||
texture_registry_ = textureRegistry;
|
||||
}
|
||||
|
||||
private:
|
||||
RasterCache raster_cache_;
|
||||
TextureRegistry* texture_registry_;
|
||||
std::unique_ptr<ProcessInfo> process_info_;
|
||||
TextureRegistry texture_registry_;
|
||||
Counter frame_count_;
|
||||
Stopwatch frame_time_;
|
||||
Stopwatch engine_time_;
|
||||
CounterValues memory_usage_;
|
||||
|
||||
void BeginFrame(ScopedFrame& frame, bool enable_instrumentation);
|
||||
|
||||
|
||||
@@ -80,3 +80,8 @@ std::ostream& operator<<(std::ostream& os, const flow::RasterCacheKey& k) {
|
||||
;
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const SkISize& size) {
|
||||
os << size.width() << ", " << size.height();
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
|
||||
#define DEF_PRINTER(x) std::ostream& operator<<(std::ostream&, const x&);
|
||||
|
||||
DEF_PRINTER(flow::RasterCacheKey);
|
||||
DEF_PRINTER(flow::MatrixDecomposition);
|
||||
DEF_PRINTER(flow::RasterCacheKey);
|
||||
DEF_PRINTER(SkISize);
|
||||
DEF_PRINTER(SkMatrix);
|
||||
DEF_PRINTER(SkMatrix44);
|
||||
DEF_PRINTER(SkVector3);
|
||||
DEF_PRINTER(SkVector4);
|
||||
DEF_PRINTER(SkPoint);
|
||||
DEF_PRINTER(SkRect);
|
||||
DEF_PRINTER(SkRRect);
|
||||
DEF_PRINTER(SkPoint);
|
||||
DEF_PRINTER(SkVector3);
|
||||
DEF_PRINTER(SkVector4);
|
||||
|
||||
#endif // FLUTTER_FLOW_DEBUG_PRINT_H_
|
||||
|
||||
@@ -4,28 +4,27 @@
|
||||
|
||||
#include "flutter/flow/export_node.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "lib/fxl/functional/make_copyable.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ExportNodeHolder::ExportNodeHolder(
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu_task_runner,
|
||||
fxl::RefPtr<zircon::dart::Handle> export_token_handle)
|
||||
: export_node_(std::make_unique<ExportNode>(export_token_handle)) {
|
||||
ASSERT_IS_UI_THREAD;
|
||||
: gpu_task_runner_(std::move(gpu_task_runner)),
|
||||
export_node_(std::make_unique<ExportNode>(export_token_handle)) {
|
||||
FXL_DCHECK(gpu_task_runner_);
|
||||
}
|
||||
|
||||
void ExportNodeHolder::Bind(SceneUpdateContext& context,
|
||||
scenic_lib::ContainerNode& container,
|
||||
const SkPoint& offset,
|
||||
bool hit_testable) {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
export_node_->Bind(context, container, offset, hit_testable);
|
||||
}
|
||||
|
||||
ExportNodeHolder::~ExportNodeHolder() {
|
||||
ASSERT_IS_UI_THREAD;
|
||||
blink::Threads::Gpu()->PostTask(
|
||||
gpu_task_runner_->PostTask(
|
||||
fxl::MakeCopyable([export_node = std::move(export_node_)]() {
|
||||
export_node->Dispose(true);
|
||||
}));
|
||||
@@ -44,8 +43,6 @@ void ExportNode::Bind(SceneUpdateContext& context,
|
||||
scenic_lib::ContainerNode& container,
|
||||
const SkPoint& offset,
|
||||
bool hit_testable) {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
|
||||
if (export_token_) {
|
||||
// Happens first time we bind.
|
||||
node_.reset(new scenic_lib::EntityNode(container.session()));
|
||||
@@ -67,8 +64,6 @@ void ExportNode::Bind(SceneUpdateContext& context,
|
||||
}
|
||||
|
||||
void ExportNode::Dispose(bool remove_from_scene_update_context) {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
|
||||
// If scene_update_context_ is set, then we should still have a node left to
|
||||
// dereference.
|
||||
// If scene_update_context_ is null, then either:
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
#include "lib/ui/scenic/client/resources.h"
|
||||
#include "third_party/flutter/fml/task_runner.h"
|
||||
#include "third_party/skia/include/core/SkPoint.h"
|
||||
|
||||
namespace flow {
|
||||
@@ -24,7 +25,8 @@ namespace flow {
|
||||
// held by the ExportNode.
|
||||
class ExportNodeHolder : public fxl::RefCountedThreadSafe<ExportNodeHolder> {
|
||||
public:
|
||||
ExportNodeHolder(fxl::RefPtr<zircon::dart::Handle> export_token_handle);
|
||||
ExportNodeHolder(fxl::RefPtr<fxl::TaskRunner> gpu_task_runner,
|
||||
fxl::RefPtr<zircon::dart::Handle> export_token_handle);
|
||||
~ExportNodeHolder();
|
||||
|
||||
// Calls Bind() on the wrapped ExportNode.
|
||||
@@ -36,6 +38,7 @@ class ExportNodeHolder : public fxl::RefCountedThreadSafe<ExportNodeHolder> {
|
||||
ExportNode* export_node() { return export_node_.get(); }
|
||||
|
||||
private:
|
||||
fxl::RefPtr<fxl::TaskRunner> gpu_task_runner_;
|
||||
std::unique_ptr<ExportNode> export_node_;
|
||||
|
||||
FRIEND_MAKE_REF_COUNTED(ExportNodeHolder);
|
||||
|
||||
@@ -137,20 +137,20 @@ void DefaultLayerBuilder::PushPerformanceOverlay(uint64_t enabled_options,
|
||||
}
|
||||
|
||||
void DefaultLayerBuilder::PushPicture(const SkPoint& offset,
|
||||
sk_sp<SkPicture> picture,
|
||||
SkiaGPUObject<SkPicture> picture,
|
||||
bool picture_is_complex,
|
||||
bool picture_will_change) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
SkRect pictureRect = picture->cullRect();
|
||||
SkRect pictureRect = picture.get()->cullRect();
|
||||
pictureRect.offset(offset.x(), offset.y());
|
||||
if (!SkRect::Intersects(pictureRect, cull_rects_.top())) {
|
||||
return;
|
||||
}
|
||||
auto layer = std::make_unique<flow::PictureLayer>();
|
||||
layer->set_offset(offset);
|
||||
layer->set_picture(picture);
|
||||
layer->set_picture(std::move(picture));
|
||||
layer->set_is_complex(picture_is_complex);
|
||||
layer->set_will_change(picture_will_change);
|
||||
current_layer_->Add(std::move(layer));
|
||||
|
||||
@@ -59,7 +59,7 @@ class DefaultLayerBuilder final : public LayerBuilder {
|
||||
|
||||
// |flow::LayerBuilder|
|
||||
void PushPicture(const SkPoint& offset,
|
||||
sk_sp<SkPicture> picture,
|
||||
SkiaGPUObject<SkPicture> picture,
|
||||
bool picture_is_complex,
|
||||
bool picture_will_change) override;
|
||||
|
||||
|
||||
@@ -44,9 +44,6 @@ class Layer {
|
||||
virtual ~Layer();
|
||||
|
||||
struct PrerollContext {
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics = nullptr;
|
||||
#endif
|
||||
RasterCache* raster_cache;
|
||||
GrContext* gr_context;
|
||||
SkColorSpace* dst_color_space;
|
||||
@@ -59,7 +56,6 @@ class Layer {
|
||||
SkCanvas& canvas;
|
||||
const Stopwatch& frame_time;
|
||||
const Stopwatch& engine_time;
|
||||
const CounterValues& memory_usage;
|
||||
TextureRegistry& texture_registry;
|
||||
const bool checkerboard_offscreen_layers;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "flutter/flow/skia_gpu_object.h"
|
||||
#include "garnet/public/lib/fxl/macros.h"
|
||||
#include "third_party/skia/include/core/SkBlendMode.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
@@ -57,7 +58,7 @@ class LayerBuilder {
|
||||
const SkRect& rect) = 0;
|
||||
|
||||
virtual void PushPicture(const SkPoint& offset,
|
||||
sk_sp<SkPicture> picture,
|
||||
SkiaGPUObject<SkPicture> picture,
|
||||
bool picture_is_complex,
|
||||
bool picture_will_change) = 0;
|
||||
|
||||
|
||||
@@ -17,43 +17,18 @@ LayerTree::LayerTree()
|
||||
|
||||
LayerTree::~LayerTree() = default;
|
||||
|
||||
void LayerTree::Raster(CompositorContext::ScopedFrame& frame,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool ignore_raster_cache) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
FXL_DCHECK(metrics);
|
||||
#endif
|
||||
Preroll(frame,
|
||||
#if defined(OS_FUCHSIA)
|
||||
metrics,
|
||||
#endif
|
||||
ignore_raster_cache);
|
||||
Paint(frame);
|
||||
}
|
||||
|
||||
void LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool ignore_raster_cache) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
FXL_DCHECK(metrics);
|
||||
#endif
|
||||
TRACE_EVENT0("flutter", "LayerTree::Preroll");
|
||||
SkColorSpace* color_space =
|
||||
frame.canvas() ? frame.canvas()->imageInfo().colorSpace() : nullptr;
|
||||
frame.context().raster_cache().SetCheckboardCacheImages(
|
||||
checkerboard_raster_cache_images_);
|
||||
Layer::PrerollContext context = {
|
||||
#if defined(OS_FUCHSIA)
|
||||
metrics,
|
||||
#endif
|
||||
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
|
||||
frame.gr_context(),
|
||||
color_space,
|
||||
SkRect::MakeEmpty(),
|
||||
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
|
||||
frame.gr_context(),
|
||||
color_space,
|
||||
SkRect::MakeEmpty(),
|
||||
};
|
||||
|
||||
root_layer_->Preroll(&context, SkMatrix::I());
|
||||
@@ -63,9 +38,12 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
|
||||
void LayerTree::UpdateScene(SceneUpdateContext& context,
|
||||
scenic_lib::ContainerNode& container) {
|
||||
TRACE_EVENT0("flutter", "LayerTree::UpdateScene");
|
||||
|
||||
SceneUpdateContext::Transform transform(context, 1.f / device_pixel_ratio_,
|
||||
1.f / device_pixel_ratio_, 1.f);
|
||||
const auto& metrics = context.metrics();
|
||||
SceneUpdateContext::Transform transform(context, // context
|
||||
1.0f / metrics->scale_x, // X
|
||||
1.0f / metrics->scale_y, // Y
|
||||
1.0f / metrics->scale_z // Z
|
||||
);
|
||||
SceneUpdateContext::Frame frame(
|
||||
context,
|
||||
SkRRect::MakeRect(
|
||||
@@ -82,12 +60,13 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
|
||||
#endif
|
||||
|
||||
void LayerTree::Paint(CompositorContext::ScopedFrame& frame) const {
|
||||
Layer::PaintContext context = {*frame.canvas(),
|
||||
frame.context().frame_time(),
|
||||
frame.context().engine_time(),
|
||||
frame.context().memory_usage(),
|
||||
frame.context().texture_registry(),
|
||||
checkerboard_offscreen_layers_};
|
||||
Layer::PaintContext context = {
|
||||
*frame.canvas(), //
|
||||
frame.context().frame_time(), //
|
||||
frame.context().engine_time(), //
|
||||
frame.context().texture_registry(), //
|
||||
checkerboard_offscreen_layers_ //
|
||||
};
|
||||
TRACE_EVENT0("flutter", "LayerTree::Paint");
|
||||
|
||||
if (root_layer_->needs_painting())
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/time/time_delta.h"
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include <fuchsia/cpp/ui.h>
|
||||
#endif
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
namespace flow {
|
||||
@@ -26,24 +23,10 @@ class LayerTree {
|
||||
|
||||
~LayerTree();
|
||||
|
||||
// Raster includes both Preroll and Paint.
|
||||
void Raster(CompositorContext::ScopedFrame& frame,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool ignore_raster_cache = false);
|
||||
|
||||
void Preroll(CompositorContext::ScopedFrame& frame,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool ignore_raster_cache = false);
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
void set_device_pixel_ratio(float device_pixel_ratio) {
|
||||
device_pixel_ratio_ = device_pixel_ratio;
|
||||
}
|
||||
|
||||
void UpdateScene(SceneUpdateContext& context,
|
||||
scenic_lib::ContainerNode& container);
|
||||
#endif
|
||||
@@ -93,10 +76,6 @@ class LayerTree {
|
||||
bool checkerboard_raster_cache_images_;
|
||||
bool checkerboard_offscreen_layers_;
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
float device_pixel_ratio_ = 1.f;
|
||||
#endif
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(LayerTree);
|
||||
};
|
||||
|
||||
|
||||
@@ -57,34 +57,6 @@ void VisualizeStopWatch(SkCanvas& canvas,
|
||||
}
|
||||
}
|
||||
|
||||
void VisualizeCounterValuesBytes(SkCanvas& canvas,
|
||||
const CounterValues& counter_values,
|
||||
SkScalar x,
|
||||
SkScalar y,
|
||||
SkScalar width,
|
||||
SkScalar height,
|
||||
bool show_graph,
|
||||
bool show_labels,
|
||||
const std::string& label_prefix) {
|
||||
const int label_x = 8; // distance from x
|
||||
const int label_y = -10; // distance from y+height
|
||||
|
||||
if (show_graph) {
|
||||
SkRect visualization_rect = SkRect::MakeXYWH(x, y, width, height);
|
||||
counter_values.Visualize(canvas, visualization_rect);
|
||||
}
|
||||
|
||||
auto current_usage = counter_values.GetCurrentValue();
|
||||
|
||||
if (show_labels && current_usage > 0) {
|
||||
std::stringstream stream;
|
||||
stream.setf(std::ios::fixed | std::ios::showpoint);
|
||||
stream << std::setprecision(2);
|
||||
stream << label_prefix << " " << current_usage * 1e-6 << " MB";
|
||||
DrawStatisticsText(canvas, stream.str(), x + label_x, y + height + label_y);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PerformanceOverlayLayer::PerformanceOverlayLayer(uint64_t options)
|
||||
@@ -111,11 +83,6 @@ void PerformanceOverlayLayer::Paint(PaintContext& context) const {
|
||||
VisualizeStopWatch(context.canvas, context.engine_time, x, y + height, width,
|
||||
height - padding, options_ & kVisualizeEngineStatistics,
|
||||
options_ & kDisplayEngineStatistics, "UI");
|
||||
|
||||
VisualizeCounterValuesBytes(
|
||||
context.canvas, context.memory_usage, x, y + (2 * height), width,
|
||||
height - padding, options_ & kVisualizeMemoryStatistics,
|
||||
options_ & kDisplayMemoryStatistics, "Memory (Resident)");
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
|
||||
@@ -14,8 +14,6 @@ const int kDisplayRasterizerStatistics = 1 << 0;
|
||||
const int kVisualizeRasterizerStatistics = 1 << 1;
|
||||
const int kDisplayEngineStatistics = 1 << 2;
|
||||
const int kVisualizeEngineStatistics = 1 << 3;
|
||||
const int kDisplayMemoryStatistics = 1 << 4;
|
||||
const int kVisualizeMemoryStatistics = 1 << 5;
|
||||
|
||||
class PerformanceOverlayLayer : public Layer {
|
||||
public:
|
||||
|
||||
@@ -4,39 +4,30 @@
|
||||
|
||||
#include "flutter/flow/layers/picture_layer.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "lib/fxl/logging.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
PictureLayer::PictureLayer() = default;
|
||||
|
||||
PictureLayer::~PictureLayer() {
|
||||
// The picture may contain references to textures that are associated
|
||||
// with the IO thread's context.
|
||||
SkPicture* picture = picture_.release();
|
||||
if (picture) {
|
||||
blink::Threads::IO()->PostTask([picture]() { picture->unref(); });
|
||||
}
|
||||
}
|
||||
PictureLayer::~PictureLayer() = default;
|
||||
|
||||
void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
SkPicture* sk_picture = picture();
|
||||
|
||||
if (auto cache = context->raster_cache) {
|
||||
raster_cache_result_ = cache->GetPrerolledImage(
|
||||
context->gr_context, picture_.get(), matrix, context->dst_color_space,
|
||||
#if defined(OS_FUCHSIA)
|
||||
context->metrics,
|
||||
#endif
|
||||
context->gr_context, sk_picture, matrix, context->dst_color_space,
|
||||
is_complex_, will_change_);
|
||||
}
|
||||
|
||||
SkRect bounds = picture_->cullRect().makeOffset(offset_.x(), offset_.y());
|
||||
SkRect bounds = sk_picture->cullRect().makeOffset(offset_.x(), offset_.y());
|
||||
set_paint_bounds(bounds);
|
||||
}
|
||||
|
||||
void PictureLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "PictureLayer::Paint");
|
||||
FXL_DCHECK(picture_);
|
||||
FXL_DCHECK(picture_.get());
|
||||
FXL_DCHECK(needs_painting());
|
||||
|
||||
SkAutoCanvasRestore save(&context.canvas, true);
|
||||
@@ -53,7 +44,7 @@ void PictureLayer::Paint(PaintContext& context) const {
|
||||
SkCanvas::kStrict_SrcRectConstraint // source constraint
|
||||
);
|
||||
} else {
|
||||
context.canvas.drawPicture(picture_.get());
|
||||
context.canvas.drawPicture(picture());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
#ifndef FLUTTER_FLOW_LAYERS_PICTURE_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_PICTURE_LAYER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "flutter/flow/raster_cache.h"
|
||||
#include "flutter/flow/skia_gpu_object.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
@@ -16,12 +19,14 @@ class PictureLayer : public Layer {
|
||||
~PictureLayer() override;
|
||||
|
||||
void set_offset(const SkPoint& offset) { offset_ = offset; }
|
||||
void set_picture(sk_sp<SkPicture> picture) { picture_ = std::move(picture); }
|
||||
void set_picture(SkiaGPUObject<SkPicture> picture) {
|
||||
picture_ = std::move(picture);
|
||||
}
|
||||
|
||||
void set_is_complex(bool value) { is_complex_ = value; }
|
||||
void set_will_change(bool value) { will_change_ = value; }
|
||||
|
||||
SkPicture* picture() const { return picture_.get(); }
|
||||
SkPicture* picture() const { return picture_.get().get(); }
|
||||
|
||||
void Preroll(PrerollContext* frame, const SkMatrix& matrix) override;
|
||||
|
||||
@@ -29,7 +34,9 @@ class PictureLayer : public Layer {
|
||||
|
||||
private:
|
||||
SkPoint offset_;
|
||||
sk_sp<SkPicture> picture_;
|
||||
// Even though pictures themselves are not GPU resources, they may reference
|
||||
// images that have a reference to a GPU resource.
|
||||
SkiaGPUObject<SkPicture> picture_;
|
||||
bool is_complex_ = false;
|
||||
bool will_change_ = false;
|
||||
RasterCacheResult raster_cache_result_;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FLOW_PROCESS_INFO_H_
|
||||
#define FLUTTER_FLOW_PROCESS_INFO_H_
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
/// The CompositorContext attempts to collect information from the process for
|
||||
/// instrumentation purposes. The compositor does not have the platform
|
||||
/// specific capabilities to collect this information on its own. The platform
|
||||
/// can choose to provide this information however.
|
||||
class ProcessInfo {
|
||||
public:
|
||||
virtual ~ProcessInfo() = default;
|
||||
|
||||
virtual bool SampleNow() = 0;
|
||||
|
||||
/// Virtual memory size in bytes.
|
||||
virtual size_t GetVirtualMemorySize() = 0;
|
||||
|
||||
/// Resident memory size in bytes.
|
||||
virtual size_t GetResidentMemorySize() = 0;
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLUTTER_FLOW_PROCESS_INFO_H_
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/flow/paint_utils.h"
|
||||
#include "flutter/glue/trace_event.h"
|
||||
#include "lib/fxl/logging.h"
|
||||
@@ -73,9 +72,6 @@ RasterCacheResult RasterizePicture(SkPicture* picture,
|
||||
GrContext* context,
|
||||
const MatrixDecomposition& matrix,
|
||||
SkColorSpace* dst_color_space,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool checkerboard) {
|
||||
TRACE_EVENT0("flutter", "RasterCachePopulate");
|
||||
|
||||
@@ -83,17 +79,9 @@ RasterCacheResult RasterizePicture(SkPicture* picture,
|
||||
|
||||
const SkRect logical_rect = picture->cullRect();
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
float metrics_scale_x = metrics->scale_x;
|
||||
float metrics_scale_y = metrics->scale_y;
|
||||
#else
|
||||
float metrics_scale_x = 1.f;
|
||||
float metrics_scale_y = 1.f;
|
||||
#endif
|
||||
|
||||
const SkRect physical_rect = SkRect::MakeWH(
|
||||
std::fabs(logical_rect.width() * metrics_scale_x * scale.x()),
|
||||
std::fabs(logical_rect.height() * metrics_scale_y * scale.y()));
|
||||
const SkRect physical_rect =
|
||||
SkRect::MakeWH(std::fabs(logical_rect.width() * scale.x()),
|
||||
std::fabs(logical_rect.height() * scale.y()));
|
||||
|
||||
const SkImageInfo image_info = SkImageInfo::MakeN32Premul(
|
||||
std::ceil(physical_rect.width()), // physical width
|
||||
@@ -120,8 +108,7 @@ RasterCacheResult RasterizePicture(SkPicture* picture,
|
||||
}
|
||||
|
||||
canvas->clear(SK_ColorTRANSPARENT);
|
||||
canvas->scale(std::abs(scale.x() * metrics_scale_x),
|
||||
std::abs(scale.y() * metrics_scale_y));
|
||||
canvas->scale(std::abs(scale.x()), std::abs(scale.y()));
|
||||
canvas->translate(-logical_rect.left(), -logical_rect.top());
|
||||
canvas->drawPicture(picture);
|
||||
|
||||
@@ -153,9 +140,6 @@ RasterCacheResult RasterCache::GetPrerolledImage(
|
||||
SkPicture* picture,
|
||||
const SkMatrix& transformation_matrix,
|
||||
SkColorSpace* dst_color_space,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool is_complex,
|
||||
bool will_change) {
|
||||
if (!IsPictureWorthRasterizing(picture, will_change, is_complex)) {
|
||||
@@ -172,11 +156,7 @@ RasterCacheResult RasterCache::GetPrerolledImage(
|
||||
return {};
|
||||
}
|
||||
|
||||
RasterCacheKey cache_key(*picture,
|
||||
#if defined(OS_FUCHSIA)
|
||||
metrics->scale_x, metrics->scale_y,
|
||||
#endif
|
||||
matrix);
|
||||
RasterCacheKey cache_key(*picture, matrix);
|
||||
|
||||
Entry& entry = cache_[cache_key];
|
||||
entry.access_count = ClampSize(entry.access_count + 1, 0, threshold_);
|
||||
@@ -189,9 +169,6 @@ RasterCacheResult RasterCache::GetPrerolledImage(
|
||||
|
||||
if (!entry.image.is_valid()) {
|
||||
entry.image = RasterizePicture(picture, context, matrix, dst_color_space,
|
||||
#if defined(OS_FUCHSIA)
|
||||
metrics,
|
||||
#endif
|
||||
checkerboard_images_);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#include "flutter/flow/raster_cache_key.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/weak_ptr.h"
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include <fuchsia/cpp/ui.h>
|
||||
#endif
|
||||
#include "third_party/skia/include/core/SkImage.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
@@ -57,9 +54,6 @@ class RasterCache {
|
||||
SkPicture* picture,
|
||||
const SkMatrix& transformation_matrix,
|
||||
SkColorSpace* dst_color_space,
|
||||
#if defined(OS_FUCHSIA)
|
||||
gfx::Metrics* metrics,
|
||||
#endif
|
||||
bool is_complex,
|
||||
bool will_change);
|
||||
|
||||
|
||||
@@ -15,30 +15,15 @@ namespace flow {
|
||||
|
||||
class RasterCacheKey {
|
||||
public:
|
||||
RasterCacheKey(const SkPicture& picture,
|
||||
#if defined(OS_FUCHSIA)
|
||||
float metrics_scale_x,
|
||||
float metrics_scale_y,
|
||||
#endif
|
||||
const MatrixDecomposition& matrix)
|
||||
RasterCacheKey(const SkPicture& picture, const MatrixDecomposition& matrix)
|
||||
: picture_id_(picture.uniqueID()),
|
||||
#if defined(OS_FUCHSIA)
|
||||
metrics_scale_x_(metrics_scale_x),
|
||||
metrics_scale_y_(metrics_scale_y),
|
||||
#endif
|
||||
scale_key_(
|
||||
SkISize::Make(matrix.scale().x() * 1e3, matrix.scale().y() * 1e3)) {
|
||||
}
|
||||
scale_key_(SkISize::Make(matrix.scale().x() * 1e3,
|
||||
matrix.scale().y() * 1e3)) {}
|
||||
|
||||
uint32_t picture_id() const { return picture_id_; }
|
||||
|
||||
const SkISize& scale_key() const { return scale_key_; }
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
float metrics_scale_x() const { return metrics_scale_x_; }
|
||||
float metrics_scale_y() const { return metrics_scale_y_; }
|
||||
#endif
|
||||
|
||||
struct Hash {
|
||||
std::size_t operator()(RasterCacheKey const& key) const {
|
||||
return key.picture_id_;
|
||||
@@ -49,11 +34,6 @@ class RasterCacheKey {
|
||||
constexpr bool operator()(const RasterCacheKey& lhs,
|
||||
const RasterCacheKey& rhs) const {
|
||||
return lhs.picture_id_ == rhs.picture_id_ &&
|
||||
#if defined(OS_FUCHSIA)
|
||||
lhs.metrics_scale_x_ == rhs.metrics_scale_x_ &&
|
||||
|
||||
lhs.metrics_scale_y_ == rhs.metrics_scale_y_ &&
|
||||
#endif
|
||||
lhs.scale_key_ == rhs.scale_key_;
|
||||
}
|
||||
};
|
||||
@@ -63,10 +43,6 @@ class RasterCacheKey {
|
||||
|
||||
private:
|
||||
uint32_t picture_id_;
|
||||
#if defined(OS_FUCHSIA)
|
||||
float metrics_scale_x_;
|
||||
float metrics_scale_y_;
|
||||
#endif
|
||||
SkISize scale_key_;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "flutter/flow/scene_update_context.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/flow/export_node.h"
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "flutter/flow/matrix_decomposition.h"
|
||||
@@ -19,9 +18,7 @@ SceneUpdateContext::SceneUpdateContext(scenic_lib::Session* session,
|
||||
}
|
||||
|
||||
SceneUpdateContext::~SceneUpdateContext() {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
|
||||
// Release Scenic session resources for all ExportNodes.
|
||||
// Release Mozart session resources for all ExportNodes.
|
||||
for (auto export_node : export_nodes_) {
|
||||
export_node->Dispose(false);
|
||||
}
|
||||
@@ -30,21 +27,16 @@ SceneUpdateContext::~SceneUpdateContext() {
|
||||
void SceneUpdateContext::AddChildScene(ExportNode* export_node,
|
||||
SkPoint offset,
|
||||
bool hit_testable) {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
FXL_DCHECK(top_entity_);
|
||||
|
||||
export_node->Bind(*this, top_entity_->entity_node(), offset, hit_testable);
|
||||
}
|
||||
|
||||
void SceneUpdateContext::AddExportNode(ExportNode* export_node) {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
|
||||
export_nodes_.insert(export_node); // Might already have been added.
|
||||
}
|
||||
|
||||
void SceneUpdateContext::RemoveExportNode(ExportNode* export_node) {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
|
||||
export_nodes_.erase(export_node);
|
||||
}
|
||||
|
||||
@@ -195,12 +187,9 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
|
||||
for (auto& task : paint_tasks_) {
|
||||
FXL_DCHECK(task.surface);
|
||||
SkCanvas* canvas = task.surface->GetSkiaSurface()->getCanvas();
|
||||
Layer::PaintContext context = {*canvas,
|
||||
frame.context().frame_time(),
|
||||
Layer::PaintContext context = {*canvas, frame.context().frame_time(),
|
||||
frame.context().engine_time(),
|
||||
frame.context().memory_usage(),
|
||||
frame.context().texture_registry(),
|
||||
false};
|
||||
frame.context().texture_registry(), false};
|
||||
canvas->restoreToCount(1);
|
||||
canvas->save();
|
||||
canvas->clear(task.background_color);
|
||||
|
||||
44
engine/src/flutter/flow/skia_gpu_object.cc
Normal file
44
engine/src/flutter/flow/skia_gpu_object.cc
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/flow/skia_gpu_object.h"
|
||||
|
||||
#include "flutter/fml/message_loop.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
SkiaUnrefQueue::SkiaUnrefQueue(fxl::RefPtr<fxl::TaskRunner> task_runner,
|
||||
fxl::TimeDelta delay)
|
||||
: task_runner_(std::move(task_runner)),
|
||||
drain_delay_(delay),
|
||||
drain_pending_(false) {}
|
||||
|
||||
SkiaUnrefQueue::~SkiaUnrefQueue() {
|
||||
Drain();
|
||||
}
|
||||
|
||||
void SkiaUnrefQueue::Unref(SkRefCnt* object) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
objects_.push_back(object);
|
||||
if (!drain_pending_) {
|
||||
drain_pending_ = true;
|
||||
task_runner_->PostDelayedTask(
|
||||
[strong = fxl::Ref(this)]() { strong->Drain(); }, drain_delay_);
|
||||
}
|
||||
}
|
||||
|
||||
void SkiaUnrefQueue::Drain() {
|
||||
std::deque<SkRefCnt*> skia_objects;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
objects_.swap(skia_objects);
|
||||
drain_pending_ = false;
|
||||
}
|
||||
|
||||
for (SkRefCnt* skia_object : skia_objects) {
|
||||
skia_object->unref();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
88
engine/src/flutter/flow/skia_gpu_object.h
Normal file
88
engine/src/flutter/flow/skia_gpu_object.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2017 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FLOW_SKIA_GPU_OBJECT_H_
|
||||
#define FLUTTER_FLOW_SKIA_GPU_OBJECT_H_
|
||||
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "flutter/fml/memory/weak_ptr.h"
|
||||
#include "flutter/fml/task_runner.h"
|
||||
#include "lib/fxl/memory/ref_ptr.h"
|
||||
#include "third_party/skia/include/core/SkRefCnt.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
// A queue that holds Skia objects that must be destructed on the the given task
|
||||
// runner.
|
||||
class SkiaUnrefQueue : public fxl::RefCountedThreadSafe<SkiaUnrefQueue> {
|
||||
public:
|
||||
void Unref(SkRefCnt* object);
|
||||
|
||||
// Usually, the drain is called automatically. However, during IO manager
|
||||
// shutdown (when the platform side reference to the OpenGL context is about
|
||||
// to go away), we may need to pre-emptively drain the unref queue. It is the
|
||||
// responsibility of the caller to ensure that no further unrefs are queued
|
||||
// after this call.
|
||||
void Drain();
|
||||
|
||||
private:
|
||||
const fxl::RefPtr<fxl::TaskRunner> task_runner_;
|
||||
const fxl::TimeDelta drain_delay_;
|
||||
std::mutex mutex_;
|
||||
std::deque<SkRefCnt*> objects_;
|
||||
bool drain_pending_;
|
||||
|
||||
SkiaUnrefQueue(fxl::RefPtr<fxl::TaskRunner> task_runner,
|
||||
fxl::TimeDelta delay);
|
||||
|
||||
~SkiaUnrefQueue();
|
||||
|
||||
FRIEND_REF_COUNTED_THREAD_SAFE(SkiaUnrefQueue);
|
||||
FRIEND_MAKE_REF_COUNTED(SkiaUnrefQueue);
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(SkiaUnrefQueue);
|
||||
};
|
||||
|
||||
/// An object whose deallocation needs to be performed on an specific unref
|
||||
/// queue. The template argument U need to have a call operator that returns
|
||||
/// that unref queue.
|
||||
template <class T>
|
||||
class SkiaGPUObject {
|
||||
public:
|
||||
using SkiaObjectType = T;
|
||||
|
||||
SkiaGPUObject() = default;
|
||||
|
||||
SkiaGPUObject(sk_sp<SkiaObjectType> object, fxl::RefPtr<SkiaUnrefQueue> queue)
|
||||
: object_(std::move(object)), queue_(std::move(queue)) {
|
||||
FXL_DCHECK(queue_ && object_);
|
||||
}
|
||||
|
||||
SkiaGPUObject(SkiaGPUObject&&) = default;
|
||||
|
||||
~SkiaGPUObject() { reset(); }
|
||||
|
||||
SkiaGPUObject& operator=(SkiaGPUObject&&) = default;
|
||||
|
||||
sk_sp<SkiaObjectType> get() const { return object_; }
|
||||
|
||||
void reset() {
|
||||
if (object_) {
|
||||
queue_->Unref(object_.release());
|
||||
}
|
||||
queue_ = nullptr;
|
||||
FXL_DCHECK(object_ == nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
sk_sp<SkiaObjectType> object_;
|
||||
fxl::RefPtr<SkiaUnrefQueue> queue_;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(SkiaGPUObject);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLUTTER_FLOW_SKIA_GPU_OBJECT_H_
|
||||
@@ -11,36 +11,32 @@ TextureRegistry::TextureRegistry() = default;
|
||||
TextureRegistry::~TextureRegistry() = default;
|
||||
|
||||
void TextureRegistry::RegisterTexture(std::shared_ptr<Texture> texture) {
|
||||
ASSERT_IS_GPU_THREAD
|
||||
mapping_[texture->Id()] = texture;
|
||||
}
|
||||
|
||||
void TextureRegistry::UnregisterTexture(int64_t id) {
|
||||
ASSERT_IS_GPU_THREAD
|
||||
mapping_.erase(id);
|
||||
}
|
||||
|
||||
void TextureRegistry::OnGrContextCreated() {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
for (auto& it : mapping_) {
|
||||
it.second->OnGrContextCreated();
|
||||
}
|
||||
}
|
||||
|
||||
void TextureRegistry::OnGrContextDestroyed() {
|
||||
ASSERT_IS_GPU_THREAD;
|
||||
for (auto& it : mapping_) {
|
||||
it.second->OnGrContextDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> TextureRegistry::GetTexture(int64_t id) {
|
||||
ASSERT_IS_GPU_THREAD
|
||||
auto it = mapping_.find(id);
|
||||
return it != mapping_.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
Texture::Texture(int64_t id) : id_(id) {}
|
||||
|
||||
Texture::~Texture() = default;
|
||||
|
||||
} // namespace flow
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define FLUTTER_FLOW_TEXTURE_H_
|
||||
|
||||
#include <map>
|
||||
#include "flutter/common/threads.h"
|
||||
|
||||
#include "lib/fxl/synchronization/waitable_event.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
@@ -29,6 +29,9 @@ class Texture {
|
||||
// Called from GPU thread.
|
||||
virtual void OnGrContextDestroyed() = 0;
|
||||
|
||||
// Called on GPU thread.
|
||||
virtual void MarkNewFrameAvailable() = 0;
|
||||
|
||||
int64_t Id() { return id_; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
source_set("fml") {
|
||||
sources = [
|
||||
"file.h",
|
||||
"icu_util.cc",
|
||||
"icu_util.h",
|
||||
"mapping.cc",
|
||||
"mapping.h",
|
||||
"memory/thread_checker.h",
|
||||
"memory/weak_ptr.h",
|
||||
"memory/weak_ptr_internal.cc",
|
||||
"memory/weak_ptr_internal.h",
|
||||
@@ -14,8 +17,9 @@ source_set("fml") {
|
||||
"message_loop.h",
|
||||
"message_loop_impl.cc",
|
||||
"message_loop_impl.h",
|
||||
"native_library.h",
|
||||
"paths.cc",
|
||||
"paths.h",
|
||||
"task_observer.h",
|
||||
"task_runner.cc",
|
||||
"task_runner.h",
|
||||
"thread.cc",
|
||||
@@ -23,6 +27,9 @@ source_set("fml") {
|
||||
"thread_local.h",
|
||||
"trace_event.cc",
|
||||
"trace_event.h",
|
||||
"unique_fd.cc",
|
||||
"unique_fd.h",
|
||||
"unique_object.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@@ -95,16 +102,25 @@ source_set("fml") {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_fuchsia) {
|
||||
sources += [ "platform/fuchsia/paths_fuchsia.cc" ]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"platform/win/file_win.cc",
|
||||
"platform/win/mapping_win.cc",
|
||||
"platform/win/message_loop_win.cc",
|
||||
"platform/win/message_loop_win.h",
|
||||
"platform/win/native_library_win.cc",
|
||||
"platform/win/paths_win.cc",
|
||||
"platform/win/wstring_conversion.h",
|
||||
]
|
||||
} else {
|
||||
sources += [
|
||||
"platform/posix/file_posix.cc",
|
||||
"platform/posix/mapping_posix.cc",
|
||||
"platform/posix/native_library_posix.cc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
35
engine/src/flutter/fml/file.h
Normal file
35
engine/src/flutter/fml/file.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_FILE_H_
|
||||
#define FLUTTER_FML_FILE_H_
|
||||
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
enum class OpenPermission {
|
||||
kRead = 1,
|
||||
kWrite = 1 << 1,
|
||||
kReadWrite = kRead | kWrite,
|
||||
kExecute,
|
||||
};
|
||||
|
||||
fml::UniqueFD OpenFile(const char* path,
|
||||
OpenPermission permission,
|
||||
bool is_directory = false);
|
||||
|
||||
fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
|
||||
const char* path,
|
||||
OpenPermission permission,
|
||||
bool is_directory = false);
|
||||
|
||||
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor);
|
||||
|
||||
bool IsDirectory(const fml::UniqueFD& directory);
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_FILE_H_
|
||||
@@ -22,8 +22,6 @@ static constexpr char kPathSeparator = '\\';
|
||||
static constexpr char kPathSeparator = '/';
|
||||
#endif
|
||||
|
||||
static constexpr char kIcuDataFileName[] = "icudtl.dat";
|
||||
|
||||
class ICUContext {
|
||||
public:
|
||||
ICUContext(const std::string& icu_data_path) : valid_(false) {
|
||||
@@ -34,15 +32,15 @@ class ICUContext {
|
||||
|
||||
bool SetupMapping(const std::string& icu_data_path) {
|
||||
// Check if the explicit path specified exists.
|
||||
auto overriden_path_mapping = std::make_unique<FileMapping>(icu_data_path);
|
||||
if (overriden_path_mapping->GetSize() != 0) {
|
||||
mapping_ = std::move(overriden_path_mapping);
|
||||
auto path_mapping = std::make_unique<FileMapping>(icu_data_path, false);
|
||||
if (path_mapping->GetSize() != 0) {
|
||||
mapping_ = std::move(path_mapping);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check to see if the mapping is in the resources bundle.
|
||||
if (PlatformHasResourcesBundle()) {
|
||||
auto resource = GetResourceMapping(kIcuDataFileName);
|
||||
auto resource = GetResourceMapping(icu_data_path);
|
||||
if (resource != nullptr && resource->GetSize() != 0) {
|
||||
mapping_ = std::move(resource);
|
||||
return true;
|
||||
@@ -57,10 +55,8 @@ class ICUContext {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME(chinmaygarde): There is no Path::Join in FXL. So a non-portable
|
||||
// version is used here. Patch FXL and update.
|
||||
auto file = std::make_unique<FileMapping>(
|
||||
directory.second + kPathSeparator + kIcuDataFileName);
|
||||
directory.second + kPathSeparator + icu_data_path, false);
|
||||
if (file->GetSize() != 0) {
|
||||
mapping_ = std::move(file);
|
||||
return true;
|
||||
@@ -96,7 +92,8 @@ class ICUContext {
|
||||
|
||||
void InitializeICUOnce(const std::string& icu_data_path) {
|
||||
static ICUContext* context = new ICUContext(icu_data_path);
|
||||
FXL_CHECK(context->IsValid()) << "Must be able to initialize the ICU context";
|
||||
FXL_CHECK(context->IsValid())
|
||||
<< "Must be able to initialize the ICU context. Tried: " << icu_data_path;
|
||||
}
|
||||
|
||||
std::once_flag g_icu_init_flag;
|
||||
|
||||
20
engine/src/flutter/fml/macros.h
Normal file
20
engine/src/flutter/fml/macros.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_MACROS_H_
|
||||
#define FLUTTER_FML_MACROS_H_
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
#ifndef FML_USED_ON_EMBEDDER
|
||||
|
||||
#define FML_EMBEDDER_ONLY [[deprecated]]
|
||||
|
||||
#else // FML_USED_ON_EMBEDDER
|
||||
|
||||
#define FML_EMBEDDER_ONLY
|
||||
|
||||
#endif // FML_USED_ON_EMBEDDER
|
||||
|
||||
#endif // FLUTTER_FML_MACROS_H_
|
||||
20
engine/src/flutter/fml/mapping.cc
Normal file
20
engine/src/flutter/fml/mapping.cc
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/mapping.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
DataMapping::DataMapping(std::vector<uint8_t> data) : data_(std::move(data)) {}
|
||||
|
||||
DataMapping::~DataMapping() = default;
|
||||
|
||||
size_t DataMapping::GetSize() const {
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
const uint8_t* DataMapping::GetMapping() const {
|
||||
return data_.data();
|
||||
}
|
||||
} // namespace fml
|
||||
@@ -7,14 +7,10 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml//unique_fd.h"
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
#if OS_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace fml {
|
||||
@@ -39,12 +35,9 @@ std::unique_ptr<Mapping> GetResourceMapping(const std::string& resource_name);
|
||||
|
||||
class FileMapping : public Mapping {
|
||||
public:
|
||||
FileMapping(const std::string& path);
|
||||
FileMapping(const std::string& path, bool executable = false);
|
||||
|
||||
// fxl::UniqueFD isn't supported for Windows handles.
|
||||
#if !OS_WIN
|
||||
FileMapping(const fxl::UniqueFD& fd);
|
||||
#endif
|
||||
FileMapping(const fml::UniqueFD& fd, bool executable = false);
|
||||
|
||||
~FileMapping() override;
|
||||
|
||||
@@ -53,16 +46,32 @@ class FileMapping : public Mapping {
|
||||
const uint8_t* GetMapping() const override;
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
uint8_t* mapping_;
|
||||
size_t size_ = 0;
|
||||
uint8_t* mapping_ = nullptr;
|
||||
|
||||
#if OS_WIN
|
||||
HANDLE mapping_handle_;
|
||||
fml::UniqueFD mapping_handle_;
|
||||
#endif
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(FileMapping);
|
||||
};
|
||||
|
||||
class DataMapping : public Mapping {
|
||||
public:
|
||||
DataMapping(std::vector<uint8_t> data);
|
||||
|
||||
~DataMapping() override;
|
||||
|
||||
size_t GetSize() const override;
|
||||
|
||||
const uint8_t* GetMapping() const override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(DataMapping);
|
||||
};
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_MAPPING_H_
|
||||
|
||||
69
engine/src/flutter/fml/memory/thread_checker.h
Normal file
69
engine/src/flutter/fml/memory/thread_checker.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// A class for checking that the current thread is/isn't the same as an initial
|
||||
// thread.
|
||||
|
||||
#ifndef FLUTTER_FML_MEMORY_THREAD_CHECKER_H_
|
||||
#define FLUTTER_FML_MEMORY_THREAD_CHECKER_H_
|
||||
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "lib/fxl/logging.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
// A simple class that records the identity of the thread that it was created
|
||||
// on, and at later points can tell if the current thread is the same as its
|
||||
// creation thread. This class is thread-safe.
|
||||
//
|
||||
// Note: Unlike Chromium's |base::ThreadChecker|, this is *not* Debug-only (so
|
||||
// #ifdef it out if you want something Debug-only). (Rationale: Having a
|
||||
// |CalledOnValidThread()| that lies in Release builds seems bad. Moreover,
|
||||
// there's a small space cost to having even an empty class. )
|
||||
class ThreadChecker final {
|
||||
public:
|
||||
#if defined(OS_WIN)
|
||||
ThreadChecker() : self_(GetCurrentThreadId()) {}
|
||||
~ThreadChecker() {}
|
||||
|
||||
bool IsCreationThreadCurrent() const { return GetCurrentThreadId() == self_; }
|
||||
|
||||
private:
|
||||
DWORD self_;
|
||||
|
||||
#else
|
||||
ThreadChecker() : self_(pthread_self()) {}
|
||||
~ThreadChecker() {}
|
||||
|
||||
// Returns true if the current thread is the thread this object was created
|
||||
// on and false otherwise.
|
||||
bool IsCreationThreadCurrent() const {
|
||||
return !!pthread_equal(pthread_self(), self_);
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_t self_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define FML_DECLARE_THREAD_CHECKER(c) fml::ThreadChecker c
|
||||
#define FML_DCHECK_CREATION_THREAD_IS_CURRENT(c) \
|
||||
FXL_DCHECK((c).IsCreationThreadCurrent())
|
||||
#else
|
||||
#define FML_DECLARE_THREAD_CHECKER(c)
|
||||
#define FML_DCHECK_CREATION_THREAD_IS_CURRENT(c) ((void)0)
|
||||
#endif
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_MEMORY_THREAD_CHECKER_H_
|
||||
@@ -10,12 +10,17 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/fml/memory/thread_checker.h"
|
||||
#include "flutter/fml/memory/weak_ptr_internal.h"
|
||||
#include "lib/fxl/logging.h"
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
struct DebugThreadChecker {
|
||||
FML_DECLARE_THREAD_CHECKER(checker);
|
||||
};
|
||||
|
||||
// Forward declaration, so |WeakPtr<T>| can friend it.
|
||||
template <typename T>
|
||||
class WeakPtrFactory;
|
||||
@@ -41,13 +46,17 @@ class WeakPtr {
|
||||
WeakPtr(const WeakPtr<T>& r) = default;
|
||||
|
||||
template <typename U>
|
||||
WeakPtr(const WeakPtr<U>& r) : ptr_(r.ptr_), flag_(r.flag_) {}
|
||||
WeakPtr(const WeakPtr<U>& r)
|
||||
: ptr_(static_cast<T*>(r.ptr_)), flag_(r.flag_), checker_(r.checker_) {}
|
||||
|
||||
// Move constructor.
|
||||
WeakPtr(WeakPtr<T>&& r) = default;
|
||||
|
||||
template <typename U>
|
||||
WeakPtr(WeakPtr<U>&& r) : ptr_(r.ptr_), flag_(std::move(r.flag_)) {}
|
||||
WeakPtr(WeakPtr<U>&& r)
|
||||
: ptr_(static_cast<T*>(r.ptr_)),
|
||||
flag_(std::move(r.flag_)),
|
||||
checker_(r.checker_) {}
|
||||
|
||||
~WeakPtr() = default;
|
||||
|
||||
@@ -65,16 +74,24 @@ class WeakPtr {
|
||||
// The following methods should only be called on the same thread as the
|
||||
// "originating" |WeakPtrFactory|.
|
||||
|
||||
explicit operator bool() const { return flag_ && flag_->is_valid(); }
|
||||
explicit operator bool() const {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
return flag_ && flag_->is_valid();
|
||||
}
|
||||
|
||||
T* get() const { return *this ? ptr_ : nullptr; }
|
||||
T* get() const {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
return *this ? ptr_ : nullptr;
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
FXL_DCHECK(*this);
|
||||
return *get();
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
FXL_DCHECK(*this);
|
||||
return get();
|
||||
}
|
||||
@@ -85,11 +102,14 @@ class WeakPtr {
|
||||
|
||||
friend class WeakPtrFactory<T>;
|
||||
|
||||
explicit WeakPtr(T* ptr, fxl::RefPtr<fml::internal::WeakPtrFlag>&& flag)
|
||||
: ptr_(ptr), flag_(std::move(flag)) {}
|
||||
explicit WeakPtr(T* ptr,
|
||||
fxl::RefPtr<fml::internal::WeakPtrFlag>&& flag,
|
||||
DebugThreadChecker checker)
|
||||
: ptr_(ptr), flag_(std::move(flag)), checker_(checker) {}
|
||||
|
||||
T* ptr_;
|
||||
fxl::RefPtr<fml::internal::WeakPtrFlag> flag_;
|
||||
DebugThreadChecker checker_;
|
||||
|
||||
// Copy/move construction/assignment supported.
|
||||
};
|
||||
@@ -140,19 +160,22 @@ template <typename T>
|
||||
class WeakPtrFactory {
|
||||
public:
|
||||
explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { FXL_DCHECK(ptr_); }
|
||||
|
||||
~WeakPtrFactory() { InvalidateWeakPtrs(); }
|
||||
|
||||
// Gets a new weak pointer, which will be valid until either
|
||||
// |InvalidateWeakPtrs()| is called or this object is destroyed.
|
||||
WeakPtr<T> GetWeakPtr() {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
if (!flag_)
|
||||
flag_ = fxl::MakeRefCounted<fml::internal::WeakPtrFlag>();
|
||||
return WeakPtr<T>(ptr_, flag_.Clone());
|
||||
return WeakPtr<T>(ptr_, flag_.Clone(), checker_);
|
||||
}
|
||||
|
||||
// Call this method to invalidate all existing weak pointers. (Note that
|
||||
// additional weak pointers can be produced even after this is called.)
|
||||
void InvalidateWeakPtrs() {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
if (!flag_)
|
||||
return;
|
||||
flag_->Invalidate();
|
||||
@@ -162,13 +185,17 @@ class WeakPtrFactory {
|
||||
// Call this method to determine if any weak pointers exist. (Note that a
|
||||
// "false" result is definitive, but a "true" result may not be if weak
|
||||
// pointers are held/reset/destroyed/reassigned on other threads.)
|
||||
bool HasWeakPtrs() const { return flag_ && !flag_->HasOneRef(); }
|
||||
bool HasWeakPtrs() const {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
|
||||
return flag_ && !flag_->HasOneRef();
|
||||
}
|
||||
|
||||
private:
|
||||
// Note: See weak_ptr_internal.h for an explanation of why we store the
|
||||
// pointer here, instead of in the "flag".
|
||||
T* const ptr_;
|
||||
fxl::RefPtr<fml::internal::WeakPtrFlag> flag_;
|
||||
DebugThreadChecker checker_;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(WeakPtrFactory);
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ void MessageLoop::Terminate() {
|
||||
loop_->DoTerminate();
|
||||
}
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> MessageLoop::GetTaskRunner() const {
|
||||
fxl::RefPtr<fml::TaskRunner> MessageLoop::GetTaskRunner() const {
|
||||
return task_runner_;
|
||||
}
|
||||
|
||||
@@ -63,12 +63,12 @@ fxl::RefPtr<MessageLoopImpl> MessageLoop::GetLoopImpl() const {
|
||||
return loop_;
|
||||
}
|
||||
|
||||
void MessageLoop::AddTaskObserver(TaskObserver* observer) {
|
||||
loop_->AddTaskObserver(observer);
|
||||
void MessageLoop::AddTaskObserver(intptr_t key, fxl::Closure callback) {
|
||||
loop_->AddTaskObserver(key, callback);
|
||||
}
|
||||
|
||||
void MessageLoop::RemoveTaskObserver(TaskObserver* observer) {
|
||||
loop_->RemoveTaskObserver(observer);
|
||||
void MessageLoop::RemoveTaskObserver(intptr_t key) {
|
||||
loop_->RemoveTaskObserver(key);
|
||||
}
|
||||
|
||||
void MessageLoop::RunExpiredTasksNow() {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef FLUTTER_FML_MESSAGE_LOOP_H_
|
||||
#define FLUTTER_FML_MESSAGE_LOOP_H_
|
||||
|
||||
#include "flutter/fml/task_observer.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/tasks/task_runner.h"
|
||||
|
||||
@@ -16,6 +16,7 @@ class MessageLoopImpl;
|
||||
|
||||
class MessageLoop {
|
||||
public:
|
||||
FML_EMBEDDER_ONLY
|
||||
static MessageLoop& GetCurrent();
|
||||
|
||||
bool IsValid() const;
|
||||
@@ -24,11 +25,11 @@ class MessageLoop {
|
||||
|
||||
void Terminate();
|
||||
|
||||
void AddTaskObserver(TaskObserver* observer);
|
||||
void AddTaskObserver(intptr_t key, fxl::Closure callback);
|
||||
|
||||
void RemoveTaskObserver(TaskObserver* observer);
|
||||
void RemoveTaskObserver(intptr_t key);
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> GetTaskRunner() const;
|
||||
fxl::RefPtr<fml::TaskRunner> GetTaskRunner() const;
|
||||
|
||||
// Exposed for the embedder shell which allows clients to poll for events
|
||||
// instead of dedicating a thread to the message loop.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#define FML_USED_ON_EMBEDDER
|
||||
|
||||
#include "flutter/fml/message_loop_impl.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -11,35 +13,29 @@
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
#if OS_MACOSX
|
||||
|
||||
#include "flutter/fml/platform/darwin/message_loop_darwin.h"
|
||||
using PlatformMessageLoopImpl = fml::MessageLoopDarwin;
|
||||
|
||||
#elif OS_ANDROID
|
||||
|
||||
#include "flutter/fml/platform/android/message_loop_android.h"
|
||||
using PlatformMessageLoopImpl = fml::MessageLoopAndroid;
|
||||
|
||||
#elif OS_LINUX
|
||||
|
||||
#include "flutter/fml/platform/linux/message_loop_linux.h"
|
||||
using PlatformMessageLoopImpl = fml::MessageLoopLinux;
|
||||
|
||||
#elif OS_WIN
|
||||
|
||||
#include "flutter/fml/platform/win/message_loop_win.h"
|
||||
using PlatformMessageLoopImpl = fml::MessageLoopWin;
|
||||
|
||||
#else
|
||||
|
||||
#error This platform does not have a message loop implementation.
|
||||
|
||||
#endif
|
||||
|
||||
namespace fml {
|
||||
|
||||
fxl::RefPtr<MessageLoopImpl> MessageLoopImpl::Create() {
|
||||
return fxl::MakeRefCounted<::PlatformMessageLoopImpl>();
|
||||
#if OS_MACOSX
|
||||
return fxl::MakeRefCounted<MessageLoopDarwin>();
|
||||
#elif OS_ANDROID
|
||||
return fxl::MakeRefCounted<MessageLoopAndroid>();
|
||||
#elif OS_LINUX
|
||||
return fxl::MakeRefCounted<MessageLoopLinux>();
|
||||
#elif OS_WIN
|
||||
return fxl::MakeRefCounted<MessageLoopWin>();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MessageLoopImpl::MessageLoopImpl() : order_(0), terminated_(false) {}
|
||||
@@ -55,20 +51,19 @@ void MessageLoopImpl::RunExpiredTasksNow() {
|
||||
RunExpiredTasks();
|
||||
}
|
||||
|
||||
void MessageLoopImpl::AddTaskObserver(TaskObserver* observer) {
|
||||
FXL_DCHECK(observer != nullptr);
|
||||
void MessageLoopImpl::AddTaskObserver(intptr_t key, fxl::Closure callback) {
|
||||
FXL_DCHECK(callback != nullptr);
|
||||
FXL_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this)
|
||||
<< "Message loop task observer must be added on the same thread as the "
|
||||
"loop.";
|
||||
task_observers_.insert(observer);
|
||||
task_observers_[key] = std::move(callback);
|
||||
}
|
||||
|
||||
void MessageLoopImpl::RemoveTaskObserver(TaskObserver* observer) {
|
||||
FXL_DCHECK(observer != nullptr);
|
||||
void MessageLoopImpl::RemoveTaskObserver(intptr_t key) {
|
||||
FXL_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this)
|
||||
<< "Message loop task observer must be removed from the same thread as "
|
||||
"the loop.";
|
||||
task_observers_.erase(observer);
|
||||
task_observers_.erase(key);
|
||||
}
|
||||
|
||||
void MessageLoopImpl::DoRun() {
|
||||
@@ -144,7 +139,7 @@ void MessageLoopImpl::RunExpiredTasks() {
|
||||
for (const auto& invocation : invocations) {
|
||||
invocation();
|
||||
for (const auto& observer : task_observers_) {
|
||||
observer->DidProcessTask();
|
||||
observer.second();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/fml/message_loop.h"
|
||||
@@ -34,9 +34,9 @@ class MessageLoopImpl : public fxl::RefCountedThreadSafe<MessageLoopImpl> {
|
||||
|
||||
void PostTask(fxl::Closure task, fxl::TimePoint target_time);
|
||||
|
||||
void AddTaskObserver(TaskObserver* observer);
|
||||
void AddTaskObserver(intptr_t key, fxl::Closure callback);
|
||||
|
||||
void RemoveTaskObserver(TaskObserver* observer);
|
||||
void RemoveTaskObserver(intptr_t key);
|
||||
|
||||
void DoRun();
|
||||
|
||||
@@ -71,7 +71,7 @@ class MessageLoopImpl : public fxl::RefCountedThreadSafe<MessageLoopImpl> {
|
||||
using DelayedTaskQueue = std::
|
||||
priority_queue<DelayedTask, std::deque<DelayedTask>, DelayedTaskCompare>;
|
||||
|
||||
std::set<TaskObserver*> task_observers_;
|
||||
std::map<intptr_t, fxl::Closure> task_observers_;
|
||||
std::mutex delayed_tasks_mutex_;
|
||||
DelayedTaskQueue delayed_tasks_;
|
||||
size_t order_;
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#define FML_USED_ON_EMBEDDER
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "flutter/fml/message_loop.h"
|
||||
#include "flutter/fml/task_runner.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "lib/fxl/synchronization/waitable_event.h"
|
||||
|
||||
@@ -244,22 +247,6 @@ TEST(MessageLoop, TIME_SENSITIVE(MultipleDelayedTasksWithDecreasingDeltas)) {
|
||||
ASSERT_EQ(checked, count);
|
||||
}
|
||||
|
||||
class CustomTaskObserver : public fml::TaskObserver {
|
||||
public:
|
||||
CustomTaskObserver(std::function<void()> lambda) : lambda_(lambda){};
|
||||
|
||||
~CustomTaskObserver() override = default;
|
||||
|
||||
void DidProcessTask() override {
|
||||
if (lambda_) {
|
||||
lambda_();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::function<void()> lambda_;
|
||||
};
|
||||
|
||||
TEST(MessageLoop, TaskObserverFire) {
|
||||
bool started = false;
|
||||
bool terminated = false;
|
||||
@@ -269,8 +256,7 @@ TEST(MessageLoop, TaskObserverFire) {
|
||||
auto& loop = fml::MessageLoop::GetCurrent();
|
||||
size_t task_count = 0;
|
||||
size_t obs_count = 0;
|
||||
CustomTaskObserver obs(
|
||||
PLATFORM_SPECIFIC_CAPTURE(&obs_count)() { obs_count++; });
|
||||
auto obs = PLATFORM_SPECIFIC_CAPTURE(&obs_count)() { obs_count++; };
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
loop.GetTaskRunner()->PostTask(
|
||||
PLATFORM_SPECIFIC_CAPTURE(&terminated, i, &task_count)() {
|
||||
@@ -282,7 +268,7 @@ TEST(MessageLoop, TaskObserverFire) {
|
||||
}
|
||||
});
|
||||
}
|
||||
loop.AddTaskObserver(&obs);
|
||||
loop.AddTaskObserver(0, obs);
|
||||
loop.Run();
|
||||
ASSERT_EQ(task_count, count);
|
||||
ASSERT_EQ(obs_count, count);
|
||||
|
||||
52
engine/src/flutter/fml/native_library.h
Normal file
52
engine/src/flutter/fml/native_library.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_NATIVE_LIBRARY_H_
|
||||
#define FLUTTER_FML_NATIVE_LIBRARY_H_
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/ref_counted.h"
|
||||
#include "lib/fxl/memory/ref_ptr.h"
|
||||
|
||||
#if OS_WIN
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif // OS_WIN
|
||||
|
||||
namespace fml {
|
||||
class NativeLibrary : public fxl::RefCountedThreadSafe<NativeLibrary> {
|
||||
public:
|
||||
#if OS_WIN
|
||||
using Handle = HMODULE;
|
||||
#else // OS_WIN
|
||||
using Handle = void*;
|
||||
#endif // OS_WIN
|
||||
|
||||
static fxl::RefPtr<NativeLibrary> Create(const char* path);
|
||||
|
||||
static fxl::RefPtr<NativeLibrary> CreateForCurrentProcess();
|
||||
|
||||
const uint8_t* ResolveSymbol(const char* symbol);
|
||||
|
||||
private:
|
||||
Handle handle_ = nullptr;
|
||||
bool close_handle_ = true;
|
||||
|
||||
NativeLibrary(const char* path);
|
||||
|
||||
NativeLibrary(Handle handle, bool close_handle);
|
||||
|
||||
~NativeLibrary();
|
||||
|
||||
Handle GetHandle() const;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(NativeLibrary);
|
||||
FRIEND_REF_COUNTED_THREAD_SAFE(NativeLibrary);
|
||||
FRIEND_MAKE_REF_COUNTED(NativeLibrary);
|
||||
};
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_NATIVE_LIBRARY_H_
|
||||
31
engine/src/flutter/fml/paths.cc
Normal file
31
engine/src/flutter/fml/paths.cc
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/paths.h"
|
||||
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
namespace fml {
|
||||
namespace paths {
|
||||
|
||||
std::string JoinPaths(std::initializer_list<fxl::StringView> components) {
|
||||
std::stringstream stream;
|
||||
size_t i = 0;
|
||||
const size_t size = components.size();
|
||||
for (const auto& component : components) {
|
||||
i++;
|
||||
stream << component;
|
||||
if (i != size) {
|
||||
#if OS_WIN
|
||||
stream << "\\";
|
||||
#else // OS_WIN
|
||||
stream << "/";
|
||||
#endif // OS_WIN
|
||||
}
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace paths
|
||||
} // namespace fml
|
||||
@@ -8,11 +8,15 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "lib/fxl/strings/string_view.h"
|
||||
|
||||
namespace fml {
|
||||
namespace paths {
|
||||
|
||||
std::pair<bool, std::string> GetExecutableDirectoryPath();
|
||||
|
||||
std::string JoinPaths(std::initializer_list<fxl::StringView> components);
|
||||
|
||||
} // namespace paths
|
||||
} // namespace fml
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "flutter/fml/message_loop_impl.h"
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/memory/unique_object.h"
|
||||
|
||||
@@ -24,8 +24,8 @@ struct UniqueLooperTraits {
|
||||
|
||||
class MessageLoopAndroid : public MessageLoopImpl {
|
||||
private:
|
||||
fxl::UniqueObject<ALooper*, UniqueLooperTraits> looper_;
|
||||
fxl::UniqueFD timer_fd_;
|
||||
fml::UniqueObject<ALooper*, UniqueLooperTraits> looper_;
|
||||
fml::UniqueFD timer_fd_;
|
||||
bool running_;
|
||||
|
||||
MessageLoopAndroid();
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
namespace fml {
|
||||
|
||||
ResourceMappingDarwin::ResourceMappingDarwin(const std::string& resource)
|
||||
: actual_([[[NSBundle mainBundle] pathForResource:@(resource.c_str()) ofType:nil] UTF8String]) {
|
||||
}
|
||||
: actual_([[[NSBundle mainBundle] pathForResource:@(resource.c_str()) ofType:nil] UTF8String],
|
||||
false) {}
|
||||
|
||||
ResourceMappingDarwin::~ResourceMappingDarwin() = default;
|
||||
|
||||
|
||||
15
engine/src/flutter/fml/platform/fuchsia/paths_fuchsia.cc
Normal file
15
engine/src/flutter/fml/platform/fuchsia/paths_fuchsia.cc
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/paths.h"
|
||||
|
||||
namespace fml {
|
||||
namespace paths {
|
||||
|
||||
std::pair<bool, std::string> GetExecutableDirectoryPath() {
|
||||
return {false, ""};
|
||||
}
|
||||
|
||||
} // namespace paths
|
||||
} // namespace fml
|
||||
@@ -8,15 +8,15 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "flutter/fml/message_loop_impl.h"
|
||||
#include "lib/fxl/files/unique_fd.h"
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
class MessageLoopLinux : public MessageLoopImpl {
|
||||
private:
|
||||
fxl::UniqueFD epoll_fd_;
|
||||
fxl::UniqueFD timer_fd_;
|
||||
fml::UniqueFD epoll_fd_;
|
||||
fml::UniqueFD timer_fd_;
|
||||
bool running_;
|
||||
|
||||
MessageLoopLinux();
|
||||
|
||||
71
engine/src/flutter/fml/platform/posix/file_posix.cc
Normal file
71
engine/src/flutter/fml/platform/posix/file_posix.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/file.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/fxl/files/eintr_wrapper.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
fml::UniqueFD OpenFile(const char* path,
|
||||
OpenPermission permission,
|
||||
bool is_directory) {
|
||||
return OpenFile(fml::UniqueFD{AT_FDCWD}, path, permission, is_directory);
|
||||
}
|
||||
|
||||
fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
|
||||
const char* path,
|
||||
OpenPermission permission,
|
||||
bool is_directory) {
|
||||
if (path == nullptr) {
|
||||
return fml::UniqueFD{};
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
switch (permission) {
|
||||
case OpenPermission::kRead:
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
case OpenPermission::kWrite:
|
||||
flags = O_WRONLY;
|
||||
break;
|
||||
case OpenPermission::kReadWrite:
|
||||
flags = O_RDWR;
|
||||
break;
|
||||
case OpenPermission::kExecute:
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_directory) {
|
||||
flags |= O_DIRECTORY;
|
||||
}
|
||||
|
||||
return fml::UniqueFD{
|
||||
HANDLE_EINTR(::openat(base_directory.get(), path, flags))};
|
||||
}
|
||||
|
||||
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
|
||||
return fml::UniqueFD{HANDLE_EINTR(::dup(descriptor))};
|
||||
}
|
||||
|
||||
bool IsDirectory(const fml::UniqueFD& directory) {
|
||||
if (!directory.is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct stat stat_result = {};
|
||||
|
||||
if (::fstat(directory.get(), &stat_result) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return S_ISDIR(stat_result.st_mode);
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "lib/fxl/build_config.h"
|
||||
#include "lib/fxl/files/eintr_wrapper.h"
|
||||
|
||||
@@ -39,11 +40,11 @@ std::unique_ptr<Mapping> GetResourceMapping(const std::string& resource_name) {
|
||||
return std::make_unique<PlatformResourceMapping>(resource_name);
|
||||
}
|
||||
|
||||
FileMapping::FileMapping(const std::string& path)
|
||||
: FileMapping(fxl::UniqueFD{HANDLE_EINTR(::open(path.c_str(), O_RDONLY))}) {
|
||||
}
|
||||
FileMapping::FileMapping(const std::string& path, bool executable)
|
||||
: FileMapping(fml::UniqueFD{HANDLE_EINTR(::open(path.c_str(), O_RDONLY))},
|
||||
executable) {}
|
||||
|
||||
FileMapping::FileMapping(const fxl::UniqueFD& handle)
|
||||
FileMapping::FileMapping(const fml::UniqueFD& handle, bool executable)
|
||||
: size_(0), mapping_(nullptr) {
|
||||
if (!handle.is_valid()) {
|
||||
return;
|
||||
@@ -59,8 +60,13 @@ FileMapping::FileMapping(const fxl::UniqueFD& handle)
|
||||
return;
|
||||
}
|
||||
|
||||
auto mapping = ::mmap(nullptr, stat_buffer.st_size, PROT_READ, MAP_PRIVATE,
|
||||
handle.get(), 0);
|
||||
int flags = PROT_READ;
|
||||
if (executable) {
|
||||
flags |= PROT_EXEC;
|
||||
}
|
||||
|
||||
auto mapping =
|
||||
::mmap(nullptr, stat_buffer.st_size, flags, MAP_PRIVATE, handle.get(), 0);
|
||||
|
||||
if (mapping == MAP_FAILED) {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/native_library.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace fml {
|
||||
|
||||
NativeLibrary::NativeLibrary(const char* path) {
|
||||
::dlerror();
|
||||
handle_ = ::dlopen(path, RTLD_NOW);
|
||||
if (handle_ == nullptr) {
|
||||
FXL_LOG(ERROR) << "Could not open library '" << path << "' due to error '"
|
||||
<< ::dlerror() << "'.";
|
||||
}
|
||||
}
|
||||
|
||||
NativeLibrary::NativeLibrary(Handle handle, bool close_handle)
|
||||
: handle_(handle), close_handle_(close_handle) {}
|
||||
|
||||
NativeLibrary::~NativeLibrary() {
|
||||
if (handle_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (close_handle_) {
|
||||
::dlerror();
|
||||
if (::dlclose(handle_) != 0) {
|
||||
handle_ = nullptr;
|
||||
FXL_LOG(ERROR) << "Could not close library due to error '" << ::dlerror()
|
||||
<< "'.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeLibrary::Handle NativeLibrary::GetHandle() const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
fxl::RefPtr<NativeLibrary> NativeLibrary::Create(const char* path) {
|
||||
auto library = fxl::AdoptRef(new NativeLibrary(path));
|
||||
return library->GetHandle() != nullptr ? library : nullptr;
|
||||
}
|
||||
|
||||
fxl::RefPtr<NativeLibrary> NativeLibrary::CreateForCurrentProcess() {
|
||||
return fxl::AdoptRef(new NativeLibrary(RTLD_DEFAULT, false));
|
||||
}
|
||||
|
||||
const uint8_t* NativeLibrary::ResolveSymbol(const char* symbol) {
|
||||
auto resolved_symbol = static_cast<const uint8_t*>(::dlsym(handle_, symbol));
|
||||
if (resolved_symbol == nullptr) {
|
||||
FXL_DLOG(ERROR) << "Could not resolve symbol in library: " << symbol;
|
||||
}
|
||||
return resolved_symbol;
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
119
engine/src/flutter/fml/platform/win/file_win.cc
Normal file
119
engine/src/flutter/fml/platform/win/file_win.cc
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/file.h"
|
||||
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "flutter/fml/platform/win/wstring_conversion.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
fml::UniqueFD OpenFile(const std::wstring& path,
|
||||
OpenPermission permission,
|
||||
bool is_directory) {
|
||||
if (path.size() == 0) {
|
||||
return fml::UniqueFD{};
|
||||
}
|
||||
|
||||
DWORD desired_access = 0;
|
||||
|
||||
switch (permission) {
|
||||
case OpenPermission::kRead:
|
||||
desired_access = GENERIC_READ;
|
||||
break;
|
||||
case OpenPermission::kWrite:
|
||||
desired_access = GENERIC_WRITE;
|
||||
break;
|
||||
case OpenPermission::kReadWrite:
|
||||
desired_access = GENERIC_WRITE | GENERIC_READ;
|
||||
break;
|
||||
case OpenPermission::kExecute:
|
||||
desired_access = GENERIC_READ | GENERIC_EXECUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
return fml::UniqueFD{::CreateFile(
|
||||
path.c_str(), // lpFileName
|
||||
desired_access, // dwDesiredAccess
|
||||
FILE_SHARE_READ, // dwShareMode
|
||||
0, // lpSecurityAttributes
|
||||
OPEN_EXISTING, // dwCreationDisposition
|
||||
FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
|
||||
0 // hTemplateFile
|
||||
)};
|
||||
}
|
||||
|
||||
fml::UniqueFD OpenFile(const char* path,
|
||||
OpenPermission permission,
|
||||
bool is_directory) {
|
||||
return OpenFile(ConvertToWString(path), permission, is_directory);
|
||||
}
|
||||
|
||||
static std::wstring GetFullHandlePath(const fml::UniqueFD& handle) {
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
DWORD returned = ::GetFinalPathNameByHandle(handle.get(), buffer, MAX_PATH,
|
||||
FILE_NAME_NORMALIZED);
|
||||
if (returned == 0 || returned > MAX_PATH) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {buffer};
|
||||
}
|
||||
|
||||
fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
|
||||
const char* path,
|
||||
OpenPermission permission,
|
||||
bool is_directory) {
|
||||
// If the base directory is invalid or the path is absolute, use the generic
|
||||
// open file variant.
|
||||
if (!base_directory.is_valid()) {
|
||||
return OpenFile(path, permission, is_directory);
|
||||
}
|
||||
|
||||
const auto wpath = ConvertToWString(path);
|
||||
|
||||
if (!::PathIsRelative(wpath.c_str())) {
|
||||
return OpenFile(path, permission, is_directory);
|
||||
}
|
||||
|
||||
std::wstringstream stream;
|
||||
stream << GetFullHandlePath(base_directory) << "\\" << path;
|
||||
return OpenFile(stream.str(), permission, is_directory);
|
||||
}
|
||||
|
||||
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
|
||||
if (descriptor == INVALID_HANDLE_VALUE) {
|
||||
return fml::UniqueFD{};
|
||||
}
|
||||
|
||||
HANDLE duplicated = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!::DuplicateHandle(
|
||||
GetCurrentProcess(), // source process
|
||||
descriptor, // source handle
|
||||
GetCurrentProcess(), // target process
|
||||
&duplicated, // target handle
|
||||
0, // desired access (ignored because DUPLICATE_SAME_ACCESS)
|
||||
FALSE, // inheritable
|
||||
DUPLICATE_SAME_ACCESS) // options
|
||||
) {
|
||||
return fml::UniqueFD{};
|
||||
}
|
||||
|
||||
return fml::UniqueFD{duplicated};
|
||||
}
|
||||
|
||||
bool IsDirectory(const fml::UniqueFD& directory) {
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (!::GetFileInformationByHandle(directory.get(), &info)) {
|
||||
return false;
|
||||
}
|
||||
return info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
@@ -5,13 +5,13 @@
|
||||
#include "flutter/fml/mapping.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#include "flutter/fml/file.h"
|
||||
#include "flutter/fml/platform/win/wstring_conversion.h"
|
||||
|
||||
using PlatformResourceMapping = fml::FileMapping;
|
||||
|
||||
@@ -29,47 +29,50 @@ std::unique_ptr<Mapping> GetResourceMapping(const std::string& resource_name) {
|
||||
return std::make_unique<PlatformResourceMapping>(resource_name);
|
||||
}
|
||||
|
||||
FileMapping::FileMapping(const std::string& path)
|
||||
FileMapping::FileMapping(const std::string& path, bool executable)
|
||||
: FileMapping(OpenFile(path.c_str(),
|
||||
executable ? OpenPermission::kExecute
|
||||
: OpenPermission::kRead,
|
||||
false),
|
||||
executable) {}
|
||||
|
||||
FileMapping::FileMapping(const fml::UniqueFD& fd, bool executable)
|
||||
: size_(0), mapping_(nullptr) {
|
||||
HANDLE file_handle_ =
|
||||
CreateFileA(reinterpret_cast<LPCSTR>(path.c_str()), GENERIC_READ,
|
||||
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
|
||||
if (file_handle_ == INVALID_HANDLE_VALUE) {
|
||||
if (!fd.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_ = GetFileSize(file_handle_, nullptr);
|
||||
if (size_ == INVALID_FILE_SIZE) {
|
||||
size_ = 0;
|
||||
if (auto size = ::GetFileSize(fd.get(), nullptr)) {
|
||||
if (size > 0) {
|
||||
size_ = size;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const DWORD protect = executable ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
||||
|
||||
mapping_handle_.reset(::CreateFileMapping(fd.get(), // hFile
|
||||
nullptr, // lpAttributes
|
||||
protect, // flProtect
|
||||
0, // dwMaximumSizeHigh
|
||||
0, // dwMaximumSizeLow
|
||||
nullptr // lpName
|
||||
));
|
||||
|
||||
if (!mapping_handle_.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mapping_handle_ = CreateFileMapping(file_handle_, nullptr, PAGE_READONLY, 0,
|
||||
size_, nullptr);
|
||||
const DWORD desired_access = executable ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ;
|
||||
|
||||
CloseHandle(file_handle_);
|
||||
|
||||
if (mapping_handle_ == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto mapping = MapViewOfFile(mapping_handle_, FILE_MAP_READ, 0, 0, size_);
|
||||
|
||||
if (mapping == INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(mapping_handle_);
|
||||
mapping_handle_ = INVALID_HANDLE_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
mapping_ = static_cast<uint8_t*>(mapping);
|
||||
mapping_ = reinterpret_cast<uint8_t*>(
|
||||
MapViewOfFile(mapping_handle_.get(), desired_access, 0, 0, size_));
|
||||
}
|
||||
|
||||
FileMapping::~FileMapping() {
|
||||
if (mapping_ != nullptr) {
|
||||
UnmapViewOfFile(mapping_);
|
||||
CloseHandle(mapping_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
51
engine/src/flutter/fml/platform/win/native_library_win.cc
Normal file
51
engine/src/flutter/fml/platform/win/native_library_win.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/native_library.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "flutter/fml/platform/win/wstring_conversion.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
NativeLibrary::NativeLibrary(const char* path)
|
||||
: handle_(nullptr), close_handle_(true) {
|
||||
if (path == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
handle_ = ::LoadLibrary(ConvertToWString(path).c_str());
|
||||
}
|
||||
|
||||
NativeLibrary::NativeLibrary(Handle handle, bool close_handle)
|
||||
: handle_(handle), close_handle_(close_handle) {}
|
||||
|
||||
NativeLibrary::~NativeLibrary() {
|
||||
if (handle_ != nullptr && close_handle_) {
|
||||
::FreeLibrary(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
NativeLibrary::Handle NativeLibrary::GetHandle() const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
fxl::RefPtr<NativeLibrary> NativeLibrary::Create(const char* path) {
|
||||
auto library = fxl::AdoptRef(new NativeLibrary(path));
|
||||
return library->GetHandle() != nullptr ? library : nullptr;
|
||||
}
|
||||
|
||||
fxl::RefPtr<NativeLibrary> NativeLibrary::CreateForCurrentProcess() {
|
||||
return fxl::AdoptRef(new NativeLibrary(::GetModuleHandle(nullptr), false));
|
||||
}
|
||||
|
||||
const uint8_t* NativeLibrary::ResolveSymbol(const char* symbol) {
|
||||
if (symbol == nullptr || handle_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const uint8_t*>(::GetProcAddress(handle_, symbol));
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
25
engine/src/flutter/fml/platform/win/wstring_conversion.h
Normal file
25
engine/src/flutter/fml/platform/win/wstring_conversion.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_PLATFORM_WIN_WSTRING_CONVERSION_H_
|
||||
#define FLUTTER_FML_PLATFORM_WIN_WSTRING_CONVERSION_H_
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
namespace fml {
|
||||
|
||||
inline std::wstring ConvertToWString(const char* path) {
|
||||
if (path == nullptr) {
|
||||
return {};
|
||||
}
|
||||
std::string path8(path);
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> wchar_conv;
|
||||
return wchar_conv.from_bytes(path8);
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_PLATFORM_WIN_WSTRING_CONVERSION_H_
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_TASK_OBSERVER_H_
|
||||
#define FLUTTER_FML_TASK_OBSERVER_H_
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
class TaskObserver {
|
||||
public:
|
||||
virtual ~TaskObserver() = default;
|
||||
|
||||
virtual void DidProcessTask() = 0;
|
||||
};
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_TASK_OBSERVER_H_
|
||||
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#define FML_USED_ON_EMBEDDER
|
||||
|
||||
#include "flutter/fml/task_runner.h"
|
||||
|
||||
#include <utility>
|
||||
@@ -38,4 +40,14 @@ bool TaskRunner::RunsTasksOnCurrentThread() {
|
||||
return MessageLoop::GetCurrent().GetLoopImpl() == loop_;
|
||||
}
|
||||
|
||||
void TaskRunner::RunNowOrPostTask(fxl::RefPtr<fxl::TaskRunner> runner,
|
||||
fxl::Closure task) {
|
||||
FXL_DCHECK(runner);
|
||||
if (runner->RunsTasksOnCurrentThread()) {
|
||||
task();
|
||||
} else {
|
||||
runner->PostTask(std::move(task));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace fml {
|
||||
|
||||
class MessageLoopImpl;
|
||||
|
||||
class TaskRunner : public fxl::TaskRunner {
|
||||
class TaskRunner final : public fxl::TaskRunner {
|
||||
public:
|
||||
void PostTask(fxl::Closure task) override;
|
||||
|
||||
@@ -23,12 +23,15 @@ class TaskRunner : public fxl::TaskRunner {
|
||||
|
||||
bool RunsTasksOnCurrentThread() override;
|
||||
|
||||
static void RunNowOrPostTask(fxl::RefPtr<fxl::TaskRunner> runner,
|
||||
fxl::Closure task);
|
||||
|
||||
private:
|
||||
fxl::RefPtr<MessageLoopImpl> loop_;
|
||||
|
||||
TaskRunner(fxl::RefPtr<MessageLoopImpl> loop);
|
||||
|
||||
~TaskRunner();
|
||||
~TaskRunner() override;
|
||||
|
||||
FRIEND_MAKE_REF_COUNTED(TaskRunner);
|
||||
FRIEND_REF_COUNTED_THREAD_SAFE(TaskRunner);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#define FML_USED_ON_EMBEDDER
|
||||
|
||||
#include "flutter/fml/thread.h"
|
||||
|
||||
#include "lib/fxl/build_config.h"
|
||||
@@ -22,7 +24,7 @@ namespace fml {
|
||||
|
||||
Thread::Thread(const std::string& name) : joined_(false) {
|
||||
fxl::AutoResetWaitableEvent latch;
|
||||
fxl::RefPtr<fxl::TaskRunner> runner;
|
||||
fxl::RefPtr<fml::TaskRunner> runner;
|
||||
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
|
||||
SetCurrentThreadName(name);
|
||||
fml::MessageLoop::EnsureInitializedForCurrentThread();
|
||||
@@ -39,7 +41,7 @@ Thread::~Thread() {
|
||||
Join();
|
||||
}
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> Thread::GetTaskRunner() const {
|
||||
fxl::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const {
|
||||
return task_runner_;
|
||||
}
|
||||
|
||||
@@ -84,7 +86,8 @@ void Thread::SetCurrentThreadName(const std::string& name) {
|
||||
} __except (EXCEPTION_CONTINUE_EXECUTION) {
|
||||
}
|
||||
#else
|
||||
#error Unsupported Platform
|
||||
FXL_DLOG(INFO) << "Could not set the thread name to '" << name
|
||||
<< "' on this platform.";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include "flutter/fml/task_runner.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "lib/fxl/tasks/task_runner.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
@@ -20,13 +20,13 @@ class Thread {
|
||||
|
||||
~Thread();
|
||||
|
||||
fxl::RefPtr<fxl::TaskRunner> GetTaskRunner() const;
|
||||
fxl::RefPtr<fml::TaskRunner> GetTaskRunner() const;
|
||||
|
||||
void Join();
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
fxl::RefPtr<fxl::TaskRunner> task_runner_;
|
||||
fxl::RefPtr<fml::TaskRunner> task_runner_;
|
||||
std::atomic_bool joined_;
|
||||
|
||||
static void SetCurrentThreadName(const std::string& name);
|
||||
|
||||
35
engine/src/flutter/fml/unique_fd.cc
Normal file
35
engine/src/flutter/fml/unique_fd.cc
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
|
||||
#include "lib/fxl/files/eintr_wrapper.h"
|
||||
|
||||
namespace fml {
|
||||
namespace internal {
|
||||
|
||||
#if OS_WIN
|
||||
|
||||
namespace win {
|
||||
|
||||
void UniqueFDTraits::Free(HANDLE fd) {
|
||||
CloseHandle(fd);
|
||||
}
|
||||
|
||||
} // namespace win
|
||||
|
||||
#else // OS_WIN
|
||||
|
||||
namespace unix {
|
||||
|
||||
void UniqueFDTraits::Free(int fd) {
|
||||
IGNORE_EINTR(fd);
|
||||
}
|
||||
|
||||
} // namespace unix
|
||||
|
||||
#endif // OS_WIN
|
||||
|
||||
} // namespace internal
|
||||
} // namespace fml
|
||||
60
engine/src/flutter/fml/unique_fd.h
Normal file
60
engine/src/flutter/fml/unique_fd.h
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_UNIQUE_FD_H_
|
||||
#define FLUTTER_FML_UNIQUE_FD_H_
|
||||
|
||||
#include "flutter/fml/unique_object.h"
|
||||
#include "lib/fxl/build_config.h"
|
||||
|
||||
#if OS_WIN
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif // OS_WIN
|
||||
|
||||
namespace fml {
|
||||
namespace internal {
|
||||
|
||||
#if OS_WIN
|
||||
|
||||
namespace win {
|
||||
|
||||
struct UniqueFDTraits {
|
||||
static HANDLE InvalidValue() { return INVALID_HANDLE_VALUE; }
|
||||
static bool IsValid(HANDLE value) { return value != InvalidValue(); }
|
||||
static void Free(HANDLE fd);
|
||||
};
|
||||
|
||||
} // namespace win
|
||||
|
||||
#else // OS_WIN
|
||||
|
||||
namespace unix {
|
||||
|
||||
struct UniqueFDTraits {
|
||||
static int InvalidValue() { return -1; }
|
||||
static bool IsValid(int value) { return value >= 0; }
|
||||
static void Free(int fd);
|
||||
};
|
||||
|
||||
} // namespace unix
|
||||
|
||||
#endif // OS_WIN
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#if OS_WIN
|
||||
|
||||
using UniqueFD = UniqueObject<HANDLE, internal::win::UniqueFDTraits>;
|
||||
|
||||
#else // OS_WIN
|
||||
|
||||
using UniqueFD = UniqueObject<int, internal::unix::UniqueFDTraits>;
|
||||
|
||||
#endif // OS_WIN
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_UNIQUE_FD_H_
|
||||
137
engine/src/flutter/fml/unique_object.h
Normal file
137
engine/src/flutter/fml/unique_object.h
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2018 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FML_UNIQUE_OBJECT_H_
|
||||
#define FLUTTER_FML_UNIQUE_OBJECT_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "lib/fxl/compiler_specific.h"
|
||||
#include "lib/fxl/logging.h"
|
||||
#include "lib/fxl/macros.h"
|
||||
|
||||
namespace fml {
|
||||
|
||||
// struct UniqueFooTraits {
|
||||
// // This function should be fast an inline.
|
||||
// static int InvalidValue() { return 0; }
|
||||
//
|
||||
// // This function should be fast an inline.
|
||||
// static bool IsValid(const T& value) { return value != InvalidValue(); }
|
||||
//
|
||||
// // This free function will not be called if f == InvalidValue()!
|
||||
// static void Free(int f) { ::FreeFoo(f); }
|
||||
// };
|
||||
|
||||
template <typename T, typename Traits>
|
||||
class UniqueObject {
|
||||
private:
|
||||
// This must be first since it's used inline below.
|
||||
//
|
||||
// Use the empty base class optimization to allow us to have a Traits
|
||||
// member, while avoiding any space overhead for it when Traits is an
|
||||
// empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
|
||||
// discussion of this technique.
|
||||
struct Data : public Traits {
|
||||
explicit Data(const T& in) : generic(in) {}
|
||||
Data(const T& in, const Traits& other) : Traits(other), generic(in) {}
|
||||
|
||||
T generic;
|
||||
};
|
||||
|
||||
public:
|
||||
using element_type = T;
|
||||
using traits_type = Traits;
|
||||
|
||||
UniqueObject() : data_(Traits::InvalidValue()) {}
|
||||
explicit UniqueObject(const T& value) : data_(value) {}
|
||||
|
||||
UniqueObject(const T& value, const Traits& traits) : data_(value, traits) {}
|
||||
|
||||
UniqueObject(UniqueObject&& other)
|
||||
: data_(other.release(), other.get_traits()) {}
|
||||
|
||||
~UniqueObject() { FreeIfNecessary(); }
|
||||
|
||||
UniqueObject& operator=(UniqueObject&& other) {
|
||||
reset(other.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(const T& value = Traits::InvalidValue()) {
|
||||
FXL_CHECK(data_.generic == Traits::InvalidValue() ||
|
||||
data_.generic != value);
|
||||
FreeIfNecessary();
|
||||
data_.generic = value;
|
||||
}
|
||||
|
||||
void swap(UniqueObject& other) {
|
||||
// Standard swap idiom: 'using std::swap' ensures that std::swap is
|
||||
// present in the overload set, but we call swap unqualified so that
|
||||
// any more-specific overloads can be used, if available.
|
||||
using std::swap;
|
||||
swap(static_cast<Traits&>(data_), static_cast<Traits&>(other.data_));
|
||||
swap(data_.generic, other.data_.generic);
|
||||
}
|
||||
|
||||
// Release the object. The return value is the current object held by this
|
||||
// object. After this operation, this object will hold an invalid value, and
|
||||
// will not own the object any more.
|
||||
T release() FXL_WARN_UNUSED_RESULT {
|
||||
T old_generic = data_.generic;
|
||||
data_.generic = Traits::InvalidValue();
|
||||
return old_generic;
|
||||
}
|
||||
|
||||
const T& get() const { return data_.generic; }
|
||||
|
||||
bool is_valid() const { return Traits::IsValid(data_.generic); }
|
||||
|
||||
bool operator==(const T& value) const { return data_.generic == value; }
|
||||
|
||||
bool operator!=(const T& value) const { return data_.generic != value; }
|
||||
|
||||
Traits& get_traits() { return data_; }
|
||||
const Traits& get_traits() const { return data_; }
|
||||
|
||||
private:
|
||||
void FreeIfNecessary() {
|
||||
if (data_.generic != Traits::InvalidValue()) {
|
||||
data_.Free(data_.generic);
|
||||
data_.generic = Traits::InvalidValue();
|
||||
}
|
||||
}
|
||||
|
||||
// Forbid comparison. If U != T, it totally doesn't make sense, and if U ==
|
||||
// T, it still doesn't make sense because you should never have the same
|
||||
// object owned by two different UniqueObject.
|
||||
template <typename T2, typename Traits2>
|
||||
bool operator==(const UniqueObject<T2, Traits2>& p2) const = delete;
|
||||
|
||||
template <typename T2, typename Traits2>
|
||||
bool operator!=(const UniqueObject<T2, Traits2>& p2) const = delete;
|
||||
|
||||
Data data_;
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(UniqueObject);
|
||||
};
|
||||
|
||||
template <class T, class Traits>
|
||||
void swap(const UniqueObject<T, Traits>& a, const UniqueObject<T, Traits>& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
bool operator==(const T& value, const UniqueObject<T, Traits>& object) {
|
||||
return value == object.get();
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
bool operator!=(const T& value, const UniqueObject<T, Traits>& object) {
|
||||
return !(value == object.get());
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
|
||||
#endif // FLUTTER_FML_UNIQUE_OBJECT_H_
|
||||
@@ -29,20 +29,40 @@ if (is_fuchsia) {
|
||||
# The sole purpose of this target is to generate a .packages file.
|
||||
sources = []
|
||||
|
||||
infer_package_name = true
|
||||
dot_packages_file = "$target_gen_dir/snapshot.packages"
|
||||
outputs = [
|
||||
dot_packages_file,
|
||||
]
|
||||
deps = []
|
||||
foreach(dep, dart_deps) {
|
||||
deps += [ "$dep($dart_toolchain)" ]
|
||||
}
|
||||
|
||||
disable_analysis = true
|
||||
|
||||
deps = [
|
||||
"//topaz/public/dart/fuchsia",
|
||||
"//topaz/public/dart/zircon",
|
||||
]
|
||||
script = "//build/dart/gen_dot_packages.py"
|
||||
args = [
|
||||
"--out",
|
||||
rebase_path(dot_packages_file, root_build_dir),
|
||||
"--source-dir",
|
||||
rebase_path("."),
|
||||
"--root-build-dir",
|
||||
rebase_path(root_build_dir),
|
||||
"--root-gen-dir",
|
||||
rebase_path(dart_root_gen_dir),
|
||||
"--package-name",
|
||||
"snapshot_root",
|
||||
"--depfile",
|
||||
rebase_path(depfile),
|
||||
"--deps",
|
||||
] + dart_deps
|
||||
}
|
||||
}
|
||||
|
||||
action("generate_snapshot_bin") {
|
||||
if (is_fuchsia) {
|
||||
snapshot_dart = "snapshot_fuchsia.dart"
|
||||
|
||||
# TODO(rmacnak): Fuchsia cross builds use the wrong Dart target
|
||||
# architecture, and have added steps that depend on this error for
|
||||
# reasonable build times (e.g., invoking the analyzer).
|
||||
@@ -85,9 +105,9 @@ action("generate_snapshot_bin") {
|
||||
|
||||
rebased_dart_ui_path = rebase_path(dart_ui_path)
|
||||
|
||||
gen_snapshot_dir =
|
||||
get_label_info("//third_party/dart/runtime/bin:gen_snapshot($host_toolchain)",
|
||||
"root_out_dir")
|
||||
gen_snapshot_dir = get_label_info(
|
||||
"//third_party/dart/runtime/bin:gen_snapshot($host_toolchain)",
|
||||
"root_out_dir")
|
||||
script = "//third_party/dart/runtime/tools/create_snapshot_bin.py"
|
||||
|
||||
args = [
|
||||
@@ -209,7 +229,7 @@ bin_to_assembly("isolate_snapshot_data_assembly") {
|
||||
]
|
||||
input = "$target_gen_dir/isolate_snapshot.bin"
|
||||
output = "$target_gen_dir/isolate_snapshot_data.S"
|
||||
symbol = "kDartIsolateCoreSnapshotData"
|
||||
symbol = "kDartIsolateSnapshotData"
|
||||
executable = false
|
||||
}
|
||||
|
||||
@@ -219,7 +239,7 @@ bin_to_assembly("isolate_snapshot_instructions_assembly") {
|
||||
]
|
||||
input = "$target_gen_dir/isolate_snapshot_instructions.bin"
|
||||
output = "$target_gen_dir/isolate_snapshot_instructions.S"
|
||||
symbol = "kDartIsolateCoreSnapshotInstructions"
|
||||
symbol = "kDartIsolateSnapshotInstructions"
|
||||
executable = true
|
||||
}
|
||||
|
||||
@@ -249,9 +269,9 @@ compile_platform("non_strong_platform") {
|
||||
]
|
||||
|
||||
args = [
|
||||
"--target=flutter",
|
||||
"dart:core",
|
||||
]
|
||||
"--target=flutter",
|
||||
"dart:core",
|
||||
]
|
||||
}
|
||||
|
||||
compile_platform("strong_platform") {
|
||||
@@ -265,10 +285,10 @@ compile_platform("strong_platform") {
|
||||
]
|
||||
|
||||
args = [
|
||||
"--target=flutter",
|
||||
"--strong",
|
||||
"dart:core"
|
||||
]
|
||||
"--target=flutter",
|
||||
"--strong",
|
||||
"dart:core",
|
||||
]
|
||||
}
|
||||
|
||||
group("kernel_platform_files") {
|
||||
|
||||
@@ -40,14 +40,10 @@ source_set("ui") {
|
||||
"painting/picture.h",
|
||||
"painting/picture_recorder.cc",
|
||||
"painting/picture_recorder.h",
|
||||
"painting/resource_context.cc",
|
||||
"painting/resource_context.h",
|
||||
"painting/rrect.cc",
|
||||
"painting/rrect.h",
|
||||
"painting/shader.cc",
|
||||
"painting/shader.h",
|
||||
"painting/utils.cc",
|
||||
"painting/utils.h",
|
||||
"painting/vertices.cc",
|
||||
"painting/vertices.h",
|
||||
"semantics/semantics_node.cc",
|
||||
@@ -87,19 +83,18 @@ source_set("ui") {
|
||||
"window/window.h",
|
||||
]
|
||||
|
||||
public_configs = [
|
||||
"$flutter_root:config",
|
||||
]
|
||||
public_configs = [ "$flutter_root:config" ]
|
||||
|
||||
deps = [
|
||||
"//third_party/dart/runtime/bin:embedded_dart_io",
|
||||
"$flutter_root/assets",
|
||||
"$flutter_root/common",
|
||||
"$flutter_root/flow",
|
||||
"$flutter_root/fml",
|
||||
"$flutter_root/glue",
|
||||
"$flutter_root/runtime:test_font",
|
||||
"$flutter_root/sky/engine",
|
||||
"$flutter_root/third_party/txt",
|
||||
"//third_party/dart/runtime/bin:embedded_dart_io",
|
||||
"//third_party/rapidjson",
|
||||
"//third_party/skia",
|
||||
"//third_party/skia:gpu",
|
||||
|
||||
@@ -120,10 +120,11 @@ void SceneBuilder::addPicture(double dx,
|
||||
double dy,
|
||||
Picture* picture,
|
||||
int hints) {
|
||||
layer_builder_->PushPicture(SkPoint::Make(dx, dy), //
|
||||
picture->picture(), //
|
||||
!!(hints & 1), // picture is complex
|
||||
!!(hints & 2) // picture will change
|
||||
layer_builder_->PushPicture(
|
||||
SkPoint::Make(dx, dy), //
|
||||
UIDartState::CreateGPUObject(picture->picture()), //
|
||||
!!(hints & 1), // picture is complex
|
||||
!!(hints & 2) // picture will change
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "flutter/lib/ui/compositing/scene_host.h"
|
||||
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/tonic/dart_args.h"
|
||||
#include "lib/tonic/dart_binding_macros.h"
|
||||
#include "lib/tonic/dart_library_natives.h"
|
||||
@@ -37,8 +38,9 @@ fxl::RefPtr<SceneHost> SceneHost::create(
|
||||
}
|
||||
|
||||
SceneHost::SceneHost(fxl::RefPtr<zircon::dart::Handle> export_token_handle) {
|
||||
export_node_holder_ =
|
||||
fxl::MakeRefCounted<flow::ExportNodeHolder>(export_token_handle);
|
||||
export_node_holder_ = fxl::MakeRefCounted<flow::ExportNodeHolder>(
|
||||
blink::UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner(),
|
||||
export_token_handle);
|
||||
}
|
||||
#else
|
||||
fxl::RefPtr<SceneHost> SceneHost::create(Dart_Handle export_token_handle) {
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "flutter/common/settings.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/fxl/build_config.h"
|
||||
#include "lib/fxl/logging.h"
|
||||
#include "lib/tonic/converter/dart_converter.h"
|
||||
@@ -141,17 +145,43 @@ void DartRuntimeHooks::Install(IsolateType isolate_type,
|
||||
// Implementation of native functions which are used for some
|
||||
// test/debug functionality in standalone dart mode.
|
||||
void Logger_PrintString(Dart_NativeArguments args) {
|
||||
intptr_t length = 0;
|
||||
uint8_t* chars = nullptr;
|
||||
Dart_Handle str = Dart_GetNativeArgument(args, 0);
|
||||
Dart_Handle result = Dart_StringToUTF8(str, &chars, &length);
|
||||
if (Dart_IsError(result)) {
|
||||
Dart_PropagateError(result);
|
||||
} else {
|
||||
std::stringstream stream;
|
||||
const auto& logger_prefix = UIDartState::Current()->logger_prefix();
|
||||
|
||||
#if !OS(ANDROID)
|
||||
// Prepend all logs with the isolate debug name except on Android where that
|
||||
// prefix is specified in the log tag.
|
||||
if (logger_prefix.size() > 0) {
|
||||
stream << logger_prefix << ": ";
|
||||
}
|
||||
#endif // !OS(ANDROID)
|
||||
|
||||
// Append the log buffer obtained from Dart code.
|
||||
{
|
||||
Dart_Handle str = Dart_GetNativeArgument(args, 0);
|
||||
uint8_t* chars = nullptr;
|
||||
intptr_t length = 0;
|
||||
Dart_Handle result = Dart_StringToUTF8(str, &chars, &length);
|
||||
if (Dart_IsError(result)) {
|
||||
Dart_PropagateError(result);
|
||||
return;
|
||||
}
|
||||
if (length > 0) {
|
||||
stream << std::string{reinterpret_cast<const char*>(chars),
|
||||
static_cast<size_t>(length)};
|
||||
}
|
||||
}
|
||||
|
||||
const auto log_string = stream.str();
|
||||
const char* chars = log_string.c_str();
|
||||
const size_t length = log_string.size();
|
||||
|
||||
// Log using platform specific mechanisms
|
||||
{
|
||||
#if defined(OS_ANDROID)
|
||||
// Write to the logcat on Android.
|
||||
const char* tag = Settings::Get().log_tag.c_str();
|
||||
__android_log_print(ANDROID_LOG_INFO, tag, "%.*s", (int)length, chars);
|
||||
__android_log_print(ANDROID_LOG_INFO, logger_prefix.c_str(), "%.*s",
|
||||
(int)length, chars);
|
||||
#elif defined(OS_IOS)
|
||||
// Write to syslog on iOS.
|
||||
//
|
||||
@@ -159,26 +189,22 @@ void Logger_PrintString(Dart_NativeArguments args) {
|
||||
// iOS logging APIs altogether.
|
||||
syslog(1 /* LOG_ALERT */, "%.*s", (int)length, chars);
|
||||
#else
|
||||
// On Fuchsia and in flutter_tester (on both macOS and Linux), write
|
||||
// directly to stdout.
|
||||
fwrite(chars, 1, length, stdout);
|
||||
fputs("\n", stdout);
|
||||
fflush(stdout);
|
||||
std::cout << log_string << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dart::bin::ShouldCaptureStdout()) {
|
||||
// For now we report print output on the Stdout stream.
|
||||
uint8_t newline[] = {'\n'};
|
||||
Dart_ServiceSendDataEvent("Stdout", "WriteEvent", chars, length);
|
||||
Dart_ServiceSendDataEvent("Stdout", "WriteEvent",
|
||||
reinterpret_cast<const uint8_t*>(chars), length);
|
||||
Dart_ServiceSendDataEvent("Stdout", "WriteEvent", newline, sizeof(newline));
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleMicrotask(Dart_NativeArguments args) {
|
||||
Dart_Handle closure = Dart_GetNativeArgument(args, 0);
|
||||
if (LogIfError(closure) || !Dart_IsClosure(closure))
|
||||
return;
|
||||
tonic::DartMicrotaskQueue::GetForCurrentThread()->ScheduleMicrotask(closure);
|
||||
UIDartState::Current()->ScheduleMicrotask(closure);
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/codec.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/common/task_runners.h"
|
||||
#include "flutter/glue/trace_event.h"
|
||||
#include "flutter/lib/ui/painting/frame_info.h"
|
||||
#include "flutter/lib/ui/painting/resource_context.h"
|
||||
#include "lib/fxl/functional/make_copyable.h"
|
||||
#include "lib/fxl/logging.h"
|
||||
#include "lib/tonic/dart_binding_macros.h"
|
||||
#include "lib/tonic/dart_library_natives.h"
|
||||
#include "lib/tonic/dart_state.h"
|
||||
@@ -17,6 +17,10 @@
|
||||
#include "third_party/skia/include/codec/SkCodec.h"
|
||||
#include "third_party/skia/include/core/SkPixelRef.h"
|
||||
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
|
||||
using tonic::DartInvoke;
|
||||
using tonic::DartPersistentValue;
|
||||
using tonic::ToDart;
|
||||
@@ -28,9 +32,9 @@ namespace {
|
||||
static constexpr const char* kInitCodecTraceTag = "InitCodec";
|
||||
static constexpr const char* kCodecNextFrameTraceTag = "CodecNextFrame";
|
||||
|
||||
void InvokeCodecCallback(fxl::RefPtr<Codec> codec,
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
size_t trace_id) {
|
||||
static void InvokeCodecCallback(fxl::RefPtr<Codec> codec,
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
size_t trace_id) {
|
||||
tonic::DartState* dart_state = callback->dart_state().get();
|
||||
if (!dart_state) {
|
||||
TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
|
||||
@@ -45,7 +49,9 @@ void InvokeCodecCallback(fxl::RefPtr<Codec> codec,
|
||||
TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
|
||||
}
|
||||
|
||||
sk_sp<SkImage> DecodeImage(sk_sp<SkData> buffer, size_t trace_id) {
|
||||
static sk_sp<SkImage> DecodeImage(fml::WeakPtr<GrContext> context,
|
||||
sk_sp<SkData> buffer,
|
||||
size_t trace_id) {
|
||||
TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
|
||||
TRACE_EVENT0("flutter", "DecodeImage");
|
||||
|
||||
@@ -53,13 +59,11 @@ sk_sp<SkImage> DecodeImage(sk_sp<SkData> buffer, size_t trace_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<ResourceContext> resourceContext = ResourceContext::Acquire();
|
||||
GrContext* context = resourceContext->Get();
|
||||
if (context) {
|
||||
// This indicates that we do not want a "linear blending" decode.
|
||||
sk_sp<SkColorSpace> dstColorSpace = nullptr;
|
||||
return SkImage::MakeCrossContextFromEncoded(context, std::move(buffer),
|
||||
false, dstColorSpace.get());
|
||||
return SkImage::MakeCrossContextFromEncoded(
|
||||
context.get(), std::move(buffer), false, dstColorSpace.get());
|
||||
} else {
|
||||
// Defer decoding until time of draw later on the GPU thread. Can happen
|
||||
// when GL operations are currently forbidden such as in the background
|
||||
@@ -68,7 +72,10 @@ sk_sp<SkImage> DecodeImage(sk_sp<SkData> buffer, size_t trace_id) {
|
||||
}
|
||||
}
|
||||
|
||||
fxl::RefPtr<Codec> InitCodec(sk_sp<SkData> buffer, size_t trace_id) {
|
||||
fxl::RefPtr<Codec> InitCodec(fml::WeakPtr<GrContext> context,
|
||||
sk_sp<SkData> buffer,
|
||||
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
|
||||
size_t trace_id) {
|
||||
TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
|
||||
TRACE_EVENT0("blink", "InitCodec");
|
||||
|
||||
@@ -86,27 +93,31 @@ fxl::RefPtr<Codec> InitCodec(sk_sp<SkData> buffer, size_t trace_id) {
|
||||
if (skCodec->getFrameCount() > 1) {
|
||||
return fxl::MakeRefCounted<MultiFrameCodec>(std::move(skCodec));
|
||||
}
|
||||
auto skImage = DecodeImage(buffer, trace_id);
|
||||
auto skImage = DecodeImage(context, buffer, trace_id);
|
||||
if (!skImage) {
|
||||
FXL_LOG(ERROR) << "DecodeImage failed";
|
||||
return nullptr;
|
||||
}
|
||||
auto image = CanvasImage::Create();
|
||||
image->set_image(skImage);
|
||||
image->set_image({skImage, unref_queue});
|
||||
auto frameInfo = fxl::MakeRefCounted<FrameInfo>(std::move(image), 0);
|
||||
return fxl::MakeRefCounted<SingleFrameCodec>(std::move(frameInfo));
|
||||
}
|
||||
|
||||
void InitCodecAndInvokeCodecCallback(
|
||||
fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
|
||||
fml::WeakPtr<GrContext> context,
|
||||
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
sk_sp<SkData> buffer,
|
||||
size_t trace_id) {
|
||||
auto codec = InitCodec(std::move(buffer), trace_id);
|
||||
Threads::UI()->PostTask(fxl::MakeCopyable([
|
||||
callback = std::move(callback), codec = std::move(codec), trace_id
|
||||
]() mutable {
|
||||
InvokeCodecCallback(std::move(codec), std::move(callback), trace_id);
|
||||
}));
|
||||
auto codec =
|
||||
InitCodec(context, std::move(buffer), std::move(unref_queue), trace_id);
|
||||
ui_task_runner->PostTask(
|
||||
fxl::MakeCopyable([callback = std::move(callback),
|
||||
codec = std::move(codec), trace_id]() mutable {
|
||||
InvokeCodecCallback(std::move(codec), std::move(callback), trace_id);
|
||||
}));
|
||||
}
|
||||
|
||||
void InstantiateImageCodec(Dart_NativeArguments args) {
|
||||
@@ -133,14 +144,20 @@ void InstantiateImageCodec(Dart_NativeArguments args) {
|
||||
|
||||
auto buffer = SkData::MakeWithCopy(list.data(), list.num_elements());
|
||||
|
||||
Threads::IO()->PostTask(fxl::MakeCopyable([
|
||||
callback = std::make_unique<DartPersistentValue>(
|
||||
tonic::DartState::Current(), callback_handle),
|
||||
buffer = std::move(buffer), trace_id
|
||||
]() mutable {
|
||||
InitCodecAndInvokeCodecCallback(std::move(callback), std::move(buffer),
|
||||
trace_id);
|
||||
}));
|
||||
auto dart_state = UIDartState::Current();
|
||||
|
||||
const auto& task_runners = dart_state->GetTaskRunners();
|
||||
task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
|
||||
[callback = std::make_unique<DartPersistentValue>(
|
||||
tonic::DartState::Current(), callback_handle),
|
||||
buffer = std::move(buffer), trace_id,
|
||||
ui_task_runner = task_runners.GetUITaskRunner(),
|
||||
context = dart_state->GetResourceContext(),
|
||||
queue = UIDartState::Current()->GetSkiaUnrefQueue()]() mutable {
|
||||
InitCodecAndInvokeCodecCallback(std::move(ui_task_runner), context,
|
||||
std::move(queue), std::move(callback),
|
||||
std::move(buffer), trace_id);
|
||||
}));
|
||||
}
|
||||
|
||||
bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
|
||||
@@ -213,7 +230,8 @@ MultiFrameCodec::MultiFrameCodec(std::unique_ptr<SkCodec> codec)
|
||||
nextFrameIndex_ = 0;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage() {
|
||||
sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage(
|
||||
fml::WeakPtr<GrContext> resourceContext) {
|
||||
SkBitmap& bitmap = frameBitmaps_[nextFrameIndex_];
|
||||
if (!bitmap.getPixels()) { // We haven't decoded this frame yet
|
||||
const SkImageInfo info = codec_->getInfo().makeColorType(kN32_SkColorType);
|
||||
@@ -245,15 +263,13 @@ sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage() {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ResourceContext> resourceContext = ResourceContext::Acquire();
|
||||
GrContext* context = resourceContext->Get();
|
||||
if (context) {
|
||||
if (resourceContext) {
|
||||
SkPixmap pixmap(bitmap.info(), bitmap.pixelRef()->pixels(),
|
||||
bitmap.pixelRef()->rowBytes());
|
||||
// This indicates that we do not want a "linear blending" decode.
|
||||
sk_sp<SkColorSpace> dstColorSpace = nullptr;
|
||||
return SkImage::MakeCrossContextFromPixmap(context, pixmap, false,
|
||||
dstColorSpace.get());
|
||||
return SkImage::MakeCrossContextFromPixmap(resourceContext.get(), pixmap,
|
||||
false, dstColorSpace.get());
|
||||
} else {
|
||||
// Defer decoding until time of draw later on the GPU thread. Can happen
|
||||
// when GL operations are currently forbidden such as in the background
|
||||
@@ -264,19 +280,22 @@ sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage() {
|
||||
|
||||
void MultiFrameCodec::GetNextFrameAndInvokeCallback(
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
|
||||
fml::WeakPtr<GrContext> resourceContext,
|
||||
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
|
||||
size_t trace_id) {
|
||||
fxl::RefPtr<FrameInfo> frameInfo = NULL;
|
||||
sk_sp<SkImage> skImage = GetNextFrameImage();
|
||||
sk_sp<SkImage> skImage = GetNextFrameImage(resourceContext);
|
||||
if (skImage) {
|
||||
fxl::RefPtr<CanvasImage> image = CanvasImage::Create();
|
||||
image->set_image(skImage);
|
||||
image->set_image({skImage, std::move(unref_queue)});
|
||||
frameInfo = fxl::MakeRefCounted<FrameInfo>(
|
||||
std::move(image), frameInfos_[nextFrameIndex_].fDuration);
|
||||
}
|
||||
nextFrameIndex_ = (nextFrameIndex_ + 1) % frameInfos_.size();
|
||||
|
||||
Threads::UI()->PostTask(fxl::MakeCopyable(
|
||||
[ callback = std::move(callback), frameInfo, trace_id ]() mutable {
|
||||
ui_task_runner->PostTask(fxl::MakeCopyable(
|
||||
[callback = std::move(callback), frameInfo, trace_id]() mutable {
|
||||
InvokeNextFrameCallback(frameInfo, std::move(callback), trace_id);
|
||||
}));
|
||||
|
||||
@@ -293,13 +312,20 @@ Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) {
|
||||
return ToDart("Callback must be a function");
|
||||
}
|
||||
|
||||
Threads::IO()->PostTask(fxl::MakeCopyable([
|
||||
callback = std::make_unique<DartPersistentValue>(
|
||||
tonic::DartState::Current(), callback_handle),
|
||||
this, trace_id
|
||||
]() mutable {
|
||||
GetNextFrameAndInvokeCallback(std::move(callback), trace_id);
|
||||
}));
|
||||
auto dart_state = UIDartState::Current();
|
||||
|
||||
const auto& task_runners = dart_state->GetTaskRunners();
|
||||
|
||||
task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
|
||||
[callback = std::make_unique<DartPersistentValue>(
|
||||
tonic::DartState::Current(), callback_handle),
|
||||
this, trace_id, ui_task_runner = task_runners.GetUITaskRunner(),
|
||||
queue = UIDartState::Current()->GetSkiaUnrefQueue(),
|
||||
context = dart_state->GetResourceContext()]() mutable {
|
||||
GetNextFrameAndInvokeCallback(std::move(callback),
|
||||
std::move(ui_task_runner), context,
|
||||
std::move(queue), trace_id);
|
||||
}));
|
||||
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
@@ -43,11 +43,16 @@ class MultiFrameCodec : public Codec {
|
||||
|
||||
private:
|
||||
MultiFrameCodec(std::unique_ptr<SkCodec> codec);
|
||||
|
||||
~MultiFrameCodec() {}
|
||||
|
||||
sk_sp<SkImage> GetNextFrameImage();
|
||||
sk_sp<SkImage> GetNextFrameImage(fml::WeakPtr<GrContext> resourceContext);
|
||||
|
||||
void GetNextFrameAndInvokeCallback(
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
|
||||
fml::WeakPtr<GrContext> resourceContext,
|
||||
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
|
||||
size_t trace_id);
|
||||
|
||||
const std::unique_ptr<SkCodec> codec_;
|
||||
|
||||
@@ -48,10 +48,10 @@ void CanvasGradient::initLinear(const tonic::Float32List& end_points,
|
||||
static_assert(sizeof(SkColor) == sizeof(int32_t),
|
||||
"SkColor doesn't use int32_t.");
|
||||
|
||||
set_shader(SkGradientShader::MakeLinear(
|
||||
set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeLinear(
|
||||
reinterpret_cast<const SkPoint*>(end_points.data()),
|
||||
reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
|
||||
colors.num_elements(), tile_mode));
|
||||
colors.num_elements(), tile_mode)));
|
||||
}
|
||||
|
||||
void CanvasGradient::initRadial(double center_x,
|
||||
@@ -73,14 +73,14 @@ void CanvasGradient::initRadial(double center_x,
|
||||
sk_matrix = ToSkMatrix(matrix4);
|
||||
}
|
||||
|
||||
set_shader(SkGradientShader::MakeRadial(
|
||||
set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeRadial(
|
||||
SkPoint::Make(center_x, center_y), radius,
|
||||
reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
|
||||
colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr));
|
||||
colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr)));
|
||||
}
|
||||
|
||||
CanvasGradient::CanvasGradient() : Shader(nullptr) {}
|
||||
CanvasGradient::CanvasGradient() = default;
|
||||
|
||||
CanvasGradient::~CanvasGradient() {}
|
||||
CanvasGradient::~CanvasGradient() = default;
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/image.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/lib/ui/painting/image_encoding.h"
|
||||
#include "flutter/lib/ui/painting/utils.h"
|
||||
#include "lib/tonic/converter/dart_converter.h"
|
||||
#include "lib/tonic/dart_args.h"
|
||||
#include "lib/tonic/dart_binding_macros.h"
|
||||
@@ -30,13 +28,9 @@ void CanvasImage::RegisterNatives(tonic::DartLibraryNatives* natives) {
|
||||
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
|
||||
}
|
||||
|
||||
CanvasImage::CanvasImage() {}
|
||||
CanvasImage::CanvasImage() = default;
|
||||
|
||||
CanvasImage::~CanvasImage() {
|
||||
// Skia objects must be deleted on the IO thread so that any associated GL
|
||||
// objects will be cleaned up through the IO thread's GL context.
|
||||
SkiaUnrefOnIOThread(&image_);
|
||||
}
|
||||
CanvasImage::~CanvasImage() = default;
|
||||
|
||||
Dart_Handle CanvasImage::toByteData(int format,
|
||||
int quality,
|
||||
@@ -49,8 +43,8 @@ void CanvasImage::dispose() {
|
||||
}
|
||||
|
||||
size_t CanvasImage::GetAllocationSize() {
|
||||
if (image_) {
|
||||
return image_->width() * image_->height() * 4;
|
||||
if (auto image = image_.get()) {
|
||||
return image->width() * image->height() * 4;
|
||||
} else {
|
||||
return sizeof(CanvasImage);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef FLUTTER_LIB_UI_PAINTING_IMAGE_H_
|
||||
#define FLUTTER_LIB_UI_PAINTING_IMAGE_H_
|
||||
|
||||
#include "flutter/flow/skia_gpu_object.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/tonic/dart_wrappable.h"
|
||||
#include "third_party/skia/include/core/SkImage.h"
|
||||
|
||||
@@ -25,13 +27,18 @@ class CanvasImage final : public fxl::RefCountedThreadSafe<CanvasImage>,
|
||||
return fxl::MakeRefCounted<CanvasImage>();
|
||||
}
|
||||
|
||||
int width() { return image_->width(); }
|
||||
int height() { return image_->height(); }
|
||||
int width() { return image_.get()->width(); }
|
||||
|
||||
int height() { return image_.get()->height(); }
|
||||
|
||||
Dart_Handle toByteData(int format, int quality, Dart_Handle callback);
|
||||
|
||||
void dispose();
|
||||
|
||||
const sk_sp<SkImage>& image() const { return image_; }
|
||||
void set_image(sk_sp<SkImage> image) { image_ = std::move(image); }
|
||||
sk_sp<SkImage> image() const { return image_.get(); }
|
||||
void set_image(flow::SkiaGPUObject<SkImage> image) {
|
||||
image_ = std::move(image);
|
||||
}
|
||||
|
||||
virtual size_t GetAllocationSize() override;
|
||||
|
||||
@@ -40,7 +47,7 @@ class CanvasImage final : public fxl::RefCountedThreadSafe<CanvasImage>,
|
||||
private:
|
||||
CanvasImage();
|
||||
|
||||
sk_sp<SkImage> image_;
|
||||
flow::SkiaGPUObject<SkImage> image_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/image_encoding.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/common/task_runners.h"
|
||||
#include "flutter/lib/ui/painting/image.h"
|
||||
#include "flutter/lib/ui/painting/resource_context.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/fxl/build_config.h"
|
||||
#include "lib/fxl/functional/make_copyable.h"
|
||||
#include "lib/tonic/dart_persistent_value.h"
|
||||
#include "lib/tonic/dart_state.h"
|
||||
#include "lib/tonic/logging/dart_invoke.h"
|
||||
#include "lib/tonic/typed_data/uint8_list.h"
|
||||
#include "third_party/skia/include/core/SkEncodedImageFormat.h"
|
||||
@@ -52,10 +54,11 @@ void EncodeImageAndInvokeDataCallback(
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
sk_sp<SkImage> image,
|
||||
SkEncodedImageFormat format,
|
||||
int quality) {
|
||||
int quality,
|
||||
fxl::RefPtr<fxl::TaskRunner> ui_task_runner) {
|
||||
sk_sp<SkData> encoded = EncodeImage(std::move(image), format, quality);
|
||||
|
||||
Threads::UI()->PostTask(
|
||||
ui_task_runner->PostTask(
|
||||
fxl::MakeCopyable([callback = std::move(callback), encoded]() mutable {
|
||||
InvokeDataCallback(std::move(callback), std::move(encoded));
|
||||
}));
|
||||
@@ -101,10 +104,14 @@ Dart_Handle EncodeImage(CanvasImage* canvas_image,
|
||||
tonic::DartState::Current(), callback_handle);
|
||||
sk_sp<SkImage> image = canvas_image->image();
|
||||
|
||||
Threads::IO()->PostTask(fxl::MakeCopyable(
|
||||
[callback = std::move(callback), image, image_format, quality]() mutable {
|
||||
const auto& task_runners = UIDartState::Current()->GetTaskRunners();
|
||||
|
||||
task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
|
||||
[callback = std::move(callback), image, image_format, quality,
|
||||
ui_task_runner = task_runners.GetUITaskRunner()]() mutable {
|
||||
EncodeImageAndInvokeDataCallback(std::move(callback), std::move(image),
|
||||
image_format, quality);
|
||||
image_format, quality,
|
||||
std::move(ui_task_runner));
|
||||
}));
|
||||
|
||||
return Dart_Null();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/image_shader.h"
|
||||
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/tonic/converter/dart_converter.h"
|
||||
#include "lib/tonic/dart_args.h"
|
||||
#include "lib/tonic/dart_binding_macros.h"
|
||||
@@ -37,15 +38,17 @@ void ImageShader::initWithImage(CanvasImage* image,
|
||||
SkShader::TileMode tmx,
|
||||
SkShader::TileMode tmy,
|
||||
const tonic::Float64List& matrix4) {
|
||||
if (!image)
|
||||
if (!image) {
|
||||
Dart_ThrowException(
|
||||
ToDart("ImageShader constructor called with non-genuine Image."));
|
||||
}
|
||||
SkMatrix sk_matrix = ToSkMatrix(matrix4);
|
||||
set_shader(image->image()->makeShader(tmx, tmy, &sk_matrix));
|
||||
set_shader(UIDartState::CreateGPUObject(
|
||||
image->image()->makeShader(tmx, tmy, &sk_matrix)));
|
||||
}
|
||||
|
||||
ImageShader::ImageShader() : Shader(nullptr) {}
|
||||
ImageShader::ImageShader() = default;
|
||||
|
||||
ImageShader::~ImageShader() {}
|
||||
ImageShader::~ImageShader() = default;
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/picture.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/lib/ui/painting/canvas.h"
|
||||
#include "flutter/lib/ui/painting/utils.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/tonic/converter/dart_converter.h"
|
||||
#include "lib/tonic/dart_args.h"
|
||||
#include "lib/tonic/dart_binding_macros.h"
|
||||
@@ -23,24 +22,20 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, Picture);
|
||||
|
||||
DART_BIND_ALL(Picture, FOR_EACH_BINDING)
|
||||
|
||||
fxl::RefPtr<Picture> Picture::Create(sk_sp<SkPicture> picture) {
|
||||
fxl::RefPtr<Picture> Picture::Create(flow::SkiaGPUObject<SkPicture> picture) {
|
||||
return fxl::MakeRefCounted<Picture>(std::move(picture));
|
||||
}
|
||||
|
||||
Picture::Picture(sk_sp<SkPicture> picture) : picture_(std::move(picture)) {}
|
||||
Picture::Picture(flow::SkiaGPUObject<SkPicture> picture)
|
||||
: picture_(std::move(picture)) {}
|
||||
|
||||
Picture::~Picture() {
|
||||
// Skia objects must be deleted on the IO thread so that any associated GL
|
||||
// objects will be cleaned up through the IO thread's GL context.
|
||||
SkiaUnrefOnIOThread(&picture_);
|
||||
}
|
||||
Picture::~Picture() = default;
|
||||
|
||||
fxl::RefPtr<CanvasImage> Picture::toImage(int width, int height) {
|
||||
fxl::RefPtr<CanvasImage> image = CanvasImage::Create();
|
||||
// TODO(abarth): We should pass in an SkColorSpace at some point.
|
||||
image->set_image(SkImage::MakeFromPicture(
|
||||
picture_, SkISize::Make(width, height), nullptr, nullptr,
|
||||
SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()));
|
||||
image->set_image(UIDartState::CreateGPUObject(SkImage::MakeFromPicture(
|
||||
picture_.get(), SkISize::Make(width, height), nullptr, nullptr,
|
||||
SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB())));
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -49,8 +44,8 @@ void Picture::dispose() {
|
||||
}
|
||||
|
||||
size_t Picture::GetAllocationSize() {
|
||||
if (picture_) {
|
||||
return picture_->approximateBytesUsed();
|
||||
if (auto picture = picture_.get()) {
|
||||
return picture->approximateBytesUsed();
|
||||
} else {
|
||||
return sizeof(Picture);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef FLUTTER_LIB_UI_PAINTING_PICTURE_H_
|
||||
#define FLUTTER_LIB_UI_PAINTING_PICTURE_H_
|
||||
|
||||
#include "flutter/flow/skia_gpu_object.h"
|
||||
#include "flutter/lib/ui/painting/image.h"
|
||||
#include "lib/tonic/dart_wrappable.h"
|
||||
#include "third_party/skia/include/core/SkPicture.h"
|
||||
@@ -23,9 +24,9 @@ class Picture : public fxl::RefCountedThreadSafe<Picture>,
|
||||
|
||||
public:
|
||||
~Picture() override;
|
||||
static fxl::RefPtr<Picture> Create(sk_sp<SkPicture> picture);
|
||||
static fxl::RefPtr<Picture> Create(flow::SkiaGPUObject<SkPicture> picture);
|
||||
|
||||
const sk_sp<SkPicture>& picture() const { return picture_; }
|
||||
sk_sp<SkPicture> picture() const { return picture_.get(); }
|
||||
|
||||
fxl::RefPtr<CanvasImage> toImage(int width, int height);
|
||||
|
||||
@@ -36,9 +37,9 @@ class Picture : public fxl::RefCountedThreadSafe<Picture>,
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
private:
|
||||
explicit Picture(sk_sp<SkPicture> picture);
|
||||
explicit Picture(flow::SkiaGPUObject<SkPicture> picture);
|
||||
|
||||
sk_sp<SkPicture> picture_;
|
||||
flow::SkiaGPUObject<SkPicture> picture_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -50,8 +50,9 @@ SkCanvas* PictureRecorder::BeginRecording(SkRect bounds) {
|
||||
fxl::RefPtr<Picture> PictureRecorder::endRecording() {
|
||||
if (!isRecording())
|
||||
return nullptr;
|
||||
fxl::RefPtr<Picture> picture =
|
||||
Picture::Create(picture_recorder_.finishRecordingAsPicture());
|
||||
|
||||
fxl::RefPtr<Picture> picture = Picture::Create(UIDartState::CreateGPUObject(
|
||||
picture_recorder_.finishRecordingAsPicture()));
|
||||
canvas_->Clear();
|
||||
canvas_->ClearDartWrapper();
|
||||
canvas_ = nullptr;
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/lib/ui/painting/resource_context.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "lib/fxl/logging.h"
|
||||
|
||||
namespace blink {
|
||||
namespace {
|
||||
|
||||
static GrContext* g_context = nullptr;
|
||||
static std::mutex g_mutex;
|
||||
static volatile bool g_freeze = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
ResourceContext::ResourceContext() {
|
||||
g_mutex.lock();
|
||||
}
|
||||
|
||||
ResourceContext::~ResourceContext() {
|
||||
g_mutex.unlock();
|
||||
}
|
||||
|
||||
void ResourceContext::Set(sk_sp<GrContext> context) {
|
||||
FXL_DCHECK(!g_context);
|
||||
g_context = context.release();
|
||||
}
|
||||
|
||||
GrContext* ResourceContext::Get() {
|
||||
return g_freeze ? nullptr : g_context;
|
||||
}
|
||||
|
||||
std::unique_ptr<ResourceContext> ResourceContext::Acquire() {
|
||||
return std::make_unique<ResourceContext>();
|
||||
}
|
||||
|
||||
void ResourceContext::Freeze() {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
g_freeze = true;
|
||||
}
|
||||
|
||||
void ResourceContext::Unfreeze() {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
g_freeze = false;
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_LIB_UI_PAINTING_RESOURCE_CONTEXT_H_
|
||||
#define FLUTTER_LIB_UI_PAINTING_RESOURCE_CONTEXT_H_
|
||||
|
||||
#include "lib/fxl/macros.h"
|
||||
#include "third_party/skia/include/gpu/GrContext.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class ResourceContext {
|
||||
public:
|
||||
/**
|
||||
* Globally set the GrContext singleton instance.
|
||||
*/
|
||||
static void Set(sk_sp<GrContext> context);
|
||||
|
||||
/**
|
||||
* Acquire a GrContext wrapping ResourceContext that's also an exclusive mutex
|
||||
* on GrContext operations.
|
||||
*
|
||||
* Destructing the ResourceContext frees the mutex.
|
||||
*/
|
||||
static std::unique_ptr<ResourceContext> Acquire();
|
||||
|
||||
/**
|
||||
* Synchronously signal a freeze on GrContext operations.
|
||||
*
|
||||
* ResourceContext instances will return nullptr on GrContext Get until
|
||||
* unfrozen.
|
||||
*/
|
||||
static void Freeze();
|
||||
|
||||
/**
|
||||
* Synchronously unfreeze GrContext operations.
|
||||
*
|
||||
* ResourceContext instances will continue to return the global GrContext
|
||||
* instance on Get.
|
||||
*/
|
||||
static void Unfreeze();
|
||||
|
||||
ResourceContext();
|
||||
~ResourceContext();
|
||||
|
||||
/**
|
||||
* Returns global GrContext instance. May return null when operations are
|
||||
* frozen.
|
||||
*
|
||||
* Happens on iOS when background operations on GrContext are forbidden.
|
||||
*/
|
||||
GrContext* Get();
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(ResourceContext);
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif // FLUTTER_LIB_UI_PAINTING_RESOURCE_CONTEXT_H_
|
||||
@@ -4,19 +4,15 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/shader.h"
|
||||
|
||||
#include "flutter/common/threads.h"
|
||||
#include "flutter/lib/ui/painting/utils.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
IMPLEMENT_WRAPPERTYPEINFO(ui, Shader);
|
||||
|
||||
Shader::Shader(sk_sp<SkShader> shader) : shader_(shader) {}
|
||||
Shader::Shader(flow::SkiaGPUObject<SkShader> shader)
|
||||
: shader_(std::move(shader)) {}
|
||||
|
||||
Shader::~Shader() {
|
||||
// Skia objects must be deleted on the IO thread so that any associated GL
|
||||
// objects will be cleaned up through the IO thread's GL context.
|
||||
SkiaUnrefOnIOThread(&shader_);
|
||||
}
|
||||
Shader::~Shader() = default;
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef FLUTTER_LIB_UI_PAINTING_SHADER_H_
|
||||
#define FLUTTER_LIB_UI_PAINTING_SHADER_H_
|
||||
|
||||
#include "flutter/flow/skia_gpu_object.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "lib/tonic/dart_wrappable.h"
|
||||
#include "third_party/skia/include/core/SkShader.h"
|
||||
|
||||
@@ -18,14 +20,17 @@ class Shader : public fxl::RefCountedThreadSafe<Shader>,
|
||||
public:
|
||||
~Shader() override;
|
||||
|
||||
const sk_sp<SkShader>& shader() { return shader_; }
|
||||
void set_shader(sk_sp<SkShader> shader) { shader_ = std::move(shader); }
|
||||
sk_sp<SkShader> shader() { return shader_.get(); }
|
||||
|
||||
void set_shader(flow::SkiaGPUObject<SkShader> shader) {
|
||||
shader_ = std::move(shader);
|
||||
}
|
||||
|
||||
protected:
|
||||
Shader(sk_sp<SkShader> shader);
|
||||
Shader(flow::SkiaGPUObject<SkShader> shader = {});
|
||||
|
||||
private:
|
||||
sk_sp<SkShader> shader_;
|
||||
flow::SkiaGPUObject<SkShader> shader_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user