| // 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 |