From 7bb229d7d58b45cae9ee672c1fcfe0baf0ffcd29 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Tue, 20 Mar 2018 18:30:12 -0700 Subject: [PATCH] Updates in flutter/lib/ui for the shell refactor (Patch 7) This changes is part of a large patch for easier review. Try the whole patch in one go by checking out https://github.com/chinmaygarde/flutter_engine/tree/shell directly. This patch contains the following changes: * Fairly mechanical removal of singltons in favor of accessing the same resource via the Dart state associated with the isolate. * Logs now respect the log_tag specified in settings on all platforms (previously only supported on Android). * Fix thread safety issue in image decoding during shell shell shutdown. --- lib/ui/BUILD.gn | 11 +- lib/ui/compositing/scene_builder.cc | 9 +- lib/ui/compositing/scene_host.cc | 6 +- lib/ui/dart_runtime_hooks.cc | 62 +++++++--- lib/ui/painting/codec.cc | 109 +++++++++++------- lib/ui/painting/codec.h | 7 +- lib/ui/painting/gradient.cc | 12 +- lib/ui/painting/image.cc | 14 +-- lib/ui/painting/image.h | 15 ++- lib/ui/painting/image_shader.cc | 11 +- lib/ui/painting/picture.cc | 25 ++-- lib/ui/painting/picture.h | 9 +- lib/ui/painting/picture_recorder.cc | 5 +- lib/ui/painting/resource_context.cc | 51 -------- lib/ui/painting/resource_context.h | 60 ---------- lib/ui/painting/shader.cc | 12 +- lib/ui/painting/shader.h | 13 ++- lib/ui/painting/utils.cc | 46 -------- lib/ui/painting/utils.h | 38 ------ lib/ui/text/font_collection.cc | 14 +-- lib/ui/text/font_collection.h | 7 +- lib/ui/text/paragraph.cc | 5 +- lib/ui/text/paragraph.h | 5 + lib/ui/text/paragraph_builder.cc | 24 ++-- lib/ui/text/paragraph_builder.h | 8 +- lib/ui/text/paragraph_impl_blink.cc | 4 +- lib/ui/text/paragraph_impl_blink.h | 5 + lib/ui/text/paragraph_impl_txt.cc | 2 +- lib/ui/ui_dart_state.cc | 93 +++++++++++---- lib/ui/ui_dart_state.h | 101 +++++++++++----- .../window/platform_message_response_dart.cc | 14 ++- .../window/platform_message_response_dart.h | 6 +- lib/ui/window/viewport_metrics.h | 19 +++ lib/ui/window/window.cc | 5 +- lib/ui/window/window.h | 5 +- 35 files changed, 412 insertions(+), 420 deletions(-) delete mode 100644 lib/ui/painting/resource_context.cc delete mode 100644 lib/ui/painting/resource_context.h delete mode 100644 lib/ui/painting/utils.cc delete mode 100644 lib/ui/painting/utils.h diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 2862a9b68cf96..eb3982514b2a1 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -38,14 +38,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", @@ -85,19 +81,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", diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 006826abbfdf6..60b911cb4ddec 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -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 ); } diff --git a/lib/ui/compositing/scene_host.cc b/lib/ui/compositing/scene_host.cc index c0e4c5332580a..f5e0cfb3547d8 100644 --- a/lib/ui/compositing/scene_host.cc +++ b/lib/ui/compositing/scene_host.cc @@ -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::create( } SceneHost::SceneHost(fxl::RefPtr export_token_handle) { - export_node_holder_ = - fxl::MakeRefCounted(export_token_handle); + export_node_holder_ = fxl::MakeRefCounted( + blink::UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner(), + export_token_handle); } #else fxl::RefPtr SceneHost::create(Dart_Handle export_token_handle) { diff --git a/lib/ui/dart_runtime_hooks.cc b/lib/ui/dart_runtime_hooks.cc index edd51245b05db..32a244c9cb67d 100644 --- a/lib/ui/dart_runtime_hooks.cc +++ b/lib/ui/dart_runtime_hooks.cc @@ -8,7 +8,11 @@ #include #include +#include +#include + #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(chars), + static_cast(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(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 diff --git a/lib/ui/painting/codec.cc b/lib/ui/painting/codec.cc index 3e47ba86d50a5..038d70bd5a3d5 100644 --- a/lib/ui/painting/codec.cc +++ b/lib/ui/painting/codec.cc @@ -4,10 +4,9 @@ #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/tonic/dart_binding_macros.h" #include "lib/tonic/dart_library_natives.h" @@ -28,9 +27,9 @@ namespace { static constexpr const char* kInitCodecTraceTag = "InitCodec"; static constexpr const char* kCodecNextFrameTraceTag = "CodecNextFrame"; -void InvokeCodecCallback(fxl::RefPtr codec, - std::unique_ptr callback, - size_t trace_id) { +static void InvokeCodecCallback(fxl::RefPtr codec, + std::unique_ptr 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 +44,9 @@ void InvokeCodecCallback(fxl::RefPtr codec, TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id); } -sk_sp DecodeImage(sk_sp buffer, size_t trace_id) { +static sk_sp DecodeImage(fml::WeakPtr context, + sk_sp buffer, + size_t trace_id) { TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id); TRACE_EVENT0("flutter", "DecodeImage"); @@ -53,13 +54,11 @@ sk_sp DecodeImage(sk_sp buffer, size_t trace_id) { return nullptr; } - std::unique_ptr resourceContext = ResourceContext::Acquire(); - GrContext* context = resourceContext->Get(); if (context) { // This indicates that we do not want a "linear blending" decode. sk_sp 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 +67,10 @@ sk_sp DecodeImage(sk_sp buffer, size_t trace_id) { } } -fxl::RefPtr InitCodec(sk_sp buffer, size_t trace_id) { +fxl::RefPtr InitCodec(fml::WeakPtr context, + sk_sp buffer, + fxl::RefPtr unref_queue, + size_t trace_id) { TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id); TRACE_EVENT0("blink", "InitCodec"); @@ -86,27 +88,31 @@ fxl::RefPtr InitCodec(sk_sp buffer, size_t trace_id) { if (skCodec->getFrameCount() > 1) { return fxl::MakeRefCounted(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(std::move(image), 0); return fxl::MakeRefCounted(std::move(frameInfo)); } void InitCodecAndInvokeCodecCallback( + fxl::RefPtr ui_task_runner, + fml::WeakPtr context, + fxl::RefPtr unref_queue, std::unique_ptr callback, sk_sp 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 +139,20 @@ void InstantiateImageCodec(Dart_NativeArguments args) { auto buffer = SkData::MakeWithCopy(list.data(), list.num_elements()); - Threads::IO()->PostTask(fxl::MakeCopyable([ - callback = std::make_unique( - 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( + 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 +225,8 @@ MultiFrameCodec::MultiFrameCodec(std::unique_ptr codec) nextFrameIndex_ = 0; } -sk_sp MultiFrameCodec::GetNextFrameImage() { +sk_sp MultiFrameCodec::GetNextFrameImage( + fml::WeakPtr 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 +258,13 @@ sk_sp MultiFrameCodec::GetNextFrameImage() { } } - std::unique_ptr 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 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 +275,22 @@ sk_sp MultiFrameCodec::GetNextFrameImage() { void MultiFrameCodec::GetNextFrameAndInvokeCallback( std::unique_ptr callback, + fxl::RefPtr ui_task_runner, + fml::WeakPtr resourceContext, + fxl::RefPtr unref_queue, size_t trace_id) { fxl::RefPtr frameInfo = NULL; - sk_sp skImage = GetNextFrameImage(); + sk_sp skImage = GetNextFrameImage(resourceContext); if (skImage) { fxl::RefPtr image = CanvasImage::Create(); - image->set_image(skImage); + image->set_image({skImage, std::move(unref_queue)}); frameInfo = fxl::MakeRefCounted( 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 +307,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( - 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( + 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(); } diff --git a/lib/ui/painting/codec.h b/lib/ui/painting/codec.h index 98e5bc56df375..9fdce1a8c1a33 100644 --- a/lib/ui/painting/codec.h +++ b/lib/ui/painting/codec.h @@ -43,11 +43,16 @@ class MultiFrameCodec : public Codec { private: MultiFrameCodec(std::unique_ptr codec); + ~MultiFrameCodec() {} - sk_sp GetNextFrameImage(); + sk_sp GetNextFrameImage(fml::WeakPtr resourceContext); + void GetNextFrameAndInvokeCallback( std::unique_ptr callback, + fxl::RefPtr ui_task_runner, + fml::WeakPtr resourceContext, + fxl::RefPtr unref_queue, size_t trace_id); const std::unique_ptr codec_; diff --git a/lib/ui/painting/gradient.cc b/lib/ui/painting/gradient.cc index 7035df81b6804..b52301c7bec96 100644 --- a/lib/ui/painting/gradient.cc +++ b/lib/ui/painting/gradient.cc @@ -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(end_points.data()), reinterpret_cast(colors.data()), color_stops.data(), - colors.num_elements(), tile_mode)); + colors.num_elements(), tile_mode))); } void CanvasGradient::initRadial(double center_x, @@ -66,14 +66,14 @@ void CanvasGradient::initRadial(double center_x, static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor doesn't use int32_t."); - set_shader(SkGradientShader::MakeRadial( + set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeRadial( SkPoint::Make(center_x, center_y), radius, reinterpret_cast(colors.data()), color_stops.data(), - colors.num_elements(), tile_mode)); + colors.num_elements(), tile_mode))); } -CanvasGradient::CanvasGradient() : Shader(nullptr) {} +CanvasGradient::CanvasGradient() = default; -CanvasGradient::~CanvasGradient() {} +CanvasGradient::~CanvasGradient() = default; } // namespace blink diff --git a/lib/ui/painting/image.cc b/lib/ui/painting/image.cc index 0b0127cd0c6c2..0f43ce085c862 100644 --- a/lib/ui/painting/image.cc +++ b/lib/ui/painting/image.cc @@ -4,8 +4,6 @@ #include "flutter/lib/ui/painting/image.h" -#include "flutter/common/threads.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" @@ -28,21 +26,17 @@ 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; void CanvasImage::dispose() { ClearDartWrapper(); } 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); } diff --git a/lib/ui/painting/image.h b/lib/ui/painting/image.h index 8ad11660721f0..4024b8f125a8e 100644 --- a/lib/ui/painting/image.h +++ b/lib/ui/painting/image.h @@ -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,12 +27,15 @@ class CanvasImage final : public fxl::RefCountedThreadSafe, return fxl::MakeRefCounted(); } - int width() { return image_->width(); } - int height() { return image_->height(); } + int width() { return image_.get()->width(); } + int height() { return image_.get()->height(); } + void dispose(); - const sk_sp& image() const { return image_; } - void set_image(sk_sp image) { image_ = std::move(image); } + sk_sp image() const { return image_.get(); } + void set_image(flow::SkiaGPUObject image) { + image_ = std::move(image); + } virtual size_t GetAllocationSize() override; @@ -39,7 +44,7 @@ class CanvasImage final : public fxl::RefCountedThreadSafe, private: CanvasImage(); - sk_sp image_; + flow::SkiaGPUObject image_; }; } // namespace blink diff --git a/lib/ui/painting/image_shader.cc b/lib/ui/painting/image_shader.cc index 0fabd134c737c..a4ddbba0ea24b 100644 --- a/lib/ui/painting/image_shader.cc +++ b/lib/ui/painting/image_shader.cc @@ -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 diff --git a/lib/ui/painting/picture.cc b/lib/ui/painting/picture.cc index 89ddbf5f41bb0..34f92b8c315fd 100644 --- a/lib/ui/painting/picture.cc +++ b/lib/ui/painting/picture.cc @@ -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::Create(sk_sp picture) { +fxl::RefPtr Picture::Create(flow::SkiaGPUObject picture) { return fxl::MakeRefCounted(std::move(picture)); } -Picture::Picture(sk_sp picture) : picture_(std::move(picture)) {} +Picture::Picture(flow::SkiaGPUObject 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 Picture::toImage(int width, int height) { fxl::RefPtr 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); } diff --git a/lib/ui/painting/picture.h b/lib/ui/painting/picture.h index 4a26d01c08374..d916086b02f02 100644 --- a/lib/ui/painting/picture.h +++ b/lib/ui/painting/picture.h @@ -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, public: ~Picture() override; - static fxl::RefPtr Create(sk_sp picture); + static fxl::RefPtr Create(flow::SkiaGPUObject picture); - const sk_sp& picture() const { return picture_; } + sk_sp picture() const { return picture_.get(); } fxl::RefPtr toImage(int width, int height); @@ -36,9 +37,9 @@ class Picture : public fxl::RefCountedThreadSafe, static void RegisterNatives(tonic::DartLibraryNatives* natives); private: - explicit Picture(sk_sp picture); + explicit Picture(flow::SkiaGPUObject picture); - sk_sp picture_; + flow::SkiaGPUObject picture_; }; } // namespace blink diff --git a/lib/ui/painting/picture_recorder.cc b/lib/ui/painting/picture_recorder.cc index adc73c0043920..e870e400a7230 100644 --- a/lib/ui/painting/picture_recorder.cc +++ b/lib/ui/painting/picture_recorder.cc @@ -50,8 +50,9 @@ SkCanvas* PictureRecorder::BeginRecording(SkRect bounds) { fxl::RefPtr PictureRecorder::endRecording() { if (!isRecording()) return nullptr; - fxl::RefPtr picture = - Picture::Create(picture_recorder_.finishRecordingAsPicture()); + + fxl::RefPtr picture = Picture::Create(UIDartState::CreateGPUObject( + picture_recorder_.finishRecordingAsPicture())); canvas_->Clear(); canvas_->ClearDartWrapper(); canvas_ = nullptr; diff --git a/lib/ui/painting/resource_context.cc b/lib/ui/painting/resource_context.cc deleted file mode 100644 index 1b9f71548c15f..0000000000000 --- a/lib/ui/painting/resource_context.cc +++ /dev/null @@ -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 - -#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 context) { - FXL_DCHECK(!g_context); - g_context = context.release(); -} - -GrContext* ResourceContext::Get() { - return g_freeze ? nullptr : g_context; -} - -std::unique_ptr ResourceContext::Acquire() { - return std::make_unique(); -} - -void ResourceContext::Freeze() { - std::lock_guard lock(g_mutex); - g_freeze = true; -} - -void ResourceContext::Unfreeze() { - std::lock_guard lock(g_mutex); - g_freeze = false; -} - -} // namespace blink diff --git a/lib/ui/painting/resource_context.h b/lib/ui/painting/resource_context.h deleted file mode 100644 index 627b2053c2df9..0000000000000 --- a/lib/ui/painting/resource_context.h +++ /dev/null @@ -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 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 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_ diff --git a/lib/ui/painting/shader.cc b/lib/ui/painting/shader.cc index d7d8ccf20aefc..7999b84dfcc29 100644 --- a/lib/ui/painting/shader.cc +++ b/lib/ui/painting/shader.cc @@ -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 shader) : shader_(shader) {} +Shader::Shader(flow::SkiaGPUObject 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 diff --git a/lib/ui/painting/shader.h b/lib/ui/painting/shader.h index 9c0f3c601db56..205197250eb84 100644 --- a/lib/ui/painting/shader.h +++ b/lib/ui/painting/shader.h @@ -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, public: ~Shader() override; - const sk_sp& shader() { return shader_; } - void set_shader(sk_sp shader) { shader_ = std::move(shader); } + sk_sp shader() { return shader_.get(); } + + void set_shader(flow::SkiaGPUObject shader) { + shader_ = std::move(shader); + } protected: - Shader(sk_sp shader); + Shader(flow::SkiaGPUObject shader = {}); private: - sk_sp shader_; + flow::SkiaGPUObject shader_; }; } // namespace blink diff --git a/lib/ui/painting/utils.cc b/lib/ui/painting/utils.cc deleted file mode 100644 index b3f87135ac0a8..0000000000000 --- a/lib/ui/painting/utils.cc +++ /dev/null @@ -1,46 +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. - -#include "flutter/lib/ui/painting/utils.h" -#include "flutter/common/threads.h" - -namespace blink { - -namespace { - -constexpr fxl::TimeDelta kDrainDelay = fxl::TimeDelta::FromMilliseconds(250); - -} // anonymous namespace - -SkiaUnrefQueue::SkiaUnrefQueue() : drain_pending_(false) {} - -SkiaUnrefQueue SkiaUnrefQueue::instance_; - -SkiaUnrefQueue& SkiaUnrefQueue::Get() { - return instance_; -} - -void SkiaUnrefQueue::Unref(SkRefCnt* object) { - std::lock_guard lock(mutex_); - objects_.push_back(object); - if (!drain_pending_) { - drain_pending_ = true; - Threads::IO()->PostDelayedTask([this] { Drain(); }, kDrainDelay); - } -} - -void SkiaUnrefQueue::Drain() { - std::deque skia_objects; - { - std::lock_guard lock(mutex_); - objects_.swap(skia_objects); - drain_pending_ = false; - } - - for (SkRefCnt* skia_object : skia_objects) { - skia_object->unref(); - } -} - -} // namespace blink diff --git a/lib/ui/painting/utils.h b/lib/ui/painting/utils.h deleted file mode 100644 index 02782c67962bc..0000000000000 --- a/lib/ui/painting/utils.h +++ /dev/null @@ -1,38 +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 "third_party/skia/include/core/SkRefCnt.h" - -#include -#include - -namespace blink { - -// A queue that holds Skia objects that must be destructed on the IO thread. -class SkiaUnrefQueue { - public: - static SkiaUnrefQueue& Get(); - - void Unref(SkRefCnt* object); - - private: - SkiaUnrefQueue(); - void Drain(); - - static SkiaUnrefQueue instance_; - - std::mutex mutex_; - std::deque objects_; - bool drain_pending_; -}; - -template -void SkiaUnrefOnIOThread(sk_sp* sp) { - T* object = sp->release(); - if (object) { - SkiaUnrefQueue::Get().Unref(object); - } -} - -} // namespace blink diff --git a/lib/ui/text/font_collection.cc b/lib/ui/text/font_collection.cc index d6407f9ed42e1..248468cc9701d 100644 --- a/lib/ui/text/font_collection.cc +++ b/lib/ui/text/font_collection.cc @@ -34,15 +34,9 @@ std::shared_ptr FontCollection::GetFontCollection() const { return collection_; } -void FontCollection::RegisterFontsFromAssetProvider( - fxl::RefPtr asset_provider) { - - if (!asset_provider){ - return; - } - +void FontCollection::RegisterFonts(const AssetManager& asset_manager) { std::vector manifest_data; - if (!asset_provider->GetAsBuffer("FontManifest.json", &manifest_data)) { + if (!asset_manager.GetAsBuffer("FontManifest.json", &manifest_data)) { FXL_DLOG(WARNING) << "Could not find the font manifest in the asset store."; return; } @@ -92,8 +86,8 @@ void FontCollection::RegisterFontsFromAssetProvider( // TODO: Handle weights and styles. std::vector font_data; - if (asset_provider->GetAsBuffer(font_asset->value.GetString(), - &font_data)) { + if (asset_manager.GetAsBuffer(font_asset->value.GetString(), + &font_data)) { // The data must be copied because it needs to be moved into the // typeface as a stream. auto data = diff --git a/lib/ui/text/font_collection.h b/lib/ui/text/font_collection.h index fb393b1582b79..ea9c2f46a96a0 100644 --- a/lib/ui/text/font_collection.h +++ b/lib/ui/text/font_collection.h @@ -7,10 +7,10 @@ #include #include -#include "flutter/assets/asset_provider.h" + +#include "flutter/assets/asset_manager.h" #include "lib/fxl/macros.h" #include "lib/fxl/memory/ref_ptr.h" -#include "txt/asset_data_provider.h" #include "txt/font_collection.h" namespace blink { @@ -21,7 +21,8 @@ class FontCollection { std::shared_ptr GetFontCollection() const; - void RegisterFontsFromAssetProvider(fxl::RefPtr asset_provider); + void RegisterFonts(const AssetManager& asset_manager); + void RegisterTestFonts(); private: diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index 858ccd01d4ef6..fd00f6f51b3a3 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -5,7 +5,7 @@ #include "flutter/lib/ui/text/paragraph.h" #include "flutter/common/settings.h" -#include "flutter/common/threads.h" +#include "flutter/common/task_runners.h" #include "flutter/sky/engine/core/rendering/PaintInfo.h" #include "flutter/sky/engine/core/rendering/RenderParagraph.h" #include "flutter/sky/engine/core/rendering/RenderText.h" @@ -53,7 +53,8 @@ Paragraph::Paragraph(std::unique_ptr paragraph) Paragraph::~Paragraph() { if (m_renderView) { RenderView* renderView = m_renderView.leakPtr(); - Threads::UI()->PostTask([renderView]() { renderView->destroy(); }); + destruction_task_runner_->PostTask( + [renderView]() { renderView->destroy(); }); } } diff --git a/lib/ui/text/paragraph.h b/lib/ui/text/paragraph.h index 1b2019373553a..b3a943209ab4c 100644 --- a/lib/ui/text/paragraph.h +++ b/lib/ui/text/paragraph.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_LIB_UI_TEXT_PARAGRAPH_H_ #define FLUTTER_LIB_UI_TEXT_PARAGRAPH_H_ +#include "flutter/fml/message_loop.h" #include "flutter/lib/ui/painting/canvas.h" #include "flutter/lib/ui/text/paragraph_impl.h" #include "flutter/lib/ui/text/paragraph_impl_blink.h" @@ -66,6 +67,10 @@ class Paragraph : public fxl::RefCountedThreadSafe, explicit Paragraph(std::unique_ptr paragraph); + // TODO: This can be removed when the render view association for the legacy + // runtime is removed. + fxl::RefPtr destruction_task_runner_ = + UIDartState::Current()->GetTaskRunners().GetUITaskRunner(); OwnPtr m_renderView; }; diff --git a/lib/ui/text/paragraph_builder.cc b/lib/ui/text/paragraph_builder.cc index 469f2ca939c7b..2ebf4006c2c8d 100644 --- a/lib/ui/text/paragraph_builder.cc +++ b/lib/ui/text/paragraph_builder.cc @@ -5,7 +5,7 @@ #include "flutter/lib/ui/text/paragraph_builder.h" #include "flutter/common/settings.h" -#include "flutter/common/threads.h" +#include "flutter/common/task_runners.h" #include "flutter/lib/ui/text/font_collection.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/sky/engine/core/rendering/RenderInline.h" @@ -201,16 +201,19 @@ fxl::RefPtr ParagraphBuilder::create( double fontSize, double lineHeight, const std::u16string& ellipsis) { - return fxl::MakeRefCounted(encoded, fontFamily, fontSize, - lineHeight, ellipsis); + return fxl::MakeRefCounted( + encoded, fontFamily, fontSize, lineHeight, ellipsis, + UIDartState::Current()->use_blink()); } ParagraphBuilder::ParagraphBuilder(tonic::Int32List& encoded, const std::string& fontFamily, double fontSize, double lineHeight, - const std::u16string& ellipsis) { - if (!Settings::Get().using_blink) { + const std::u16string& ellipsis, + bool use_blink) + : m_useBlink(use_blink) { + if (!m_useBlink) { int32_t mask = encoded[0]; txt::ParagraphStyle style; if (mask & psTextAlignMask) @@ -265,7 +268,8 @@ ParagraphBuilder::ParagraphBuilder(tonic::Int32List& encoded, ParagraphBuilder::~ParagraphBuilder() { if (m_renderView) { RenderView* renderView = m_renderView.leakPtr(); - Threads::UI()->PostTask([renderView]() { renderView->destroy(); }); + destruction_task_runner_->PostTask( + [renderView]() { renderView->destroy(); }); } } @@ -279,7 +283,7 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, int32_t mask = encoded[0]; - if (!Settings::Get().using_blink) { + if (!m_useBlink) { // Set to use the properties of the previous style if the property is not // explicitly given. txt::TextStyle style = m_paragraphBuilder->PeekStyle(); @@ -408,7 +412,7 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, } void ParagraphBuilder::pop() { - if (!Settings::Get().using_blink) { + if (!m_useBlink) { m_paragraphBuilder->Pop(); } else { // Blink Version. @@ -430,7 +434,7 @@ Dart_Handle ParagraphBuilder::addText(const std::u16string& text) { if (error_code != U_BUFFER_OVERFLOW_ERROR) return tonic::ToDart("string is not well-formed UTF-16"); - if (!Settings::Get().using_blink) { + if (!m_useBlink) { m_paragraphBuilder->AddText(text); } else { // Blink Version. @@ -449,7 +453,7 @@ Dart_Handle ParagraphBuilder::addText(const std::u16string& text) { fxl::RefPtr ParagraphBuilder::build() { m_currentRenderObject = nullptr; - if (!Settings::Get().using_blink) { + if (!m_useBlink) { return Paragraph::Create(m_paragraphBuilder->Build()); } else { return Paragraph::Create(m_renderView.release()); diff --git a/lib/ui/text/paragraph_builder.h b/lib/ui/text/paragraph_builder.h index ceb8c3a5de8f6..15f6be6512ea0 100644 --- a/lib/ui/text/paragraph_builder.h +++ b/lib/ui/text/paragraph_builder.h @@ -55,14 +55,20 @@ class ParagraphBuilder : public fxl::RefCountedThreadSafe, const std::string& fontFamily, double fontSize, double lineHeight, - const std::u16string& ellipsis); + const std::u16string& ellipsis, + bool use_blink); void createRenderView(); + // TODO: This can be removed when the render view association for the legacy + // runtime is removed. + fxl::RefPtr destruction_task_runner_ = + UIDartState::Current()->GetTaskRunners().GetUITaskRunner(); OwnPtr m_renderView; RenderObject* m_renderParagraph; RenderObject* m_currentRenderObject; std::unique_ptr m_paragraphBuilder; + bool m_useBlink; }; } // namespace blink diff --git a/lib/ui/text/paragraph_impl_blink.cc b/lib/ui/text/paragraph_impl_blink.cc index c7752c0a7c757..5c50f047afa33 100644 --- a/lib/ui/text/paragraph_impl_blink.cc +++ b/lib/ui/text/paragraph_impl_blink.cc @@ -4,7 +4,6 @@ #include "flutter/lib/ui/text/paragraph_impl_blink.h" -#include "flutter/common/threads.h" #include "flutter/lib/ui/text/paragraph.h" #include "flutter/lib/ui/text/paragraph_impl.h" #include "flutter/sky/engine/core/rendering/PaintInfo.h" @@ -30,7 +29,8 @@ ParagraphImplBlink::ParagraphImplBlink(PassOwnPtr renderView) ParagraphImplBlink::~ParagraphImplBlink() { if (m_renderView) { RenderView* renderView = m_renderView.leakPtr(); - Threads::UI()->PostTask([renderView]() { renderView->destroy(); }); + destruction_task_runner_->PostTask( + [renderView]() { renderView->destroy(); }); } } diff --git a/lib/ui/text/paragraph_impl_blink.h b/lib/ui/text/paragraph_impl_blink.h index 79d89ad471962..ebd80f8dd5382 100644 --- a/lib/ui/text/paragraph_impl_blink.h +++ b/lib/ui/text/paragraph_impl_blink.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_LIB_UI_TEXT_PARAGRAPH_IMPL_BLINK_H_ #define FLUTTER_LIB_UI_TEXT_PARAGRAPH_IMPL_BLINK_H_ +#include "flutter/fml/message_loop.h" #include "flutter/lib/ui/painting/canvas.h" #include "flutter/lib/ui/text/paragraph_impl.h" #include "flutter/lib/ui/text/text_box.h" @@ -41,6 +42,10 @@ class ParagraphImplBlink : public ParagraphImpl { int absoluteOffsetForPosition(const PositionWithAffinity& position); + // TODO: This can be removed when the render view association for the legacy + // runtime is removed. + fxl::RefPtr destruction_task_runner_ = + UIDartState::Current()->GetTaskRunners().GetUITaskRunner(); OwnPtr m_renderView; }; diff --git a/lib/ui/text/paragraph_impl_txt.cc b/lib/ui/text/paragraph_impl_txt.cc index de8d8ff0b2fc3..28c6ea19a8157 100644 --- a/lib/ui/text/paragraph_impl_txt.cc +++ b/lib/ui/text/paragraph_impl_txt.cc @@ -4,7 +4,7 @@ #include "flutter/lib/ui/text/paragraph_impl_txt.h" -#include "flutter/common/threads.h" +#include "flutter/common/task_runners.h" #include "flutter/lib/ui/text/paragraph.h" #include "flutter/lib/ui/text/paragraph_impl.h" #include "lib/fxl/logging.h" diff --git a/lib/ui/ui_dart_state.cc b/lib/ui/ui_dart_state.cc index 3bdf21e6a1a93..8ef7ca98fd758 100644 --- a/lib/ui/ui_dart_state.cc +++ b/lib/ui/ui_dart_state.cc @@ -4,6 +4,7 @@ #include "flutter/lib/ui/ui_dart_state.h" +#include "flutter/fml/message_loop.h" #include "flutter/lib/ui/window/window.h" #include "flutter/sky/engine/platform/fonts/FontSelector.h" #include "lib/tonic/converter/dart_converter.h" @@ -12,34 +13,44 @@ using tonic::ToDart; namespace blink { -IsolateClient::~IsolateClient() {} - -UIDartState::UIDartState(IsolateClient* isolate_client, - std::unique_ptr window, - int dirfd) - : tonic::DartState(dirfd), - isolate_client_(isolate_client), - main_port_(ILLEGAL_PORT), - window_(std::move(window)) {} +UIDartState::UIDartState(TaskRunners task_runners, + TaskObserverAdd add_callback, + TaskObserverRemove remove_callback, + fml::WeakPtr resource_context, + fxl::RefPtr skia_unref_queue, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + std::string logger_prefix) + : task_runners_(std::move(task_runners)), + add_callback_(std::move(add_callback)), + remove_callback_(std::move(remove_callback)), + resource_context_(std::move(resource_context)), + advisory_script_uri_(std::move(advisory_script_uri)), + advisory_script_entrypoint_(std::move(advisory_script_entrypoint)), + logger_prefix_(std::move(logger_prefix)), + skia_unref_queue_(std::move(skia_unref_queue)), + weak_factory_(this) { + AddOrRemoveTaskObserver(true /* add */); +} UIDartState::~UIDartState() { - main_port_ = ILLEGAL_PORT; - // We've already destroyed the isolate. Revoke any weak ptrs held by - // DartPersistentValues so they don't try to enter the destroyed isolate to - // clean themselves up. - // TODO(abarth): Can we do this work in the base class? - weak_factory_.InvalidateWeakPtrs(); + AddOrRemoveTaskObserver(false /* remove */); } -UIDartState* UIDartState::CreateForChildIsolate() { - return new UIDartState(isolate_client_, nullptr); +const std::string& UIDartState::GetAdvisoryScriptURI() const { + return advisory_script_uri_; +} + +const std::string& UIDartState::GetAdvisoryScriptEntrypoint() const { + return advisory_script_entrypoint_; } void UIDartState::DidSetIsolate() { - FXL_DCHECK(!debug_name_prefix_.empty()); main_port_ = Dart_GetMainPortId(); std::ostringstream debug_name; - debug_name << debug_name_prefix_ << "$main-" << main_port_; + // main.dart$main-1234 + debug_name << advisory_script_uri_ << "$" << advisory_script_entrypoint_ + << "-" << main_port_; debug_name_ = debug_name.str(); } @@ -55,8 +66,48 @@ PassRefPtr UIDartState::font_selector() { return font_selector_; } -void UIDartState::set_debug_name_prefix(const std::string& debug_name_prefix) { - debug_name_prefix_ = debug_name_prefix; +void UIDartState::SetWindow(std::unique_ptr window) { + window_ = std::move(window); +} + +const TaskRunners& UIDartState::GetTaskRunners() const { + return task_runners_; +} + +fxl::RefPtr UIDartState::GetSkiaUnrefQueue() const { + return skia_unref_queue_; +} + +void UIDartState::ScheduleMicrotask(Dart_Handle closure) { + if (tonic::LogIfError(closure) || !Dart_IsClosure(closure)) { + return; + } + + microtask_queue_.ScheduleMicrotask(closure); +} + +void UIDartState::FlushMicrotasksNow() { + microtask_queue_.RunMicrotasks(); +} + +void UIDartState::AddOrRemoveTaskObserver(bool add) { + auto task_runner = task_runners_.GetUITaskRunner(); + if (!task_runner) { + // This may happen in case the isolate has no thread affinity (for example, + // the service isolate). + return; + } + FXL_DCHECK(add_callback_ && remove_callback_); + if (add) { + add_callback_(reinterpret_cast(this), + [this]() { this->FlushMicrotasksNow(); }); + } else { + remove_callback_(reinterpret_cast(this)); + } +} + +fml::WeakPtr UIDartState::GetResourceContext() const { + return resource_context_; } } // namespace blink diff --git a/lib/ui/ui_dart_state.h b/lib/ui/ui_dart_state.h index 0f7f9343d4958..a5c78c1671815 100644 --- a/lib/ui/ui_dart_state.h +++ b/lib/ui/ui_dart_state.h @@ -5,65 +5,106 @@ #ifndef FLUTTER_LIB_UI_UI_DART_STATE_H_ #define FLUTTER_LIB_UI_UI_DART_STATE_H_ +#include +#include #include +#include "flutter/common/settings.h" +#include "flutter/common/task_runners.h" +#include "flutter/flow/skia_gpu_object.h" +#include "flutter/fml/memory/weak_ptr.h" #include "flutter/sky/engine/wtf/RefPtr.h" #include "lib/fxl/build_config.h" +#include "lib/tonic/dart_microtask_queue.h" #include "lib/tonic/dart_persistent_value.h" #include "lib/tonic/dart_state.h" #include "third_party/dart/runtime/include/dart_api.h" +#include "third_party/skia/include/gpu/GrContext.h" namespace blink { class FontSelector; class Window; -class IsolateClient { - public: - virtual void DidCreateSecondaryIsolate(Dart_Isolate isolate) = 0; - virtual void DidShutdownMainIsolate() = 0; - - protected: - virtual ~IsolateClient(); -}; - class UIDartState : public tonic::DartState { public: - UIDartState(IsolateClient* isolate_client, - std::unique_ptr window, - int dirfd = -1); - ~UIDartState() override; - static UIDartState* Current(); - UIDartState* CreateForChildIsolate(); - - IsolateClient* isolate_client() const { return isolate_client_; } - void set_isolate_client(IsolateClient* isolate_client) { - isolate_client_ = isolate_client; - } Dart_Port main_port() const { return main_port_; } + const std::string& debug_name() const { return debug_name_; } + + const std::string& logger_prefix() const { return logger_prefix_; } + Window* window() const { return window_.get(); } - void set_debug_name_prefix(const std::string& debug_name_prefix); void set_font_selector(PassRefPtr selector); + PassRefPtr font_selector(); - bool is_controller_state() const { return is_controller_state_; } - void set_is_controller_state(bool value) { is_controller_state_ = value; } - bool shutting_down() const { return shutting_down_; } - void set_shutting_down(bool value) { shutting_down_ = value; } + + bool use_blink() const { return use_blink_; } + + const TaskRunners& GetTaskRunners() const; + + void ScheduleMicrotask(Dart_Handle handle); + + void FlushMicrotasksNow(); + + fxl::RefPtr GetSkiaUnrefQueue() const; + + fml::WeakPtr GetResourceContext() const; + + template + static flow::SkiaGPUObject CreateGPUObject(sk_sp object) { + if (!object) { + return {}; + } + auto state = UIDartState::Current(); + FXL_DCHECK(state); + auto queue = state->GetSkiaUnrefQueue(); + return {std::move(object), std::move(queue)}; + }; + + protected: + UIDartState(TaskRunners task_runners, + TaskObserverAdd add_callback, + TaskObserverRemove remove_callback, + fml::WeakPtr resource_context, + fxl::RefPtr skia_unref_queue, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + std::string logger_prefix); + + ~UIDartState() override; + + void SetWindow(std::unique_ptr window); + + void set_use_blink(bool use_blink) { use_blink_ = use_blink; } + + const std::string& GetAdvisoryScriptURI() const; + + const std::string& GetAdvisoryScriptEntrypoint() const; private: void DidSetIsolate() override; - IsolateClient* isolate_client_; - Dart_Port main_port_; - std::string debug_name_prefix_; + const TaskRunners task_runners_; + const TaskObserverAdd add_callback_; + const TaskObserverRemove remove_callback_; + fml::WeakPtr resource_context_; + const std::string advisory_script_uri_; + const std::string advisory_script_entrypoint_; + const std::string logger_prefix_; + Dart_Port main_port_ = ILLEGAL_PORT; std::string debug_name_; std::unique_ptr window_; RefPtr font_selector_; - bool is_controller_state_; - bool shutting_down_ = false; + fxl::RefPtr skia_unref_queue_; + tonic::DartMicrotaskQueue microtask_queue_; + fml::WeakPtrFactory weak_factory_; + + void AddOrRemoveTaskObserver(bool add); + + bool use_blink_ = false; }; } // namespace blink diff --git a/lib/ui/window/platform_message_response_dart.cc b/lib/ui/window/platform_message_response_dart.cc index adddae83653d7..3751b608a8823 100644 --- a/lib/ui/window/platform_message_response_dart.cc +++ b/lib/ui/window/platform_message_response_dart.cc @@ -6,7 +6,7 @@ #include -#include "flutter/common/threads.h" +#include "flutter/common/task_runners.h" #include "lib/fxl/functional/make_copyable.h" #include "lib/tonic/dart_state.h" #include "lib/tonic/logging/dart_invoke.h" @@ -14,12 +14,14 @@ namespace blink { PlatformMessageResponseDart::PlatformMessageResponseDart( - tonic::DartPersistentValue callback) - : callback_(std::move(callback)) {} + tonic::DartPersistentValue callback, + fxl::RefPtr ui_task_runner) + : callback_(std::move(callback)), + ui_task_runner_(std::move(ui_task_runner)) {} PlatformMessageResponseDart::~PlatformMessageResponseDart() { if (!callback_.is_empty()) { - Threads::UI()->PostTask( + ui_task_runner_->PostTask( fxl::MakeCopyable([callback = std::move(callback_)]() mutable { callback.Clear(); })); @@ -31,7 +33,7 @@ void PlatformMessageResponseDart::Complete(std::vector data) { return; FXL_DCHECK(!is_complete_); is_complete_ = true; - Threads::UI()->PostTask(fxl::MakeCopyable( + ui_task_runner_->PostTask(fxl::MakeCopyable( [ callback = std::move(callback_), data = std::move(data) ]() mutable { tonic::DartState* dart_state = callback.dart_state().get(); if (!dart_state) @@ -60,7 +62,7 @@ void PlatformMessageResponseDart::CompleteEmpty() { return; FXL_DCHECK(!is_complete_); is_complete_ = true; - Threads::UI()->PostTask( + ui_task_runner_->PostTask( fxl::MakeCopyable([callback = std::move(callback_)]() mutable { tonic::DartState* dart_state = callback.dart_state().get(); if (!dart_state) diff --git a/lib/ui/window/platform_message_response_dart.h b/lib/ui/window/platform_message_response_dart.h index 51c55a930014b..67bfb3d359691 100644 --- a/lib/ui/window/platform_message_response_dart.h +++ b/lib/ui/window/platform_message_response_dart.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_DART_H_ #define FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_DART_H_ +#include "flutter/fml/message_loop.h" #include "flutter/lib/ui/window/platform_message_response.h" #include "lib/tonic/dart_persistent_value.h" @@ -19,10 +20,13 @@ class PlatformMessageResponseDart : public PlatformMessageResponse { void CompleteEmpty() override; protected: - explicit PlatformMessageResponseDart(tonic::DartPersistentValue callback); + explicit PlatformMessageResponseDart( + tonic::DartPersistentValue callback, + fxl::RefPtr ui_task_runner); ~PlatformMessageResponseDart() override; tonic::DartPersistentValue callback_; + fxl::RefPtr ui_task_runner_; }; } // namespace blink diff --git a/lib/ui/window/viewport_metrics.h b/lib/ui/window/viewport_metrics.h index 1e443ae8c1404..5085d06f42724 100644 --- a/lib/ui/window/viewport_metrics.h +++ b/lib/ui/window/viewport_metrics.h @@ -23,6 +23,25 @@ struct ViewportMetrics { int32_t physical_view_inset_left = 0; }; +struct LogicalSize { + double width = 0.0; + double height = 0.0; +}; + +struct LogicalInset { + double left = 0.0; + double top = 0.0; + double right = 0.0; + double bottom = 0.0; +}; + +struct LogicalMetrics { + LogicalSize size; + double scale = 1.0; + LogicalInset padding; + LogicalInset view_inset; +}; + } // namespace blink #endif // FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_ diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 7b4cf2cde1247..8722c1bc30a6b 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -80,7 +80,8 @@ void SendPlatformMessage(Dart_Handle window, fxl::RefPtr response; if (!Dart_IsNull(callback)) { response = fxl::MakeRefCounted( - tonic::DartPersistentValue(dart_state, callback)); + tonic::DartPersistentValue(dart_state, callback), + dart_state->GetTaskRunners().GetUITaskRunner()); } if (Dart_IsNull(data.dart_handle())) { UIDartState::Current()->window()->client()->HandlePlatformMessage( @@ -254,7 +255,7 @@ void Window::BeginFrame(fxl::TimePoint frameTime) { Dart_NewInteger(microseconds), }); - tonic::DartMicrotaskQueue::GetForCurrentThread()->RunMicrotasks(); + UIDartState::Current()->FlushMicrotasksNow(); DartInvokeField(library_.value(), "_drawFrame", {}); } diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index fa8ce41835b0a..5ecd29afce73b 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -13,6 +13,7 @@ #include "flutter/lib/ui/window/viewport_metrics.h" #include "lib/fxl/time/time_point.h" #include "lib/tonic/dart_persistent_value.h" +#include "third_party/skia/include/gpu/GrContext.h" namespace tonic { class DartLibraryNatives; @@ -33,12 +34,14 @@ class WindowClient { virtual ~WindowClient(); }; -class Window { +class Window final { public: explicit Window(WindowClient* client); + ~Window(); WindowClient* client() const { return client_; } + const ViewportMetrics& viewport_metrics() { return viewport_metrics_; } void DidCreateIsolate();