| // 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 <functional> | |
| #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<void(LifecycleEvent)>; | |
| //---------------------------------------------------------------------------- | |
| /// @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<UniqueID> 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<UniqueID, LifecycleListener> 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_ |