Migrate software rendering stack from OSMesa to EGL Surfaceless.

- Removed OSMesa support and associated files (PlatformOSMesa, BlueGLOSMesa).
- Implemented universal EGL Surfaceless support for macOS and Linux.
- Added BlueEGL dynamic loading layer to resolve EGL symbols at runtime, removing link-time dependency on libEGL.
- Patched Mesa build system for macOS to support EGL without X11 or DRI3.
- Added workaround for Mesa/macOS multi-threaded shader specialization issues by forcing synchronous compilation.
- Correctly filter Vulkan instance extensions to avoid crashes on non-Metal drivers.
- Verified rendering correctness via renderdiff on macOS using llvmpipe (OpenGL and WebGPU).
This commit is contained in:
Powei Feng
2026-03-23 23:51:16 -07:00
parent 859d930f60
commit f731abd17a
24 changed files with 423 additions and 497 deletions

View File

@@ -33,7 +33,7 @@ option(FILAMENT_SUPPORTS_XCB "Include XCB support in Linux builds" ON)
option(FILAMENT_SUPPORTS_XLIB "Include XLIB support in Linux builds" ON)
option(FILAMENT_SUPPORTS_EGL_ON_LINUX "Use EGL for OpenGL in Linux builds" OFF)
option(FILAMENT_SUPPORTS_EGL_ON_DESKTOP "Use EGL for OpenGL in Linux builds" OFF)
option(FILAMENT_SUPPORTS_WAYLAND "Include Wayland support in Linux builds" OFF)
@@ -51,8 +51,6 @@ option(FILAMENT_ENABLE_FEATURE_LEVEL_0 "Enable Feature Level 0" ON)
option(FILAMENT_ENABLE_MULTIVIEW "Enable multiview for Filament" OFF)
option(FILAMENT_SUPPORTS_OSMESA "Enable OSMesa (headless GL context) for Filament" OFF)
option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
option(FILAMENT_USE_ABSEIL_LOGGING "Use Abseil to log, may increase binary size" OFF)
@@ -157,23 +155,13 @@ else()
set(LINUX FALSE)
endif()
if (NOT FILAMENT_OSMESA_PATH STREQUAL "")
if (NOT EXISTS ${FILAMENT_OSMESA_PATH}/)
message(FATAL_ERROR "Cannot find specified OSMesa build directory: ${FILAMENT_OSMESA_PATH}")
endif()
set(FILAMENT_SUPPORTS_OSMESA TRUE)
endif()
if (LINUX)
if (FILAMENT_SUPPORTS_WAYLAND)
add_definitions(-DFILAMENT_SUPPORTS_WAYLAND)
set(FILAMENT_SUPPORTS_X11 FALSE)
elseif (FILAMENT_SUPPORTS_EGL_ON_LINUX)
add_definitions(-DFILAMENT_SUPPORTS_EGL_ON_LINUX)
elseif (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
add_definitions(-DFILAMENT_SUPPORTS_EGL_ON_DESKTOP)
set(FILAMENT_SUPPORTS_X11 FALSE)
elseif (FILAMENT_SUPPORTS_OSMESA)
set(FILAMENT_SUPPORTS_X11 FALSE)
add_definitions(-DFILAMENT_SUPPORTS_OSMESA)
else ()
if (FILAMENT_SUPPORTS_XCB)
add_definitions(-DFILAMENT_SUPPORTS_XCB)
@@ -203,8 +191,8 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS AND NOT FILAMENT_LINUX_IS_MOBILE)
endif()
if (APPLE)
if (FILAMENT_SUPPORTS_OSMESA)
add_definitions(-DFILAMENT_SUPPORTS_OSMESA)
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
add_definitions(-DFILAMENT_SUPPORTS_EGL_ON_DESKTOP)
endif()
endif()
@@ -362,7 +350,7 @@ if (FILAMENT_USE_EXTERNAL_GLES3)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFILAMENT_USE_EXTERNAL_GLES3")
endif()
if (FILAMENT_SUPPORTS_EGL_ON_LINUX)
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
set(EGL TRUE)
endif()
@@ -1005,3 +993,4 @@ endif()
if ((NOT CMAKE_CROSSCOMPILING AND NOT FILAMENT_IMPORT_PREBUILT_EXECUTABLES) OR FILAMENT_EXPORT_PREBUILT_EXECUTABLES)
export(TARGETS matc cmgen filamesh mipgen resgen uberz glslminifier FILE ${IMPORT_EXECUTABLES})
endif()

View File

