Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gl: add PlatformOSMesa as an offscreen context #8161

Merged
merged 2 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ 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)

set(FILAMENT_NDK_VERSION "" CACHE STRING
"Android NDK version or version prefix to be used when building for Android."
)
Expand Down Expand Up @@ -73,6 +75,10 @@ set(FILAMENT_BACKEND_DEBUG_FLAG "" CACHE STRING
"A debug flag meant for enabling/disabling backend debugging paths"
)

set(FILAMENT_OSMESA_PATH "" CACHE STRING
"Path to the OSMesa header and lib"
)

# Enable exceptions by default in spirv-cross.
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS OFF)

Expand Down Expand Up @@ -132,12 +138,22 @@ else()
endif()

if (LINUX)
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 (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)
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)
Expand Down
10 changes: 9 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ function print_help {
echo " enabling debug paths in the backend from the build script. For example, make a"
echo " systrace-enabled build without directly changing #defines. Remember to add -f when"
echo " changing this option."
echo " -X osmesa_path"
echo " Indicates a path to a completed OSMesa build. OSMesa is used to create an offscreen GL"
echo " context for software rasterization"
echo " -S type"
echo " Enable stereoscopic rendering where type is one of [instanced|multiview]. This is only"
echo " meant for building the samples."
Expand Down Expand Up @@ -180,6 +183,8 @@ BACKEND_DEBUG_FLAG_OPTION=""

STEREOSCOPIC_OPTION=""

OSMESA_OPTION=""

IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false

Expand Down Expand Up @@ -240,6 +245,7 @@ function build_desktop_target {
${ASAN_UBSAN_OPTION} \
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
${OSMESA_OPTION} \
${architectures} \
../..
ln -sf "out/cmake-${lc_target}/compile_commands.json" \
Expand Down Expand Up @@ -796,7 +802,7 @@ function check_debug_release_build {

pushd "$(dirname "$0")" > /dev/null

while getopts ":hacCfgijmp:q:uvslwedk:bx:S:" opt; do
while getopts ":hacCfgijmp:q:uvslwedk:bx:S:X:" opt; do
case ${opt} in
h)
print_help
Expand Down Expand Up @@ -950,6 +956,8 @@ while getopts ":hacCfgijmp:q:uvslwedk:bx:S:" opt; do
exit 1
esac
;;
X) OSMESA_OPTION="-DFILAMENT_OSMESA_PATH=${OPTARG}"
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
echo ""
Expand Down
13 changes: 13 additions & 0 deletions filament/backend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3)
list(APPEND SRCS src/opengl/platforms/PlatformGLX.cpp)
elseif (FILAMENT_SUPPORTS_EGL_ON_LINUX)
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)
Expand Down Expand Up @@ -361,6 +363,15 @@ set(LINUX_LINKER_OPTIMIZATION_FLAGS
-Wl,--exclude-libs,bluegl
)

if (LINUX AND FILAMENT_SUPPORTS_OSMESA)
set(OSMESA_COMPILE_FLAGS
-I${FILAMENT_OSMESA_PATH}/include/GL)
set(OSMESA_LINKER_FLAGS
-Wl,-L${FILAMENT_OSMESA_PATH}/lib/x86_64-linux-gnu/
-lOSMesa
)
endif()

if (MSVC)
set(FILAMENT_WARNINGS /W3)
else()
Expand All @@ -381,6 +392,7 @@ endif()

target_compile_options(${TARGET} PRIVATE
${FILAMENT_WARNINGS}
${OSMESA_COMPILE_FLAGS}
$<$<CONFIG:Release>:${OPTIMIZATION_FLAGS}>
$<$<AND:$<PLATFORM_ID:Darwin>,$<CONFIG:Release>>:${DARWIN_OPTIMIZATION_FLAGS}>
)
Expand All @@ -390,6 +402,7 @@ if (FILAMENT_SUPPORTS_METAL)
endif()

target_link_libraries(${TARGET} PRIVATE
${OSMESA_LINKER_FLAGS}
$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>:${LINUX_LINKER_OPTIMIZATION_FLAGS}>
)

Expand Down
63 changes: 63 additions & 0 deletions filament/backend/include/backend/platforms/PlatformOSMesa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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"

#include "osmesa.h"

#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) noexcept 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) noexcept override;
void commit(SwapChain* swapChain) noexcept override;

private:
OSMesaContext mContext;
};

} // namespace filament::backend

#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_OSMESA_H
6 changes: 6 additions & 0 deletions filament/backend/src/PlatformFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
#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)
Expand Down Expand Up @@ -124,6 +128,8 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
return new PlatformGLX();
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
return new PlatformEGLHeadless();
#elif defined(FILAMENT_SUPPORTS_OSMESA)
return new PlatformOSMesa();
#else
return nullptr;
#endif
Expand Down
100 changes: 100 additions & 0 deletions filament/backend/src/opengl/platforms/PlatformOSMesa.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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 <memory>

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;
};

} // anonymous namespace

Driver* PlatformOSMesa::createDriver(void* const sharedGLContext,
const DriverConfig& driverConfig) noexcept {
FILAMENT_CHECK_PRECONDITION(sharedGLContext == nullptr)
<< "shared GL context is not supported with PlatformOSMesa";
mContext = OSMesaCreateContext(GL_RGBA, 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 {
OSMesaDestroyContext(mContext);
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) noexcept {
OSMesaSwapchain* impl = (OSMesaSwapchain*) drawSwapChain;

auto result = OSMesaMakeCurrent(mContext, (BackingType*) impl->buffer.get(), BACKING_GL_TYPE,
impl->width, impl->height);
FILAMENT_CHECK_POSTCONDITION(result) << "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
4 changes: 4 additions & 0 deletions third_party/libsdl2/include/SDL_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
#include "SDL_config_linux_wayland.h"
#elif defined(FILAMENT_SUPPORTS_X11)
#include "SDL_config_linux_x11.h"
#elif defined(FILAMENT_SUPPORTS_OSMESA)
// We still want the same defines and libs as x11 but we won't actually
// open any windows.
#include "SDL_config_linux_x11.h"
#endif
#else
/* This is a minimal configuration just to get SDL running on new platforms */
Expand Down
2 changes: 1 addition & 1 deletion third_party/libsdl2/tnt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ if (LINUX)
if (FILAMENT_SUPPORTS_WAYLAND)
file(GLOB SRCS_LINUX_WAYLAND ${SRC_DIR}/video/wayland/*.c)
list(APPEND SRCS ${SRCS_LINUX_WAYLAND})
elseif(FILAMENT_SUPPORTS_X11)
elseif(FILAMENT_SUPPORTS_X11 OR FILAMENT_SUPPORTS_OSMESA)
file(GLOB SRCS_LINUX_X11 ${SRC_DIR}/video/x11/*.c)
list(APPEND SRCS ${SRCS_LINUX_X11})
endif()
Expand Down
Loading