blob: c3ba631cf9322452b977ef1ddc0f5a28cd9ab3c5 [file] [log] [blame] [edit]
/*
* Copyright 2021 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gpu/egl/egl_context.h"
#include <utility>
#include <vector>
#include "cros-camera/common.h"
#include "gpu/egl/utils.h"
namespace cros {
// static
std::unique_ptr<EglContext> EglContext::GetSurfacelessContext(
const EglContextOptions& options) {
EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglInitialize(egl_display, /*major=*/nullptr, /*minor=*/nullptr) !=
EGL_TRUE) {
LOGF(ERROR) << "Failed to create EGL display";
return std::make_unique<EglContext>();
}
// This will leak |egl_display|, but it should be okay.
return std::make_unique<EglContext>(egl_display, options);
}
EglContext::EglContext(EGLDisplay display, const EglContextOptions& options)
: display_(display) {
// Bind API.
eglBindAPI(EGL_OPENGL_ES_API);
EGLConfig config = EGL_NO_CONFIG_KHR;
EGLContext share_context = EGL_NO_CONTEXT;
if (options.share_context) {
share_context = options.share_context->Get();
}
std::vector<EGLint> context_attribs = {
EGL_CONTEXT_MAJOR_VERSION,
options.context_major_version,
EGL_CONTEXT_MINOR_VERSION,
options.context_minor_version,
EGL_NONE,
};
context_ =
eglCreateContext(display_, config, share_context, context_attribs.data());
}
EglContext::EglContext(EglContext&& other) {
*this = std::move(other);
}
EglContext& EglContext::operator=(EglContext&& other) {
if (this != &other) {
Invalidate();
display_ = other.display_;
context_ = other.context_;
other.display_ = EGL_NO_DISPLAY;
other.context_ = EGL_NO_CONTEXT;
}
return *this;
}
EglContext::~EglContext() {
Invalidate();
}
bool EglContext::IsCurrent() const {
if (!IsValid()) {
return false;
}
return context_ == eglGetCurrentContext();
}
bool EglContext::MakeCurrent() {
if (!IsValid()) {
LOGF(ERROR) << "Cannot make invalid context current";
return false;
}
EGLSurface draw_surface = EGL_NO_SURFACE;
EGLSurface read_surface = EGL_NO_SURFACE;
EGLBoolean ok =
eglMakeCurrent(display_, draw_surface, read_surface, context_);
EGLint error = eglGetError();
if (error != EGL_SUCCESS) {
LOGF(ERROR) << "Failed to make context current: "
<< EglGetErrorString(error);
}
return ok == EGL_TRUE;
}
void EglContext::Invalidate() {
if (IsValid()) {
if (IsCurrent()) {
eglReleaseThread();
}
if (display_ != EGL_NO_DISPLAY) {
eglDestroyContext(display_, context_);
display_ = EGL_NO_DISPLAY;
}
context_ = EGL_NO_CONTEXT;
}
}
EGLContext EglContext::Get() const {
return context_;
}
} // namespace cros