diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 14b2dbd8cd4a1..b2735bd17ef95 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -690,6 +690,7 @@ FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/ FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registry.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/json_message_codec.cc FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/json_method_codec.cc FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/method_call_unittests.cc @@ -704,6 +705,7 @@ FILE: ../../../flutter/shell/platform/common/cpp/incoming_message_dispatcher.h 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/darwin/common/buffer_conversions.h @@ -993,6 +995,8 @@ FILE: ../../../flutter/shell/platform/glfw/client_wrapper/flutter_window_control FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window_controller.h FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/plugin_registrar_glfw.h +FILE: ../../../flutter/shell/platform/glfw/external_texture_gl.cc +FILE: ../../../flutter/shell/platform/glfw/external_texture_gl.h FILE: ../../../flutter/shell/platform/glfw/flutter_glfw.cc FILE: ../../../flutter/shell/platform/glfw/glfw_event_loop.cc FILE: ../../../flutter/shell/platform/glfw/glfw_event_loop.h diff --git a/shell/platform/common/cpp/BUILD.gn b/shell/platform/common/cpp/BUILD.gn index ac678700d86b6..9d26a8a518f96 100644 --- a/shell/platform/common/cpp/BUILD.gn +++ b/shell/platform/common/cpp/BUILD.gn @@ -10,6 +10,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/core_wrapper_files.gni b/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni index ce91be7866717..1f5f3c56ec87f 100644 --- a/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni +++ b/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni @@ -18,6 +18,7 @@ core_cpp_client_wrapper_includes = "include/flutter/method_result.h", "include/flutter/plugin_registrar.h", "include/flutter/plugin_registry.h", + "include/flutter/texture_registrar.h", "include/flutter/standard_message_codec.h", "include/flutter/standard_method_codec.h", ], 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 5fbe1b5b6297c..fffa66d37471b 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 @@ -12,6 +12,7 @@ #include #include "binary_messenger.h" +#include "texture_registrar.h" namespace flutter { @@ -40,6 +41,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* textures() { return textures_.get(); } + // Takes ownership of |plugin|. // // Plugins are not required to call this method if they have other lifetime @@ -59,6 +64,8 @@ class PluginRegistrar { std::unique_ptr messenger_; + std::unique_ptr textures_; + // 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..b3cff321c6e0a --- /dev/null +++ b/shell/platform/common/cpp/client_wrapper/include/flutter/texture_registrar.h @@ -0,0 +1,49 @@ +// 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 external texture interface declaration. +class Texture { + public: + virtual ~Texture() {} + // This interface is used to respond to texture copy requests from the Flutter + // engine, Flutter engine will be providing the |height| and |width| + // parameters of bounds. In some cases, the user can be scale the texture to + // the size of the bounds to reduce memory usage. + virtual const PixelBuffer* CopyPixelBuffer(size_t width, size_t height) = 0; +}; + +class TextureRegistrar { + public: + virtual ~TextureRegistrar() {} + + /** + * Registers a |texture| object and returns the ID for that texture. + */ + virtual int64_t RegisterTexture(Texture* texture) = 0; + + /** + * Notify the flutter engine that the texture object corresponding + * to |texure_id| needs to render a new texture. + */ + virtual void MarkTextureFrameAvailable(int64_t texture_id) = 0; + + /** + * Unregisters an existing Texture object. + */ + virtual void 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 7ca7c3de73b1c..352a390ddff8e 100644 --- a/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc +++ b/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc @@ -138,12 +138,52 @@ void BinaryMessengerImpl::SetMessageHandler(const std::string& channel, ForwardToHandler, message_handler); } +// Wrapper around a FlutterDesktopTextureRegistrarRef that implements the +// TextureRegistrar API. +class TextureRegistrarImpl : public TextureRegistrar { + public: + explicit TextureRegistrarImpl( + FlutterDesktopTextureRegistrarRef texture_registrar_ref) + : texture_registrar_ref_(texture_registrar_ref) {} + + virtual ~TextureRegistrarImpl() = default; + + // Prevent copying. + TextureRegistrarImpl(TextureRegistrarImpl const&) = delete; + TextureRegistrarImpl& operator=(TextureRegistrarImpl const&) = delete; + + virtual int64_t RegisterTexture(Texture* texture) override { + FlutterTextureCallback callback = + [](size_t width, size_t height, void* user_data) -> const PixelBuffer* { + return static_cast(user_data)->CopyPixelBuffer(width, height); + }; + int64_t texture_id = FlutterDesktopRegisterExternalTexture( + texture_registrar_ref_, callback, texture); + return texture_id; + } + + virtual void MarkTextureFrameAvailable(int64_t texture_id) override { + FlutterDesktopMarkExternalTextureFrameAvailable(texture_registrar_ref_, + texture_id); + } + + virtual void UnregisterTexture(int64_t texture_id) override { + FlutterDesktopUnregisterExternalTexture(texture_registrar_ref_, texture_id); + } + + private: + // Handle for interacting with the C API. + FlutterDesktopTextureRegistrarRef texture_registrar_ref_; +}; + // PluginRegistrar: PluginRegistrar::PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar) : registrar_(registrar) { auto core_messenger = FlutterDesktopRegistrarGetMessenger(registrar_); messenger_ = std::make_unique(core_messenger); + auto texture_registrar = FlutterDesktopGetTextureRegistrar(registrar_); + textures_ = 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 22ca10ea58f27..1d06f17cf9d09 100644 --- a/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc +++ b/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc @@ -2,10 +2,12 @@ // 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" @@ -15,6 +17,14 @@ 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; + FlutterTextureCallback texture_callback; + void* user_data; + }; + public: // |flutter::testing::StubFlutterApi| bool MessengerSend(const char* channel, @@ -34,8 +44,53 @@ class TestApi : public testing::StubFlutterApi { const uint8_t* last_data_sent() { return last_data_sent_; } + int64_t RegisterExternalTexture(FlutterTextureCallback 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 UnregisterExternalTexture(int64_t texture_id) override { + auto it = textures_.find(texture_id); + if (it != textures_.end()) { + textures_.erase(it); + return true; + } + return false; + } + + bool TextureFrameAvailable(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: const uint8_t* last_data_sent_ = nullptr; + int64_t last_texture_id_ = -1; + std::map> textures_; }; } // namespace @@ -55,4 +110,37 @@ TEST(MethodCallTest, MessengerSend) { EXPECT_EQ(test_api->last_data_sent(), &message[0]); } +// Tests texture register that calls through to the C API. +TEST(MethodCallTest, RegisterTexture) { + 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.textures(); + + 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); + textures->MarkTextureFrameAvailable(texture_id); + EXPECT_EQ(texture->mark_count, 3); + + textures->UnregisterTexture(texture_id); + texture = test_api->GetFakeTexture(texture_id); + EXPECT_EQ(texture, nullptr); + EXPECT_EQ(test_api->textures_size(), static_cast(0)); +} + } // 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 4bd6ddce01a39..34e09c98673ec 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 @@ -44,6 +44,43 @@ FlutterDesktopMessengerRef FlutterDesktopRegistrarGetMessenger( return reinterpret_cast(1); } +FlutterDesktopTextureRegistrarRef FlutterDesktopGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + return reinterpret_cast(1); +} + +int64_t FlutterDesktopRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterTextureCallback texture_callback, + void* user_data) { + uint64_t result = -1; + if (s_stub_implementation) { + result = s_stub_implementation->RegisterExternalTexture(texture_callback, + user_data); + } + return result; +} + +bool FlutterDesktopUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + bool result = false; + if (s_stub_implementation) { + result = s_stub_implementation->UnregisterExternalTexture(texture_id); + } + return result; +} + +bool FlutterDesktopMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + bool result = false; + if (s_stub_implementation) { + result = s_stub_implementation->TextureFrameAvailable(texture_id); + } + return result; +} + void FlutterDesktopRegistrarEnableInputBlocking( FlutterDesktopPluginRegistrarRef registrar, const char* channel) { 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 c5f9dbbb2a2a5..cfe485188fbb5 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 @@ -63,6 +63,19 @@ class StubFlutterApi { virtual void MessengerSetCallback(const char* channel, FlutterDesktopMessageCallback callback, void* user_data) {} + + // Called for FlutterDesktopRegisterExternalTexture. + virtual int64_t RegisterExternalTexture( + FlutterTextureCallback texture_callback, + void* user_data) { + return -1; + } + + // Called for FlutterDesktopUnregisterExternalTexture. + virtual bool UnregisterExternalTexture(int64_t texture_id) { return false; } + + // Called for FlutterDesktopMarkExternalTextureFrameAvailable. + virtual bool TextureFrameAvailable(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/public/flutter_plugin_registrar.h b/shell/platform/common/cpp/public/flutter_plugin_registrar.h index 1caa3cee1f9e4..1cde2eae06008 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" { @@ -22,6 +23,10 @@ typedef struct FlutterDesktopPluginRegistrar* FlutterDesktopPluginRegistrarRef; FLUTTER_EXPORT FlutterDesktopMessengerRef FlutterDesktopRegistrarGetMessenger(FlutterDesktopPluginRegistrarRef registrar); +// Returns the texture registrar associated with this registrar. +FLUTTER_EXPORT FlutterDesktopTextureRegistrarRef +FlutterDesktopGetTextureRegistrar(FlutterDesktopPluginRegistrarRef registrar); + // Enables input blocking on the given channel. // // If set, then the Flutter window will disable input callbacks 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..0f57ffc685b8f --- /dev/null +++ b/shell/platform/common/cpp/public/flutter_texture_registrar.h @@ -0,0 +1,62 @@ +// 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 + +// Opaque reference to a texture registrar. +typedef struct FlutterDesktopTextureRegistrar* + FlutterDesktopTextureRegistrarRef; + +// Constructs a pixel buffer object for the plugin side, providing +// height/width and buffer pointers. +typedef struct { + // Bitmap buffer pointer, currently only supports RGBA. + const uint8_t* buffer; + // Width of the pixel buffer. + size_t width; + // Height of the pixel buffer. + size_t height; +} PixelBuffer; + +// The pixel buffer copy callback definition is provided to +// the Flutter engine to copy the texture. +typedef const PixelBuffer* (*FlutterTextureCallback)(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 plugin caller. +FLUTTER_EXPORT int64_t FlutterDesktopRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterTextureCallback texture_callback, + void* user_data); + +// Unregisters an existing texture from the Flutter engine for a |texture_id|. +// Returns true on success, false on failure. +FLUTTER_EXPORT bool FlutterDesktopUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id); + +// Marks that a new texture frame is available for a given |texture_id|. +// Returns true on success, false on failure. +FLUTTER_EXPORT bool FlutterDesktopMarkExternalTextureFrameAvailable( + 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/fuchsia/runtime/dart/utils/BUILD.gn b/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn index b1c94a762da59..1dca94e3c2acd 100644 --- a/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn +++ b/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn @@ -34,10 +34,10 @@ source_set("utils") { "$fuchsia_sdk_root/pkg:async-loop-default", "$fuchsia_sdk_root/pkg:fdio", "$fuchsia_sdk_root/pkg:memfs", - "$fuchsia_sdk_root/pkg:syslog", - "$fuchsia_sdk_root/pkg:zx", "$fuchsia_sdk_root/pkg:sys_cpp", + "$fuchsia_sdk_root/pkg:syslog", "$fuchsia_sdk_root/pkg:vfs_cpp", + "$fuchsia_sdk_root/pkg:zx", "//third_party/tonic", ] diff --git a/shell/platform/glfw/BUILD.gn b/shell/platform/glfw/BUILD.gn index f751aa23ce767..f2fa99cdf3b6f 100644 --- a/shell/platform/glfw/BUILD.gn +++ b/shell/platform/glfw/BUILD.gn @@ -32,6 +32,8 @@ source_set("flutter_glfw_headers") { source_set("flutter_glfw") { sources = [ + "external_texture_gl.cc", + "external_texture_gl.h", "flutter_glfw.cc", "glfw_event_loop.cc", "glfw_event_loop.h", @@ -56,10 +58,10 @@ source_set("flutter_glfw") { "$flutter_root/shell/platform/common/cpp/client_wrapper:client_wrapper", "$flutter_root/shell/platform/embedder:embedder_with_symbol_prefix", "$flutter_root/shell/platform/glfw/client_wrapper:client_wrapper_glfw", + "$flutter_root/third_party/glad", "//build/secondary/third_party/glfw", "//third_party/rapidjson", ] - if (is_linux) { libs = [ "GL" ] diff --git a/shell/platform/glfw/external_texture_gl.cc b/shell/platform/glfw/external_texture_gl.cc new file mode 100644 index 0000000000000..e4eafc18f89ad --- /dev/null +++ b/shell/platform/glfw/external_texture_gl.cc @@ -0,0 +1,83 @@ +// 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/glfw/external_texture_gl.h" + +#include + +// glad/gl.h must be included before GLFW/glfw3.h. +#include + +#include + +namespace flutter { + +// Just to not declare GLFWwindow and GLuint in the header. +struct ExternalTextureGLState { + GLFWwindow* window; + GLuint gl_texture; +}; + +ExternalTextureGL::ExternalTextureGL(FlutterTextureCallback texture_callback, + void* user_data) + : state_(std::make_unique()), + texture_callback_(texture_callback), + user_data_(user_data) {} + +ExternalTextureGL::~ExternalTextureGL() { + if (state_->gl_texture != 0) + glDeleteTextures(1, &state_->gl_texture); +} + +bool ExternalTextureGL::PopulateTextureWithIdentifier( + size_t width, + size_t height, + FlutterOpenGLTexture* opengl_texture) { + // Confirm that the current window context is available. + if (!state_->window) { + state_->window = glfwGetCurrentContext(); + if (!state_->window) { + std::cerr << "Failed to get window context in current thread." + << std::endl; + return false; + } + glfwMakeContextCurrent(state_->window); + // Load GL functions. + gladLoadGL(); + } + + const PixelBuffer* pixel_buffer = + texture_callback_(width, height, user_data_); + + if (!pixel_buffer || !pixel_buffer->buffer) { + std::cerr << "Failed to copy pixel buffer from plugin." << std::endl; + return false; + } + + if (state_->gl_texture == 0) { + glGenTextures(1, &state_->gl_texture); + glBindTexture(GL_TEXTURE_2D, state_->gl_texture); + // set the texture wrapping parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glBindTexture(GL_TEXTURE_2D, state_->gl_texture); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixel_buffer->width, + pixel_buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixel_buffer->buffer); + + opengl_texture->target = GL_TEXTURE_2D; + opengl_texture->name = state_->gl_texture; + opengl_texture->format = GL_RGBA8; + opengl_texture->destruction_callback = (VoidCallback) nullptr; + opengl_texture->user_data = static_cast(this); + return true; +} + +} // namespace flutter diff --git a/shell/platform/glfw/external_texture_gl.h b/shell/platform/glfw/external_texture_gl.h new file mode 100644 index 0000000000000..a7a544fe14b48 --- /dev/null +++ b/shell/platform/glfw/external_texture_gl.h @@ -0,0 +1,50 @@ +// 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_GLFW_EXTERNAL_TEXTURE_GL_H_ +#define FLUTTER_SHELL_PLATFORM_GLFW_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 adaptation class of flutter engine and external texture interface. +class ExternalTextureGL { + public: + ExternalTextureGL(FlutterTextureCallback texture_callback, void* user_data); + + virtual ~ExternalTextureGL(); + + /** + * Returns the unique id for the ExternalTextureGL instance. + */ + int64_t texture_id() { return reinterpret_cast(this); } + + /** + * Accepts texture buffer copy request from the Flutter engine. + * When the user side marks the texture_id as available, the Flutter engine + * will callback to this method and ask for populate the |opengl_texture| + * object, such as the texture type and the format of the pixel buffer and the + * texture object. + * Returns true on success, false on failure. + */ + bool PopulateTextureWithIdentifier(size_t width, + size_t height, + FlutterOpenGLTexture* opengl_texture); + + private: + std::unique_ptr state_; + FlutterTextureCallback texture_callback_ = nullptr; + void* user_data_ = nullptr; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_GLFW_EXTERNAL_TEXTURE_GL_H_ diff --git a/shell/platform/glfw/flutter_glfw.cc b/shell/platform/glfw/flutter_glfw.cc index b91dbdd93cf62..eb56d8b977697 100644 --- a/shell/platform/glfw/flutter_glfw.cc +++ b/shell/platform/glfw/flutter_glfw.cc @@ -13,8 +13,10 @@ #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/incoming_message_dispatcher.h" #include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/glfw/external_texture_gl.h" #include "flutter/shell/platform/glfw/glfw_event_loop.h" #include "flutter/shell/platform/glfw/key_event_handler.h" #include "flutter/shell/platform/glfw/keyboard_hook_handler.h" @@ -54,6 +56,9 @@ struct FlutterDesktopWindowControllerState { // The plugin registrar handle given to API clients. std::unique_ptr plugin_registrar; + // The plugin texture registrar handle given to API clients. + std::unique_ptr texture_registrar; + // Message dispatch manager for messages from the Flutter engine. std::unique_ptr message_dispatcher; @@ -112,10 +117,20 @@ struct FlutterDesktopPluginRegistrar { // The plugin messenger handle given to API clients. std::unique_ptr messenger; + // The plugin texture registrar handle given to API clients. + FlutterDesktopTextureRegistrar* texture_registrar; + // The handle for the window associated with this registrar. FlutterDesktopWindow* window; }; +// State associated with the texture registrar. +struct FlutterDesktopTextureRegistrar { + FLUTTER_API_SYMBOL(FlutterEngine) engine; + // The texture registrar managing external texture adapters. + std::map> textures; +}; + // State associated with the messenger used to communicate with the engine. struct FlutterDesktopMessenger { // The Flutter engine this messenger sends outgoing messages to. @@ -478,6 +493,17 @@ static void* GLFWProcResolver(void* user_data, const char* name) { return reinterpret_cast(glfwGetProcAddress(name)); } +static bool OnAcquireExternalTexture(void* user_data, + int64_t texture_id, + size_t width, + size_t height, + FlutterOpenGLTexture* texture) { + GLFWwindow* window = reinterpret_cast(user_data); + auto state = GetSavedWindowState(window); + return state->plugin_registrar->texture_registrar->textures[texture_id] + ->PopulateTextureWithIdentifier(width, height, texture); +} + static void GLFWErrorCallback(int error_code, const char* description) { std::cerr << "GLFW error " << error_code << ": " << description << std::endl; } @@ -520,6 +546,8 @@ static FLUTTER_API_SYMBOL(FlutterEngine) config.open_gl.fbo_callback = GLFWGetActiveFbo; config.open_gl.make_resource_current = GLFWMakeResourceContextCurrent; config.open_gl.gl_proc_resolver = GLFWProcResolver; + config.open_gl.gl_external_texture_frame_callback = + OnAcquireExternalTexture; } FlutterProjectArgs args = {}; args.struct_size = sizeof(FlutterProjectArgs); @@ -625,6 +653,12 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow( state->plugin_registrar->messenger = std::move(messenger); state->plugin_registrar->window = state->window_wrapper.get(); + std::unique_ptr textures = + std::make_unique(); + textures->engine = state->engine; + state->texture_registrar = std::move(textures); + state->plugin_registrar->texture_registrar = state->texture_registrar.get(); + state->internal_plugin_registrar = std::make_unique(state->plugin_registrar.get()); @@ -795,6 +829,11 @@ FlutterDesktopMessengerRef FlutterDesktopRegistrarGetMessenger( return registrar->messenger.get(); } +FlutterDesktopTextureRegistrarRef FlutterDesktopGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + return registrar->texture_registrar; +} + FlutterDesktopWindowRef FlutterDesktopRegistrarGetWindow( FlutterDesktopPluginRegistrarRef registrar) { return registrar->window; @@ -858,3 +897,35 @@ void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, void* user_data) { messenger->dispatcher->SetMessageCallback(channel, callback, user_data); } + +int64_t FlutterDesktopRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterTextureCallback texture_callback, + void* user_data) { + auto texture_gl = + std::make_unique(texture_callback, user_data); + int64_t texture_id = texture_gl->texture_id(); + texture_registrar->textures[texture_id] = std::move(texture_gl); + if (FlutterEngineRegisterExternalTexture(texture_registrar->engine, + texture_id) == kSuccess) { + return texture_id; + } + return -1; +} + +bool FlutterDesktopUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + auto it = texture_registrar->textures.find(texture_id); + if (it != texture_registrar->textures.end()) + texture_registrar->textures.erase(it); + return (FlutterEngineUnregisterExternalTexture(texture_registrar->engine, + texture_id) == kSuccess); +} + +bool FlutterDesktopMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + return (FlutterEngineMarkExternalTextureFrameAvailable( + texture_registrar->engine, texture_id) == kSuccess); +} diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index beff9bed1ac7f..8f86fe98f6130 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -13,6 +13,7 @@ #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/incoming_message_dispatcher.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/windows/key_event_handler.h" @@ -239,3 +240,33 @@ void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, void* user_data) { messenger->dispatcher->SetMessageCallback(channel, callback, user_data); } + +// Texture support isn't implemented yet for Windows, +// Please refer to https://github.com/flutter/flutter/issues/38601. +FlutterDesktopTextureRegistrarRef FlutterDesktopGetTextureRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + std::cout << "Texture support is not yet implemented." << std::endl; + return reinterpret_cast(nullptr); +} + +int64_t FlutterDesktopRegisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + FlutterTextureCallback texture_callback, + void* user_data) { + std::cout << "Texture support is not yet implemented." << std::endl; + return -1; +} + +bool FlutterDesktopUnregisterExternalTexture( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + std::cout << "Texture support is not yet implemented." << std::endl; + return false; +} + +bool FlutterDesktopMarkExternalTextureFrameAvailable( + FlutterDesktopTextureRegistrarRef texture_registrar, + int64_t texture_id) { + std::cout << "Texture support is not yet implemented." << std::endl; + return false; +}