Skip to content

Commit

Permalink
[engine] A headless OpenGL renderer for MacOS
Browse files Browse the repository at this point in the history
Inspired by pull request #76, thank you!
  • Loading branch information
tkoeppe committed Jan 15, 2021
1 parent 4ba75db commit f10251d
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 11 deletions.
37 changes: 26 additions & 11 deletions .github/workflows/precommit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,57 @@ on:

jobs:
build-and-test:
name: Build and test ${{matrix.cfg.name}} ${{matrix.os.name}}
name: Build and test ${{matrix.cfg.name}}

runs-on: ${{matrix.os.id}}
runs-on: ${{matrix.cfg.os}}

strategy:
matrix:
os:
- { name: 'Linux', id: 'ubuntu-20.04' }
cfg:
- { name: 'GCC', cc: gcc-10, cxx: g++-10, config: --copt=-Wno-maybe-uninitialized }
- { name: 'LLVM+libstdc++', cc: clang, cxx: clang++, config: --copt=-Wno-uninitialized }
- { name: 'LLVM+libc++', cc: clang, cxx: clang++, config: --config=libc++ --copt=-Wno-uninitialized }
- { name: 'Linux GCC', os: 'ubuntu-20.04', cc: gcc-10, cxx: g++-10, config: --copt=-Wno-maybe-uninitialized }
- { name: 'Linux LLVM+libstdc++', os: 'ubuntu-20.04', cc: clang, cxx: clang++, config: --copt=-Wno-uninitialized }
- { name: 'Linux LLVM+libc++', os: 'ubuntu-20.04', cc: clang, cxx: clang++, config: --config=libc++ --copt=-Wno-uninitialized }
- { name: 'MacOS LLVM+libc++', os: 'macos-10.15', config: --config=libc++ --copt=-Wno-uninitialized }

env:
CC: ${{matrix.cfg.cc}}
CXX: ${{matrix.cfg.cxx}}

steps:
- uses: actions/checkout@v2
- name: install infrastructure
- name: install infrastructure (Linux)
if: matrix.cfg.os == 'ubuntu-20.04'
run: |
sudo apt-get update
sudo apt-get install gettext python2-dev python3-dev libsdl2-dev libosmesa6-dev python-numpy-dev python3-numpy-dev python-pil python3-pil python-enum34
sudo find /usr -type f -name Python.h -o -name arrayobject.h -o -name functional -o -name -filesystem
sudo ln -s /usr/lib/llvm-10/include/c++/v1 /usr/include/c++/v1
- name: build
- name: install infrastructure (MacOS)
if: matrix.cfg.os == 'macos-10.15'
run: |
brew install SDL2
sudo -H pip install numpy
sudo -H pip3 install numpy
sudo find -L /usr /Library -type f -name SDL.h -o -name glib.h -o -name Python.h -o -name arrayobject.h
- name: build (Linux)
if: matrix.cfg.os == 'ubuntu-20.04'
run: |
bazel --bazelrc=.precommit.bazelrc build ${{matrix.cfg.config}} --copt=-Wno-sign-compare //...
- name: run-tests
- name: run-tests (Linux)
if: matrix.cfg.os == 'ubuntu-20.04'
timeout-minutes: 45
run: |
bazel --bazelrc=.precommit.bazelrc test ${{matrix.cfg.config}} --copt=-Wno-sign-compare //...
bazel --bazelrc=.precommit.bazelrc test ${{matrix.cfg.config}} --copt=-Wno-sign-compare //python/tests:python_module_test.py2 --test_tag_filters="" --test_arg=--verbose
bazel --bazelrc=.precommit.bazelrc test ${{matrix.cfg.config}} --copt=-Wno-sign-compare //python/tests:python_module_test.py3 --test_tag_filters="" --test_arg=--verbose
bazel --bazelrc=.precommit.bazelrc test ${{matrix.cfg.config}} --copt=-Wno-sign-compare //python/tests:dmenv_module_test.py2 --test_tag_filters="" --test_arg=--verbose
bazel --bazelrc=.precommit.bazelrc test ${{matrix.cfg.config}} --copt=-Wno-sign-compare //python/tests:dmenv_module_test.py3 --test_tag_filters="" --test_arg=--verbose
- name: run-agent
- name: run-agent (Linux)
if: matrix.cfg.os == 'ubuntu-20.04'
run: |
bazel --bazelrc=.precommit.bazelrc run ${{matrix.cfg.config}} --copt=-Wno-sign-compare --define headless=osmesa //:python_random_agent
- name: build-and-run-tests (MacOS)
if: matrix.cfg.os == 'macos-10.15'
timeout-minutes: 45
run: |
bazel --bazelrc=.precommit.bazelrc build ${{matrix.cfg.config}} --copt=-Wno-sign-compare -c opt --dynamic_mode=off --show_progress_rate_limit=10 //:game_lib_headless_macos
24 changes: 24 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,27 @@ cc_library(
alwayslink = 1,
)

