Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

Commit

Permalink
Allow embedders to specify software renderer configs. (#6133)
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored Sep 1, 2018
1 parent da41991 commit b3c778f
Show file tree
Hide file tree
Showing 12 changed files with 620 additions and 157 deletions.
6 changes: 6 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,12 @@ FILE: ../../../flutter/shell/platform/android/platform_message_response_android.
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
FILE: ../../../flutter/shell/version/version.cc
FILE: ../../../flutter/shell/version/version.h
----------------------------------------------------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import("$flutter_root/shell/gpu/gpu.gni")
import("$flutter_root/shell/platform/embedder/embedder.gni")

shell_gpu_configuration("embedder_gpu_configuration") {
enable_software = false
enable_software = true
enable_vulkan = false
enable_gl = true
}
Expand All @@ -16,6 +16,12 @@ source_set("embedder") {
sources = [
"embedder.cc",
"embedder.h",
"embedder_surface.cc",
"embedder_surface.h",
"embedder_surface_gl.cc",
"embedder_surface_gl.h",
"embedder_surface_software.cc",
"embedder_surface_software.h",
"embedder_engine.cc",
"embedder_engine.h",
"embedder_include.c",
Expand Down
250 changes: 180 additions & 70 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
return static_cast<decltype(pointer->member)>((default_value)); \
})()

bool IsRendererValid(const FlutterRendererConfig* config) {
if (config == nullptr || config->type != kOpenGL) {
static bool IsOpenGLRendererConfigValid(const FlutterRendererConfig* config) {
if (config->type != kOpenGL) {
return false;
}

Expand All @@ -56,76 +56,68 @@ bool IsRendererValid(const FlutterRendererConfig* config) {
return true;
}

struct _FlutterPlatformMessageResponseHandle {
fml::RefPtr<blink::PlatformMessage> message;
};

FlutterResult FlutterEngineRun(size_t version,
const FlutterRendererConfig* config,
const FlutterProjectArgs* args,
void* user_data,
FlutterEngine* engine_out) {
// Step 0: Figure out arguments for shell creation.
if (version != FLUTTER_ENGINE_VERSION) {
return kInvalidLibraryVersion;
static bool IsSoftwareRendererConfigValid(const FlutterRendererConfig* config) {
if (config->type != kSoftware) {
return false;
}

if (engine_out == nullptr) {
return kInvalidArguments;
const FlutterSoftwareRendererConfig* software_config = &config->software;

if (SAFE_ACCESS(software_config, surface_present_callback, nullptr) ==
nullptr) {
return false;
}

if (args == nullptr) {
return kInvalidArguments;
return true;
}

static bool IsRendererValid(const FlutterRendererConfig* config) {
if (config == nullptr) {
return false;
}

if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr ||
SAFE_ACCESS(args, main_path, nullptr) == nullptr ||
SAFE_ACCESS(args, packages_path, nullptr) == nullptr) {
return kInvalidArguments;
switch (config->type) {
case kOpenGL:
return IsOpenGLRendererConfigValid(config);
case kSoftware:
return IsSoftwareRendererConfigValid(config);
default:
return false;
}

if (!IsRendererValid(config)) {
return kInvalidArguments;
return false;
}

static shell::Shell::CreateCallback<shell::PlatformView>
InferOpenGLPlatformViewCreationCallback(
const FlutterRendererConfig* config,
void* user_data,
shell::PlatformViewEmbedder::PlatformDispatchTable
platform_dispatch_table) {
if (config->type != kOpenGL) {
return nullptr;
}

auto make_current = [ptr = config->open_gl.make_current,
user_data]() -> bool { return ptr(user_data); };
auto gl_make_current = [ptr = config->open_gl.make_current,
user_data]() -> bool { return ptr(user_data); };

auto clear_current = [ptr = config->open_gl.clear_current,
user_data]() -> bool { return ptr(user_data); };
auto gl_clear_current = [ptr = config->open_gl.clear_current,
user_data]() -> bool { return ptr(user_data); };

auto present = [ptr = config->open_gl.present, user_data]() -> bool {
auto gl_present = [ptr = config->open_gl.present, user_data]() -> bool {
return ptr(user_data);
};

auto fbo_callback = [ptr = config->open_gl.fbo_callback,
user_data]() -> intptr_t { return ptr(user_data); };

shell::PlatformViewEmbedder::PlatformMessageResponseCallback
platform_message_response_callback = nullptr;
if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) {
platform_message_response_callback =
[ptr = args->platform_message_callback,
user_data](fml::RefPtr<blink::PlatformMessage> message) {
auto handle = new FlutterPlatformMessageResponseHandle();
const FlutterPlatformMessage incoming_message = {
sizeof(FlutterPlatformMessage), // struct_size
message->channel().c_str(), // channel
message->data().data(), // message
message->data().size(), // message_size
handle, // response_handle
};
handle->message = std::move(message);
return ptr(&incoming_message, user_data);
};
}
auto gl_fbo_callback = [ptr = config->open_gl.fbo_callback,
user_data]() -> intptr_t { return ptr(user_data); };

const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
std::function<bool()> make_resource_current_callback = nullptr;
std::function<bool()> gl_make_resource_current_callback = nullptr;
if (SAFE_ACCESS(open_gl_config, make_resource_current, nullptr) != nullptr) {
make_resource_current_callback = [ptr =
config->open_gl.make_resource_current,
user_data]() { return ptr(user_data); };
gl_make_resource_current_callback =
[ptr = config->open_gl.make_resource_current, user_data]() {
return ptr(user_data);
};
}

std::function<SkMatrix(void)> gl_surface_transformation_callback = nullptr;
Expand All @@ -149,6 +141,114 @@ FlutterResult FlutterEngineRun(size_t version,
bool fbo_reset_after_present =
SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false);

shell::EmbedderSurfaceGL::GLDispatchTable gl_dispatch_table = {
gl_make_current, // gl_make_current_callback
gl_clear_current, // gl_clear_current_callback
gl_present, // gl_present_callback
gl_fbo_callback, // gl_fbo_callback
gl_make_resource_current_callback, // gl_make_resource_current_callback
gl_surface_transformation_callback // gl_surface_transformation_callback
};

return [gl_dispatch_table, fbo_reset_after_present,
platform_dispatch_table](shell::Shell& shell) {
return std::make_unique<shell::PlatformViewEmbedder>(
shell, // delegate
shell.GetTaskRunners(), // task runners
gl_dispatch_table, // embedder GL dispatch table
fbo_reset_after_present, // fbo reset after present
platform_dispatch_table // embedder platform dispatch table
);
};
}

static shell::Shell::CreateCallback<shell::PlatformView>
InferSoftwarePlatformViewCreationCallback(
const FlutterRendererConfig* config,
void* user_data,
shell::PlatformViewEmbedder::PlatformDispatchTable
platform_dispatch_table) {
if (config->type != kSoftware) {
return nullptr;
}

auto software_present_backing_store =
[ptr = config->software.surface_present_callback, user_data](
const void* allocation, size_t row_bytes, size_t height) -> bool {
return ptr(user_data, allocation, row_bytes, height);
};

shell::EmbedderSurfaceSoftware::SoftwareDispatchTable
software_dispatch_table = {
software_present_backing_store, // required
};

return
[software_dispatch_table, platform_dispatch_table](shell::Shell& shell) {
return std::make_unique<shell::PlatformViewEmbedder>(
shell, // delegate
shell.GetTaskRunners(), // task runners
software_dispatch_table, // software dispatch table
platform_dispatch_table // platform dispatch table
);
};
}

static shell::Shell::CreateCallback<shell::PlatformView>
InferPlatformViewCreationCallback(
const FlutterRendererConfig* config,
void* user_data,
shell::PlatformViewEmbedder::PlatformDispatchTable
platform_dispatch_table) {
if (config == nullptr) {
return nullptr;
}

switch (config->type) {
case kOpenGL:
return InferOpenGLPlatformViewCreationCallback(config, user_data,
platform_dispatch_table);
case kSoftware:
return InferSoftwarePlatformViewCreationCallback(config, user_data,
platform_dispatch_table);
default:
return nullptr;
}
return nullptr;
}

struct _FlutterPlatformMessageResponseHandle {
fml::RefPtr<blink::PlatformMessage> message;
};

FlutterResult FlutterEngineRun(size_t version,
const FlutterRendererConfig* config,
const FlutterProjectArgs* args,
void* user_data,
FlutterEngine* engine_out) {
// Step 0: Figure out arguments for shell creation.
if (version != FLUTTER_ENGINE_VERSION) {
return kInvalidLibraryVersion;
}

if (engine_out == nullptr) {
return kInvalidArguments;
}

if (args == nullptr) {
return kInvalidArguments;
}

if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr ||
SAFE_ACCESS(args, main_path, nullptr) == nullptr ||
SAFE_ACCESS(args, packages_path, nullptr) == nullptr) {
return kInvalidArguments;
}

if (!IsRendererValid(config)) {
return kInvalidArguments;
}

std::string icu_data_path;
if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) {
icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr);
Expand Down Expand Up @@ -205,25 +305,35 @@ FlutterResult FlutterEngineRun(size_t version,
thread_host.io_thread->GetTaskRunner() // io
);

shell::PlatformViewEmbedder::DispatchTable dispatch_table = {
make_current, // gl_make_current_callback
clear_current, // gl_clear_current_callback
present, // gl_present_callback
fbo_callback, // gl_fbo_callback
shell::PlatformViewEmbedder::PlatformMessageResponseCallback
platform_message_response_callback = nullptr;
if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) {
platform_message_response_callback =
[ptr = args->platform_message_callback,
user_data](fml::RefPtr<blink::PlatformMessage> message) {
auto handle = new FlutterPlatformMessageResponseHandle();
const FlutterPlatformMessage incoming_message = {
sizeof(FlutterPlatformMessage), // struct_size
message->channel().c_str(), // channel
message->data().data(), // message
message->data().size(), // message_size
handle, // response_handle
};
handle->message = std::move(message);
return ptr(&incoming_message, user_data);
};
}

shell::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table = {
platform_message_response_callback, // platform_message_response_callback
make_resource_current_callback, // gl_make_resource_current_callback
gl_surface_transformation_callback // gl_surface_transformation_callback
};

shell::Shell::CreateCallback<shell::PlatformView> on_create_platform_view =
[dispatch_table, fbo_reset_after_present](shell::Shell& shell) {
return std::make_unique<shell::PlatformViewEmbedder>(
shell, // delegate
shell.GetTaskRunners(), // task runners
dispatch_table, // embedder dispatch table
fbo_reset_after_present // fbo reset after present
);
};
auto on_create_platform_view = InferPlatformViewCreationCallback(
config, user_data, platform_dispatch_table);

if (!on_create_platform_view) {
return kInvalidArguments;
}

shell::Shell::CreateCallback<shell::Rasterizer> on_create_rasterizer =
[](shell::Shell& shell) {
Expand Down
16 changes: 16 additions & 0 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ typedef enum {

typedef enum {
kOpenGL,
kSoftware,
} FlutterRendererType;

typedef struct _FlutterEngine* FlutterEngine;
Expand Down Expand Up @@ -55,6 +56,10 @@ typedef struct {
typedef bool (*BoolCallback)(void* /* user data */);
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
typedef uint32_t (*UIntCallback)(void* /* user data */);
typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,
const void* /* allocation */,
size_t /* row bytes */,
size_t /* height */);

typedef struct {
// The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Expand All @@ -74,10 +79,21 @@ typedef struct {
TransformationCallback surface_transformation;
} FlutterOpenGLRendererConfig;

typedef struct {
// The size of this struct. Must be sizeof(FlutterSoftwareRendererConfig).
size_t struct_size;
// The callback presented to the embedder to present a fully populated buffer
// to the user. The pixel format of the buffer is the native 32-bit RGBA
// format. The buffer is owned by the Flutter engine and must be copied in
// this callback if needed.
SoftwareSurfacePresentCallback surface_present_callback;
} FlutterSoftwareRendererConfig;

typedef struct {
FlutterRendererType type;
union {
FlutterOpenGLRendererConfig open_gl;
FlutterSoftwareRendererConfig software;
};
} FlutterRendererConfig;

Expand Down
13 changes: 13 additions & 0 deletions shell/platform/embedder/embedder_surface.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2018 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/embedder_surface.h"

namespace shell {

EmbedderSurface::EmbedderSurface() = default;

EmbedderSurface::~EmbedderSurface() = default;

} // namespace shell
Loading

0 comments on commit b3c778f

Please sign in to comment.