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
5#include "flutter/shell/gpu/gpu_surface_vulkan.h"
6
7#include "flutter/fml/logging.h"
8#include "flutter/fml/trace_event.h"
9
10#include "third_party/skia/include/core/SkColorSpace.h"
11#include "third_party/skia/include/core/SkSize.h"
12#include "third_party/skia/include/core/SkSurface.h"
13#include "third_party/skia/include/gpu/GrBackendSurface.h"
14#include "third_party/skia/include/gpu/GrDirectContext.h"
15#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
16#include "vulkan/vulkan_core.h"
17
18namespace flutter {
19
20GPUSurfaceVulkan::GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
21 const sk_sp<GrDirectContext>& skia_context,
22 bool render_to_surface)
23 : delegate_(delegate),
24 skia_context_(skia_context),
25 render_to_surface_(render_to_surface),
26 weak_factory_(this) {}
27
28GPUSurfaceVulkan::~GPUSurfaceVulkan() = default;
29
30bool GPUSurfaceVulkan::IsValid() {
31 return skia_context_ != nullptr;
32}
33
34std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
35 const SkISize& frame_size) {
36 if (!IsValid()) {
37 FML_LOG(ERROR) << "Vulkan surface was invalid.";
38 return nullptr;
39 }
40
41 if (frame_size.isEmpty()) {
42 FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
43 return nullptr;
44 }
45
46 if (!render_to_surface_) {
47 return std::make_unique<SurfaceFrame>(
48 args: nullptr, args: SurfaceFrame::FramebufferInfo(),
49 args: [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
50 return true;
51 },
52 args: frame_size);
53 }
54
55 FlutterVulkanImage image = delegate_->AcquireImage(size: frame_size);
56 if (!image.image) {
57 FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
58 return nullptr;
59 }
60
61 sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage(
62 image: reinterpret_cast<VkImage>(image.image),
63 format: static_cast<VkFormat>(image.format), size: frame_size);
64 if (!surface) {
65 FML_LOG(ERROR) << "Could not create the SkSurface from the Vulkan image.";
66 return nullptr;
67 }
68
69 SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
70 const SurfaceFrame&,
71 DlCanvas* canvas) -> bool {
72 TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
73 if (canvas == nullptr) {
74 FML_DLOG(ERROR) << "Canvas not available.";
75 return false;
76 }
77
78 canvas->Flush();
79
80 return delegate->PresentImage(image: reinterpret_cast<VkImage>(image.image),
81 format: static_cast<VkFormat>(image.format));
82 };
83
84 SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
85
86 return std::make_unique<SurfaceFrame>(args: std::move(surface), args&: framebuffer_info,
87 args: std::move(callback), args: frame_size);
88}
89
90SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
91 // This backend does not support delegating to the underlying platform to
92 // query for root surface transformations. Just return identity.
93 SkMatrix matrix;
94 matrix.reset();
95 return matrix;
96}
97
98GrDirectContext* GPUSurfaceVulkan::GetContext() {
99 return skia_context_.get();
100}
101
102sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage(
103 const VkImage image,
104 const VkFormat format,
105 const SkISize& size) {
106 GrVkImageInfo image_info = {
107 .fImage = image,
108 .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
109 .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
110 .fFormat = format,
111 .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
112 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
113 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
114 VK_IMAGE_USAGE_SAMPLED_BIT,
115 .fSampleCount = 1,
116 .fLevelCount = 1,
117 };
118 GrBackendTexture backend_texture(size.width(), //
119 size.height(), //
120 image_info //
121 );
122
123 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
124
125 return SkSurfaces::WrapBackendTexture(
126 context: skia_context_.get(), // context
127 backendTexture: backend_texture, // back-end texture
128 origin: kTopLeft_GrSurfaceOrigin, // surface origin
129 sampleCnt: 1, // sample count
130 colorType: ColorTypeFromFormat(format), // color type
131 colorSpace: SkColorSpace::MakeSRGB(), // color space
132 surfaceProps: &surface_properties // surface properties
133 );
134}
135
136SkColorType GPUSurfaceVulkan::ColorTypeFromFormat(const VkFormat format) {
137 switch (format) {
138 case VK_FORMAT_R8G8B8A8_UNORM:
139 case VK_FORMAT_R8G8B8A8_SRGB:
140 return SkColorType::kRGBA_8888_SkColorType;
141 case VK_FORMAT_B8G8R8A8_UNORM:
142 case VK_FORMAT_B8G8R8A8_SRGB:
143 return SkColorType::kBGRA_8888_SkColorType;
144 default:
145 return SkColorType::kUnknown_SkColorType;
146 }
147}
148
149} // namespace flutter
150

source code of flutter_engine/flutter/shell/gpu/gpu_surface_vulkan.cc

Morty Proxy This is a proxified and sanitized view of the page, visit original site.