Flutter Engine
android_surface_gl.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 #include "flutter/shell/platform/android/android_surface_gl.h"
6 
7 #include <GLES/gl.h>
8 #include <utility>
9 
10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/memory/ref_ptr.h"
12 #include "flutter/shell/platform/android/android_shell_holder.h"
13 
14 namespace flutter {
15 
16 namespace {
17 // GL renderer string prefix used by the Android emulator GLES implementation.
18 constexpr char kEmulatorRendererPrefix[] =
19  "Android Emulator OpenGL ES Translator";
20 } // anonymous namespace
21 
23  std::shared_ptr<AndroidContext> android_context,
24  std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
25  std::shared_ptr<AndroidExternalViewEmbedder> external_view_embedder)
26  : external_view_embedder_(external_view_embedder),
27  android_context_(
28  std::static_pointer_cast<AndroidContextGL>(android_context)),
29  native_window_(nullptr),
30  onscreen_surface_(nullptr),
31  offscreen_surface_(nullptr) {
32  // Acquire the offscreen surface.
33  offscreen_surface_ = android_context_->CreateOffscreenSurface();
34  if (!offscreen_surface_->IsValid()) {
35  offscreen_surface_ = nullptr;
36  }
37 }
38 
40 
42  // When the onscreen surface is destroyed, the context and the surface
43  // instance should be deleted. Issue:
44  // https://github.com/flutter/flutter/issues/64414
45  android_context_->ClearCurrent();
46  onscreen_surface_ = nullptr;
47 }
48 
50  return offscreen_surface_ && android_context_->IsValid();
51 }
52 
53 std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface(
54  GrDirectContext* gr_context) {
55  if (gr_context) {
56  return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
57  }
58  return std::make_unique<GPUSurfaceGL>(this, true);
59 }
60 
63  FML_DCHECK(onscreen_surface_);
64  FML_DCHECK(native_window_);
65 
66  if (size == onscreen_surface_->GetSize()) {
67  return true;
68  }
69 
70  android_context_->ClearCurrent();
71 
72  // Ensure the destructor is called since it destroys the `EGLSurface` before
73  // creating a new onscreen surface.
74  onscreen_surface_ = nullptr;
75  onscreen_surface_ = android_context_->CreateOnscreenSurface(native_window_);
76  if (!onscreen_surface_->IsValid()) {
77  FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
78  return false;
79  }
80  onscreen_surface_->MakeCurrent();
81  return true;
82 }
83 
86  return offscreen_surface_->MakeCurrent();
87 }
88 
91  return android_context_->ClearCurrent();
92 }
93 
97  FML_DCHECK(window);
98  native_window_ = window;
99  // Ensure the destructor is called since it destroys the `EGLSurface` before
100  // creating a new onscreen surface.
101  onscreen_surface_ = nullptr;
102  // Create the onscreen surface.
103  onscreen_surface_ = android_context_->CreateOnscreenSurface(window);
104  if (!onscreen_surface_->IsValid()) {
105  return false;
106  }
107  return true;
108 }
109 
110 std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
111  FML_DCHECK(IsValid());
112  FML_DCHECK(onscreen_surface_);
113  auto default_context_result = std::make_unique<GLContextDefaultResult>(
114  onscreen_surface_->MakeCurrent());
115  return std::move(default_context_result);
116 }
117 
119  FML_DCHECK(IsValid());
120  return android_context_->ClearCurrent();
121 }
122 
123 bool AndroidSurfaceGL::GLContextPresent(uint32_t fbo_id) {
124  FML_DCHECK(IsValid());
125  FML_DCHECK(onscreen_surface_);
126  return onscreen_surface_->SwapBuffers();
127 }
128 
129 intptr_t AndroidSurfaceGL::GLContextFBO(GLFrameInfo frame_info) const {
130  FML_DCHECK(IsValid());
131  // The default window bound framebuffer on Android.
132  return 0;
133 }
134 
135 // |GPUSurfaceGLDelegate|
137  return external_view_embedder_.get();
138 }
139 
140 // |GPUSurfaceGLDelegate|
141 sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
142  // This is a workaround for a bug in the Android emulator EGL/GLES
143  // implementation. Some versions of the emulator will not update the
144  // GL version string when the process switches to a new EGL context
145  // unless the EGL context is being made current for the first time.
146  // The inaccurate version string will be rejected by Skia when it
147  // tries to build the GrGLInterface. Flutter can work around this
148  // by creating a new context, making it current to force an update
149  // of the version, and then reverting to the previous context.
150  const char* gl_renderer =
151  reinterpret_cast<const char*>(glGetString(GL_RENDERER));
152  if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix,
153  strlen(kEmulatorRendererPrefix)) == 0) {
154  EGLContext new_context = android_context_->CreateNewContext();
155  if (new_context != EGL_NO_CONTEXT) {
156  EGLContext old_context = eglGetCurrentContext();
157  EGLDisplay display = eglGetCurrentDisplay();
158  EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW);
159  EGLSurface read_surface = eglGetCurrentSurface(EGL_READ);
160  EGLBoolean result =
161  eglMakeCurrent(display, draw_surface, read_surface, new_context);
162  FML_DCHECK(result == EGL_TRUE);
163  result = eglMakeCurrent(display, draw_surface, read_surface, old_context);
164  FML_DCHECK(result == EGL_TRUE);
165  result = eglDestroyContext(display, new_context);
166  FML_DCHECK(result == EGL_TRUE);
167  }
168  }
169 
171 }
172 
173 } // namespace flutter
bool OnScreenSurfaceResize(const SkISize &size) override
#define FML_DCHECK(condition)
Definition: logging.h:86
intptr_t GLContextFBO(GLFrameInfo frame_info) const override
sk_sp< const GrGLInterface > GetGLInterface() const override
Definition: ref_ptr.h:252
bool IsValid() const override
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
#define FML_LOG(severity)
Definition: logging.h:65
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
Definition: mock_egl.cc:306
bool GLContextClearCurrent() override
bool ResourceContextClearCurrent() override
ExternalViewEmbedder * GetExternalViewEmbedder() override
Gets the view embedder that controls how the Flutter layer hierarchy split into multiple chunks shoul...
bool GLContextPresent(uint32_t fbo_id) override
void TeardownOnScreenContext() override
AndroidSurfaceGL(std::shared_ptr< AndroidContext > android_context, std::shared_ptr< PlatformViewAndroidJNI > jni_facade, std::shared_ptr< AndroidExternalViewEmbedder > external_view_embedder)
std::unique_ptr< GLContextResult > GLContextMakeCurrent() override
bool SetNativeWindow(fml::RefPtr< AndroidNativeWindow > window) override
bool ResourceContextMakeCurrent() override
virtual sk_sp< const GrGLInterface > GetGLInterface() const
std::unique_ptr< Surface > CreateGPUSurface(GrDirectContext *gr_context) override