Flutter Engine
The Flutter Engine
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
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/fixtures/gles/fixtures_shaders_gles.h"
21#include "impeller/playground/imgui/gles/imgui_shaders_gles.h"
24#include "impeller/scene/shaders/gles/scene_shaders_gles.h"
25
26namespace impeller {
27
29 public:
30 ReactorWorker() = default;
31
32 // |ReactorGLES::Worker|
34 const ReactorGLES& reactor) const override {
35 ReaderLock lock(mutex_);
36 auto found = reactions_allowed_.find(std::this_thread::get_id());
37 if (found == reactions_allowed_.end()) {
38 return false;
39 }
40 return found->second;
41 }
42
44 WriterLock lock(mutex_);
45 reactions_allowed_[std::this_thread::get_id()] = allowed;
46 }
47
48 private:
49 mutable RWMutex mutex_;
50 std::map<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);
51
52 ReactorWorker(const ReactorWorker&) = delete;
53
54 ReactorWorker& operator=(const ReactorWorker&) = delete;
55};
56
57void PlaygroundImplGLES::DestroyWindowHandle(WindowHandle handle) {
58 if (!handle) {
59 return;
60 }
61 ::glfwDestroyWindow(reinterpret_cast<GLFWwindow*>(handle));
62}
63
65 : PlaygroundImpl(switches),
66 handle_(nullptr, &DestroyWindowHandle),
67 worker_(std::shared_ptr<ReactorWorker>(new ReactorWorker())),
68 use_angle_(switches.use_angle) {
69 if (use_angle_) {
70#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
71 angle_glesv2_ = dlopen("libGLESv2.dylib", RTLD_LAZY);
72#endif
73 FML_CHECK(angle_glesv2_ != nullptr);
74 }
75
76 ::glfwDefaultWindowHints();
77
78#if FML_OS_MACOSX
79 FML_CHECK(use_angle_) << "Must use Angle on macOS for OpenGL ES.";
80 ::glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
81#endif // FML_OS_MACOSX
82 ::glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
83 ::glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
84 ::glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
85 ::glfwWindowHint(GLFW_RED_BITS, 8);
86 ::glfwWindowHint(GLFW_GREEN_BITS, 8);
87 ::glfwWindowHint(GLFW_BLUE_BITS, 8);
88 ::glfwWindowHint(GLFW_ALPHA_BITS, 8);
89 ::glfwWindowHint(GLFW_DEPTH_BITS, 32); // 32 bit depth buffer
90 ::glfwWindowHint(GLFW_STENCIL_BITS, 8); // 8 bit stencil buffer
91 ::glfwWindowHint(GLFW_SAMPLES, 4); // 4xMSAA
92
93 ::glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
94
95 auto window = ::glfwCreateWindow(1, 1, "Test", nullptr, nullptr);
96
97 ::glfwMakeContextCurrent(window);
98 worker_->SetReactionsAllowedOnCurrentThread(true);
99
100 handle_.reset(window);
101}
102
104
105static std::vector<std::shared_ptr<fml::Mapping>>
107 return {
108 std::make_shared<fml::NonOwnedMapping>(
109 impeller_entity_shaders_gles_data,
110 impeller_entity_shaders_gles_length),
111 std::make_shared<fml::NonOwnedMapping>(
112 impeller_modern_shaders_gles_data,
113 impeller_modern_shaders_gles_length),
114 std::make_shared<fml::NonOwnedMapping>(
115 impeller_framebuffer_blend_shaders_gles_data,
116 impeller_framebuffer_blend_shaders_gles_length),
117 std::make_shared<fml::NonOwnedMapping>(
118 impeller_fixtures_shaders_gles_data,
119 impeller_fixtures_shaders_gles_length),
120 std::make_shared<fml::NonOwnedMapping>(
121 impeller_imgui_shaders_gles_data, impeller_imgui_shaders_gles_length),
122 std::make_shared<fml::NonOwnedMapping>(
123 impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length),
124 };
125}
126
127// |PlaygroundImpl|
128std::shared_ptr<Context> PlaygroundImplGLES::GetContext() const {
129 auto resolver = use_angle_ ? [](const char* name) -> void* {
130 void* symbol = nullptr;
131#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE
132 void* angle_glesv2 = dlopen("libGLESv2.dylib", RTLD_LAZY);
133 symbol = dlsym(angle_glesv2, name);
134#endif
135 FML_CHECK(symbol);
136 return symbol;
137 }
138 : [](const char* name) -> void* {
139 return reinterpret_cast<void*>(::glfwGetProcAddress(name));
140 };
141 auto gl = std::make_unique<ProcTableGLES>(resolver);
142 if (!gl->IsValid()) {
143 FML_LOG(ERROR) << "Proc table when creating a playground was invalid.";
144 return nullptr;
145 }
146
147 auto context = ContextGLES::Create(
148 std::move(gl), ShaderLibraryMappingsForPlayground(), true);
149 if (!context) {
150 FML_LOG(ERROR) << "Could not create context.";
151 return nullptr;
152 }
153
154 auto worker_id = context->AddReactorWorker(worker_);
155 if (!worker_id.has_value()) {
156 FML_LOG(ERROR) << "Could not add reactor worker.";
157 return nullptr;
158 }
159 return context;
160}
161
162// |PlaygroundImpl|
163PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() const {
164 return handle_.get();
165}
166
167// |PlaygroundImpl|
168std::unique_ptr<Surface> PlaygroundImplGLES::AcquireSurfaceFrame(
169 std::shared_ptr<Context> context) {
170 auto window = reinterpret_cast<GLFWwindow*>(GetWindowHandle());
171 int width = 0;
172 int height = 0;
173 ::glfwGetFramebufferSize(window, &width, &height);
174 if (width <= 0 || height <= 0) {
175 return nullptr;
176 }
177 SurfaceGLES::SwapCallback swap_callback = [window]() -> bool {
178 ::glfwSwapBuffers(window);
179 return true;
180 };
181 return SurfaceGLES::WrapFBO(context, //
182 swap_callback, //
183 0u, //
186 );
187}
188
190 const std::shared_ptr<Capabilities>& capabilities) {
191 return fml::Status(
193 "PlaygroundImplGLES doesn't support setting the capabilities.");
194}
195
196} // namespace impeller
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)
Definition: context_gles.cc:16
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
A delegate implemented by a thread on which an OpenGL context is current. There may be multiple worke...
Definition: reactor_gles.h:67
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
Definition: reactor_gles.h:55
static std::unique_ptr< Surface > WrapFBO(const std::shared_ptr< Context > &context, SwapCallback swap_callback, GLuint fbo, PixelFormat color_format, ISize fbo_size)
Definition: surface_gles.cc:14
std::function< bool(void)> SwapCallback
Definition: surface_gles.h:19
GLFWwindow * window
Definition: main.cc:45
#define GLFW_FALSE
Definition: flutter_glfw.cc:36
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
static std::vector< std::shared_ptr< fml::Mapping > > ShaderLibraryMappingsForPlayground()
gl
Definition: malisc.py:41
Task::Status Status
Definition: TaskList.cpp:15
Definition: ref_ptr.h:256
fuchsia::ui::composition::ParentViewportWatcherHandle handle_
int32_t height
int32_t width
static constexpr TSize MakeWH(Type width, Type height)
Definition: size.h:34
#define ERROR(message)
Definition: elf_loader.cc:260