Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
playground_impl_gles.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
7#define IMPELLER_PLAYGROUND_SUPPORTS_ANGLE FML_OS_MACOSX
8
9#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
10#include <dlfcn.h>
11#endif
12
13#define GLFW_INCLUDE_NONE
14#include "third_party/glfw/include/GLFW/glfw3.h"
15
17#include "impeller/entity/gles/entity_shaders_gles.h"
18#include "impeller/entity/gles/framebuffer_blend_shaders_gles.h"
19#include "impeller/entity/gles/modern_shaders_gles.h"
20#include "impeller/entity/gles3/entity_shaders_gles.h"
21#include "impeller/entity/gles3/framebuffer_blend_shaders_gles.h"
22#include "impeller/entity/gles3/modern_shaders_gles.h"
23#include "impeller/fixtures/gles/fixtures_shaders_gles.h"
24#include "impeller/fixtures/gles/modern_fixtures_shaders_gles.h"
25#include "impeller/fixtures/gles3/fixtures_shaders_gles.h"
26#include "impeller/fixtures/gles3/modern_fixtures_shaders_gles.h"
27#include "impeller/playground/imgui/gles/imgui_shaders_gles.h"
28#include "impeller/playground/imgui/gles3/imgui_shaders_gles.h"
31
32namespace impeller {
33
35 public:
36 ReactorWorker() = default;
37
38 // |ReactorGLES::Worker|
40 const ReactorGLES& reactor) const override {
41 ReaderLock lock(mutex_);
42 auto found = reactions_allowed_.find(std::this_thread::get_id());
43 if (found == reactions_allowed_.end()) {
44 return false;
45 }
46 return found->second;
47 }
48
50 WriterLock lock(mutex_);
51 reactions_allowed_[std::this_thread::get_id()] = allowed;
52 }
53
54 private:
55 mutable RWMutex mutex_;
56 std::map<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);
57
58 ReactorWorker(const ReactorWorker&) = delete;
59
60 ReactorWorker& operator=(const ReactorWorker&) = delete;
61};
62
63void PlaygroundImplGLES::DestroyWindowHandle(WindowHandle handle) {
64 if (!handle) {
65 return;
66 }
67 ::glfwDestroyWindow(reinterpret_cast<GLFWwindow*>(handle));
68}
69
70static std::vector<std::shared_ptr<fml::Mapping>>
72
74 : PlaygroundImpl(switches),
75 handle_(nullptr, &DestroyWindowHandle),
76 worker_(std::shared_ptr<ReactorWorker>(new ReactorWorker())),
77 use_angle_(switches.use_angle) {
78 if (use_angle_) {
79#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
80 angle_glesv2_ = dlopen("libGLESv2.dylib", RTLD_LAZY);
81#endif
82 FML_CHECK(angle_glesv2_ != nullptr);
83 }
84
85 ::glfwDefaultWindowHints();
86
87#if FML_OS_MACOSX
88 FML_CHECK(use_angle_) << "Must use Angle on macOS for OpenGL ES.";
89 ::glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
90#endif // FML_OS_MACOSX
91#if FML_OS_LINUX
92 // Use EGL even on X11 then the client can select the GLES implementation
93 // by defining __EGL_VENDOR_LIBRARY_FILENAMES
94 ::glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
95#endif
96 ::glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
97 ::glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
98 ::glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
99 ::glfwWindowHint(GLFW_RED_BITS, 8);
100 ::glfwWindowHint(GLFW_GREEN_BITS, 8);
101 ::glfwWindowHint(GLFW_BLUE_BITS, 8);
102 ::glfwWindowHint(GLFW_ALPHA_BITS, 8);
103 ::glfwWindowHint(GLFW_DEPTH_BITS, 32); // 32 bit depth buffer
104 ::glfwWindowHint(GLFW_STENCIL_BITS, 8); // 8 bit stencil buffer
105 ::glfwWindowHint(GLFW_SAMPLES, 4); // 4xMSAA
106
107 ::glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
108#ifndef NDEBUG
109 ::glfwWindowHint(GLFW_CONTEXT_DEBUG, GLFW_TRUE);
110#endif
111
112 auto window = ::glfwCreateWindow(1, 1, "Test", nullptr, nullptr);
113
114 ::glfwMakeContextCurrent(window);
115 worker_->SetReactionsAllowedOnCurrentThread(true);
116
117 handle_.reset(window);
118
119 auto gl = std::make_unique<ProcTableGLES>(CreateGLProcAddressResolver());
120 if (!gl->IsValid()) {
121 FML_LOG(ERROR) << "Proc table when creating a playground was invalid.";
122 return;
123 }
124
125 if (gl->GetDescription()->HasDebugExtension()) {
126 gl->DebugMessageCallbackKHR(
127 +[](GLenum /* source */, GLenum message_type, GLuint /* message_id */,
128 GLenum /* severity */, GLsizei /* length */, const GLchar* message,
129 const void* /* user_param */) {
130 switch (message_type) {
131 case GL_DEBUG_TYPE_ERROR_KHR:
132 FML_LOG(ERROR) << "GL Error: " << message;
133 return;
134 default:
135 return;
136 }
137 },
138 nullptr);
139
140#ifndef NDEBUG
141 gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
142#endif
143 }
144 bool is_gles3 = gl->GetDescription()->GetGlVersion().IsAtLeast(Version(3));
145 auto context_gles =
146 ContextGLES::Create(switches_.flags, std::move(gl),
147 ShaderLibraryMappingsForPlayground(is_gles3), true);
148 if (!context_gles) {
149 FML_LOG(ERROR) << "Could not create context.";
150 return;
151 }
152
153 auto worker_id = context_gles->AddReactorWorker(worker_);
154 if (!worker_id.has_value()) {
155 FML_LOG(ERROR) << "Could not add reactor worker.";
156 return;
157 }
158 context_ = std::move(context_gles);
159}
160
162
163static std::vector<std::shared_ptr<fml::Mapping>>
165 if (is_gles3) {
166 return {
167 std::make_shared<fml::NonOwnedMapping>(
168 impeller_entity_shaders_gles3_data,
169 impeller_entity_shaders_gles3_length),
170 std::make_shared<fml::NonOwnedMapping>(
171 impeller_modern_shaders_gles3_data,
172 impeller_modern_shaders_gles3_length),
173 std::make_shared<fml::NonOwnedMapping>(
174 impeller_framebuffer_blend_shaders_gles3_data,
175 impeller_framebuffer_blend_shaders_gles3_length),
176 std::make_shared<fml::NonOwnedMapping>(
177 impeller_fixtures_shaders_gles3_data,
178 impeller_fixtures_shaders_gles3_length),
179 std::make_shared<fml::NonOwnedMapping>(
180 impeller_modern_fixtures_shaders_gles3_data,
181 impeller_modern_fixtures_shaders_gles3_length),
182 std::make_shared<fml::NonOwnedMapping>(
183 impeller_imgui_shaders_gles3_data,
184 impeller_imgui_shaders_gles3_length),
185 };
186 }
187 return {
188 std::make_shared<fml::NonOwnedMapping>(
189 impeller_entity_shaders_gles_data,
190 impeller_entity_shaders_gles_length),
191 std::make_shared<fml::NonOwnedMapping>(
192 impeller_modern_shaders_gles_data,
193 impeller_modern_shaders_gles_length),
194 std::make_shared<fml::NonOwnedMapping>(
195 impeller_framebuffer_blend_shaders_gles_data,
196 impeller_framebuffer_blend_shaders_gles_length),
197 std::make_shared<fml::NonOwnedMapping>(
198 impeller_fixtures_shaders_gles_data,
199 impeller_fixtures_shaders_gles_length),
200 std::make_shared<fml::NonOwnedMapping>(
201 impeller_modern_fixtures_shaders_gles_data,
202 impeller_modern_fixtures_shaders_gles_length),
203 std::make_shared<fml::NonOwnedMapping>(
204 impeller_imgui_shaders_gles_data, impeller_imgui_shaders_gles_length),
205 };
206}
207
208// |PlaygroundImpl|
209std::shared_ptr<Context> PlaygroundImplGLES::GetContext() const {
210 return context_;
211}
212
213// |PlaygroundImpl|
215PlaygroundImplGLES::CreateGLProcAddressResolver() const {
216 return use_angle_ ? [](const char* name) -> void* {
217 void* symbol = nullptr;
218#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
219 void* angle_glesv2 = dlopen("libGLESv2.dylib", RTLD_LAZY);
220 symbol = dlsym(angle_glesv2, name);
221#endif
222 FML_CHECK(symbol);
223 return symbol;
224 }
225 : [](const char* name) -> void* {
226 return reinterpret_cast<void*>(::glfwGetProcAddress(name));
227 };
228}
229
230// |PlaygroundImpl|
231PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() const {
232 return handle_.get();
233}
234
235// |PlaygroundImpl|
236std::unique_ptr<Surface> PlaygroundImplGLES::AcquireSurfaceFrame(
237 std::shared_ptr<Context> context) {
238 auto window = reinterpret_cast<GLFWwindow*>(GetWindowHandle());
239 int width = 0;
240 int height = 0;
241 ::glfwGetFramebufferSize(window, &width, &height);
242 if (width <= 0 || height <= 0) {
243 return nullptr;
244 }
245 SurfaceGLES::SwapCallback swap_callback = [window]() -> bool {
246 ::glfwSwapBuffers(window);
247 return true;
248 };
250 swap_callback, //
251 0u, //
254 );
255}
256
258 const std::shared_ptr<Capabilities>& capabilities) {
259 return fml::Status(
261 "PlaygroundImplGLES doesn't support setting the capabilities.");
262}
263
264RuntimeStageBackend PlaygroundImplGLES::GetRuntimeStageBackend() const {
265 const auto gl =
266 std::make_unique<ProcTableGLES>(CreateGLProcAddressResolver());
267 if (!gl->IsValid()) {
268 FML_LOG(ERROR) << "Proc table was invalid. Assuming baseline OpenGL ES";
270 }
271 bool is_gles3 = gl->GetDescription()->GetGlVersion().IsAtLeast(Version(3));
272 return is_gles3 ? RuntimeStageBackend::kOpenGLES3
274}
275
276} // 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)
std::function< void *(const char *proc_name)> GLProcAddressResolver
Definition playground.h:108
bool CanReactorReactOnCurrentThreadNow(const ReactorGLES &reactor) const override
Determines the ability of the worker to service a reaction on the current thread. The OpenGL context ...
PlaygroundImplGLES(PlaygroundSwitches switches)
fml::Status SetCapabilities(const std::shared_ptr< Capabilities > &capabilities) override
const PlaygroundSwitches switches_
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.
static std::unique_ptr< Surface > WrapFBO(const std::shared_ptr< Context > &context, SwapCallback swap_callback, GLuint fbo, PixelFormat color_format, ISize fbo_size)
std::function< bool(void)> SwapCallback
GLFWwindow * window
Definition main.cc:60
const char * message
#define GLFW_TRUE
#define GLFW_FALSE
#define FML_LOG(severity)
Definition logging.h:101
#define FML_CHECK(condition)
Definition logging.h:104
const char * name
Definition fuchsia.cc:50
static std::vector< std::shared_ptr< fml::Mapping > > ShaderLibraryMappingsForPlayground()
Definition ref_ptr.h:261
fuchsia::ui::composition::ParentViewportWatcherHandle handle_
std::shared_ptr< ReactorGLES > reactor
std::shared_ptr< ContextGLES > context
int32_t height
int32_t width
static constexpr TSize MakeWH(Type width, Type height)
Definition size.h:43
#define IPLR_GUARDED_BY(x)