Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
command_buffer_gles_unittests.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 <atomic>
6#include <memory>
7#include <vector>
8
10#include "flutter/testing/testing.h" // IWYU pragma: keep
11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
21
22namespace impeller {
23namespace testing {
24namespace {
25
26using ::testing::_;
27using ::testing::NiceMock;
28
29class ToggleWorker final : public ReactorGLES::Worker {
30 public:
31 explicit ToggleWorker(bool allowed) : allowed_(allowed) {}
32
33 bool CanReactorReactOnCurrentThreadNow(
34 const ReactorGLES& reactor) const override {
35 return allowed_.load();
36 }
37
38 void SetAllowed(bool allowed) { allowed_.store(allowed); }
39
40 private:
41 std::atomic<bool> allowed_;
42};
43
44std::shared_ptr<ContextGLES> CreateFakeGLESContext() {
45 auto gl = std::make_unique<ProcTableGLES>(kMockResolverGLES);
46 return ContextGLES::Create(Flags{}, std::move(gl),
47 std::vector<std::shared_ptr<fml::Mapping>>{},
48 /*enable_gpu_tracing=*/false);
49}
50
51} // namespace
52
54 SubmitWithoutCurrentContextIsAcceptedAndCompletesAfterReaction) {
55 auto mock_gles = MockGLES::Init();
56 auto context = CreateFakeGLESContext();
57 auto context_base = std::static_pointer_cast<Context>(context);
58 auto worker = std::make_shared<ToggleWorker>(false);
59 context->AddReactorWorker(worker);
60
61 auto command_buffer = context_base->CreateCommandBuffer();
62 ASSERT_TRUE(command_buffer);
63
64 bool callback_called = false;
66 auto status = context_base->GetCommandQueue()->Submit(
68 callback_called = true;
69 callback_status = status;
70 });
71
72 EXPECT_TRUE(status.ok());
73 EXPECT_FALSE(callback_called);
74
75 worker->SetAllowed(true);
76 EXPECT_TRUE(context->GetReactor()->React());
77 EXPECT_TRUE(callback_called);
78 EXPECT_EQ(callback_status, CommandBuffer::Status::kCompleted);
79}
80
81TEST(CommandBufferGLES, SubmitWithoutCallbackIsAcceptedWithoutCurrentContext) {
82 auto mock_gles = MockGLES::Init();
83 auto context = CreateFakeGLESContext();
84 auto context_base = std::static_pointer_cast<Context>(context);
85 auto worker = std::make_shared<ToggleWorker>(false);
86 context->AddReactorWorker(worker);
87
88 auto command_buffer = context_base->CreateCommandBuffer();
89 ASSERT_TRUE(command_buffer);
90
91 EXPECT_TRUE(context_base->GetCommandQueue()->Submit({command_buffer}).ok());
92}
93
94TEST(CommandBufferGLES, DeferredSubmitCallbackErrorsIfReactorIsDestroyed) {
95 bool callback_called = false;
97
98 {
99 auto mock_gles = MockGLES::Init();
100 auto context = CreateFakeGLESContext();
101 auto context_base = std::static_pointer_cast<Context>(context);
102 auto worker = std::make_shared<ToggleWorker>(false);
103 context->AddReactorWorker(worker);
104
105 auto command_buffer = context_base->CreateCommandBuffer();
106 ASSERT_TRUE(command_buffer);
107 auto status = context_base->GetCommandQueue()->Submit(
109 callback_called = true;
110 callback_status = status;
111 });
112
113 EXPECT_TRUE(status.ok());
114 EXPECT_FALSE(callback_called);
115 }
116
117 EXPECT_TRUE(callback_called);
118 EXPECT_EQ(callback_status, CommandBuffer::Status::kError);
119}
120
121TEST(CommandBufferGLES, DeferredSubmitCompletesAfterPreviouslyQueuedWork) {
122 auto mock_gles = MockGLES::Init();
123 auto context = CreateFakeGLESContext();
124 auto context_base = std::static_pointer_cast<Context>(context);
125 auto worker = std::make_shared<ToggleWorker>(false);
126 context->AddReactorWorker(worker);
127
128 std::vector<int> order;
129 ASSERT_TRUE(context->GetReactor()->AddOperation(
130 [&](const ReactorGLES& reactor) { order.push_back(1); },
131 /*defer=*/true));
132
133 auto command_buffer = context_base->CreateCommandBuffer();
134 ASSERT_TRUE(command_buffer);
135 auto status = context_base->GetCommandQueue()->Submit(
137 [&](CommandBuffer::Status status) { order.push_back(2); });
138
139 EXPECT_TRUE(status.ok());
140 EXPECT_TRUE(order.empty());
141
142 worker->SetAllowed(true);
143 EXPECT_TRUE(context->GetReactor()->React());
144 EXPECT_THAT(order, ::testing::ElementsAre(1, 2));
145}
146
147TEST(CommandBufferGLES, LaterCurrentSubmitDrainsPreviouslyDeferredWork) {
148 auto mock_gles = MockGLES::Init();
149 auto context = CreateFakeGLESContext();
150 auto context_base = std::static_pointer_cast<Context>(context);
151 auto worker = std::make_shared<ToggleWorker>(false);
152 context->AddReactorWorker(worker);
153
154 std::vector<int> order;
155 ASSERT_TRUE(context->GetReactor()->AddOperation(
156 [&](const ReactorGLES& reactor) { order.push_back(1); },
157 /*defer=*/true));
158
159 auto deferred_command_buffer = context_base->CreateCommandBuffer();
160 ASSERT_TRUE(deferred_command_buffer);
161 EXPECT_TRUE(
162 context_base->GetCommandQueue()->Submit({deferred_command_buffer}).ok());
163 EXPECT_TRUE(order.empty());
164
165 worker->SetAllowed(true);
166 auto current_command_buffer = context_base->CreateCommandBuffer();
167 ASSERT_TRUE(current_command_buffer);
168 EXPECT_TRUE(
169 context_base->GetCommandQueue()
170 ->Submit({current_command_buffer},
171 [&](CommandBuffer::Status status) { order.push_back(2); })
172 .ok());
173 EXPECT_THAT(order, ::testing::ElementsAre(1, 2));
174}
175
176TEST(CommandBufferGLES, BufferToTextureBlitCanBeSubmittedBeforeContextCurrent) {
177 auto mock_gles_impl = std::make_unique<NiceMock<MockGLESImpl>>();
178 auto& mock_gles_impl_ref = *mock_gles_impl;
179 auto mock_gles = MockGLES::Init(std::move(mock_gles_impl));
180 auto context = CreateFakeGLESContext();
181 auto context_base = std::static_pointer_cast<Context>(context);
182 auto worker = std::make_shared<ToggleWorker>(false);
183 context->AddReactorWorker(worker);
184
185 constexpr GLuint kTextureHandle = 1234;
186 bool texture_generated = false;
187 bool texture_uploaded = false;
188 EXPECT_CALL(mock_gles_impl_ref, GenTextures(1, _))
189 .WillOnce([&](GLsizei size, GLuint* textures) {
190 texture_generated = true;
191 textures[0] = kTextureHandle;
192 });
193 EXPECT_CALL(mock_gles_impl_ref, BindTexture(GL_TEXTURE_2D, kTextureHandle))
194 .Times(::testing::AtLeast(1));
195 EXPECT_CALL(mock_gles_impl_ref,
196 TexImage2D(GL_TEXTURE_2D, 0, _, 2, 2, 0, _, _, nullptr))
197 .Times(1);
198 EXPECT_CALL(mock_gles_impl_ref,
199 TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, _, _, _))
200 .WillOnce([&](GLenum target, GLint level, GLint xoffset, GLint yoffset,
201 GLsizei width, GLsizei height, GLenum format, GLenum type,
202 const void* pixels) { texture_uploaded = true; });
203
204 TextureDescriptor texture_descriptor;
205 texture_descriptor.size = {2, 2};
206 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
207 auto texture = context_base->GetResourceAllocator()->CreateTexture(
208 texture_descriptor, /*threadsafe=*/true);
209 ASSERT_TRUE(texture);
210
211 const uint8_t pixels[16] = {};
212 auto buffer =
213 context_base->GetResourceAllocator()->CreateBufferWithCopy(pixels, 16);
214 ASSERT_TRUE(buffer);
215
216 auto command_buffer = context_base->CreateCommandBuffer();
217 ASSERT_TRUE(command_buffer);
218 auto blit_pass = command_buffer->CreateBlitPass();
219 ASSERT_TRUE(blit_pass);
220
221 EXPECT_TRUE(blit_pass->AddCopy(BufferView(buffer, Range(0, 16)), texture,
222 IRect::MakeXYWH(0, 0, 2, 2),
223 "Deferred texture overwrite"));
224 EXPECT_TRUE(blit_pass->EncodeCommands());
225 EXPECT_TRUE(context_base->GetCommandQueue()->Submit({command_buffer}).ok());
226 EXPECT_FALSE(texture_generated);
227 EXPECT_FALSE(texture_uploaded);
228
229 worker->SetAllowed(true);
230 EXPECT_TRUE(context->GetReactor()->React());
231 EXPECT_TRUE(texture_generated);
232 EXPECT_TRUE(texture_uploaded);
233}
234
235} // namespace testing
236} // namespace impeller
static std::shared_ptr< ContextGLES > Create(const Flags &flags, std::unique_ptr< ProcTableGLES > gl, const std::vector< std::shared_ptr< fml::Mapping > > &shader_libraries, bool enable_gpu_tracing)
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
static std::shared_ptr< MockGLES > Init(std::unique_ptr< MockGLESImpl > impl, const std::optional< std::vector< const char * > > &extensions=std::nullopt, const char *version_string="OpenGL ES 3.0")
Definition mock_gles.cc:417
uint32_t uint32_t * format
uint32_t * target
FlTexture * texture
TEST(FrameTimingsRecorderTest, RecordVsync)
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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
const ProcTableGLES::Resolver kMockResolverGLES
Definition mock_gles.cc:459
std::shared_ptr< ReactorGLES > reactor
std::shared_ptr< ContextGLES > context
std::shared_ptr< CommandBuffer > command_buffer
impeller::ShaderType type
int32_t height
int32_t width
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...