Drop last usages of Dart_New from engine (flutter/engine#16838)

Image
Codec
FrameInfo
Scene/Picture toImage
This commit is contained in:
Dan Field
2020-03-02 21:30:28 -08:00
committed by GitHub
parent cb2e877e5d
commit b41f86eb00
22 changed files with 155 additions and 221 deletions

View File

@@ -298,8 +298,6 @@ 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

View File

@@ -30,8 +30,6 @@ 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",

View File

@@ -22,14 +22,16 @@ 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) {
Future<Image> toImage(int width, int height) async {
if (width <= 0 || height <= 0) {
throw Exception('Invalid image dimensions.');
}
return _futurize((_Callback<Image> callback) => _toImage(width, height, callback));
final Image image = Image._();
await _futurize((_Callback<bool> callback) => _toImage(image, width, height, callback));
return image;
}
String _toImage(int width, int height, _Callback<Image> callback) native 'Scene_toImage';
String _toImage(Image outImage, int width, int height, _Callback<bool> callback) native 'Scene_toImage';
/// Releases the resources used by this scene.
///

View File

@@ -61,7 +61,8 @@ void Scene::dispose() {
ClearDartWrapper();
}
Dart_Handle Scene::toImage(uint32_t width,
Dart_Handle Scene::toImage(Dart_Handle image_handle,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
TRACE_EVENT0("flutter", "Scene::toImage");
@@ -75,7 +76,8 @@ Dart_Handle Scene::toImage(uint32_t width,
return tonic::ToDart("Could not flatten scene into a layer tree.");
}
return Picture::RasterizeToImage(picture, width, height, raw_image_callback);
return Picture::RasterizeToImage(image_handle, picture, width, height,
raw_image_callback);
}
std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() {

View File

@@ -32,7 +32,8 @@ class Scene : public RefCountedDartWrappable<Scene> {
std::unique_ptr<flutter::LayerTree> takeLayerTree();
Dart_Handle toImage(uint32_t width,
Dart_Handle toImage(Dart_Handle image_handle,
uint32_t width,
uint32_t height,
Dart_Handle image_callback);

View File

@@ -13,7 +13,6 @@
#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"
@@ -80,7 +79,6 @@ 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);

View File

@@ -1639,22 +1639,19 @@ typedef ImageDecoderCallback = void Function(Image result);
///
/// To obtain an instance of the [FrameInfo] interface, see
/// [Codec.getNextFrame].
@pragma('vm:entry-point')
class FrameInfo extends NativeFieldWrapperClass2 {
class FrameInfo {
/// 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].
@pragma('vm:entry-point')
FrameInfo._();
FrameInfo._(int durationMilliseconds, this.image) : duration = Duration(milliseconds: durationMilliseconds);
/// The duration this frame should be shown.
Duration get duration => Duration(milliseconds: _durationMillis);
int get _durationMillis native 'FrameInfo_durationMillis';
final Duration duration;
/// The [Image] object for this frame.
Image get image native 'FrameInfo_image';
final Image image;
}
/// A handle to an image codec.
@@ -1684,21 +1681,32 @@ 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() {
return _futurize(_getNextFrame);
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;
}
/// Returns an error message on failure, null on success.
String _getNextFrame(_Callback<FrameInfo> callback) native 'Codec_getNextFrame';
String _getNextFrame(Image outImage, _Callback<int> callback) native 'Codec_getNextFrame';
/// Release the resources used by this object. The object is no longer usable
/// after this method is called.
void dispose() native 'Codec_dispose';
void dispose() {
_cachedFrame = null;
_dispose();
}
void _dispose() native 'Codec_dispose';
}
/// Instantiates an image codec [Codec] object.
@@ -1718,10 +1726,12 @@ class Codec extends NativeFieldWrapperClass2 {
Future<Codec> instantiateImageCodec(Uint8List list, {
int targetWidth,
int targetHeight,
}) {
return _futurize(
(_Callback<Codec> callback) => _instantiateImageCodec(list, callback, null, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
);
}) async {
final Codec codec = Codec._();
await _futurize((_Callback<bool> callback) {
return _instantiateImageCodec(codec, list, callback, null, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension);
});
return codec;
}
/// Instantiates a [Codec] object for an image binary data.
@@ -1735,7 +1745,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(Uint8List list, _Callback<Codec> callback, _ImageInfo imageInfo, int targetWidth, int targetHeight)
String _instantiateImageCodec(Codec outCodec, Uint8List list, _Callback<bool> callback, _ImageInfo imageInfo, int targetWidth, int targetHeight)
native 'instantiateImageCodec';
/// Loads a single image frame from a byte array into an [Image] object.
@@ -1776,11 +1786,12 @@ void decodeImageFromPixels(
{int rowBytes, int targetWidth, int targetHeight}
) {
final _ImageInfo imageInfo = _ImageInfo(width, height, format.index, rowBytes);
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));
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));
});
}
/// Determines the winding rule that decides how the interior of a [Path] is
@@ -4125,15 +4136,17 @@ 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) {
Future<Image> toImage(int width, int height) async {
if (width <= 0 || height <= 0)
throw Exception('Invalid image dimensions.');
return _futurize(
(_Callback<Image> callback) => _toImage(width, height, callback)
final Image image = Image._();
await _futurize(
(_Callback<bool> callback) => _toImage(image, width, height, callback)
);
return image;
}
String _toImage(int width, int height, _Callback<Image> callback) native 'Picture_toImage';
String _toImage(Image outImage, int width, int height, _Callback<bool> callback) native 'Picture_toImage';
/// Release the resources used by this object. The object is no longer usable
/// after this method is called.

View File

@@ -10,7 +10,6 @@
#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"
@@ -145,13 +144,14 @@ static std::variant<ImageDecoder::ImageInfo, std::string> ConvertImageInfo(
}
static void InstantiateImageCodec(Dart_NativeArguments args) {
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
Dart_Handle codec_handle = Dart_GetNativeArgument(args, 0);
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 2);
if (!Dart_IsClosure(callback_handle)) {
Dart_SetReturnValue(args, tonic::ToDart("Callback must be a function"));
return;
}
Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 2);
Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 3);
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, 0,
tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 1,
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, 3));
const int targetHeight =
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 4));
const int targetHeight =
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 5));
std::unique_ptr<SkCodec> codec;
bool single_frame;
@@ -208,8 +208,6 @@ 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;
@@ -222,12 +220,13 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
}
descriptor.data = std::move(buffer);
ui_codec = fml::MakeRefCounted<SingleFrameCodec>(std::move(descriptor));
SingleFrameCodec::Create(codec_handle, std::move(descriptor));
} else {
ui_codec = fml::MakeRefCounted<MultiFrameCodec>(std::move(codec));
MultiFrameCodec::Create(codec_handle, std::move(codec));
}
tonic::DartInvoke(callback_handle, {ToDart(ui_codec)});
tonic::DartInvoke(callback_handle, {Dart_True()});
Dart_SetReturnValue(args, Dart_Null());
}
IMPLEMENT_WRAPPERTYPEINFO(ui, Codec);
@@ -246,7 +245,7 @@ void Codec::dispose() {
void Codec::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"instantiateImageCodec", InstantiateImageCodec, 5, true},
{"instantiateImageCodec", InstantiateImageCodec, 6, true},
});
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

