| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "flutter/shell/platform/android/android_surface_gl.h" |
| |
| #include <utility> |
| |
| #include "flutter/common/threads.h" |
| #include "lib/ftl/logging.h" |
| #include "lib/ftl/memory/ref_ptr.h" |
| |
| namespace shell { |
| |
| static ftl::RefPtr<AndroidContextGL> GlobalResourceLoadingContext( |
| PlatformView::SurfaceConfig offscreen_config) { |
| // AndroidSurfaceGL instances are only ever created on the platform thread. So |
| // there is no need to lock here. |
| |
| static ftl::RefPtr<AndroidContextGL> global_context; |
| |
| if (global_context) { |
| return global_context; |
| } |
| |
| auto environment = ftl::MakeRefCounted<AndroidEnvironmentGL>(); |
| |
| if (!environment->IsValid()) { |
| return nullptr; |
| } |
| |
| // TODO(chinmaygarde): We should check that the configurations are stable |
| // across multiple invocations. |
| |
| auto context = |
| ftl::MakeRefCounted<AndroidContextGL>(environment, offscreen_config); |
| |
| if (!context->IsValid()) { |
| return nullptr; |
| } |
| |
| global_context = context; |
| return global_context; |
| } |
| |
| AndroidSurfaceGL::AndroidSurfaceGL( |
| PlatformView::SurfaceConfig offscreen_config) { |
| // Acquire the offscreen context. |
| offscreen_context_ = GlobalResourceLoadingContext(offscreen_config); |
| |
| if (!offscreen_context_ || !offscreen_context_->IsValid()) { |
| offscreen_context_ = nullptr; |
| } |
| } |
| |
| AndroidSurfaceGL::~AndroidSurfaceGL() = default; |
| |
| bool AndroidSurfaceGL::IsOffscreenContextValid() const { |
| return offscreen_context_ && offscreen_context_->IsValid(); |
| } |
| |
| void AndroidSurfaceGL::TeardownOnScreenContext() { |
| ftl::AutoResetWaitableEvent latch; |
| blink::Threads::Gpu()->PostTask([this, &latch]() { |
| if (IsValid()) { |
| GLContextClearCurrent(); |
| } |
| latch.Signal(); |
| }); |
| latch.Wait(); |
| onscreen_context_ = nullptr; |
| } |
| |
| bool AndroidSurfaceGL::IsValid() const { |
| if (!onscreen_context_ || !offscreen_context_) { |
| return false; |
| } |
| |
| return onscreen_context_->IsValid() && offscreen_context_->IsValid(); |
| } |
| |
| std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface() { |
| auto surface = std::make_unique<GPUSurfaceGL>(this); |
| |
| if (!surface->Setup()) { |
| return nullptr; |
| } |
| |
| return surface; |
| } |
| |
| SkISize AndroidSurfaceGL::OnScreenSurfaceSize() const { |
| FTL_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); |
| return onscreen_context_->GetSize(); |
| } |
| |
| bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) const { |
| FTL_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); |
| return onscreen_context_->Resize(size); |
| } |
| |
| bool AndroidSurfaceGL::ResourceContextMakeCurrent() { |
| FTL_DCHECK(offscreen_context_ && offscreen_context_->IsValid()); |
| return offscreen_context_->MakeCurrent(); |
| } |
| |
| bool AndroidSurfaceGL::SetNativeWindow(ftl::RefPtr<AndroidNativeWindow> window, |
| PlatformView::SurfaceConfig config) { |
| // In any case, we want to get rid of our current onscreen context. |
| onscreen_context_ = nullptr; |
| |
| // If the offscreen context has not been setup, we dont have the sharegroup. |
| // So bail. |
| if (!offscreen_context_ || !offscreen_context_->IsValid()) { |
| return false; |
| } |
| |
| // Create the onscreen context. |
| onscreen_context_ = ftl::MakeRefCounted<AndroidContextGL>( |
| offscreen_context_->Environment(), std::move(window), config, |
| offscreen_context_.get() /* sharegroup */); |
| |
| if (!onscreen_context_->IsValid()) { |
| onscreen_context_ = nullptr; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool AndroidSurfaceGL::GLContextMakeCurrent() { |
| FTL_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); |
| return onscreen_context_->MakeCurrent(); |
| } |
| |
| bool AndroidSurfaceGL::GLContextClearCurrent() { |
| FTL_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); |
| return onscreen_context_->ClearCurrent(); |
| } |
| |
| bool AndroidSurfaceGL::GLContextPresent() { |
| FTL_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); |
| return onscreen_context_->SwapBuffers(); |
| } |
| |
| intptr_t AndroidSurfaceGL::GLContextFBO() const { |
| FTL_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); |
| // The default window bound framebuffer on Android. |
| return 0; |
| } |
| |
| void AndroidSurfaceGL::SetFlutterView( |
| const fml::jni::JavaObjectWeakGlobalRef& flutter_view) {} |
| |
| } // namespace shell |