未验证 提交 78a1c7eb 编写于 作者: C Chris Bracken 提交者: GitHub

Revert "Drop last usages of Dart_New from engine (#16838)" (#16915)

We believe this may be implicated in a Windows-specific crash during the
Flutter Gallery integration test.

See:
https://github.com/flutter/flutter/issues/51896

This reverts commit f9b78c5d.
上级 ba8a8922
......@@ -298,6 +298,8 @@ FILE: ../../../flutter/lib/ui/painting/color_filter.cc
FILE: ../../../flutter/lib/ui/painting/color_filter.h
FILE: ../../../flutter/lib/ui/painting/engine_layer.cc
FILE: ../../../flutter/lib/ui/painting/engine_layer.h
FILE: ../../../flutter/lib/ui/painting/frame_info.cc
FILE: ../../../flutter/lib/ui/painting/frame_info.h
FILE: ../../../flutter/lib/ui/painting/gradient.cc
FILE: ../../../flutter/lib/ui/painting/gradient.h
FILE: ../../../flutter/lib/ui/painting/image.cc
......
......@@ -30,6 +30,8 @@ source_set("ui") {
"painting/color_filter.h",
"painting/engine_layer.cc",
"painting/engine_layer.h",
"painting/frame_info.cc",
"painting/frame_info.h",
"painting/gradient.cc",
"painting/gradient.h",
"painting/image.cc",
......
......@@ -22,16 +22,14 @@ class Scene extends NativeFieldWrapperClass2 {
/// Creates a raster image representation of the current state of the scene.
/// This is a slow operation that is performed on a background thread.
Future<Image> toImage(int width, int height) async {
Future<Image> toImage(int width, int height) {
if (width <= 0 || height <= 0) {
throw Exception('Invalid image dimensions.');
}
final Image image = Image._();
await _futurize((_Callback<bool> callback) => _toImage(image, width, height, callback));
return image;
return _futurize((_Callback<Image> callback) => _toImage(width, height, callback));
}
String _toImage(Image outImage, int width, int height, _Callback<bool> callback) native 'Scene_toImage';
String _toImage(int width, int height, _Callback<Image> callback) native 'Scene_toImage';
/// Releases the resources used by this scene.
///
......
......@@ -61,8 +61,7 @@ void Scene::dispose() {
ClearDartWrapper();
}
Dart_Handle Scene::toImage(Dart_Handle image_handle,
uint32_t width,
Dart_Handle Scene::toImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
TRACE_EVENT0("flutter", "Scene::toImage");
......@@ -76,8 +75,7 @@ Dart_Handle Scene::toImage(Dart_Handle image_handle,
return tonic::ToDart("Could not flatten scene into a layer tree.");
}
return Picture::RasterizeToImage(image_handle, picture, width, height,
raw_image_callback);
return Picture::RasterizeToImage(picture, width, height, raw_image_callback);
}
std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() {
......
......@@ -32,8 +32,7 @@ class Scene : public RefCountedDartWrappable<Scene> {
std::unique_ptr<flutter::LayerTree> takeLayerTree();
Dart_Handle toImage(Dart_Handle image_handle,
uint32_t width,
Dart_Handle toImage(uint32_t width,
uint32_t height,
Dart_Handle image_callback);
......
......@@ -13,6 +13,7 @@
#include "flutter/lib/ui/painting/codec.h"
#include "flutter/lib/ui/painting/color_filter.h"
#include "flutter/lib/ui/painting/engine_layer.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/painting/gradient.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/image_filter.h"
......@@ -79,6 +80,7 @@ void DartUI::InitForGlobal() {
DartRuntimeHooks::RegisterNatives(g_natives);
EngineLayer::RegisterNatives(g_natives);
FontCollection::RegisterNatives(g_natives);
FrameInfo::RegisterNatives(g_natives);
ImageFilter::RegisterNatives(g_natives);
ImageShader::RegisterNatives(g_natives);
IsolateNameServerNatives::RegisterNatives(g_natives);
......
......@@ -1639,19 +1639,22 @@ typedef ImageDecoderCallback = void Function(Image result);
///
/// To obtain an instance of the [FrameInfo] interface, see
/// [Codec.getNextFrame].
class FrameInfo {
@pragma('vm:entry-point')
class FrameInfo extends NativeFieldWrapperClass2 {
/// This class is created by the engine, and should not be instantiated
/// or extended directly.
///
/// To obtain an instance of the [FrameInfo] interface, see
/// [Codec.getNextFrame].
FrameInfo._(int durationMilliseconds, this.image) : duration = Duration(milliseconds: durationMilliseconds);
@pragma('vm:entry-point')
FrameInfo._();
/// The duration this frame should be shown.
final Duration duration;
Duration get duration => Duration(milliseconds: _durationMillis);
int get _durationMillis native 'FrameInfo_durationMillis';
/// The [Image] object for this frame.
final Image image;
Image get image native 'FrameInfo_image';
}
/// A handle to an image codec.
......@@ -1681,32 +1684,21 @@ class Codec extends NativeFieldWrapperClass2 {
/// * -1 for infinity repetitions.
int get repetitionCount native 'Codec_repetitionCount';
FrameInfo _cachedFrame;
/// Fetches the next animation frame.
///
/// Wraps back to the first frame after returning the last frame.
///
/// The returned future can complete with an error if the decoding has failed.
Future<FrameInfo> getNextFrame() async {
if (_cachedFrame == null || frameCount != 1) {
final Image image = Image._();
final int durationMilliseconds = await _futurize((_Callback<int> callback) => _getNextFrame(image, callback));
_cachedFrame = FrameInfo._(durationMilliseconds, image);
}
return _cachedFrame;
Future<FrameInfo> getNextFrame() {
return _futurize(_getNextFrame);
}
/// Returns an error message on failure, null on success.
String _getNextFrame(Image outImage, _Callback<int> callback) native 'Codec_getNextFrame';
String _getNextFrame(_Callback<FrameInfo> callback) native 'Codec_getNextFrame';
/// Release the resources used by this object. The object is no longer usable
/// after this method is called.
void dispose() {
_cachedFrame = null;
_dispose();
}
void _dispose() native 'Codec_dispose';
void dispose() native 'Codec_dispose';
}
/// Instantiates an image codec [Codec] object.
......@@ -1726,12 +1718,10 @@ class Codec extends NativeFieldWrapperClass2 {
Future<Codec> instantiateImageCodec(Uint8List list, {
int targetWidth,
int targetHeight,
}) async {
final Codec codec = Codec._();
await _futurize((_Callback<bool> callback) {
return _instantiateImageCodec(codec, list, callback, null, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension);
});
return codec;
}) {
return _futurize(
(_Callback<Codec> callback) => _instantiateImageCodec(list, callback, null, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
);
}
/// Instantiates a [Codec] object for an image binary data.
......@@ -1745,7 +1735,7 @@ Future<Codec> instantiateImageCodec(Uint8List list, {
/// If both are equal to [_kDoNotResizeDimension], then the image maintains its real size.
///
/// Returns an error message if the instantiation has failed, null otherwise.
String _instantiateImageCodec(Codec outCodec, Uint8List list, _Callback<bool> callback, _ImageInfo imageInfo, int targetWidth, int targetHeight)
String _instantiateImageCodec(Uint8List list, _Callback<Codec> callback, _ImageInfo imageInfo, int targetWidth, int targetHeight)
native 'instantiateImageCodec';
/// Loads a single image frame from a byte array into an [Image] object.
......@@ -1786,12 +1776,11 @@ void decodeImageFromPixels(
{int rowBytes, int targetWidth, int targetHeight}
) {
final _ImageInfo imageInfo = _ImageInfo(width, height, format.index, rowBytes);
final Codec codec = Codec._();
_futurize(
(_Callback<bool> callback) => _instantiateImageCodec(codec, pixels, callback, imageInfo, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
).then((bool _) {
codec.getNextFrame().then((FrameInfo frameInfo) => callback(frameInfo.image));
});
final Future<Codec> codecFuture = _futurize(
(_Callback<Codec> callback) => _instantiateImageCodec(pixels, callback, imageInfo, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
);
codecFuture.then((Codec codec) => codec.getNextFrame())
.then((FrameInfo frameInfo) => callback(frameInfo.image));
}
/// Determines the winding rule that decides how the interior of a [Path] is
......@@ -4136,17 +4125,15 @@ class Picture extends NativeFieldWrapperClass2 {
///
/// Although the image is returned synchronously, the picture is actually
/// rasterized the first time the image is drawn and then cached.
Future<Image> toImage(int width, int height) async {
Future<Image> toImage(int width, int height) {
if (width <= 0 || height <= 0)
throw Exception('Invalid image dimensions.');
final Image image = Image._();
await _futurize(
(_Callback<bool> callback) => _toImage(image, width, height, callback)
return _futurize(
(_Callback<Image> callback) => _toImage(width, height, callback)
);
return image;
}
String _toImage(Image outImage, int width, int height, _Callback<bool> callback) native 'Picture_toImage';
String _toImage(int width, int height, _Callback<Image> callback) native 'Picture_toImage';
/// Release the resources used by this object. The object is no longer usable
/// after this method is called.
......
......@@ -10,6 +10,7 @@
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/trace_event.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/painting/multi_frame_codec.h"
#include "flutter/lib/ui/painting/single_frame_codec.h"
#include "third_party/skia/include/codec/SkCodec.h"
......@@ -144,14 +145,13 @@ static std::variant<ImageDecoder::ImageInfo, std::string> ConvertImageInfo(
}
static void InstantiateImageCodec(Dart_NativeArguments args) {
Dart_Handle codec_handle = Dart_GetNativeArgument(args, 0);
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 2);
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
if (!Dart_IsClosure(callback_handle)) {
Dart_SetReturnValue(args, tonic::ToDart("Callback must be a function"));
return;
}
Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 3);
Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 2);
std::optional<ImageDecoder::ImageInfo> image_info;
......@@ -171,7 +171,7 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
{
Dart_Handle exception = nullptr;
tonic::Uint8List list =
tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 1,
tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 0,
exception);
if (exception) {
Dart_SetReturnValue(args, exception);
......@@ -191,9 +191,9 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
}
const int targetWidth =
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 4));
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 3));
const int targetHeight =
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 5));
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 4));
std::unique_ptr<SkCodec> codec;
bool single_frame;
......@@ -208,6 +208,8 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
single_frame = codec->getFrameCount() == 1;
}
fml::RefPtr<Codec> ui_codec;
if (single_frame) {
ImageDecoder::ImageDescriptor descriptor;
descriptor.decompressed_image_info = image_info;
......@@ -220,13 +222,12 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
}
descriptor.data = std::move(buffer);
SingleFrameCodec::Create(codec_handle, std::move(descriptor));
ui_codec = fml::MakeRefCounted<SingleFrameCodec>(std::move(descriptor));
} else {
MultiFrameCodec::Create(codec_handle, std::move(codec));
ui_codec = fml::MakeRefCounted<MultiFrameCodec>(std::move(codec));
}
tonic::DartInvoke(callback_handle, {Dart_True()});
Dart_SetReturnValue(args, Dart_Null());
tonic::DartInvoke(callback_handle, {ToDart(ui_codec)});
}
IMPLEMENT_WRAPPERTYPEINFO(ui, Codec);
......@@ -245,7 +246,7 @@ void Codec::dispose() {
void Codec::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"instantiateImageCodec", InstantiateImageCodec, 6, true},
{"instantiateImageCodec", InstantiateImageCodec, 5, true},
});
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
......
......@@ -6,6 +6,7 @@
#define FLUTTER_LIB_UI_PAINTING_CODEC_H_
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
......@@ -29,8 +30,7 @@ class Codec : public RefCountedDartWrappable<Codec> {
virtual int repetitionCount() const = 0;
virtual Dart_Handle getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) = 0;
virtual Dart_Handle getNextFrame(Dart_Handle callback_handle) = 0;
void dispose();
......
// Copyright 2013 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/lib/ui/painting/frame_info.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"
namespace flutter {
IMPLEMENT_WRAPPERTYPEINFO(ui, FrameInfo);
#define FOR_EACH_BINDING(V) \
V(FrameInfo, durationMillis) \
V(FrameInfo, image)
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
FrameInfo::FrameInfo(fml::RefPtr<CanvasImage> image, int durationMillis)
: image_(std::move(image)), durationMillis_(durationMillis) {}
FrameInfo::~FrameInfo(){};
void FrameInfo::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
} // namespace flutter
// Copyright 2013 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_LIB_UI_PAINTING_FRAME_INFO_H_
#define FLUTTER_LIB_UI_PAINTING_FRAME_INFO_H_
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/image.h"
namespace flutter {
// A single animation frame.
class FrameInfo final : public RefCountedDartWrappable<FrameInfo> {
DEFINE_WRAPPERTYPEINFO();
public:
int durationMillis() { return durationMillis_; }
fml::RefPtr<CanvasImage> image() { return image_; }
static void RegisterNatives(tonic::DartLibraryNatives* natives);
private:
FrameInfo(fml::RefPtr<CanvasImage> image, int durationMillis);
~FrameInfo() override;
const fml::RefPtr<CanvasImage> image_;
const int durationMillis_;
FML_FRIEND_MAKE_REF_COUNTED(FrameInfo);
FML_FRIEND_REF_COUNTED_THREAD_SAFE(FrameInfo);
};
} // namespace flutter
#endif // FLUTTER_LIB_UI_PAINTING_FRAME_INFO_H_
......@@ -22,10 +22,8 @@ class CanvasImage final : public RefCountedDartWrappable<CanvasImage> {
public:
~CanvasImage() override;
static fml::RefPtr<CanvasImage> Create(Dart_Handle dart_handle) {
auto image = fml::MakeRefCounted<CanvasImage>();
image->AssociateWithDartWrapper(dart_handle);
return image;
static fml::RefPtr<CanvasImage> Create() {
return fml::MakeRefCounted<CanvasImage>();
}
int width() { return image_.get()->width(); }
......
......@@ -20,11 +20,8 @@ MultiFrameCodec::MultiFrameCodec(std::unique_ptr<SkCodec> codec)
MultiFrameCodec::~MultiFrameCodec() = default;
static void InvokeNextFrameCallback(
sk_sp<SkImage> skImage,
fml::RefPtr<CanvasImage> canvas_image,
fml::RefPtr<FrameInfo> frameInfo,
std::unique_ptr<DartPersistentValue> callback,
fml::RefPtr<flutter::SkiaUnrefQueue> unref_queue,
SkCodec::FrameInfo skFrameInfo,
size_t trace_id) {
std::shared_ptr<tonic::DartState> dart_state = callback->dart_state().lock();
if (!dart_state) {
......@@ -33,13 +30,10 @@ static void InvokeNextFrameCallback(
return;
}
tonic::DartState::Scope scope(dart_state);
if (skImage) {
canvas_image->set_image({skImage, std::move(unref_queue)});
tonic::DartInvoke(callback->value(),
{tonic::ToDart(skFrameInfo.fDuration)});
} else {
if (!frameInfo) {
tonic::DartInvoke(callback->value(), {Dart_Null()});
} else {
tonic::DartInvoke(callback->value(), {ToDart(frameInfo)});
}
}
......@@ -135,32 +129,30 @@ sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage(
}
void MultiFrameCodec::GetNextFrameAndInvokeCallback(
fml::RefPtr<CanvasImage> canvas_image,
std::unique_ptr<DartPersistentValue> callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner,
fml::WeakPtr<GrContext> resourceContext,
fml::RefPtr<flutter::SkiaUnrefQueue> unref_queue,
size_t trace_id) {
fml::RefPtr<FrameInfo> frameInfo = NULL;
sk_sp<SkImage> skImage = GetNextFrameImage(resourceContext);
SkCodec::FrameInfo skFrameInfo;
if (skImage) {
fml::RefPtr<CanvasImage> image = CanvasImage::Create();
image->set_image({skImage, std::move(unref_queue)});
SkCodec::FrameInfo skFrameInfo;
codec_->getFrameInfo(nextFrameIndex_, &skFrameInfo);
frameInfo =
fml::MakeRefCounted<FrameInfo>(std::move(image), skFrameInfo.fDuration);
}
nextFrameIndex_ = (nextFrameIndex_ + 1) % frameCount_;
ui_task_runner->PostTask(fml::MakeCopyable(
[skImage = std::move(skImage), callback = std::move(callback),
canvas_image = std::move(canvas_image),
unref_queue = std::move(unref_queue),
skFrameInfo = std::move(skFrameInfo), trace_id]() mutable {
InvokeNextFrameCallback(std::move(skImage), std::move(canvas_image),
std::move(callback), std::move(unref_queue),
std::move(skFrameInfo), trace_id);
[callback = std::move(callback), frameInfo, trace_id]() mutable {
InvokeNextFrameCallback(frameInfo, std::move(callback), trace_id);
}));
}
Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) {
Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) {
static size_t trace_counter = 1;
const size_t trace_id = trace_counter++;
......@@ -168,19 +160,17 @@ Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle image_handle,
return tonic::ToDart("Callback must be a function");
}
auto canvas_image = CanvasImage::Create(image_handle);
auto* dart_state = UIDartState::Current();
const auto& task_runners = dart_state->GetTaskRunners();
task_runners.GetIOTaskRunner()->PostTask(fml::MakeCopyable(
[canvas_image = std::move(canvas_image),
callback = std::make_unique<DartPersistentValue>(
[callback = std::make_unique<DartPersistentValue>(
tonic::DartState::Current(), callback_handle),
this, trace_id, ui_task_runner = task_runners.GetUITaskRunner(),
io_manager = dart_state->GetIOManager()]() mutable {
GetNextFrameAndInvokeCallback(
canvas_image, std::move(callback), std::move(ui_task_runner),
std::move(callback), std::move(ui_task_runner),
io_manager->GetResourceContext(), io_manager->GetSkiaUnrefQueue(),
trace_id);
}));
......
......@@ -5,23 +5,15 @@
#ifndef FLUTTER_LIB_UI_PAINTING_MUTLI_FRAME_CODEC_H_
#define FLUTTER_LIB_UI_PAINTING_MUTLI_FRAME_CODEC_H_
#include "flutter/flow/skia_gpu_object.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/lib/ui/painting/codec.h"
#include "flutter/lib/ui/painting/image.h"
namespace flutter {
class MultiFrameCodec : public Codec {
public:
static fml::RefPtr<MultiFrameCodec> Create(Dart_Handle codec_handle,
std::unique_ptr<SkCodec> codec) {
auto multi_frame_codec =
fml::MakeRefCounted<MultiFrameCodec>(std::move(codec));
multi_frame_codec->AssociateWithDartWrapper(codec_handle);
return multi_frame_codec;
}
MultiFrameCodec(std::unique_ptr<SkCodec> codec);
~MultiFrameCodec() override;
// |Codec|
......@@ -31,10 +23,9 @@ class MultiFrameCodec : public Codec {
int repetitionCount() const override;
// |Codec|
Dart_Handle getNextFrame(Dart_Handle image_handle, Dart_Handle args) override;
Dart_Handle getNextFrame(Dart_Handle args) override;
private:
MultiFrameCodec(std::unique_ptr<SkCodec> codec);
const std::unique_ptr<SkCodec> codec_;
const int frameCount_;
const int repetitionCount_;
......@@ -48,7 +39,6 @@ class MultiFrameCodec : public Codec {
sk_sp<SkImage> GetNextFrameImage(fml::WeakPtr<GrContext> resourceContext);
void GetNextFrameAndInvokeCallback(
fml::RefPtr<CanvasImage> canvas_image,
std::unique_ptr<DartPersistentValue> callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner,
fml::WeakPtr<GrContext> resourceContext,
......
......@@ -40,16 +40,14 @@ Picture::Picture(flutter::SkiaGPUObject<SkPicture> picture)
Picture::~Picture() = default;
Dart_Handle Picture::toImage(Dart_Handle image_handle,
uint32_t width,
Dart_Handle Picture::toImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
if (!picture_.get()) {
return tonic::ToDart("Picture is null");
}
return RasterizeToImage(image_handle, picture_.get(), width, height,
raw_image_callback);
return RasterizeToImage(picture_.get(), width, height, raw_image_callback);
}
void Picture::dispose() {
......@@ -64,8 +62,7 @@ size_t Picture::GetAllocationSize() {
}
}
Dart_Handle Picture::RasterizeToImage(Dart_Handle image_handle,
sk_sp<SkPicture> picture,
Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
......@@ -77,8 +74,6 @@ Dart_Handle Picture::RasterizeToImage(Dart_Handle image_handle,
return tonic::ToDart("Image dimensions for scene were invalid.");
}
auto canvas_image = CanvasImage::Create(image_handle);
auto* dart_state = UIDartState::Current();
tonic::DartPersistentValue* image_callback =
new tonic::DartPersistentValue(dart_state, raw_image_callback);
......@@ -94,7 +89,7 @@ Dart_Handle Picture::RasterizeToImage(Dart_Handle image_handle,
auto picture_bounds = SkISize::Make(width, height);
auto ui_task = fml::MakeCopyable([canvas_image, image_callback, unref_queue](
auto ui_task = fml::MakeCopyable([image_callback, unref_queue](
sk_sp<SkImage> raster_image) mutable {
auto dart_state = image_callback->dart_state().lock();
if (!dart_state) {
......@@ -105,14 +100,15 @@ Dart_Handle Picture::RasterizeToImage(Dart_Handle image_handle,
if (!raster_image) {
tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
delete image_callback;
return;
}
canvas_image->set_image({std::move(raster_image), std::move(unref_queue)});
auto dart_image = CanvasImage::Create();
dart_image->set_image({std::move(raster_image), std::move(unref_queue)});
auto* raw_dart_image = tonic::ToDart(std::move(dart_image));
// All done!
tonic::DartInvoke(image_callback->Get(), {Dart_True()});
tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
// image_callback is associated with the Dart isolate and must be deleted
// on the UI thread
......
......@@ -28,8 +28,7 @@ class Picture : public RefCountedDartWrappable<Picture> {
sk_sp<SkPicture> picture() const { return picture_.get(); }
Dart_Handle toImage(Dart_Handle image_handle,
uint32_t width,
Dart_Handle toImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback);
......@@ -39,8 +38,7 @@ class Picture : public RefCountedDartWrappable<Picture> {
static void RegisterNatives(tonic::DartLibraryNatives* natives);
static Dart_Handle RasterizeToImage(Dart_Handle image_handle,
sk_sp<SkPicture> picture,
static Dart_Handle RasterizeToImage(sk_sp<SkPicture> picture,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback);
......
......@@ -4,6 +4,7 @@
#include "flutter/lib/ui/painting/single_frame_codec.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/tonic/logging/dart_invoke.h"
......@@ -22,20 +23,16 @@ int SingleFrameCodec::repetitionCount() const {
return 0;
}
Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) {
Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_handle) {
if (!Dart_IsClosure(callback_handle)) {
return tonic::ToDart("Callback must be a function");
}
if (status_ == Status::kComplete) {
return tonic::ToDart(
"Dart callers are responsible for caching the frame callback "
"information");
tonic::DartInvoke(callback_handle, {tonic::ToDart(cached_frame_)});
return Dart_Null();
}
auto canvas_image = CanvasImage::Create(image_handle);
// This has to be valid because this method is called from Dart.
auto dart_state = UIDartState::Current();
......@@ -60,7 +57,7 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle image_handle,
fml::RefPtr<SingleFrameCodec>* raw_codec_ref =
new fml::RefPtr<SingleFrameCodec>(this);
decoder->Decode(descriptor_, [canvas_image, raw_codec_ref](auto image) {
decoder->Decode(descriptor_, [raw_codec_ref](auto image) {
std::unique_ptr<fml::RefPtr<SingleFrameCodec>> codec_ref(raw_codec_ref);
fml::RefPtr<SingleFrameCodec> codec(std::move(*codec_ref));
......@@ -69,14 +66,18 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle image_handle,
if (!state) {
// This is probably because the isolate has been terminated before the
// image could be decoded.
return;
}
tonic::DartState::Scope scope(state.get());
if (image.get()) {
auto canvas_image = fml::MakeRefCounted<CanvasImage>();
canvas_image->set_image(std::move(image));
codec->cached_frame_image_size_ = canvas_image->GetAllocationSize();
codec->cached_frame_ = fml::MakeRefCounted<FrameInfo>(
std::move(canvas_image), 0 /* duration */);
}
// The cached frame is now available and should be returned to any future
......@@ -84,8 +85,9 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle image_handle,
codec->status_ = Status::kComplete;
// Invoke any callbacks that were provided before the frame was decoded.
Dart_Handle frame = tonic::ToDart(codec->cached_frame_);
for (const DartPersistentValue& callback : codec->pending_callbacks_) {
tonic::DartInvoke(callback.value(), {tonic::ToDart(0)});
tonic::DartInvoke(callback.value(), {frame});
}
codec->pending_callbacks_.clear();
});
......@@ -95,13 +97,17 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle image_handle,
descriptor_.data.reset();
status_ = Status::kInProgress;
return Dart_Null();
}
size_t SingleFrameCodec::GetAllocationSize() {
const auto& data = descriptor_.data;
const auto data_byte_size = data ? data->size() : 0;
return data_byte_size + cached_frame_image_size_ + sizeof(this);
const auto frame_byte_size = (cached_frame_ && cached_frame_->image())
? cached_frame_->image()->GetAllocationSize()
: 0;
return data_byte_size + frame_byte_size + sizeof(this);
}
} // namespace flutter
......@@ -7,20 +7,15 @@
#include "flutter/fml/macros.h"
#include "flutter/lib/ui/painting/codec.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/painting/image_decoder.h"
namespace flutter {
class SingleFrameCodec : public Codec {
public:
static fml::RefPtr<SingleFrameCodec> Create(
Dart_Handle codec_handle,
ImageDecoder::ImageDescriptor descriptor) {
auto codec = fml::MakeRefCounted<SingleFrameCodec>(std::move(descriptor));
codec->AssociateWithDartWrapper(codec_handle);
return codec;
}
SingleFrameCodec(ImageDecoder::ImageDescriptor descriptor);
~SingleFrameCodec() override;
// |Codec|
......@@ -30,18 +25,16 @@ class SingleFrameCodec : public Codec {
int repetitionCount() const override;
// |Codec|
Dart_Handle getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) override;
Dart_Handle getNextFrame(Dart_Handle args) override;
// |DartWrappable|
size_t GetAllocationSize() override;
private:
SingleFrameCodec(ImageDecoder::ImageDescriptor descriptor);
enum class Status { kNew, kInProgress, kComplete };
Status status_;
ImageDecoder::ImageDescriptor descriptor_;
size_t cached_frame_image_size_;
fml::RefPtr<FrameInfo> cached_frame_;
std::vector<DartPersistentValue> pending_callbacks_;
FML_FRIEND_MAKE_REF_COUNTED(SingleFrameCodec);
......
......@@ -22,6 +22,7 @@ DartState::Scope::~Scope() {}
DartState::DartState(int dirfd,
std::function<void(Dart_Handle)> message_epilogue)
: isolate_(nullptr),
private_constructor_name_(),
class_library_(new DartClassLibrary),
message_handler_(new DartMessageHandler()),
file_loader_(new FileLoader(dirfd)),
......@@ -36,6 +37,12 @@ void DartState::SetIsolate(Dart_Isolate isolate) {
if (!isolate_)
return;
private_constructor_name_.Clear();
Dart_EnterScope();
private_constructor_name_.Set(
this, Dart_NewPersistentHandle(Dart_NewStringFromCString("_")));
Dart_ExitScope();
DidSetIsolate();
}
......
......@@ -49,6 +49,12 @@ class DartState : public std::enable_shared_from_this<DartState> {
Dart_Isolate isolate() { return isolate_; }
void SetIsolate(Dart_Isolate isolate);
// TODO(https://github.com/flutter/flutter/issues/50997): Work around until we
// drop the need for Dart_New in tonic.
Dart_PersistentHandle private_constructor_name() {
return private_constructor_name_.Get();
}
DartClassLibrary& class_library() { return *class_library_; }
DartMessageHandler& message_handler() { return *message_handler_; }
FileLoader& file_loader() { return *file_loader_; }
......@@ -70,6 +76,7 @@ class DartState : public std::enable_shared_from_this<DartState> {
private:
Dart_Isolate isolate_;
DartPersistentValue private_constructor_name_;
std::unique_ptr<DartClassLibrary> class_library_;
std::unique_ptr<DartMessageHandler> message_handler_;
std::unique_ptr<FileLoader> file_loader_;
......
......@@ -15,6 +15,33 @@ DartWrappable::~DartWrappable() {
TONIC_CHECK(!dart_wrapper_);
}
// TODO(dnfield): Delete this. https://github.com/flutter/flutter/issues/50997
Dart_Handle DartWrappable::CreateDartWrapper(DartState* dart_state) {
TONIC_DCHECK(!dart_wrapper_);
const DartWrapperInfo& info = GetDartWrapperInfo();
Dart_PersistentHandle type = dart_state->class_library().GetClass(info);
TONIC_DCHECK(!LogIfError(type));
Dart_Handle wrapper =
Dart_New(type, dart_state->private_constructor_name(), 0, nullptr);
TONIC_DCHECK(!LogIfError(wrapper));
Dart_Handle res = Dart_SetNativeInstanceField(
wrapper, kPeerIndex, reinterpret_cast<intptr_t>(this));
TONIC_DCHECK(!LogIfError(res));
res = Dart_SetNativeInstanceField(wrapper, kWrapperInfoIndex,
reinterpret_cast<intptr_t>(&info));
TONIC_DCHECK(!LogIfError(res));
this->RetainDartWrappableReference(); // Balanced in FinalizeDartWrapper.
dart_wrapper_ = Dart_NewWeakPersistentHandle(
wrapper, this, GetAllocationSize(), &FinalizeDartWrapper);
return wrapper;
}
void DartWrappable::AssociateWithDartWrapper(Dart_Handle wrapper) {
TONIC_DCHECK(!dart_wrapper_);
TONIC_CHECK(!LogIfError(wrapper));
......@@ -47,8 +74,7 @@ void DartWrappable::FinalizeDartWrapper(void* isolate_callback_data,
void* peer) {
DartWrappable* wrappable = reinterpret_cast<DartWrappable*>(peer);
wrappable->dart_wrapper_ = nullptr;
wrappable->ReleaseDartWrappableReference(); // Balanced in
// AssociateWithDartWrapper.
wrappable->ReleaseDartWrappableReference(); // Balanced in CreateDartWrapper.
}
size_t DartWrappable::GetAllocationSize() {
......
......@@ -43,6 +43,10 @@ class DartWrappable {
virtual void ReleaseDartWrappableReference() const = 0;
// Use this method sparingly. It follows a slower path using Dart_New.
// Prefer constructing the object in Dart code and using
// AssociateWithDartWrapper.
Dart_Handle CreateDartWrapper(DartState* dart_state);
void AssociateWithDartWrapper(Dart_Handle wrappable);
void ClearDartWrapper(); // Warning: Might delete this.
Dart_WeakPersistentHandle dart_wrapper() const { return dart_wrapper_; }
......@@ -103,23 +107,18 @@ struct DartConverter<
return Dart_Null();
if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
return Dart_HandleFromWeakPersistent(wrapper);
Log("Do not create non-primitive Dart objects from C++ code.");
TONIC_DCHECK(false);
return Dart_NewApiError("Invalid object conversion");
return val->CreateDartWrapper(DartState::Current());
}
static void SetReturnValue(Dart_NativeArguments args,
DartWrappable* val,
bool auto_scope = true) {
if (!val) {
if (!val)
Dart_SetReturnValue(args, Dart_Null());
} else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) {
else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
Dart_SetWeakHandleReturnValue(args, wrapper);
} else {
Log("Do not create non-primitive Dart objects from C++ code.");
TONIC_DCHECK(false);
}
else
Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current()));
}
static T* FromDart(Dart_Handle handle) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册