View File

@@ -6,7 +6,6 @@
#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"
@@ -30,7 +29,8 @@ class Codec : public RefCountedDartWrappable<Codec> {
virtual int repetitionCount() const = 0;
virtual Dart_Handle getNextFrame(Dart_Handle callback_handle) = 0;
virtual Dart_Handle getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) = 0;
void dispose();

View File

@@ -1,30 +0,0 @@
// 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

View File

@@ -1,37 +0,0 @@
// 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_

View File

@@ -22,8 +22,10 @@ class CanvasImage final : public RefCountedDartWrappable<CanvasImage> {
public:
~CanvasImage() override;
static fml::RefPtr<CanvasImage> Create() {
return fml::MakeRefCounted<CanvasImage>();
static fml::RefPtr<CanvasImage> Create(Dart_Handle dart_handle) {
auto image = fml::MakeRefCounted<CanvasImage>();
image->AssociateWithDartWrapper(dart_handle);
return image;
}
int width() { return image_.get()->width(); }

View File

@@ -20,8 +20,11 @@ MultiFrameCodec::MultiFrameCodec(std::unique_ptr<SkCodec> codec)
MultiFrameCodec::~MultiFrameCodec() = default;
static void InvokeNextFrameCallback(
fml::RefPtr<FrameInfo> frameInfo,
sk_sp<SkImage> skImage,
fml::RefPtr<CanvasImage> canvas_image,
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) {
@@ -30,10 +33,13 @@ static void InvokeNextFrameCallback(
return;
}
tonic::DartState::Scope scope(dart_state);
if (!frameInfo) {
tonic::DartInvoke(callback->value(), {Dart_Null()});
if (skImage) {
canvas_image->set_image({skImage, std::move(unref_queue)});
tonic::DartInvoke(callback->value(),
{tonic::ToDart(skFrameInfo.fDuration)});
} else {
tonic::DartInvoke(callback->value(), {ToDart(frameInfo)});
tonic::DartInvoke(callback->value(), {Dart_Null()});
}
}
@@ -129,30 +135,32 @@ 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(
[callback = std::move(callback), frameInfo, trace_id]() mutable {
InvokeNextFrameCallback(frameInfo, std::move(callback), trace_id);
[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);
}));
}
Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) {
Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) {
static size_t trace_counter = 1;
const size_t trace_id = trace_counter++;
@@ -160,17 +168,19 @@ Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_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(
[callback = std::make_unique<DartPersistentValue>(
[canvas_image = std::move(canvas_image),
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(
std::move(callback), std::move(ui_task_runner),
canvas_image, std::move(callback), std::move(ui_task_runner),
io_manager->GetResourceContext(), io_manager->GetSkiaUnrefQueue(),
trace_id);
}));

View File

@@ -5,15 +5,23 @@
#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:
MultiFrameCodec(std::unique_ptr<SkCodec> codec);
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() override;
// |Codec|
@@ -23,9 +31,10 @@ class MultiFrameCodec : public Codec {
int repetitionCount() const override;
// |Codec|
Dart_Handle getNextFrame(Dart_Handle args) override;
Dart_Handle getNextFrame(Dart_Handle image_handle, Dart_Handle args) override;
private:
MultiFrameCodec(std::unique_ptr<SkCodec> codec);
const std::unique_ptr<SkCodec> codec_;
const int frameCount_;
const int repetitionCount_;
@@ -39,6 +48,7 @@ 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,

View File

@@ -40,14 +40,16 @@ Picture::Picture(flutter::SkiaGPUObject<SkPicture> picture)
Picture::~Picture() = default;
Dart_Handle Picture::toImage(uint32_t width,
Dart_Handle Picture::toImage(Dart_Handle image_handle,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
if (!picture_.get()) {
return tonic::ToDart("Picture is null");
}
return RasterizeToImage(picture_.get(), width, height, raw_image_callback);
return RasterizeToImage(image_handle, picture_.get(), width, height,
raw_image_callback);
}
void Picture::dispose() {
@@ -62,7 +64,8 @@ size_t Picture::GetAllocationSize() {
}
}
Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
Dart_Handle Picture::RasterizeToImage(Dart_Handle image_handle,
sk_sp<SkPicture> picture,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
@@ -74,6 +77,8 @@ Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
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);
@@ -89,7 +94,7 @@ Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
auto picture_bounds = SkISize::Make(width, height);
auto ui_task = fml::MakeCopyable([image_callback, unref_queue](
auto ui_task = fml::MakeCopyable([canvas_image, image_callback, unref_queue](
sk_sp<SkImage> raster_image) mutable {
auto dart_state = image_callback->dart_state().lock();
if (!dart_state) {
@@ -100,15 +105,14 @@ Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
if (!raster_image) {
tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
delete image_callback;
return;
}
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));
canvas_image->set_image({std::move(raster_image), std::move(unref_queue)});
// All done!
tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
tonic::DartInvoke(image_callback->Get(), {Dart_True()});
// image_callback is associated with the Dart isolate and must be deleted
// on the UI thread

View File

@@ -28,7 +28,8 @@ class Picture : public RefCountedDartWrappable<Picture> {
sk_sp<SkPicture> picture() const { return picture_.get(); }
Dart_Handle toImage(uint32_t width,
Dart_Handle toImage(Dart_Handle image_handle,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback);
@@ -38,7 +39,8 @@ class Picture : public RefCountedDartWrappable<Picture> {
static void RegisterNatives(tonic::DartLibraryNatives* natives);
static Dart_Handle RasterizeToImage(sk_sp<SkPicture> picture,
static Dart_Handle RasterizeToImage(Dart_Handle image_handle,
sk_sp<SkPicture> picture,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback);

View File

@@ -4,7 +4,6 @@
#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"
@@ -23,16 +22,20 @@ int SingleFrameCodec::repetitionCount() const {
return 0;
}
Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_handle) {
Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) {
if (!Dart_IsClosure(callback_handle)) {
return tonic::ToDart("Callback must be a function");
}
if (status_ == Status::kComplete) {
tonic::DartInvoke(callback_handle, {tonic::ToDart(cached_frame_)});
return Dart_Null();
return tonic::ToDart(
"Dart callers are responsible for caching the frame callback "
"information");
}
auto canvas_image = CanvasImage::Create(image_handle);
// This has to be valid because this method is called from Dart.
auto dart_state = UIDartState::Current();
@@ -57,7 +60,7 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_handle) {
fml::RefPtr<SingleFrameCodec>* raw_codec_ref =
new fml::RefPtr<SingleFrameCodec>(this);
decoder->Decode(descriptor_, [raw_codec_ref](auto image) {
decoder->Decode(descriptor_, [canvas_image, raw_codec_ref](auto image) {
std::unique_ptr<fml::RefPtr<SingleFrameCodec>> codec_ref(raw_codec_ref);
fml::RefPtr<SingleFrameCodec> codec(std::move(*codec_ref));
@@ -66,18 +69,14 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_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_ = fml::MakeRefCounted<FrameInfo>(
std::move(canvas_image), 0 /* duration */);
codec->cached_frame_image_size_ = canvas_image->GetAllocationSize();
}
// The cached frame is now available and should be returned to any future
@@ -85,9 +84,8 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_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(), {frame});
tonic::DartInvoke(callback.value(), {tonic::ToDart(0)});
}
codec->pending_callbacks_.clear();
});
@@ -97,17 +95,13 @@ Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_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;
const auto frame_byte_size = (cached_frame_ && cached_frame_->image())
? cached_frame_->image()->GetAllocationSize()
: 0;
return data_byte_size + frame_byte_size + sizeof(this);
return data_byte_size + cached_frame_image_size_ + sizeof(this);
}
} // namespace flutter

View File

@@ -7,15 +7,20 @@
#include "flutter/fml/macros.h"
#include "flutter/lib/ui/painting/codec.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/image_decoder.h"
namespace flutter {
class SingleFrameCodec : public Codec {
public:
SingleFrameCodec(ImageDecoder::ImageDescriptor descriptor);
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() override;
// |Codec|
@@ -25,16 +30,18 @@ class SingleFrameCodec : public Codec {
int repetitionCount() const override;
// |Codec|
Dart_Handle getNextFrame(Dart_Handle args) override;
Dart_Handle getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) override;
// |DartWrappable|
size_t GetAllocationSize() override;
private:
SingleFrameCodec(ImageDecoder::ImageDescriptor descriptor);
enum class Status { kNew, kInProgress, kComplete };
Status status_;
ImageDecoder::ImageDescriptor descriptor_;
fml::RefPtr<FrameInfo> cached_frame_;
size_t cached_frame_image_size_;
std::vector<DartPersistentValue> pending_callbacks_;
FML_FRIEND_MAKE_REF_COUNTED(SingleFrameCodec);

View File

@@ -22,7 +22,6 @@ 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)),
@@ -37,12 +36,6 @@ 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();
}

View File

@@ -49,12 +49,6 @@ 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_; }
@@ -76,7 +70,6 @@ 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_;

View File

@@ -15,33 +15,6 @@ 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));
@@ -74,7 +47,8 @@ void DartWrappable::FinalizeDartWrapper(void* isolate_callback_data,
void* peer) {
DartWrappable* wrappable = reinterpret_cast<DartWrappable*>(peer);
wrappable->dart_wrapper_ = nullptr;
wrappable->ReleaseDartWrappableReference(); // Balanced in CreateDartWrapper.
wrappable->ReleaseDartWrappableReference(); // Balanced in
// AssociateWithDartWrapper.
}
size_t DartWrappable::GetAllocationSize() {

View File

@@ -43,10 +43,6 @@ 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_; }
@@ -107,18 +103,23 @@ struct DartConverter<
return Dart_Null();
if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
return Dart_HandleFromWeakPersistent(wrapper);
return val->CreateDartWrapper(DartState::Current());
Log("Do not create non-primitive Dart objects from C++ code.");
TONIC_DCHECK(false);
return Dart_NewApiError("Invalid object conversion");
}
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
Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current()));
} else {
Log("Do not create non-primitive Dart objects from C++ code.");
TONIC_DCHECK(false);
}
}
static T* FromDart(Dart_Handle handle) {