From 446959042fa15dbb675f24dbb1ecc1a0620d66ea Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Fri, 24 Aug 2018 17:17:40 -0700 Subject: [PATCH] Make code friendly to WebAssembly. (#140) This does not add any build stuff or new sample code yet, it just does some prep to our C++ codebase: - Similar to Android, WebAssembly will not be using BlueGL. We were using a mixture of #if and #ifdef when checking for the existence of certain GL prototypes, but the latter is what we want in order to build robustly with any GL headers. (We still perform run-time checks for extensions, this doesn't change that.) - Add a trivial ContextManager, does a bit more than Dummy since it needs to create an actual driver. This doesn't get compiled yet, it just adds files to the tree. - WebAssembly does not support mmap, execinfo, or asm volatile. --- filament/src/driver/CircularBuffer.cpp | 11 ++-- filament/src/driver/ExternalContext.cpp | 4 ++ .../src/driver/opengl/ContextManagerWebGL.cpp | 58 +++++++++++++++++ .../src/driver/opengl/ContextManagerWebGL.h | 63 +++++++++++++++++++ filament/src/driver/opengl/OpenGLDriver.cpp | 6 +- filament/src/driver/opengl/gl_headers.h | 2 +- libs/utils/include/utils/compiler.h | 4 ++ libs/utils/src/CallStack.cpp | 11 ++-- 8 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 filament/src/driver/opengl/ContextManagerWebGL.cpp create mode 100644 filament/src/driver/opengl/ContextManagerWebGL.h diff --git a/filament/src/driver/CircularBuffer.cpp b/filament/src/driver/CircularBuffer.cpp index 2378a76577..8195982d46 100644 --- a/filament/src/driver/CircularBuffer.cpp +++ b/filament/src/driver/CircularBuffer.cpp @@ -16,9 +16,12 @@ #include "driver/CircularBuffer.h" -#if !defined(WIN32) +#if !defined(WIN32) && !defined(__EMSCRIPTEN__) # include # include +# define HAS_MMAP 1 +#else +# define HAS_MMAP 0 #endif #include @@ -27,12 +30,6 @@ #include #include -#if defined(WIN32) -# define HAS_MMAP 0 -#else -# define HAS_MMAP 1 -#endif - using namespace utils; namespace filament { diff --git a/filament/src/driver/ExternalContext.cpp b/filament/src/driver/ExternalContext.cpp index a9029c4ef4..7df72735f7 100644 --- a/filament/src/driver/ExternalContext.cpp +++ b/filament/src/driver/ExternalContext.cpp @@ -44,6 +44,8 @@ #if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN) #include "driver/vulkan/ContextManagerVkWindows.h" #endif +#elif defined(__EMSCRIPTEN__) + #include "driver/opengl/ContextManagerWebGL.h" #else #ifndef USE_EXTERNAL_GLES3 #include "driver/opengl/ContextManagerDummy.h" @@ -92,6 +94,8 @@ ExternalContext* ExternalContext::create(Backend* backend) noexcept { return new ContextManagerGLX(); #elif defined(WIN32) return new ContextManagerWGL(); + #elif defined(__EMSCRIPTEN__) + return new ContextManagerWebGL(); #else return new ContextManagerDummy(); #endif diff --git a/filament/src/driver/opengl/ContextManagerWebGL.cpp b/filament/src/driver/opengl/ContextManagerWebGL.cpp new file mode 100644 index 0000000000..e0626d6313 --- /dev/null +++ b/filament/src/driver/opengl/ContextManagerWebGL.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 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 "driver/opengl/ContextManagerWebGL.h" +#include "driver/opengl/OpenGLDriver.h" + +namespace filament { + +using namespace driver; + +std::unique_ptr ContextManagerWebGL::createDriver(void* const sharedGLContext) noexcept { + return OpenGLDriver::create(this, sharedGLContext); +} + +void ContextManagerWebGL::terminate() noexcept { +} + +ExternalContext::SwapChain* ContextManagerWebGL::createSwapChain( + void* nativeWindow, uint64_t& flags) noexcept { + return (SwapChain*) nativeWindow; +} + +void ContextManagerWebGL::destroySwapChain(ExternalContext::SwapChain* swapChain) noexcept { +} + +void ContextManagerWebGL::makeCurrent(ExternalContext::SwapChain* swapChain) noexcept { +} + +void ContextManagerWebGL::commit(ExternalContext::SwapChain* swapChain) noexcept { +} + +ExternalContext::Fence* ContextManagerWebGL::createFence() noexcept { + Fence* f = new Fence(); + return f; +} + +void ContextManagerWebGL::destroyFence(Fence* fence) noexcept { + delete fence; +} + +driver::FenceStatus ContextManagerWebGL::waitFence(Fence* fence, uint64_t timeout) noexcept { + return driver::FenceStatus::CONDITION_SATISFIED; +} + +} // namespace filament diff --git a/filament/src/driver/opengl/ContextManagerWebGL.h b/filament/src/driver/opengl/ContextManagerWebGL.h new file mode 100644 index 0000000000..b053676469 --- /dev/null +++ b/filament/src/driver/opengl/ContextManagerWebGL.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 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_DRIVER_OPENGL_CONTEXT_MANAGER_WEBGL_H +#define TNT_FILAMENT_DRIVER_OPENGL_CONTEXT_MANAGER_WEBGL_H + +#include + +#include +#include + +#include +#include + +namespace filament { + +class ContextManagerWebGL final : public driver::ContextManagerGL { +public: + + std::unique_ptr createDriver(void* const sharedGLContext) noexcept override; + void terminate() noexcept override; + + SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept final override; + void destroySwapChain(SwapChain* swapChain) noexcept final override; + void makeCurrent(SwapChain* swapChain) noexcept final override; + void commit(SwapChain* swapChain) noexcept final override; + + Fence* createFence() noexcept final override; + void destroyFence(Fence* fence) noexcept final override; + driver::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept final override; + + Stream* createStream(void* nativeStream) noexcept final override { return nullptr; } + void destroyStream(Stream* stream) noexcept final override {} + void attach(Stream* stream, intptr_t tname) noexcept final override {} + void detach(Stream* stream) noexcept final override {} + void updateTexImage(Stream* stream) noexcept final override {} + + ExternalTexture* createExternalTextureStorage() noexcept final override { return nullptr; } + void reallocateExternalStorage(ExternalTexture* ets, + uint32_t w, uint32_t h, driver::TextureFormat format) noexcept final override { } + void destroyExternalTextureStorage(ExternalTexture* ets) noexcept final override { } + + int getOSVersion() const noexcept final override { return 0; } +}; + +using ContextManager = filament::ContextManagerWebGL; + +} // namespace filament + +#endif // TNT_FILAMENT_DRIVER_OPENGL_CONTEXT_MANAGER_WEBGL_H diff --git a/filament/src/driver/opengl/OpenGLDriver.cpp b/filament/src/driver/opengl/OpenGLDriver.cpp index 247d8583c4..9fbde02cee 100644 --- a/filament/src/driver/opengl/OpenGLDriver.cpp +++ b/filament/src/driver/opengl/OpenGLDriver.cpp @@ -2368,7 +2368,7 @@ GLuint OpenGLDriver::getSamplerSlow(driver::SamplerParams params) const noexcept } void OpenGLDriver::insertEventMarker(char const* string, size_t len) { -#if GL_EXT_debug_marker +#ifdef GL_EXT_debug_marker if (ext.EXT_debug_marker) { glInsertEventMarkerEXT(GLsizei(len ? len : strlen(string)), string); } @@ -2376,7 +2376,7 @@ void OpenGLDriver::insertEventMarker(char const* string, size_t len) { } void OpenGLDriver::pushGroupMarker(char const* string, size_t len) { -#if GL_EXT_debug_marker +#ifdef GL_EXT_debug_marker if (ext.EXT_debug_marker) { glPushGroupMarkerEXT(GLsizei(len ? len : strlen(string)), string); } @@ -2384,7 +2384,7 @@ void OpenGLDriver::pushGroupMarker(char const* string, size_t len) { } void OpenGLDriver::popGroupMarker(int) { -#if GL_EXT_debug_marker +#ifdef GL_EXT_debug_marker if (ext.EXT_debug_marker) { glPopGroupMarkerEXT(); } diff --git a/filament/src/driver/opengl/gl_headers.h b/filament/src/driver/opengl/gl_headers.h index e30ae40280..476dc1f04b 100644 --- a/filament/src/driver/opengl/gl_headers.h +++ b/filament/src/driver/opengl/gl_headers.h @@ -31,7 +31,7 @@ #ifdef GL_OES_EGL_image extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; #endif -#if GL_EXT_debug_marker +#ifdef GL_EXT_debug_marker extern PFNGLINSERTEVENTMARKEREXTPROC glInsertEventMarkerEXT; extern PFNGLPUSHGROUPMARKEREXTPROC glPushGroupMarkerEXT; extern PFNGLPOPGROUPMARKEREXTPROC glPopGroupMarkerEXT; diff --git a/libs/utils/include/utils/compiler.h b/libs/utils/include/utils/compiler.h index 4814543b9b..26d545fff5 100644 --- a/libs/utils/include/utils/compiler.h +++ b/libs/utils/include/utils/compiler.h @@ -110,7 +110,11 @@ #define UTILS_RESTRICT __restrict__ // TODO: set the proper alignment for the target +#ifndef __EMSCRIPTEN__ #define UTILS_ALIGN_LOOP {__asm__ __volatile__(".align 4");} +#else +#define UTILS_ALIGN_LOOP +#endif #if __has_feature(cxx_thread_local) # ifdef ANDROID diff --git a/libs/utils/src/CallStack.cpp b/libs/utils/src/CallStack.cpp index ec618a18b8..93f15845e9 100644 --- a/libs/utils/src/CallStack.cpp +++ b/libs/utils/src/CallStack.cpp @@ -22,9 +22,12 @@ #include #include -// FIXME: Android doesn't have execinfo.h (but has unwind.h) -#if !defined(ANDROID) && !defined(WIN32) +// FIXME: Some platforms do not have execinfo.h (but have unwind.h) +#if !defined(ANDROID) && !defined(WIN32) && !defined(__EMSCRIPTEN__) #include +#define HAS_EXECINFO 1 +#else +#define HAS_EXECINFO 0 #endif #if !defined(WIN32) @@ -76,7 +79,7 @@ void CallStack::update_gcc(size_t ignore) noexcept { ssize_t size = 0; void *array[NUM_FRAMES]; -#if !defined(ANDROID) && !defined(WIN32) +#if HAS_EXECINFO size = ::backtrace(array, NUM_FRAMES); size -= ignore; #endif @@ -115,7 +118,7 @@ utils::CString CallStack::demangleTypeName(const char* mangled) { // ------------------------------------------------------------------------------------------------ io::ostream& operator<<(io::ostream& stream, const CallStack& callstack) { -#if !defined(ANDROID) && !defined(WIN32) +#if HAS_EXECINFO size_t size = callstack.getFrameCount(); for (size_t i = 0; i < size; i++) { intptr_t pc = callstack[i];