Flutter Impeller
blit_command_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 "flutter/testing/testing.h" // IWYU pragma: keep
6 #include "gtest/gtest.h"
10 #include "impeller/renderer/backend/gles/test/mock_gles.h"
12 
13 namespace impeller {
14 namespace testing {
15 
16 using ::testing::_;
17 using ::testing::Return;
18 
19 class TestReactorGLES : public ReactorGLES {
20  public:
22  : ReactorGLES(std::make_unique<ProcTableGLES>(kMockResolverGLES)) {}
23 
24  ~TestReactorGLES() = default;
25 };
26 
27 class MockWorker final : public ReactorGLES::Worker {
28  public:
29  MockWorker() = default;
30 
31  // |ReactorGLES::Worker|
33  const ReactorGLES& reactor) const override {
34  return true;
35  }
36 };
37 
38 namespace {
39 
40 std::shared_ptr<TextureGLES> CreateTexture(
41  const std::shared_ptr<ReactorGLES>& reactor,
42  PixelFormat format) {
43  TextureDescriptor tex_desc;
44  tex_desc.format = format;
45  tex_desc.size = {10, 10};
46  tex_desc.usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
47  auto texture = std::make_shared<TextureGLES>(reactor, tex_desc);
48  // Avoids the flip which would crash.
49  texture->SetCoordinateSystem(TextureCoordinateSystem::kUploadFromHost);
50  return texture;
51 }
52 
53 std::shared_ptr<DeviceBufferGLES> CreateBuffer(
54  const std::shared_ptr<ReactorGLES>& reactor) {
55  DeviceBufferDescriptor buffer_desc;
56  buffer_desc.size = 10 * 10 * 4;
57  buffer_desc.storage_mode = StorageMode::kHostVisible;
58  auto allocation = std::make_shared<Allocation>();
59  FML_CHECK(allocation->Truncate(Bytes(buffer_desc.size)));
60  auto buffer =
61  std::make_shared<DeviceBufferGLES>(buffer_desc, reactor, allocation);
62  return buffer;
63 }
64 
65 BlitCopyBufferToTextureCommandGLES CreateCopyBufferToTextureCommand(
66  const std::shared_ptr<DeviceBufferGLES>& source,
67  const std::shared_ptr<TextureGLES>& dest) {
68  BlitCopyBufferToTextureCommandGLES command;
69  command.source = DeviceBuffer::AsBufferView(source);
70  command.destination = dest;
71  command.destination_region =
72  IRect::MakeSize(dest->GetTextureDescriptor().size);
73  command.mip_level = 0;
74  command.slice = 0;
75  command.label = "TestBlit";
76  return command;
77 }
78 
79 BlitCopyTextureToBufferCommandGLES CreateCopyTextureToBufferCommand(
80  const std::shared_ptr<TextureGLES>& source,
81  const std::shared_ptr<DeviceBufferGLES>& dest) {
82  BlitCopyTextureToBufferCommandGLES command;
83  command.source = source;
84  command.destination = dest;
85  command.source_region = IRect::MakeSize(source->GetTextureDescriptor().size);
86  command.label = "TestBlit";
87  return command;
88 }
89 
90 } // namespace
91 
92 TEST(BlitCommandGLESTest, BlitCopyBufferToTextureCommandGLESRGBA) {
93  auto mock_gles_impl = std::make_unique<MockGLESImpl>();
94  auto& mock_gles_impl_ref = *mock_gles_impl;
95 
96  std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
97  auto reactor = std::make_shared<TestReactorGLES>();
98  auto worker = std::make_shared<MockWorker>();
99  reactor->AddWorker(worker);
100 
101  // Dest texture with RGBA format.
102  std::shared_ptr<TextureGLES> dest_texture =
104  std::shared_ptr<DeviceBufferGLES> source_buffer = CreateBuffer(reactor);
106  CreateCopyBufferToTextureCommand(source_buffer, dest_texture);
107 
108  // Expect gl TexSubImage2D with GL_RGBA.
109  EXPECT_CALL(mock_gles_impl_ref,
110  TexSubImage2D(GL_TEXTURE_2D, _, _, _, _, _, GL_RGBA, _, _))
111  .Times(1);
112 
113  EXPECT_TRUE(command.Encode(*reactor));
114 }
115 
116 TEST(BlitCommandGLESTest, BlitCopyBufferToTextureCommandGLESBGRA) {
117  auto mock_gles_impl = std::make_unique<MockGLESImpl>();
118  auto& mock_gles_impl_ref = *mock_gles_impl;
119 
120  // Mock gl to support BGRA.
121  std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(
122  std::move(mock_gles_impl),
123  std::vector<const char*>{"GL_EXT_texture_format_BGRA8888"});
124  auto reactor = std::make_shared<TestReactorGLES>();
125  auto worker = std::make_shared<MockWorker>();
126  reactor->AddWorker(worker);
127 
128  // Dest texture with BGRA format.
129  std::shared_ptr<TextureGLES> dest_texture =
131  std::shared_ptr<DeviceBufferGLES> source_buffer = CreateBuffer(reactor);
133  CreateCopyBufferToTextureCommand(source_buffer, dest_texture);
134 
135  // Expect gl TexSubImage2D with GL_BGRA_EXT.
136  EXPECT_CALL(mock_gles_impl_ref,
137  TexSubImage2D(GL_TEXTURE_2D, _, _, _, _, _, GL_BGRA_EXT, _, _))
138  .Times(1);
139 
140  EXPECT_TRUE(command.Encode(*reactor));
141 }
142 
143 // This test makes sure we bind to GL_FRAMEBUFFER so that it's compatible for
144 // OpenGLES 2 and OpenGLES 3.
145 TEST(BlitCommandGLESTest, BlitCopyTextureToBufferCommandGLESBindsFramebuffer) {
146  auto mock_gles_impl = std::make_unique<MockGLESImpl>();
147  auto& mock_gles_impl_ref = *mock_gles_impl;
148 
149  EXPECT_CALL(mock_gles_impl_ref, GenFramebuffers(1, _))
150  .WillOnce(::testing::SetArgPointee<1>(3));
151  EXPECT_CALL(mock_gles_impl_ref, GenTextures(1, _))
152  .WillOnce(::testing::SetArgPointee<1>(1));
153  EXPECT_CALL(mock_gles_impl_ref, BindFramebuffer(GL_FRAMEBUFFER, 3)).Times(1);
154  EXPECT_CALL(mock_gles_impl_ref, CheckFramebufferStatus(GL_FRAMEBUFFER))
155  .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE));
156  EXPECT_CALL(mock_gles_impl_ref, ReadPixels(_, _, _, _, _, _, _)).Times(1);
157  EXPECT_CALL(mock_gles_impl_ref, BindFramebuffer(GL_FRAMEBUFFER, 0)).Times(1);
158 
159  std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
160  auto reactor = std::make_shared<TestReactorGLES>();
161  auto worker = std::make_shared<MockWorker>();
162  reactor->AddWorker(worker);
163 
164  std::shared_ptr<TextureGLES> source_texture =
166  std::shared_ptr<DeviceBufferGLES> dest_buffer = CreateBuffer(reactor);
167 
168  ASSERT_TRUE(reactor->React());
169 
171  CreateCopyTextureToBufferCommand(source_texture, dest_buffer);
172 
173  EXPECT_TRUE(command.Encode(*reactor));
174 
175  source_texture.reset();
176  dest_buffer.reset();
177 
178  ASSERT_TRUE(reactor->React());
179 }
180 
181 TEST(BlitCommandGLESTest, BlitCopyTextureToBufferCommandGLESRGBA) {
182  auto mock_gles_impl = std::make_unique<MockGLESImpl>();
183  auto& mock_gles_impl_ref = *mock_gles_impl;
184 
185  std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
186  auto reactor = std::make_shared<TestReactorGLES>();
187  auto worker = std::make_shared<MockWorker>();
188  reactor->AddWorker(worker);
189 
190  // Source texture with RGBA format.
191  std::shared_ptr<TextureGLES> source_texture =
193  std::shared_ptr<DeviceBufferGLES> dest_buffer = CreateBuffer(reactor);
195  CreateCopyTextureToBufferCommand(source_texture, dest_buffer);
196 
197  EXPECT_CALL(mock_gles_impl_ref, CheckFramebufferStatus(_))
198  .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE));
199  // Expect gl ReadPixels with GL_RGBA.
200  EXPECT_CALL(mock_gles_impl_ref, ReadPixels(_, _, _, _, GL_RGBA, _, _))
201  .Times(1);
202 
203  EXPECT_TRUE(command.Encode(*reactor));
204 }
205 
206 TEST(BlitCommandGLESTest, BlitCopyTextureToBufferCommandGLESBGRA) {
207  auto mock_gles_impl = std::make_unique<MockGLESImpl>();
208  auto& mock_gles_impl_ref = *mock_gles_impl;
209 
210  // Mock gl to support BGRA.
211  std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(
212  std::move(mock_gles_impl),
213  std::vector<const char*>{"GL_EXT_texture_format_BGRA8888"});
214  auto reactor = std::make_shared<TestReactorGLES>();
215  auto worker = std::make_shared<MockWorker>();
216  reactor->AddWorker(worker);
217 
218  // Source texture with BGRA format.
219  std::shared_ptr<TextureGLES> source_texture =
221  std::shared_ptr<DeviceBufferGLES> dest_buffer = CreateBuffer(reactor);
223  CreateCopyTextureToBufferCommand(source_texture, dest_buffer);
224 
225  EXPECT_CALL(mock_gles_impl_ref, CheckFramebufferStatus(_))
226  .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE));
227  // Expect gl ReadPixels with GL_BGRA_EXT.
228  EXPECT_CALL(mock_gles_impl_ref, ReadPixels(_, _, _, _, GL_BGRA_EXT, _, _))
229  .Times(1);
230 
231  EXPECT_TRUE(command.Encode(*reactor));
232 }
233 
234 TEST(BlitCommandGLESTest,
235  BlitCopyTextureToBufferCommandGLESUnsupportedPixelFormats) {
236  auto mock_gles_impl = std::make_unique<MockGLESImpl>();
237  auto& mock_gles_impl_ref = *mock_gles_impl;
238 
239  std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
240  auto reactor = std::make_shared<TestReactorGLES>();
241  auto worker = std::make_shared<MockWorker>();
242  reactor->AddWorker(worker);
243 
244  std::shared_ptr<DeviceBufferGLES> dest_buffer = CreateBuffer(reactor);
245 
246  std::shared_ptr<TextureGLES> source_texture_D32FloatS8Uint =
248  BlitCopyTextureToBufferCommandGLES command_for_D32FloatS8Uint =
249  CreateCopyTextureToBufferCommand(source_texture_D32FloatS8Uint,
250  dest_buffer);
251 
252  std::shared_ptr<TextureGLES> source_texture_R8G8UNormInt =
254  BlitCopyTextureToBufferCommandGLES command_for_R8G8UNormInt =
255  CreateCopyTextureToBufferCommand(source_texture_R8G8UNormInt,
256  dest_buffer);
257 
258  EXPECT_CALL(mock_gles_impl_ref, CheckFramebufferStatus(_)).Times(0);
259 
260  // GL does not support texture with an unsupported pixel format.
261  EXPECT_FALSE(command_for_D32FloatS8Uint.Encode(*reactor));
262 
263  // GL does not support texture with another unsupported pixel format.
264  EXPECT_FALSE(command_for_R8G8UNormInt.Encode(*reactor));
265 }
266 
267 } // namespace testing
268 } // namespace impeller
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
A delegate implemented by a thread on which an OpenGL context is current. There may be multiple worke...
Definition: reactor_gles.h:69
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
Definition: reactor_gles.h:57
bool CanReactorReactOnCurrentThreadNow(const ReactorGLES &reactor) const override
Determines the ability of the worker to service a reaction on the current thread. The OpenGL context ...
TEST(AllocationSizeTest, CanCreateTypedAllocations)
AllocationSize< 1u > Bytes
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
Mask< TextureUsage > TextureUsageMask
Definition: formats.h:311
std::shared_ptr< Texture > CreateTexture(const TextureDescriptor &texture_descriptor, const std::vector< uint8_t > &data, const std::shared_ptr< impeller::Context > &context, std::string_view debug_label)
Definition: texture_util.cc:11
Definition: comparable.h:93
bool Encode(const ReactorGLES &reactor) const override
bool Encode(const ReactorGLES &reactor) const override
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...