Skip to content

Commit

Permalink
Make GPUSurfaceVulkan use delegate (EmbedderSurfaceVulkan) and create…
Browse files Browse the repository at this point in the history
… Vulkan-backed SkSurfaces used by EmbedderExternalViewEmbedder
  • Loading branch information
bdero committed Nov 17, 2021
1 parent 98d36f5 commit 5ae6eeb
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 31 deletions.
85 changes: 66 additions & 19 deletions shell/gpu/gpu_surface_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "flutter/shell/gpu/gpu_surface_vulkan.h"

#include "flutter/fml/logging.h"
#include "fml/trace_event.h"
#include "include/core/SkSize.h"

namespace flutter {

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

std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
const SkISize& size) {
VkImage image = delegate_->AcquireImage(size);
const SkISize& frame_size) {
if (!IsValid()) {
FML_LOG(ERROR) << "Vulkan surface was invalid.";
return nullptr;
}

if (frame_size.isEmpty()) {
FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
return nullptr;
}

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

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

if (surface == nullptr) {
sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage(image, frame_size);
if (!surface) {
FML_LOG(ERROR) << "Could not create the SkSurface from the Vulkan image.";
return nullptr;
}

SurfaceFrame::SubmitCallback callback =
[weak_this = weak_factory_.GetWeakPtr()](const SurfaceFrame&,
SkCanvas* canvas) -> bool {
// Frames are only ever acquired on the raster thread. This is also the
// thread on which the weak pointer factory is collected (as this instance
// is owned by the rasterizer). So this use of weak pointers is safe.
if (canvas == nullptr || !weak_this) {
SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
const SurfaceFrame&,
SkCanvas* canvas) -> bool {
TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
if (canvas == nullptr) {
FML_DLOG(ERROR) << "Canvas not available.";
return false;
}
return weak_this->Present();

canvas->flush();

return delegate->PresentImage(image);
};

SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};

return std::make_unique<SurfaceFrame>(
std::move(surface), std::move(framebuffer_info), std::move(callback));
}

bool GPUSurfaceVulkan::Present() {}

SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
// This backend does not support delegating to the underlying platform to
// query for root surface transformations. Just return identity.
Expand All @@ -71,7 +88,37 @@ GrDirectContext* GPUSurfaceVulkan::GetContext() {
return skia_context_.get();
}

sk_sp<SkSurface> GPUSurfaceVulkan::AcquireSurfaceFromVulkanImage(
VkImage image) {}
sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage(
VkImage image,
const SkISize& size) {
GrVkImageInfo image_info = {
.fImage = image,
.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,
};
GrBackendTexture backend_texture(size.width(), //
size.height(), //
image_info //
);

SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);

return SkSurface::MakeFromBackendTexture(
skia_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
);
}

} // namespace flutter
12 changes: 2 additions & 10 deletions shell/gpu/gpu_surface_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ class GPUSurfaceVulkan : public Surface {
// |Surface|
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;

/// @brief Called when a frame is done rendering. It blocks on the render
/// fence and then calls `GPUSurfaceVulkanDelegate::PresentImage` with
/// the populated image.
bool Present();

// |Surface|
SkMatrix GetRootTransformation() const override;

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

std::unique_ptr<vulkan::VulkanBackbuffer> backbuffer_;
sk_sp<SkSurface> surface_;
size_t current_backbuffer_index_;

fml::WeakPtrFactory<GPUSurfaceVulkan> weak_factory_;

sk_sp<SkSurface> AcquireSurfaceFromVulkanImage(VkImage image);
sk_sp<SkSurface> CreateSurfaceFromVulkanImage(VkImage image,
const SkISize& size);

FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkan);
};
Expand Down
49 changes: 47 additions & 2 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ InferVulkanPlatformViewCreationCallback(
vulkan_get_instance_proc_address =
[ptr = config->vulkan.get_instance_proc_address_callback, user_data](
VkInstance instance, const char* proc_name) -> void* {
ptr(user_data, instance, proc_name);
return ptr(user_data, instance, proc_name);
};

auto vulkan_get_next_image =
Expand Down Expand Up @@ -689,8 +689,53 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
GrDirectContext* context,
const FlutterBackingStoreConfig& config,
const FlutterVulkanBackingStore* vulkan) {
assert(false); // TODO(bdero)
#ifdef SHELL_ENABLE_VULKAN
if (!vulkan->image.image) {
FML_LOG(ERROR) << "Embedder supplied null Vulkan image.";
return nullptr;
}

GrVkImageInfo image_info = {
.fImage = static_cast<VkImage>(vulkan->image.image),
.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,
};
GrBackendTexture backend_texture(config.size.width, //
config.size.height, //
image_info //
);

SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);

auto surface = SkSurface::MakeFromBackendTexture(
context, // 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
static_cast<SkSurface::TextureReleaseProc>(
vulkan->image.destruction_callback), // release proc
vulkan->image.user_data // release context
);

if (!surface) {
FML_LOG(ERROR) << "Could not wrap embedder supplied Vulkan render texture.";
return nullptr;
}

return surface;
#else
return nullptr;
#endif
}

static std::unique_ptr<flutter::EmbedderRenderTarget>
Expand Down

0 comments on commit 5ae6eeb

Please sign in to comment.