Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
embedder_test_backingstore_producer.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
5#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h"
6
7#include "flutter/fml/logging.h"
8#include "flutter/shell/platform/embedder/pixel_formats.h"
20
21#include <cstdlib>
22#include <memory>
23#include <utility>
24
25#ifdef SHELL_ENABLE_VULKAN
27#endif // SHELL_ENABLE_VULKAN
28
29#ifdef SHELL_ENABLE_METAL
32#endif
33
34// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
35// NOLINTBEGIN(bugprone-unchecked-optional-access)
36
37namespace flutter {
38namespace testing {
39
43 FlutterSoftwarePixelFormat software_pixfmt)
44 : context_(std::move(context)),
45 type_(type),
46 software_pixfmt_(software_pixfmt)
47#ifdef SHELL_ENABLE_METAL
48 ,
49 test_metal_context_(std::make_unique<TestMetalContext>())
50#endif
51#ifdef SHELL_ENABLE_VULKAN
52 ,
53 test_vulkan_context_(nullptr)
54#endif
55{
57 software_pixfmt_ != kFlutterSoftwarePixelFormatNative32) {
58 FML_LOG(ERROR) << "Expected pixel format to be the default "
59 "(kFlutterSoftwarePixelFormatNative32) when"
60 "backing store producer should produce deprecated v1 "
61 "software backing "
62 "stores.";
63 std::abort();
64 };
65}
66
68
70 const FlutterBackingStoreConfig* config,
71 FlutterBackingStore* renderer_out) {
72 switch (type_) {
74 return CreateSoftware(config, renderer_out);
76 return CreateSoftware2(config, renderer_out);
77#ifdef SHELL_ENABLE_GL
79 return CreateTexture(config, renderer_out);
81 return CreateFramebuffer(config, renderer_out);
82#endif
83#ifdef SHELL_ENABLE_METAL
85 return CreateMTLTexture(config, renderer_out);
86#endif
87#ifdef SHELL_ENABLE_VULKAN
89 return CreateVulkanImage(config, renderer_out);
90#endif
91 default:
92 return false;
93 }
94}
95
96bool EmbedderTestBackingStoreProducer::CreateFramebuffer(
97 const FlutterBackingStoreConfig* config,
98 FlutterBackingStore* backing_store_out) {
99#ifdef SHELL_ENABLE_GL
100 const auto image_info =
102
103 auto surface =
104 SkSurfaces::RenderTarget(context_.get(), // context
105 skgpu::Budgeted::kNo, // budgeted
106 image_info, // image info
107 1, // sample count
108 kBottomLeft_GrSurfaceOrigin, // surface origin
109 nullptr, // surface properties
110 false // mipmaps
111 );
112
113 if (!surface) {
114 FML_LOG(ERROR) << "Could not create render target for compositor layer.";
115 return false;
116 }
117
119 surface.get(), SkSurfaces::BackendHandleAccess::kDiscardWrite);
120
121 if (!render_target.isValid()) {
122 FML_LOG(ERROR) << "Backend render target was invalid.";
123 return false;
124 }
125
126 GrGLFramebufferInfo framebuffer_info = {};
128 &framebuffer_info)) {
129 FML_LOG(ERROR) << "Could not access backend framebuffer info.";
130 return false;
131 }
132
133 backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
134 backing_store_out->user_data = surface.get();
136 backing_store_out->open_gl.framebuffer.target = framebuffer_info.fFormat;
137 backing_store_out->open_gl.framebuffer.name = framebuffer_info.fFBOID;
138 // The balancing unref is in the destruction callback.
139 surface->ref();
140 backing_store_out->open_gl.framebuffer.user_data = surface.get();
141 backing_store_out->open_gl.framebuffer.destruction_callback =
142 [](void* user_data) { reinterpret_cast<SkSurface*>(user_data)->unref(); };
143
144 return true;
145#else
146 return false;
147#endif
148}
149
150bool EmbedderTestBackingStoreProducer::CreateTexture(
151 const FlutterBackingStoreConfig* config,
152 FlutterBackingStore* backing_store_out) {
153#ifdef SHELL_ENABLE_GL
154 const auto image_info =
156
157 auto surface =
158 SkSurfaces::RenderTarget(context_.get(), // context
159 skgpu::Budgeted::kNo, // budgeted
160 image_info, // image info
161 1, // sample count
162 kBottomLeft_GrSurfaceOrigin, // surface origin
163 nullptr, // surface properties
164 false // mipmaps
165 );
166
167 if (!surface) {
168 FML_LOG(ERROR) << "Could not create render target for compositor layer.";
169 return false;
170 }
171
173 surface.get(), SkSurfaces::BackendHandleAccess::kDiscardWrite);
174
175 if (!render_texture.isValid()) {
176 FML_LOG(ERROR) << "Backend render texture was invalid.";
177 return false;
178 }
179
180 GrGLTextureInfo texture_info = {};
181 if (!GrBackendTextures::GetGLTextureInfo(render_texture, &texture_info)) {
182 FML_LOG(ERROR) << "Could not access backend texture info.";
183 return false;
184 }
185
186 backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
187 backing_store_out->user_data = surface.get();
188 backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeTexture;
189 backing_store_out->open_gl.texture.target = texture_info.fTarget;
190 backing_store_out->open_gl.texture.name = texture_info.fID;
191 backing_store_out->open_gl.texture.format = texture_info.fFormat;
192 // The balancing unref is in the destruction callback.
193 surface->ref();
194 backing_store_out->open_gl.texture.user_data = surface.get();
195 backing_store_out->open_gl.texture.destruction_callback =
196 [](void* user_data) { reinterpret_cast<SkSurface*>(user_data)->unref(); };
197
198 return true;
199#else
200 return false;
201#endif
202}
203
204bool EmbedderTestBackingStoreProducer::CreateSoftware(
205 const FlutterBackingStoreConfig* config,
206 FlutterBackingStore* backing_store_out) {
209
210 if (!surface) {
212 << "Could not create the render target for compositor layer.";
213 return false;
214 }
215
216 SkPixmap pixmap;
217 if (!surface->peekPixels(&pixmap)) {
218 FML_LOG(ERROR) << "Could not peek pixels of pixmap.";
219 return false;
220 }
221
222 backing_store_out->type = kFlutterBackingStoreTypeSoftware;
223 backing_store_out->user_data = surface.get();
224 backing_store_out->software.allocation = pixmap.addr();
225 backing_store_out->software.row_bytes = pixmap.rowBytes();
226 backing_store_out->software.height = pixmap.height();
227 // The balancing unref is in the destruction callback.
228 surface->ref();
229 backing_store_out->software.user_data = surface.get();
230 backing_store_out->software.destruction_callback = [](void* user_data) {
231 reinterpret_cast<SkSurface*>(user_data)->unref();
232 };
233
234 return true;
235}
236
237bool EmbedderTestBackingStoreProducer::CreateSoftware2(
238 const FlutterBackingStoreConfig* config,
239 FlutterBackingStore* backing_store_out) {
240 const auto color_info = getSkColorInfo(software_pixfmt_);
241 if (!color_info) {
242 return false;
243 }
244
246 SkISize::Make(config->size.width, config->size.height), *color_info));
247 if (!surface) {
249 << "Could not create the render target for compositor layer.";
250 return false;
251 }
252
253 SkPixmap pixmap;
254 if (!surface->peekPixels(&pixmap)) {
255 FML_LOG(ERROR) << "Could not peek pixels of pixmap.";
256 return false;
257 }
258
259 backing_store_out->type = kFlutterBackingStoreTypeSoftware2;
260 backing_store_out->user_data = surface.get();
261 backing_store_out->software2.struct_size =
263 backing_store_out->software2.user_data = surface.get();
264 backing_store_out->software2.allocation = pixmap.writable_addr();
265 backing_store_out->software2.row_bytes = pixmap.rowBytes();
266 backing_store_out->software2.height = pixmap.height();
267 // The balancing unref is in the destruction callback.
268 surface->ref();
269 backing_store_out->software2.user_data = surface.get();
270 backing_store_out->software2.destruction_callback = [](void* user_data) {
271 reinterpret_cast<SkSurface*>(user_data)->unref();
272 };
273 backing_store_out->software2.pixel_format = software_pixfmt_;
274
275 return true;
276}
277
278bool EmbedderTestBackingStoreProducer::CreateMTLTexture(
279 const FlutterBackingStoreConfig* config,
280 FlutterBackingStore* backing_store_out) {
281#ifdef SHELL_ENABLE_METAL
282 // TODO(gw280): Use SkSurfaces::RenderTarget instead of generating our
283 // own MTLTexture and wrapping it.
284 auto surface_size = SkISize::Make(config->size.width, config->size.height);
285 auto texture_info = test_metal_context_->CreateMetalTexture(surface_size);
286
287 GrMtlTextureInfo skia_texture_info;
288 skia_texture_info.fTexture.reset(SkCFSafeRetain(texture_info.texture));
289 GrBackendTexture backend_texture =
290 GrBackendTextures::MakeMtl(surface_size.width(), surface_size.height(),
291 skgpu::Mipmapped::kNo, skia_texture_info);
292
294 context_.get(), backend_texture, kTopLeft_GrSurfaceOrigin, 1,
295 kBGRA_8888_SkColorType, nullptr, nullptr);
296
297 if (!surface) {
298 FML_LOG(ERROR) << "Could not create Skia surface from a Metal texture.";
299 return false;
300 }
301
302 backing_store_out->type = kFlutterBackingStoreTypeMetal;
303 backing_store_out->user_data = surface.get();
304 backing_store_out->metal.texture.texture = texture_info.texture;
305 // The balancing unref is in the destruction callback.
306 surface->ref();
307 backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore);
308 backing_store_out->metal.texture.user_data = surface.get();
309 backing_store_out->metal.texture.destruction_callback = [](void* user_data) {
310 reinterpret_cast<SkSurface*>(user_data)->unref();
311 };
312
313 return true;
314#else
315 return false;
316#endif
317}
318
319bool EmbedderTestBackingStoreProducer::CreateVulkanImage(
320 const FlutterBackingStoreConfig* config,
321 FlutterBackingStore* backing_store_out) {
322#ifdef SHELL_ENABLE_VULKAN
323 if (!test_vulkan_context_) {
324 test_vulkan_context_ = fml::MakeRefCounted<TestVulkanContext>();
325 }
326
327 auto surface_size = SkISize::Make(config->size.width, config->size.height);
328 TestVulkanImage* test_image = new TestVulkanImage(
329 std::move(test_vulkan_context_->CreateImage(surface_size).value()));
330
331 GrVkImageInfo image_info = {
332 .fImage = test_image->GetImage(),
333 .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
334 .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
335 .fFormat = VK_FORMAT_R8G8B8A8_UNORM,
336 .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
340 .fSampleCount = 1,
341 .fLevelCount = 1,
342 };
343 auto backend_texture = GrBackendTextures::MakeVk(
344 surface_size.width(), surface_size.height(), image_info);
345
346 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
347
348 SkSurfaces::TextureReleaseProc release_vktexture = [](void* user_data) {
349 delete reinterpret_cast<TestVulkanImage*>(user_data);
350 };
351
353 context_.get(), // context
354 backend_texture, // back-end texture
355 kTopLeft_GrSurfaceOrigin, // surface origin
356 1, // sample count
357 kRGBA_8888_SkColorType, // color type
358 SkColorSpace::MakeSRGB(), // color space
359 &surface_properties, // surface properties
360 release_vktexture, // texture release proc
361 test_image // release context
362 );
363
364 if (!surface) {
365 FML_LOG(ERROR) << "Could not create Skia surface from Vulkan image.";
366 return false;
367 }
368 backing_store_out->type = kFlutterBackingStoreTypeVulkan;
369
371 image->image = reinterpret_cast<uint64_t>(image_info.fImage);
373 backing_store_out->vulkan.image = image;
374
375 // Collect all allocated resources in the destruction_callback.
376 {
377 UserData* user_data = new UserData();
378 user_data->image = image;
379 user_data->surface = surface.get();
380
381 backing_store_out->user_data = user_data;
382 backing_store_out->vulkan.user_data = user_data;
383 backing_store_out->vulkan.destruction_callback = [](void* user_data) {
384 UserData* d = reinterpret_cast<UserData*>(user_data);
385 d->surface->unref();
386 delete d->image;
387 delete d;
388 };
389
390 // The balancing unref is in the destruction callback.
391 surface->ref();
392 }
393
394 return true;
395#else
396 return false;
397#endif
398}
399
400} // namespace testing
401} // namespace flutter
402
403// NOLINTEND(bugprone-unchecked-optional-access)
@ kBottomLeft_GrSurfaceOrigin
Definition GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kUnknown_SkPixelGeometry
static void test_image(const sk_sp< SkSpecialImage > &img, skiatest::Reporter *reporter, GrRecordingContext *rContext, bool isGPUBacked)
static sk_sp< SkColorSpace > MakeSRGB()
size_t rowBytes() const
Definition SkPixmap.h:145
void * writable_addr() const
Definition SkPixmap.h:483
const void * addr() const
Definition SkPixmap.h:153
int height() const
Definition SkPixmap.h:166
EmbedderTestBackingStoreProducer(sk_sp< GrDirectContext > context, RenderTargetType type, FlutterSoftwarePixelFormat software_pixfmt=kFlutterSoftwarePixelFormatNative32)
bool Create(const FlutterBackingStoreConfig *config, FlutterBackingStore *renderer_out)
T * get() const
Definition SkRefCnt.h:303
FlutterSoftwarePixelFormat
Definition embedder.h:333
@ kFlutterSoftwarePixelFormatNative32
Definition embedder.h:361
@ kFlutterOpenGLTargetTypeFramebuffer
Definition embedder.h:304
@ kFlutterOpenGLTargetTypeTexture
Definition embedder.h:301
@ kFlutterBackingStoreTypeSoftware2
Definition embedder.h:1749
@ kFlutterBackingStoreTypeMetal
Specifies a Metal backing store. This is backed by a Metal texture.
Definition embedder.h:1744
@ kFlutterBackingStoreTypeVulkan
Specifies a Vulkan backing store. This is backed by a Vulkan VkImage.
Definition embedder.h:1746
@ kFlutterBackingStoreTypeSoftware
Specified an software allocation for Flutter to render into using the CPU.
Definition embedder.h:1742
@ kFlutterBackingStoreTypeOpenGL
Definition embedder.h:1740
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
#define FML_LOG(severity)
Definition logging.h:82
SK_API bool GetGLFramebufferInfo(const GrBackendRenderTarget &, GrGLFramebufferInfo *)
SK_API GrBackendTexture MakeMtl(int width, int height, skgpu::Mipmapped, const GrMtlTextureInfo &mtlInfo, std::string_view label={})
SK_API GrBackendTexture MakeVk(int width, int height, const GrVkImageInfo &, std::string_view label={})
SK_API bool GetGLTextureInfo(const GrBackendTexture &, GrGLTextureInfo *)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API GrBackendTexture GetBackendTexture(SkSurface *, BackendHandleAccess)
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API GrBackendRenderTarget GetBackendRenderTarget(SkSurface *, BackendHandleAccess)
void(*)(ReleaseContext) TextureReleaseProc
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
Definition ref_ptr.h:256
std::optional< SkColorInfo > getSkColorInfo(FlutterSoftwarePixelFormat pixfmt)
FlutterSize size
The size of the render target the engine expects to render into.
Definition embedder.h:1782
FlutterVulkanBackingStore vulkan
Definition embedder.h:1774
FlutterMetalBackingStore metal
Definition embedder.h:1772
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:1760
FlutterOpenGLBackingStore open_gl
The description of the OpenGL backing store.
Definition embedder.h:1766
FlutterSoftwareBackingStore software
The description of the software backing store.
Definition embedder.h:1768
FlutterSoftwareBackingStore2 software2
The description of the software backing store.
Definition embedder.h:1770
size_t struct_size
The size of this struct. Must be sizeof(FlutterMetalBackingStore).
Definition embedder.h:1658
FlutterMetalTexture texture
Definition embedder.h:1663
FlutterMetalTextureHandle texture
Definition embedder.h:659
VoidCallback destruction_callback
Definition embedder.h:666
FlutterOpenGLTexture texture
A texture for Flutter to render into.
Definition embedder.h:1611
FlutterOpenGLTargetType type
Definition embedder.h:1608
FlutterOpenGLFramebuffer framebuffer
Definition embedder.h:1614
uint32_t name
The name of the framebuffer.
Definition embedder.h:394
VoidCallback destruction_callback
Definition embedder.h:401
void * user_data
User data to be returned on the invocation of the destruction callback.
Definition embedder.h:397
uint32_t name
The name of the texture.
Definition embedder.h:369
VoidCallback destruction_callback
Definition embedder.h:376
void * user_data
User data to be returned on the invocation of the destruction callback.
Definition embedder.h:373
uint32_t format
The texture format (example GL_RGBA8).
Definition embedder.h:371
double height
Definition embedder.h:423
double width
Definition embedder.h:422
VoidCallback destruction_callback
Definition embedder.h:1650
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1641
size_t height
The number of rows in the allocation.
Definition embedder.h:1643
FlutterSoftwarePixelFormat pixel_format
Definition embedder.h:1653
VoidCallback destruction_callback
Definition embedder.h:1632
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1623
size_t height
The number of rows in the allocation.
Definition embedder.h:1625
VoidCallback destruction_callback
Definition embedder.h:1683
const FlutterVulkanImage * image
Definition embedder.h:1676
GrGLenum fFormat
Definition GrGLTypes.h:183
GrGLenum fTarget
Definition GrGLTypes.h:181
VkImage fImage
Definition GrVkTypes.h:26
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
#define ERROR(message)
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_IMAGE_TILING_OPTIMAL
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_SAMPLED_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
@ VK_FORMAT_R8G8B8A8_UNORM