5#define FML_USED_ON_EMBEDDER
10#include <EGL/eglext.h>
11#include <EGL/eglplatform.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"
34class TesterGLESDelegate :
public GPUSurfaceGLDelegate {
36 static absl::StatusOr<TesterGLESDelegate> Create() {
38 if (display == EGL_NO_DISPLAY) {
39 return absl::InternalError(
"Could not create EGL display.");
42 if (::eglInitialize(display,
nullptr,
nullptr) != EGL_TRUE) {
43 return absl::InternalError(
"Could not initialize EGL display.");
46 EGLint num_config = 0;
47 const EGLint attribute_list[] = {EGL_RED_SIZE,
67 EGLConfig config =
nullptr;
68 if (::eglChooseConfig(display, attribute_list, &config, 1, &num_config) !=
71 return absl::InternalError(
"Could not choose EGL config.");
74 const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
78 ::eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
79 if (context == EGL_NO_CONTEXT) {
80 return absl::InternalError(
"Could not create EGL context.");
84 const EGLint surface_attributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
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.");
92 return TesterGLESDelegate(display, context,
surface);
95 TesterGLESDelegate(TesterGLESDelegate&& other)
97 context_(other.context_),
99 other.display_ = EGL_NO_DISPLAY;
100 other.context_ = EGL_NO_CONTEXT;
101 other.surface_ = EGL_NO_SURFACE;
104 virtual ~TesterGLESDelegate() {
109 if (context_ != EGL_NO_CONTEXT) {
110 ::eglMakeCurrent(
display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
112 ::eglDestroyContext(
display_, context_);
118 bool MakeContextCurrent() {
123 std::unique_ptr<GLContextResult> GLContextMakeCurrent()
override {
124 return std::make_unique<GLContextDefaultResult>(MakeContextCurrent());
128 bool GLContextClearCurrent()
override {
129 return ::eglMakeCurrent(
display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
130 EGL_NO_CONTEXT) == EGL_TRUE;
134 bool GLContextPresent(
const GLPresentInfo& present_info)
override {
139 GLFBOInfo GLContextFBO(GLFrameInfo frame_info)
const override {
140 return GLFBOInfo{0, std::nullopt};
144 SurfaceFrame::FramebufferInfo GLContextFramebufferInfo()
const override {
145 return SurfaceFrame::FramebufferInfo{.supports_readback =
true};
149 TesterGLESDelegate(EGLDisplay display, EGLContext context, EGLSurface
surface)
152 EGLDisplay
display_ = EGL_NO_DISPLAY;
153 EGLContext context_ = EGL_NO_CONTEXT;
154 EGLSurface
surface_ = EGL_NO_SURFACE;
161 explicit TesterGLESWorker(TesterGLESDelegate* delegate)
164 bool CanReactorReactOnCurrentThreadNow(
173class TesterContextGLES :
public TesterContext {
175 TesterContextGLES() =
default;
177 ~TesterContextGLES()
override {
179 std::shared_ptr<impeller::Context> raw_context = context_;
180 raw_context->Shutdown();
185 auto delegate_status = TesterGLESDelegate::Create();
186 if (!delegate_status.ok()) {
187 FML_LOG(ERROR) << delegate_status.status().message();
190 delegate_ = std::make_unique<TesterGLESDelegate>(
191 std::move(delegate_status.value()));
194 FML_LOG(ERROR) <<
"Could not make GLES context current.";
198 auto resolver = [](
const char*
name) ->
void* {
199 return reinterpret_cast<void*
>(eglGetProcAddress(
name));
202 auto gl = std::make_unique<impeller::ProcTableGLES>(resolver);
203 if (!gl->IsValid()) {
204 FML_LOG(ERROR) <<
"Could not create valid proc table.";
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),
220 shader_mappings,
false);
223 !
static_cast<std::shared_ptr<impeller::Context>
>(context_)->IsValid()) {
224 FML_LOG(ERROR) <<
"Could not create OpenGLES context.";
228 worker_ = std::make_shared<TesterGLESWorker>(
delegate_.get());
229 context_->AddReactorWorker(worker_);
235 std::shared_ptr<impeller::Context> GetImpellerContext()
const override {
240 std::unique_ptr<Surface> CreateRenderingSurface()
override {
241 auto surface = std::make_unique<GPUSurfaceGLImpeller>(
250 std::unique_ptr<TesterGLESDelegate>
delegate_;
251 std::shared_ptr<TesterGLESWorker> worker_;
252 std::shared_ptr<impeller::ContextGLES> context_;
259 auto context = std::make_unique<TesterContextGLES>();
260 if (!context->Initialize()) {
261 FML_LOG(ERROR) <<
"Unable to create TesterContextGLESFactory";
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.
#define FML_LOG(severity)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
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