@@ -198,7 +198,7 @@ VULKAN_ANDROID_GRADLE_OPTION=""
WEBGPU_OPTION="-DFILAMENT_SUPPORTS_WEBGPU=OFF"
WEBGPU_ANDROID_GRADLE_OPTION=""
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=OFF"
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_DESKTOP=OFF"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
MATDBG_GRADLE_OPTION=""
@@ -216,8 +216,6 @@ BACKEND_DEBUG_FLAG_OPTION=""
STEREOSCOPIC_OPTION=""
OSMESA_OPTION=""
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
@@ -308,7 +306,7 @@ function build_desktop_target {
${IMPORT_EXECUTABLES_DIR_OPTION} \
-DCMAKE_BUILD_TYPE="$1" \
-DCMAKE_INSTALL_PREFIX="../${lc_target}/filament" \
${EGL_ON_LINUX_OPTION} \
${EGL_ON_DESKTOP_OPTION} \
${FGVIEWER_OPTION} \
${WEBGPU_OPTION} \
${MATDBG_OPTION} \
@@ -317,7 +315,6 @@ function build_desktop_target {
${COVERAGE_OPTION} \
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
${OSMESA_OPTION} \
${architectures} \
../..
ln -sf "out/cmake-${lc_target}/compile_commands.json" \
@@ -858,7 +855,7 @@ function check_debug_release_build {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
while getopts ":hacCfgimp:q:uvWslwE:dtk:bVx:S:X:Py:" opt; do
case ${opt} in
h)
print_help
@@ -987,10 +984,6 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
IOS_BUILD_SIMULATOR=true
echo "iOS simulator support enabled."
;;
e)
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=ON -DFILAMENT_SKIP_SDL2=ON -DFILAMENT_SKIP_SAMPLES=ON"
echo "EGL on Linux support enabled; skipping SDL2."
;;
l)
IOS_BUILD_SIMULATOR=true
BUILD_UNIVERSAL_LIBRARIES=true
@@ -1025,7 +1018,7 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
exit 1
esac
;;
X) OSMESA_OPTION="-DFILAMENT_OSMESA_PATH=${OPTARG}"
E) EGL_ON_DESKTOP_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_DESKTOP=ON -DFILAMENT_EGL_PATH=${OPTARG}"
;;
y)
ISSUE_SPLIT_BUILD=true

View File

@@ -137,9 +137,12 @@ mkdir -p out
source ${ORIG_DIR}/venv/bin/activate
if [[ "$OS_NAME" == "Darwin" ]]; then
LOCAL_LDFLAGS="-L/opt/homebrew/opt/llvm@${LLVM_VERSION}/lib"
LOCAL_CPPFLAGS="-I/opt/homebrew/opt/llvm@${LLVM_VERSION}/include -I/opt/homebrew/include"
LOCAL_PATH=${PATH}:/opt/homebrew/opt/llvm@${LLVM_VERSION}/bin
# Ensure Homebrew and LLVM paths are correctly set for the linker and compiler
HOMEBREW_PREFIX=$(brew --prefix)
LOCAL_LDFLAGS="-L${HOMEBREW_PREFIX}/lib -L${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/lib"
LOCAL_CPPFLAGS="-I${HOMEBREW_PREFIX}/include -I${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/include"
LOCAL_PATH=${PATH}:${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/bin
LOCAL_PKG_CONFIG_PATH="${HOMEBREW_PREFIX}/lib/pkgconfig:${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/lib/pkgconfig"
# This is necessary to be able to build vk (lavapipe) on macOS. Doesn't seem like a real dependency.
sed -I '' "s/error('Vulkan drivers require dri3 for X11 support')//g" meson.build
@@ -148,13 +151,39 @@ if [[ "$OS_NAME" == "Darwin" ]]; then
sed -I '' "s/dep_xcb_present = null_dep/dep_xcb_present = dependency('xcb-present')/g" meson.build
fi
# Modify mesa to allow building EGL surfaceless without X11 or DRI
python3 - <<EOF
import os
path = 'meson.build'
with open(path, 'r') as f:
content = f.read()
content = content.replace(
"""with_egl = get_option('egl') \\
.require(with_platform_windows or with_platform_haiku or with_dri or with_platform_android, error_message : 'EGL requires DRI, Haiku, Windows or Android') \\
.require(with_shared_glapi, error_message : 'EGL requires shared-glapi') \\
.require(with_glx != 'xlib', error_message :'EGL requires DRI, but GLX is being built with xlib support') \\
.disable_auto_if(with_platform_haiku) \\
.allowed()""",
"""with_egl = get_option('egl') \\
.require(with_shared_glapi, error_message : 'EGL requires shared-glapi') \\
.disable_auto_if(with_platform_haiku) \\
.allowed()"""
)
content = content.replace(
"with_dri = false",
"with_dri = true"
)
with open(path, 'w') as f:
f.write(content)
EOF
# -Dosmesa=true => builds OSMesa, which is an offscreen GL context
# -Dgallium-drivers=swrast => builds GL software rasterizer
# -Dvulkan-drivers=swrast => builds VK software rasterizer
# -Dgallium-drivers=llvmpipe is needed for GL >= 4.1 pipe-screen (see src/gallium/auxiliary/target-helpers/inline_sw_helper.h)
PKG_CONFIG_PATH=${LOCAL_PKG_CONFIG_PATH} PATH=${LOCAL_PATH} \
CXX=${LOCAL_CXX} CC=${LOCAL_CC} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
meson setup --wipe builddir/ -Dprefix="${MESA_DIR}/out" -Dglx=xlib -Dosmesa=true -Dgallium-drivers=llvmpipe,swrast -Dvulkan-drivers=swrast
meson setup --wipe builddir/ -Dprefix="${MESA_DIR}/out" -Dglx=disabled -Degl=enabled -Dosmesa=false -Dplatforms= -Dgallium-drivers=llvmpipe,swrast -Dvulkan-drivers=swrast -Dshared-glapi=enabled
PKG_CONFIG_PATH=${LOCAL_PKG_CONFIG_PATH} PATH=${LOCAL_PATH} \
CXX=${LOCAL_CXX} CC=${LOCAL_CC} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
meson install -C builddir/

View File

@@ -116,8 +116,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaTouchGL.mm)
list(APPEND SRCS src/opengl/platforms/CocoaTouchExternalImage.mm)
elseif (APPLE)
if (FILAMENT_SUPPORTS_OSMESA)
list(APPEND SRCS src/opengl/platforms/PlatformOSMesa.cpp)
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
list(APPEND SRCS src/opengl/platforms/PlatformEGLHeadless.cpp)
else()
list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
list(APPEND SRCS src/opengl/platforms/CocoaExternalImage.mm)
@@ -127,10 +127,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3)
elseif (LINUX)
if (FILAMENT_SUPPORTS_X11)
list(APPEND SRCS src/opengl/platforms/PlatformGLX.cpp)
elseif (FILAMENT_SUPPORTS_EGL_ON_LINUX)
elseif (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
list(APPEND SRCS src/opengl/platforms/PlatformEGLHeadless.cpp)
elseif (FILAMENT_SUPPORTS_OSMESA)
list(APPEND SRCS src/opengl/platforms/PlatformOSMesa.cpp)
endif()
elseif (WIN32)
list(APPEND SRCS src/opengl/platforms/PlatformWGL.cpp)
@@ -449,9 +447,6 @@ endif()
if (LINUX)
target_link_libraries(${TARGET} PRIVATE dl)
if(FILAMENT_SUPPORTS_EGL_ON_LINUX)
target_link_libraries(${TARGET} PUBLIC EGL)
endif()
endif()
# ==================================================================================================
@@ -487,12 +482,9 @@ set(LINUX_LINKER_OPTIMIZATION_FLAGS
-Wl,--exclude-libs,bluegl
)
if (FILAMENT_SUPPORTS_OSMESA)
if (LINUX)
set(OSMESA_COMPILE_FLAGS -I${FILAMENT_OSMESA_PATH}/include/GL)
elseif (APPLE)
set(OSMESA_COMPILE_FLAGS -I${FILAMENT_OSMESA_PATH}/include)
endif()
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP AND NOT FILAMENT_EGL_PATH STREQUAL "")
target_include_directories(${TARGET} PRIVATE ${FILAMENT_EGL_PATH}/include)
target_include_directories(${TARGET} PRIVATE ${FILAMENT_EGL_PATH}/../include)
endif()
if (MSVC)

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* 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.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_OSMESA_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_OSMESA_H
#include <stdint.h>
#include "bluegl/BlueGL.h"
#if defined(__linux__)
#include <osmesa.h>
#elif defined(__APPLE__)
#undef GLAPI
#include <GL/osmesa.h>
#endif
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
namespace filament::backend {
/**
* A concrete implementation of OpenGLPlatform that uses OSMesa, which is an offscreen
* context that can be used in conjunction with Mesa for software rasterization.
* See https://docs.mesa3d.org/osmesa.html for more information.
*/
class PlatformOSMesa : public OpenGLPlatform {
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedGLContext, const DriverConfig& driverConfig) override;
int getOSVersion() const noexcept final override { return 0; }
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain,
SwapChain* readSwapChain) override;
void commit(SwapChain* swapChain) noexcept override;
private:
OSMesaContext mContext;
void* mOsMesaApi = nullptr;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_OSMESA_H

