// 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. #ifndef FLUTTER_IMPELLER_TOOLKIT_GLVK_TRAMPOLINE_H_ #define FLUTTER_IMPELLER_TOOLKIT_GLVK_TRAMPOLINE_H_ #include "impeller/base/thread_safety.h" #include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" #include "impeller/toolkit/egl/context.h" #include "impeller/toolkit/egl/display.h" #include "impeller/toolkit/egl/surface.h" #include "impeller/toolkit/glvk/proc_table.h" namespace impeller::glvk { class AutoTrampolineContext; //------------------------------------------------------------------------------ /// @brief An object used to interoperate between OpenGL and Vulkan. /// /// While these are not super expensive to create, they do manage an /// internal EGL context as well as some OpenGL state. For this /// reason, it is recommended that callers cache these for the /// duration of the lifecycle of main rendering context. /// class Trampoline { public: //---------------------------------------------------------------------------- /// @brief Constructs a new trampoline. It is recommended that these /// objects be cached and reused for all conversion operations. /// /// EGL contexts on already bound to the callers thread may become /// unbound after a call to this method. /// Trampoline(); //---------------------------------------------------------------------------- /// @brief Destroys the trampoline. There are no threading restrictions. /// EGL contexts on already bound to the callers thread may become /// unbound after a call to this method. /// ~Trampoline(); Trampoline(const Trampoline&) = delete; Trampoline& operator=(const Trampoline&) = delete; //---------------------------------------------------------------------------- /// @brief Determines if this is a valid trampoline. There is no error /// recovery mechanism if a trampoline cannot be constructed and /// an invalid trampoline must be immediately discarded. /// /// @return True if valid, False otherwise. /// bool IsValid() const; //---------------------------------------------------------------------------- /// @brief Describes an OpenGL texture along with information on how to /// sample from it. /// struct GLTextureInfo { //-------------------------------------------------------------------------- /// The OpenGL texture handle. /// GLuint texture = 0; //-------------------------------------------------------------------------- /// The OpenGL texture target enum. For instance, GL_TEXTURE_2D or /// GL_TEXTURE_EXTERNAL_OES. /// GLenum target = 0; //-------------------------------------------------------------------------- /// A transformation applied to the texture coordinates in the form of (u, /// v, 0, 1) when sampling from the texture. /// Matrix uv_transformation; }; //---------------------------------------------------------------------------- /// @brief Perform a blit operation from the source OpenGL texture to a /// target Vulkan texture. /// /// It is the callers responsibility to ensure that the EGL /// context associated with the trampoline is already current /// before making this call. /// /// It is also the responsibility of the caller to ensure that the /// destination texture is the color-attachment-optimal layout. /// Failure to ensure this will lead to validation error. /// /// @see `MakeCurrentContext` /// /// @param[in] src_texture The source OpenGL texture. /// @param[in] dst_texture The destination Vulkan texture. /// /// @return True if the blit was successful, False otherwise. /// bool BlitTextureOpenGLToVulkan(const GLTextureInfo& src_texture, const AHBTextureSourceVK& dst_texture) const; //---------------------------------------------------------------------------- /// @brief Make the EGL context associated with this trampoline current /// on the calling thread. /// /// @return The automatic trampoline context. The collection of this /// context clears the threads EGL binding. /// [[nodiscard]] AutoTrampolineContext MakeCurrentContext() const; private: friend class AutoTrampolineContext; std::unique_ptr egl_display_; std::unique_ptr egl_context_; std::unique_ptr egl_surface_; std::unique_ptr gl_; GLuint program_ = GL_NONE; GLint texture_uniform_location_ = 0; GLint uv_transformation_location_ = 0; bool is_valid_ = false; }; //------------------------------------------------------------------------------ /// @brief An RAII object that makes the trampolines EGL context current /// when constructed and clears the EGL binding on destruction. /// class AutoTrampolineContext final { public: //---------------------------------------------------------------------------- /// @brief Constructs a new instance and makes the trampolines EGL /// context current on the calling thread. /// /// @param[in] trampoline The trampoline. /// explicit AutoTrampolineContext(const Trampoline& trampoline); //---------------------------------------------------------------------------- /// @brief Destroys the object and clears the previous EGL binding. /// ~AutoTrampolineContext(); AutoTrampolineContext(const AutoTrampolineContext&) = delete; AutoTrampolineContext& operator=(const AutoTrampolineContext&) = delete; private: const egl::Context* context_ = nullptr; const egl::Surface* surface_ = nullptr; }; } // namespace impeller::glvk #endif // FLUTTER_IMPELLER_TOOLKIT_GLVK_TRAMPOLINE_H_