| // 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 "impeller/toolkit/egl/context.h" | |
| #include "impeller/toolkit/egl/surface.h" | |
| namespace impeller { | |
| namespace egl { | |
| Context::Context(EGLDisplay display, EGLContext context) | |
| : display_(display), context_(context) {} | |
| Context::~Context() { | |
| if (context_ != EGL_NO_CONTEXT) { | |
| if (::eglDestroyContext(display_, context_) != EGL_TRUE) { | |
| IMPELLER_LOG_EGL_ERROR; | |
| } | |
| } | |
| } | |
| bool Context::IsValid() const { | |
| return context_ != EGL_NO_CONTEXT; | |
| } | |
| const EGLContext& Context::GetHandle() const { | |
| return context_; | |
| } | |
| static EGLBoolean EGLMakeCurrentIfNecessary(EGLDisplay display, | |
| EGLSurface draw, | |
| EGLSurface read, | |
| EGLContext context) { | |
| if (display != ::eglGetCurrentDisplay() || | |
| draw != ::eglGetCurrentSurface(EGL_DRAW) || | |
| read != ::eglGetCurrentSurface(EGL_READ) || | |
| context != ::eglGetCurrentContext()) { | |
| return ::eglMakeCurrent(display, draw, read, context); | |
| } | |
| // The specified context configuration is already current. | |
| return EGL_TRUE; | |
| } | |
| bool Context::MakeCurrent(const Surface& surface) const { | |
| if (context_ == EGL_NO_CONTEXT) { | |
| return false; | |
| } | |
| const auto result = EGLMakeCurrentIfNecessary(display_, // | |
| surface.GetHandle(), // | |
| surface.GetHandle(), // | |
| context_ // | |
| ) == EGL_TRUE; | |
| if (!result) { | |
| IMPELLER_LOG_EGL_ERROR; | |
| } | |
| DispatchLifecyleEvent(LifecycleEvent::kDidMakeCurrent); | |
| return result; | |
| } | |
| bool Context::ClearCurrent() const { | |
| DispatchLifecyleEvent(LifecycleEvent::kWillClearCurrent); | |
| const auto result = EGLMakeCurrentIfNecessary(display_, // | |
| EGL_NO_SURFACE, // | |
| EGL_NO_SURFACE, // | |
| EGL_NO_CONTEXT // | |
| ) == EGL_TRUE; | |
| if (!result) { | |
| IMPELLER_LOG_EGL_ERROR; | |
| } | |
| return result; | |
| } | |
| std::optional<UniqueID> Context::AddLifecycleListener( | |
| const LifecycleListener& listener) { | |
| if (!listener) { | |
| return std::nullopt; | |
| } | |
| WriterLock lock(listeners_mutex_); | |
| UniqueID id; | |
| listeners_[id] = listener; | |
| return id; | |
| } | |
| bool Context::RemoveLifecycleListener(UniqueID id) { | |
| WriterLock lock(listeners_mutex_); | |
| auto found = listeners_.find(id); | |
| if (found == listeners_.end()) { | |
| return false; | |
| } | |
| listeners_.erase(found); | |
| return true; | |
| } | |
| void Context::DispatchLifecyleEvent(LifecycleEvent event) const { | |
| ReaderLock lock(listeners_mutex_); | |
| for (const auto& listener : listeners_) { | |
| listener.second(event); | |
| } | |
| } | |
| } // namespace egl | |
| } // namespace impeller |