Files
Mujoco_WASM/src/experimental/platform/hal/egl_utils.cc
T
Matija Kecman 9f3babd60c Group platform components into descriptive subfolders
PiperOrigin-RevId: 895832492
Change-Id: I6cc56b0e4b002b2998579cde95f4b88dfbd88184
2026-04-07 04:58:32 -07:00

157 lines
4.8 KiB
C++

// Copyright 2026 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "experimental/platform/hal/egl_utils.h"
#include <memory>
#if __has_include("third_party/GL/gl/include/EGL/egl.h")
#define MUJOCO_HAS_EGL
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
#include <mujoco/mujoco.h>
namespace mujoco::platform {
#ifdef MUJOCO_HAS_EGL
static EGLDisplay CreateInitializedEglDisplay() {
auto eglQueryDevicesEXT =
(PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT");
auto eglGetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress(
"eglGetPlatformDisplayEXT");
if (!eglQueryDevicesEXT || !eglGetPlatformDisplayEXT) {
mju_error("Failed to load EGL functions");
return EGL_NO_DISPLAY;
}
// Query all available EGL devices.
constexpr int kMaxDevices = 32;
EGLDeviceEXT devices[kMaxDevices];
int ndevice = 0;
if (!eglQueryDevicesEXT(kMaxDevices, devices, &ndevice)) {
mju_error("eglQueryDevices error: 0x%x", eglGetError());
return EGL_NO_DISPLAY;
}
// Initialize the first valid EGL display.
for (int i = 0; i < ndevice; ++i) {
EGLDisplay display =
eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[i], nullptr);
if (display != EGL_NO_DISPLAY) {
int major, minor;
EGLBoolean initialized = eglInitialize(display, &major, &minor);
if (initialized) {
return display;
}
}
}
mju_error("Failed to create and initialize a valid EGL display!");
return EGL_NO_DISPLAY;
}
static EGLContext InitializeEglContext(EGLDisplay display) {
constexpr EGLint config_attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_DEPTH_SIZE,
24,
EGL_STENCIL_SIZE,
8,
EGL_COLOR_BUFFER_TYPE,
EGL_RGB_BUFFER,
EGL_SURFACE_TYPE,
EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_BIT,
EGL_NONE};
EGLint nconfig;
EGLConfig config;
if (!eglChooseConfig(display, config_attribs, &config, 1, &nconfig)) {
mju_error("eglChooseConfig error: 0x%x", eglGetError());
}
// Bind the OpenGL API to the EGL.
if (!eglBindAPI(EGL_OPENGL_API)) {
mju_error("eglBindAPI error: 0x%x", eglGetError());
}
// Create an EGL context.
constexpr EGLint context_attribs[] = {
EGL_CONTEXT_MAJOR_VERSION,
1,
EGL_CONTEXT_MINOR_VERSION,
5,
EGL_CONTEXT_OPENGL_PROFILE_MASK,
EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
EGL_NONE};
EGLContext context =
eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs);
if (context == EGL_NO_CONTEXT) {
mju_error("eglCreateContext error: 0x%x", eglGetError());
return EGL_NO_CONTEXT;
}
// Make the EGL context current.
if (!eglMakeCurrent(display, nullptr, nullptr, context)) {
mju_error("eglMakeCurrent error: 0x%x", eglGetError());
return EGL_NO_CONTEXT;
}
return context;
}
struct EglContext {
EglContext() {
display_ = CreateInitializedEglDisplay();
context_ = InitializeEglContext(display_);
}
~EglContext() {
if (context_ != EGL_NO_CONTEXT) {
eglMakeCurrent(display_, nullptr, nullptr, EGL_NO_CONTEXT);
eglDestroyContext(display_, context_);
context_ = EGL_NO_CONTEXT;
}
if (display_ != EGL_NO_DISPLAY) {
eglTerminate(display_);
display_ = EGL_NO_DISPLAY;
}
}
EGLDisplay display_;
EGLContext context_;
};
#endif // MUJOCO_HAS_EGL
std::shared_ptr<void> CreateEglContext() {
#ifdef MUJOCO_HAS_EGL
auto egl_context = std::make_shared<EglContext>();
return std::static_pointer_cast<void>(egl_context);
#else
mju_error("EGL is not supported");
return nullptr;
#endif
}
} // namespace mujoco::platform