Re-land "Support multiple shells in a single process. (#4932)" (flutter/engine#4977)

This reverts commit a1befb4f30.
This commit is contained in:
Chinmay Garde
2018-04-11 15:41:23 -07:00
committed by GitHub
parent e4c501ce80
commit e27940623b
296 changed files with 10215 additions and 8918 deletions

2
DEPS
View File

@@ -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
#

View File

@@ -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") {

View File

@@ -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" ]
}

View 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

View 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_

View File

@@ -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

View 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_

View File

@@ -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

View File

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

View File

@@ -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

View File

@@ -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_

View File

@@ -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;

View File

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

View File

@@ -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",
]

View File

@@ -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

View File

@@ -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

View 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

View 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_

View File

@@ -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

View File

@@ -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_

View File

@@ -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",
]
}

View File

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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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:

View File

@@ -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);

View File

@@ -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));

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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())

View File

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

View File

@@ -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

View File

@@ -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:

View File

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

View File

@@ -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_;

View File

@@ -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_

View File

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

View File

@@ -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);

View File

@@ -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_;
};

View File

@@ -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);

View 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

View 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_

View File

@@ -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

View File

@@ -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:

View File

@@ -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",
]
}
}

View 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_

View File

@@ -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;

View 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_

View 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

View File

@@ -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_

View 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_

View File

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

View File

@@ -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() {

View File

@@ -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.

View File

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

View File

@@ -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_;

View File

@@ -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);

View 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_

View 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

View File

@@ -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

View File

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

View File

@@ -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;

View 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

View File

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

View 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

View File

@@ -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;

View 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.
#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

View 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

View File

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

View 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

View 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_

View File

@@ -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_

View File

@@ -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

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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);

View 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

View 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_

View 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_

View File

@@ -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") {

View File

@@ -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",

View File

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

View File

@@ -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) {

View File

@@ -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

View File

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

View File

@@ -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_;

View File

@@ -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

View File

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

View File

@@ -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

View File

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

View File

@@ -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

View File

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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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