From fce8036a2231558d9c9cdd152096ae6b892fb4e7 Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Fri, 15 Nov 2024 09:50:47 -0800 Subject: [PATCH 1/3] Backend-specific EmbedderTestBackingStoreProducers Extracts backend-specific subclasses of EmbedderTestBackingStoreProducer for OpenGL, Metal, Software, and Vulkan. Issue: https://github.com/flutter/flutter/issues/158998 --- shell/platform/embedder/BUILD.gn | 8 + .../embedder_test_backingstore_producer.cc | 447 +----------------- .../embedder_test_backingstore_producer.h | 64 +-- .../embedder_test_backingstore_producer_gl.cc | 183 +++++++ .../embedder_test_backingstore_producer_gl.h | 46 ++ ...mbedder_test_backingstore_producer_metal.h | 32 ++ ...bedder_test_backingstore_producer_metal.mm | 59 +++ ...der_test_backingstore_producer_software.cc | 122 +++++ ...dder_test_backingstore_producer_software.h | 40 ++ ...edder_test_backingstore_producer_vulkan.cc | 95 ++++ ...bedder_test_backingstore_producer_vulkan.h | 33 ++ .../tests/embedder_test_compositor_gl.cc | 21 +- .../tests/embedder_test_compositor_metal.mm | 10 +- .../embedder_test_compositor_software.cc | 11 +- .../tests/embedder_test_compositor_vulkan.cc | 12 +- .../embedder/tests/embedder_test_context.h | 4 - .../tests/embedder_test_context_gl.cc | 6 +- .../embedder/tests/embedder_test_context_gl.h | 2 + .../embedder/tests/embedder_unittests.cc | 3 +- 19 files changed, 666 insertions(+), 532 deletions(-) create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.cc create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.h create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.h create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.mm create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_software.cc create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc create mode 100644 shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.h diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index 2dbe8eb990b13..7e568ef5eb5c6 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -284,6 +284,8 @@ if (enable_unittests) { "tests/embedder_test.h", "tests/embedder_test_backingstore_producer.cc", "tests/embedder_test_backingstore_producer.h", + "tests/embedder_test_backingstore_producer_software.cc", + "tests/embedder_test_backingstore_producer_software.h", "tests/embedder_test_compositor.cc", "tests/embedder_test_compositor.h", "tests/embedder_test_compositor_software.cc", @@ -314,6 +316,8 @@ if (enable_unittests) { if (test_enable_gl) { sources += [ "tests/embedder_config_builder_gl.cc", + "tests/embedder_test_backingstore_producer_gl.cc", + "tests/embedder_test_backingstore_producer_gl.h", "tests/embedder_test_compositor_gl.cc", "tests/embedder_test_compositor_gl.h", "tests/embedder_test_context_gl.cc", @@ -330,6 +334,8 @@ if (enable_unittests) { if (test_enable_metal) { sources += [ "tests/embedder_config_builder_metal.mm", + "tests/embedder_test_backingstore_producer_metal.h", + "tests/embedder_test_backingstore_producer_metal.mm", "tests/embedder_test_compositor_metal.h", "tests/embedder_test_compositor_metal.mm", "tests/embedder_test_context_metal.h", @@ -343,6 +349,8 @@ if (enable_unittests) { if (test_enable_vulkan) { sources += [ "tests/embedder_config_builder_vulkan.cc", + "tests/embedder_test_backingstore_producer_vulkan.cc", + "tests/embedder_test_backingstore_producer_vulkan.h", "tests/embedder_test_compositor_vulkan.cc", "tests/embedder_test_compositor_vulkan.h", "tests/embedder_test_context_vulkan.cc", diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc b/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc index 477493f1be868..3bea53bcb925d 100644 --- a/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc @@ -4,457 +4,18 @@ #include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" -#include "flutter/fml/logging.h" -#include "flutter/shell/platform/embedder/pixel_formats.h" -#include "third_party/skia/include/core/SkColorSpace.h" -#include "third_party/skia/include/core/SkColorType.h" -#include "third_party/skia/include/core/SkImageInfo.h" -#include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/gpu/GpuTypes.h" -#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" -#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" - -#include -#include -#include - -#ifdef SHELL_ENABLE_VULKAN -#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h" -#include "third_party/skia/include/gpu/ganesh/vk/GrVkTypes.h" -#endif // SHELL_ENABLE_VULKAN - -#ifdef SHELL_ENABLE_METAL -#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlBackendSurface.h" -#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlTypes.h" -#endif // SHELL_ENABLE_METAL - -#ifdef SHELL_ENABLE_GL -#include "flutter/testing/test_gl_surface.h" -#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" -#include "third_party/skia/include/gpu/ganesh/gl/GrGLTypes.h" -#endif // SHELL_ENABLE_GL - // TODO(zanderso): https://github.com/flutter/flutter/issues/127701 // NOLINTBEGIN(bugprone-unchecked-optional-access) -namespace flutter { -namespace testing { +namespace flutter::testing { EmbedderTestBackingStoreProducer::EmbedderTestBackingStoreProducer( sk_sp context, - RenderTargetType type, - FlutterSoftwarePixelFormat software_pixfmt) - : context_(std::move(context)), - type_(type), - software_pixfmt_(software_pixfmt) -#ifdef SHELL_ENABLE_GL - , - test_egl_context_(nullptr) -#endif -#ifdef SHELL_ENABLE_METAL - , - test_metal_context_(std::make_unique()) -#endif -#ifdef SHELL_ENABLE_VULKAN - , - test_vulkan_context_(nullptr) -#endif -{ - if (type == RenderTargetType::kSoftwareBuffer && - software_pixfmt_ != kFlutterSoftwarePixelFormatNative32) { - FML_LOG(ERROR) << "Expected pixel format to be the default " - "(kFlutterSoftwarePixelFormatNative32) when" - "backing store producer should produce deprecated v1 " - "software backing " - "stores."; - std::abort(); - }; -} + RenderTargetType type) + : context_(std::move(context)), type_(type) {} EmbedderTestBackingStoreProducer::~EmbedderTestBackingStoreProducer() = default; -#ifdef SHELL_ENABLE_GL -void EmbedderTestBackingStoreProducer::SetEGLContext( - std::shared_ptr context) { - // Ideally this would be set in the constructor, however we can't do that - // without introducing different constructors depending on different graphics - // APIs, which is a bit ugly. - test_egl_context_ = std::move(context); -} -#endif - -bool EmbedderTestBackingStoreProducer::Create( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out) { - switch (type_) { - case RenderTargetType::kSoftwareBuffer: - return CreateSoftware(config, renderer_out); - case RenderTargetType::kSoftwareBuffer2: - return CreateSoftware2(config, renderer_out); -#ifdef SHELL_ENABLE_GL - case RenderTargetType::kOpenGLTexture: - return CreateTexture(config, renderer_out); - case RenderTargetType::kOpenGLFramebuffer: - return CreateFramebuffer(config, renderer_out); - case RenderTargetType::kOpenGLSurface: - return CreateSurface(config, renderer_out); -#endif -#ifdef SHELL_ENABLE_METAL - case RenderTargetType::kMetalTexture: - return CreateMTLTexture(config, renderer_out); -#endif -#ifdef SHELL_ENABLE_VULKAN - case RenderTargetType::kVulkanImage: - return CreateVulkanImage(config, renderer_out); -#endif - default: - return false; - } -} - -bool EmbedderTestBackingStoreProducer::CreateFramebuffer( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { -#ifdef SHELL_ENABLE_GL - const auto image_info = - SkImageInfo::MakeN32Premul(config->size.width, config->size.height); - - auto surface = - SkSurfaces::RenderTarget(context_.get(), // context - skgpu::Budgeted::kNo, // budgeted - image_info, // image info - 1, // sample count - kBottomLeft_GrSurfaceOrigin, // surface origin - nullptr, // surface properties - false // mipmaps - ); - - if (!surface) { - FML_LOG(ERROR) << "Could not create render target for compositor layer."; - return false; - } - - GrBackendRenderTarget render_target = SkSurfaces::GetBackendRenderTarget( - surface.get(), SkSurfaces::BackendHandleAccess::kDiscardWrite); - - if (!render_target.isValid()) { - FML_LOG(ERROR) << "Backend render target was invalid."; - return false; - } - - GrGLFramebufferInfo framebuffer_info = {}; - if (!GrBackendRenderTargets::GetGLFramebufferInfo(render_target, - &framebuffer_info)) { - FML_LOG(ERROR) << "Could not access backend framebuffer info."; - return false; - } - - auto user_data = new UserData(surface); - - backing_store_out->type = kFlutterBackingStoreTypeOpenGL; - backing_store_out->user_data = user_data; - backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; - backing_store_out->open_gl.framebuffer.target = framebuffer_info.fFormat; - backing_store_out->open_gl.framebuffer.name = framebuffer_info.fFBOID; - backing_store_out->open_gl.framebuffer.user_data = user_data; - backing_store_out->open_gl.framebuffer.destruction_callback = - [](void* user_data) { delete reinterpret_cast(user_data); }; - - return true; -#else - return false; -#endif -} - -bool EmbedderTestBackingStoreProducer::CreateTexture( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { -#ifdef SHELL_ENABLE_GL - const auto image_info = - SkImageInfo::MakeN32Premul(config->size.width, config->size.height); - - auto surface = - SkSurfaces::RenderTarget(context_.get(), // context - skgpu::Budgeted::kNo, // budgeted - image_info, // image info - 1, // sample count - kBottomLeft_GrSurfaceOrigin, // surface origin - nullptr, // surface properties - false // mipmaps - ); - - if (!surface) { - FML_LOG(ERROR) << "Could not create render target for compositor layer."; - return false; - } - - GrBackendTexture render_texture = SkSurfaces::GetBackendTexture( - surface.get(), SkSurfaces::BackendHandleAccess::kDiscardWrite); - - if (!render_texture.isValid()) { - FML_LOG(ERROR) << "Backend render texture was invalid."; - return false; - } - - GrGLTextureInfo texture_info = {}; - if (!GrBackendTextures::GetGLTextureInfo(render_texture, &texture_info)) { - FML_LOG(ERROR) << "Could not access backend texture info."; - return false; - } - - auto user_data = new UserData(surface); - - backing_store_out->type = kFlutterBackingStoreTypeOpenGL; - backing_store_out->user_data = user_data; - backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeTexture; - backing_store_out->open_gl.texture.target = texture_info.fTarget; - backing_store_out->open_gl.texture.name = texture_info.fID; - backing_store_out->open_gl.texture.format = texture_info.fFormat; - backing_store_out->open_gl.texture.user_data = user_data; - backing_store_out->open_gl.texture.destruction_callback = - [](void* user_data) { delete reinterpret_cast(user_data); }; - - return true; -#else - return false; -#endif -} - -bool EmbedderTestBackingStoreProducer::CreateSurface( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { -#ifdef SHELL_ENABLE_GL - FML_CHECK(test_egl_context_); - auto surface = std::make_unique( - test_egl_context_, - SkSize::Make(config->size.width, config->size.height).toRound()); - - auto make_current = [](void* user_data, bool* invalidate_state) -> bool { - *invalidate_state = false; - return reinterpret_cast(user_data)->gl_surface->MakeCurrent(); - }; - - auto clear_current = [](void* user_data, bool* invalidate_state) -> bool { - *invalidate_state = false; - // return - // reinterpret_cast(user_data)->gl_surface->ClearCurrent(); - return true; - }; - - auto destruction_callback = [](void* user_data) { - delete reinterpret_cast(user_data); - }; - - auto sk_surface = surface->GetOnscreenSurface(); - - auto user_data = new UserData(sk_surface, nullptr, std::move(surface)); - - backing_store_out->type = kFlutterBackingStoreTypeOpenGL; - backing_store_out->user_data = user_data; - backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeSurface; - backing_store_out->open_gl.surface.user_data = user_data; - backing_store_out->open_gl.surface.make_current_callback = make_current; - backing_store_out->open_gl.surface.clear_current_callback = clear_current; - backing_store_out->open_gl.surface.destruction_callback = - destruction_callback; - backing_store_out->open_gl.surface.format = 0x93A1 /* GL_BGRA8_EXT */; - - return true; -#else - return false; -#endif -} - -bool EmbedderTestBackingStoreProducer::CreateSoftware( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { - auto surface = SkSurfaces::Raster( - SkImageInfo::MakeN32Premul(config->size.width, config->size.height)); - - if (!surface) { - FML_LOG(ERROR) - << "Could not create the render target for compositor layer."; - return false; - } - - SkPixmap pixmap; - if (!surface->peekPixels(&pixmap)) { - FML_LOG(ERROR) << "Could not peek pixels of pixmap."; - return false; - } - - auto user_data = new UserData(surface); - - backing_store_out->type = kFlutterBackingStoreTypeSoftware; - backing_store_out->user_data = user_data; - backing_store_out->software.allocation = pixmap.addr(); - backing_store_out->software.row_bytes = pixmap.rowBytes(); - backing_store_out->software.height = pixmap.height(); - backing_store_out->software.user_data = user_data; - backing_store_out->software.destruction_callback = [](void* user_data) { - delete reinterpret_cast(user_data); - }; - - return true; -} - -bool EmbedderTestBackingStoreProducer::CreateSoftware2( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { - const auto color_info = getSkColorInfo(software_pixfmt_); - if (!color_info) { - return false; - } - - auto surface = SkSurfaces::Raster(SkImageInfo::Make( - SkISize::Make(config->size.width, config->size.height), *color_info)); - if (!surface) { - FML_LOG(ERROR) - << "Could not create the render target for compositor layer."; - return false; - } - - SkPixmap pixmap; - if (!surface->peekPixels(&pixmap)) { - FML_LOG(ERROR) << "Could not peek pixels of pixmap."; - return false; - } - - auto user_data = new UserData(surface); - - backing_store_out->type = kFlutterBackingStoreTypeSoftware2; - backing_store_out->user_data = user_data; - backing_store_out->software2.struct_size = - sizeof(FlutterSoftwareBackingStore2); - backing_store_out->software2.allocation = pixmap.writable_addr(); - backing_store_out->software2.row_bytes = pixmap.rowBytes(); - backing_store_out->software2.height = pixmap.height(); - backing_store_out->software2.user_data = user_data; - backing_store_out->software2.destruction_callback = [](void* user_data) { - delete reinterpret_cast(user_data); - }; - backing_store_out->software2.pixel_format = software_pixfmt_; - - return true; -} - -bool EmbedderTestBackingStoreProducer::CreateMTLTexture( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { -#ifdef SHELL_ENABLE_METAL - // TODO(gw280): Use SkSurfaces::RenderTarget instead of generating our - // own MTLTexture and wrapping it. - auto surface_size = SkISize::Make(config->size.width, config->size.height); - auto texture_info = test_metal_context_->CreateMetalTexture(surface_size); - - GrMtlTextureInfo skia_texture_info; - skia_texture_info.fTexture.reset(SkCFSafeRetain(texture_info.texture)); - GrBackendTexture backend_texture = - GrBackendTextures::MakeMtl(surface_size.width(), surface_size.height(), - skgpu::Mipmapped::kNo, skia_texture_info); - - sk_sp surface = SkSurfaces::WrapBackendTexture( - context_.get(), backend_texture, kTopLeft_GrSurfaceOrigin, 1, - kBGRA_8888_SkColorType, nullptr, nullptr); - - if (!surface) { - FML_LOG(ERROR) << "Could not create Skia surface from a Metal texture."; - return false; - } - - backing_store_out->type = kFlutterBackingStoreTypeMetal; - backing_store_out->user_data = surface.get(); - backing_store_out->metal.texture.texture = texture_info.texture; - // The balancing unref is in the destruction callback. - surface->ref(); - backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore); - backing_store_out->metal.texture.user_data = surface.get(); - backing_store_out->metal.texture.destruction_callback = [](void* user_data) { - reinterpret_cast(user_data)->unref(); - }; - - return true; -#else - return false; -#endif -} - -bool EmbedderTestBackingStoreProducer::CreateVulkanImage( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { -#ifdef SHELL_ENABLE_VULKAN - if (!test_vulkan_context_) { - test_vulkan_context_ = fml::MakeRefCounted(); - } - - auto surface_size = SkISize::Make(config->size.width, config->size.height); - TestVulkanImage* test_image = new TestVulkanImage( - std::move(test_vulkan_context_->CreateImage(surface_size).value())); - - GrVkImageInfo image_info = { - .fImage = test_image->GetImage(), - .fImageTiling = VK_IMAGE_TILING_OPTIMAL, - .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .fFormat = VK_FORMAT_R8G8B8A8_UNORM, - .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT, - .fSampleCount = 1, - .fLevelCount = 1, - }; - auto backend_texture = GrBackendTextures::MakeVk( - surface_size.width(), surface_size.height(), image_info); - - SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry); - - SkSurfaces::TextureReleaseProc release_vktexture = [](void* user_data) { - delete reinterpret_cast(user_data); - }; - - sk_sp surface = SkSurfaces::WrapBackendTexture( - context_.get(), // context - backend_texture, // back-end texture - kTopLeft_GrSurfaceOrigin, // surface origin - 1, // sample count - kRGBA_8888_SkColorType, // color type - SkColorSpace::MakeSRGB(), // color space - &surface_properties, // surface properties - release_vktexture, // texture release proc - test_image // release context - ); - - if (!surface) { - FML_LOG(ERROR) << "Could not create Skia surface from Vulkan image."; - return false; - } - backing_store_out->type = kFlutterBackingStoreTypeVulkan; - - FlutterVulkanImage* image = new FlutterVulkanImage(); - image->image = reinterpret_cast(image_info.fImage); - image->format = VK_FORMAT_R8G8B8A8_UNORM; - backing_store_out->vulkan.image = image; - - // Collect all allocated resources in the destruction_callback. - { - auto user_data = new UserData(surface, image); - backing_store_out->user_data = user_data; - backing_store_out->vulkan.user_data = user_data; - backing_store_out->vulkan.destruction_callback = [](void* user_data) { - UserData* d = reinterpret_cast(user_data); - delete d->image; - delete d; - }; - } - - return true; -#else - return false; -#endif -} - -} // namespace testing -} // namespace flutter +} // namespace flutter::testing // NOLINTEND(bugprone-unchecked-optional-access) diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer.h b/shell/platform/embedder/tests/embedder_test_backingstore_producer.h index 09c89ceb9aee1..410fa608c0943 100644 --- a/shell/platform/embedder/tests/embedder_test_backingstore_producer.h +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer.h @@ -13,20 +13,11 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/ganesh/GrDirectContext.h" -#ifdef SHELL_ENABLE_METAL -#include "flutter/testing/test_metal_context.h" -#endif - -#ifdef SHELL_ENABLE_VULKAN -#include "flutter/testing/test_vulkan_context.h" // nogncheck -#endif - #ifdef SHELL_ENABLE_GL #include "flutter/testing/test_gl_surface.h" #endif -namespace flutter { -namespace testing { +namespace flutter::testing { class EmbedderTestBackingStoreProducer { public: @@ -64,60 +55,19 @@ class EmbedderTestBackingStoreProducer { }; EmbedderTestBackingStoreProducer(sk_sp context, - RenderTargetType type, - FlutterSoftwarePixelFormat software_pixfmt = - kFlutterSoftwarePixelFormatNative32); - ~EmbedderTestBackingStoreProducer(); - -#ifdef SHELL_ENABLE_GL - void SetEGLContext(std::shared_ptr context); -#endif - - bool Create(const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out); - - private: - bool CreateFramebuffer(const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out); - - bool CreateTexture(const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out); - - bool CreateSurface(const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out); + RenderTargetType type); + virtual ~EmbedderTestBackingStoreProducer(); - bool CreateSoftware(const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out); - - bool CreateSoftware2(const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out); - - bool CreateMTLTexture(const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out); - - bool CreateVulkanImage(const FlutterBackingStoreConfig* config, - FlutterBackingStore* renderer_out); + virtual bool Create(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) = 0; + protected: sk_sp context_; RenderTargetType type_; - FlutterSoftwarePixelFormat software_pixfmt_; - -#ifdef SHELL_ENABLE_GL - std::shared_ptr test_egl_context_; -#endif - -#ifdef SHELL_ENABLE_METAL - std::unique_ptr test_metal_context_; -#endif - -#ifdef SHELL_ENABLE_VULKAN - fml::RefPtr test_vulkan_context_; -#endif FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestBackingStoreProducer); }; -} // namespace testing -} // namespace flutter +} // namespace flutter::testing #endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_H_ diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.cc b/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.cc new file mode 100644 index 0000000000000..5a088c61d3997 --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.cc @@ -0,0 +1,183 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.h" + +#include "flutter/fml/logging.h" +#include "flutter/testing/test_gl_surface.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" +#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/gl/GrGLTypes.h" + +namespace flutter::testing { + +EmbedderTestBackingStoreProducerGL::EmbedderTestBackingStoreProducerGL( + sk_sp context, + RenderTargetType type, + std::shared_ptr egl_context) + : EmbedderTestBackingStoreProducer(std::move(context), type), + test_egl_context_(std::move(egl_context)) {} + +EmbedderTestBackingStoreProducerGL::~EmbedderTestBackingStoreProducerGL() = + default; + +bool EmbedderTestBackingStoreProducerGL::Create( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + switch (type_) { + case RenderTargetType::kOpenGLTexture: + return CreateTexture(config, backing_store_out); + case RenderTargetType::kOpenGLFramebuffer: + return CreateFramebuffer(config, backing_store_out); + case RenderTargetType::kOpenGLSurface: + return CreateSurface(config, backing_store_out); + default: + return false; + }; +} + +bool EmbedderTestBackingStoreProducerGL::CreateFramebuffer( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + const auto image_info = + SkImageInfo::MakeN32Premul(config->size.width, config->size.height); + + auto surface = + SkSurfaces::RenderTarget(context_.get(), // context + skgpu::Budgeted::kNo, // budgeted + image_info, // image info + 1, // sample count + kBottomLeft_GrSurfaceOrigin, // surface origin + nullptr, // surface properties + false // mipmaps + ); + + if (!surface) { + FML_LOG(ERROR) << "Could not create render target for compositor layer."; + return false; + } + + GrBackendRenderTarget render_target = SkSurfaces::GetBackendRenderTarget( + surface.get(), SkSurfaces::BackendHandleAccess::kDiscardWrite); + + if (!render_target.isValid()) { + FML_LOG(ERROR) << "Backend render target was invalid."; + return false; + } + + GrGLFramebufferInfo framebuffer_info = {}; + if (!GrBackendRenderTargets::GetGLFramebufferInfo(render_target, + &framebuffer_info)) { + FML_LOG(ERROR) << "Could not access backend framebuffer info."; + return false; + } + + auto user_data = new UserData(surface); + + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; + backing_store_out->user_data = user_data; + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; + backing_store_out->open_gl.framebuffer.target = framebuffer_info.fFormat; + backing_store_out->open_gl.framebuffer.name = framebuffer_info.fFBOID; + backing_store_out->open_gl.framebuffer.user_data = user_data; + backing_store_out->open_gl.framebuffer.destruction_callback = + [](void* user_data) { delete reinterpret_cast(user_data); }; + + return true; +} + +bool EmbedderTestBackingStoreProducerGL::CreateTexture( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + const auto image_info = + SkImageInfo::MakeN32Premul(config->size.width, config->size.height); + + auto surface = + SkSurfaces::RenderTarget(context_.get(), // context + skgpu::Budgeted::kNo, // budgeted + image_info, // image info + 1, // sample count + kBottomLeft_GrSurfaceOrigin, // surface origin + nullptr, // surface properties + false // mipmaps + ); + + if (!surface) { + FML_LOG(ERROR) << "Could not create render target for compositor layer."; + return false; + } + + GrBackendTexture render_texture = SkSurfaces::GetBackendTexture( + surface.get(), SkSurfaces::BackendHandleAccess::kDiscardWrite); + + if (!render_texture.isValid()) { + FML_LOG(ERROR) << "Backend render texture was invalid."; + return false; + } + + GrGLTextureInfo texture_info = {}; + if (!GrBackendTextures::GetGLTextureInfo(render_texture, &texture_info)) { + FML_LOG(ERROR) << "Could not access backend texture info."; + return false; + } + + auto user_data = new UserData(surface); + + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; + backing_store_out->user_data = user_data; + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeTexture; + backing_store_out->open_gl.texture.target = texture_info.fTarget; + backing_store_out->open_gl.texture.name = texture_info.fID; + backing_store_out->open_gl.texture.format = texture_info.fFormat; + backing_store_out->open_gl.texture.user_data = user_data; + backing_store_out->open_gl.texture.destruction_callback = + [](void* user_data) { delete reinterpret_cast(user_data); }; + + return true; +} + +bool EmbedderTestBackingStoreProducerGL::CreateSurface( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + FML_CHECK(test_egl_context_); + auto surface = std::make_unique( + test_egl_context_, + SkSize::Make(config->size.width, config->size.height).toRound()); + + auto make_current = [](void* user_data, bool* invalidate_state) -> bool { + *invalidate_state = false; + return reinterpret_cast(user_data)->gl_surface->MakeCurrent(); + }; + + auto clear_current = [](void* user_data, bool* invalidate_state) -> bool { + *invalidate_state = false; + // return + // reinterpret_cast(user_data)->gl_surface->ClearCurrent(); + return true; + }; + + auto destruction_callback = [](void* user_data) { + delete reinterpret_cast(user_data); + }; + + auto sk_surface = surface->GetOnscreenSurface(); + + auto user_data = new UserData(sk_surface, nullptr, std::move(surface)); + + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; + backing_store_out->user_data = user_data; + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeSurface; + backing_store_out->open_gl.surface.user_data = user_data; + backing_store_out->open_gl.surface.make_current_callback = make_current; + backing_store_out->open_gl.surface.clear_current_callback = clear_current; + backing_store_out->open_gl.surface.destruction_callback = + destruction_callback; + backing_store_out->open_gl.surface.format = 0x93A1 /* GL_BGRA8_EXT */; + + return true; +} + +} // namespace flutter::testing diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.h b/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.h new file mode 100644 index 0000000000000..bf6bb09b5129f --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.h @@ -0,0 +1,46 @@ +// 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_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_GL_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_GL_H_ + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" + +#include + +#include "flutter/testing/test_gl_surface.h" + +namespace flutter::testing { + +class EmbedderTestBackingStoreProducerGL + : public EmbedderTestBackingStoreProducer { + public: + EmbedderTestBackingStoreProducerGL( + sk_sp context, + RenderTargetType type, + std::shared_ptr egl_context); + + virtual ~EmbedderTestBackingStoreProducerGL(); + + virtual bool Create(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + private: + bool CreateFramebuffer(const FlutterBackingStoreConfig* config, + FlutterBackingStore* renderer_out); + + bool CreateTexture(const FlutterBackingStoreConfig* config, + FlutterBackingStore* renderer_out); + + bool CreateSurface(const FlutterBackingStoreConfig* config, + FlutterBackingStore* renderer_out); + + std::shared_ptr test_egl_context_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestBackingStoreProducerGL); +}; + +} // namespace flutter::testing + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_GL_H_ diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.h b/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.h new file mode 100644 index 0000000000000..e7d959c535cb4 --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.h @@ -0,0 +1,32 @@ +// 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_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_METAL_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_METAL_H_ + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" +#include "flutter/testing/test_metal_context.h" + +namespace flutter::testing { + +class EmbedderTestBackingStoreProducerMetal + : public EmbedderTestBackingStoreProducer { + public: + EmbedderTestBackingStoreProducerMetal(sk_sp context, + RenderTargetType type); + + virtual ~EmbedderTestBackingStoreProducerMetal(); + + virtual bool Create(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + private: + std::unique_ptr test_metal_context_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestBackingStoreProducerMetal); +}; + +} // namespace flutter::testing + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_METAL_H_ diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.mm b/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.mm new file mode 100644 index 0000000000000..fb920025ff998 --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.mm @@ -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/embedder/tests/embedder_test_backingstore_producer_metal.h" + +#include "flutter/fml/logging.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" +#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlTypes.h" + +namespace flutter::testing { + +EmbedderTestBackingStoreProducerMetal::EmbedderTestBackingStoreProducerMetal( + sk_sp context, + RenderTargetType type) + : EmbedderTestBackingStoreProducer(std::move(context), type), + test_metal_context_(std::make_unique()) {} + +EmbedderTestBackingStoreProducerMetal::~EmbedderTestBackingStoreProducerMetal() = default; + +bool EmbedderTestBackingStoreProducerMetal::Create(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + // TODO(gw280): Use SkSurfaces::RenderTarget instead of generating our + // own MTLTexture and wrapping it. + auto surface_size = SkISize::Make(config->size.width, config->size.height); + auto texture_info = test_metal_context_->CreateMetalTexture(surface_size); + + GrMtlTextureInfo skia_texture_info; + skia_texture_info.fTexture.reset(SkCFSafeRetain(texture_info.texture)); + GrBackendTexture backend_texture = GrBackendTextures::MakeMtl( + surface_size.width(), surface_size.height(), skgpu::Mipmapped::kNo, skia_texture_info); + + sk_sp surface = + SkSurfaces::WrapBackendTexture(context_.get(), backend_texture, kTopLeft_GrSurfaceOrigin, 1, + kBGRA_8888_SkColorType, nullptr, nullptr); + + if (!surface) { + FML_LOG(ERROR) << "Could not create Skia surface from a Metal texture."; + return false; + } + + backing_store_out->type = kFlutterBackingStoreTypeMetal; + backing_store_out->user_data = surface.get(); + backing_store_out->metal.texture.texture = texture_info.texture; + // The balancing unref is in the destruction callback. + surface->ref(); + backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore); + backing_store_out->metal.texture.user_data = surface.get(); + backing_store_out->metal.texture.destruction_callback = [](void* user_data) { + reinterpret_cast(user_data)->unref(); + }; + + return true; +} + +} // namespace flutter::testing diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.cc b/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.cc new file mode 100644 index 0000000000000..5c3c3ded58d90 --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.cc @@ -0,0 +1,122 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h" + +#include "flutter/fml/logging.h" +#include "flutter/shell/platform/embedder/pixel_formats.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" + +namespace flutter::testing { + +EmbedderTestBackingStoreProducerSoftware:: + EmbedderTestBackingStoreProducerSoftware( + sk_sp context, + RenderTargetType type, + FlutterSoftwarePixelFormat software_pixfmt) + : EmbedderTestBackingStoreProducer(std::move(context), type), + software_pixfmt_(software_pixfmt) { + if (type == RenderTargetType::kSoftwareBuffer && + software_pixfmt_ != kFlutterSoftwarePixelFormatNative32) { + FML_LOG(ERROR) << "Expected pixel format to be the default " + "(kFlutterSoftwarePixelFormatNative32) when" + "backing store producer should produce deprecated v1 " + "software backing " + "stores."; + std::abort(); + }; +} + +EmbedderTestBackingStoreProducerSoftware:: + ~EmbedderTestBackingStoreProducerSoftware() = default; + +bool EmbedderTestBackingStoreProducerSoftware::Create( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + switch (type_) { + case RenderTargetType::kSoftwareBuffer: + return CreateSoftware(config, backing_store_out); + case RenderTargetType::kSoftwareBuffer2: + return CreateSoftware2(config, backing_store_out); + default: + return false; + } +} + +bool EmbedderTestBackingStoreProducerSoftware::CreateSoftware( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + auto surface = SkSurfaces::Raster( + SkImageInfo::MakeN32Premul(config->size.width, config->size.height)); + + if (!surface) { + FML_LOG(ERROR) + << "Could not create the render target for compositor layer."; + return false; + } + + SkPixmap pixmap; + if (!surface->peekPixels(&pixmap)) { + FML_LOG(ERROR) << "Could not peek pixels of pixmap."; + return false; + } + + auto user_data = new UserData(surface); + + backing_store_out->type = kFlutterBackingStoreTypeSoftware; + backing_store_out->user_data = user_data; + backing_store_out->software.allocation = pixmap.addr(); + backing_store_out->software.row_bytes = pixmap.rowBytes(); + backing_store_out->software.height = pixmap.height(); + backing_store_out->software.user_data = user_data; + backing_store_out->software.destruction_callback = [](void* user_data) { + delete reinterpret_cast(user_data); + }; + + return true; +} + +bool EmbedderTestBackingStoreProducerSoftware::CreateSoftware2( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + const auto color_info = getSkColorInfo(software_pixfmt_); + if (!color_info) { + return false; + } + + auto surface = SkSurfaces::Raster(SkImageInfo::Make( + SkISize::Make(config->size.width, config->size.height), *color_info)); + if (!surface) { + FML_LOG(ERROR) + << "Could not create the render target for compositor layer."; + return false; + } + + SkPixmap pixmap; + if (!surface->peekPixels(&pixmap)) { + FML_LOG(ERROR) << "Could not peek pixels of pixmap."; + return false; + } + + auto user_data = new UserData(surface); + + backing_store_out->type = kFlutterBackingStoreTypeSoftware2; + backing_store_out->user_data = user_data; + backing_store_out->software2.struct_size = + sizeof(FlutterSoftwareBackingStore2); + backing_store_out->software2.allocation = pixmap.writable_addr(); + backing_store_out->software2.row_bytes = pixmap.rowBytes(); + backing_store_out->software2.height = pixmap.height(); + backing_store_out->software2.user_data = user_data; + backing_store_out->software2.destruction_callback = [](void* user_data) { + delete reinterpret_cast(user_data); + }; + backing_store_out->software2.pixel_format = software_pixfmt_; + + return true; +} + +} // namespace flutter::testing diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h b/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h new file mode 100644 index 0000000000000..52cde2487ad97 --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h @@ -0,0 +1,40 @@ +// 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_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_SOFTWARE_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_SOFTWARE_H_ + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" + +namespace flutter::testing { + +class EmbedderTestBackingStoreProducerSoftware + : public EmbedderTestBackingStoreProducer { + public: + EmbedderTestBackingStoreProducerSoftware( + sk_sp context, + RenderTargetType type, + FlutterSoftwarePixelFormat software_pixfmt = + kFlutterSoftwarePixelFormatNative32); + + virtual ~EmbedderTestBackingStoreProducerSoftware(); + + virtual bool Create(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + private: + bool CreateSoftware(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + bool CreateSoftware2(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + FlutterSoftwarePixelFormat software_pixfmt_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestBackingStoreProducerSoftware); +}; + +} // namespace flutter::testing + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_SOFTWARE_H_ diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc b/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc new file mode 100644 index 0000000000000..4e791e0d51c1e --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc @@ -0,0 +1,95 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.h" + +#include "flutter/fml/logging.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" +#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/vk/GrVkTypes.h" + +namespace flutter::testing { + +EmbedderTestBackingStoreProducerVulkan::EmbedderTestBackingStoreProducerVulkan( + sk_sp context, + RenderTargetType type) + : EmbedderTestBackingStoreProducer(std::move(context), type), + test_vulkan_context_(nullptr) {} + +EmbedderTestBackingStoreProducerVulkan:: + ~EmbedderTestBackingStoreProducerVulkan() = default; + +bool EmbedderTestBackingStoreProducerVulkan::Create( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + if (!test_vulkan_context_) { + test_vulkan_context_ = fml::MakeRefCounted(); + } + + auto surface_size = SkISize::Make(config->size.width, config->size.height); + TestVulkanImage* test_image = new TestVulkanImage( + std::move(test_vulkan_context_->CreateImage(surface_size).value())); + + GrVkImageInfo image_info = { + .fImage = test_image->GetImage(), + .fImageTiling = VK_IMAGE_TILING_OPTIMAL, + .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .fFormat = VK_FORMAT_R8G8B8A8_UNORM, + .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT, + .fSampleCount = 1, + .fLevelCount = 1, + }; + auto backend_texture = GrBackendTextures::MakeVk( + surface_size.width(), surface_size.height(), image_info); + + SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry); + + SkSurfaces::TextureReleaseProc release_vktexture = [](void* user_data) { + delete reinterpret_cast(user_data); + }; + + sk_sp surface = SkSurfaces::WrapBackendTexture( + context_.get(), // context + backend_texture, // back-end texture + kTopLeft_GrSurfaceOrigin, // surface origin + 1, // sample count + kRGBA_8888_SkColorType, // color type + SkColorSpace::MakeSRGB(), // color space + &surface_properties, // surface properties + release_vktexture, // texture release proc + test_image // release context + ); + + if (!surface) { + FML_LOG(ERROR) << "Could not create Skia surface from Vulkan image."; + return false; + } + backing_store_out->type = kFlutterBackingStoreTypeVulkan; + + FlutterVulkanImage* image = new FlutterVulkanImage(); + image->image = reinterpret_cast(image_info.fImage); + image->format = VK_FORMAT_R8G8B8A8_UNORM; + backing_store_out->vulkan.image = image; + + // Collect all allocated resources in the destruction_callback. + { + auto user_data = new UserData(surface, image); + backing_store_out->user_data = user_data; + backing_store_out->vulkan.user_data = user_data; + backing_store_out->vulkan.destruction_callback = [](void* user_data) { + UserData* d = reinterpret_cast(user_data); + delete d->image; + delete d; + }; + } + + return true; +} + +} // namespace flutter::testing diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.h b/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.h new file mode 100644 index 0000000000000..5fb50875299c6 --- /dev/null +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.h @@ -0,0 +1,33 @@ +// 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_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_VULKAN_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_VULKAN_H_ + +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" + +#include "flutter/testing/test_vulkan_context.h" + +namespace flutter::testing { + +class EmbedderTestBackingStoreProducerVulkan + : public EmbedderTestBackingStoreProducer { + public: + EmbedderTestBackingStoreProducerVulkan(sk_sp context, + RenderTargetType type); + + virtual ~EmbedderTestBackingStoreProducerVulkan(); + + virtual bool Create(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + private: + fml::RefPtr test_vulkan_context_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestBackingStoreProducerVulkan); +}; + +} // namespace flutter::testing + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_BACKINGSTORE_PRODUCER_VULKAN_H_ diff --git a/shell/platform/embedder/tests/embedder_test_compositor_gl.cc b/shell/platform/embedder/tests/embedder_test_compositor_gl.cc index 8727317a901dc..92026955df5e7 100644 --- a/shell/platform/embedder/tests/embedder_test_compositor_gl.cc +++ b/shell/platform/embedder/tests/embedder_test_compositor_gl.cc @@ -8,6 +8,8 @@ #include "flutter/fml/logging.h" #include "flutter/shell/platform/embedder/tests/embedder_assertions.h" +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_gl.h" +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" @@ -29,21 +31,24 @@ void EmbedderTestCompositorGL::SetRenderTargetType( switch (type) { case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLFramebuffer: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLSurface: - case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLTexture: + case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLTexture: { + backingstore_producer_ = + std::make_unique(context_, type, + egl_context_); + return; + } case EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer: case EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer2: - // no-op: Rendering into GL and software render targets is supported. - break; + backingstore_producer_ = + std::make_unique( + context_, type, software_pixfmt); + return; case EmbedderTestBackingStoreProducer::RenderTargetType::kMetalTexture: case EmbedderTestBackingStoreProducer::RenderTargetType::kVulkanImage: FML_LOG(FATAL) << "Unsupported render target type: " << static_cast(type); - break; + return; } - auto producer = std::make_unique( - context_, type, software_pixfmt); - producer->SetEGLContext(egl_context_); - backingstore_producer_ = std::move(producer); } bool EmbedderTestCompositorGL::UpdateOffscrenComposition( diff --git a/shell/platform/embedder/tests/embedder_test_compositor_metal.mm b/shell/platform/embedder/tests/embedder_test_compositor_metal.mm index bdf1b59492940..cb3c2548e988a 100644 --- a/shell/platform/embedder/tests/embedder_test_compositor_metal.mm +++ b/shell/platform/embedder/tests/embedder_test_compositor_metal.mm @@ -8,6 +8,7 @@ #include "flutter/fml/logging.h" #include "flutter/shell/platform/embedder/tests/embedder_assertions.h" +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_metal.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" @@ -25,8 +26,9 @@ FlutterSoftwarePixelFormat software_pixfmt) { switch (type) { case EmbedderTestBackingStoreProducer::RenderTargetType::kMetalTexture: - // no-op. - break; + backingstore_producer_ = + std::make_unique(context_, type); + return; case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLFramebuffer: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLSurface: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLTexture: @@ -34,10 +36,8 @@ case EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer2: case EmbedderTestBackingStoreProducer::RenderTargetType::kVulkanImage: FML_LOG(FATAL) << "Unsupported render target type: " << static_cast(type); - break; + return; } - backingstore_producer_ = - std::make_unique(context_, type, software_pixfmt); } bool EmbedderTestCompositorMetal::UpdateOffscrenComposition(const FlutterLayer** layers, diff --git a/shell/platform/embedder/tests/embedder_test_compositor_software.cc b/shell/platform/embedder/tests/embedder_test_compositor_software.cc index 08e277039541b..8469542d49c03 100644 --- a/shell/platform/embedder/tests/embedder_test_compositor_software.cc +++ b/shell/platform/embedder/tests/embedder_test_compositor_software.cc @@ -6,6 +6,7 @@ #include "flutter/fml/logging.h" #include "flutter/shell/platform/embedder/tests/embedder_assertions.h" +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h" #include "third_party/skia/include/core/SkSurface.h" namespace flutter { @@ -23,8 +24,10 @@ void EmbedderTestCompositorSoftware::SetRenderTargetType( switch (type) { case EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer: case EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer2: - // no-op. - break; + backingstore_producer_ = + std::make_unique( + context_, type, software_pixfmt); + return; case EmbedderTestBackingStoreProducer::RenderTargetType::kMetalTexture: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLFramebuffer: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLSurface: @@ -32,10 +35,8 @@ void EmbedderTestCompositorSoftware::SetRenderTargetType( case EmbedderTestBackingStoreProducer::RenderTargetType::kVulkanImage: FML_LOG(FATAL) << "Unsupported render target type: " << static_cast(type); - break; + return; } - backingstore_producer_ = std::make_unique( - context_, type, software_pixfmt); } bool EmbedderTestCompositorSoftware::UpdateOffscrenComposition( diff --git a/shell/platform/embedder/tests/embedder_test_compositor_vulkan.cc b/shell/platform/embedder/tests/embedder_test_compositor_vulkan.cc index 3477a223c250c..d487483b4b34a 100644 --- a/shell/platform/embedder/tests/embedder_test_compositor_vulkan.cc +++ b/shell/platform/embedder/tests/embedder_test_compositor_vulkan.cc @@ -8,7 +8,7 @@ #include "flutter/fml/logging.h" #include "flutter/shell/platform/embedder/tests/embedder_assertions.h" -#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" @@ -27,8 +27,10 @@ void EmbedderTestCompositorVulkan::SetRenderTargetType( FlutterSoftwarePixelFormat software_pixfmt) { switch (type) { case EmbedderTestBackingStoreProducer::RenderTargetType::kVulkanImage: - // no-op. - break; + backingstore_producer_ = + std::make_unique(context_, + type); + return; case EmbedderTestBackingStoreProducer::RenderTargetType::kMetalTexture: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLFramebuffer: case EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLSurface: @@ -37,10 +39,8 @@ void EmbedderTestCompositorVulkan::SetRenderTargetType( case EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer2: FML_LOG(FATAL) << "Unsupported render target type: " << static_cast(type); - break; + return; } - backingstore_producer_ = std::make_unique( - context_, type, software_pixfmt); } bool EmbedderTestCompositorVulkan::UpdateOffscrenComposition( diff --git a/shell/platform/embedder/tests/embedder_test_context.h b/shell/platform/embedder/tests/embedder_test_context.h index 4ea8de4cc9da5..11d2eb6a322ad 100644 --- a/shell/platform/embedder/tests/embedder_test_context.h +++ b/shell/platform/embedder/tests/embedder_test_context.h @@ -120,10 +120,6 @@ class EmbedderTestContext { using NextSceneCallback = std::function image)>; -#ifdef SHELL_ENABLE_GL - std::shared_ptr egl_context_ = nullptr; -#endif - std::string assets_path_; ELFAOTSymbols aot_symbols_; std::unique_ptr vm_snapshot_data_; diff --git a/shell/platform/embedder/tests/embedder_test_context_gl.cc b/shell/platform/embedder/tests/embedder_test_context_gl.cc index e562411841f0c..7dddb4a35a159 100644 --- a/shell/platform/embedder/tests/embedder_test_context_gl.cc +++ b/shell/platform/embedder/tests/embedder_test_context_gl.cc @@ -11,6 +11,7 @@ #include "flutter/runtime/dart_vm.h" #include "flutter/shell/platform/embedder/tests/embedder_assertions.h" #include "flutter/shell/platform/embedder/tests/embedder_test_compositor_gl.h" +#include "flutter/testing/test_gl_surface.h" #include "flutter/testing/testing.h" #include "tests/embedder_test.h" #include "third_party/dart/runtime/bin/elf_loader.h" @@ -20,9 +21,8 @@ namespace flutter { namespace testing { EmbedderTestContextGL::EmbedderTestContextGL(std::string assets_path) - : EmbedderTestContext(std::move(assets_path)) { - egl_context_ = std::make_shared(); -} + : EmbedderTestContext(std::move(assets_path)), + egl_context_(std::make_shared()) {} EmbedderTestContextGL::~EmbedderTestContextGL() { SetGLGetFBOCallback(nullptr); diff --git a/shell/platform/embedder/tests/embedder_test_context_gl.h b/shell/platform/embedder/tests/embedder_test_context_gl.h index a7c880803851c..748d49028403f 100644 --- a/shell/platform/embedder/tests/embedder_test_context_gl.h +++ b/shell/platform/embedder/tests/embedder_test_context_gl.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_TEST_CONTEXT_GL_H_ #include "flutter/shell/platform/embedder/tests/embedder_test_context.h" + #include "flutter/testing/test_gl_surface.h" namespace flutter { @@ -73,6 +74,7 @@ class EmbedderTestContextGL : public EmbedderTestContext { // This allows the builder to access the hooks. friend class EmbedderConfigBuilder; + std::shared_ptr egl_context_; std::unique_ptr gl_surface_; size_t gl_surface_present_count_ = 0; std::mutex gl_callback_mutex_; diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index 656865ad0e1aa..120dbb8202eab 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -27,6 +27,7 @@ #include "flutter/shell/platform/embedder/tests/embedder_assertions.h" #include "flutter/shell/platform/embedder/tests/embedder_config_builder.h" #include "flutter/shell/platform/embedder/tests/embedder_test.h" +#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer_software.h" #include "flutter/shell/platform/embedder/tests/embedder_unittests_util.h" #include "flutter/testing/assertions_skia.h" #include "flutter/testing/testing.h" @@ -1845,7 +1846,7 @@ TEST_F(EmbedderTest, BackingStoresCorrespondToTheirViews) { builder.SetSoftwareRendererConfig(SkISize::Make(800, 600)); builder.SetCompositor(); - EmbedderTestBackingStoreProducer producer( + EmbedderTestBackingStoreProducerSoftware producer( context.GetCompositor().GetGrContext(), EmbedderTestBackingStoreProducer::RenderTargetType::kSoftwareBuffer); From 6cb009c65173a95e8a5d3fd9a5c50cab030c5430 Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Fri, 15 Nov 2024 17:44:22 -0800 Subject: [PATCH 2/3] Fix optional check --- .../tests/embedder_test_backingstore_producer_vulkan.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc b/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc index 4e791e0d51c1e..154f507bc536a 100644 --- a/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer_vulkan.cc @@ -30,8 +30,12 @@ bool EmbedderTestBackingStoreProducerVulkan::Create( } auto surface_size = SkISize::Make(config->size.width, config->size.height); - TestVulkanImage* test_image = new TestVulkanImage( - std::move(test_vulkan_context_->CreateImage(surface_size).value())); + auto optional_image = test_vulkan_context_->CreateImage(surface_size); + if (!optional_image.has_value()) { + FML_LOG(ERROR) << "Could not create Vulkan image."; + return false; + } + TestVulkanImage* test_image = new TestVulkanImage(std::move(*optional_image)); GrVkImageInfo image_info = { .fImage = test_image->GetImage(), From d4e6ce6217d0dfd3d12842c7aa8f6d5d9fc2bbab Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Fri, 15 Nov 2024 18:07:20 -0800 Subject: [PATCH 3/3] More lint --- shell/platform/embedder/tests/embedder_test_context_gl.cc | 5 +++-- shell/platform/embedder/tests/embedder_test_context_gl.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/shell/platform/embedder/tests/embedder_test_context_gl.cc b/shell/platform/embedder/tests/embedder_test_context_gl.cc index 7dddb4a35a159..2ee44156b9260 100644 --- a/shell/platform/embedder/tests/embedder_test_context_gl.cc +++ b/shell/platform/embedder/tests/embedder_test_context_gl.cc @@ -63,9 +63,10 @@ bool EmbedderTestContextGL::GLPresent(FlutterPresentInfo present_info) { return gl_surface_->Present(); } -void EmbedderTestContextGL::SetGLGetFBOCallback(GLGetFBOCallback callback) { +void EmbedderTestContextGL::SetGLGetFBOCallback( + const GLGetFBOCallback& callback) { std::scoped_lock lock(gl_callback_mutex_); - gl_get_fbo_callback_ = std::move(callback); + gl_get_fbo_callback_ = callback; } void EmbedderTestContextGL::SetGLPopulateExistingDamageCallback( diff --git a/shell/platform/embedder/tests/embedder_test_context_gl.h b/shell/platform/embedder/tests/embedder_test_context_gl.h index 748d49028403f..85581783940ec 100644 --- a/shell/platform/embedder/tests/embedder_test_context_gl.h +++ b/shell/platform/embedder/tests/embedder_test_context_gl.h @@ -40,7 +40,7 @@ class EmbedderTestContextGL : public EmbedderTestContext { /// @param[in] callback The callback to set. The previous callback will be /// un-registered. /// - void SetGLGetFBOCallback(GLGetFBOCallback callback); + void SetGLGetFBOCallback(const GLGetFBOCallback& callback); void SetGLPopulateExistingDamageCallback( GLPopulateExistingDamageCallback callback);