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/waitable_event.h"
9 #include "flutter/lib/ui/painting/canvas.h"
10 #include "flutter/lib/ui/painting/image.h"
11 #include "flutter/lib/ui/painting/picture.h"
12 #include "flutter/lib/ui/painting/picture_recorder.h"
13 #include "flutter/runtime/dart_vm.h"
14 #include "flutter/shell/common/shell_test.h"
15 #include "flutter/shell/common/thread_host.h"
16 #include "flutter/testing/testing.h"
17 
18 namespace flutter {
19 namespace testing {
20 
21 class ImageDisposeTest : public ShellTest {
22  public:
23  template <class T>
24  T* GetNativePeer(Dart_Handle handle) {
25  intptr_t peer = 0;
26  auto native_handle = Dart_GetNativeInstanceField(
27  handle, tonic::DartWrappable::kPeerIndex, &peer);
28  EXPECT_FALSE(Dart_IsError(native_handle)) << Dart_GetError(native_handle);
29  return reinterpret_cast<T*>(peer);
30  }
31 
32  // Used to wait on Dart callbacks or Shell task runner flushing
34 
35  sk_sp<SkPicture> current_picture_;
36  sk_sp<DisplayList> current_display_list_;
37  sk_sp<SkImage> current_image_;
38 };
39 
40 TEST_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  if (picture->display_list()) {
52  ASSERT_FALSE(picture->display_list()->unique());
53  current_display_list_ = picture->display_list();
54  } else {
55  ASSERT_FALSE(picture->picture()->unique());
56  current_picture_ = picture->picture();
57  }
58  current_image_ = image->image();
59  };
60 
61  auto native_finish = [&](Dart_NativeArguments args) {
63  };
64 
66  auto task_runner = CreateNewThread();
67  TaskRunners task_runners("test", // label
68  GetCurrentTaskRunner(), // platform
69  task_runner, // raster
70  task_runner, // ui
71  task_runner // io
72  );
73 
74  AddNativeCallback("CaptureImageAndPicture",
75  CREATE_NATIVE_ENTRY(native_capture_image_and_picture));
76  AddNativeCallback("Finish", CREATE_NATIVE_ENTRY(native_finish));
77 
78  std::unique_ptr<Shell> shell = CreateShell(std::move(settings), task_runners);
79 
80  ASSERT_TRUE(shell->IsSetup());
81 
82  SetViewportMetrics(shell.get(), 800, 600);
83 
84  shell->GetPlatformView()->NotifyCreated();
85 
86  auto configuration = RunConfiguration::InferFromSettings(settings);
87  configuration.SetEntrypoint("pumpImage");
88 
89  shell->RunEngine(std::move(configuration), [&](auto result) {
91  });
92 
94 
96  ASSERT_TRUE(current_image_);
97 
98  // Force a drain the SkiaUnrefQueue. The engine does this normally as frames
99  // pump, but we force it here to make the test more deterministic.
101  task_runner->PostTask([&, io_manager = shell->GetIOManager()]() {
102  io_manager->GetSkiaUnrefQueue()->Drain();
104  });
106 
107  if (current_display_list_) {
108  EXPECT_TRUE(current_display_list_->unique());
109  current_display_list_.reset();
110  } else {
111  EXPECT_TRUE(current_picture_->unique());
112  current_picture_.reset();
113  }
114 
115  EXPECT_TRUE(current_image_->unique());
116  current_image_.reset();
117 
118  shell->GetPlatformView()->NotifyDestroyed();
119  DestroyShell(std::move(shell), std::move(task_runners));
120 }
121 
122 } // namespace testing
123 } // namespace flutter
G_BEGIN_DECLS FlValue * args
fml::RefPtr< fml::TaskRunner > GetCurrentTaskRunner()
Get the task runner for the thread that the current unit-test is running on. This creates a message l...
Definition: thread_test.cc:22
fml::RefPtr< fml::TaskRunner > CreateNewThread(std::string name="")
Creates a new thread, initializes a message loop on it, and, returns its task runner to the unit-test...
Definition: thread_test.cc:26
GAsyncResult * result
static void SetViewportMetrics(Shell *shell, double width, double height)
Definition: shell_test.cc:112
static RunConfiguration InferFromSettings(const Settings &settings, fml::RefPtr< fml::TaskRunner > io_worker=nullptr)
Attempts to infer a run configuration from the settings object. This tries to create a run configurat...
void DestroyShell(std::unique_ptr< Shell > shell)
Definition: shell_test.cc:369
#define CREATE_NATIVE_ENTRY(native_entry)
Settings CreateSettingsForFixture() override
Definition: shell_test.cc:282
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)
fml::AutoResetWaitableEvent message_latch_
sk_sp< SkImage > image() const
Definition: image.h:37
void AddNativeCallback(std::string name, Dart_NativeFunction callback)
Definition: dart_fixture.cc:67
std::unique_ptr< Shell > CreateShell(Settings settings, bool simulate_vsync=false)
Definition: shell_test.cc:315