View File

@@ -44,8 +44,8 @@
#endif
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#if defined(FILAMENT_SUPPORTS_OSMESA)
#include <backend/platforms/PlatformOSMesa.h>
#if defined(FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
#include <backend/platforms/PlatformEGLHeadless.h>
#else
#include <backend/platforms/PlatformCocoaGL.h>
#endif
@@ -55,14 +55,10 @@
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformGLX.h"
#endif
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
#elif defined(FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformEGLHeadless.h"
#endif
#elif defined(FILAMENT_SUPPORTS_OSMESA)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformOSMesa.h"
#endif
#endif
#elif defined(WIN32)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
@@ -175,18 +171,16 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
#elif defined(FILAMENT_IOS)
return new PlatformCocoaTouchGL();
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OSMESA)
return new PlatformOSMesa();
#if defined(FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
return new PlatformEGLHeadless();
#else
return new PlatformCocoaGL();
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_X11)
return new PlatformGLX();
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
#elif defined(FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
return new PlatformEGLHeadless();
#elif defined(FILAMENT_SUPPORTS_OSMESA)
return new PlatformOSMesa();
#else
return nullptr;
#endif

View File

@@ -222,6 +222,17 @@ void ShaderCompilerService::init() noexcept {
}
if (mMode == Mode::THREAD_POOL) {
char const* const renderer = mDriver.getContext().state.renderer;
#ifdef __APPLE__
if (UTILS_UNLIKELY(strstr(renderer, "Mesa") || strstr(renderer, "llvmpipe"))) {
// Mesa on macOS has issues with shared contexts and shader specialization/linking
// across threads, leading to "linking with uncompiled/unspecialized shader" errors.
mMode = Mode::SYNCHRONOUS;
return;
}
#endif
// - on Adreno there is a single compiler object. We can't use a pool > 1
// also glProgramBinary blocks if other threads are compiling.
// - on Mali shader compilation can be multithreaded, but program linking happens on
@@ -237,7 +248,6 @@ void ShaderCompilerService::init() noexcept {
uint32_t poolSize = 1;
JobSystem::Priority priority = JobSystem::Priority::DISPLAY;
auto const& renderer = mDriver.getContext().state.renderer;
// Some drivers support parallel shader compilation well, so we use N
// threads, we can use lower priority threads here because urgent compilations
// will most likely happen on the main gl thread. Using too many thread can

View File

@@ -37,7 +37,7 @@
*/
#if defined(__ANDROID__) || defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(__EMSCRIPTEN__) || defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
#if defined(__ANDROID__) || defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(__EMSCRIPTEN__) || (defined(FILAMENT_SUPPORTS_EGL_ON_DESKTOP) && defined(__linux__))
#if defined(__EMSCRIPTEN__)
# include <GLES3/gl3.h>
@@ -62,7 +62,6 @@
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#else
// bluegl exposes symbols prefixed with bluegl_ to avoid clashing with clients that also link
@@ -74,6 +73,11 @@
#include <bluegl/BlueGLDefines.h>
#include <bluegl/BlueGL.h>
extern "C" {
void glFramebufferTextureMultiviewOVR(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
void glFramebufferTextureMultisampleMultiviewOVR(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
}
#endif
/* Validate the header configurations we aim to support */

View File

@@ -23,9 +23,7 @@
#include <backend/Platform.h>
#include <backend/DriverEnums.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <bluegl/BlueEGL.h>
#if defined(__ANDROID__)
#include <sys/system_properties.h>
@@ -130,7 +128,20 @@ void PlatformEGL::setEglDisplay(EGLDisplay display) noexcept {
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) {
if (mEGLDisplay == EGL_NO_DISPLAY) {
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglBindAPI(EGL_OPENGL_API);
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
if (getPlatformDisplayEXT) {
// 0x31DD is EGL_PLATFORM_SURFACELESS_MESA
mEGLDisplay = getPlatformDisplayEXT(0x31DD, (void*)EGL_DEFAULT_DISPLAY, nullptr);
}
if (mEGLDisplay == EGL_NO_DISPLAY) {
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
EGLint major, minor;
@@ -196,9 +207,11 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& drive
Config contextAttribs;
if (isOpenGL()) {
// Request a OpenGL 4.1 context
// Request a OpenGL 4.1 Core Profile context
contextAttribs[EGL_CONTEXT_MAJOR_VERSION] = 4;
contextAttribs[EGL_CONTEXT_MINOR_VERSION] = 1;
contextAttribs[EGL_CONTEXT_OPENGL_PROFILE_MASK] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
contextAttribs[EGL_CONTEXT_FLAGS_KHR] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
} else {
// Request a ES2 context, devices that support ES3 will return an ES3 context
contextAttribs[EGL_CONTEXT_CLIENT_VERSION] = 2;
@@ -717,11 +730,20 @@ bool PlatformEGL::setExternalImage(ExternalImageHandleRef externalImage,
// -----------------------------------------------------------------------------------------------
void PlatformEGL::initializeGlExtensions() noexcept {
const char* const extensions = (const char*)glGetString(GL_EXTENSIONS);
if (extensions) {
GLUtils::unordered_string_set const glExtensions = GLUtils::split(extensions);
ext.gl.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
GLUtils::unordered_string_set glExtensions;
if (isOpenGL()) {
GLint n = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for (GLint i = 0; i < n; i++) {
glExtensions.emplace((const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i));
}
} else {
const char* const extensions = (const char*)glGetString(GL_EXTENSIONS);
if (extensions) {
glExtensions = GLUtils::split(extensions);
}
}
ext.gl.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
}
EGLContext PlatformEGL::getContextForType(ContextType const type) const noexcept {

View File

@@ -17,9 +17,7 @@
#include <backend/platforms/PlatformEGLHeadless.h>
#include <bluegl/BlueGL.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <bluegl/BlueEGL.h>
#include <utils/Logger.h>
#include <utils/Panic.h>
@@ -44,6 +42,12 @@ bool PlatformEGLHeadless::isOpenGL() const noexcept {
backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) {
int bindBlueGL = bluegl::bind();
if (UTILS_UNLIKELY(bindBlueGL != 0)) {
LOG(ERROR) << "bluegl bind failed";
return nullptr;
}
auto bindApiHelper = [](EGLenum api, const char* errorString) -> bool {
EGLBoolean bindAPI = eglBindAPI(api);
if (UTILS_UNLIKELY(bindAPI == EGL_FALSE || bindAPI == EGL_BAD_PARAMETER)) {
@@ -60,12 +64,6 @@ backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext,
return nullptr;
}
int bindBlueGL = bluegl::bind();
if (UTILS_UNLIKELY(bindBlueGL != 0)) {
LOG(ERROR) << "bluegl bind failed";
return nullptr;
}
return PlatformEGL::createDriver(sharedContext, driverConfig);
}

View File

@@ -1,187 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* 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 <backend/platforms/PlatformOSMesa.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <dlfcn.h>
#include <memory>
#if defined(__linux__)
// This is to ensure that linking during compilation will not fail even if
// OSMesaGetProcAddress is not linked.
__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
#endif
namespace filament::backend {
using namespace backend;
namespace {
using BackingType = GLfloat;
#define BACKING_GL_TYPE GL_FLOAT
struct OSMesaSwapchain {
OSMesaSwapchain(uint32_t width, uint32_t height)
: width(width),
height(height),
buffer(new uint8_t[width * height * 4 * sizeof(BackingType)]) {}
uint32_t width = 0;
uint32_t height = 0;
std::unique_ptr<uint8_t[]> buffer;
};
struct OSMesaAPI {
private:
using CreateContextAttribsFunc = OSMesaContext (*)(const int *, OSMesaContext);
using DestroyContextFunc = GLboolean (*)(OSMesaContext);
using MakeCurrentFunc = GLboolean (*)(OSMesaContext ctx, void* buffer, GLenum type,
GLsizei width, GLsizei height);
using GetProcAddressFunc = OSMESAproc (*)(const char* funcName);
public:
CreateContextAttribsFunc fOSMesaCreateContextAttribs;
DestroyContextFunc fOSMesaDestroyContext;
MakeCurrentFunc fOSMesaMakeCurrent;
GetProcAddressFunc fOSMesaGetProcAddress;
OSMesaAPI() {
static constexpr char const* libraryNames[] = {
#if defined(__linux__)
"libOSMesa.so",
"libosmesa.so",
#elif defined(__APPLE__)
"libOSMesa.dylib",
#endif
};
for (char const* libName: libraryNames) {
mLib = dlopen(libName, RTLD_GLOBAL | RTLD_NOW);
if (mLib) {
break;
}
}
if (mLib) {
// Loading from a libosmesa.os
fOSMesaGetProcAddress = (GetProcAddressFunc) dlsym(mLib, "OSMesaGetProcAddress");
}
#if defined(__linux__)
else {
// Filament is built into a .so
fOSMesaGetProcAddress = (GetProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
}
if (!fOSMesaGetProcAddress) {
// Statically linking osmesa
fOSMesaGetProcAddress = OSMesaGetProcAddress;
}
#endif // __linux__
FILAMENT_CHECK_PRECONDITION(fOSMesaGetProcAddress)
<< "Unable to link against libOSMesa to create a software GL context";
fOSMesaCreateContextAttribs =
(CreateContextAttribsFunc) fOSMesaGetProcAddress("OSMesaCreateContextAttribs");
fOSMesaDestroyContext = (DestroyContextFunc) fOSMesaGetProcAddress("OSMesaDestroyContext");
fOSMesaMakeCurrent = (MakeCurrentFunc) fOSMesaGetProcAddress("OSMesaMakeCurrent");
}
~OSMesaAPI() {
if (mLib) {
dlclose(mLib);
}
}
private:
void* mLib = nullptr;
};
}// anonymous namespace
Driver* PlatformOSMesa::createDriver(void* sharedGLContext,
const DriverConfig& driverConfig) {
OSMesaAPI* api = new OSMesaAPI();
mOsMesaApi = api;
static constexpr int attribs[] = {
OSMESA_FORMAT, GL_RGBA,
OSMESA_DEPTH_BITS, 24,
OSMESA_STENCIL_BITS, 8,
OSMESA_ACCUM_BITS, 0,
OSMESA_PROFILE, OSMESA_CORE_PROFILE,
0,
};
FILAMENT_CHECK_PRECONDITION(sharedGLContext == nullptr)
<< "shared GL context is not supported with PlatformOSMesa";
mContext = api->fOSMesaCreateContextAttribs(attribs, NULL);
// We need to do a no-op makecurrent here so that the context will be in a correct state before
// any GL calls.
auto chain = createSwapChain(1, 1, 0);
makeCurrent(ContextType::UNPROTECTED, chain, nullptr);
destroySwapChain(chain);
int result = bluegl::bind();
FILAMENT_CHECK_POSTCONDITION(!result) << "Unable to load OpenGL entry points.";
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
}
void PlatformOSMesa::terminate() noexcept {
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
api->fOSMesaDestroyContext(mContext);
delete api;
mOsMesaApi = nullptr;
bluegl::unbind();
}
Platform::SwapChain* PlatformOSMesa::createSwapChain(void* nativeWindow, uint64_t flags) noexcept {
FILAMENT_CHECK_POSTCONDITION(false) << "Cannot create non-headless swapchain";
return (SwapChain*) nativeWindow;
}
Platform::SwapChain* PlatformOSMesa::createSwapChain(uint32_t width, uint32_t height,
uint64_t flags) noexcept {
OSMesaSwapchain* swapchain = new OSMesaSwapchain(width, height);
return (SwapChain*) swapchain;
}
void PlatformOSMesa::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
OSMesaSwapchain* impl = (OSMesaSwapchain*) swapChain;
delete impl;
}
bool PlatformOSMesa::makeCurrent(ContextType type, SwapChain* drawSwapChain,
SwapChain* readSwapChain) {
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
OSMesaSwapchain* impl = (OSMesaSwapchain*) drawSwapChain;
auto result = api->fOSMesaMakeCurrent(mContext, (BackingType*) impl->buffer.get(),
BACKING_GL_TYPE, impl->width, impl->height);
FILAMENT_CHECK_POSTCONDITION(result == GL_TRUE) << "OSMesaMakeCurrent failed!";
return true;
}
void PlatformOSMesa::commit(Platform::SwapChain* swapChain) noexcept {
// No-op since we are not scanning out to a display.
}
} // namespace filament::backend

View File

@@ -580,7 +580,11 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
}
#endif
instExts.merge(getRequiredInstanceExtensions());
ExtensionSet const requiredExts = getRequiredInstanceExtensions();
ExtensionSet const filteredRequiredExts = getInstanceExtensions(requiredExts);
for (auto const& extension : filteredRequiredExts) {
instExts.insert(extension);
}
}
if (mImpl->mInstance == VK_NULL_HANDLE) {
createInstance(instExts);

View File

@@ -37,6 +37,7 @@ namespace filament::backend {
VulkanPlatform::ExtensionSet VulkanPlatformApple::getSwapchainInstanceExtensions() const {
ExtensionSet const ret = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_EXT_METAL_SURFACE_EXTENSION_NAME,
};
return ret;

View File

@@ -31,17 +31,15 @@ if (WIN32)
set(SRCS ${SRCS} src/BlueGLCoreWindowsImpl.S)
endif()
elseif (APPLE AND NOT IOS)
if (FILAMENT_SUPPORTS_OSMESA)
set(SRCS ${SRCS} src/BlueGLOSMesa.cpp)
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
set(SRCS ${SRCS} src/BlueGLEGL.cpp)
else()
set(SRCS ${SRCS} src/BlueGLDarwin.cpp)
endif()
set(SRCS ${SRCS} src/BlueGLCoreDarwinUniversalImpl.S)
elseif(LINUX)
if (FILAMENT_SUPPORTS_EGL_ON_LINUX)
set(SRCS ${SRCS} src/BlueGLLinuxEGL.cpp)
elseif (FILAMENT_SUPPORTS_OSMESA)
set(SRCS ${SRCS} src/BlueGLOSMesa.cpp)
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP)
set(SRCS ${SRCS} src/BlueGLEGL.cpp)
else()
set(SRCS ${SRCS} src/BlueGLLinux.cpp)
endif()
@@ -56,18 +54,15 @@ include_directories(${PUBLIC_HDR_DIR})
# we're building a library
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
if(FILAMENT_SUPPORTS_OSMESA)
if (APPLE)
target_compile_options(${TARGET} PRIVATE -I${FILAMENT_OSMESA_PATH}/include)
else()
target_compile_options(${TARGET} PRIVATE -I${FILAMENT_OSMESA_PATH}/include/GL)
endif()
endif()
# specify where the public headers of this library are
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
if (FILAMENT_SUPPORTS_EGL_ON_DESKTOP AND NOT FILAMENT_EGL_PATH STREQUAL "")
target_include_directories(${TARGET} PRIVATE ${FILAMENT_EGL_PATH}/include)
target_include_directories(${TARGET} PRIVATE ${FILAMENT_EGL_PATH}/../include)
endif()
if (WIN32)
target_link_libraries(${TARGET} PRIVATE opengl32 gdi32)
endif()

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* 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.
*/
#ifndef TNT_BLUEGL_BLUEEGL_H
#define TNT_BLUEGL_BLUEEGL_H
#include <EGL/egl.h>
#include <EGL/eglext.h>
#ifdef __cplusplus
extern "C" {
#endif
#define EGL_PLATFORM_SURFACELESS_MESA 0x31DD
extern void* bluegl_eglGetProcAddress;
extern void* bluegl_eglGetDisplay;
extern void* bluegl_eglInitialize;
extern void* bluegl_eglTerminate;
extern void* bluegl_eglBindAPI;
extern void* bluegl_eglCreateContext;
extern void* bluegl_eglDestroyContext;
extern void* bluegl_eglMakeCurrent;
extern void* bluegl_eglCreatePbufferSurface;
extern void* bluegl_eglCreateWindowSurface;
extern void* bluegl_eglDestroySurface;
extern void* bluegl_eglSurfaceAttrib;
extern void* bluegl_eglSwapBuffers;
extern void* bluegl_eglQueryString;
extern void* bluegl_eglChooseConfig;
extern void* bluegl_eglGetConfigAttrib;
extern void* bluegl_eglGetConfigs;
extern void* bluegl_eglGetCurrentContext;
extern void* bluegl_eglReleaseThread;
extern void* bluegl_eglGetError;
extern void* bluegl_eglGetPlatformDisplayEXT;
#if !defined(__ANDROID__)
#ifdef eglGetProcAddress
#undef eglGetProcAddress
#endif
#define eglGetProcAddress ((PFNEGLGETPROCADDRESSPROC)bluegl_eglGetProcAddress)
#ifdef eglGetDisplay
#undef eglGetDisplay
#endif
#define eglGetDisplay ((PFNEGLGETDISPLAYPROC)bluegl_eglGetDisplay)
#ifdef eglInitialize
#undef eglInitialize
#endif
#define eglInitialize ((PFNEGLINITIALIZEPROC)bluegl_eglInitialize)
#ifdef eglTerminate
#undef eglTerminate
#endif
#define eglTerminate ((PFNEGLTERMINATEPROC)bluegl_eglTerminate)
#ifdef eglBindAPI
#undef eglBindAPI
#endif
#define eglBindAPI ((PFNEGLBINDAPIPROC)bluegl_eglBindAPI)
#ifdef eglCreateContext
#undef eglCreateContext
#endif
#define eglCreateContext ((PFNEGLCREATECONTEXTPROC)bluegl_eglCreateContext)
#ifdef eglDestroyContext
#undef eglDestroyContext
#endif
#define eglDestroyContext ((PFNEGLDESTROYCONTEXTPROC)bluegl_eglDestroyContext)
#ifdef eglMakeCurrent
#undef eglMakeCurrent
#endif
#define eglMakeCurrent ((PFNEGLMAKECURRENTPROC)bluegl_eglMakeCurrent)
#ifdef eglCreatePbufferSurface
#undef eglCreatePbufferSurface
#endif
#define eglCreatePbufferSurface ((PFNEGLCREATEPBUFFERSURFACEPROC)bluegl_eglCreatePbufferSurface)
#ifdef eglCreateWindowSurface
#undef eglCreateWindowSurface
#endif
#define eglCreateWindowSurface ((PFNEGLCREATEWINDOWSURFACEPROC)bluegl_eglCreateWindowSurface)
#ifdef eglDestroySurface
#undef eglDestroySurface
#endif
#define eglDestroySurface ((PFNEGLDESTROYSURFACEPROC)bluegl_eglDestroySurface)
#ifdef eglSurfaceAttrib
#undef eglSurfaceAttrib
#endif
#define eglSurfaceAttrib ((PFNEGLSURFACEATTRIBPROC)bluegl_eglSurfaceAttrib)
#ifdef eglSwapBuffers
#undef eglSwapBuffers
#endif
#define eglSwapBuffers ((PFNEGLSWAPBUFFERSPROC)bluegl_eglSwapBuffers)
#ifdef eglQueryString
#undef eglQueryString
#endif
#define eglQueryString ((PFNEGLQUERYSTRINGPROC)bluegl_eglQueryString)
#ifdef eglChooseConfig
#undef eglChooseConfig
#endif
#define eglChooseConfig ((PFNEGLCHOOSECONFIGPROC)bluegl_eglChooseConfig)
#ifdef eglGetConfigAttrib
#undef eglGetConfigAttrib
#endif
#define eglGetConfigAttrib ((PFNEGLGETCONFIGATTRIBPROC)bluegl_eglGetConfigAttrib)
#ifdef eglGetConfigs
#undef eglGetConfigs
#endif
#define eglGetConfigs ((PFNEGLGETCONFIGSPROC)bluegl_eglGetConfigs)
#ifdef eglGetCurrentContext
#undef eglGetCurrentContext
#endif
#define eglGetCurrentContext ((PFNEGLGETCURRENTCONTEXTPROC)bluegl_eglGetCurrentContext)
#ifdef eglReleaseThread
#undef eglReleaseThread
#endif
#define eglReleaseThread ((PFNEGLRELEASETHREADPROC)bluegl_eglReleaseThread)
#ifdef eglGetError
#undef eglGetError
#endif
#define eglGetError ((PFNEGLGETERRORPROC)bluegl_eglGetError)
#define eglGetPlatformDisplayEXT ((PFNEGLGETPLATFORMDISPLAYEXTPROC)bluegl_eglGetPlatformDisplayEXT)
#endif // !defined(__ANDROID__)
#ifdef __cplusplus
}
#endif
#endif // TNT_BLUEGL_BLUEEGL_H

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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 <dlfcn.h>
#include <string.h>
#include <stdio.h>
namespace bluegl {
struct Driver {
void* (*eglGetProcAddress)(const char*);
void* library;
void* glapi;
void* glesv2;
} g_driver = {nullptr, nullptr, nullptr, nullptr};
extern "C" {
#define BLUEGL_EGL_STUB(name) \
void* bluegl_##name; \
void* name() { return bluegl_##name; }
void* bluegl_eglGetProcAddress;
void* bluegl_eglGetDisplay;
void* bluegl_eglInitialize;
void* bluegl_eglTerminate;
void* bluegl_eglBindAPI;
void* bluegl_eglCreateContext;
void* bluegl_eglDestroyContext;
void* bluegl_eglMakeCurrent;
void* bluegl_eglCreatePbufferSurface;
void* bluegl_eglCreateWindowSurface;
void* bluegl_eglDestroySurface;
void* bluegl_eglSurfaceAttrib;
void* bluegl_eglSwapBuffers;
void* bluegl_eglQueryString;
void* bluegl_eglChooseConfig;
void* bluegl_eglGetConfigAttrib;
void* bluegl_eglGetConfigs;
void* bluegl_eglGetCurrentContext;
void* bluegl_eglReleaseThread;
void* bluegl_eglGetError;
void* bluegl_eglGetPlatformDisplayEXT;
}
bool initBinder() {
#ifdef __APPLE__
const char* library_name = "libEGL.1.dylib";
const char* glapi_name = "libglapi.0.dylib";
const char* glesv2_name = "libGLESv2.2.dylib";
#else
const char* library_name = "libEGL.so.1";
const char* glapi_name = "libglapi.so.0";
const char* glesv2_name = "libGLESv2.so.2";
#endif
g_driver.library = dlopen(library_name, RTLD_GLOBAL | RTLD_NOW);
if (!g_driver.library) {
return false;
}
g_driver.glapi = dlopen(glapi_name, RTLD_GLOBAL | RTLD_NOW);
g_driver.glesv2 = dlopen(glesv2_name, RTLD_GLOBAL | RTLD_NOW);
g_driver.eglGetProcAddress = (void *(*)(const char *))
dlsym(g_driver.library, "eglGetProcAddress");
#define LOAD_EGL_SYMBOL(name) bluegl_##name = dlsym(g_driver.library, #name)
LOAD_EGL_SYMBOL(eglGetProcAddress);
LOAD_EGL_SYMBOL(eglGetDisplay);
LOAD_EGL_SYMBOL(eglInitialize);
LOAD_EGL_SYMBOL(eglTerminate);
LOAD_EGL_SYMBOL(eglBindAPI);
LOAD_EGL_SYMBOL(eglCreateContext);
LOAD_EGL_SYMBOL(eglDestroyContext);
LOAD_EGL_SYMBOL(eglMakeCurrent);
LOAD_EGL_SYMBOL(eglCreatePbufferSurface);
LOAD_EGL_SYMBOL(eglCreateWindowSurface);
LOAD_EGL_SYMBOL(eglDestroySurface);
LOAD_EGL_SYMBOL(eglSurfaceAttrib);
LOAD_EGL_SYMBOL(eglSwapBuffers);
LOAD_EGL_SYMBOL(eglQueryString);
LOAD_EGL_SYMBOL(eglChooseConfig);
LOAD_EGL_SYMBOL(eglGetConfigAttrib);
LOAD_EGL_SYMBOL(eglGetConfigs);
LOAD_EGL_SYMBOL(eglGetCurrentContext);
LOAD_EGL_SYMBOL(eglReleaseThread);
LOAD_EGL_SYMBOL(eglGetError);
bluegl_eglGetPlatformDisplayEXT = (void*)g_driver.eglGetProcAddress("eglGetPlatformDisplayEXT");
return g_driver.eglGetProcAddress;
}
void* loadFunction(const char* name) {
void* ptr = (void*) g_driver.eglGetProcAddress((const char*) name);
if (!ptr) {
if (g_driver.glesv2) {
ptr = dlsym(g_driver.glesv2, name);
}
if (!ptr && g_driver.glapi) {
ptr = dlsym(g_driver.glapi, name);
}
if (!ptr) {
ptr = dlsym(g_driver.library, name);
}
}
return ptr;
}
void shutdownBinder() {
if (g_driver.library) dlclose(g_driver.library);
if (g_driver.glapi) dlclose(g_driver.glapi);
if (g_driver.glesv2) dlclose(g_driver.glesv2);
memset(&g_driver, 0, sizeof(g_driver));
}
} // namespace bluegl

View File

@@ -1,50 +0,0 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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 <dlfcn.h>
#include <string.h>
namespace bluegl {
struct Driver {
void* (*eglGetProcAddress)(const char*);
void* library;
} g_driver = {nullptr, nullptr};
bool initBinder() {
const char* library_name = "libEGL.so.1";
g_driver.library = dlopen(library_name, RTLD_GLOBAL | RTLD_NOW);
if (!g_driver.library) {
return false;
}
g_driver.eglGetProcAddress = (void *(*)(const char *))
dlsym(g_driver.library, "eglGetProcAddress");
return g_driver.eglGetProcAddress;
}
void* loadFunction(const char* name) {
return (void*) g_driver.eglGetProcAddress((const char*) name);
}
void shutdownBinder() {
dlclose(g_driver.library);
memset(&g_driver, 0, sizeof(g_driver));
}
} // namespace bluegl

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* 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 <dlfcn.h>
#include <string.h>
#if defined(__linux__)
#include <osmesa.h>
// This is to ensure that linking during compilation will not fail even if
// OSMesaGetProcAddress is not linked.
__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
#elif defined(__APPLE__)
#include <GL/osmesa.h>
#endif // __linux__
#if defined(__linux__)
#endif
namespace bluegl {
namespace {
using ProcAddressFunc = void*(*)(char const* funcName);
}
struct Driver {
ProcAddressFunc OSMesaGetProcAddress;
void* library;
} g_driver = {nullptr, nullptr};
bool initBinder() {
static constexpr char const* libraryNames[] = {
#if defined(__linux__)
"libOSMesa.so",
"libosmesa.so",
#elif defined(__APPLE__)
"libOSMesa.dylib",
#endif
};
for (char const* name: libraryNames) {
g_driver.library = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
if (g_driver.library) {
break;
}
}
if (g_driver.library) {
// Linking against a libosmesa.so.
g_driver.OSMesaGetProcAddress =
(ProcAddressFunc) dlsym(g_driver.library, "OSMesaGetProcAddress");
}
#if defined(__linux__)
else {
// If Filament was built as a dynamic library.
g_driver.OSMesaGetProcAddress = (ProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
}
if (!g_driver.OSMesaGetProcAddress) {
// If statically linking OSMesa.
g_driver.OSMesaGetProcAddress = (ProcAddressFunc) OSMesaGetProcAddress;
}
#endif
return g_driver.OSMesaGetProcAddress;
}
void* loadFunction(const char* name) {
return (void*) g_driver.OSMesaGetProcAddress(name);
}
void shutdownBinder() {
if (g_driver.library) {
dlclose(g_driver.library);
}
memset(&g_driver, 0, sizeof(g_driver));
}
} // namespace bluegl

3
lldb_cmds.txt Normal file
View File

@@ -0,0 +1,3 @@
run
bt
quit

View File

@@ -35,7 +35,7 @@ fi
# Build backend_test_mac
echo "Building backend_test_mac..."
"${PROJECT_ROOT_DIR}/build.sh" -W -p desktop -X "${PROJECT_ROOT_DIR}/mesa" debug ${BACKEND_TEST_TARGET}
"${PROJECT_ROOT_DIR}/build.sh" -W -p desktop -E "${PROJECT_ROOT_DIR}/mesa" debug ${BACKEND_TEST_TARGET}
set +e

View File

@@ -40,12 +40,12 @@ function start_render_() {
fi
# -W enables the webgpu build
# -f forces regeneration of cmake build files
# -X points to the mesa directory, which contains the compiled gl and vk drivers.
# -E points to the mesa directory, which contains the compiled gl and vk drivers.
GLTF_VIEWER_PATH="$(pwd)/out/cmake-debug/samples/gltf_viewer"
if [[ "$NOREBUILD" == "true" ]] && [[ -f ${GLTF_VIEWER_PATH} ]]; then
echo "Skipping build of gltf_viewer"
else
CXX=`which clang++` CC=`which clang` ./build.sh -f -W -X ${MESA_DIR} -p desktop debug gltf_viewer
./build.sh -f -W -E ${MESA_DIR} -p desktop debug gltf_viewer
fi
}

Binary file not shown.