cc_library(
name = "game_lib_headless_macos",
srcs = IOQ3_COMMON_SRCS + [
CODE_DIR + "/deepmind/dmlab_connect.c",
CODE_DIR + "/null/null_input.c",
CODE_DIR + "/null/null_snddma.c",

## OpenGL rendering
CODE_DIR + "/deepmind/headless_macos_glimp.c",
CODE_DIR + "/deepmind/glimp_common.h",
CODE_DIR + "/deepmind/glimp_common.c",
],
hdrs = ["public/dmlab.h"],
copts = IOQ3_COMMON_COPTS,
defines = IOQ3_COMMON_DEFINES,
linkopts = ["-framework OpenGL"],
tags = ["manual"], # don't build on Linux with //...
deps = IOQ3_COMMON_DEPS,
alwayslink = 1,
)

cc_library(
name = "game_lib_headless_osmesa",
srcs = IOQ3_COMMON_SRCS + [
Expand Down Expand Up @@ -929,11 +950,13 @@ config_setting(

config_setting(
name = "dmlab_graphics_osmesa_or_glx",
constraint_values = ["@platforms//os:linux"],
define_values = {"graphics": "osmesa_or_glx"},
)

config_setting(
name = "dmlab_graphics_osmesa_or_egl",
constraint_values = ["@platforms//os:linux"],
define_values = {"graphics": "osmesa_or_egl"},
)

Expand All @@ -947,6 +970,7 @@ cc_binary(
linkstatic = 1,
visibility = ["//testing:__subpackages__"],
deps = [":dmlab.lds"] + select({
"is_macos": [":game_lib_headless_macos"],
"dmlab_graphics_osmesa_or_egl": [":game_lib_headless_egl"],
"dmlab_graphics_osmesa_or_glx": [":game_lib_headless_glx"],
"//conditions:default": [":game_lib_headless_egl"],
Expand Down
58 changes: 58 additions & 0 deletions engine/code/deepmind/headless_macos_glimp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

#include <OpenGL/OpenGL.h>
#include <OpenGL/gl3.h>

#include "glimp_common.h"

static CGLContextObj context;

void GLimp_MakeCurrent(void) {
}

void GLimp_Init(void) {
CGLPixelFormatObj pix;
GLint npix;
int attribs[] = {
kCGLPFAAccelerated, // no software rendering
kCGLPFAOpenGLProfile,
kCGLOGLPVersion_Legacy,
0
};

GLimp_CommonPreInit();

// NOTE: in headless mode there is no GUI, hence output to console instead of message boxes

if (CGLChoosePixelFormat((CGLPixelFormatAttribute*)attribs, &pix, &npix) != kCGLNoError) {
// Sys_Error("GLimp_Init - choose pixel format error!\n");
printf("GLimp_Init - choose pixel format error!\n");
exit(1);
}
if (CGLCreateContext(pix, NULL, &context) != kCGLNoError) {
// Sys_Error("GLimp_Init - create context error!\n");
printf("GLimp_Init - create context error!\n");
exit(1);
}
if (CGLSetCurrentContext(context) != kCGLNoError) {
// Sys_Error("GLimp_Init - set current context error!");
printf("GLimp_Init - set current context error!\n");
exit(1);
}
CGLDestroyPixelFormat(pix);

printf("Renderer: %s\nVersion: %s\n", glGetString(GL_RENDERER), glGetString(GL_VERSION));

GLimp_CommonPostInit();
}

void* GLimp_GetProcAddress(const char* func) {
return dlsym(RTLD_SELF, func);
}

void GLimp_Shutdown(void) {
CGLSetCurrentContext(NULL);
CGLDestroyContext(context);
}

0 comments on commit f10251d

Please sign in to comment.