Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 249e0fa

Browse files
committed
Make GPUSurfaceVulkan use delegate (EmbedderSurfaceVulkan) and create Vulkan-backed SkSurfaces used by EmbedderExternalViewEmbedder
1 parent afa70e9 commit 249e0fa

File tree

3 files changed

+115
-31
lines changed

3 files changed

+115
-31
lines changed

shell/gpu/gpu_surface_vulkan.cc

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
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"
810

911
namespace flutter {
1012

@@ -23,42 +25,57 @@ bool GPUSurfaceVulkan::IsValid() {
2325
}
2426

2527
std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
26-
const SkISize& size) {
27-
VkImage image = delegate_->AcquireImage(size);
28+
const SkISize& frame_size) {
29+
if (!IsValid()) {
30+
FML_LOG(ERROR) << "Vulkan surface was invalid.";
31+
return nullptr;
32+
}
33+
34+
if (frame_size.isEmpty()) {
35+
FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
36+
return nullptr;
37+
}
2838

29-
// TODO(38466): Refactor GPU surface APIs take into account the fact that an
30-
// external view embedder may want to render to the root surface.
3139
if (!render_to_surface_) {
3240
return std::make_unique<SurfaceFrame>(
33-
nullptr, std::move(framebuffer_info),
41+
nullptr, SurfaceFrame::FramebufferInfo(),
3442
[](const SurfaceFrame& surface_frame, SkCanvas* canvas) {
3543
return true;
3644
});
3745
}
3846

39-
sk_sp<SkSurface> surface = window_.AcquireSurface();
47+
VkImage image = delegate_->AcquireImage(frame_size);
48+
if (!image) {
49+
FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
50+
return nullptr;
51+
}
4052

41-
if (surface == nullptr) {
53+
sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage(image, frame_size);
54+
if (!surface) {
55+
FML_LOG(ERROR) << "Could not create the SkSurface from the Vulkan image.";
4256
return nullptr;
4357
}
4458

45-
SurfaceFrame::SubmitCallback callback =
46-
[weak_this = weak_factory_.GetWeakPtr()](const SurfaceFrame&,
47-
SkCanvas* canvas) -> bool {
48-
// Frames are only ever acquired on the raster thread. This is also the
49-
// thread on which the weak pointer factory is collected (as this instance
50-
// is owned by the rasterizer). So this use of weak pointers is safe.
51-
if (canvas == nullptr || !weak_this) {
59+
SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
60+
const SurfaceFrame&,
61+
SkCanvas* canvas) -> bool {
62+
TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
63+
if (canvas == nullptr) {
64+
FML_DLOG(ERROR) << "Canvas not available.";
5265
return false;
5366
}
54-
return weak_this->Present();
67+
68+
canvas->flush();
69+
70+
return delegate->PresentImage(image);
5571
};
72+
73+
SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
74+
5675
return std::make_unique<SurfaceFrame>(
5776
std::move(surface), std::move(framebuffer_info), std::move(callback));
5877
}
5978

60-
bool GPUSurfaceVulkan::Present() {}
61-
6279
SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
6380
// This backend does not support delegating to the underlying platform to
6481
// query for root surface transformations. Just return identity.
@@ -71,7 +88,37 @@ GrDirectContext* GPUSurfaceVulkan::GetContext() {
7188
return skia_context_.get();
7289
}
7390

74-
sk_sp<SkSurface> GPUSurfaceVulkan::AcquireSurfaceFromVulkanImage(
75-
VkImage image) {}
91+
sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage(
92+
VkImage image,
93+
const SkISize& size) {
94+
GrVkImageInfo image_info = {
95+
.fImage = image,
96+
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
97+
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
98+
.fFormat = VK_FORMAT_R8G8B8A8_UNORM,
99+
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
100+
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
101+
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
102+
VK_IMAGE_USAGE_SAMPLED_BIT,
103+
.fSampleCount = 1,
104+
.fLevelCount = 1,
105+
};
106+
GrBackendTexture backend_texture(size.width(), //
107+
size.height(), //
108+
image_info //
109+
);
110+
111+
SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
112+
113+
return SkSurface::MakeFromBackendTexture(
114+
skia_context_.get(), // context
115+
backend_texture, // back-end texture
116+
kTopLeft_GrSurfaceOrigin, // surface origin
117+
1, // sample count
118+
kRGBA_8888_SkColorType, // color type
119+
SkColorSpace::MakeSRGB(), // color space
120+
&surface_properties // surface properties
121+
);
122+
}
76123

77124
} // namespace flutter

shell/gpu/gpu_surface_vulkan.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ class GPUSurfaceVulkan : public Surface {
4040
// |Surface|
4141
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;
4242

43-
/// @brief Called when a frame is done rendering. It blocks on the render
44-
/// fence and then calls `GPUSurfaceVulkanDelegate::PresentImage` with
45-
/// the populated image.
46-
bool Present();
47-
4843
// |Surface|
4944
SkMatrix GetRootTransformation() const override;
5045

@@ -56,13 +51,10 @@ class GPUSurfaceVulkan : public Surface {
5651
sk_sp<GrDirectContext> skia_context_;
5752
bool render_to_surface_;
5853

59-
std::unique_ptr<vulkan::VulkanBackbuffer> backbuffer_;
60-
sk_sp<SkSurface> surface_;
61-
size_t current_backbuffer_index_;
62-
6354
fml::WeakPtrFactory<GPUSurfaceVulkan> weak_factory_;
6455

65-
sk_sp<SkSurface> AcquireSurfaceFromVulkanImage(VkImage image);
56+
sk_sp<SkSurface> CreateSurfaceFromVulkanImage(VkImage image,
57+
const SkISize& size);
6658

6759
FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkan);
6860
};

shell/platform/embedder/embedder.cc

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ InferVulkanPlatformViewCreationCallback(
387387
vulkan_get_instance_proc_address =
388388
[ptr = config->vulkan.get_instance_proc_address_callback, user_data](
389389
VkInstance instance, const char* proc_name) -> void* {
390-
ptr(user_data, instance, proc_name);
390+
return ptr(user_data, instance, proc_name);
391391
};
392392

393393
auto vulkan_get_next_image =
@@ -689,8 +689,53 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
689689
GrDirectContext* context,
690690
const FlutterBackingStoreConfig& config,
691691
const FlutterVulkanBackingStore* vulkan) {
692-
assert(false); // TODO(bdero)
692+
#ifdef SHELL_ENABLE_VULKAN
693+
if (!vulkan->image.image) {
694+
FML_LOG(ERROR) << "Embedder supplied null Vulkan image.";
695+
return nullptr;
696+
}
697+
698+
GrVkImageInfo image_info = {
699+
.fImage = static_cast<VkImage>(vulkan->image.image),
700+
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
701+
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
702+
.fFormat = VK_FORMAT_R8G8B8A8_UNORM,
703+
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
704+
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
705+
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
706+
VK_IMAGE_USAGE_SAMPLED_BIT,
707+
.fSampleCount = 1,
708+
.fLevelCount = 1,
709+
};
710+
GrBackendTexture backend_texture(config.size.width, //
711+
config.size.height, //
712+
image_info //
713+
);
714+
715+
SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
716+
717+
auto surface = SkSurface::MakeFromBackendTexture(
718+
context, // context
719+
backend_texture, // back-end texture
720+
kTopLeft_GrSurfaceOrigin, // surface origin
721+
1, // sample count
722+
kRGBA_8888_SkColorType, // color type
723+
SkColorSpace::MakeSRGB(), // color space
724+
&surface_properties, // surface properties
725+
static_cast<SkSurface::TextureReleaseProc>(
726+
vulkan->image.destruction_callback), // release proc
727+
vulkan->image.user_data // release context
728+
);
729+
730+
if (!surface) {
731+
FML_LOG(ERROR) << "Could not wrap embedder supplied Vulkan render texture.";
732+
return nullptr;
733+
}
734+
735+
return surface;
736+
#else
693737
return nullptr;
738+
#endif
694739
}
695740

696741
static std::unique_ptr<flutter::EmbedderRenderTarget>

0 commit comments

Comments
 (0)