Flutter Engine
The Flutter Engine
image_dispose_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define FML_USED_ON_EMBEDDER
6
7#include "flutter/common/task_runners.h"
8#include "flutter/fml/synchronization/count_down_latch.h"
9#include "flutter/fml/synchronization/waitable_event.h"
10#include "flutter/lib/ui/painting/canvas.h"
11#include "flutter/lib/ui/painting/image.h"
12#include "flutter/lib/ui/painting/picture.h"
13#include "flutter/lib/ui/painting/picture_recorder.h"
14#include "flutter/runtime/dart_vm.h"
15#include "flutter/shell/common/shell_test.h"
16#include "flutter/shell/common/thread_host.h"
17#include "flutter/testing/testing.h"
18
19namespace flutter {
20namespace testing {
21
23 public:
24 template <class T>
26 intptr_t peer = 0;
27 auto native_handle = Dart_GetNativeInstanceField(
29 EXPECT_FALSE(Dart_IsError(native_handle)) << Dart_GetError(native_handle);
30 return reinterpret_cast<T*>(peer);
31 }
32
33 // Used to wait on Dart callbacks or Shell task runner flushing
35
38};
39
40TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) {
41 auto native_capture_image_and_picture = [&](Dart_NativeArguments args) {
42 auto image_handle = Dart_GetNativeArgument(args, 0);
43 auto native_image_handle =
44 Dart_GetField(image_handle, Dart_NewStringFromCString("_image"));
45 ASSERT_FALSE(Dart_IsError(native_image_handle))
46 << Dart_GetError(native_image_handle);
47 ASSERT_FALSE(Dart_IsNull(native_image_handle));
48 CanvasImage* image = GetNativePeer<CanvasImage>(native_image_handle);
49 Picture* picture = GetNativePeer<Picture>(Dart_GetNativeArgument(args, 1));
50 ASSERT_FALSE(image->image()->unique());
51 ASSERT_FALSE(picture->display_list()->unique());
52 current_display_list_ = picture->display_list();
53 current_image_ = image->image();
54 };
55
56 auto native_finish = [&](Dart_NativeArguments args) {
57 message_latch_.Signal();
58 };
59
60 Settings settings = CreateSettingsForFixture();
61 fml::CountDownLatch frame_latch{2};
62 settings.frame_rasterized_callback = [&frame_latch](const FrameTiming& t) {
63 frame_latch.CountDown();
64 };
65 auto task_runner = CreateNewThread();
66 TaskRunners task_runners("test", // label
67 GetCurrentTaskRunner(), // platform
68 task_runner, // raster
69 task_runner, // ui
70 task_runner // io
71 );
72
73 AddNativeCallback("CaptureImageAndPicture",
74 CREATE_NATIVE_ENTRY(native_capture_image_and_picture));
75 AddNativeCallback("Finish", CREATE_NATIVE_ENTRY(native_finish));
76
77 std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
78
79 ASSERT_TRUE(shell->IsSetup());
80
81 SetViewportMetrics(shell.get(), 800, 600);
82
83 shell->GetPlatformView()->NotifyCreated();
84
86 configuration.SetEntrypoint("pumpImage");
87
88 shell->RunEngine(std::move(configuration), [&](auto result) {
90 });
91 message_latch_.Wait();
92
93 ASSERT_TRUE(current_display_list_);
94 ASSERT_TRUE(current_image_);
95
96 // Wait for 2 frames to be rasterized. The 2nd frame releases resources of the
97 // 1st frame.
98 frame_latch.Wait();
99
100 // Force a drain the SkiaUnrefQueue. The engine does this normally as frames
101 // pump, but we force it here to make the test more deterministic.
102 message_latch_.Reset();
103 task_runner->PostTask([&, io_manager = shell->GetIOManager()]() {
104 io_manager->GetSkiaUnrefQueue()->Drain();
105 message_latch_.Signal();
106 });
107 message_latch_.Wait();
108
109 if (current_display_list_) {
110 EXPECT_TRUE(current_display_list_->unique());
111 current_display_list_.reset();
112 }
113
114 EXPECT_TRUE(current_image_->unique());
115 current_image_.reset();
116
117 shell->GetPlatformView()->NotifyDestroyed();
118 DestroyShell(std::move(shell), task_runners);
119}
120
121} // namespace testing
122} // namespace flutter
bool unique() const
Definition: SkRefCnt.h:50
static RunConfiguration InferFromSettings(const Settings &settings, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer a run configuration from the settings object. This tries to create a run configurat...
fml::AutoResetWaitableEvent message_latch_
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
fml::RefPtr< fml::TaskRunner > CreateNewThread(const std::string &name)
fml::RefPtr< fml::TaskRunner > GetCurrentTaskRunner()
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< const SkPicture > picture
Definition: SkRecords.h:299
TEST_F(DisplayListTest, Defaults)
static void SetViewportMetrics(JNIEnv *env, jobject jcaller, jlong shell_holder, jfloat devicePixelRatio, jint physicalWidth, jint physicalHeight, jint physicalPaddingTop, jint physicalPaddingRight, jint physicalPaddingBottom, jint physicalPaddingLeft, jint physicalViewInsetTop, jint physicalViewInsetRight, jint physicalViewInsetBottom, jint physicalViewInsetLeft, jint systemGestureInsetTop, jint systemGestureInsetRight, jint systemGestureInsetBottom, jint systemGestureInsetLeft, jint physicalTouchSlop, jintArray javaDisplayFeaturesBounds, jintArray javaDisplayFeaturesType, jintArray javaDisplayFeaturesState)
#define T
Definition: precompiler.cc:65
#define CREATE_NATIVE_ENTRY(native_entry)
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678