From 0c365e937a21a23262a697682d3c894c77be5cc5 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Tue, 30 Jun 2020 08:28:52 +0200 Subject: [PATCH 01/17] Add windows plugin texture support --- ci/licenses_golden/licenses_flutter | 9 ++ shell/platform/common/cpp/BUILD.gn | 1 + .../common/cpp/client_wrapper/BUILD.gn | 1 + .../client_wrapper/core_implementations.cc | 30 ++++ .../cpp/client_wrapper/core_wrapper_files.gni | 2 + .../include/flutter/plugin_registrar.h | 7 + .../include/flutter/texture_registrar.h | 44 ++++++ .../cpp/client_wrapper/plugin_registrar.cc | 6 + .../plugin_registrar_unittests.cc | 11 ++ .../testing/stub_flutter_api.cc | 39 +++++ .../client_wrapper/testing/stub_flutter_api.h | 17 +++ .../client_wrapper/texture_registrar_impl.h | 35 +++++ .../texture_registrar_unittests.cc | 143 ++++++++++++++++++ .../cpp/public/flutter_plugin_registrar.h | 6 + .../cpp/public/flutter_texture_registrar.h | 64 ++++++++ shell/platform/glfw/flutter_glfw.cc | 28 ++++ shell/platform/windows/BUILD.gn | 5 + .../testing/stub_flutter_windows_api.cc | 6 + shell/platform/windows/external_texture_gl.cc | 134 ++++++++++++++++ shell/platform/windows/external_texture_gl.h | 54 +++++++ shell/platform/windows/flutter_windows.cc | 45 ++++++ .../windows/flutter_windows_engine.cc | 11 ++ .../platform/windows/flutter_windows_engine.h | 8 + .../flutter_windows_texture_registrar.cc | 59 ++++++++ .../flutter_windows_texture_registrar.h | 53 +++++++ ...ter_windows_texture_registrar_unittests.cc | 44 ++++++ .../platform/windows/public/flutter_windows.h | 5 + 27 files changed, 867 insertions(+) mode change 100755 => 100644 ci/licenses_golden/licenses_flutter create mode 100644 shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h create mode 100644 shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h create mode 100644 shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc create mode 100644 shell/platform/common/cpp/public/flutter_texture_registrar.h create mode 100644 shell/platform/windows/external_texture_gl.cc create mode 100644 shell/platform/windows/external_texture_gl.h create mode 100644 shell/platform/windows/flutter_windows_texture_registrar.cc create mode 100644 shell/platform/windows/flutter_windows_texture_registrar.h create mode 100644 shell/platform/windows/flutter_windows_texture_registrar_unittests.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter old mode 100755 new mode 100644 index 177517471df03..adc8d864dffe5 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1666,6 +1666,7 @@ FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/ FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/standard_codec_serializer.h FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/standard_message_codec.h FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/standard_method_codec.h +FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/method_call_unittests.cc FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/method_channel_unittests.cc FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/method_result_functions_unittests.cc @@ -1674,6 +1675,8 @@ FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/plugin_registrar FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/standard_codec.cc FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/standard_message_codec_unittests.cc FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/standard_method_codec_unittests.cc +FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h +FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc FILE: ../../../flutter/shell/platform/common/cpp/engine_switches.cc FILE: ../../../flutter/shell/platform/common/cpp/engine_switches.h FILE: ../../../flutter/shell/platform/common/cpp/engine_switches_unittests.cc @@ -1691,6 +1694,7 @@ FILE: ../../../flutter/shell/platform/common/cpp/path_utils_unittests.cc FILE: ../../../flutter/shell/platform/common/cpp/public/flutter_export.h FILE: ../../../flutter/shell/platform/common/cpp/public/flutter_messenger.h FILE: ../../../flutter/shell/platform/common/cpp/public/flutter_plugin_registrar.h +FILE: ../../../flutter/shell/platform/common/cpp/public/flutter_texture_registrar.h FILE: ../../../flutter/shell/platform/common/cpp/text_input_model.cc FILE: ../../../flutter/shell/platform/common/cpp/text_input_model.h FILE: ../../../flutter/shell/platform/common/cpp/text_input_model_unittests.cc @@ -2179,6 +2183,8 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plu FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc FILE: ../../../flutter/shell/platform/windows/cursor_handler.cc FILE: ../../../flutter/shell/platform/windows/cursor_handler.h +FILE: ../../../flutter/shell/platform/windows/external_texture_gl.cc +FILE: ../../../flutter/shell/platform/windows/external_texture_gl.h FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle.cc FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle.h FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle_unittests.cc @@ -2186,6 +2192,9 @@ FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.cc FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.h FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine_unittests.cc +FILE: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar.cc +FILE: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar.h +FILE: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h FILE: ../../../flutter/shell/platform/windows/flutter_windows_win32.cc diff --git a/shell/platform/common/cpp/BUILD.gn b/shell/platform/common/cpp/BUILD.gn index d1b4888c2f9e9..36c9760c419c2 100644 --- a/shell/platform/common/cpp/BUILD.gn +++ b/shell/platform/common/cpp/BUILD.gn @@ -13,6 +13,7 @@ _public_headers = [ "public/flutter_export.h", "public/flutter_messenger.h", "public/flutter_plugin_registrar.h", + "public/flutter_texture_registrar.h", ] # Any files that are built by clients (client_wrapper code, library headers for diff --git a/shell/platform/common/cpp/client_wrapper/BUILD.gn b/shell/platform/common/cpp/client_wrapper/BUILD.gn index 719029b63257b..96a1c34177066 100644 --- a/shell/platform/common/cpp/client_wrapper/BUILD.gn +++ b/shell/platform/common/cpp/client_wrapper/BUILD.gn @@ -51,6 +51,7 @@ executable("client_wrapper_unittests") { "standard_method_codec_unittests.cc", "testing/test_codec_extensions.cc", "testing/test_codec_extensions.h", + "texture_registrar_unittests.cc", ] deps = [ diff --git a/shell/platform/common/cpp/client_wrapper/core_implementations.cc b/shell/platform/common/cpp/client_wrapper/core_implementations.cc index 21136fdb40bb5..27a2340c458cb 100644 --- a/shell/platform/common/cpp/client_wrapper/core_implementations.cc +++ b/shell/platform/common/cpp/client_wrapper/core_implementations.cc @@ -18,6 +18,7 @@ #include "binary_messenger_impl.h" #include "include/flutter/engine_method_result.h" +#include "texture_registrar_impl.h" namespace flutter { @@ -146,4 +147,33 @@ void ReplyManager::SendResponseData(const std::vector* data) { } // namespace internal +// ========== texture_registrar_impl.h ========== + +TextureRegistrarImpl::TextureRegistrarImpl( + FlutterDesktopTextureRegistrarRef texture_registrar_ref) + : texture_registrar_ref_(texture_registrar_ref) {} + +TextureRegistrarImpl::~TextureRegistrarImpl() = default; + +int64_t TextureRegistrarImpl::RegisterTexture(Texture* texture) { + FlutterDesktopTextureCallback callback = + [](size_t width, size_t height, + void* user_data) -> const FlutterDesktopPixelBuffer* { + return static_cast(user_data)->CopyPixelBuffer(width, height); + }; + int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture( + texture_registrar_ref_, callback, texture); + return texture_id; +} + +bool TextureRegistrarImpl::MarkTextureFrameAvailable(int64_t texture_id) { + return FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( + texture_registrar_ref_, texture_id); +} + +bool TextureRegistrarImpl::UnregisterTexture(int64_t texture_id) { + return FlutterDesktopTextureRegistrarUnregisterExternalTexture( + texture_registrar_ref_, texture_id); +} + } // namespace flutter diff --git a/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni b/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni index 264bf774e6111..c2ee524e0f117 100644 --- a/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni +++ b/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni @@ -24,6 +24,7 @@ core_cpp_client_wrapper_includes = "include/flutter/standard_codec_serializer.h", "include/flutter/standard_message_codec.h", "include/flutter/standard_method_codec.h", + "include/flutter/texture_registrar.h", ], "abspath") @@ -34,6 +35,7 @@ core_cpp_client_wrapper_internal_headers = get_path_info([ "binary_messenger_impl.h", "byte_buffer_streams.h", + "texture_registrar_impl.h", ], "abspath") diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h index a01b75e8c9136..3c4afa0b121ab 100644 --- a/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h @@ -13,6 +13,7 @@ #include #include "binary_messenger.h" +#include "texture_registrar.h" namespace flutter { @@ -41,6 +42,10 @@ class PluginRegistrar { // This pointer will remain valid for the lifetime of this instance. BinaryMessenger* messenger() { return messenger_.get(); } + // Returns the texture registrar to use for the plugin to render a pixel + // buffer. + TextureRegistrar* texture_registrar() { return texture_registrar_.get(); } + // Takes ownership of |plugin|. // // Plugins are not required to call this method if they have other lifetime @@ -62,6 +67,8 @@ class PluginRegistrar { std::unique_ptr messenger_; + std::unique_ptr texture_registrar_; + // Plugins registered for ownership. std::set> plugins_; }; diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h new file mode 100644 index 0000000000000..a41b8b1f8f55d --- /dev/null +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -0,0 +1,44 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_ + +#include +#include + +#include + +namespace flutter { + +// An interface used as an image source by texture widgets. +class Texture { + public: + virtual ~Texture() {} + + // Returns a FlutterDesktopPixelBuffer that contains the actual pixel data. + // The intended surface size is specified by |width| and |height|. + virtual const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width, + size_t height) = 0; +}; + +// An object keeping track of external textures. +class TextureRegistrar { + public: + virtual ~TextureRegistrar() {} + + // Registers a |texture| object and returns the ID for that texture. + virtual int64_t RegisterTexture(Texture* texture) = 0; + + // Notifies the flutter engine that the texture object corresponding + // to |texure_id| needs to render a new texture. + virtual bool MarkTextureFrameAvailable(int64_t texture_id) = 0; + + // Unregisters an existing Texture object. + virtual bool UnregisterTexture(int64_t texture_id) = 0; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_ diff --git a/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc b/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc index b5ab707c80aec..65fef5cccfa28 100644 --- a/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc +++ b/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc @@ -10,6 +10,7 @@ #include "binary_messenger_impl.h" #include "include/flutter/engine_method_result.h" #include "include/flutter/method_channel.h" +#include "texture_registrar_impl.h" namespace flutter { @@ -19,6 +20,11 @@ PluginRegistrar::PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar) : registrar_(registrar) { auto core_messenger = FlutterDesktopPluginRegistrarGetMessenger(registrar_); messenger_ = std::make_unique(core_messenger); + + auto texture_registrar = + FlutterDesktopRegistrarGetTextureRegistrar(registrar_); + texture_registrar_ = + std::make_unique(texture_registrar); } PluginRegistrar::~PluginRegistrar() { diff --git a/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc b/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc index b3a92aa67d714..c30e07a26183f 100644 --- a/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc +++ b/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc @@ -214,4 +214,15 @@ TEST(PluginRegistrarTest, ManagerRemovesOnDestruction) { nullptr); } +// Tests that the texture registrar getter returns a non-null TextureRegistrar +TEST(PluginRegistrarTest, TextureRegistrarNotNull) { + auto dummy_registrar_handle = + reinterpret_cast(1); + PluginRegistrar registrar(dummy_registrar_handle); + + TextureRegistrar* texture_registrar = registrar.texture_registrar(); + + ASSERT_NE(texture_registrar, nullptr); +} + } // namespace flutter diff --git a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc index 749f99c02443c..4eb8956b85e32 100644 --- a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc +++ b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc @@ -92,3 +92,42 @@ void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, s_stub_implementation->MessengerSetCallback(channel, callback, user_data); } } + +FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + return reinterpret_cast(1); +} + +int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterDesktopTextureCallback texture_callback, + void* user_data) { + uint64_t result = -1; + if (s_stub_implementation) { + result = s_stub_implementation->TextureRegistrarRegisterExternalTexture( + texture_callback, user_data); + } + return result; +} + +bool FlutterDesktopTextureRegistrarUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + bool result = false; + if (s_stub_implementation) { + result = s_stub_implementation->TextureRegistrarUnregisterExternalTexture( + texture_id); + } + return result; +} + +bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + bool result = false; + if (s_stub_implementation) { + result = s_stub_implementation->TextureRegistrarMarkTextureFrameAvailable( + texture_id); + } + return result; +} diff --git a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h index d7b966740fded..7837bbc01dd08 100644 --- a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h +++ b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h @@ -64,6 +64,23 @@ class StubFlutterApi { virtual void MessengerSetCallback(const char* channel, FlutterDesktopMessageCallback callback, void* user_data) {} + + // Called for FlutterDesktopRegisterExternalTexture. + virtual int64_t TextureRegistrarRegisterExternalTexture( + FlutterDesktopTextureCallback texture_callback, + void* user_data) { + return -1; + } + + // Called for FlutterDesktopUnregisterExternalTexture. + virtual bool TextureRegistrarUnregisterExternalTexture(int64_t texture_id) { + return false; + } + + // Called for FlutterDesktopMarkExternalTextureFrameAvailable. + virtual bool TextureRegistrarMarkTextureFrameAvailable(int64_t texture_id) { + return false; + } }; // A test helper that owns a stub implementation, making it the test stub for diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h b/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h new file mode 100644 index 0000000000000..7e1d95a994b6e --- /dev/null +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h @@ -0,0 +1,35 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_TEXTURE_REGISTRAR_IMPL_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_TEXTURE_REGISTRAR_IMPL_H_ + +#include "include/flutter/texture_registrar.h" + +namespace flutter { + +// Wrapper around a FlutterDesktopTextureRegistrarRef that implements the +// TextureRegistrar API. +class TextureRegistrarImpl : public TextureRegistrar { + public: + explicit TextureRegistrarImpl( + FlutterDesktopTextureRegistrarRef texture_registrar_ref); + virtual ~TextureRegistrarImpl(); + + // Prevent copying. + TextureRegistrarImpl(TextureRegistrarImpl const&) = delete; + TextureRegistrarImpl& operator=(TextureRegistrarImpl const&) = delete; + + int64_t RegisterTexture(Texture* texture) override; + bool MarkTextureFrameAvailable(int64_t texture_id) override; + bool UnregisterTexture(int64_t texture_id) override; + + private: + // Handle for interacting with the C API. + FlutterDesktopTextureRegistrarRef texture_registrar_ref_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_TEXTURE_REGISTRAR_IMPL_H_ diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc new file mode 100644 index 0000000000000..e34748eed63c6 --- /dev/null +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc @@ -0,0 +1,143 @@ +// 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 +#include +#include + +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h" +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h" +#include "flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h" +#include "gtest/gtest.h" + +namespace flutter { + +namespace { + +// Stub implementation to validate calls to the API. +class TestApi : public testing::StubFlutterApi { + public: + struct FakeTexture { + int64_t texture_id; + int32_t mark_count; + FlutterDesktopTextureCallback texture_callback; + void* user_data; + }; + + public: + int64_t TextureRegistrarRegisterExternalTexture( + FlutterDesktopTextureCallback texture_callback, + void* user_data) override { + last_texture_id_++; + + auto texture = std::make_unique(); + texture->texture_callback = texture_callback; + texture->user_data = user_data; + texture->mark_count = 0; + texture->texture_id = last_texture_id_; + + textures_[last_texture_id_] = std::move(texture); + return last_texture_id_; + } + + bool TextureRegistrarUnregisterExternalTexture(int64_t texture_id) override { + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + textures_.erase(it); + return true; + } + return false; + } + + bool TextureRegistrarMarkTextureFrameAvailable(int64_t texture_id) override { + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + it->second->mark_count++; + return true; + } + return false; + } + + FakeTexture* GetFakeTexture(int64_t texture_id) { + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + return it->second.get(); + } + return nullptr; + } + + int64_t last_texture_id() { return last_texture_id_; } + + size_t textures_size() { return textures_.size(); } + + private: + int64_t last_texture_id_ = -1; + std::map> textures_; +}; + +} // namespace + +// Tests thats textures can be registered and unregistered. +TEST(TextureRegistrarTest, RegisterUnregisterTexture) { + testing::ScopedStubFlutterApi scoped_api_stub(std::make_unique()); + auto test_api = static_cast(scoped_api_stub.stub()); + + auto dummy_registrar_handle = + reinterpret_cast(1); + PluginRegistrar registrar(dummy_registrar_handle); + TextureRegistrar* textures = registrar.texture_registrar(); + ASSERT_NE(textures, nullptr); + + EXPECT_EQ(test_api->last_texture_id(), -1); + auto texture = test_api->GetFakeTexture(0); + EXPECT_EQ(texture, nullptr); + + int64_t texture_id = textures->RegisterTexture(reinterpret_cast(2)); + EXPECT_EQ(test_api->last_texture_id(), texture_id); + EXPECT_EQ(test_api->textures_size(), static_cast(1)); + + texture = test_api->GetFakeTexture(texture_id); + EXPECT_EQ(texture->texture_id, texture_id); + EXPECT_EQ(texture->user_data, reinterpret_cast(2)); + + textures->MarkTextureFrameAvailable(texture_id); + textures->MarkTextureFrameAvailable(texture_id); + bool success = textures->MarkTextureFrameAvailable(texture_id); + EXPECT_TRUE(success); + EXPECT_EQ(texture->mark_count, 3); + + success = textures->UnregisterTexture(texture_id); + EXPECT_TRUE(success); + + texture = test_api->GetFakeTexture(texture_id); + EXPECT_EQ(texture, nullptr); + EXPECT_EQ(test_api->textures_size(), static_cast(0)); +} + +// Tests that unregistering a texture with an unknown id returns false. +TEST(TextureRegistrarTest, UnregisterInvalidTexture) { + auto dummy_registrar_handle = + reinterpret_cast(1); + PluginRegistrar registrar(dummy_registrar_handle); + + TextureRegistrar* textures = registrar.texture_registrar(); + + bool success = textures->UnregisterTexture(42); + EXPECT_FALSE(success); +} + +// Tests that claiming a new frame being available for an unknown texture +// returns false. +TEST(TextureRegistrarTest, MarkFrameAvailableInvalidTexture) { + auto dummy_registrar_handle = + reinterpret_cast(1); + PluginRegistrar registrar(dummy_registrar_handle); + + TextureRegistrar* textures = registrar.texture_registrar(); + + bool success = textures->MarkTextureFrameAvailable(42); + EXPECT_FALSE(success); +} + +} // namespace flutter diff --git a/shell/platform/common/cpp/public/flutter_plugin_registrar.h b/shell/platform/common/cpp/public/flutter_plugin_registrar.h index 5287a00ec5c69..820b134177afd 100644 --- a/shell/platform/common/cpp/public/flutter_plugin_registrar.h +++ b/shell/platform/common/cpp/public/flutter_plugin_registrar.h @@ -10,6 +10,7 @@ #include "flutter_export.h" #include "flutter_messenger.h" +#include "flutter_texture_registrar.h" #if defined(__cplusplus) extern "C" { @@ -27,6 +28,11 @@ FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopPluginRegistrarGetMessenger( FlutterDesktopPluginRegistrarRef registrar); +// Returns the texture registrar associated with this registrar. +FLUTTER_EXPORT FlutterDesktopTextureRegistrarRef +FlutterDesktopRegistrarGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + // Registers a callback to be called when the plugin registrar is destroyed. FLUTTER_EXPORT void FlutterDesktopPluginRegistrarSetDestructionHandler( FlutterDesktopPluginRegistrarRef registrar, diff --git a/shell/platform/common/cpp/public/flutter_texture_registrar.h b/shell/platform/common/cpp/public/flutter_texture_registrar.h new file mode 100644 index 0000000000000..cfd6b6815573b --- /dev/null +++ b/shell/platform/common/cpp/public/flutter_texture_registrar.h @@ -0,0 +1,64 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_TEXTURE_REGISTRAR_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_TEXTURE_REGISTRAR_H_ + +#include +#include + +#include "flutter_export.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +struct FlutterDesktopTextureRegistrar; +// Opaque reference to a texture registrar. +typedef struct FlutterDesktopTextureRegistrar* + FlutterDesktopTextureRegistrarRef; + +// An image buffer object. +typedef struct { + // The pixel data buffer. + const uint8_t* buffer; + // Width of the pixel buffer. + size_t width; + // Height of the pixel buffer. + size_t height; +} FlutterDesktopPixelBuffer; + +// The pixel buffer copy callback definition provided to +// the Flutter engine to copy the texture. +typedef const FlutterDesktopPixelBuffer* (*FlutterDesktopTextureCallback)( + size_t width, + size_t height, + void* user_data); + +// Registers a new texture with the Flutter engine and returns the texture ID, +// The engine will use the |texture_callback| +// function to copy the pixel buffer from the caller. +FLUTTER_EXPORT int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterDesktopTextureCallback texture_callback, + void* user_data); + +// Unregisters an existing texture from the Flutter engine for a |texture_id|. +// Returns true on success or false if the specified texture doesn't exist. +FLUTTER_EXPORT bool FlutterDesktopTextureRegistrarUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id); + +// Marks that a new texture frame is available for a given |texture_id|. +// Returns true on success or false if the specified texture doesn't exist. +FLUTTER_EXPORT bool +FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_TEXTURE_REGISTRAR_H_ diff --git a/shell/platform/glfw/flutter_glfw.cc b/shell/platform/glfw/flutter_glfw.cc index 423e5a80b6f31..43dbdfce5016c 100644 --- a/shell/platform/glfw/flutter_glfw.cc +++ b/shell/platform/glfw/flutter_glfw.cc @@ -1072,3 +1072,31 @@ void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, messenger->engine->message_dispatcher->SetMessageCallback(channel, callback, user_data); } + +FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + std::cerr << "GLFW Texture support is not implemented yet." << std::endl; + return nullptr; +} + +int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterDesktopTextureCallback texture_callback, + void* user_data) { + std::cerr << "GLFW Texture support is not implemented yet." << std::endl; + return -1; +} + +bool FlutterDesktopTextureRegistrarUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + std::cerr << "GLFW Texture support is not implemented yet." << std::endl; + return false; +} + +bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + std::cerr << "GLFW Texture support is not implemented yet." << std::endl; + return false; +} diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index 873125ad4ebef..6baf2996ce237 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -48,11 +48,15 @@ source_set("flutter_windows_source") { "angle_surface_manager.h", "cursor_handler.cc", "cursor_handler.h", + "external_texture_gl.cc", + "external_texture_gl.h", "flutter_project_bundle.cc", "flutter_project_bundle.h", "flutter_windows.cc", "flutter_windows_engine.cc", "flutter_windows_engine.h", + "flutter_windows_texture_registrar.cc", + "flutter_windows_texture_registrar.h", "flutter_windows_view.cc", "flutter_windows_view.h", "key_event_handler.cc", @@ -160,6 +164,7 @@ if (target_os == "winuwp") { sources = [ "flutter_project_bundle_unittests.cc", "flutter_windows_engine_unittests.cc", + "flutter_windows_texture_registrar_unittests.cc", "string_conversion_unittests.cc", "system_utils_unittests.cc", "testing/engine_embedder_api_modifier.h", diff --git a/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc b/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc index afe35b8f88911..1a292c04a41f1 100644 --- a/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc +++ b/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc @@ -127,6 +127,12 @@ FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger( return reinterpret_cast(2); } +FlutterDesktopTextureRegistrarRef FlutterDesktopEngineGetTextureRegistrar( + FlutterDesktopEngineRef engine) { + // The stub ignores this, so just return an arbitrary non-zero value. + return reinterpret_cast(3); +} + HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) { if (s_stub_implementation) { return s_stub_implementation->ViewGetHWND(); diff --git a/shell/platform/windows/external_texture_gl.cc b/shell/platform/windows/external_texture_gl.cc new file mode 100644 index 0000000000000..edcd3fd49ec4e --- /dev/null +++ b/shell/platform/windows/external_texture_gl.cc @@ -0,0 +1,134 @@ +// 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/windows/external_texture_gl.h" + +#include +#include +#include + +#include + +namespace { + +typedef void (*glGenTexturesProc)(GLsizei n, GLuint* textures); +typedef void (*glDeleteTexturesProc)(GLsizei n, const GLuint* textures); +typedef void (*glBindTextureProc)(GLenum target, GLuint texture); +typedef void (*glTexParameteriProc)(GLenum target, GLenum pname, GLint param); +typedef void (*glTexImage2DProc)(GLenum target, + GLint level, + GLint internalformat, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const void* data); + +// A struct containing pointers to resolved gl* functions. +struct GlProcs { + glGenTexturesProc glGenTextures; + glDeleteTexturesProc glDeleteTextures; + glBindTextureProc glBindTexture; + glTexParameteriProc glTexParameteri; + glTexImage2DProc glTexImage2D; + bool valid; +}; + +static const GlProcs& GlProcs() { + static struct GlProcs procs = {}; + static bool initialized = false; + if (!initialized) { + procs.glGenTextures = + reinterpret_cast(eglGetProcAddress("glGenTextures")); + procs.glDeleteTextures = reinterpret_cast( + eglGetProcAddress("glDeleteTextures")); + procs.glBindTexture = + reinterpret_cast(eglGetProcAddress("glBindTexture")); + procs.glTexParameteri = reinterpret_cast( + eglGetProcAddress("glTexParameteri")); + procs.glTexImage2D = + reinterpret_cast(eglGetProcAddress("glTexImage2D")); + + procs.valid = procs.glGenTextures && procs.glDeleteTextures && + procs.glBindTexture && procs.glTexParameteri && + procs.glTexImage2D; + initialized = true; + } + return procs; +} + +} // namespace + +namespace flutter { + +struct ExternalTextureGLState { + GLuint gl_texture = 0; +}; + +ExternalTextureGL::ExternalTextureGL( + FlutterDesktopTextureCallback texture_callback, + void* user_data) + : state_(std::make_unique()), + texture_callback_(texture_callback), + user_data_(user_data) {} + +ExternalTextureGL::~ExternalTextureGL() { + const auto& gl = GlProcs(); + if (gl.valid && state_->gl_texture != 0) { + gl.glDeleteTextures(1, &state_->gl_texture); + } +} + +bool ExternalTextureGL::PopulateTexture(size_t width, + size_t height, + FlutterOpenGLTexture* opengl_texture) { + if (!CopyPixelBuffer(width, height)) { + std::cerr << "Failed to copy pixel buffer from provider." << std::endl; + return false; + } + + // Populate the texture object used by the engine. + opengl_texture->target = GL_TEXTURE_2D; + opengl_texture->name = state_->gl_texture; + opengl_texture->format = GL_RGBA8; + opengl_texture->destruction_callback = nullptr; + opengl_texture->user_data = nullptr; + opengl_texture->width = width; + opengl_texture->height = height; + + return true; +} + +bool ExternalTextureGL::CopyPixelBuffer(size_t& width, size_t& height) { + const FlutterDesktopPixelBuffer* pixel_buffer = + texture_callback_(width, height, user_data_); + const auto& gl = GlProcs(); + if (!gl.valid || !pixel_buffer || !pixel_buffer->buffer) { + return false; + } + width = pixel_buffer->width; + height = pixel_buffer->height; + + if (state_->gl_texture == 0) { + gl.glGenTextures(1, &state_->gl_texture); + + gl.glBindTexture(GL_TEXTURE_2D, state_->gl_texture); + + gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + } else { + gl.glBindTexture(GL_TEXTURE_2D, state_->gl_texture); + } + gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixel_buffer->width, + pixel_buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixel_buffer->buffer); + return true; +} + +} // namespace flutter diff --git a/shell/platform/windows/external_texture_gl.h b/shell/platform/windows/external_texture_gl.h new file mode 100644 index 0000000000000..4d473e5f60365 --- /dev/null +++ b/shell/platform/windows/external_texture_gl.h @@ -0,0 +1,54 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_GL_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_GL_H_ + +#include + +#include + +#include "flutter/shell/platform/common/cpp/public/flutter_texture_registrar.h" +#include "flutter/shell/platform/embedder/embedder.h" + +namespace flutter { + +typedef struct ExternalTextureGLState ExternalTextureGLState; + +// An abstraction of an OpenGL texture. +class ExternalTextureGL { + public: + ExternalTextureGL(FlutterDesktopTextureCallback texture_callback, + void* user_data); + + virtual ~ExternalTextureGL(); + + // Returns the unique id of this texture. + int64_t texture_id() { return reinterpret_cast(this); } + + // Attempts to populate the specified |opengl_texture| with texture details + // such as the name, width, height and the pixel format upon successfully + // copying the buffer provided by |texture_callback_|. See |CopyPixelBuffer|. + // Returns true on success or false if the pixel buffer could not be copied. + bool PopulateTexture(size_t width, + size_t height, + FlutterOpenGLTexture* opengl_texture); + + private: + // Attempts to copy the pixel buffer returned by |texture_callback_| to + // OpenGL. + // The |width| and |height| will be set to the actual bounds of the copied + // pixel buffer. + // Returns true on success or false if the pixel buffer returned + // by |texture_callback_| was invalid. + bool CopyPixelBuffer(size_t& width, size_t& height); + + std::unique_ptr state_; + FlutterDesktopTextureCallback texture_callback_ = nullptr; + void* user_data_ = nullptr; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_GL_H_ diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index 177d103f7bc30..969732fb68a02 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -49,6 +49,18 @@ static FlutterDesktopViewRef HandleForView(flutter::FlutterWindowsView* view) { return reinterpret_cast(view); } +// Returns the texture registrar corresponding to the given opaque API handle. +static flutter::FlutterWindowsTextureRegistrar* TextureRegistrarFromHandle( + FlutterDesktopTextureRegistrarRef ref) { + return reinterpret_cast(ref); +} + +// Returns the opaque API handle for the given texture registrar instance. +static FlutterDesktopTextureRegistrarRef HandleForTextureRegistrar( + flutter::FlutterWindowsTextureRegistrar* registrar) { + return reinterpret_cast(registrar); +} + void FlutterDesktopViewControllerDestroy( FlutterDesktopViewControllerRef controller) { delete controller; @@ -105,6 +117,12 @@ FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger( return EngineFromHandle(engine)->messenger(); } +FlutterDesktopTextureRegistrarRef FlutterDesktopEngineGetTextureRegistrar( + FlutterDesktopEngineRef engine) { + return HandleForTextureRegistrar( + EngineFromHandle(engine)->texture_registrar()); +} + HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view) { return std::get(*ViewFromHandle(view)->GetRenderTarget()); } @@ -171,3 +189,30 @@ void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, messenger->engine->message_dispatcher()->SetMessageCallback(channel, callback, user_data); } + +FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + return HandleForTextureRegistrar(registrar->engine->texture_registrar()); +} + +int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterDesktopTextureCallback texture_callback, + void* user_data) { + return TextureRegistrarFromHandle(texture_registrar) + ->RegisterTexture(texture_callback, user_data); +} + +bool FlutterDesktopTextureRegistrarUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + return TextureRegistrarFromHandle(texture_registrar) + ->UnregisterTexture(texture_id); +} + +bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + return TextureRegistrarFromHandle(texture_registrar) + ->MarkTextureFrameAvailable(texture_id); +} diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index a284baa6f9da9..35567245d0cfd 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -62,6 +62,16 @@ FlutterRendererConfig GetRendererConfig() { } return host->view()->MakeResourceCurrent(); }; + config.open_gl.gl_external_texture_frame_callback = + [](void* user_data, int64_t texture_id, size_t width, size_t height, + FlutterOpenGLTexture* texture) -> bool { + auto host = static_cast(user_data); + if (!host->texture_registrar()) { + return false; + } + return host->texture_registrar()->PopulateTexture(texture_id, width, height, + texture); + }; return config; } @@ -122,6 +132,7 @@ FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project) messenger_wrapper_ = std::make_unique(messenger_.get()); message_dispatcher_ = std::make_unique(messenger_.get()); + texture_registrar_ = std::make_unique(this); #ifndef WINUWP window_proc_delegate_manager_ = std::make_unique(); diff --git a/shell/platform/windows/flutter_windows_engine.h b/shell/platform/windows/flutter_windows_engine.h index 86fe2c9a20978..337ea6a09cce2 100644 --- a/shell/platform/windows/flutter_windows_engine.h +++ b/shell/platform/windows/flutter_windows_engine.h @@ -15,6 +15,7 @@ #include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/windows/flutter_project_bundle.h" +#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h" #include "flutter/shell/platform/windows/public/flutter_windows.h" #include "flutter/shell/platform/windows/task_runner.h" #include "flutter/shell/platform/windows/window_state.h" @@ -80,6 +81,10 @@ class FlutterWindowsEngine { TaskRunner* task_runner() { return task_runner_.get(); } + FlutterWindowsTextureRegistrar* texture_registrar() { + return texture_registrar_.get(); + } + #ifndef WINUWP Win32WindowProcDelegateManager* window_proc_delegate_manager() { return window_proc_delegate_manager_.get(); @@ -151,6 +156,9 @@ class FlutterWindowsEngine { // The plugin registrar handle given to API clients. std::unique_ptr plugin_registrar_; + // The texture registrar. + std::unique_ptr texture_registrar_; + // The MethodChannel used for communication with the Flutter engine. std::unique_ptr> settings_channel_; diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc new file mode 100644 index 0000000000000..9b6624dcac44e --- /dev/null +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -0,0 +1,59 @@ +// 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/windows/flutter_windows_texture_registrar.h" + +#include "flutter/shell/platform/windows/flutter_windows_engine.h" + +namespace flutter { + +FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar( + FlutterWindowsEngine* engine) + : engine_(engine) {} + +int64_t FlutterWindowsTextureRegistrar::RegisterTexture( + FlutterDesktopTextureCallback texture_callback, + void* user_data) { + auto texture_gl = + std::make_unique(texture_callback, user_data); + + int64_t texture_id = texture_gl->texture_id(); + textures_[texture_id] = std::move(texture_gl); + + if (FlutterEngineRegisterExternalTexture(engine_->engine(), texture_id) == + kSuccess) { + return texture_id; + } + + return -1; +} + +bool FlutterWindowsTextureRegistrar::UnregisterTexture(int64_t texture_id) { + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + textures_.erase(it); + } + return (FlutterEngineUnregisterExternalTexture(engine_->engine(), + texture_id) == kSuccess); +} + +bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( + int64_t texture_id) { + return (FlutterEngineMarkExternalTextureFrameAvailable( + engine_->engine(), texture_id) == kSuccess); +} + +bool FlutterWindowsTextureRegistrar::PopulateTexture( + int64_t texture_id, + size_t width, + size_t height, + FlutterOpenGLTexture* texture) { + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + return it->second->PopulateTexture(width, height, texture); + } + return false; +} + +}; // namespace flutter diff --git a/shell/platform/windows/flutter_windows_texture_registrar.h b/shell/platform/windows/flutter_windows_texture_registrar.h new file mode 100644 index 0000000000000..908806e2183f3 --- /dev/null +++ b/shell/platform/windows/flutter_windows_texture_registrar.h @@ -0,0 +1,53 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_TEXTURE_REGISTRAR_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_TEXTURE_REGISTRAR_H_ + +#include +#include + +#include "flutter/shell/platform/windows/external_texture_gl.h" + +namespace flutter { + +class FlutterWindowsEngine; + +// An object managing the registration of an external texture. +class FlutterWindowsTextureRegistrar { + public: + explicit FlutterWindowsTextureRegistrar(FlutterWindowsEngine* engine); + + // Registers a texture whose pixel data will be obtained using the + // specified |texture_callback| + // Returns the non-zero, positive texture id or -1 on error. + int64_t RegisterTexture(FlutterDesktopTextureCallback texture_callback, + void* user_data); + + // Attempts to unregister the texture identified by |texture_id|. + // Returns true if the texture was successfully unregistered. + bool UnregisterTexture(int64_t texture_id); + + // Notifies the engine about a new frame being available. + // Returns true on success. + bool MarkTextureFrameAvailable(int64_t texture_id); + + // Attempts to populate the given |texture| by copying the + // contents of the texture identified by |texture_id|. + // Returns true on success. + bool PopulateTexture(int64_t texture_id, + size_t width, + size_t height, + FlutterOpenGLTexture* texture); + + private: + FlutterWindowsEngine* engine_ = nullptr; + + // All registered textures, keyed by their IDs. + std::map> textures_; +}; + +}; // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_TEXTURE_REGISTRAR_H_ diff --git a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc new file mode 100644 index 0000000000000..4c3df7f83c238 --- /dev/null +++ b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc @@ -0,0 +1,44 @@ +// 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 + +#include "flutter/shell/platform/windows/flutter_windows_engine.h" +#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) { + FlutterDesktopEngineProperties props = {}; + props.assets_path = L"FakeAssets"; + props.icu_data_path = L"icudtl.dat"; + + FlutterProjectBundle bundle(props); + FlutterWindowsEngine engine(bundle); + + FlutterWindowsTextureRegistrar registrar(&engine); + + EXPECT_TRUE(true); +} + +TEST(FlutterWindowsTextureRegistrarTest, PopulateInvalidTexture) { + FlutterDesktopEngineProperties props = {}; + props.assets_path = L"FakeAssets"; + props.icu_data_path = L"icudtl.dat"; + + FlutterProjectBundle bundle(props); + FlutterWindowsEngine engine(bundle); + + FlutterWindowsTextureRegistrar registrar(&engine); + auto result = registrar.PopulateTexture(1, 640, 480, nullptr); + EXPECT_FALSE(result); +} + +// TODO Add additional tests for testing actual texture registration using +// FlutterEngineRegisterExternalTexture + +} // namespace testing +} // namespace flutter diff --git a/shell/platform/windows/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index dbcaf8df17035..a79c357bdbeed 100644 --- a/shell/platform/windows/public/flutter_windows.h +++ b/shell/platform/windows/public/flutter_windows.h @@ -159,6 +159,11 @@ FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine, FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger(FlutterDesktopEngineRef engine); +// Returns the texture registrar associated with the engine. +FLUTTER_EXPORT FlutterDesktopTextureRegistrarRef +FlutterDesktopEngineGetTextureRegistrar( + FlutterDesktopTextureRegistrarRef texture_registrar); + // ========== View ========== // Return backing HWND for manipulation in host application. From f07da6f8d358f2b83fdf49ca4c7aa76e75e88ce6 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Tue, 17 Nov 2020 15:22:19 +0100 Subject: [PATCH 02/17] [windows] Rename Texture to PixelBufferTexture and make it a variant --- .../client_wrapper/core_implementations.cc | 32 ++++-- .../include/flutter/texture_registrar.h | 24 +++- .../testing/stub_flutter_api.cc | 7 +- .../client_wrapper/testing/stub_flutter_api.h | 3 +- .../client_wrapper/texture_registrar_impl.h | 2 +- .../texture_registrar_unittests.cc | 32 ++++-- .../cpp/public/flutter_texture_registrar.h | 35 ++++-- shell/platform/glfw/flutter_glfw.cc | 3 +- shell/platform/windows/external_texture_gl.cc | 2 +- shell/platform/windows/external_texture_gl.h | 4 +- shell/platform/windows/flutter_windows.cc | 5 +- .../windows/flutter_windows_engine.cc | 16 +++ .../platform/windows/flutter_windows_engine.h | 10 ++ .../flutter_windows_texture_registrar.cc | 30 +++-- .../flutter_windows_texture_registrar.h | 6 +- ...ter_windows_texture_registrar_unittests.cc | 106 +++++++++++++++--- 16 files changed, 238 insertions(+), 79 deletions(-) diff --git a/shell/platform/common/cpp/client_wrapper/core_implementations.cc b/shell/platform/common/cpp/client_wrapper/core_implementations.cc index 27a2340c458cb..0188787823886 100644 --- a/shell/platform/common/cpp/client_wrapper/core_implementations.cc +++ b/shell/platform/common/cpp/client_wrapper/core_implementations.cc @@ -15,6 +15,7 @@ #include #include +#include #include "binary_messenger_impl.h" #include "include/flutter/engine_method_result.h" @@ -155,16 +156,27 @@ TextureRegistrarImpl::TextureRegistrarImpl( TextureRegistrarImpl::~TextureRegistrarImpl() = default; -int64_t TextureRegistrarImpl::RegisterTexture(Texture* texture) { - FlutterDesktopTextureCallback callback = - [](size_t width, size_t height, - void* user_data) -> const FlutterDesktopPixelBuffer* { - return static_cast(user_data)->CopyPixelBuffer(width, height); - }; - int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture( - texture_registrar_ref_, callback, texture); - return texture_id; -} +int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) { + if (auto pixel_buffer_texture = std::get_if(texture)) { + FlutterDesktopTextureInfo info = {}; + info.type = kFlutterDesktopPixelBufferTexture; + info.pixel_buffer.user_data = pixel_buffer_texture; + info.pixel_buffer.callback = + [](size_t width, size_t height, + void* user_data) -> const FlutterDesktopPixelBuffer* { + auto texture = static_cast(user_data); + auto buffer = texture->delegate()->CopyPixelBuffer(width, height); + return buffer; + }; + + int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture( + texture_registrar_ref_, &info); + return texture_id; + } + + std::cerr << "Attempting to register unknown texture variant." << std::endl; + return -1; +} // namespace flutter bool TextureRegistrarImpl::MarkTextureFrameAvailable(int64_t texture_id) { return FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h index a41b8b1f8f55d..53962f31582f0 100644 --- a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -9,13 +9,14 @@ #include #include +#include namespace flutter { -// An interface used as an image source by texture widgets. -class Texture { +// An interface used as an image source by pixel buffer textures. +class PixelBufferTextureDelegate { public: - virtual ~Texture() {} + virtual ~PixelBufferTextureDelegate() = default; // Returns a FlutterDesktopPixelBuffer that contains the actual pixel data. // The intended surface size is specified by |width| and |height|. @@ -23,13 +24,26 @@ class Texture { size_t height) = 0; }; +// A pixel buffer texture. +class PixelBufferTexture { + public: + PixelBufferTexture(std::unique_ptr&& delegate) + : delegate_(std::move(delegate)) {} + PixelBufferTextureDelegate* delegate() const { return delegate_.get(); }; + + private: + std::unique_ptr delegate_; +}; + +typedef std::variant TextureVariant; + // An object keeping track of external textures. class TextureRegistrar { public: - virtual ~TextureRegistrar() {} + virtual ~TextureRegistrar() = default; // Registers a |texture| object and returns the ID for that texture. - virtual int64_t RegisterTexture(Texture* texture) = 0; + virtual int64_t RegisterTexture(TextureVariant* texture) = 0; // Notifies the flutter engine that the texture object corresponding // to |texure_id| needs to render a new texture. diff --git a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc index 4eb8956b85e32..265f85407edfc 100644 --- a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc +++ b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc @@ -100,12 +100,11 @@ FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar( int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( FlutterDesktopTextureRegistrarRef texture_registrar, - FlutterDesktopTextureCallback texture_callback, - void* user_data) { + const FlutterDesktopTextureInfo* info) { uint64_t result = -1; if (s_stub_implementation) { - result = s_stub_implementation->TextureRegistrarRegisterExternalTexture( - texture_callback, user_data); + result = + s_stub_implementation->TextureRegistrarRegisterExternalTexture(info); } return result; } diff --git a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h index 7837bbc01dd08..9549aa2aa0867 100644 --- a/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h +++ b/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h @@ -67,8 +67,7 @@ class StubFlutterApi { // Called for FlutterDesktopRegisterExternalTexture. virtual int64_t TextureRegistrarRegisterExternalTexture( - FlutterDesktopTextureCallback texture_callback, - void* user_data) { + const FlutterDesktopTextureInfo* info) { return -1; } diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h b/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h index 7e1d95a994b6e..ab278ec383017 100644 --- a/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h @@ -21,7 +21,7 @@ class TextureRegistrarImpl : public TextureRegistrar { TextureRegistrarImpl(TextureRegistrarImpl const&) = delete; TextureRegistrarImpl& operator=(TextureRegistrarImpl const&) = delete; - int64_t RegisterTexture(Texture* texture) override; + int64_t RegisterTexture(TextureVariant* texture) override; bool MarkTextureFrameAvailable(int64_t texture_id) override; bool UnregisterTexture(int64_t texture_id) override; diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc index e34748eed63c6..df8bec593a7dc 100644 --- a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc @@ -15,25 +15,32 @@ namespace flutter { namespace { +class TestPixelBufferTextureDelegate : public PixelBufferTextureDelegate { + public: + const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width, + size_t height) override { + return nullptr; + } +}; + // Stub implementation to validate calls to the API. class TestApi : public testing::StubFlutterApi { public: - struct FakeTexture { + struct FakePixelBufferTexture { int64_t texture_id; int32_t mark_count; - FlutterDesktopTextureCallback texture_callback; + FlutterDesktopPixelBufferTextureCallback texture_callback; void* user_data; }; public: int64_t TextureRegistrarRegisterExternalTexture( - FlutterDesktopTextureCallback texture_callback, - void* user_data) override { + const FlutterDesktopTextureInfo* info) override { last_texture_id_++; - auto texture = std::make_unique(); - texture->texture_callback = texture_callback; - texture->user_data = user_data; + auto texture = std::make_unique(); + texture->texture_callback = info->pixel_buffer.callback; + texture->user_data = info->pixel_buffer.user_data; texture->mark_count = 0; texture->texture_id = last_texture_id_; @@ -59,7 +66,7 @@ class TestApi : public testing::StubFlutterApi { return false; } - FakeTexture* GetFakeTexture(int64_t texture_id) { + FakePixelBufferTexture* GetFakeTexture(int64_t texture_id) { auto it = textures_.find(texture_id); if (it != textures_.end()) { return it->second.get(); @@ -73,7 +80,7 @@ class TestApi : public testing::StubFlutterApi { private: int64_t last_texture_id_ = -1; - std::map> textures_; + std::map> textures_; }; } // namespace @@ -93,13 +100,16 @@ TEST(TextureRegistrarTest, RegisterUnregisterTexture) { auto texture = test_api->GetFakeTexture(0); EXPECT_EQ(texture, nullptr); - int64_t texture_id = textures->RegisterTexture(reinterpret_cast(2)); + auto pixel_buffer_texture = std::make_unique( + PixelBufferTexture(std::make_unique())); + int64_t texture_id = textures->RegisterTexture(pixel_buffer_texture.get()); EXPECT_EQ(test_api->last_texture_id(), texture_id); EXPECT_EQ(test_api->textures_size(), static_cast(1)); texture = test_api->GetFakeTexture(texture_id); EXPECT_EQ(texture->texture_id, texture_id); - EXPECT_EQ(texture->user_data, reinterpret_cast(2)); + EXPECT_EQ(texture->user_data, + std::get_if(pixel_buffer_texture.get())); textures->MarkTextureFrameAvailable(texture_id); textures->MarkTextureFrameAvailable(texture_id); diff --git a/shell/platform/common/cpp/public/flutter_texture_registrar.h b/shell/platform/common/cpp/public/flutter_texture_registrar.h index cfd6b6815573b..c9ceae3efece3 100644 --- a/shell/platform/common/cpp/public/flutter_texture_registrar.h +++ b/shell/platform/common/cpp/public/flutter_texture_registrar.h @@ -19,6 +19,11 @@ struct FlutterDesktopTextureRegistrar; typedef struct FlutterDesktopTextureRegistrar* FlutterDesktopTextureRegistrarRef; +typedef enum { + // A Pixel buffer-based texture. + kFlutterDesktopPixelBufferTexture +} FlutterDesktopTextureType; + // An image buffer object. typedef struct { // The pixel data buffer. @@ -31,18 +36,30 @@ typedef struct { // The pixel buffer copy callback definition provided to // the Flutter engine to copy the texture. -typedef const FlutterDesktopPixelBuffer* (*FlutterDesktopTextureCallback)( - size_t width, - size_t height, - void* user_data); +typedef const FlutterDesktopPixelBuffer* ( + *FlutterDesktopPixelBufferTextureCallback)(size_t width, + size_t height, + void* user_data); + +// An object used to configure pixel buffer textures. +typedef struct { + // The callback used by the engine to copy the pixel buffer object. + FlutterDesktopPixelBufferTextureCallback callback; + // Opaque data that will get passed to the provided |callback|. + void* user_data; +} FlutterDesktopPixelBufferTextureConfig; + +typedef struct { + FlutterDesktopTextureType type; + union { + FlutterDesktopPixelBufferTextureConfig pixel_buffer; + }; +} FlutterDesktopTextureInfo; -// Registers a new texture with the Flutter engine and returns the texture ID, -// The engine will use the |texture_callback| -// function to copy the pixel buffer from the caller. +// Registers a new texture with the Flutter engine and returns the texture ID. FLUTTER_EXPORT int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( FlutterDesktopTextureRegistrarRef texture_registrar, - FlutterDesktopTextureCallback texture_callback, - void* user_data); + const FlutterDesktopTextureInfo* info); // Unregisters an existing texture from the Flutter engine for a |texture_id|. // Returns true on success or false if the specified texture doesn't exist. diff --git a/shell/platform/glfw/flutter_glfw.cc b/shell/platform/glfw/flutter_glfw.cc index 43dbdfce5016c..c926e86ca549c 100644 --- a/shell/platform/glfw/flutter_glfw.cc +++ b/shell/platform/glfw/flutter_glfw.cc @@ -1081,8 +1081,7 @@ FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar( int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( FlutterDesktopTextureRegistrarRef texture_registrar, - FlutterDesktopTextureCallback texture_callback, - void* user_data) { + const FlutterDesktopTextureInfo* texture_info) { std::cerr << "GLFW Texture support is not implemented yet." << std::endl; return -1; } diff --git a/shell/platform/windows/external_texture_gl.cc b/shell/platform/windows/external_texture_gl.cc index edcd3fd49ec4e..175643ec44c66 100644 --- a/shell/platform/windows/external_texture_gl.cc +++ b/shell/platform/windows/external_texture_gl.cc @@ -68,7 +68,7 @@ struct ExternalTextureGLState { }; ExternalTextureGL::ExternalTextureGL( - FlutterDesktopTextureCallback texture_callback, + FlutterDesktopPixelBufferTextureCallback texture_callback, void* user_data) : state_(std::make_unique()), texture_callback_(texture_callback), diff --git a/shell/platform/windows/external_texture_gl.h b/shell/platform/windows/external_texture_gl.h index 4d473e5f60365..9d1d5ae5e940f 100644 --- a/shell/platform/windows/external_texture_gl.h +++ b/shell/platform/windows/external_texture_gl.h @@ -19,7 +19,7 @@ typedef struct ExternalTextureGLState ExternalTextureGLState; // An abstraction of an OpenGL texture. class ExternalTextureGL { public: - ExternalTextureGL(FlutterDesktopTextureCallback texture_callback, + ExternalTextureGL(FlutterDesktopPixelBufferTextureCallback texture_callback, void* user_data); virtual ~ExternalTextureGL(); @@ -45,7 +45,7 @@ class ExternalTextureGL { bool CopyPixelBuffer(size_t& width, size_t& height); std::unique_ptr state_; - FlutterDesktopTextureCallback texture_callback_ = nullptr; + FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr; void* user_data_ = nullptr; }; diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index 969732fb68a02..1c56965d88a5a 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -197,10 +197,9 @@ FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar( int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( FlutterDesktopTextureRegistrarRef texture_registrar, - FlutterDesktopTextureCallback texture_callback, - void* user_data) { + const FlutterDesktopTextureInfo* texture_info) { return TextureRegistrarFromHandle(texture_registrar) - ->RegisterTexture(texture_callback, user_data); + ->RegisterTexture(texture_info); } bool FlutterDesktopTextureRegistrarUnregisterExternalTexture( diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 35567245d0cfd..723dd7c2ceea1 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -367,4 +367,20 @@ void FlutterWindowsEngine::SendSystemSettings() { settings_channel_->Send(settings); } +bool FlutterWindowsEngine::RegisterExternalTexture(int64_t texture_id) { + return (embedder_api_.RegisterExternalTexture(engine_, texture_id) == + kSuccess); +} + +bool FlutterWindowsEngine::UnregisterExternalTexture(int64_t texture_id) { + return (embedder_api_.UnregisterExternalTexture(engine_, texture_id) == + kSuccess); +} + +bool FlutterWindowsEngine::MarkExternalTextureFrameAvailable( + int64_t texture_id) { + return (embedder_api_.MarkExternalTextureFrameAvailable( + engine_, texture_id) == kSuccess); +} + } // namespace flutter diff --git a/shell/platform/windows/flutter_windows_engine.h b/shell/platform/windows/flutter_windows_engine.h index 337ea6a09cce2..5e2cac869c704 100644 --- a/shell/platform/windows/flutter_windows_engine.h +++ b/shell/platform/windows/flutter_windows_engine.h @@ -118,6 +118,16 @@ class FlutterWindowsEngine { // Informs the engine that the system font list has changed. void ReloadSystemFonts(); + // Attempts to register the texture with the given |texture_id|. + bool RegisterExternalTexture(int64_t texture_id); + + // Attempts to unregister the texture with the given |texture_id|. + bool UnregisterExternalTexture(int64_t texture_id); + + // Notifies the engine about a new frame being available for the + // given |texture_id|. + bool MarkExternalTextureFrameAvailable(int64_t texture_id); + private: // Allows swapping out embedder_api_ calls in tests. friend class EngineEmbedderApiModifier; diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc index 9b6624dcac44e..94ff5e33dfe49 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -6,6 +6,8 @@ #include "flutter/shell/platform/windows/flutter_windows_engine.h" +#include + namespace flutter { FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar( @@ -13,16 +15,26 @@ FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar( : engine_(engine) {} int64_t FlutterWindowsTextureRegistrar::RegisterTexture( - FlutterDesktopTextureCallback texture_callback, - void* user_data) { - auto texture_gl = - std::make_unique(texture_callback, user_data); + const FlutterDesktopTextureInfo* texture_info) { + if (texture_info->type != kFlutterDesktopPixelBufferTexture) { + std::cerr << "Attempted to register texture of unsupport type." + << std::endl; + return -1; + } + + if (!texture_info->pixel_buffer.callback) { + std::cerr << "Invalid pixel buffer texture callback." << std::endl; + return -1; + } + + auto texture_gl = std::make_unique( + engine_, texture_info->pixel_buffer.callback, + texture_info->pixel_buffer.user_data); int64_t texture_id = texture_gl->texture_id(); textures_[texture_id] = std::move(texture_gl); - if (FlutterEngineRegisterExternalTexture(engine_->engine(), texture_id) == - kSuccess) { + if (engine_->RegisterExternalTexture(texture_id)) { return texture_id; } @@ -34,14 +46,12 @@ bool FlutterWindowsTextureRegistrar::UnregisterTexture(int64_t texture_id) { if (it != textures_.end()) { textures_.erase(it); } - return (FlutterEngineUnregisterExternalTexture(engine_->engine(), - texture_id) == kSuccess); + return engine_->UnregisterExternalTexture(texture_id); } bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( int64_t texture_id) { - return (FlutterEngineMarkExternalTextureFrameAvailable( - engine_->engine(), texture_id) == kSuccess); + return engine_->MarkExternalTextureFrameAvailable(texture_id); } bool FlutterWindowsTextureRegistrar::PopulateTexture( diff --git a/shell/platform/windows/flutter_windows_texture_registrar.h b/shell/platform/windows/flutter_windows_texture_registrar.h index 908806e2183f3..6db0e29e08823 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.h +++ b/shell/platform/windows/flutter_windows_texture_registrar.h @@ -19,11 +19,9 @@ class FlutterWindowsTextureRegistrar { public: explicit FlutterWindowsTextureRegistrar(FlutterWindowsEngine* engine); - // Registers a texture whose pixel data will be obtained using the - // specified |texture_callback| + // Registers a texture described by the given |texture_info| object. // Returns the non-zero, positive texture id or -1 on error. - int64_t RegisterTexture(FlutterDesktopTextureCallback texture_callback, - void* user_data); + int64_t RegisterTexture(const FlutterDesktopTextureInfo* texture_info); // Attempts to unregister the texture identified by |texture_id|. // Returns true if the texture was successfully unregistered. diff --git a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc index 4c3df7f83c238..f356f40882ec7 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc @@ -4,41 +4,117 @@ #include +#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" #include "flutter/shell/platform/windows/flutter_windows_engine.h" #include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h" +#include "flutter/shell/platform/windows/testing/engine_embedder_api_modifier.h" #include "gtest/gtest.h" namespace flutter { namespace testing { -TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) { - FlutterDesktopEngineProperties props = {}; - props.assets_path = L"FakeAssets"; - props.icu_data_path = L"icudtl.dat"; +namespace { +// Returns an engine instance configured with dummy project path values. +std::unique_ptr GetTestEngine() { + FlutterDesktopEngineProperties properties = {}; + properties.assets_path = L"C:\\foo\\flutter_assets"; + properties.icu_data_path = L"C:\\foo\\icudtl.dat"; + properties.aot_library_path = L"C:\\foo\\aot.so"; + FlutterProjectBundle project(properties); + return std::make_unique(project); +} +} // namespace - FlutterProjectBundle bundle(props); - FlutterWindowsEngine engine(bundle); +TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) { + std::unique_ptr engine = GetTestEngine(); - FlutterWindowsTextureRegistrar registrar(&engine); + FlutterWindowsTextureRegistrar registrar(engine.get()); EXPECT_TRUE(true); } +TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) { + std::unique_ptr engine = GetTestEngine(); + EngineEmbedderApiModifier modifier(engine.get()); + + FlutterWindowsTextureRegistrar registrar(engine.get()); + + FlutterDesktopPixelBufferTextureConfig config = {}; + config.callback = [](size_t width, size_t height, + void* user_data) -> const FlutterDesktopPixelBuffer* { + return nullptr; + }; + + FlutterDesktopTextureInfo texture_info = {}; + texture_info.type = kFlutterDesktopPixelBufferTexture; + texture_info.pixel_buffer = config; + + int64_t registered_texture_id = 0; + bool register_called = false; + modifier.embedder_api().RegisterExternalTexture = MOCK_ENGINE_PROC( + RegisterExternalTexture, ([®ister_called, ®istered_texture_id]( + auto engine, auto texture_id) { + register_called = true; + registered_texture_id = texture_id; + return kSuccess; + })); + + bool unregister_called = false; + modifier.embedder_api().UnregisterExternalTexture = MOCK_ENGINE_PROC( + UnregisterExternalTexture, ([&unregister_called, ®istered_texture_id]( + auto engine, auto texture_id) { + unregister_called = true; + EXPECT_EQ(registered_texture_id, texture_id); + return kSuccess; + })); + + bool mark_frame_available_called = false; + modifier.embedder_api().MarkExternalTextureFrameAvailable = + MOCK_ENGINE_PROC(MarkExternalTextureFrameAvailable, + ([&mark_frame_available_called, ®istered_texture_id]( + auto engine, auto texture_id) { + mark_frame_available_called = true; + EXPECT_EQ(registered_texture_id, texture_id); + return kSuccess; + })); + + auto texture_id = registrar.RegisterTexture(&texture_info); + EXPECT_TRUE(register_called); + EXPECT_NE(texture_id, -1); + EXPECT_EQ(texture_id, registered_texture_id); + + EXPECT_TRUE(registrar.MarkTextureFrameAvailable(texture_id)); + EXPECT_TRUE(mark_frame_available_called); + + EXPECT_TRUE(registrar.UnregisterTexture(texture_id)); + EXPECT_TRUE(unregister_called); +} + +TEST(FlutterWindowsTextureRegistrarTest, RegisterUnknownTextureType) { + std::unique_ptr engine = GetTestEngine(); + EngineEmbedderApiModifier modifier(engine.get()); + + FlutterWindowsTextureRegistrar registrar(engine.get()); + + FlutterDesktopTextureInfo texture_info = {}; + texture_info.type = static_cast(1234); + + auto texture_id = registrar.RegisterTexture(&texture_info); + + EXPECT_EQ(texture_id, -1); +} + TEST(FlutterWindowsTextureRegistrarTest, PopulateInvalidTexture) { - FlutterDesktopEngineProperties props = {}; - props.assets_path = L"FakeAssets"; - props.icu_data_path = L"icudtl.dat"; + std::unique_ptr engine = GetTestEngine(); - FlutterProjectBundle bundle(props); - FlutterWindowsEngine engine(bundle); + FlutterWindowsTextureRegistrar registrar(engine.get()); - FlutterWindowsTextureRegistrar registrar(&engine); auto result = registrar.PopulateTexture(1, 640, 480, nullptr); EXPECT_FALSE(result); } -// TODO Add additional tests for testing actual texture registration using -// FlutterEngineRegisterExternalTexture +// TODO Add additional tests for PopulateTexture() once we've mocked gl* +// functions used by ExternalTextureGL } // namespace testing } // namespace flutter From a44de993f6e207b73784f276e0b09c3ff4367503 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Wed, 18 Nov 2020 13:14:25 +0100 Subject: [PATCH 03/17] Embedder API: Add PostPlatformThreadTask method --- shell/platform/embedder/embedder.cc | 23 ++++++++++++++++++++++ shell/platform/embedder/embedder.h | 3 +++ shell/platform/embedder/embedder_engine.cc | 9 +++++++++ shell/platform/embedder/embedder_engine.h | 2 ++ 4 files changed, 37 insertions(+) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 1dc3ea6b448ed..df6d56f1b68b4 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -1691,6 +1691,28 @@ void FlutterEngineTraceEventInstant(const char* name) { fml::tracing::TraceEventInstant0("flutter", name); } +FlutterEngineResult FlutterEnginePostPlatformThreadTask( + FLUTTER_API_SYMBOL(FlutterEngine) engine, + VoidCallback callback, + void* baton) { + if (engine == nullptr) { + return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle."); + } + + if (callback == nullptr) { + return LOG_EMBEDDER_ERROR(kInvalidArguments, + "Platform thread callback was null."); + } + + auto task = [callback, baton]() { callback(baton); }; + + return reinterpret_cast(engine) + ->PostPlatformThreadTask(task) + ? kSuccess + : LOG_EMBEDDER_ERROR(kInternalInconsistency, + "Could not post the platform thread task."); +} + FlutterEngineResult FlutterEnginePostRenderThreadTask( FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, @@ -2090,6 +2112,7 @@ FlutterEngineResult FlutterEngineGetProcAddresses( SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin); SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd); SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant); + SET_PROC(PostPlatformThreadTask, FlutterEnginePostPlatformThreadTask); SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask); SET_PROC(GetCurrentTime, FlutterEngineGetCurrentTime); SET_PROC(RunTask, FlutterEngineRunTask); diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 4819aa87fa611..a070f13cd70c9 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -2062,6 +2062,8 @@ typedef FlutterEngineResult (*FlutterEnginePostRenderThreadTaskFnPtr)( FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, void* callback_data); +typedef FlutterEnginePostRenderThreadTaskFnPtr + FlutterEnginePostPlatformThreadTaskFnPtr; typedef uint64_t (*FlutterEngineGetCurrentTimeFnPtr)(); typedef FlutterEngineResult (*FlutterEngineRunTaskFnPtr)( FLUTTER_API_SYMBOL(FlutterEngine) engine, @@ -2119,6 +2121,7 @@ typedef struct { FlutterEngineTraceEventDurationBeginFnPtr TraceEventDurationBegin; FlutterEngineTraceEventDurationEndFnPtr TraceEventDurationEnd; FlutterEngineTraceEventInstantFnPtr TraceEventInstant; + FlutterEnginePostPlatformThreadTaskFnPtr PostPlatformThreadTask; FlutterEnginePostRenderThreadTaskFnPtr PostRenderThreadTask; FlutterEngineGetCurrentTimeFnPtr GetCurrentTime; FlutterEngineRunTaskFnPtr RunTask; diff --git a/shell/platform/embedder/embedder_engine.cc b/shell/platform/embedder/embedder_engine.cc index bb0aa08bb42d5..bf5b019338746 100644 --- a/shell/platform/embedder/embedder_engine.cc +++ b/shell/platform/embedder/embedder_engine.cc @@ -244,6 +244,15 @@ bool EmbedderEngine::ReloadSystemFonts() { return shell_->ReloadSystemFonts(); } +bool EmbedderEngine::PostPlatformThreadTask(const fml::closure& task) { + if (!IsValid()) { + return false; + } + + shell_->GetTaskRunners().GetPlatformTaskRunner()->PostTask(task); + return true; +} + bool EmbedderEngine::PostRenderThreadTask(const fml::closure& task) { if (!IsValid()) { return false; diff --git a/shell/platform/embedder/embedder_engine.h b/shell/platform/embedder/embedder_engine.h index 4f38ba4410cd0..a48dfa226dc9a 100644 --- a/shell/platform/embedder/embedder_engine.h +++ b/shell/platform/embedder/embedder_engine.h @@ -82,6 +82,8 @@ class EmbedderEngine { bool ReloadSystemFonts(); + bool PostPlatformThreadTask(const fml::closure& task); + bool PostRenderThreadTask(const fml::closure& task); bool RunTask(const FlutterTask* task); From 92279aafbb10bb05c498ab0340a609388c5ea026 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Wed, 18 Nov 2020 13:19:30 +0100 Subject: [PATCH 04/17] Windows textures: Allow calling MarkTextureFrameAvailable from arbitrary threads --- shell/platform/windows/external_texture_gl.cc | 10 +++++++++- shell/platform/windows/external_texture_gl.h | 10 +++++++++- shell/platform/windows/flutter_windows_engine.cc | 6 ++++++ shell/platform/windows/flutter_windows_engine.h | 3 +++ .../windows/flutter_windows_texture_registrar.cc | 11 ++++++++++- .../flutter_windows_texture_registrar_unittests.cc | 7 +++++++ 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/shell/platform/windows/external_texture_gl.cc b/shell/platform/windows/external_texture_gl.cc index 175643ec44c66..8cd764a5edc0d 100644 --- a/shell/platform/windows/external_texture_gl.cc +++ b/shell/platform/windows/external_texture_gl.cc @@ -4,6 +4,8 @@ #include "flutter/shell/platform/windows/external_texture_gl.h" +#include "flutter/shell/platform/windows/flutter_windows_engine.h" + #include #include #include @@ -68,9 +70,11 @@ struct ExternalTextureGLState { }; ExternalTextureGL::ExternalTextureGL( + FlutterWindowsEngine* engine, FlutterDesktopPixelBufferTextureCallback texture_callback, void* user_data) - : state_(std::make_unique()), + : engine_(engine), + state_(std::make_unique()), texture_callback_(texture_callback), user_data_(user_data) {} @@ -81,6 +85,10 @@ ExternalTextureGL::~ExternalTextureGL() { } } +void ExternalTextureGL::MarkFrameAvailable() { + engine_->MarkExternalTextureFrameAvailable(texture_id()); +} + bool ExternalTextureGL::PopulateTexture(size_t width, size_t height, FlutterOpenGLTexture* opengl_texture) { diff --git a/shell/platform/windows/external_texture_gl.h b/shell/platform/windows/external_texture_gl.h index 9d1d5ae5e940f..7ff69528a7654 100644 --- a/shell/platform/windows/external_texture_gl.h +++ b/shell/platform/windows/external_texture_gl.h @@ -16,10 +16,13 @@ namespace flutter { typedef struct ExternalTextureGLState ExternalTextureGLState; +class FlutterWindowsEngine; + // An abstraction of an OpenGL texture. class ExternalTextureGL { public: - ExternalTextureGL(FlutterDesktopPixelBufferTextureCallback texture_callback, + ExternalTextureGL(FlutterWindowsEngine* engine, + FlutterDesktopPixelBufferTextureCallback texture_callback, void* user_data); virtual ~ExternalTextureGL(); @@ -27,6 +30,10 @@ class ExternalTextureGL { // Returns the unique id of this texture. int64_t texture_id() { return reinterpret_cast(this); } + FlutterWindowsEngine* engine() { return engine_; } + + void MarkFrameAvailable(); + // Attempts to populate the specified |opengl_texture| with texture details // such as the name, width, height and the pixel format upon successfully // copying the buffer provided by |texture_callback_|. See |CopyPixelBuffer|. @@ -47,6 +54,7 @@ class ExternalTextureGL { std::unique_ptr state_; FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr; void* user_data_ = nullptr; + FlutterWindowsEngine* engine_ = nullptr; }; } // namespace flutter diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 723dd7c2ceea1..170075d5c80c3 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -383,4 +383,10 @@ bool FlutterWindowsEngine::MarkExternalTextureFrameAvailable( engine_, texture_id) == kSuccess); } +bool FlutterWindowsEngine::PostPlatformThreadTask(VoidCallback callback, + void* callback_data) { + return (embedder_api_.PostPlatformThreadTask(engine_, callback, + callback_data) == kSuccess); +} + } // namespace flutter diff --git a/shell/platform/windows/flutter_windows_engine.h b/shell/platform/windows/flutter_windows_engine.h index 5e2cac869c704..7fc8e55dd6788 100644 --- a/shell/platform/windows/flutter_windows_engine.h +++ b/shell/platform/windows/flutter_windows_engine.h @@ -128,6 +128,9 @@ class FlutterWindowsEngine { // given |texture_id|. bool MarkExternalTextureFrameAvailable(int64_t texture_id); + // Posts a task onto the platform thread. + bool PostPlatformThreadTask(VoidCallback callback, void* callback_data); + private: // Allows swapping out embedder_api_ calls in tests. friend class EngineEmbedderApiModifier; diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc index 94ff5e33dfe49..492f54e8a693a 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -51,7 +51,16 @@ bool FlutterWindowsTextureRegistrar::UnregisterTexture(int64_t texture_id) { bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( int64_t texture_id) { - return engine_->MarkExternalTextureFrameAvailable(texture_id); + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + return engine_->PostPlatformThreadTask( + [](void* data) { + auto texture = reinterpret_cast(data); + texture->MarkFrameAvailable(); + }, + it->second.get()); + } + return false; } bool FlutterWindowsTextureRegistrar::PopulateTexture( diff --git a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc index f356f40882ec7..caa7c382f3878 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc @@ -78,6 +78,13 @@ TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) { return kSuccess; })); + modifier.embedder_api().PostPlatformThreadTask = + MOCK_ENGINE_PROC(PostPlatformThreadTask, + ([](auto engine, auto callback, auto callback_data) { + callback(callback_data); + return kSuccess; + })); + auto texture_id = registrar.RegisterTexture(&texture_info); EXPECT_TRUE(register_called); EXPECT_NE(texture_id, -1); From 0c1c2f1fd3cbc657fa9e0487d95d9fc1cee368c8 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Thu, 7 Jan 2021 11:22:59 +0100 Subject: [PATCH 05/17] Windows textures: Do review-related cleanup --- .../client_wrapper/core_implementations.cc | 6 +-- .../include/flutter/texture_registrar.h | 40 +++++++++++-------- .../client_wrapper/texture_registrar_impl.h | 5 +++ .../texture_registrar_unittests.cc | 14 ++----- .../cpp/public/flutter_texture_registrar.h | 6 ++- .../flutter_windows_texture_registrar.cc | 6 +-- ...ter_windows_texture_registrar_unittests.cc | 12 +++--- 7 files changed, 48 insertions(+), 41 deletions(-) diff --git a/shell/platform/common/cpp/client_wrapper/core_implementations.cc b/shell/platform/common/cpp/client_wrapper/core_implementations.cc index 0188787823886..1412db7c939f2 100644 --- a/shell/platform/common/cpp/client_wrapper/core_implementations.cc +++ b/shell/platform/common/cpp/client_wrapper/core_implementations.cc @@ -160,12 +160,12 @@ int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) { if (auto pixel_buffer_texture = std::get_if(texture)) { FlutterDesktopTextureInfo info = {}; info.type = kFlutterDesktopPixelBufferTexture; - info.pixel_buffer.user_data = pixel_buffer_texture; - info.pixel_buffer.callback = + info.pixel_buffer_config.user_data = pixel_buffer_texture; + info.pixel_buffer_config.callback = [](size_t width, size_t height, void* user_data) -> const FlutterDesktopPixelBuffer* { auto texture = static_cast(user_data); - auto buffer = texture->delegate()->CopyPixelBuffer(width, height); + auto buffer = texture->CopyPixelBuffer(width, height); return buffer; }; diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h index 53962f31582f0..ffbdd0ce33cc5 100644 --- a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -6,35 +6,43 @@ #define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_ #include -#include +#include #include #include -namespace flutter { - -// An interface used as an image source by pixel buffer textures. -class PixelBufferTextureDelegate { - public: - virtual ~PixelBufferTextureDelegate() = default; +#include - // Returns a FlutterDesktopPixelBuffer that contains the actual pixel data. - // The intended surface size is specified by |width| and |height|. - virtual const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width, - size_t height) = 0; -}; +namespace flutter { // A pixel buffer texture. class PixelBufferTexture { public: - PixelBufferTexture(std::unique_ptr&& delegate) - : delegate_(std::move(delegate)) {} - PixelBufferTextureDelegate* delegate() const { return delegate_.get(); }; + // A callback used for retrieving pixel buffers. + typedef std::function + CopyBufferCb; + + // Creates a pixel buffer texture that uses the provided |copy_buffer_cb| to + // retrieve the buffer. + PixelBufferTexture(CopyBufferCb copy_buffer_cb) + : copy_buffer_cb_(copy_buffer_cb) {} + + // Returns the callback-provided FlutterDesktopPixelBuffer that contains the + // actual pixel data. The intended surface size is specified by |width| and + // |height|. + const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width, + size_t height) const { + return copy_buffer_cb_(width, height); + } private: - std::unique_ptr delegate_; + const CopyBufferCb copy_buffer_cb_; }; +// The available texture variants. +// While PixelBufferTexture is the only implementation we currently have, +// this is going to be extended once we have additional implementations like +// PBO-based textures etc. typedef std::variant TextureVariant; // An object keeping track of external textures. diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h b/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h index ab278ec383017..128ed843d259e 100644 --- a/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_impl.h @@ -21,8 +21,13 @@ class TextureRegistrarImpl : public TextureRegistrar { TextureRegistrarImpl(TextureRegistrarImpl const&) = delete; TextureRegistrarImpl& operator=(TextureRegistrarImpl const&) = delete; + // |flutter::TextureRegistrar| int64_t RegisterTexture(TextureVariant* texture) override; + + // |flutter::TextureRegistrar| bool MarkTextureFrameAvailable(int64_t texture_id) override; + + // |flutter::TextureRegistrar| bool UnregisterTexture(int64_t texture_id) override; private: diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc index df8bec593a7dc..a10dcffdca26b 100644 --- a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc @@ -15,14 +15,6 @@ namespace flutter { namespace { -class TestPixelBufferTextureDelegate : public PixelBufferTextureDelegate { - public: - const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width, - size_t height) override { - return nullptr; - } -}; - // Stub implementation to validate calls to the API. class TestApi : public testing::StubFlutterApi { public: @@ -39,8 +31,8 @@ class TestApi : public testing::StubFlutterApi { last_texture_id_++; auto texture = std::make_unique(); - texture->texture_callback = info->pixel_buffer.callback; - texture->user_data = info->pixel_buffer.user_data; + texture->texture_callback = info->pixel_buffer_config.callback; + texture->user_data = info->pixel_buffer_config.user_data; texture->mark_count = 0; texture->texture_id = last_texture_id_; @@ -101,7 +93,7 @@ TEST(TextureRegistrarTest, RegisterUnregisterTexture) { EXPECT_EQ(texture, nullptr); auto pixel_buffer_texture = std::make_unique( - PixelBufferTexture(std::make_unique())); + PixelBufferTexture([](size_t width, size_t height) { return nullptr; })); int64_t texture_id = textures->RegisterTexture(pixel_buffer_texture.get()); EXPECT_EQ(test_api->last_texture_id(), texture_id); EXPECT_EQ(test_api->textures_size(), static_cast(1)); diff --git a/shell/platform/common/cpp/public/flutter_texture_registrar.h b/shell/platform/common/cpp/public/flutter_texture_registrar.h index c9ceae3efece3..dacb9013cad3e 100644 --- a/shell/platform/common/cpp/public/flutter_texture_registrar.h +++ b/shell/platform/common/cpp/public/flutter_texture_registrar.h @@ -19,6 +19,8 @@ struct FlutterDesktopTextureRegistrar; typedef struct FlutterDesktopTextureRegistrar* FlutterDesktopTextureRegistrarRef; +// Possible values for the type specified in FlutterDesktopTextureInfo. +// Additional types may be added in the future. typedef enum { // A Pixel buffer-based texture. kFlutterDesktopPixelBufferTexture @@ -36,6 +38,8 @@ typedef struct { // The pixel buffer copy callback definition provided to // the Flutter engine to copy the texture. +// It is invoked with the intended surface size specified by |width| and +// |height| and the |user_data| held by FlutterDesktopPixelBufferTextureConfig. typedef const FlutterDesktopPixelBuffer* ( *FlutterDesktopPixelBufferTextureCallback)(size_t width, size_t height, @@ -52,7 +56,7 @@ typedef struct { typedef struct { FlutterDesktopTextureType type; union { - FlutterDesktopPixelBufferTextureConfig pixel_buffer; + FlutterDesktopPixelBufferTextureConfig pixel_buffer_config; }; } FlutterDesktopTextureInfo; diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc index 492f54e8a693a..d3f101cb2cda4 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -22,14 +22,14 @@ int64_t FlutterWindowsTextureRegistrar::RegisterTexture( return -1; } - if (!texture_info->pixel_buffer.callback) { + if (!texture_info->pixel_buffer_config.callback) { std::cerr << "Invalid pixel buffer texture callback." << std::endl; return -1; } auto texture_gl = std::make_unique( - engine_, texture_info->pixel_buffer.callback, - texture_info->pixel_buffer.user_data); + engine_, texture_info->pixel_buffer_config.callback, + texture_info->pixel_buffer_config.user_data); int64_t texture_id = texture_gl->texture_id(); textures_[texture_id] = std::move(texture_gl); diff --git a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc index caa7c382f3878..fb1a0b57938dd 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc @@ -39,15 +39,13 @@ TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) { FlutterWindowsTextureRegistrar registrar(engine.get()); - FlutterDesktopPixelBufferTextureConfig config = {}; - config.callback = [](size_t width, size_t height, - void* user_data) -> const FlutterDesktopPixelBuffer* { - return nullptr; - }; - FlutterDesktopTextureInfo texture_info = {}; texture_info.type = kFlutterDesktopPixelBufferTexture; - texture_info.pixel_buffer = config; + texture_info.pixel_buffer_config.callback = + [](size_t width, size_t height, + void* user_data) -> const FlutterDesktopPixelBuffer* { + return nullptr; + }; int64_t registered_texture_id = 0; bool register_called = false; From f3d0dc4609d54b34a01958aa4be2376d7bf66250 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Thu, 7 Jan 2021 11:26:33 +0100 Subject: [PATCH 06/17] Windows textures: Remove message when copying a pixel buffer fails as null buffers should be considered fine --- shell/platform/windows/external_texture_gl.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/shell/platform/windows/external_texture_gl.cc b/shell/platform/windows/external_texture_gl.cc index 8cd764a5edc0d..855e1a0fc29f1 100644 --- a/shell/platform/windows/external_texture_gl.cc +++ b/shell/platform/windows/external_texture_gl.cc @@ -10,8 +10,6 @@ #include #include -#include - namespace { typedef void (*glGenTexturesProc)(GLsizei n, GLuint* textures); @@ -93,7 +91,6 @@ bool ExternalTextureGL::PopulateTexture(size_t width, size_t height, FlutterOpenGLTexture* opengl_texture) { if (!CopyPixelBuffer(width, height)) { - std::cerr << "Failed to copy pixel buffer from provider." << std::endl; return false; } From b94d4f48ffdd73e03cfa2ea0d1be5c6832995080 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Thu, 7 Jan 2021 12:24:14 +0100 Subject: [PATCH 07/17] Embedder API: Add missing FlutterEnginePostPlatformThreadTask declaration --- shell/platform/embedder/embedder.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index a070f13cd70c9..06df4f6816b4b 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1786,6 +1786,24 @@ void FlutterEngineTraceEventDurationEnd(const char* name); FLUTTER_EXPORT void FlutterEngineTraceEventInstant(const char* name); +//------------------------------------------------------------------------------ +/// @brief Posts a task onto the Flutter platform thread. Typically, this +/// may be called from any thread as long as a +/// `FlutterEngineShutdown` on the specific engine has not already +/// been initiated. +/// +/// @param[in] engine A running engine instance. +/// @param[in] callback The callback to execute on the platform thread. +/// @param callback_data The callback context. +/// +/// @return The result of the call. +/// +FLUTTER_EXPORT +FlutterEngineResult FlutterEnginePostPlatformThreadTask( + FLUTTER_API_SYMBOL(FlutterEngine) engine, + VoidCallback callback, + void* callback_data); + //------------------------------------------------------------------------------ /// @brief Posts a task onto the Flutter render thread. Typically, this may /// be called from any thread as long as a `FlutterEngineShutdown` From 018e479162d6cdb945a819b98714f611f70f92b6 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Thu, 7 Jan 2021 12:24:44 +0100 Subject: [PATCH 08/17] Embedder API: Move PostPlatformThreadTask to end of proc table --- shell/platform/embedder/embedder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 06df4f6816b4b..f54e3b73c4e1b 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -2139,7 +2139,6 @@ typedef struct { FlutterEngineTraceEventDurationBeginFnPtr TraceEventDurationBegin; FlutterEngineTraceEventDurationEndFnPtr TraceEventDurationEnd; FlutterEngineTraceEventInstantFnPtr TraceEventInstant; - FlutterEnginePostPlatformThreadTaskFnPtr PostPlatformThreadTask; FlutterEnginePostRenderThreadTaskFnPtr PostRenderThreadTask; FlutterEngineGetCurrentTimeFnPtr GetCurrentTime; FlutterEngineRunTaskFnPtr RunTask; @@ -2150,6 +2149,7 @@ typedef struct { FlutterEnginePostCallbackOnAllNativeThreadsFnPtr PostCallbackOnAllNativeThreads; FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate; + FlutterEnginePostPlatformThreadTaskFnPtr PostPlatformThreadTask; } FlutterEngineProcTable; //------------------------------------------------------------------------------ From d9e7d5e6b2455e31131425186414572375cafc53 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Thu, 7 Jan 2021 13:01:21 +0100 Subject: [PATCH 09/17] Windows textures: Make PixelBufferTexture's copy cb return type const --- .../cpp/client_wrapper/include/flutter/texture_registrar.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h index ffbdd0ce33cc5..0bd6978751895 100644 --- a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -19,7 +19,8 @@ namespace flutter { class PixelBufferTexture { public: // A callback used for retrieving pixel buffers. - typedef std::function + typedef std::function CopyBufferCb; // Creates a pixel buffer texture that uses the provided |copy_buffer_cb| to From 6a8a20e6e5bf139f004dbcdc7d59a0f3dbdcae87 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Fri, 8 Jan 2021 12:11:46 +0100 Subject: [PATCH 10/17] Windows: Extend TaskRunner to allow direct posting --- .../windows/flutter_windows_engine.cc | 3 +- shell/platform/windows/task_runner.h | 15 +++++++-- shell/platform/windows/task_runner_win32.cc | 33 ++++++++++++++----- shell/platform/windows/task_runner_win32.h | 17 +++++++--- shell/platform/windows/task_runner_winuwp.cc | 12 +++++-- shell/platform/windows/task_runner_winuwp.h | 8 +++-- 6 files changed, 67 insertions(+), 21 deletions(-) diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 170075d5c80c3..76a082e529a8d 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -194,7 +194,8 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) { platform_task_runner.post_task_callback = [](FlutterTask task, uint64_t target_time_nanos, void* user_data) -> void { - static_cast(user_data)->PostTask(task, target_time_nanos); + static_cast(user_data)->PostFlutterTask(task, + target_time_nanos); }; FlutterCustomTaskRunners custom_task_runners = {}; custom_task_runners.struct_size = sizeof(FlutterCustomTaskRunners); diff --git a/shell/platform/windows/task_runner.h b/shell/platform/windows/task_runner.h index 9d2c22b9043c0..4ac58f7b0a56c 100644 --- a/shell/platform/windows/task_runner.h +++ b/shell/platform/windows/task_runner.h @@ -9,6 +9,7 @@ #include #include +#include #include "flutter/shell/platform/embedder/embedder.h" @@ -19,16 +20,24 @@ typedef uint64_t (*CurrentTimeProc)(); // Abstract custom task runner for scheduling custom tasks. class TaskRunner { public: + using TaskTimePoint = std::chrono::steady_clock::time_point; using TaskExpiredCallback = std::function; + using TaskClosure = std::function; virtual ~TaskRunner() = default; // Returns if the current thread is the UI thread. virtual bool RunsTasksOnCurrentThread() const = 0; - // Post a Flutter engine tasks to the event loop for delayed execution. - virtual void PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) = 0; + // Post a Flutter engine task to the event loop for delayed execution. + virtual void PostFlutterTask(FlutterTask flutter_task, + uint64_t flutter_target_time_nanos) = 0; + + // Post a task to the event loop for delayed execution with an optional target + // time. + virtual void PostTask( + TaskClosure task, + std::optional target_time = std::nullopt) = 0; // Creates a new task runner with the given main thread ID, current time // provider, and callback for tasks that are ready to be run. diff --git a/shell/platform/windows/task_runner_win32.cc b/shell/platform/windows/task_runner_win32.cc index bb1fe147707de..e85f37c50a908 100644 --- a/shell/platform/windows/task_runner_win32.cc +++ b/shell/platform/windows/task_runner_win32.cc @@ -35,7 +35,7 @@ bool TaskRunnerWin32::RunsTasksOnCurrentThread() const { std::chrono::nanoseconds TaskRunnerWin32::ProcessTasks() { const TaskTimePoint now = TaskTimePoint::clock::now(); - std::vector expired_tasks; + std::vector expired_tasks; // Process expired tasks. { @@ -52,7 +52,7 @@ std::chrono::nanoseconds TaskRunnerWin32::ProcessTasks() { // because we are still holding onto the task queue mutex. We don't want // other threads to block on posting tasks onto this thread till we are // done processing expired tasks. - expired_tasks.push_back(task_queue_.top().task); + expired_tasks.push_back(task_queue_.top()); // Remove the tasks from the delayed tasks queue. task_queue_.pop(); @@ -63,7 +63,10 @@ std::chrono::nanoseconds TaskRunnerWin32::ProcessTasks() { { // Flushing tasks here without holing onto the task queue mutex. for (const auto& task : expired_tasks) { - on_task_expired_(&task); + if (auto flutter_task = std::get_if(&task.variant)) { + on_task_expired_(flutter_task); + } else if (auto closure = std::get_if(&task.variant)) + (*closure)(); } } @@ -84,15 +87,27 @@ TaskRunnerWin32::TaskTimePoint TaskRunnerWin32::TimePointFromFlutterTime( return now + std::chrono::nanoseconds(flutter_duration); } -void TaskRunnerWin32::PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) { - static std::atomic_uint64_t sGlobalTaskOrder(0); - +void TaskRunnerWin32::PostFlutterTask(FlutterTask flutter_task, + uint64_t flutter_target_time_nanos) { Task task; - task.order = ++sGlobalTaskOrder; task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos); - task.task = flutter_task; + task.variant = flutter_task; + EnqueueTask(std::move(task)); +} + +void TaskRunnerWin32::PostTask(TaskClosure closure, + std::optional target_time) { + Task task; + task.fire_time = + target_time ? target_time.value() : TaskTimePoint::clock::now(); + task.variant = closure; + EnqueueTask(std::move(task)); +} +void TaskRunnerWin32::EnqueueTask(Task task) { + static std::atomic_uint64_t sGlobalTaskOrder(0); + + task.order = ++sGlobalTaskOrder; { std::lock_guard lock(task_queue_mutex_); task_queue_.push(task); diff --git a/shell/platform/windows/task_runner_win32.h b/shell/platform/windows/task_runner_win32.h index 1ac2f64b861c5..28c77c968439c 100644 --- a/shell/platform/windows/task_runner_win32.h +++ b/shell/platform/windows/task_runner_win32.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/windows/task_runner.h" @@ -36,17 +37,22 @@ class TaskRunnerWin32 : public TaskRunner { bool RunsTasksOnCurrentThread() const override; // |TaskRunner| - void PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) override; + void PostFlutterTask(FlutterTask flutter_task, + uint64_t flutter_target_time_nanos) override; + + // |TaskRunner| + void PostTask(TaskClosure task, + std::optional target_time) override; std::chrono::nanoseconds ProcessTasks(); private: - using TaskTimePoint = std::chrono::steady_clock::time_point; + typedef std::variant TaskVariant; + struct Task { uint64_t order; TaskTimePoint fire_time; - FlutterTask task; + TaskVariant variant; struct Comparer { bool operator()(const Task& a, const Task& b) { @@ -58,6 +64,9 @@ class TaskRunnerWin32 : public TaskRunner { }; }; + // Enqueues the given task. + void EnqueueTask(Task task); + // Returns a TaskTimePoint computed from the given target time from Flutter. TaskTimePoint TimePointFromFlutterTime( uint64_t flutter_target_time_nanos) const; diff --git a/shell/platform/windows/task_runner_winuwp.cc b/shell/platform/windows/task_runner_winuwp.cc index a2fbe7040c412..1d4ec473de260 100644 --- a/shell/platform/windows/task_runner_winuwp.cc +++ b/shell/platform/windows/task_runner_winuwp.cc @@ -31,8 +31,8 @@ bool TaskRunnerWinUwp::RunsTasksOnCurrentThread() const { return GetCurrentThreadId() == main_thread_id_; } -void TaskRunnerWinUwp::PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) { +void TaskRunnerWinUwp::PostFlutterTask(FlutterTask flutter_task, + uint64_t flutter_target_time_nanos) { // TODO: Handle the target time. See // https://github.com/flutter/flutter/issues/70890. @@ -41,4 +41,12 @@ void TaskRunnerWinUwp::PostTask(FlutterTask flutter_task, [this, flutter_task]() { on_task_expired_(&flutter_task); }); } +void TaskRunnerWinUwp::PostTask(TaskClosure task, + std::optional target_time) { + // TODO: Handle the target time. See PostFlutterTask() + + dispatcher_.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, + [task]() { task() }); +} + } // namespace flutter diff --git a/shell/platform/windows/task_runner_winuwp.h b/shell/platform/windows/task_runner_winuwp.h index 49bdb4da587ce..7c73678be0892 100644 --- a/shell/platform/windows/task_runner_winuwp.h +++ b/shell/platform/windows/task_runner_winuwp.h @@ -34,8 +34,12 @@ class TaskRunnerWinUwp : public TaskRunner { bool RunsTasksOnCurrentThread() const override; // |TaskRunner| - void PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) override; + void PostFlutterTask(FlutterTask flutter_task, + uint64_t flutter_target_time_nanos) override; + + // |TaskRunner| + void PostTask(TaskClosure task, + std::optional target_time) override; private: DWORD main_thread_id_; From 256db6a64c2ed8b6582cc755e4a235e67814d783 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Fri, 8 Jan 2021 12:15:40 +0100 Subject: [PATCH 11/17] Windows textures: Use TaskRunner::PostTask --- .../windows/flutter_windows_texture_registrar.cc | 13 +++++++------ .../flutter_windows_texture_registrar_unittests.cc | 7 ------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc index d3f101cb2cda4..cbec6ae594f5b 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -53,12 +53,13 @@ bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( int64_t texture_id) { auto it = textures_.find(texture_id); if (it != textures_.end()) { - return engine_->PostPlatformThreadTask( - [](void* data) { - auto texture = reinterpret_cast(data); - texture->MarkFrameAvailable(); - }, - it->second.get()); + auto texture = it->second.get(); + if (engine_->task_runner()->RunsTasksOnCurrentThread()) { + texture->MarkFrameAvailable(); + } + engine_->task_runner()->PostTask( + [texture]() { texture->MarkFrameAvailable(); }); + return true; } return false; } diff --git a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc index fb1a0b57938dd..2183093bc9df5 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar_unittests.cc @@ -76,13 +76,6 @@ TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) { return kSuccess; })); - modifier.embedder_api().PostPlatformThreadTask = - MOCK_ENGINE_PROC(PostPlatformThreadTask, - ([](auto engine, auto callback, auto callback_data) { - callback(callback_data); - return kSuccess; - })); - auto texture_id = registrar.RegisterTexture(&texture_info); EXPECT_TRUE(register_called); EXPECT_NE(texture_id, -1); From fa221528ea8442b99664d40a06984c860bdb85f2 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Fri, 8 Jan 2021 12:27:42 +0100 Subject: [PATCH 12/17] Revert "Embedder API: Add PostPlatformThreadTask method" --- shell/platform/embedder/embedder.cc | 23 ------------------- shell/platform/embedder/embedder.h | 21 ----------------- shell/platform/embedder/embedder_engine.cc | 9 -------- shell/platform/embedder/embedder_engine.h | 2 -- .../windows/flutter_windows_engine.cc | 6 ----- .../platform/windows/flutter_windows_engine.h | 3 --- 6 files changed, 64 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index df6d56f1b68b4..1dc3ea6b448ed 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -1691,28 +1691,6 @@ void FlutterEngineTraceEventInstant(const char* name) { fml::tracing::TraceEventInstant0("flutter", name); } -FlutterEngineResult FlutterEnginePostPlatformThreadTask( - FLUTTER_API_SYMBOL(FlutterEngine) engine, - VoidCallback callback, - void* baton) { - if (engine == nullptr) { - return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle."); - } - - if (callback == nullptr) { - return LOG_EMBEDDER_ERROR(kInvalidArguments, - "Platform thread callback was null."); - } - - auto task = [callback, baton]() { callback(baton); }; - - return reinterpret_cast(engine) - ->PostPlatformThreadTask(task) - ? kSuccess - : LOG_EMBEDDER_ERROR(kInternalInconsistency, - "Could not post the platform thread task."); -} - FlutterEngineResult FlutterEnginePostRenderThreadTask( FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, @@ -2112,7 +2090,6 @@ FlutterEngineResult FlutterEngineGetProcAddresses( SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin); SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd); SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant); - SET_PROC(PostPlatformThreadTask, FlutterEnginePostPlatformThreadTask); SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask); SET_PROC(GetCurrentTime, FlutterEngineGetCurrentTime); SET_PROC(RunTask, FlutterEngineRunTask); diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index f54e3b73c4e1b..4819aa87fa611 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1786,24 +1786,6 @@ void FlutterEngineTraceEventDurationEnd(const char* name); FLUTTER_EXPORT void FlutterEngineTraceEventInstant(const char* name); -//------------------------------------------------------------------------------ -/// @brief Posts a task onto the Flutter platform thread. Typically, this -/// may be called from any thread as long as a -/// `FlutterEngineShutdown` on the specific engine has not already -/// been initiated. -/// -/// @param[in] engine A running engine instance. -/// @param[in] callback The callback to execute on the platform thread. -/// @param callback_data The callback context. -/// -/// @return The result of the call. -/// -FLUTTER_EXPORT -FlutterEngineResult FlutterEnginePostPlatformThreadTask( - FLUTTER_API_SYMBOL(FlutterEngine) engine, - VoidCallback callback, - void* callback_data); - //------------------------------------------------------------------------------ /// @brief Posts a task onto the Flutter render thread. Typically, this may /// be called from any thread as long as a `FlutterEngineShutdown` @@ -2080,8 +2062,6 @@ typedef FlutterEngineResult (*FlutterEnginePostRenderThreadTaskFnPtr)( FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, void* callback_data); -typedef FlutterEnginePostRenderThreadTaskFnPtr - FlutterEnginePostPlatformThreadTaskFnPtr; typedef uint64_t (*FlutterEngineGetCurrentTimeFnPtr)(); typedef FlutterEngineResult (*FlutterEngineRunTaskFnPtr)( FLUTTER_API_SYMBOL(FlutterEngine) engine, @@ -2149,7 +2129,6 @@ typedef struct { FlutterEnginePostCallbackOnAllNativeThreadsFnPtr PostCallbackOnAllNativeThreads; FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate; - FlutterEnginePostPlatformThreadTaskFnPtr PostPlatformThreadTask; } FlutterEngineProcTable; //------------------------------------------------------------------------------ diff --git a/shell/platform/embedder/embedder_engine.cc b/shell/platform/embedder/embedder_engine.cc index bf5b019338746..bb0aa08bb42d5 100644 --- a/shell/platform/embedder/embedder_engine.cc +++ b/shell/platform/embedder/embedder_engine.cc @@ -244,15 +244,6 @@ bool EmbedderEngine::ReloadSystemFonts() { return shell_->ReloadSystemFonts(); } -bool EmbedderEngine::PostPlatformThreadTask(const fml::closure& task) { - if (!IsValid()) { - return false; - } - - shell_->GetTaskRunners().GetPlatformTaskRunner()->PostTask(task); - return true; -} - bool EmbedderEngine::PostRenderThreadTask(const fml::closure& task) { if (!IsValid()) { return false; diff --git a/shell/platform/embedder/embedder_engine.h b/shell/platform/embedder/embedder_engine.h index a48dfa226dc9a..4f38ba4410cd0 100644 --- a/shell/platform/embedder/embedder_engine.h +++ b/shell/platform/embedder/embedder_engine.h @@ -82,8 +82,6 @@ class EmbedderEngine { bool ReloadSystemFonts(); - bool PostPlatformThreadTask(const fml::closure& task); - bool PostRenderThreadTask(const fml::closure& task); bool RunTask(const FlutterTask* task); diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 76a082e529a8d..8fcedb2a7ecdd 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -384,10 +384,4 @@ bool FlutterWindowsEngine::MarkExternalTextureFrameAvailable( engine_, texture_id) == kSuccess); } -bool FlutterWindowsEngine::PostPlatformThreadTask(VoidCallback callback, - void* callback_data) { - return (embedder_api_.PostPlatformThreadTask(engine_, callback, - callback_data) == kSuccess); -} - } // namespace flutter diff --git a/shell/platform/windows/flutter_windows_engine.h b/shell/platform/windows/flutter_windows_engine.h index 7fc8e55dd6788..5e2cac869c704 100644 --- a/shell/platform/windows/flutter_windows_engine.h +++ b/shell/platform/windows/flutter_windows_engine.h @@ -128,9 +128,6 @@ class FlutterWindowsEngine { // given |texture_id|. bool MarkExternalTextureFrameAvailable(int64_t texture_id); - // Posts a task onto the platform thread. - bool PostPlatformThreadTask(VoidCallback callback, void* callback_data); - private: // Allows swapping out embedder_api_ calls in tests. friend class EngineEmbedderApiModifier; From cfe1b34b6b08a9daa0a9e338ab6e52d4c50c677f Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Fri, 8 Jan 2021 13:21:08 +0100 Subject: [PATCH 13/17] Windows textures: Make texture registration/unregistration thread safe --- shell/platform/windows/external_texture_gl.cc | 10 +---- shell/platform/windows/external_texture_gl.h | 8 +--- .../flutter_windows_texture_registrar.cc | 40 ++++++++++--------- .../flutter_windows_texture_registrar.h | 7 +++- shell/platform/windows/task_runner.h | 10 +++++ 5 files changed, 39 insertions(+), 36 deletions(-) diff --git a/shell/platform/windows/external_texture_gl.cc b/shell/platform/windows/external_texture_gl.cc index 855e1a0fc29f1..50b9979c7b12e 100644 --- a/shell/platform/windows/external_texture_gl.cc +++ b/shell/platform/windows/external_texture_gl.cc @@ -4,8 +4,6 @@ #include "flutter/shell/platform/windows/external_texture_gl.h" -#include "flutter/shell/platform/windows/flutter_windows_engine.h" - #include #include #include @@ -68,11 +66,9 @@ struct ExternalTextureGLState { }; ExternalTextureGL::ExternalTextureGL( - FlutterWindowsEngine* engine, FlutterDesktopPixelBufferTextureCallback texture_callback, void* user_data) - : engine_(engine), - state_(std::make_unique()), + : state_(std::make_unique()), texture_callback_(texture_callback), user_data_(user_data) {} @@ -83,10 +79,6 @@ ExternalTextureGL::~ExternalTextureGL() { } } -void ExternalTextureGL::MarkFrameAvailable() { - engine_->MarkExternalTextureFrameAvailable(texture_id()); -} - bool ExternalTextureGL::PopulateTexture(size_t width, size_t height, FlutterOpenGLTexture* opengl_texture) { diff --git a/shell/platform/windows/external_texture_gl.h b/shell/platform/windows/external_texture_gl.h index 7ff69528a7654..a2e61f5e33ac4 100644 --- a/shell/platform/windows/external_texture_gl.h +++ b/shell/platform/windows/external_texture_gl.h @@ -16,13 +16,10 @@ namespace flutter { typedef struct ExternalTextureGLState ExternalTextureGLState; -class FlutterWindowsEngine; - // An abstraction of an OpenGL texture. class ExternalTextureGL { public: - ExternalTextureGL(FlutterWindowsEngine* engine, - FlutterDesktopPixelBufferTextureCallback texture_callback, + ExternalTextureGL(FlutterDesktopPixelBufferTextureCallback texture_callback, void* user_data); virtual ~ExternalTextureGL(); @@ -30,8 +27,6 @@ class ExternalTextureGL { // Returns the unique id of this texture. int64_t texture_id() { return reinterpret_cast(this); } - FlutterWindowsEngine* engine() { return engine_; } - void MarkFrameAvailable(); // Attempts to populate the specified |opengl_texture| with texture details @@ -54,7 +49,6 @@ class ExternalTextureGL { std::unique_ptr state_; FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr; void* user_data_ = nullptr; - FlutterWindowsEngine* engine_ = nullptr; }; } // namespace flutter diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc index cbec6ae594f5b..4d4e3f6bece6b 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -7,6 +7,7 @@ #include "flutter/shell/platform/windows/flutter_windows_engine.h" #include +#include namespace flutter { @@ -28,40 +29,41 @@ int64_t FlutterWindowsTextureRegistrar::RegisterTexture( } auto texture_gl = std::make_unique( - engine_, texture_info->pixel_buffer_config.callback, + texture_info->pixel_buffer_config.callback, texture_info->pixel_buffer_config.user_data); - int64_t texture_id = texture_gl->texture_id(); - textures_[texture_id] = std::move(texture_gl); - if (engine_->RegisterExternalTexture(texture_id)) { - return texture_id; + { + std::lock_guard lock(map_mutex_); + textures_[texture_id] = std::move(texture_gl); } - return -1; + engine_->task_runner()->RunNowOrPostTask( + [texture_id, this]() { engine_->RegisterExternalTexture(texture_id); }); + + return texture_id; } bool FlutterWindowsTextureRegistrar::UnregisterTexture(int64_t texture_id) { + std::lock_guard lock(map_mutex_); + auto it = textures_.find(texture_id); if (it != textures_.end()) { textures_.erase(it); + engine_->task_runner()->RunNowOrPostTask([texture_id, this]() { + engine_->UnregisterExternalTexture(texture_id); + }); + return true; } - return engine_->UnregisterExternalTexture(texture_id); + return false; } bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( int64_t texture_id) { - auto it = textures_.find(texture_id); - if (it != textures_.end()) { - auto texture = it->second.get(); - if (engine_->task_runner()->RunsTasksOnCurrentThread()) { - texture->MarkFrameAvailable(); - } - engine_->task_runner()->PostTask( - [texture]() { texture->MarkFrameAvailable(); }); - return true; - } - return false; + engine_->task_runner()->RunNowOrPostTask([this, texture_id]() { + engine_->MarkExternalTextureFrameAvailable(texture_id); + }); + return true; } bool FlutterWindowsTextureRegistrar::PopulateTexture( @@ -69,6 +71,8 @@ bool FlutterWindowsTextureRegistrar::PopulateTexture( size_t width, size_t height, FlutterOpenGLTexture* texture) { + std::lock_guard lock(map_mutex_); + auto it = textures_.find(texture_id); if (it != textures_.end()) { return it->second->PopulateTexture(width, height, texture); diff --git a/shell/platform/windows/flutter_windows_texture_registrar.h b/shell/platform/windows/flutter_windows_texture_registrar.h index 6db0e29e08823..cf7ff73377458 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.h +++ b/shell/platform/windows/flutter_windows_texture_registrar.h @@ -5,8 +5,9 @@ #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_TEXTURE_REGISTRAR_H_ #define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_TEXTURE_REGISTRAR_H_ -#include #include +#include +#include #include "flutter/shell/platform/windows/external_texture_gl.h" @@ -43,7 +44,9 @@ class FlutterWindowsTextureRegistrar { FlutterWindowsEngine* engine_ = nullptr; // All registered textures, keyed by their IDs. - std::map> textures_; + std::unordered_map> + textures_; + std::mutex map_mutex_; }; }; // namespace flutter diff --git a/shell/platform/windows/task_runner.h b/shell/platform/windows/task_runner.h index 4ac58f7b0a56c..9cf5daa1bedd5 100644 --- a/shell/platform/windows/task_runner.h +++ b/shell/platform/windows/task_runner.h @@ -39,6 +39,16 @@ class TaskRunner { TaskClosure task, std::optional target_time = std::nullopt) = 0; + // Post a task to the event loop or run it immediately if this is being called + // from the main thread. + void RunNowOrPostTask(TaskClosure task) { + if (RunsTasksOnCurrentThread()) { + task(); + } else { + PostTask(std::move(task)); + } + } + // Creates a new task runner with the given main thread ID, current time // provider, and callback for tasks that are ready to be run. static std::unique_ptr Create( From 1d8057d6a004cdc20a3b3107e979ee6dab776d56 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Fri, 8 Jan 2021 14:22:20 +0100 Subject: [PATCH 14/17] Windows textures: Improve comments in terms of thread safety --- .../include/flutter/texture_registrar.h | 12 +++++++++++- .../common/cpp/public/flutter_texture_registrar.h | 9 +++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h index 0bd6978751895..2caa348daef88 100644 --- a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -25,6 +25,9 @@ class PixelBufferTexture { // Creates a pixel buffer texture that uses the provided |copy_buffer_cb| to // retrieve the buffer. + // As the callback is usually invoked from the render thread, the callee must + // take care of proper synchronization. It also needs to be ensured that the + // returned buffer isn't released prior to unregistering this texture. PixelBufferTexture(CopyBufferCb copy_buffer_cb) : copy_buffer_cb_(copy_buffer_cb) {} @@ -47,6 +50,9 @@ class PixelBufferTexture { typedef std::variant TextureVariant; // An object keeping track of external textures. +// +// Thread safety: +// It's safe to call the member methods from any thread. class TextureRegistrar { public: virtual ~TextureRegistrar() = default; @@ -55,10 +61,14 @@ class TextureRegistrar { virtual int64_t RegisterTexture(TextureVariant* texture) = 0; // Notifies the flutter engine that the texture object corresponding - // to |texure_id| needs to render a new texture. + // to |texure_id| needs to render a new frame. + // + // For PixelBufferTextures, this will effectively make the engine invoke + // the callback that was provided upon creating the texture. virtual bool MarkTextureFrameAvailable(int64_t texture_id) = 0; // Unregisters an existing Texture object. + // Textures must not be unregistered while they're in use. virtual bool UnregisterTexture(int64_t texture_id) = 0; }; diff --git a/shell/platform/common/cpp/public/flutter_texture_registrar.h b/shell/platform/common/cpp/public/flutter_texture_registrar.h index dacb9013cad3e..81219d64e662c 100644 --- a/shell/platform/common/cpp/public/flutter_texture_registrar.h +++ b/shell/platform/common/cpp/public/flutter_texture_registrar.h @@ -40,6 +40,11 @@ typedef struct { // the Flutter engine to copy the texture. // It is invoked with the intended surface size specified by |width| and // |height| and the |user_data| held by FlutterDesktopPixelBufferTextureConfig. +// +// As this is usually called from the render thread, the callee must take +// care of proper synchronization. It also needs to be ensured that the +// returned FlutterDesktopPixelBuffer isn't released prior to unregistering +// the corresponding texture. typedef const FlutterDesktopPixelBuffer* ( *FlutterDesktopPixelBufferTextureCallback)(size_t width, size_t height, @@ -61,18 +66,22 @@ typedef struct { } FlutterDesktopTextureInfo; // Registers a new texture with the Flutter engine and returns the texture ID. +// This function can be called from any thread. FLUTTER_EXPORT int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture( FlutterDesktopTextureRegistrarRef texture_registrar, const FlutterDesktopTextureInfo* info); // Unregisters an existing texture from the Flutter engine for a |texture_id|. // Returns true on success or false if the specified texture doesn't exist. +// This function can be called from any thread. +// However, textures must not be unregistered while they're in use. FLUTTER_EXPORT bool FlutterDesktopTextureRegistrarUnregisterExternalTexture( FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id); // Marks that a new texture frame is available for a given |texture_id|. // Returns true on success or false if the specified texture doesn't exist. +// This function can be called from any thread. FLUTTER_EXPORT bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable( FlutterDesktopTextureRegistrarRef texture_registrar, From c69c9273a243044cf06f21f82f4337af403b30d5 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Mon, 11 Jan 2021 19:56:21 +0100 Subject: [PATCH 15/17] Windows task runner: PostTask: Remove unused target_time parameter --- shell/platform/windows/task_runner.h | 8 ++------ shell/platform/windows/task_runner_win32.cc | 8 +++----- shell/platform/windows/task_runner_win32.h | 3 +-- shell/platform/windows/task_runner_winuwp.cc | 3 +-- shell/platform/windows/task_runner_winuwp.h | 3 +-- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/shell/platform/windows/task_runner.h b/shell/platform/windows/task_runner.h index 9cf5daa1bedd5..0e3d44450281e 100644 --- a/shell/platform/windows/task_runner.h +++ b/shell/platform/windows/task_runner.h @@ -9,7 +9,6 @@ #include #include -#include #include "flutter/shell/platform/embedder/embedder.h" @@ -33,11 +32,8 @@ class TaskRunner { virtual void PostFlutterTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos) = 0; - // Post a task to the event loop for delayed execution with an optional target - // time. - virtual void PostTask( - TaskClosure task, - std::optional target_time = std::nullopt) = 0; + // Post a task to the event loop. + virtual void PostTask(TaskClosure task) = 0; // Post a task to the event loop or run it immediately if this is being called // from the main thread. diff --git a/shell/platform/windows/task_runner_win32.cc b/shell/platform/windows/task_runner_win32.cc index e85f37c50a908..d51a52879de1e 100644 --- a/shell/platform/windows/task_runner_win32.cc +++ b/shell/platform/windows/task_runner_win32.cc @@ -95,12 +95,10 @@ void TaskRunnerWin32::PostFlutterTask(FlutterTask flutter_task, EnqueueTask(std::move(task)); } -void TaskRunnerWin32::PostTask(TaskClosure closure, - std::optional target_time) { +void TaskRunnerWin32::PostTask(TaskClosure closure) { Task task; - task.fire_time = - target_time ? target_time.value() : TaskTimePoint::clock::now(); - task.variant = closure; + task.fire_time = TaskTimePoint::clock::now(); + task.variant = std::move(closure); EnqueueTask(std::move(task)); } diff --git a/shell/platform/windows/task_runner_win32.h b/shell/platform/windows/task_runner_win32.h index 28c77c968439c..cd7e3dd877620 100644 --- a/shell/platform/windows/task_runner_win32.h +++ b/shell/platform/windows/task_runner_win32.h @@ -41,8 +41,7 @@ class TaskRunnerWin32 : public TaskRunner { uint64_t flutter_target_time_nanos) override; // |TaskRunner| - void PostTask(TaskClosure task, - std::optional target_time) override; + void PostTask(TaskClosure task) override; std::chrono::nanoseconds ProcessTasks(); diff --git a/shell/platform/windows/task_runner_winuwp.cc b/shell/platform/windows/task_runner_winuwp.cc index 1d4ec473de260..8bfc4c9cbd2cc 100644 --- a/shell/platform/windows/task_runner_winuwp.cc +++ b/shell/platform/windows/task_runner_winuwp.cc @@ -41,8 +41,7 @@ void TaskRunnerWinUwp::PostFlutterTask(FlutterTask flutter_task, [this, flutter_task]() { on_task_expired_(&flutter_task); }); } -void TaskRunnerWinUwp::PostTask(TaskClosure task, - std::optional target_time) { +void TaskRunnerWinUwp::PostTask(TaskClosure task) { // TODO: Handle the target time. See PostFlutterTask() dispatcher_.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, diff --git a/shell/platform/windows/task_runner_winuwp.h b/shell/platform/windows/task_runner_winuwp.h index 7c73678be0892..654dd0e54dc97 100644 --- a/shell/platform/windows/task_runner_winuwp.h +++ b/shell/platform/windows/task_runner_winuwp.h @@ -38,8 +38,7 @@ class TaskRunnerWinUwp : public TaskRunner { uint64_t flutter_target_time_nanos) override; // |TaskRunner| - void PostTask(TaskClosure task, - std::optional target_time) override; + void PostTask(TaskClosure task) override; private: DWORD main_thread_id_; From 8e2a2bc1080ed59cdbb57c9984a9518adf79040d Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Mon, 11 Jan 2021 19:59:14 +0100 Subject: [PATCH 16/17] Windows textures: minimize lock scope --- .../flutter_windows_texture_registrar.cc | 46 +++++++++++-------- .../flutter_windows_texture_registrar.h | 1 + 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/shell/platform/windows/flutter_windows_texture_registrar.cc b/shell/platform/windows/flutter_windows_texture_registrar.cc index 4d4e3f6bece6b..f6c10db14b713 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.cc +++ b/shell/platform/windows/flutter_windows_texture_registrar.cc @@ -38,30 +38,33 @@ int64_t FlutterWindowsTextureRegistrar::RegisterTexture( textures_[texture_id] = std::move(texture_gl); } - engine_->task_runner()->RunNowOrPostTask( - [texture_id, this]() { engine_->RegisterExternalTexture(texture_id); }); + engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() { + engine->RegisterExternalTexture(texture_id); + }); return texture_id; } bool FlutterWindowsTextureRegistrar::UnregisterTexture(int64_t texture_id) { - std::lock_guard lock(map_mutex_); - - auto it = textures_.find(texture_id); - if (it != textures_.end()) { + { + std::lock_guard lock(map_mutex_); + auto it = textures_.find(texture_id); + if (it == textures_.end()) { + return false; + } textures_.erase(it); - engine_->task_runner()->RunNowOrPostTask([texture_id, this]() { - engine_->UnregisterExternalTexture(texture_id); - }); - return true; } - return false; + + engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() { + engine->UnregisterExternalTexture(texture_id); + }); + return true; } bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( int64_t texture_id) { - engine_->task_runner()->RunNowOrPostTask([this, texture_id]() { - engine_->MarkExternalTextureFrameAvailable(texture_id); + engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() { + engine->MarkExternalTextureFrameAvailable(texture_id); }); return true; } @@ -70,14 +73,17 @@ bool FlutterWindowsTextureRegistrar::PopulateTexture( int64_t texture_id, size_t width, size_t height, - FlutterOpenGLTexture* texture) { - std::lock_guard lock(map_mutex_); - - auto it = textures_.find(texture_id); - if (it != textures_.end()) { - return it->second->PopulateTexture(width, height, texture); + FlutterOpenGLTexture* opengl_texture) { + flutter::ExternalTextureGL* texture; + { + std::lock_guard lock(map_mutex_); + auto it = textures_.find(texture_id); + if (it == textures_.end()) { + return false; + } + texture = it->second.get(); } - return false; + return texture->PopulateTexture(width, height, opengl_texture); } }; // namespace flutter diff --git a/shell/platform/windows/flutter_windows_texture_registrar.h b/shell/platform/windows/flutter_windows_texture_registrar.h index cf7ff73377458..75d724f799b61 100644 --- a/shell/platform/windows/flutter_windows_texture_registrar.h +++ b/shell/platform/windows/flutter_windows_texture_registrar.h @@ -16,6 +16,7 @@ namespace flutter { class FlutterWindowsEngine; // An object managing the registration of an external texture. +// Thread safety: All member methods are thread safe. class FlutterWindowsTextureRegistrar { public: explicit FlutterWindowsTextureRegistrar(FlutterWindowsEngine* engine); From 3e9977efbef8950ca84e2e3b147f61d27a09289c Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Mon, 11 Jan 2021 20:02:04 +0100 Subject: [PATCH 17/17] Windows textures: Clean up comments --- .../include/flutter/texture_registrar.h | 20 +++++++++---------- .../texture_registrar_unittests.cc | 3 ++- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h index 2caa348daef88..77b1e167b6bcc 100644 --- a/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -6,13 +6,12 @@ #define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_ #include -#include +#include +#include #include #include -#include - namespace flutter { // A pixel buffer texture. @@ -21,32 +20,31 @@ class PixelBufferTexture { // A callback used for retrieving pixel buffers. typedef std::function - CopyBufferCb; + CopyBufferCallback; // Creates a pixel buffer texture that uses the provided |copy_buffer_cb| to // retrieve the buffer. // As the callback is usually invoked from the render thread, the callee must // take care of proper synchronization. It also needs to be ensured that the // returned buffer isn't released prior to unregistering this texture. - PixelBufferTexture(CopyBufferCb copy_buffer_cb) - : copy_buffer_cb_(copy_buffer_cb) {} + PixelBufferTexture(CopyBufferCallback copy_buffer_callback) + : copy_buffer_callback_(copy_buffer_callback) {} // Returns the callback-provided FlutterDesktopPixelBuffer that contains the // actual pixel data. The intended surface size is specified by |width| and // |height|. const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width, size_t height) const { - return copy_buffer_cb_(width, height); + return copy_buffer_callback_(width, height); } private: - const CopyBufferCb copy_buffer_cb_; + const CopyBufferCallback copy_buffer_callback_; }; // The available texture variants. -// While PixelBufferTexture is the only implementation we currently have, -// this is going to be extended once we have additional implementations like -// PBO-based textures etc. +// Only PixelBufferTexture is currently implemented. +// Other variants are expected to be added in the future. typedef std::variant TextureVariant; // An object keeping track of external textures. diff --git a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc index a10dcffdca26b..6a0718462e5c9 100644 --- a/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc +++ b/shell/platform/common/cpp/client_wrapper/texture_registrar_unittests.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h" + #include #include #include #include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h" -#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h" #include "flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h" #include "gtest/gtest.h"