Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
android_context_gl_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
12#include "impeller/entity/gles/entity_shaders_gles.h"
13#include "impeller/entity/gles/framebuffer_blend_shaders_gles.h"
14#if !SLIMPELLER
15#include "impeller/entity/gles3/entity_shaders_gles.h"
16#include "impeller/entity/gles3/framebuffer_blend_shaders_gles.h"
17#endif // !SLIMPELLER
18
19namespace flutter {
20
23 public:
24 ReactorWorker() = default;
25
26 // |impeller::ReactorGLES::Worker|
27 ~ReactorWorker() override = default;
28
29 // |impeller::ReactorGLES::Worker|
31 const impeller::ReactorGLES& reactor) const override {
32 impeller::ReaderLock lock(mutex_);
33 auto found = reactions_allowed_.find(std::this_thread::get_id());
34 if (found == reactions_allowed_.end()) {
35 return false;
36 }
37 return found->second;
38 }
39
41 impeller::WriterLock lock(mutex_);
42 reactions_allowed_[std::this_thread::get_id()] = allowed;
43 }
44
45 private:
46 mutable impeller::RWMutex mutex_;
47 std::map<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);
48
50};
51
52static std::shared_ptr<impeller::Context> CreateImpellerContext(
53 const std::shared_ptr<impeller::ReactorGLES::Worker>& worker,
54 bool enable_gpu_tracing,
55 std::shared_ptr<fml::BasicTaskRunner> io_task_runner) {
56 auto proc_table = std::make_unique<impeller::ProcTableGLES>(
58
59 if (!proc_table->IsValid()) {
60 FML_LOG(ERROR) << "Could not create OpenGL proc table.";
61 return nullptr;
62 }
63 std::vector<std::shared_ptr<fml::Mapping>> gles2_shader_mappings = {
64 std::make_shared<fml::NonOwnedMapping>(
65 impeller_entity_shaders_gles_data,
66 impeller_entity_shaders_gles_length),
67 std::make_shared<fml::NonOwnedMapping>(
68 impeller_framebuffer_blend_shaders_gles_data,
69 impeller_framebuffer_blend_shaders_gles_length),
70 };
71
72// To maximally reduce code size, only load the older GLES2 shaders.
73#if !SLIMPELLER
74 bool is_gles3 = proc_table->GetDescription()->GetGlVersion().IsAtLeast(
75 impeller::Version{3, 0, 0});
76
77 std::vector<std::shared_ptr<fml::Mapping>> gles3_shader_mappings = {
78 std::make_shared<fml::NonOwnedMapping>(
79 impeller_entity_shaders_gles3_data,
80 impeller_entity_shaders_gles3_length),
81 std::make_shared<fml::NonOwnedMapping>(
82 impeller_framebuffer_blend_shaders_gles3_data,
83 impeller_framebuffer_blend_shaders_gles3_length),
84 };
85
87 impeller::Flags{}, std::move(proc_table),
88 is_gles3 ? gles3_shader_mappings : gles2_shader_mappings,
89 enable_gpu_tracing, std::move(io_task_runner));
90#else
92 impeller::Flags{}, std::move(proc_table), gles2_shader_mappings,
93 enable_gpu_tracing, std::move(io_task_runner));
94#endif // !SLIMPELLER
95
96 if (!context) {
97 FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context.";
98 return nullptr;
99 }
100
101 if (!context->AddReactorWorker(worker).has_value()) {
102 FML_LOG(ERROR) << "Could not add reactor worker.";
103 return nullptr;
104 }
105 FML_LOG(IMPORTANT) << "Using the Impeller rendering backend (OpenGLES).";
106 return context;
107}
108
110 std::unique_ptr<impeller::egl::Display> display,
111 bool enable_gpu_tracing,
112 std::shared_ptr<fml::BasicTaskRunner> io_task_runner)
114 reactor_worker_(std::shared_ptr<ReactorWorker>(new ReactorWorker())),
115 display_(std::move(display)),
116 io_task_runner_(std::move(io_task_runner)) {
117 if (!display_ || !display_->IsValid()) {
118 FML_LOG(ERROR) << "Could not create context with invalid EGL display.";
119 return;
120 }
121
128
130 std::unique_ptr<impeller::egl::Config> onscreen_config =
131 display_->ChooseConfig(desc);
132
133 if (!onscreen_config) {
135 onscreen_config = display_->ChooseConfig(desc);
136 }
137
138 if (!onscreen_config) {
139 // Fallback for Android emulator.
141 onscreen_config = display_->ChooseConfig(desc);
142 if (onscreen_config) {
143 FML_LOG(INFO) << "Warning: This device doesn't support MSAA for onscreen "
144 "framebuffers. Falling back to a single sample.";
145 } else {
146 FML_LOG(ERROR) << "Could not choose onscreen config.";
147 return;
148 }
149 }
150
152 auto offscreen_config = display_->ChooseConfig(desc);
153 if (!offscreen_config) {
154 FML_LOG(ERROR) << "Could not choose offscreen config.";
155 return;
156 }
157
158 auto onscreen_context = display_->CreateContext(*onscreen_config, nullptr);
159 if (!onscreen_context) {
160 FML_LOG(ERROR) << "Could not create onscreen context.";
161 return;
162 }
163
164 auto offscreen_context =
165 display_->CreateContext(*offscreen_config, onscreen_context.get());
166 if (!offscreen_context) {
167 FML_LOG(ERROR) << "Could not create offscreen context.";
168 return;
169 }
170
171 // Creating the impeller::Context requires a current context, which requires
172 // some surface.
173 auto offscreen_surface =
174 display_->CreatePixelBufferSurface(*offscreen_config, 1u, 1u);
175 if (!offscreen_context->MakeCurrent(*offscreen_surface)) {
176 FML_LOG(ERROR) << "Could not make offscreen context current.";
177 return;
178 }
179
180 auto impeller_context = CreateImpellerContext(
181 reactor_worker_, enable_gpu_tracing, io_task_runner_);
182
183 if (!impeller_context) {
184 FML_LOG(ERROR) << "Could not create Impeller context.";
185 return;
186 }
187
188 if (!offscreen_context->ClearCurrent()) {
189 FML_LOG(ERROR) << "Could not clear offscreen context.";
190 return;
191 }
192 // Setup context listeners.
194 [worker =
195 reactor_worker_](impeller::egl ::Context::LifecycleEvent event) {
196 switch (event) {
198 worker->SetReactionsAllowedOnCurrentThread(true);
199 break;
201 worker->SetReactionsAllowedOnCurrentThread(false);
202 break;
203 }
204 };
205 if (!onscreen_context->AddLifecycleListener(listener).has_value() ||
206 !offscreen_context->AddLifecycleListener(listener).has_value()) {
207 FML_LOG(ERROR) << "Could not add lifecycle listeners";
208 }
209
210 onscreen_config_ = std::move(onscreen_config);
211 offscreen_config_ = std::move(offscreen_config);
212 onscreen_context_ = std::move(onscreen_context);
213 offscreen_context_ = std::move(offscreen_context);
214 SetImpellerContext(impeller_context);
215
216 is_valid_ = true;
217}
218
220
222 return is_valid_;
223}
224
226 if (!offscreen_context_) {
227 return false;
228 }
229
230 return offscreen_context_->ClearCurrent();
231}
232
234 impeller::egl::Surface* offscreen_surface) {
235 if (!offscreen_context_ || !offscreen_surface) {
236 return false;
237 }
238
239 return offscreen_context_->MakeCurrent(*offscreen_surface);
240}
241
242std::unique_ptr<impeller::egl::Surface>
244 return display_->CreatePixelBufferSurface(*offscreen_config_, 1u, 1u);
245}
246
248 impeller::egl::Surface* onscreen_surface) {
249 if (!onscreen_surface || !onscreen_context_) {
250 return false;
251 }
252
253 return onscreen_context_->MakeCurrent(*onscreen_surface);
254}
255
257 if (!onscreen_context_) {
258 return false;
259 }
260
261 return onscreen_context_->ClearCurrent();
262}
263
264std::unique_ptr<impeller::egl::Surface>
266 return display_->CreateWindowSurface(*onscreen_config_, window);
267}
268
272
273} // namespace flutter
static std::shared_ptr< impeller::ContextMTL > CreateImpellerContext()
bool CanReactorReactOnCurrentThreadNow(const impeller::ReactorGLES &reactor) const override
Determines the ability of the worker to service a reaction on the current thread. The OpenGL context ...
std::unique_ptr< impeller::egl::Surface > CreateOnscreenSurface(EGLNativeWindowType window)
AndroidContextGLImpeller(std::unique_ptr< impeller::egl::Display > display, bool enable_gpu_tracing, std::shared_ptr< fml::BasicTaskRunner > io_task_runner)
bool OnscreenContextMakeCurrent(impeller::egl::Surface *onscreen_surface)
AndroidRenderingAPI RenderingApi() const override
bool ResourceContextMakeCurrent(impeller::egl::Surface *offscreen_surface)
std::unique_ptr< impeller::egl::Surface > CreateOffscreenSurface()
Holds state that is shared across Android surfaces.
void SetImpellerContext(const std::shared_ptr< impeller::Context > &impeller_context)
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, std::shared_ptr< fml::BasicTaskRunner > io_task_runner=nullptr)
A delegate implemented by a thread on which an OpenGL context is current. There may be multiple worke...
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
std::function< void(LifecycleEvent)> LifecycleListener
Definition context.h:75
An instance of an EGL surface. There is no ability to create surfaces directly. Instead,...
Definition surface.h:18
GLFWwindow * window
Definition main.cc:60
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
EGLDisplay display_
std::function< void *(const char *)> CreateProcAddressResolver()
Creates a proc address resolver that resolves function pointers to EGL and OpenGL (ES) procs.
Definition egl.cc:12
Definition ref_ptr.h:261
std::shared_ptr< ReactorGLES > reactor
std::shared_ptr< ContextGLES > context
#define IPLR_GUARDED_BY(x)