diff --git a/shell/platform/android/android_context_gl.cc b/shell/platform/android/android_context_gl.cc index 31bfc74847394..f1257e6632295 100644 --- a/shell/platform/android/android_context_gl.cc +++ b/shell/platform/android/android_context_gl.cc @@ -252,13 +252,40 @@ bool AndroidEGLSurface::IsValid() const { return surface_ != EGL_NO_SURFACE; } -bool AndroidEGLSurface::MakeCurrent() const { +bool AndroidEGLSurface::IsContextCurrent() const { + EGLContext current_egl_context = eglGetCurrentContext(); + if (context_ != current_egl_context) { + return false; + } + + EGLDisplay current_egl_display = eglGetCurrentDisplay(); + if (display_ != current_egl_display) { + return false; + } + + EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW); + if (draw_surface != surface_) { + return false; + } + + EGLSurface read_surface = eglGetCurrentSurface(EGL_READ); + if (read_surface != surface_) { + return false; + } + + return true; +} + +AndroidEGLSurfaceMakeCurrentStatus AndroidEGLSurface::MakeCurrent() const { + if (IsContextCurrent()) { + return AndroidEGLSurfaceMakeCurrentStatus::kSuccessAlreadyCurrent; + } if (eglMakeCurrent(display_, surface_, surface_, context_) != EGL_TRUE) { FML_LOG(ERROR) << "Could not make the context current"; LogLastEGLError(); - return false; + return AndroidEGLSurfaceMakeCurrentStatus::kFailure; } - return true; + return AndroidEGLSurfaceMakeCurrentStatus::kSuccessMadeCurrent; } void AndroidEGLSurface::SetDamageRegion( @@ -350,7 +377,8 @@ AndroidContextGL::~AndroidContextGL() { if (main_context) { std::unique_ptr pbuffer_surface = CreatePbufferSurface(); - if (pbuffer_surface->MakeCurrent()) { + auto status = pbuffer_surface->MakeCurrent(); + if (status != AndroidEGLSurfaceMakeCurrentStatus::kFailure) { main_context->releaseResourcesAndAbandonContext(); main_context.reset(); ClearCurrent(); diff --git a/shell/platform/android/android_context_gl.h b/shell/platform/android/android_context_gl.h index 4bd4e1886e9aa..db130bcd089bd 100644 --- a/shell/platform/android/android_context_gl.h +++ b/shell/platform/android/android_context_gl.h @@ -25,6 +25,16 @@ namespace flutter { /// class AndroidEGLSurfaceDamage; +/// Result of calling MakeCurrent on AndroidEGLSurface. +enum class AndroidEGLSurfaceMakeCurrentStatus { + /// Success, the egl context for the surface was already current. + kSuccessAlreadyCurrent, + /// Success, the egl context for the surface made current. + kSuccessMadeCurrent, + /// Failed to make the egl context for the surface current. + kFailure, +}; + class AndroidEGLSurface { public: AndroidEGLSurface(EGLSurface surface, EGLDisplay display, EGLContext context); @@ -43,7 +53,7 @@ class AndroidEGLSurface { /// /// @return Whether the surface was made current. /// - bool MakeCurrent() const; + AndroidEGLSurfaceMakeCurrentStatus MakeCurrent() const; //---------------------------------------------------------------------------- /// @@ -81,6 +91,9 @@ class AndroidEGLSurface { SkISize GetSize() const; private: + /// Returns true if the EGLContext held is current for the display and surface + bool IsContextCurrent() const; + const EGLSurface surface_; const EGLDisplay display_; const EGLContext context_; diff --git a/shell/platform/android/android_context_gl_unittests.cc b/shell/platform/android/android_context_gl_unittests.cc index fd327187a210e..2491886b7b5fe 100644 --- a/shell/platform/android/android_context_gl_unittests.cc +++ b/shell/platform/android/android_context_gl_unittests.cc @@ -184,6 +184,30 @@ TEST(AndroidContextGl, MSAAx4) { &sample_count); EXPECT_EQ(sample_count, 4); } + +TEST(AndroidContextGl, EnsureMakeCurrentChecksCurrentContextStatus) { + GrMockOptions main_context_options; + sk_sp main_context = + GrDirectContext::MakeMock(&main_context_options); + auto environment = fml::MakeRefCounted(); + std::string thread_label = + ::testing::UnitTest::GetInstance()->current_test_info()->name(); + + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + thread_label, + ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO)); + TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); + auto context = std::make_unique( + AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0); + + auto pbuffer_surface = context->CreatePbufferSurface(); + auto status = pbuffer_surface->MakeCurrent(); + EXPECT_EQ(AndroidEGLSurfaceMakeCurrentStatus::kSuccessMadeCurrent, status); + + // context already current, so status must reflect that. + status = pbuffer_surface->MakeCurrent(); + EXPECT_EQ(AndroidEGLSurfaceMakeCurrentStatus::kSuccessAlreadyCurrent, status); +} } // namespace android } // namespace testing } // namespace flutter diff --git a/shell/platform/android/android_surface_gl.cc b/shell/platform/android/android_surface_gl.cc index 7b749ca690913..51e72f494fba7 100644 --- a/shell/platform/android/android_surface_gl.cc +++ b/shell/platform/android/android_surface_gl.cc @@ -87,7 +87,8 @@ bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) { bool AndroidSurfaceGL::ResourceContextMakeCurrent() { FML_DCHECK(IsValid()); - return offscreen_surface_->MakeCurrent(); + auto status = offscreen_surface_->MakeCurrent(); + return status != AndroidEGLSurfaceMakeCurrentStatus::kFailure; } bool AndroidSurfaceGL::ResourceContextClearCurrent() { @@ -116,8 +117,9 @@ bool AndroidSurfaceGL::SetNativeWindow( std::unique_ptr AndroidSurfaceGL::GLContextMakeCurrent() { FML_DCHECK(IsValid()); FML_DCHECK(onscreen_surface_); + auto status = onscreen_surface_->MakeCurrent(); auto default_context_result = std::make_unique( - onscreen_surface_->MakeCurrent()); + status != AndroidEGLSurfaceMakeCurrentStatus::kFailure); return std::move(default_context_result); }