Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
tester_context_gles_factory.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#define FML_USED_ON_EMBEDDER
6
8
9#include <EGL/egl.h>
10#include <EGL/eglext.h>
11#include <EGL/eglplatform.h>
12#include <cstring>
13#include <memory>
14#include <vector>
15
17#include "flutter/fml/logging.h"
18#include "flutter/fml/mapping.h"
23#include "impeller/entity/gles3/entity_shaders_gles.h"
24#include "impeller/entity/gles3/framebuffer_blend_shaders_gles.h"
25#include "impeller/entity/gles3/modern_shaders_gles.h"
28#include "third_party/abseil-cpp/absl/status/statusor.h"
29
30namespace flutter {
31
32namespace {
33
34class TesterGLESDelegate : public GPUSurfaceGLDelegate {
35 public:
36 static absl::StatusOr<TesterGLESDelegate> Create() {
37 EGLDisplay display = flutter::testing::CreateSwangleDisplay();
38 if (display == EGL_NO_DISPLAY) {
39 return absl::InternalError("Could not create EGL display.");
40 }
41
42 if (::eglInitialize(display, nullptr, nullptr) != EGL_TRUE) {
43 return absl::InternalError("Could not initialize EGL display.");
44 }
45
46 EGLint num_config = 0;
47 const EGLint attribute_list[] = {EGL_RED_SIZE,
48 8,
49 EGL_GREEN_SIZE,
50 8,
51 EGL_BLUE_SIZE,
52 8,
53 EGL_ALPHA_SIZE,
54 8,
55 EGL_DEPTH_SIZE,
56 24,
57 EGL_STENCIL_SIZE,
58 8,
59 EGL_SURFACE_TYPE,
60 EGL_PBUFFER_BIT,
61 EGL_CONFORMANT,
62 EGL_OPENGL_ES2_BIT,
63 EGL_RENDERABLE_TYPE,
64 EGL_OPENGL_ES2_BIT,
65 EGL_NONE};
66
67 EGLConfig config = nullptr;
68 if (::eglChooseConfig(display, attribute_list, &config, 1, &num_config) !=
69 EGL_TRUE ||
70 num_config != 1) {
71 return absl::InternalError("Could not choose EGL config.");
72 }
73
74 const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
75 EGL_NONE};
76
77 EGLContext context =
78 ::eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
79 if (context == EGL_NO_CONTEXT) {
80 return absl::InternalError("Could not create EGL context.");
81 }
82
83 // Create a pbuffer surface to make current
84 const EGLint surface_attributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
85 EGLSurface surface =
86 ::eglCreatePbufferSurface(display, config, surface_attributes);
87 if (surface == EGL_NO_SURFACE) {
88 ::eglDestroyContext(display, context);
89 return absl::InternalError("Could not create EGL pbuffer surface.");
90 }
91
92 return TesterGLESDelegate(display, context, surface);
93 }
94
95 TesterGLESDelegate(TesterGLESDelegate&& other)
96 : display_(other.display_),
97 context_(other.context_),
98 surface_(other.surface_) {
99 other.display_ = EGL_NO_DISPLAY;
100 other.context_ = EGL_NO_CONTEXT;
101 other.surface_ = EGL_NO_SURFACE;
102 }
103
104 virtual ~TesterGLESDelegate() {
105 if (display_ != EGL_NO_DISPLAY) {
106 if (surface_ != EGL_NO_SURFACE) {
107 ::eglDestroySurface(display_, surface_);
108 }
109 if (context_ != EGL_NO_CONTEXT) {
110 ::eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
111 EGL_NO_CONTEXT);
112 ::eglDestroyContext(display_, context_);
113 }
114 ::eglTerminate(display_);
115 }
116 }
117
118 bool MakeContextCurrent() {
119 return ::eglMakeCurrent(display_, surface_, surface_, context_) == EGL_TRUE;
120 }
121
122 // |GPUSurfaceGLDelegate|
123 std::unique_ptr<GLContextResult> GLContextMakeCurrent() override {
124 return std::make_unique<GLContextDefaultResult>(MakeContextCurrent());
125 }
126
127 // |GPUSurfaceGLDelegate|
128 bool GLContextClearCurrent() override {
129 return ::eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
130 EGL_NO_CONTEXT) == EGL_TRUE;
131 }
132
133 // |GPUSurfaceGLDelegate|
134 bool GLContextPresent(const GLPresentInfo& present_info) override {
135 return true;
136 }
137
138 // |GPUSurfaceGLDelegate|
139 GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override {
140 return GLFBOInfo{0, std::nullopt};
141 }
142
143 // |GPUSurfaceGLDelegate|
144 SurfaceFrame::FramebufferInfo GLContextFramebufferInfo() const override {
145 return SurfaceFrame::FramebufferInfo{.supports_readback = true};
146 }
147
148 private:
149 TesterGLESDelegate(EGLDisplay display, EGLContext context, EGLSurface surface)
150 : display_(display), context_(context), surface_(surface) {}
151
152 EGLDisplay display_ = EGL_NO_DISPLAY;
153 EGLContext context_ = EGL_NO_CONTEXT;
154 EGLSurface surface_ = EGL_NO_SURFACE;
155
156 FML_DISALLOW_COPY_AND_ASSIGN(TesterGLESDelegate);
157};
158
159class TesterGLESWorker : public impeller::ReactorGLES::Worker {
160 public:
161 explicit TesterGLESWorker(TesterGLESDelegate* delegate)
162 : delegate_(delegate) {}
163
164 bool CanReactorReactOnCurrentThreadNow(
165 const impeller::ReactorGLES& reactor) const override {
166 return delegate_->MakeContextCurrent();
167 }
168
169 private:
170 TesterGLESDelegate* delegate_;
171};
172
173class TesterContextGLES : public TesterContext {
174 public:
175 TesterContextGLES() = default;
176
177 ~TesterContextGLES() override {
178 if (context_) {
179 std::shared_ptr<impeller::Context> raw_context = context_;
180 raw_context->Shutdown();
181 }
182 }
183
184 bool Initialize() {
185 auto delegate_status = TesterGLESDelegate::Create();
186 if (!delegate_status.ok()) {
187 FML_LOG(ERROR) << delegate_status.status().message();
188 return false;
189 }
190 delegate_ = std::make_unique<TesterGLESDelegate>(
191 std::move(delegate_status.value()));
192
193 if (!delegate_->MakeContextCurrent()) {
194 FML_LOG(ERROR) << "Could not make GLES context current.";
195 return false;
196 }
197
198 auto resolver = [](const char* name) -> void* {
199 return reinterpret_cast<void*>(eglGetProcAddress(name));
200 };
201
202 auto gl = std::make_unique<impeller::ProcTableGLES>(resolver);
203 if (!gl->IsValid()) {
204 FML_LOG(ERROR) << "Could not create valid proc table.";
205 return false;
206 }
207
208 std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
209 std::make_shared<fml::NonOwnedMapping>(
210 impeller_entity_shaders_gles3_data,
211 impeller_entity_shaders_gles3_length),
212 std::make_shared<fml::NonOwnedMapping>(
213 impeller_modern_shaders_gles3_data,
214 impeller_modern_shaders_gles3_length),
215 std::make_shared<fml::NonOwnedMapping>(
216 impeller_framebuffer_blend_shaders_gles3_data,
217 impeller_framebuffer_blend_shaders_gles3_length),
218 };
219 context_ = impeller::ContextGLES::Create(impeller::Flags{}, std::move(gl),
220 shader_mappings, false);
221
222 if (!context_ ||
223 !static_cast<std::shared_ptr<impeller::Context>>(context_)->IsValid()) {
224 FML_LOG(ERROR) << "Could not create OpenGLES context.";
225 return false;
226 }
227
228 worker_ = std::make_shared<TesterGLESWorker>(delegate_.get());
229 context_->AddReactorWorker(worker_);
230
231 return true;
232 }
233
234 // |TesterContext|
235 std::shared_ptr<impeller::Context> GetImpellerContext() const override {
236 return context_;
237 }
238
239 // |TesterContext|
240 std::unique_ptr<Surface> CreateRenderingSurface() override {
241 auto surface = std::make_unique<GPUSurfaceGLImpeller>(
242 delegate_.get(), context_, /*render_to_surface=*/true);
243 if (!surface->IsValid()) {
244 return nullptr;
245 }
246 return surface;
247 }
248
249 private:
250 std::unique_ptr<TesterGLESDelegate> delegate_;
251 std::shared_ptr<TesterGLESWorker> worker_;
252 std::shared_ptr<impeller::ContextGLES> context_;
253};
254
255} // namespace
256
257std::unique_ptr<TesterContext> TesterContextGLESFactory::Create() {
259 auto context = std::make_unique<TesterContextGLES>();
260 if (!context->Initialize()) {
261 FML_LOG(ERROR) << "Unable to create TesterContextGLESFactory";
262 return nullptr;
263 }
264 return context;
265}
266
267} // namespace flutter
static std::unique_ptr< TesterContext > Create()
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)
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.
MockDelegate delegate_
VkSurfaceKHR surface
Definition main.cc:65
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
EGLDisplay display_
EGLSurface surface_
EGLDisplay CreateSwangleDisplay()
Creates an EGLDisplay using ANGLE with the Vulkan backend and SwiftShader as the device type.
void SetupSwiftshaderOnce(bool use_swiftshader)
Find and setup the installable client driver for a locally built SwiftShader at known paths....
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27