|
4 | 4 |
|
5 | 5 | #include "flutter/shell/platform/android/android_surface_gl.h" |
6 | 6 |
|
| 7 | +#include <GLES/gl.h> |
7 | 8 | #include <utility> |
8 | 9 |
|
9 | 10 | #include "flutter/fml/logging.h" |
|
12 | 13 |
|
13 | 14 | namespace flutter { |
14 | 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 | + |
15 | 22 | AndroidSurfaceGL::AndroidSurfaceGL( |
16 | 23 | std::shared_ptr<AndroidContext> android_context, |
17 | 24 | std::shared_ptr<PlatformViewAndroidJNI> jni_facade, |
@@ -133,4 +140,37 @@ ExternalViewEmbedder* AndroidSurfaceGL::GetExternalViewEmbedder() { |
133 | 140 | return external_view_embedder_.get(); |
134 | 141 | } |
135 | 142 |
|
| 143 | +// |GPUSurfaceGLDelegate| |
| 144 | +sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const { |
| 145 | + // This is a workaround for a bug in the Android emulator EGL/GLES |
| 146 | + // implementation. Some versions of the emulator will not update the |
| 147 | + // GL version string when the process switches to a new EGL context |
| 148 | + // unless the EGL context is being made current for the first time. |
| 149 | + // The inaccurate version string will be rejected by Skia when it |
| 150 | + // tries to build the GrGLInterface. Flutter can work around this |
| 151 | + // by creating a new context, making it current to force an update |
| 152 | + // of the version, and then reverting to the previous context. |
| 153 | + const char* gl_renderer = |
| 154 | + reinterpret_cast<const char*>(glGetString(GL_RENDERER)); |
| 155 | + if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix, |
| 156 | + strlen(kEmulatorRendererPrefix)) == 0) { |
| 157 | + EGLContext new_context = android_context_->CreateNewContext(); |
| 158 | + if (new_context != EGL_NO_CONTEXT) { |
| 159 | + EGLContext old_context = eglGetCurrentContext(); |
| 160 | + EGLDisplay display = eglGetCurrentDisplay(); |
| 161 | + EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW); |
| 162 | + EGLSurface read_surface = eglGetCurrentSurface(EGL_READ); |
| 163 | + EGLBoolean result = |
| 164 | + eglMakeCurrent(display, draw_surface, read_surface, new_context); |
| 165 | + FML_DCHECK(result == EGL_TRUE); |
| 166 | + result = eglMakeCurrent(display, draw_surface, read_surface, old_context); |
| 167 | + FML_DCHECK(result == EGL_TRUE); |
| 168 | + result = eglDestroyContext(display, new_context); |
| 169 | + FML_DCHECK(result == EGL_TRUE); |
| 170 | + } |
| 171 | + } |
| 172 | + |
| 173 | + return GPUSurfaceGLDelegate::GetGLInterface(); |
| 174 | +} |
| 175 | + |
136 | 176 | } // namespace flutter |
0 commit comments