Flutter Engine
 
Loading...
Searching...
No Matches
shell_test_platform_view_vulkan.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <utility>
8
14
15#include "third_party/skia/include/core/SkSurface.h"
16#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
17#include "third_party/skia/include/gpu/ganesh/vk/GrVkDirectContext.h"
18#include "third_party/skia/include/gpu/vk/VulkanExtensions.h"
19
20#if OS_FUCHSIA
21#define VULKAN_SO_PATH "libvulkan.so"
22#else
24#endif
25
26namespace flutter::testing {
27
28std::unique_ptr<ShellTestPlatformView> ShellTestPlatformView::CreateVulkan(
29 PlatformView::Delegate& delegate,
30 const TaskRunners& task_runners,
31 const std::shared_ptr<ShellTestVsyncClock>& vsync_clock,
32 const CreateVsyncWaiter& create_vsync_waiter,
33 const std::shared_ptr<ShellTestExternalViewEmbedder>&
34 shell_test_external_view_embedder,
35 const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
36 return std::make_unique<ShellTestPlatformViewVulkan>(
37 delegate, task_runners, vsync_clock, create_vsync_waiter,
38 shell_test_external_view_embedder);
39}
40
42 PlatformView::Delegate& delegate,
43 const TaskRunners& task_runners,
44 std::shared_ptr<ShellTestVsyncClock> vsync_clock,
45 CreateVsyncWaiter create_vsync_waiter,
46 std::shared_ptr<ShellTestExternalViewEmbedder>
47 shell_test_external_view_embedder)
48 : ShellTestPlatformView(delegate, task_runners),
49 create_vsync_waiter_(std::move(create_vsync_waiter)),
50 vsync_clock_(std::move(vsync_clock)),
51 proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>(VULKAN_SO_PATH)),
52 shell_test_external_view_embedder_(
53 std::move(shell_test_external_view_embedder)) {}
54
56
57std::unique_ptr<VsyncWaiter> ShellTestPlatformViewVulkan::CreateVSyncWaiter() {
58 return create_vsync_waiter_();
59}
60
62 vsync_clock_->SimulateVSync();
63}
64
65// |PlatformView|
66std::unique_ptr<Surface> ShellTestPlatformViewVulkan::CreateRenderingSurface() {
67 return std::make_unique<OffScreenSurface>(proc_table_,
68 shell_test_external_view_embedder_);
69}
70
71// |PlatformView|
72std::shared_ptr<ExternalViewEmbedder>
73ShellTestPlatformViewVulkan::CreateExternalViewEmbedder() {
74 return shell_test_external_view_embedder_;
75}
76
77// |PlatformView|
78PointerDataDispatcherMaker ShellTestPlatformViewVulkan::GetDispatcherMaker() {
79 return [](DefaultPointerDataDispatcher::Delegate& delegate) {
80 return std::make_unique<SmoothPointerDataDispatcher>(delegate);
81 };
82}
83
84// TODO(gw280): This code was forked from vulkan_window.cc specifically for
85// shell_test.
86// We need to merge this functionality back into //vulkan.
87// https://github.com/flutter/flutter/issues/51132
88ShellTestPlatformViewVulkan::OffScreenSurface::OffScreenSurface(
90 std::shared_ptr<ShellTestExternalViewEmbedder>
91 shell_test_external_view_embedder)
92 : vk_(std::move(vk)),
93 shell_test_external_view_embedder_(
94 std::move(shell_test_external_view_embedder)) {
95 if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) {
96 FML_DLOG(ERROR) << "Proc table has not acquired mandatory proc addresses.";
97 return;
98 }
99
100 // Create the application instance.
101 std::vector<std::string> extensions = {
102 VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
103 };
104
105 application_ = std::make_unique<vulkan::VulkanApplication>(
106 *vk_, "FlutterTest", std::move(extensions), VK_MAKE_VERSION(1, 0, 0),
107 VK_MAKE_VERSION(1, 1, 0), true);
108
109 if (!application_->IsValid() || !vk_->AreInstanceProcsSetup()) {
110 // Make certain the application instance was created and it set up the
111 // instance proc table entries.
112 FML_DLOG(ERROR) << "Instance proc addresses have not been set up.";
113 return;
114 }
115
116 // Create the device.
117
118 logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();
119
120 if (logical_device_ == nullptr || !logical_device_->IsValid() ||
121 !vk_->AreDeviceProcsSetup()) {
122 // Make certain the device was created and it set up the device proc table
123 // entries.
124 FML_DLOG(ERROR) << "Device proc addresses have not been set up.";
125 return;
126 }
127
128 memory_allocator_ = FlutterSkiaVulkanMemoryAllocator::Make(
129 application_->GetAPIVersion(), application_->GetInstance(),
130 logical_device_->GetPhysicalDeviceHandle(), logical_device_->GetHandle(),
131 vk_, true);
132
133 // Create the Skia GrContext.
134 if (!CreateSkiaGrContext()) {
135 FML_DLOG(ERROR) << "Could not create Skia context.";
136 return;
137 }
138
139 valid_ = true;
140}
141
142bool ShellTestPlatformViewVulkan::OffScreenSurface::CreateSkiaGrContext() {
143 skgpu::VulkanBackendContext backend_context;
144 skgpu::VulkanExtensions no_extensions;
145 // For now, Skia crashes if fDeviceFeatures is set but fVkExtensions is not.
146 backend_context.fVkExtensions = &no_extensions;
147 VkPhysicalDeviceFeatures features;
148 // It may be tempting to put features into backend_context here
149 // and pass just backend_context into the below function, however the pointers
150 // for features are const, so we won't be able to update them.
151
152 if (!this->CreateSkiaBackendContext(&backend_context, &features)) {
153 FML_DLOG(ERROR) << "Could not create Skia backend context.";
154 return false;
155 }
156
157 const auto options =
158 MakeDefaultContextOptions(ContextType::kRender, GrBackendApi::kVulkan);
159
160 sk_sp<GrDirectContext> context =
161 GrDirectContexts::MakeVulkan(backend_context, options);
162
163 if (context == nullptr) {
164 FML_DLOG(ERROR) << "Failed to create GrDirectContext";
165 return false;
166 }
167
168 context->setResourceCacheLimit(vulkan::kGrCacheMaxByteSize);
169
170 context_ = context;
171
172 return true;
173}
174
175bool ShellTestPlatformViewVulkan::OffScreenSurface::CreateSkiaBackendContext(
176 skgpu::VulkanBackendContext* context,
177 VkPhysicalDeviceFeatures* features) {
178 FML_CHECK(context);
179 FML_CHECK(features);
180 auto getProc = CreateSkiaGetProc(vk_);
181
182 if (getProc == nullptr) {
183 FML_DLOG(ERROR) << "GetProcAddress is null";
184 return false;
185 }
186
187 if (!logical_device_->GetPhysicalDeviceFeatures(features)) {
188 FML_DLOG(ERROR) << "Failed to get Physical Device features";
189 return false;
190 }
191
192 context->fInstance = application_->GetInstance();
193 context->fPhysicalDevice = logical_device_->GetPhysicalDeviceHandle();
194 context->fDevice = logical_device_->GetHandle();
195 context->fQueue = logical_device_->GetQueueHandle();
196 context->fGraphicsQueueIndex = logical_device_->GetGraphicsQueueIndex();
197 context->fMaxAPIVersion = application_->GetAPIVersion();
198 context->fDeviceFeatures = features;
199 context->fGetProc = std::move(getProc);
200 context->fMemoryAllocator = memory_allocator_;
201
202 return true;
203}
204
205ShellTestPlatformViewVulkan::OffScreenSurface::~OffScreenSurface() {}
206
207bool ShellTestPlatformViewVulkan::OffScreenSurface::IsValid() {
208 return valid_;
209}
210
211std::unique_ptr<SurfaceFrame>
212ShellTestPlatformViewVulkan::OffScreenSurface::AcquireFrame(
213 const DlISize& size) {
214 auto image_info = SkImageInfo::Make(size.width, size.height,
215 SkColorType::kRGBA_8888_SkColorType,
216 SkAlphaType::kOpaque_SkAlphaType);
217 auto surface = SkSurfaces::RenderTarget(context_.get(), skgpu::Budgeted::kNo,
218 image_info, 0, nullptr);
219
220 SurfaceFrame::EncodeCallback encode_callback = [](const SurfaceFrame&,
221 DlCanvas* canvas) -> bool {
222 canvas->Flush();
223 return true;
224 };
225 SurfaceFrame::SubmitCallback submit_callback =
226 [](const SurfaceFrame&) -> bool { return true; };
227
228 SurfaceFrame::FramebufferInfo framebuffer_info;
229 framebuffer_info.supports_readback = true;
230
231 return std::make_unique<SurfaceFrame>(std::move(surface), framebuffer_info,
232 std::move(encode_callback),
233 std::move(submit_callback),
234 /*frame_size=*/DlISize(800, 600));
235}
236
237GrDirectContext* ShellTestPlatformViewVulkan::OffScreenSurface::GetContext() {
238 return context_.get();
239}
240
241DlMatrix ShellTestPlatformViewVulkan::OffScreenSurface::GetRootTransformation()
242 const {
243 return DlMatrix();
244}
245
246} // namespace flutter::testing
static sk_sp< VulkanMemoryAllocator > Make(uint32_t vulkan_api_version, VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, const fml::RefPtr< vulkan::VulkanProcTable > &vk, bool mustUseCoherentHostVisibleMemory)
Used to forward events from the platform view to interested subsystems. This forwarding is done by th...
std::function< bool(SurfaceFrame &surface_frame, DlCanvas *canvas)> EncodeCallback
std::function< bool(SurfaceFrame &surface_frame)> SubmitCallback
static std::unique_ptr< ShellTestPlatformView > CreateVulkan(PlatformView::Delegate &delegate, const TaskRunners &task_runners, const std::shared_ptr< ShellTestVsyncClock > &vsync_clock, const CreateVsyncWaiter &create_vsync_waiter, const std::shared_ptr< ShellTestExternalViewEmbedder > &shell_test_external_view_embedder, const std::shared_ptr< const fml::SyncSwitch > &is_gpu_disabled_sync_switch)
ShellTestPlatformViewVulkan(PlatformView::Delegate &delegate, const TaskRunners &task_runners, std::shared_ptr< ShellTestVsyncClock > vsync_clock, CreateVsyncWaiter create_vsync_waiter, std::shared_ptr< ShellTestExternalViewEmbedder > shell_test_external_view_embedder)
VkSurfaceKHR surface
Definition main.cc:65
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_CHECK(condition)
Definition logging.h:104
std::function< std::unique_ptr< VsyncWaiter >()> CreateVsyncWaiter
impeller::Matrix DlMatrix
impeller::ISize32 DlISize
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
GrContextOptions MakeDefaultContextOptions(ContextType type, std::optional< GrBackendApi > api)
Initializes GrContextOptions with values suitable for Flutter. The options can be further tweaked bef...
std::function< std::unique_ptr< PointerDataDispatcher >(PointerDataDispatcher::Delegate &)> PointerDataDispatcherMaker
Signature for constructing PointerDataDispatcher.
@ kRender
The context is used to render to a texture or renderbuffer.
Definition ref_ptr.h:261
flutter::DlCanvas DlCanvas
skgpu::VulkanGetProc CreateSkiaGetProc(const fml::RefPtr< vulkan::VulkanProcTable > &vk)
static const size_t kGrCacheMaxByteSize
#define VULKAN_SO_PATH