Flutter Engine
 
Loading...
Searching...
No Matches
surface_texture_external_texture_vk_impeller.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 <chrono>
8
9#include <GLES2/gl2.h>
10#define GL_GLEXT_PROTOTYPES
11#include <GLES2/gl2ext.h>
12
19
20namespace flutter {
21
22using namespace impeller;
23
26 std::shared_ptr<impeller::ContextVK> context,
27 int64_t id,
28 const fml::jni::ScopedJavaGlobalRef<jobject>& surface_texture,
29 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
30 : SurfaceTextureExternalTexture(id, surface_texture, jni_facade),
31 context_(std::move(context)),
32 trampoline_(std::make_shared<glvk::Trampoline>()) {
33 is_valid_ = trampoline_->IsValid();
34}
35
38
39enum class LayoutUpdateMode {
40 kSync,
41 kAsync,
42};
43
44static bool SetTextureLayout(const ContextVK& context,
46 vk::ImageLayout layout,
47 LayoutUpdateMode mode) {
48 TRACE_EVENT0("flutter", __FUNCTION__);
49 if (!texture) {
50 return true;
51 }
52 auto command_buffer = context.CreateCommandBuffer();
53 if (!command_buffer) {
55 << "Could not create command buffer for texture layout update.";
56 return false;
57 }
58 command_buffer->SetLabel("GLVKTextureLayoutUpdateCB");
59 const CommandBufferVK& encoder = CommandBufferVK::Cast(*command_buffer);
60 const auto command_buffer_vk = encoder.GetCommandBuffer();
61
62 BarrierVK barrier;
63 barrier.cmd_buffer = command_buffer_vk;
64 barrier.new_layout = layout;
65 barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
66 impeller::vk::PipelineStageFlagBits::eFragmentShader;
67 barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite |
68 vk::AccessFlagBits::eShaderRead;
69 barrier.dst_stage = impeller::vk::PipelineStageFlagBits::eFragmentShader;
70 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
71
72 if (!texture->SetLayout(barrier).ok()) {
73 VALIDATION_LOG << "Could not encoder layout transition.";
74 return false;
75 }
76
77 encoder.EndCommandBuffer();
78
79 vk::SubmitInfo submit_info;
80 submit_info.setCommandBuffers(command_buffer_vk);
81
82 // There is no need to track the fence in the encoder since we are going to do
83 // a sync wait for completion.
84 vk::UniqueFence fence;
85
87 auto fence_pair =
88 context.GetDevice().createFenceUnique(vk::FenceCreateFlags{});
89 if (fence_pair.result != impeller::vk::Result::eSuccess) {
90 VALIDATION_LOG << "Could not create fence.";
91 return false;
92 }
93 fence = std::move(fence_pair.value);
94 }
95
96 if (context.GetGraphicsQueue()->Submit(submit_info, fence.get()) !=
97 impeller::vk::Result::eSuccess) {
98 VALIDATION_LOG << "Could not submit layout transition fence.";
99 return false;
100 }
101
102 using namespace std::chrono_literals;
103
104 if (fence &&
105 context.GetDevice().waitForFences(
106 fence.get(), //
107 VK_TRUE, //
108 std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count() //
109 ) != impeller::vk::Result::eSuccess) {
110 VALIDATION_LOG << "Could not perform sync wait on fence.";
111 return false;
112 }
113
114 return true;
115}
116
117// |SurfaceTextureExternalTexture|
118void SurfaceTextureExternalTextureVKImpeller::ProcessFrame(
119 PaintContext& context,
120 const SkRect& bounds) {
121 if (!is_valid_ || !context.aiks_context) {
122 VALIDATION_LOG << "Invalid external texture.";
123 return;
124 }
125 DlMatrix matrix = context.canvas->GetMatrix();
126 DlRect mapped_bounds = ToDlRect(bounds).TransformAndClipBounds(matrix);
127
128 const auto& surface_context =
129 SurfaceContextVK::Cast(*context.aiks_context->GetContext());
130 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
131
132 auto dst_texture = GetCachedTextureSource(
133 surface_context.GetParent(), //
134 ISize::MakeWH(mapped_bounds.GetWidth(), mapped_bounds.GetHeight()) //
135 );
136 if (!dst_texture || !dst_texture->IsValid()) {
137 VALIDATION_LOG << "Could not fetch trampoline texture target.";
138 return;
139 }
140
141 auto current_context = trampoline_->MakeCurrentContext();
142
143 GLuint src_gl_texture = {};
144 glGenTextures(1u, &src_gl_texture);
145 Attach(src_gl_texture);
146 Update();
147
148 SetTextureLayout(context_vk, dst_texture.get(),
149 vk::ImageLayout::eColorAttachmentOptimal,
151
152 impeller::Matrix uv_transformation;
153 GetCurrentUVTransformation().getColMajor(
154 reinterpret_cast<SkScalar*>(&uv_transformation));
155
157 src_texture.texture = src_gl_texture;
158 src_texture.target = GL_TEXTURE_EXTERNAL_OES;
159 src_texture.uv_transformation = uv_transformation;
160
161 if (!trampoline_->BlitTextureOpenGLToVulkan(src_texture, *dst_texture)) {
162 VALIDATION_LOG << "Texture copy failed.";
163 }
164
165 SetTextureLayout(context_vk, dst_texture.get(),
166 vk::ImageLayout::eShaderReadOnlyOptimal,
168
169 glDeleteTextures(1u, &src_gl_texture);
170
172 std::make_shared<TextureVK>(surface_context.GetParent(), dst_texture));
173}
174
175// |SurfaceTextureExternalTexture|
176void SurfaceTextureExternalTextureVKImpeller::Detach() {
177 // Detaching from the underlying surface texture requires a context to be
178 // current. On the other hand, the texture source is a pure Vulkan construct
179 // and has no EGL related requirements.
180 auto context = trampoline_->MakeCurrentContext();
182 cached_texture_source_.reset();
183}
184
185std::shared_ptr<impeller::AHBTextureSourceVK>
186SurfaceTextureExternalTextureVKImpeller::GetCachedTextureSource(
187 const std::shared_ptr<Context>& context,
188 const impeller::ISize& size) {
189 if (cached_texture_source_ &&
190 cached_texture_source_->GetTextureDescriptor().size == size) {
191 return cached_texture_source_;
192 }
193 cached_texture_source_ = nullptr;
194
196 ahb_descriptor.format = android::HardwareBufferFormat::kR8G8B8A8UNormInt;
197 ahb_descriptor.size = size.Max(ISize{1u, 1u});
198 ahb_descriptor.usage =
199 android::HardwareBufferUsageFlags::kFrameBufferAttachment |
200 android::HardwareBufferUsageFlags::kSampledImage;
201
202 if (!ahb_descriptor.IsAllocatable()) {
203 VALIDATION_LOG << "Invalid hardware buffer texture descriptor.";
204 return nullptr;
205 }
206
207 auto ahb = std::make_unique<android::HardwareBuffer>(ahb_descriptor);
208 if (!ahb->IsValid()) {
209 VALIDATION_LOG << "Could not allocate hardware buffer.";
210 return nullptr;
211 }
212
213 auto texture_source =
214 std::make_shared<AHBTextureSourceVK>(context, std::move(ahb), false);
215
216 if (!texture_source->IsValid()) {
217 VALIDATION_LOG << "Could not create trampoline texture source.";
218 return nullptr;
219 }
220 cached_texture_source_ = std::move(texture_source);
221 return cached_texture_source_;
222}
223
224// |SurfaceTextureExternalTexture|
225void SurfaceTextureExternalTextureVKImpeller::DrawFrame(
226 PaintContext& context,
227 const SkRect& bounds,
228 const DlImageSampling sampling) const {
229 context.canvas->DrawImageRect(dl_image_, ToDlRect(bounds), sampling,
230 context.paint);
231}
232
233} // namespace flutter
Instances of external textures peered to android.graphics.SurfaceTexture.
void Attach(int gl_tex_id)
Attaches the given OpenGL texture handle to the surface texture via a bind operation.
const SkM44 & GetCurrentUVTransformation() const
Get the transformation that should be applied to the UV texture coordinates when sampling from this t...
virtual void Detach()
Provides an opportunity for the subclasses to sever the connection between the OpenGL texture resourc...
void Update()
Update the surface texture contents and transformation matrix.
SurfaceTextureExternalTextureVKImpeller(std::shared_ptr< impeller::ContextVK > context, int64_t id, const fml::jni::ScopedJavaGlobalRef< jobject > &surface_texture, const std::shared_ptr< PlatformViewAndroidJNI > &jni_facade)
bool EndCommandBuffer() const
End recording of the current command buffer.
vk::CommandBuffer GetCommandBuffer() const
Retrieve the native command buffer from this object.
const vk::Device & GetDevice() const
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
const std::shared_ptr< QueueVK > & GetGraphicsQueue() const
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Abstract base class that represents a vkImage and an vkImageView.
FlTexture * texture
impeller::Matrix DlMatrix
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
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 mode
static bool SetTextureLayout(const ContextVK &context, const TextureSourceVK *texture, vk::ImageLayout layout, LayoutUpdateMode mode)
const DlRect & ToDlRect(const SkRect &rect)
Definition ref_ptr.h:261
Defines an operations and memory access barrier on a resource.
Definition barrier_vk.h:27
vk::CommandBuffer cmd_buffer
Definition barrier_vk.h:28
vk::AccessFlags src_access
Definition barrier_vk.h:39
vk::PipelineStageFlags dst_stage
Definition barrier_vk.h:44
vk::ImageLayout new_layout
Definition barrier_vk.h:29
vk::PipelineStageFlags src_stage
Definition barrier_vk.h:34
vk::AccessFlags dst_access
Definition barrier_vk.h:49
A 4x4 matrix using column-major storage.
Definition matrix.h:37
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition rect.h:347
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
Definition rect.h:438
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition rect.h:341
constexpr TSize Max(const TSize &o) const
Definition size.h:97
static constexpr TSize MakeWH(Type width, Type height)
Definition size.h:43
A descriptor use to specify hardware buffer allocations.
bool IsAllocatable() const
If hardware buffers can be created using this descriptor. Allocatable descriptors may still cause fai...
Describes an OpenGL texture along with information on how to sample from it.
Definition trampoline.h:62
const uintptr_t id
#define TRACE_EVENT0(category_group, name)
#define VALIDATION_LOG
Definition validation.h:91