| // Copyright 2013 The Flutter 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_impeller.h" | |
| #include "flutter/fml/logging.h" | |
| #include "flutter/impeller/toolkit/egl/surface.h" | |
| #include "flutter/shell/gpu/gpu_surface_gl_impeller.h" | |
| namespace flutter { | |
| AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( | |
| const std::shared_ptr<AndroidContextGLImpeller>& android_context) | |
| : android_context_(android_context) { | |
| offscreen_surface_ = android_context_->CreateOffscreenSurface(); | |
| if (!offscreen_surface_) { | |
| FML_DLOG(ERROR) << "Could not create offscreen surface."; | |
| return; | |
| } | |
| // The onscreen surface will be acquired once the native window is set. | |
| is_valid_ = true; | |
| } | |
| AndroidSurfaceGLImpeller::~AndroidSurfaceGLImpeller() = default; | |
| // |AndroidSurface| | |
| bool AndroidSurfaceGLImpeller::IsValid() const { | |
| return is_valid_; | |
| } | |
| // |AndroidSurface| | |
| std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateGPUSurface( | |
| GrDirectContext* gr_context) { | |
| auto surface = std::make_unique<GPUSurfaceGLImpeller>( | |
| this, // delegate | |
| android_context_->GetImpellerContext(), // context | |
| true // render to surface | |
| ); | |
| if (!surface->IsValid()) { | |
| return nullptr; | |
| } | |
| return surface; | |
| } | |
| // |AndroidSurface| | |
| void AndroidSurfaceGLImpeller::TeardownOnScreenContext() { | |
| GLContextClearCurrent(); | |
| onscreen_surface_.reset(); | |
| } | |
| // |AndroidSurface| | |
| bool AndroidSurfaceGLImpeller::OnScreenSurfaceResize(const SkISize& size) { | |
| // The size is unused. It was added only for iOS where the sizes were | |
| // necessary to re-create auxiliary buffers (stencil, depth, etc.). | |
| return RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent(); | |
| } | |
| // |AndroidSurface| | |
| bool AndroidSurfaceGLImpeller::ResourceContextMakeCurrent() { | |
| if (!offscreen_surface_) { | |
| return false; | |
| } | |
| return android_context_->ResourceContextMakeCurrent(offscreen_surface_.get()); | |
| } | |
| // |AndroidSurface| | |
| bool AndroidSurfaceGLImpeller::ResourceContextClearCurrent() { | |
| return android_context_->ResourceContextClearCurrent(); | |
| } | |
| // |AndroidSurface| | |
| bool AndroidSurfaceGLImpeller::SetNativeWindow( | |
| fml::RefPtr<AndroidNativeWindow> window) { | |
| native_window_ = std::move(window); | |
| return RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent(); | |
| } | |
| // |AndroidSurface| | |
| std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateSnapshotSurface() { | |
| FML_UNREACHABLE(); | |
| } | |
| // |AndroidSurface| | |
| std::shared_ptr<impeller::Context> | |
| AndroidSurfaceGLImpeller::GetImpellerContext() { | |
| return android_context_->GetImpellerContext(); | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| std::unique_ptr<GLContextResult> | |
| AndroidSurfaceGLImpeller::GLContextMakeCurrent() { | |
| return std::make_unique<GLContextDefaultResult>(OnGLContextMakeCurrent()); | |
| } | |
| bool AndroidSurfaceGLImpeller::OnGLContextMakeCurrent() { | |
| if (!onscreen_surface_) { | |
| return false; | |
| } | |
| return android_context_->OnscreenContextMakeCurrent(onscreen_surface_.get()); | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| bool AndroidSurfaceGLImpeller::GLContextClearCurrent() { | |
| if (!onscreen_surface_) { | |
| return false; | |
| } | |
| return android_context_->OnscreenContextClearCurrent(); | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| SurfaceFrame::FramebufferInfo | |
| AndroidSurfaceGLImpeller::GLContextFramebufferInfo() const { | |
| auto info = SurfaceFrame::FramebufferInfo{}; | |
| info.supports_readback = true; | |
| info.supports_partial_repaint = false; | |
| return info; | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| void AndroidSurfaceGLImpeller::GLContextSetDamageRegion( | |
| const std::optional<SkIRect>& region) { | |
| // Not supported. | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| bool AndroidSurfaceGLImpeller::GLContextPresent( | |
| const GLPresentInfo& present_info) { | |
| // The FBO ID is superfluous and was introduced for iOS where the default | |
| // framebuffer was not FBO0. | |
| if (!onscreen_surface_) { | |
| return false; | |
| } | |
| return onscreen_surface_->Present(); | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| GLFBOInfo AndroidSurfaceGLImpeller::GLContextFBO(GLFrameInfo frame_info) const { | |
| // FBO0 is the default window bound framebuffer in EGL environments. | |
| return GLFBOInfo{ | |
| .fbo_id = 0, | |
| }; | |
| } | |
| // |GPUSurfaceGLDelegate| | |
| sk_sp<const GrGLInterface> AndroidSurfaceGLImpeller::GetGLInterface() const { | |
| return nullptr; | |
| } | |
| bool AndroidSurfaceGLImpeller:: | |
| RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent() { | |
| GLContextClearCurrent(); | |
| if (!native_window_) { | |
| return false; | |
| } | |
| onscreen_surface_.reset(); | |
| auto onscreen_surface = | |
| android_context_->CreateOnscreenSurface(native_window_->handle()); | |
| if (!onscreen_surface) { | |
| FML_DLOG(ERROR) << "Could not create onscreen surface."; | |
| return false; | |
| } | |
| onscreen_surface_ = std::move(onscreen_surface); | |
| return OnGLContextMakeCurrent(); | |
| } | |
| } // namespace flutter |