55#include " flutter/shell/gpu/gpu_surface_vulkan.h"
66
77#include " flutter/fml/logging.h"
8+ #include " fml/trace_event.h"
9+ #include " include/core/SkSize.h"
10+ #include " third_party/swiftshader/include/vulkan/vulkan_core.h"
811
912namespace flutter {
1013
11- GPUSurfaceVulkan::GPUSurfaceVulkan (
12- GPUSurfaceVulkanDelegate* delegate,
13- std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
14- bool render_to_surface)
15- : GPUSurfaceVulkan(/* context=*/ nullptr ,
16- delegate,
17- std::move (native_surface),
18- render_to_surface) {}
19-
20- GPUSurfaceVulkan::GPUSurfaceVulkan (
21- const sk_sp<GrDirectContext>& context,
22- GPUSurfaceVulkanDelegate* delegate,
23- std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
24- bool render_to_surface)
25- : window_(context,
26- delegate->vk (),
27- std::move(native_surface),
28- render_to_surface),
14+ GPUSurfaceVulkan::GPUSurfaceVulkan (GPUSurfaceVulkanDelegate* delegate,
15+ const sk_sp<GrDirectContext>& skia_context,
16+ bool render_to_surface)
17+ : delegate_(delegate),
18+ skia_context_ (skia_context),
2919 render_to_surface_(render_to_surface),
3020 weak_factory_(this ) {}
3121
3222GPUSurfaceVulkan::~GPUSurfaceVulkan () = default ;
3323
3424bool GPUSurfaceVulkan::IsValid () {
35- return window_. IsValid () ;
25+ return skia_context_ != nullptr ;
3626}
3727
3828std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame (
39- const SkISize& size) {
40- SurfaceFrame::FramebufferInfo framebuffer_info;
41- framebuffer_info.supports_readback = true ;
29+ const SkISize& frame_size) {
30+ if (!IsValid ()) {
31+ FML_LOG (ERROR) << " Vulkan surface was invalid." ;
32+ return nullptr ;
33+ }
34+
35+ if (frame_size.isEmpty ()) {
36+ FML_LOG (ERROR) << " Vulkan surface was asked for an empty frame." ;
37+ return nullptr ;
38+ }
4239
43- // TODO(38466): Refactor GPU surface APIs take into account the fact that an
44- // external view embedder may want to render to the root surface.
4540 if (!render_to_surface_) {
4641 return std::make_unique<SurfaceFrame>(
47- nullptr , std::move (framebuffer_info ),
42+ nullptr , SurfaceFrame::FramebufferInfo ( ),
4843 [](const SurfaceFrame& surface_frame, SkCanvas* canvas) {
4944 return true ;
5045 });
5146 }
5247
53- auto surface = window_.AcquireSurface ();
48+ FlutterVulkanImage image = delegate_->AcquireImage (frame_size);
49+ if (!image.image ) {
50+ FML_LOG (ERROR) << " Invalid VkImage given by the embedder." ;
51+ return nullptr ;
52+ }
5453
55- if (surface == nullptr ) {
54+ sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage (
55+ reinterpret_cast <VkImage>(image.image ),
56+ static_cast <VkFormat>(image.format ), frame_size);
57+ if (!surface) {
58+ FML_LOG (ERROR) << " Could not create the SkSurface from the Vulkan image." ;
5659 return nullptr ;
5760 }
5861
59- SurfaceFrame::SubmitCallback callback =
60- [weak_this = weak_factory_.GetWeakPtr ()](const SurfaceFrame&,
61- SkCanvas* canvas) -> bool {
62- // Frames are only ever acquired on the raster thread. This is also the
63- // thread on which the weak pointer factory is collected (as this instance
64- // is owned by the rasterizer). So this use of weak pointers is safe.
65- if (canvas == nullptr || !weak_this) {
62+ SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
63+ const SurfaceFrame&,
64+ SkCanvas* canvas) -> bool {
65+ TRACE_EVENT0 (" flutter" , " GPUSurfaceVulkan::PresentImage" );
66+ if (canvas == nullptr ) {
67+ FML_DLOG (ERROR) << " Canvas not available." ;
6668 return false ;
6769 }
68- return weak_this->window_ .SwapBuffers ();
70+
71+ canvas->flush ();
72+
73+ return delegate->PresentImage (reinterpret_cast <VkImage>(image.image ),
74+ static_cast <VkFormat>(image.format ));
6975 };
76+
77+ SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true };
78+
7079 return std::make_unique<SurfaceFrame>(
7180 std::move (surface), std::move (framebuffer_info), std::move (callback));
7281}
@@ -80,7 +89,54 @@ SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
8089}
8190
8291GrDirectContext* GPUSurfaceVulkan::GetContext () {
83- return window_.GetSkiaGrContext ();
92+ return skia_context_.get ();
93+ }
94+
95+ sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage (
96+ const VkImage image,
97+ const VkFormat format,
98+ const SkISize& size) {
99+ GrVkImageInfo image_info = {
100+ .fImage = image,
101+ .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
102+ .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
103+ .fFormat = format,
104+ .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
105+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
106+ VK_IMAGE_USAGE_TRANSFER_DST_BIT |
107+ VK_IMAGE_USAGE_SAMPLED_BIT,
108+ .fSampleCount = 1 ,
109+ .fLevelCount = 1 ,
110+ };
111+ GrBackendTexture backend_texture (size.width (), //
112+ size.height (), //
113+ image_info //
114+ );
115+
116+ SkSurfaceProps surface_properties (0 , kUnknown_SkPixelGeometry );
117+
118+ return SkSurface::MakeFromBackendTexture (
119+ skia_context_.get (), // context
120+ backend_texture, // back-end texture
121+ kTopLeft_GrSurfaceOrigin , // surface origin
122+ 1 , // sample count
123+ ColorTypeFromFormat (format), // color type
124+ SkColorSpace::MakeSRGB (), // color space
125+ &surface_properties // surface properties
126+ );
127+ }
128+
129+ SkColorType GPUSurfaceVulkan::ColorTypeFromFormat (const VkFormat format) {
130+ switch (format) {
131+ case VK_FORMAT_R8G8B8A8_UNORM:
132+ case VK_FORMAT_R8G8B8A8_SRGB:
133+ return SkColorType::kRGBA_8888_SkColorType ;
134+ case VK_FORMAT_B8G8R8A8_UNORM:
135+ case VK_FORMAT_B8G8R8A8_SRGB:
136+ return SkColorType::kBGRA_8888_SkColorType ;
137+ default :
138+ return SkColorType::kUnknown_SkColorType ;
139+ }
84140}
85141
86142} // namespace flutter
0 commit comments