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  const std::shared_ptr<AndroidContext>& android_context,
24  std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
25  : AndroidSurface(android_context),
26  native_window_(nullptr),
27  onscreen_surface_(nullptr),
28  offscreen_surface_(nullptr) {
29  // Acquire the offscreen surface.
30  offscreen_surface_ = GLContextPtr()->CreateOffscreenSurface();
31  if (!offscreen_surface_->IsValid()) {
32  offscreen_surface_ = nullptr;
33  }
34 }
35 
37 
39  // When the onscreen surface is destroyed, the context and the surface
40  // instance should be deleted. Issue:
41  // https://github.com/flutter/flutter/issues/64414
42  GLContextPtr()->ClearCurrent();
43  onscreen_surface_ = nullptr;
44 }
45 
47  return offscreen_surface_ && GLContextPtr()->IsValid();
48 }
49 
50 std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface(
51  GrDirectContext* gr_context) {
52  if (gr_context) {
53  return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
54  } else {
55  return std::make_unique<GPUSurfaceGL>(this, true);
56  }
57 }
58 
61  FML_DCHECK(onscreen_surface_);
62  FML_DCHECK(native_window_);
63 
64  if (size == onscreen_surface_->GetSize()) {
65  return true;
66  }
67 
68  GLContextPtr()->ClearCurrent();
69 
70  // Ensure the destructor is called since it destroys the `EGLSurface` before
71  // creating a new onscreen surface.
72  onscreen_surface_ = nullptr;
73  onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_);
74  if (!onscreen_surface_->IsValid()) {
75  FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
76  return false;
77  }
78  onscreen_surface_->MakeCurrent();
79  return true;
80 }
81 
84  return offscreen_surface_->MakeCurrent();
85 }
86 
89  EGLBoolean result = eglMakeCurrent(eglGetCurrentDisplay(), EGL_NO_SURFACE,
90  EGL_NO_SURFACE, EGL_NO_CONTEXT);
91  return result == EGL_TRUE;
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_ = GLContextPtr()->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 GLContextPtr()->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|
136 sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
137  // This is a workaround for a bug in the Android emulator EGL/GLES
138  // implementation. Some versions of the emulator will not update the
139  // GL version string when the process switches to a new EGL context
140  // unless the EGL context is being made current for the first time.
141  // The inaccurate version string will be rejected by Skia when it
142  // tries to build the GrGLInterface. Flutter can work around this
143  // by creating a new context, making it current to force an update
144  // of the version, and then reverting to the previous context.
145  const char* gl_renderer =
146  reinterpret_cast<const char*>(glGetString(GL_RENDERER));
147  if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix,
148  strlen(kEmulatorRendererPrefix)) == 0) {
149  EGLContext new_context = GLContextPtr()->CreateNewContext();
150  if (new_context != EGL_NO_CONTEXT) {
151  EGLContext old_context = eglGetCurrentContext();
152  EGLDisplay display = eglGetCurrentDisplay();
153  EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW);
154  EGLSurface read_surface = eglGetCurrentSurface(EGL_READ);
155  EGLBoolean result =
156  eglMakeCurrent(display, draw_surface, read_surface, new_context);
157  FML_DCHECK(result == EGL_TRUE);
158  result = eglMakeCurrent(display, draw_surface, read_surface, old_context);
159  FML_DCHECK(result == EGL_TRUE);
160  result = eglDestroyContext(display, new_context);
161  FML_DCHECK(result == EGL_TRUE);
162  }
163  }
164 
166 }
167 
168 AndroidContextGL* AndroidSurfaceGL::GLContextPtr() const {
169  return reinterpret_cast<AndroidContextGL*>(android_context_.get());
170 }
171 
172 std::unique_ptr<Surface> AndroidSurfaceGL::CreatePbufferSurface() {
173  onscreen_surface_ = GLContextPtr()->CreatePbufferSurface();
174  return std::make_unique<GPUSurfaceGL>(this, true);
175 }
176 
177 } // namespace flutter
bool IsValid() const override
bool OnScreenSurfaceResize(const SkISize &size) override
#define FML_DCHECK(condition)
Definition: logging.h:86
std::shared_ptr< AndroidContext > android_context_
intptr_t GLContextFBO(GLFrameInfo frame_info) const override
sk_sp< const GrGLInterface > GetGLInterface() const override
bool IsValid() const override
std::unique_ptr< AndroidEGLSurface > CreatePbufferSurface() const
Allocates an 1x1 pbuffer surface that is used for making the onscreen context current for snapshottin...
GAsyncResult * result
virtual std::unique_ptr< Surface > CreatePbufferSurface() override
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
AndroidSurfaceGL(const std::shared_ptr< AndroidContext > &android_context, std::shared_ptr< PlatformViewAndroidJNI > jni_facade)
#define FML_LOG(severity)
Definition: logging.h:65
EGLContext CreateNewContext() const
Create a new EGLContext using the same EGLConfig.
bool GLContextClearCurrent() override
bool ResourceContextClearCurrent() override
bool GLContextPresent(uint32_t fbo_id) override
void TeardownOnScreenContext() override
std::unique_ptr< GLContextResult > GLContextMakeCurrent() override
bool SetNativeWindow(fml::RefPtr< AndroidNativeWindow > window) override
std::unique_ptr< AndroidEGLSurface > CreateOffscreenSurface() const
Allocates an 1x1 pbuffer surface that is used for making the offscreen current for texture uploads...
bool ResourceContextMakeCurrent() override
std::unique_ptr< AndroidEGLSurface > CreateOnscreenSurface(fml::RefPtr< AndroidNativeWindow > window) const
Allocates an new EGL window surface that is used for on-screen pixels.
virtual sk_sp< const GrGLInterface > GetGLInterface() const
std::unique_ptr< Surface > CreateGPUSurface(GrDirectContext *gr_context) override