// 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_EGL_CONTEXT_H_ #define FLUTTER_IMPELLER_TOOLKIT_EGL_CONTEXT_H_ #include #include "impeller/base/comparable.h" #include "impeller/base/thread.h" #include "impeller/toolkit/egl/egl.h" namespace impeller { namespace egl { class Surface; class Display; //------------------------------------------------------------------------------ /// @brief An instance of an EGL context. /// /// An EGL context can only be used on a single thread at a given /// time. A thread can only have a single context current at any /// given time. /// /// Context cannot be created directly. Only a valid instance of an /// egl::Display can create a context. /// class Context { public: ~Context(); //---------------------------------------------------------------------------- /// @brief Determines if a valid context could be created. The context /// still needs to be made current on the thread for it to be /// useful. /// /// @return True if valid, False otherwise. /// bool IsValid() const; //---------------------------------------------------------------------------- /// @brief Get the underlying handle to the EGL context. /// /// @return The handle. /// const EGLContext& GetHandle() const; //---------------------------------------------------------------------------- /// @brief Make the context current on the calling thread. It is the /// caller responsibility to ensure that any context previously /// current on the thread must be cleared via `ClearCurrent`. /// /// @important The config used to create the surface must match the config /// used to create this context instance. /// /// @param[in] surface The surface to use to make the context current. /// /// @return If the context could be made current on the callers thread. /// bool MakeCurrent(const Surface& surface) const; //---------------------------------------------------------------------------- /// @brief Clear the thread association of this context. /// /// @return If the thread association could be cleared. /// bool ClearCurrent() const; enum class LifecycleEvent { kDidMakeCurrent, kWillClearCurrent, }; using LifecycleListener = std::function; //---------------------------------------------------------------------------- /// @brief Add a listener that gets invoked when the context is made and /// cleared current from the thread. Applications typically use /// this to manage workers that schedule OpenGL API calls that /// need to be careful about the context being current when /// called. /// /// @param[in] listener The listener /// /// @return A unique ID for the listener that can used used in /// `RemoveLifecycleListener` to remove a previously added /// listener. /// std::optional AddLifecycleListener( const LifecycleListener& listener); //---------------------------------------------------------------------------- /// @brief Remove a previously added context listener. /// /// @param[in] id The identifier obtained via a previous call to /// `AddLifecycleListener`. /// /// @return True if the listener could be removed. /// bool RemoveLifecycleListener(UniqueID id); //---------------------------------------------------------------------------- /// @return True if the context is current and attached to any surface, /// False otherwise. /// bool IsCurrent() const; private: friend class Display; EGLDisplay display_ = EGL_NO_DISPLAY; EGLContext context_ = EGL_NO_CONTEXT; mutable RWMutex listeners_mutex_; std::map listeners_ IPLR_GUARDED_BY( listeners_mutex_); Context(EGLDisplay display, EGLContext context); void DispatchLifecyleEvent(LifecycleEvent event) const; Context(const Context&) = delete; Context& operator=(const Context&) = delete; }; } // namespace egl } // namespace impeller #endif // FLUTTER_IMPELLER_TOOLKIT_EGL_CONTEXT_H_