Drop last usages of Dart_New from engine (flutter/engine#16838)
Image Codec FrameInfo Scene/Picture toImage
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)});
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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);
|
||||
}));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user