7 #define IMPELLER_PLAYGROUND_SUPPORTS_ANGLE FML_OS_MACOSX
9 #if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
13 #define GLFW_INCLUDE_NONE
14 #include "third_party/glfw/include/GLFW/glfw3.h"
16 #include "flutter/fml/build_config.h"
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"
42 auto found = reactions_allowed_.find(std::this_thread::get_id());
43 if (found == reactions_allowed_.end()) {
51 reactions_allowed_[std::this_thread::get_id()] = allowed;
55 mutable RWMutex mutex_;
56 std::map<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);
63 void PlaygroundImplGLES::DestroyWindowHandle(WindowHandle handle) {
67 ::glfwDestroyWindow(
reinterpret_cast<GLFWwindow*
>(handle));
72 handle_(nullptr, &DestroyWindowHandle),
74 use_angle_(switches.use_angle) {
76 #if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
77 angle_glesv2_ = dlopen(
"libGLESv2.dylib", RTLD_LAZY);
79 FML_CHECK(angle_glesv2_ !=
nullptr);
82 ::glfwDefaultWindowHints();
85 FML_CHECK(use_angle_) <<
"Must use Angle on macOS for OpenGL ES.";
86 ::glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
91 ::glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
93 ::glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
94 ::glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
95 ::glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
96 ::glfwWindowHint(GLFW_RED_BITS, 8);
97 ::glfwWindowHint(GLFW_GREEN_BITS, 8);
98 ::glfwWindowHint(GLFW_BLUE_BITS, 8);
99 ::glfwWindowHint(GLFW_ALPHA_BITS, 8);
100 ::glfwWindowHint(GLFW_DEPTH_BITS, 32);
101 ::glfwWindowHint(GLFW_STENCIL_BITS, 8);
102 ::glfwWindowHint(GLFW_SAMPLES, 4);
104 ::glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
106 ::glfwWindowHint(GLFW_CONTEXT_DEBUG, GLFW_TRUE);
109 auto window = ::glfwCreateWindow(1, 1,
"Test",
nullptr,
nullptr);
111 ::glfwMakeContextCurrent(window);
112 worker_->SetReactionsAllowedOnCurrentThread(
true);
114 handle_.reset(window);
119 static std::vector<std::shared_ptr<fml::Mapping>>
123 std::make_shared<fml::NonOwnedMapping>(
124 impeller_entity_shaders_gles3_data,
125 impeller_entity_shaders_gles3_length),
126 std::make_shared<fml::NonOwnedMapping>(
127 impeller_modern_shaders_gles3_data,
128 impeller_modern_shaders_gles3_length),
129 std::make_shared<fml::NonOwnedMapping>(
130 impeller_framebuffer_blend_shaders_gles3_data,
131 impeller_framebuffer_blend_shaders_gles3_length),
132 std::make_shared<fml::NonOwnedMapping>(
133 impeller_fixtures_shaders_gles3_data,
134 impeller_fixtures_shaders_gles3_length),
135 std::make_shared<fml::NonOwnedMapping>(
136 impeller_modern_fixtures_shaders_gles3_data,
137 impeller_modern_fixtures_shaders_gles3_length),
138 std::make_shared<fml::NonOwnedMapping>(
139 impeller_imgui_shaders_gles3_data,
140 impeller_imgui_shaders_gles3_length),
144 std::make_shared<fml::NonOwnedMapping>(
145 impeller_entity_shaders_gles_data,
146 impeller_entity_shaders_gles_length),
147 std::make_shared<fml::NonOwnedMapping>(
148 impeller_modern_shaders_gles_data,
149 impeller_modern_shaders_gles_length),
150 std::make_shared<fml::NonOwnedMapping>(
151 impeller_framebuffer_blend_shaders_gles_data,
152 impeller_framebuffer_blend_shaders_gles_length),
153 std::make_shared<fml::NonOwnedMapping>(
154 impeller_fixtures_shaders_gles_data,
155 impeller_fixtures_shaders_gles_length),
156 std::make_shared<fml::NonOwnedMapping>(
157 impeller_modern_fixtures_shaders_gles_data,
158 impeller_modern_fixtures_shaders_gles_length),
159 std::make_shared<fml::NonOwnedMapping>(
160 impeller_imgui_shaders_gles_data, impeller_imgui_shaders_gles_length),
165 std::shared_ptr<Context> PlaygroundImplGLES::GetContext()
const {
166 auto gl = std::make_unique<ProcTableGLES>(CreateGLProcAddressResolver());
167 if (!gl->IsValid()) {
168 FML_LOG(ERROR) <<
"Proc table when creating a playground was invalid.";
172 if (gl->GetDescription()->HasDebugExtension()) {
173 gl->DebugMessageCallbackKHR(
174 +[](GLenum , GLenum message_type, GLuint ,
175 GLenum , GLsizei ,
const GLchar* message,
177 switch (message_type) {
178 case GL_DEBUG_TYPE_ERROR_KHR:
179 FML_LOG(ERROR) <<
"GL Error: " << message;
188 gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
191 bool is_gles3 = gl->GetDescription()->GetGlVersion().IsAtLeast(Version(3));
196 FML_LOG(ERROR) <<
"Could not create context.";
200 auto worker_id = context->AddReactorWorker(worker_);
201 if (!worker_id.has_value()) {
202 FML_LOG(ERROR) <<
"Could not add reactor worker.";
210 PlaygroundImplGLES::CreateGLProcAddressResolver()
const {
211 return use_angle_ ? [](
const char* name) ->
void* {
212 void* symbol =
nullptr;
213 #if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
214 void* angle_glesv2 = dlopen(
"libGLESv2.dylib", RTLD_LAZY);
215 symbol = dlsym(angle_glesv2, name);
220 : [](
const char* name) ->
void* {
221 return reinterpret_cast<void*
>(::glfwGetProcAddress(name));
227 return handle_.get();
231 std::unique_ptr<Surface> PlaygroundImplGLES::AcquireSurfaceFrame(
232 std::shared_ptr<Context> context) {
233 auto window =
reinterpret_cast<GLFWwindow*
>(GetWindowHandle());
236 ::glfwGetFramebufferSize(window, &width, &height);
237 if (width <= 0 || height <= 0) {
241 ::glfwSwapBuffers(window);
253 const std::shared_ptr<Capabilities>& capabilities) {
255 fml::StatusCode::kUnimplemented,
256 "PlaygroundImplGLES doesn't support setting the capabilities.");
261 std::make_unique<ProcTableGLES>(CreateGLProcAddressResolver());
262 if (!gl->IsValid()) {
263 FML_LOG(ERROR) <<
"Proc table was invalid. Assuming baseline OpenGL ES";
266 bool is_gles3 = gl->GetDescription()->GetGlVersion().IsAtLeast(Version(3));
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
bool CanReactorReactOnCurrentThreadNow(const ReactorGLES &reactor) const override
Determines the ability of the worker to service a reaction on the current thread. The OpenGL context ...
void SetReactionsAllowedOnCurrentThread(bool allowed)
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
static std::vector< std::shared_ptr< fml::Mapping > > ShaderLibraryMappingsForPlayground(bool is_gles3)
static constexpr TSize MakeWH(Type width, Type height)