Flutter Engine
The Flutter Engine
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
5#include "flutter/shell/platform/android/android_context_gl_impeller.h"
6
7#include "flutter/impeller/renderer/backend/gles/context_gles.h"
8#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h"
9#include "flutter/impeller/renderer/backend/gles/reactor_gles.h"
10#include "flutter/impeller/toolkit/egl/context.h"
11#include "flutter/impeller/toolkit/egl/surface.h"
12#include "impeller/entity/gles/entity_shaders_gles.h"
13#include "impeller/entity/gles/framebuffer_blend_shaders_gles.h"
14
15#if IMPELLER_ENABLE_3D
16// This include was turned to an error since it breaks GN.
17#include "impeller/scene/shaders/gles/scene_shaders_gles.h" // nogncheck
18#endif // IMPELLER_ENABLE_3D
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 auto proc_table = std::make_unique<impeller::ProcTableGLES>(
57
58 if (!proc_table->IsValid()) {
59 FML_LOG(ERROR) << "Could not create OpenGL proc table.";
60 return nullptr;
61 }
62
63 std::vector<std::shared_ptr<fml::Mapping>> 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#if IMPELLER_ENABLE_3D
71 std::make_shared<fml::NonOwnedMapping>(
72 impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length),
73#endif // IMPELLER_ENABLE_3D
74 };
75
76 auto context = impeller::ContextGLES::Create(
77 std::move(proc_table), shader_mappings, enable_gpu_tracing);
78 if (!context) {
79 FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context.";
80 return nullptr;
81 }
82
83 if (!context->AddReactorWorker(worker).has_value()) {
84 FML_LOG(ERROR) << "Could not add reactor worker.";
85 return nullptr;
86 }
87 FML_LOG(IMPORTANT) << "Using the Impeller rendering backend (OpenGLES).";
88 return context;
89}
90
92 std::unique_ptr<impeller::egl::Display> display,
93 bool enable_gpu_tracing)
95 reactor_worker_(std::shared_ptr<ReactorWorker>(new ReactorWorker())),
96 display_(std::move(display)) {
97 if (!display_ || !display_->IsValid()) {
98 FML_DLOG(ERROR) << "Could not create context with invalid EGL display.";
99 return;
100 }
101
104 desc.color_format = impeller::egl::ColorFormat::kRGBA8888;
105 desc.depth_bits = impeller::egl::DepthBits::kZero;
106 desc.stencil_bits = impeller::egl::StencilBits::kEight;
107 desc.samples = impeller::egl::Samples::kFour;
108
109 desc.surface_type = impeller::egl::SurfaceType::kWindow;
110 std::unique_ptr<impeller::egl::Config> onscreen_config =
111 display_->ChooseConfig(desc);
112 if (!onscreen_config) {
113 // Fallback for Android emulator.
114 desc.samples = impeller::egl::Samples::kOne;
115 onscreen_config = display_->ChooseConfig(desc);
116 if (onscreen_config) {
117 FML_LOG(INFO) << "Warning: This device doesn't support MSAA for onscreen "
118 "framebuffers. Falling back to a single sample.";
119 } else {
120 FML_DLOG(ERROR) << "Could not choose onscreen config.";
121 return;
122 }
123 }
124
125 desc.surface_type = impeller::egl::SurfaceType::kPBuffer;
126 auto offscreen_config = display_->ChooseConfig(desc);
127 if (!offscreen_config) {
128 FML_DLOG(ERROR) << "Could not choose offscreen config.";
129 return;
130 }
131
132 auto onscreen_context = display_->CreateContext(*onscreen_config, nullptr);
133 if (!onscreen_context) {
134 FML_DLOG(ERROR) << "Could not create onscreen context.";
135 return;
136 }
137
138 auto offscreen_context =
139 display_->CreateContext(*offscreen_config, onscreen_context.get());
140 if (!offscreen_context) {
141 FML_DLOG(ERROR) << "Could not create offscreen context.";
142 return;
143 }
144
145 // Creating the impeller::Context requires a current context, which requires
146 // some surface.
147 auto offscreen_surface =
148 display_->CreatePixelBufferSurface(*offscreen_config, 1u, 1u);
149 if (!offscreen_context->MakeCurrent(*offscreen_surface)) {
150 FML_DLOG(ERROR) << "Could not make offscreen context current.";
151 return;
152 }
153
154 auto impeller_context =
155 CreateImpellerContext(reactor_worker_, enable_gpu_tracing);
156
157 if (!impeller_context) {
158 FML_DLOG(ERROR) << "Could not create Impeller context.";
159 return;
160 }
161
162 if (!offscreen_context->ClearCurrent()) {
163 FML_DLOG(ERROR) << "Could not clear offscreen context.";
164 return;
165 }
166 // Setup context listeners.
168 [worker =
169 reactor_worker_](impeller::egl ::Context::LifecycleEvent event) {
170 switch (event) {
172 worker->SetReactionsAllowedOnCurrentThread(true);
173 break;
175 worker->SetReactionsAllowedOnCurrentThread(false);
176 break;
177 }
178 };
179 if (!onscreen_context->AddLifecycleListener(listener).has_value() ||
180 !offscreen_context->AddLifecycleListener(listener).has_value()) {
181 FML_DLOG(ERROR) << "Could not add lifecycle listeners";
182 }
183
184 onscreen_config_ = std::move(onscreen_config);
185 offscreen_config_ = std::move(offscreen_config);
186 onscreen_context_ = std::move(onscreen_context);
187 offscreen_context_ = std::move(offscreen_context);
188 SetImpellerContext(impeller_context);
189
190 is_valid_ = true;
191}
192
194
196 return is_valid_;
197}
198
200 if (!offscreen_context_) {
201 return false;
202 }
203
204 return offscreen_context_->ClearCurrent();
205}
206
208 impeller::egl::Surface* offscreen_surface) {
209 if (!offscreen_context_ || !offscreen_surface) {
210 return false;
211 }
212
213 return offscreen_context_->MakeCurrent(*offscreen_surface);
214}
215
216std::unique_ptr<impeller::egl::Surface>
218 return display_->CreatePixelBufferSurface(*offscreen_config_, 1u, 1u);
219}
220
222 impeller::egl::Surface* onscreen_surface) {
223 if (!onscreen_surface || !onscreen_context_) {
224 return false;
225 }
226
227 return onscreen_context_->MakeCurrent(*onscreen_surface);
228}
229
231 if (!onscreen_context_) {
232 return false;
233 }
234
235 return onscreen_context_->ClearCurrent();
236}
237
238std::unique_ptr<impeller::egl::Surface>
240 return display_->CreateWindowSurface(*onscreen_config_, window);
241}
242
243} // namespace flutter
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)
bool OnscreenContextMakeCurrent(impeller::egl::Surface *onscreen_surface)
bool ResourceContextMakeCurrent(impeller::egl::Surface *offscreen_surface)
std::unique_ptr< impeller::egl::Surface > CreateOffscreenSurface()
AndroidContextGLImpeller(std::unique_ptr< impeller::egl::Display > display, bool enable_gpu_tracing)
Holds state that is shared across Android surfaces.
void SetImpellerContext(const std::shared_ptr< impeller::Context > &context)
static std::shared_ptr< ContextGLES > Create(std::unique_ptr< ProcTableGLES > gl, const std::vector< std::shared_ptr< fml::Mapping > > &shader_libraries, bool enable_gpu_tracing)
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:38
GLFWwindow * window
Definition main.cc:45
FlKeyEvent * event
#define FML_DLOG(severity)
Definition logging.h:102
#define FML_LOG(severity)
Definition logging.h:82
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
EGLDisplay display_
AndroidRenderingAPI
Definition settings.h:26
static std::shared_ptr< impeller::Context > CreateImpellerContext(const std::shared_ptr< impeller::ReactorGLES::Worker > &worker, bool enable_gpu_tracing)
std::function< void *(const char *)> CreateProcAddressResolver()
Definition egl.cc:12
Definition ref_ptr.h:256
#define ERROR(message)
#define IPLR_GUARDED_BY(x)