Flutter Engine
 
Loading...
Searching...
No Matches
gpu_surface_metal_impeller_unittests.mm
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 <Foundation/Foundation.h>
6#include <QuartzCore/QuartzCore.h>
7
9#include "gtest/gtest.h"
11#include "impeller/entity/mtl/entity_shaders.h"
12#include "impeller/entity/mtl/framebuffer_blend_shaders.h"
13#include "impeller/entity/mtl/modern_shaders.h"
16
17namespace flutter {
18namespace testing {
19
21 public:
23 layer_ = [[CAMetalLayer alloc] init];
24 }
25
27
28 GPUCAMetalLayerHandle GetCAMetalLayer(const DlISize& frame_info) const override {
29 layer_.drawableSize = CGSizeMake(frame_info.width, frame_info.height);
30 return (__bridge GPUCAMetalLayerHandle)(layer_);
31 }
32
33 bool PresentDrawable(GrMTLHandle drawable) const override { return true; }
34
35 GPUMTLTextureInfo GetMTLTexture(const DlISize& frame_info) const override { return {}; }
36
37 bool PresentTexture(GPUMTLTextureInfo texture) const override { return true; }
38
39 bool AllowsDrawingWhenGpuDisabled() const override { return true; }
40
41 void SetDevice() { layer_.device = ::MTLCreateSystemDefaultDevice(); }
42
43 private:
44 CAMetalLayer* layer_ = nil;
45};
46
47static std::shared_ptr<impeller::ContextMTL> CreateImpellerContext() {
48 std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
49 std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_data,
50 impeller_entity_shaders_length),
51 std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_data,
52 impeller_modern_shaders_length),
53 std::make_shared<fml::NonOwnedMapping>(impeller_framebuffer_blend_shaders_data,
54 impeller_framebuffer_blend_shaders_length),
55 };
56 auto sync_switch = std::make_shared<fml::SyncSwitch>(false);
57 return impeller::ContextMTL::Create(impeller::Flags{}, shader_mappings, sync_switch,
58 "Impeller Library");
59}
60
61TEST(GPUSurfaceMetalImpeller, InvalidImpellerContextCreatesCausesSurfaceToBeInvalid) {
62 auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
63 auto surface = std::make_shared<GPUSurfaceMetalImpeller>(delegate.get(), nullptr);
64
65 ASSERT_FALSE(surface->IsValid());
66}
67
68TEST(GPUSurfaceMetalImpeller, CanCreateValidSurface) {
69 auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
70 auto surface = std::make_shared<GPUSurfaceMetalImpeller>(
71 delegate.get(), std::make_shared<impeller::AiksContext>(CreateImpellerContext(), nullptr));
72
73 ASSERT_TRUE(surface->IsValid());
74}
75
76TEST(GPUSurfaceMetalImpeller, AcquireFrameFromCAMetalLayerNullChecksDrawable) {
77 auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
78 std::shared_ptr<Surface> surface = std::make_shared<GPUSurfaceMetalImpeller>(
79 delegate.get(), std::make_shared<impeller::AiksContext>(CreateImpellerContext(), nullptr));
80
81 ASSERT_TRUE(surface->IsValid());
82
83 auto frame = surface->AcquireFrame(DlISize(100, 100));
84 ASSERT_EQ(frame, nullptr);
85}
86
87TEST(GPUSurfaceMetalImpeller, AcquireFrameFromCAMetalLayerDoesNotRetainThis) {
88 auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
89 delegate->SetDevice();
90 std::unique_ptr<Surface> surface = std::make_unique<GPUSurfaceMetalImpeller>(
91 delegate.get(), std::make_shared<impeller::AiksContext>(CreateImpellerContext(), nullptr));
92
93 ASSERT_TRUE(surface->IsValid());
94
95 auto frame = surface->AcquireFrame(DlISize(100, 100));
96 ASSERT_TRUE(frame);
97
98 // Simulate a rasterizer teardown, e.g. due to going to the background.
99 surface.reset();
100
101 ASSERT_TRUE(frame->Submit());
102}
103
104TEST(GPUSurfaceMetalImpeller, ResetHostBufferBasedOnFrameBoundary) {
105 auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
106 delegate->SetDevice();
107
108 auto context = CreateImpellerContext();
109 std::unique_ptr<Surface> surface = std::make_unique<GPUSurfaceMetalImpeller>(
110 delegate.get(), std::make_shared<impeller::AiksContext>(context, nullptr));
111
112 ASSERT_TRUE(surface->IsValid());
113
114 auto& data_host_buffer = surface->GetAiksContext()->GetContentContext().GetTransientsDataBuffer();
115
116 EXPECT_EQ(data_host_buffer.GetStateForTest().current_frame, 0u);
117
118 auto frame = surface->AcquireFrame(DlISize(100, 100));
119 frame->set_submit_info({.frame_boundary = false});
120
121 ASSERT_TRUE(frame->Submit());
122 EXPECT_EQ(data_host_buffer.GetStateForTest().current_frame, 0u);
123
124 frame = surface->AcquireFrame(DlISize(100, 100));
125 frame->set_submit_info({.frame_boundary = true});
126
127 ASSERT_TRUE(frame->Submit());
128 EXPECT_EQ(data_host_buffer.GetStateForTest().current_frame, 1u);
129}
130
131#ifdef IMPELLER_DEBUG
132TEST(GPUSurfaceMetalImpeller, CreatesImpellerCaptureScope) {
133 auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
134 delegate->SetDevice();
135
136 auto context = CreateImpellerContext();
137 auto aiks_context = std::make_shared<impeller::AiksContext>(context, nullptr);
138
139 EXPECT_FALSE(context->GetCaptureManager()->CaptureScopeActive());
140
141 std::unique_ptr<Surface> surface =
142 std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), aiks_context);
143 auto frame_1 = surface->AcquireFrame(DlISize(100, 100));
144 frame_1->set_submit_info({.frame_boundary = false});
145
146 EXPECT_TRUE(context->GetCaptureManager()->CaptureScopeActive());
147
148 std::unique_ptr<Surface> surface_2 =
149 std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), aiks_context);
150 auto frame_2 = surface->AcquireFrame(DlISize(100, 100));
151 frame_2->set_submit_info({.frame_boundary = true});
152
153 EXPECT_TRUE(context->GetCaptureManager()->CaptureScopeActive());
154
155 ASSERT_TRUE(frame_1->Submit());
156 EXPECT_TRUE(context->GetCaptureManager()->CaptureScopeActive());
157 ASSERT_TRUE(frame_2->Submit());
158 EXPECT_FALSE(context->GetCaptureManager()->CaptureScopeActive());
159}
160#endif // IMPELLER_DEBUG
161
162} // namespace testing
163} // namespace flutter
Interface implemented by all platform surfaces that can present a metal backing store to the "screen"...
bool PresentDrawable(GrMTLHandle drawable) const override
Presents the drawable to the "screen". The drawable is obtained from the CAMetalLayer that given by G...
bool AllowsDrawingWhenGpuDisabled() const override
Whether to allow drawing to the surface when the GPU is disabled.
GPUMTLTextureInfo GetMTLTexture(const DlISize &frame_info) const override
Returns the handle to the MTLTexture to render to. This is only called when the specified render targ...
bool PresentTexture(GPUMTLTextureInfo texture) const override
Presents the texture with texture_id to the "screen". texture_id corresponds to a texture that has be...
GPUCAMetalLayerHandle GetCAMetalLayer(const DlISize &frame_info) const override
Returns the handle to the CAMetalLayer to render to. This is only called when the specified render ta...
static std::shared_ptr< ContextMTL > Create(const Flags &flags, const std::vector< std::string > &shader_library_paths, std::shared_ptr< const fml::SyncSwitch > is_gpu_disabled_sync_switch)
VkSurfaceKHR surface
Definition main.cc:65
FlTexture * texture
static std::shared_ptr< impeller::ContextMTL > CreateImpellerContext()
TEST(NativeAssetsManagerTest, NoAvailableAssets)
impeller::ISize32 DlISize
Type height
Definition size.h:29
Type width
Definition size.h:28