未验证 提交 43828e86 编写于 作者: J Jason Simmons 提交者: GitHub

Workaround for an Android emulator EGL bug that can cause inaccurate GL version strings (#21258)

上级 88fd4cea
...@@ -57,7 +57,7 @@ class GPUSurfaceGLDelegate : public GPUSurfaceDelegate { ...@@ -57,7 +57,7 @@ class GPUSurfaceGLDelegate : public GPUSurfaceDelegate {
// flushed. // flushed.
virtual SkMatrix GLContextSurfaceTransformation() const; virtual SkMatrix GLContextSurfaceTransformation() const;
sk_sp<const GrGLInterface> GetGLInterface() const; virtual sk_sp<const GrGLInterface> GetGLInterface() const;
// TODO(chinmaygarde): The presence of this method is to work around the fact // TODO(chinmaygarde): The presence of this method is to work around the fact
// that not all platforms can accept a custom GL proc table. Migrate all // that not all platforms can accept a custom GL proc table. Migrate all
......
...@@ -248,4 +248,12 @@ bool AndroidContextGL::ClearCurrent() { ...@@ -248,4 +248,12 @@ bool AndroidContextGL::ClearCurrent() {
return true; return true;
} }
EGLContext AndroidContextGL::CreateNewContext() const {
bool success;
EGLContext context;
std::tie(success, context) =
CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
return success ? context : EGL_NO_CONTEXT;
}
} // namespace flutter } // namespace flutter
...@@ -110,6 +110,13 @@ class AndroidContextGL : public AndroidContext { ...@@ -110,6 +110,13 @@ class AndroidContextGL : public AndroidContext {
/// ///
bool ClearCurrent(); bool ClearCurrent();
//----------------------------------------------------------------------------
/// @brief Create a new EGLContext using the same EGLConfig.
///
/// @return The EGLContext.
///
EGLContext CreateNewContext() const;
private: private:
fml::RefPtr<AndroidEnvironmentGL> environment_; fml::RefPtr<AndroidEnvironmentGL> environment_;
EGLConfig config_; EGLConfig config_;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "flutter/shell/platform/android/android_surface_gl.h" #include "flutter/shell/platform/android/android_surface_gl.h"
#include <GLES/gl.h>
#include <utility> #include <utility>
#include "flutter/fml/logging.h" #include "flutter/fml/logging.h"
...@@ -12,6 +13,12 @@ ...@@ -12,6 +13,12 @@
namespace flutter { namespace flutter {
namespace {
// GL renderer string prefix used by the Android emulator GLES implementation.
constexpr char kEmulatorRendererPrefix[] =
"Android Emulator OpenGL ES Translator";
} // anonymous namespace
AndroidSurfaceGL::AndroidSurfaceGL( AndroidSurfaceGL::AndroidSurfaceGL(
std::shared_ptr<AndroidContext> android_context, std::shared_ptr<AndroidContext> android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade, std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
...@@ -133,4 +140,37 @@ ExternalViewEmbedder* AndroidSurfaceGL::GetExternalViewEmbedder() { ...@@ -133,4 +140,37 @@ ExternalViewEmbedder* AndroidSurfaceGL::GetExternalViewEmbedder() {
return external_view_embedder_.get(); return external_view_embedder_.get();
} }
// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
// This is a workaround for a bug in the Android emulator EGL/GLES
// implementation. Some versions of the emulator will not update the
// GL version string when the process switches to a new EGL context
// unless the EGL context is being made current for the first time.
// The inaccurate version string will be rejected by Skia when it
// tries to build the GrGLInterface. Flutter can work around this
// by creating a new context, making it current to force an update
// of the version, and then reverting to the previous context.
const char* gl_renderer =
reinterpret_cast<const char*>(glGetString(GL_RENDERER));
if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix,
strlen(kEmulatorRendererPrefix)) == 0) {
EGLContext new_context = android_context_->CreateNewContext();
if (new_context != EGL_NO_CONTEXT) {
EGLContext old_context = eglGetCurrentContext();
EGLDisplay display = eglGetCurrentDisplay();
EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW);
EGLSurface read_surface = eglGetCurrentSurface(EGL_READ);
EGLBoolean result =
eglMakeCurrent(display, draw_surface, read_surface, new_context);
FML_DCHECK(result == EGL_TRUE);
result = eglMakeCurrent(display, draw_surface, read_surface, old_context);
FML_DCHECK(result == EGL_TRUE);
result = eglDestroyContext(display, new_context);
FML_DCHECK(result == EGL_TRUE);
}
}
return GPUSurfaceGLDelegate::GetGLInterface();
}
} // namespace flutter } // namespace flutter
...@@ -65,6 +65,9 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate, ...@@ -65,6 +65,9 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
// |GPUSurfaceGLDelegate| // |GPUSurfaceGLDelegate|
ExternalViewEmbedder* GetExternalViewEmbedder() override; ExternalViewEmbedder* GetExternalViewEmbedder() override;
// |GPUSurfaceGLDelegate|
sk_sp<const GrGLInterface> GetGLInterface() const override;
private: private:
const std::unique_ptr<AndroidExternalViewEmbedder> external_view_embedder_; const std::unique_ptr<AndroidExternalViewEmbedder> external_view_embedder_;
const std::shared_ptr<AndroidContextGL> android_context_; const std::shared_ptr<AndroidContextGL> android_context_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册