embedder_test_context.cc 8.0 KB
Newer Older
1 2 3 4
// 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.

5
#include "flutter/shell/platform/embedder/tests/embedder_test_context.h"
6 7

#include "flutter/runtime/dart_vm.h"
8
#include "flutter/shell/platform/embedder/tests/embedder_assertions.h"
9
#include "third_party/dart/runtime/bin/elf_loader.h"
10
#include "third_party/skia/include/core/SkSurface.h"
11

12
namespace flutter {
13 14
namespace testing {

15
EmbedderTestContext::EmbedderTestContext(std::string assets_path)
16
    : assets_path_(std::move(assets_path)),
17
      native_resolver_(std::make_shared<TestDartNativeResolver>()) {
18 19 20
  auto assets_dir = fml::OpenDirectory(assets_path_.c_str(), false,
                                       fml::FilePermission::kRead);

21
  if (flutter::DartVM::IsRunningPrecompiledCode()) {
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    std::string filename(assets_path_);
    filename += "/app_elf_snapshot.so";

    const uint8_t *vm_snapshot_data = nullptr,
                  *vm_snapshot_instructions = nullptr,
                  *isolate_snapshot_data = nullptr,
                  *isolate_snapshot_instructions = nullptr;
    const char* error = nullptr;

    elf_library_handle_ =
        Dart_LoadELF(filename.c_str(), /*file_offset=*/0, &error,
                     &vm_snapshot_data, &vm_snapshot_instructions,
                     &isolate_snapshot_data, &isolate_snapshot_instructions);

    if (elf_library_handle_ != nullptr) {
      vm_snapshot_data_.reset(new fml::NonOwnedMapping(vm_snapshot_data, 0));
      vm_snapshot_instructions_.reset(
          new fml::NonOwnedMapping(vm_snapshot_instructions, 0));
      isolate_snapshot_data_.reset(
          new fml::NonOwnedMapping(isolate_snapshot_data, 0));
      isolate_snapshot_instructions_.reset(
          new fml::NonOwnedMapping(isolate_snapshot_instructions, 0));
    } else {
      FML_LOG(WARNING) << "Could not load snapshot: " << error;
    }
47
  }
48 49

  isolate_create_callbacks_.push_back(
50 51
      [weak_resolver =
           std::weak_ptr<TestDartNativeResolver>{native_resolver_}]() {
52 53 54 55
        if (auto resolver = weak_resolver.lock()) {
          resolver->SetNativeResolverForIsolate();
        }
      });
56 57
}

58 59 60 61 62
EmbedderTestContext::~EmbedderTestContext() {
  if (elf_library_handle_ != nullptr) {
    Dart_UnloadELF(elf_library_handle_);
  }
}
63

64
const std::string& EmbedderTestContext::GetAssetsPath() const {
65 66 67
  return assets_path_;
}

68
const fml::Mapping* EmbedderTestContext::GetVMSnapshotData() const {
69 70 71
  return vm_snapshot_data_.get();
}

72
const fml::Mapping* EmbedderTestContext::GetVMSnapshotInstructions() const {
73 74 75
  return vm_snapshot_instructions_.get();
}

76
const fml::Mapping* EmbedderTestContext::GetIsolateSnapshotData() const {
77 78 79
  return isolate_snapshot_data_.get();
}

80 81
const fml::Mapping* EmbedderTestContext::GetIsolateSnapshotInstructions()
    const {
82 83 84
  return isolate_snapshot_instructions_.get();
}

85 86 87 88
void EmbedderTestContext::SetRootSurfaceTransformation(SkMatrix matrix) {
  root_surface_transformation_ = matrix;
}

89
void EmbedderTestContext::AddIsolateCreateCallback(fml::closure closure) {
90 91 92 93 94
  if (closure) {
    isolate_create_callbacks_.push_back(closure);
  }
}

95
VoidCallback EmbedderTestContext::GetIsolateCreateCallbackHook() {
96
  return [](void* user_data) {
97 98
    reinterpret_cast<EmbedderTestContext*>(user_data)
        ->FireIsolateCreateCallbacks();
99 100 101
  };
}

102
void EmbedderTestContext::FireIsolateCreateCallbacks() {
103 104 105 106 107
  for (auto closure : isolate_create_callbacks_) {
    closure();
  }
}

108 109
void EmbedderTestContext::AddNativeCallback(const char* name,
                                            Dart_NativeFunction function) {
110 111 112
  native_resolver_->AddNativeCallback({name}, function);
}

113
void EmbedderTestContext::SetSemanticsNodeCallback(
114 115 116 117
    SemanticsNodeCallback update_semantics_node_callback) {
  update_semantics_node_callback_ = update_semantics_node_callback;
}

118
void EmbedderTestContext::SetSemanticsCustomActionCallback(
119 120 121 122 123
    SemanticsActionCallback update_semantics_custom_action_callback) {
  update_semantics_custom_action_callback_ =
      update_semantics_custom_action_callback;
}

124
void EmbedderTestContext::SetPlatformMessageCallback(
125 126 127 128
    std::function<void(const FlutterPlatformMessage*)> callback) {
  platform_message_callback_ = callback;
}

129
void EmbedderTestContext::PlatformMessageCallback(
130 131 132 133 134 135
    const FlutterPlatformMessage* message) {
  if (platform_message_callback_) {
    platform_message_callback_(message);
  }
}

136
FlutterUpdateSemanticsNodeCallback
137
EmbedderTestContext::GetUpdateSemanticsNodeCallbackHook() {
138
  return [](const FlutterSemanticsNode* semantics_node, void* user_data) {
139
    auto context = reinterpret_cast<EmbedderTestContext*>(user_data);
140 141 142 143 144 145 146
    if (auto callback = context->update_semantics_node_callback_) {
      callback(semantics_node);
    }
  };
}

FlutterUpdateSemanticsCustomActionCallback
147
EmbedderTestContext::GetUpdateSemanticsCustomActionCallbackHook() {
148
  return [](const FlutterSemanticsCustomAction* action, void* user_data) {
149
    auto context = reinterpret_cast<EmbedderTestContext*>(user_data);
150 151 152 153 154 155
    if (auto callback = context->update_semantics_custom_action_callback_) {
      callback(action);
    }
  };
}

156 157 158
void EmbedderTestContext::SetupOpenGLSurface(SkISize surface_size) {
  FML_CHECK(!gl_surface_);
  gl_surface_ = std::make_unique<TestGLSurface>(surface_size);
159 160
}

161
bool EmbedderTestContext::GLMakeCurrent() {
162 163 164 165
  FML_CHECK(gl_surface_) << "GL surface must be initialized.";
  return gl_surface_->MakeCurrent();
}

166
bool EmbedderTestContext::GLClearCurrent() {
167 168 169 170
  FML_CHECK(gl_surface_) << "GL surface must be initialized.";
  return gl_surface_->ClearCurrent();
}

171
bool EmbedderTestContext::GLPresent() {
172
  FML_CHECK(gl_surface_) << "GL surface must be initialized.";
173
  gl_surface_present_count_++;
174

175 176
  FireRootSurfacePresentCallbackIfPresent(
      [&]() { return gl_surface_->GetRasterSurfaceSnapshot(); });
177 178 179 180 181 182

  if (!gl_surface_->Present()) {
    return false;
  }

  return true;
183 184
}

185
uint32_t EmbedderTestContext::GLGetFramebuffer() {
186 187 188 189
  FML_CHECK(gl_surface_) << "GL surface must be initialized.";
  return gl_surface_->GetFramebuffer();
}

190
bool EmbedderTestContext::GLMakeResourceCurrent() {
191 192 193 194
  FML_CHECK(gl_surface_) << "GL surface must be initialized.";
  return gl_surface_->MakeResourceCurrent();
}

195
void* EmbedderTestContext::GLGetProcAddress(const char* name) {
196 197 198 199
  FML_CHECK(gl_surface_) << "GL surface must be initialized.";
  return gl_surface_->GetProcAddress(name);
}

200 201 202 203
FlutterTransformation EmbedderTestContext::GetRootSurfaceTransformation() {
  return FlutterTransformationMake(root_surface_transformation_);
}

204
void EmbedderTestContext::SetupCompositor() {
205 206 207 208 209
  FML_CHECK(!compositor_) << "Already ssetup a compositor in this context.";
  FML_CHECK(gl_surface_)
      << "Setup the GL surface before setting up a compositor.";
  compositor_ = std::make_unique<EmbedderTestCompositor>(
      gl_surface_->GetSurfaceSize(), gl_surface_->GetGrContext());
210 211 212 213
}

EmbedderTestCompositor& EmbedderTestContext::GetCompositor() {
  FML_CHECK(compositor_)
214
      << "Accessed the compositor on a context where one was not setup. Use "
215 216 217 218 219 220 221 222 223 224 225 226 227
         "the config builder to setup a context with a custom compositor.";
  return *compositor_;
}

void EmbedderTestContext::SetNextSceneCallback(
    NextSceneCallback next_scene_callback) {
  if (compositor_) {
    compositor_->SetNextSceneCallback(next_scene_callback);
    return;
  }
  next_scene_callback_ = next_scene_callback;
}

228 229
bool EmbedderTestContext::SofwarePresent(sk_sp<SkImage> image) {
  software_surface_present_count_++;
230 231 232 233

  FireRootSurfacePresentCallbackIfPresent([image] { return image; });

  return true;
234 235 236 237 238 239 240 241 242 243
}

size_t EmbedderTestContext::GetGLSurfacePresentCount() const {
  return gl_surface_present_count_;
}

size_t EmbedderTestContext::GetSoftwareSurfacePresentCount() const {
  return software_surface_present_count_;
}

244 245 246 247 248 249 250 251 252 253
void EmbedderTestContext::FireRootSurfacePresentCallbackIfPresent(
    std::function<sk_sp<SkImage>(void)> image_callback) {
  if (!next_scene_callback_) {
    return;
  }
  auto callback = next_scene_callback_;
  next_scene_callback_ = nullptr;
  callback(image_callback());
}

254
}  // namespace testing
255
}  // namespace flutter