blob: c2d0ecd759a1be0eb0ec661a435a5358853c88e7 [file] [log] [blame] [edit]
// 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