embedder_config_builder.cc 8.7 KB
Newer Older
1 2 3 4 5 6
// 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/shell/platform/embedder/tests/embedder_config_builder.h"

7
#include "flutter/shell/platform/embedder/embedder.h"
8
#include "third_party/skia/include/core/SkBitmap.h"
9

10
namespace flutter {
11 12
namespace testing {

13
EmbedderConfigBuilder::EmbedderConfigBuilder(
14
    EmbedderTestContext& context,
15 16
    InitializationPreference preference)
    : context_(context) {
17
  project_args_.struct_size = sizeof(project_args_);
18
  project_args_.shutdown_dart_vm_when_done = true;
19 20
  project_args_.platform_message_callback =
      [](const FlutterPlatformMessage* message, void* context) {
21 22
        reinterpret_cast<EmbedderTestContext*>(context)
            ->PlatformMessageCallback(message);
23
      };
24

25
  custom_task_runners_.struct_size = sizeof(FlutterCustomTaskRunners);
26 27 28

  opengl_renderer_config_.struct_size = sizeof(FlutterOpenGLRendererConfig);
  opengl_renderer_config_.make_current = [](void* context) -> bool {
29
    return reinterpret_cast<EmbedderTestContext*>(context)->GLMakeCurrent();
30 31
  };
  opengl_renderer_config_.clear_current = [](void* context) -> bool {
32
    return reinterpret_cast<EmbedderTestContext*>(context)->GLClearCurrent();
33 34
  };
  opengl_renderer_config_.present = [](void* context) -> bool {
35
    return reinterpret_cast<EmbedderTestContext*>(context)->GLPresent();
36 37
  };
  opengl_renderer_config_.fbo_callback = [](void* context) -> uint32_t {
38
    return reinterpret_cast<EmbedderTestContext*>(context)->GLGetFramebuffer();
39 40
  };
  opengl_renderer_config_.make_resource_current = [](void* context) -> bool {
41 42
    return reinterpret_cast<EmbedderTestContext*>(context)
        ->GLMakeResourceCurrent();
43 44 45
  };
  opengl_renderer_config_.gl_proc_resolver = [](void* context,
                                                const char* name) -> void* {
46 47
    return reinterpret_cast<EmbedderTestContext*>(context)->GLGetProcAddress(
        name);
48
  };
49 50 51 52 53 54
  opengl_renderer_config_.fbo_reset_after_present = true;
  opengl_renderer_config_.surface_transformation =
      [](void* context) -> FlutterTransformation {
    return reinterpret_cast<EmbedderTestContext*>(context)
        ->GetRootSurfaceTransformation();
  };
55 56

  software_renderer_config_.struct_size = sizeof(FlutterSoftwareRendererConfig);
57
  software_renderer_config_.surface_present_callback =
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
      [](void* context, const void* allocation, size_t row_bytes,
         size_t height) {
        auto image_info =
            SkImageInfo::MakeN32Premul(SkISize::Make(row_bytes / 4, height));
        SkBitmap bitmap;
        if (!bitmap.installPixels(image_info, const_cast<void*>(allocation),
                                  row_bytes)) {
          FML_LOG(ERROR) << "Could not copy pixels for the software "
                            "composition from the engine.";
          return false;
        }
        bitmap.setImmutable();
        return reinterpret_cast<EmbedderTestContext*>(context)->SofwarePresent(
            SkImage::MakeFromBitmap(bitmap));
      };
73

74 75 76 77
  // The first argument is treated as the executable name. Don't make tests have
  // to do this manually.
  AddCommandLineArgument("embedder_unittest");

78 79 80 81
  if (preference == InitializationPreference::kInitialize) {
    SetAssetsPath();
    SetSnapshots();
    SetIsolateCreateCallbackHook();
82
    SetSemanticsCallbackHooks();
83
    AddCommandLineArgument("--disable-observatory");
84
  }
85 86 87 88
}

EmbedderConfigBuilder::~EmbedderConfigBuilder() = default;

89 90 91 92
FlutterProjectArgs& EmbedderConfigBuilder::GetProjectArgs() {
  return project_args_;
}

93
void EmbedderConfigBuilder::SetSoftwareRendererConfig(SkISize surface_size) {
94 95
  renderer_config_.type = FlutterRendererType::kSoftware;
  renderer_config_.software = software_renderer_config_;
96 97 98 99 100

  // TODO(chinmaygarde): The compositor still uses a GL surface for operation.
  // Once this is no longer the case, don't setup the GL surface when using the
  // software renderer config.
  context_.SetupOpenGLSurface(surface_size);
101 102
}

103
void EmbedderConfigBuilder::SetOpenGLRendererConfig(SkISize surface_size) {
104 105
  renderer_config_.type = FlutterRendererType::kOpenGL;
  renderer_config_.open_gl = opengl_renderer_config_;
106
  context_.SetupOpenGLSurface(surface_size);
107 108
}

109 110
void EmbedderConfigBuilder::SetAssetsPath() {
  project_args_.assets_path = context_.GetAssetsPath().c_str();
111 112
}

113 114
void EmbedderConfigBuilder::SetSnapshots() {
  if (auto mapping = context_.GetVMSnapshotData()) {
115 116 117 118
    project_args_.vm_snapshot_data = mapping->GetMapping();
    project_args_.vm_snapshot_data_size = mapping->GetSize();
  }

119
  if (auto mapping = context_.GetVMSnapshotInstructions()) {
120 121 122 123
    project_args_.vm_snapshot_instructions = mapping->GetMapping();
    project_args_.vm_snapshot_instructions_size = mapping->GetSize();
  }

124
  if (auto mapping = context_.GetIsolateSnapshotData()) {
125 126 127 128
    project_args_.isolate_snapshot_data = mapping->GetMapping();
    project_args_.isolate_snapshot_data_size = mapping->GetSize();
  }

129
  if (auto mapping = context_.GetIsolateSnapshotInstructions()) {
130 131 132 133 134
    project_args_.isolate_snapshot_instructions = mapping->GetMapping();
    project_args_.isolate_snapshot_instructions_size = mapping->GetSize();
  }
}

135 136
void EmbedderConfigBuilder::SetIsolateCreateCallbackHook() {
  project_args_.root_isolate_create_callback =
137
      EmbedderTestContext::GetIsolateCreateCallbackHook();
138 139
}

140 141
void EmbedderConfigBuilder::SetSemanticsCallbackHooks() {
  project_args_.update_semantics_node_callback =
142
      EmbedderTestContext::GetUpdateSemanticsNodeCallbackHook();
143
  project_args_.update_semantics_custom_action_callback =
144
      EmbedderTestContext::GetUpdateSemanticsCustomActionCallbackHook();
145 146
}

147 148 149 150 151 152 153 154 155
void EmbedderConfigBuilder::SetDartEntrypoint(std::string entrypoint) {
  if (entrypoint.size() == 0) {
    return;
  }

  dart_entrypoint_ = std::move(entrypoint);
  project_args_.custom_dart_entrypoint = dart_entrypoint_.c_str();
}

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
void EmbedderConfigBuilder::AddCommandLineArgument(std::string arg) {
  if (arg.size() == 0) {
    return;
  }

  command_line_arguments_.emplace_back(std::move(arg));
}

void EmbedderConfigBuilder::SetPlatformTaskRunner(
    const FlutterTaskRunnerDescription* runner) {
  if (runner == nullptr) {
    return;
  }
  custom_task_runners_.platform_task_runner = runner;
  project_args_.custom_task_runners = &custom_task_runners_;
}

173 174 175 176 177
void EmbedderConfigBuilder::SetPlatformMessageCallback(
    std::function<void(const FlutterPlatformMessage*)> callback) {
  context_.SetPlatformMessageCallback(callback);
}

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
void EmbedderConfigBuilder::SetCompositor() {
  context_.SetupCompositor();
  auto& compositor = context_.GetCompositor();
  compositor_.struct_size = sizeof(compositor_);
  compositor_.user_data = &compositor;
  compositor_.create_backing_store_callback =
      [](const FlutterBackingStoreConfig* config,  //
         FlutterBackingStore* backing_store_out,   //
         void* user_data                           //
      ) {
        return reinterpret_cast<EmbedderTestCompositor*>(user_data)
            ->CreateBackingStore(config, backing_store_out);
      };
  compositor_.collect_backing_store_callback =
      [](const FlutterBackingStore* backing_store,  //
         void* user_data                            //
      ) {
        return reinterpret_cast<EmbedderTestCompositor*>(user_data)
            ->CollectBackingStore(backing_store);
      };
  compositor_.present_layers_callback = [](const FlutterLayer** layers,  //
                                           size_t layers_count,          //
                                           void* user_data               //
                                        ) {
    return reinterpret_cast<EmbedderTestCompositor*>(user_data)->Present(
        layers,       //
        layers_count  //

    );
  };
  project_args_.compositor = &compositor_;
}

FlutterCompositor& EmbedderConfigBuilder::GetCompositor() {
  return compositor_;
}

215
UniqueEngine EmbedderConfigBuilder::LaunchEngine() const {
216
  FlutterEngine engine = nullptr;
217
  FlutterProjectArgs project_args = project_args_;
218 219 220 221 222 223 224 225 226

  std::vector<const char*> args;
  args.reserve(command_line_arguments_.size());

  for (const auto& arg : command_line_arguments_) {
    args.push_back(arg.c_str());
  }

  if (args.size() > 0) {
227 228
    project_args.command_line_argv = args.data();
    project_args.command_line_argc = args.size();
229 230 231
  } else {
    // Clear it out in case this is not the first engine launch from the
    // embedder config builder.
232 233
    project_args.command_line_argv = nullptr;
    project_args.command_line_argc = 0;
234 235
  }

236
  auto result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &renderer_config_,
237
                                 &project_args, &context_, &engine);
238 239 240 241 242 243 244 245 246

  if (result != kSuccess) {
    return {};
  }

  return UniqueEngine{engine};
}

}  // namespace testing
247
}  // namespace flutter