| // 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 <mutex> |
| |
| #include "flutter/fml/logging.h" |
| #include "flutter/shell/platform/embedder/embedder_struct_macros.h" |
| #include "flutter/shell/platform/windows/external_texture_d3d.h" |
| #include "flutter/shell/platform/windows/external_texture_pixelbuffer.h" |
| #include "flutter/shell/platform/windows/flutter_windows_engine.h" |
| |
| namespace { |
| static constexpr int64_t kInvalidTexture = -1; |
| } |
| |
| namespace flutter { |
| |
| FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar( |
| FlutterWindowsEngine* engine, |
| std::shared_ptr<GlProcTable> gl) |
| : engine_(engine), gl_(std::move(gl)) {} |
| |
| int64_t FlutterWindowsTextureRegistrar::RegisterTexture( |
| const FlutterDesktopTextureInfo* texture_info) { |
| if (!gl_) { |
| return kInvalidTexture; |
| } |
| |
| if (texture_info->type == kFlutterDesktopPixelBufferTexture) { |
| if (!texture_info->pixel_buffer_config.callback) { |
| FML_LOG(ERROR) << "Invalid pixel buffer texture callback."; |
| return kInvalidTexture; |
| } |
| |
| return EmplaceTexture(std::make_unique<flutter::ExternalTexturePixelBuffer>( |
| texture_info->pixel_buffer_config.callback, |
| texture_info->pixel_buffer_config.user_data, gl_)); |
| } else if (texture_info->type == kFlutterDesktopGpuSurfaceTexture) { |
| const FlutterDesktopGpuSurfaceTextureConfig* gpu_surface_config = |
| &texture_info->gpu_surface_config; |
| auto surface_type = SAFE_ACCESS(gpu_surface_config, type, |
| kFlutterDesktopGpuSurfaceTypeNone); |
| if (surface_type == kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle || |
| surface_type == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D) { |
| auto callback = SAFE_ACCESS(gpu_surface_config, callback, nullptr); |
| if (!callback) { |
| FML_LOG(ERROR) << "Invalid GPU surface descriptor callback."; |
| return kInvalidTexture; |
| } |
| |
| auto user_data = SAFE_ACCESS(gpu_surface_config, user_data, nullptr); |
| return EmplaceTexture(std::make_unique<flutter::ExternalTextureD3d>( |
| surface_type, callback, user_data, engine_->surface_manager(), gl_)); |
| } |
| } |
| |
| FML_LOG(ERROR) << "Attempted to register texture of unsupport type."; |
| return kInvalidTexture; |
| } |
| |
| int64_t FlutterWindowsTextureRegistrar::EmplaceTexture( |
| std::unique_ptr<ExternalTexture> texture) { |
| int64_t texture_id = texture->texture_id(); |
| { |
| std::lock_guard<std::mutex> lock(map_mutex_); |
| textures_[texture_id] = std::move(texture); |
| } |
| |
| engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() { |
| engine->RegisterExternalTexture(texture_id); |
| }); |
| |
| return texture_id; |
| } |
| |
| void FlutterWindowsTextureRegistrar::UnregisterTexture(int64_t texture_id, |
| fml::closure callback) { |
| engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() { |
| engine->UnregisterExternalTexture(texture_id); |
| }); |
| |
| bool posted = engine_->PostRasterThreadTask([this, texture_id, callback]() { |
| { |
| std::lock_guard<std::mutex> lock(map_mutex_); |
| auto it = textures_.find(texture_id); |
| if (it != textures_.end()) { |
| textures_.erase(it); |
| } |
| } |
| if (callback) { |
| callback(); |
| } |
| }); |
| |
| if (!posted && callback) { |
| callback(); |
| } |
| } |
| |
| bool FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable( |
| int64_t texture_id) { |
| engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() { |
| engine->MarkExternalTextureFrameAvailable(texture_id); |
| }); |
| return true; |
| } |
| |
| bool FlutterWindowsTextureRegistrar::PopulateTexture( |
| int64_t texture_id, |
| size_t width, |
| size_t height, |
| FlutterOpenGLTexture* opengl_texture) { |
| flutter::ExternalTexture* texture; |
| { |
| std::lock_guard<std::mutex> lock(map_mutex_); |
| auto it = textures_.find(texture_id); |
| if (it == textures_.end()) { |
| return false; |
| } |
| texture = it->second.get(); |
| } |
| return texture->PopulateTexture(width, height, opengl_texture); |
| } |
| |
| }; // namespace flutter |