From b921d78fe770bf6ddc4f6c5b8b985d7260a55431 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 23 Feb 2024 10:09:13 -0800 Subject: [PATCH] Add support for protected SwapChain. This is supported only by the PlatformEGL currently. There is not much that can be done with it either at this point. A protected swapchain is one that can only be written by a protected context, however, there is currently no way to create such context. --- .../src/main/cpp/SwapChain.cpp | 12 +++++- .../google/android/filament/SwapChain.java | 18 +++++++++ .../backend/include/backend/DriverEnums.h | 9 ++++- .../backend/platforms/OpenGLPlatform.h | 24 ++++++++---- .../include/backend/platforms/PlatformEGL.h | 4 ++ .../include/private/backend/DriverAPI.inc | 1 + filament/backend/src/metal/MetalDriver.mm | 5 +++ filament/backend/src/noop/NoopDriver.cpp | 4 ++ filament/backend/src/opengl/OpenGLDriver.cpp | 4 ++ .../backend/src/opengl/OpenGLPlatform.cpp | 4 ++ .../src/opengl/platforms/PlatformEGL.cpp | 38 +++++++++++++++++-- filament/backend/src/vulkan/VulkanDriver.cpp | 5 +++ filament/include/filament/SwapChain.h | 21 ++++++++-- filament/src/SwapChain.cpp | 8 ++++ filament/src/details/SwapChain.cpp | 10 +++++ filament/src/details/SwapChain.h | 2 + 16 files changed, 152 insertions(+), 17 deletions(-) diff --git a/android/filament-android/src/main/cpp/SwapChain.cpp b/android/filament-android/src/main/cpp/SwapChain.cpp index 27e006ae87..e1424595b2 100644 --- a/android/filament-android/src/main/cpp/SwapChain.cpp +++ b/android/filament-android/src/main/cpp/SwapChain.cpp @@ -34,7 +34,15 @@ Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* en } extern "C" JNIEXPORT jboolean JNICALL -Java_com_google_android_filament_SwapChain_nIsSRGBSwapChainSupported(JNIEnv *, jclass, jlong nativeEngine) { +Java_com_google_android_filament_SwapChain_nIsSRGBSwapChainSupported( + JNIEnv *, jclass, jlong nativeEngine) { Engine* engine = (Engine*) nativeEngine; - return (bool)SwapChain::isSRGBSwapChainSupported(*engine); + return (jboolean)SwapChain::isSRGBSwapChainSupported(*engine); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_google_android_filament_SwapChain_nIsProtectedContentSupported( + JNIEnv *, jclass, jlong nativeEngine) { + Engine* engine = (Engine*) nativeEngine; + return (jboolean)SwapChain::isProtectedContentSupported(*engine); } diff --git a/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java b/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java index 429af3e140..e3d1cf43aa 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java +++ b/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java @@ -128,11 +128,28 @@ public class SwapChain { */ public static final long CONFIG_HAS_STENCIL_BUFFER = 0x20; + /** + * The SwapChain contains protected content. Only supported when isProtectedContentSupported() + * is true. + */ + public static final long CONFIG_PROTECTED_CONTENT = 0x40; + SwapChain(long nativeSwapChain, Object surface) { mNativeObject = nativeSwapChain; mSurface = surface; } + /** + * Return whether createSwapChain supports the CONFIG_PROTECTED_CONTENT flag. + * The default implementation returns false. + * + * @param engine A reference to the filament Engine + * @return true if CONFIG_PROTECTED_CONTENT is supported, false otherwise. + */ + public static boolean isProtectedContentSupported(@NonNull Engine engine) { + return nIsProtectedContentSupported(engine.getNativeObject()); + } + /** * Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag. * The default implementation returns false. @@ -186,4 +203,5 @@ public class SwapChain { private static native void nSetFrameCompletedCallback(long nativeSwapChain, Object handler, Runnable callback); private static native boolean nIsSRGBSwapChainSupported(long nativeEngine); + private static native boolean nIsProtectedContentSupported(long nativeEngine); } diff --git a/filament/backend/include/backend/DriverEnums.h b/filament/backend/include/backend/DriverEnums.h index 035179486a..61a8b0ad70 100644 --- a/filament/backend/include/backend/DriverEnums.h +++ b/filament/backend/include/backend/DriverEnums.h @@ -81,7 +81,14 @@ static constexpr uint64_t SWAP_CHAIN_CONFIG_SRGB_COLORSPACE = 0x10; /** * Indicates that the SwapChain should also contain a stencil component. */ -static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = 0x20; +static constexpr uint64_t SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER = 0x20; +static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER; + +/** + * The SwapChain contains protected content. Currently only supported by OpenGLPlatform and + * only when OpenGLPlatform::isProtectedContextSupported() is true. + */ +static constexpr uint64_t SWAP_CHAIN_CONFIG_PROTECTED_CONTENT = 0x40; static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES. diff --git a/filament/backend/include/backend/platforms/OpenGLPlatform.h b/filament/backend/include/backend/platforms/OpenGLPlatform.h index 12deb80130..63b346fe46 100644 --- a/filament/backend/include/backend/platforms/OpenGLPlatform.h +++ b/filament/backend/include/backend/platforms/OpenGLPlatform.h @@ -62,6 +62,22 @@ public: */ virtual void terminate() noexcept = 0; + /** + * Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag. + * The default implementation returns false. + * + * @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise. + */ + virtual bool isSRGBSwapChainSupported() const noexcept; + + /** + * Return whether protected contexts are supported by this backend. + * If protected context are supported, the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag can be + * used when creating a SwapChain. + * The default implementation returns false. + */ + virtual bool isProtectedContextSupported() const noexcept; + /** * Called by the driver to create a SwapChain for this driver. * @@ -74,14 +90,6 @@ public: virtual SwapChain* UTILS_NONNULL createSwapChain( void* UTILS_NULLABLE nativeWindow, uint64_t flags) noexcept = 0; - /** - * Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag. - * The default implementation returns false. - * - * @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise. - */ - virtual bool isSRGBSwapChainSupported() const noexcept; - /** * Called by the driver create a headless SwapChain. * diff --git a/filament/backend/include/backend/platforms/PlatformEGL.h b/filament/backend/include/backend/platforms/PlatformEGL.h index 61b7ec8c45..c1be11e137 100644 --- a/filament/backend/include/backend/platforms/PlatformEGL.h +++ b/filament/backend/include/backend/platforms/PlatformEGL.h @@ -91,6 +91,8 @@ protected: void terminate() noexcept override; + bool isProtectedContextSupported() const noexcept override; + bool isSRGBSwapChainSupported() const noexcept override; SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override; SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override; @@ -148,6 +150,7 @@ protected: bool KHR_gl_colorspace = false; bool KHR_no_config_context = false; bool KHR_surfaceless_context = false; + bool EXT_protected_content = false; } egl; } ext; @@ -156,6 +159,7 @@ protected: Config attribs{}; EGLNativeWindowType nativeWindow{}; EGLConfig config{}; + uint64_t flags{}; }; void initializeGlExtensions() noexcept; diff --git a/filament/backend/include/private/backend/DriverAPI.inc b/filament/backend/include/private/backend/DriverAPI.inc index b04a71059c..09a302c9d7 100644 --- a/filament/backend/include/private/backend/DriverAPI.inc +++ b/filament/backend/include/private/backend/DriverAPI.inc @@ -298,6 +298,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchMultiSampleSupported) DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameTimeSupported) DECL_DRIVER_API_SYNCHRONOUS_0(bool, isAutoDepthResolveSupported) DECL_DRIVER_API_SYNCHRONOUS_0(bool, isSRGBSwapChainSupported) +DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedContentSupported) DECL_DRIVER_API_SYNCHRONOUS_N(bool, isStereoSupported, backend::StereoscopicType, stereoscopicType) DECL_DRIVER_API_SYNCHRONOUS_0(bool, isParallelShaderCompileSupported) DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthStencilResolveSupported) diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index f36fbfb0da..4761b33e2f 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -770,6 +770,11 @@ bool MetalDriver::isSRGBSwapChainSupported() { return false; } +bool MetalDriver::isProtectedContentSupported() { + // the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag is not supported + return false; +} + bool MetalDriver::isStereoSupported(backend::StereoscopicType stereoscopicType) { switch (stereoscopicType) { case backend::StereoscopicType::INSTANCED: diff --git a/filament/backend/src/noop/NoopDriver.cpp b/filament/backend/src/noop/NoopDriver.cpp index 6c29129789..f6de98ceae 100644 --- a/filament/backend/src/noop/NoopDriver.cpp +++ b/filament/backend/src/noop/NoopDriver.cpp @@ -177,6 +177,10 @@ bool NoopDriver::isSRGBSwapChainSupported() { return false; } +bool NoopDriver::isProtectedContentSupported() { + return false; +} + bool NoopDriver::isStereoSupported(backend::StereoscopicType) { return false; } diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp index 9682fc2ce1..d496fea911 100644 --- a/filament/backend/src/opengl/OpenGLDriver.cpp +++ b/filament/backend/src/opengl/OpenGLDriver.cpp @@ -1938,6 +1938,10 @@ bool OpenGLDriver::isSRGBSwapChainSupported() { return mPlatform.isSRGBSwapChainSupported(); } +bool OpenGLDriver::isProtectedContentSupported() { + return mPlatform.isProtectedContextSupported(); +} + bool OpenGLDriver::isStereoSupported(backend::StereoscopicType stereoscopicType) { // Instanced-stereo requires instancing and EXT_clip_cull_distance. // Multiview-stereo requires ES 3.0 and OVR_multiview2. diff --git a/filament/backend/src/opengl/OpenGLPlatform.cpp b/filament/backend/src/opengl/OpenGLPlatform.cpp index ccffdfa6d4..d3aa2e6f99 100644 --- a/filament/backend/src/opengl/OpenGLPlatform.cpp +++ b/filament/backend/src/opengl/OpenGLPlatform.cpp @@ -35,6 +35,10 @@ Driver* OpenGLPlatform::createDefaultDriver(OpenGLPlatform* platform, OpenGLPlatform::~OpenGLPlatform() noexcept = default; +bool OpenGLPlatform::isProtectedContextSupported() const noexcept { + return false; +} + bool OpenGLPlatform::isSRGBSwapChainSupported() const noexcept { return false; } diff --git a/filament/backend/src/opengl/platforms/PlatformEGL.cpp b/filament/backend/src/opengl/platforms/PlatformEGL.cpp index c05fa09786..ab01df1122 100644 --- a/filament/backend/src/opengl/platforms/PlatformEGL.cpp +++ b/filament/backend/src/opengl/platforms/PlatformEGL.cpp @@ -152,6 +152,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon ext.egl.KHR_create_context = extensions.has("EGL_KHR_create_context"); ext.egl.KHR_no_config_context = extensions.has("EGL_KHR_no_config_context"); ext.egl.KHR_surfaceless_context = extensions.has("EGL_KHR_surfaceless_context"); + ext.egl.EXT_protected_content = extensions.has("EGL_EXT_protected_content"); if (ext.egl.KHR_create_context) { // KHR_create_context implies KHR_surfaceless_context for ES3.x contexts ext.egl.KHR_surfaceless_context = true; @@ -318,6 +319,10 @@ bool PlatformEGL::isExtraContextSupported() const noexcept { return ext.egl.KHR_surfaceless_context; } +bool PlatformEGL::isProtectedContextSupported() const noexcept { + return ext.egl.EXT_protected_content; +} + void PlatformEGL::createContext(bool shared) { EGLConfig config = ext.egl.KHR_no_config_context ? EGL_NO_CONFIG_KHR : mEGLConfig; @@ -438,6 +443,8 @@ EGLConfig PlatformEGL::findSwapChainConfig(uint64_t flags, bool window, bool pbu return config; } +// ----------------------------------------------------------------------------------------------- + bool PlatformEGL::isSRGBSwapChainSupported() const noexcept { return ext.egl.KHR_gl_colorspace; } @@ -462,6 +469,16 @@ Platform::SwapChain* PlatformEGL::createSwapChain( if (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) { attribs[EGL_GL_COLORSPACE_KHR] = EGL_GL_COLORSPACE_SRGB_KHR; } + } else { + flags &= ~SWAP_CHAIN_CONFIG_SRGB_COLORSPACE; + } + + if (ext.egl.EXT_protected_content) { + if (flags & SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) { + attribs[EGL_PROTECTED_CONTENT_EXT] = EGL_TRUE; + } + } else { + flags &= ~SWAP_CHAIN_CONFIG_PROTECTED_CONTENT; } EGLSurface sur = eglCreateWindowSurface(mEGLDisplay, config, @@ -479,7 +496,8 @@ Platform::SwapChain* PlatformEGL::createSwapChain( .sur = sur, .attribs = std::move(attribs), .nativeWindow = (EGLNativeWindowType)nativeWindow, - .config = config + .config = config, + .flags = flags }); return sc; } @@ -507,6 +525,16 @@ Platform::SwapChain* PlatformEGL::createSwapChain( if (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) { attribs[EGL_GL_COLORSPACE_KHR] = EGL_GL_COLORSPACE_SRGB_KHR; } + } else { + flags &= ~SWAP_CHAIN_CONFIG_SRGB_COLORSPACE; + } + + if (ext.egl.EXT_protected_content) { + if (flags & SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) { + attribs[EGL_PROTECTED_CONTENT_EXT] = EGL_TRUE; + } + } else { + flags &= ~SWAP_CHAIN_CONFIG_PROTECTED_CONTENT; } EGLSurface sur = eglCreatePbufferSurface(mEGLDisplay, config, attribs.data()); @@ -554,6 +582,8 @@ void PlatformEGL::commit(Platform::SwapChain* swapChain) noexcept { } } +// ----------------------------------------------------------------------------------------------- + bool PlatformEGL::canCreateFence() noexcept { return true; } @@ -592,6 +622,8 @@ FenceStatus PlatformEGL::waitFence( return FenceStatus::ERROR; } +// ----------------------------------------------------------------------------------------------- + OpenGLPlatform::ExternalTexture* PlatformEGL::createExternalImageTexture() noexcept { ExternalTexture* outTexture = new(std::nothrow) ExternalTexture{}; glGenTextures(1, &outTexture->id); @@ -622,6 +654,8 @@ bool PlatformEGL::setExternalImage(void* externalImage, return true; } +// ----------------------------------------------------------------------------------------------- + void PlatformEGL::initializeGlExtensions() noexcept { // We're guaranteed to be on an ES platform, since we're using EGL GLUtils::unordered_string_set glExtensions; @@ -667,5 +701,3 @@ void PlatformEGL::Config::erase(EGLint name) noexcept { } } // namespace filament::backend - -// --------------------------------------------------------------------------------------------- diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 7c8b19a992..c5f0cdb90a 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -868,6 +868,11 @@ bool VulkanDriver::isSRGBSwapChainSupported() { return mIsSRGBSwapChainSupported; } +bool VulkanDriver::isProtectedContentSupported() { + // the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag is not supported + return false; +} + bool VulkanDriver::isStereoSupported(backend::StereoscopicType stereoscopicType) { switch (stereoscopicType) { case backend::StereoscopicType::INSTANCED: diff --git a/filament/include/filament/SwapChain.h b/filament/include/filament/SwapChain.h index 8db477ade0..404ab0c1db 100644 --- a/filament/include/filament/SwapChain.h +++ b/filament/include/filament/SwapChain.h @@ -225,14 +225,29 @@ public: * @see View.setStencilBufferEnabled * @see View.setPostProcessingEnabled */ - static constexpr uint64_t CONFIG_HAS_STENCIL_BUFFER = backend::SWAP_CHAIN_HAS_STENCIL_BUFFER; + static constexpr uint64_t CONFIG_HAS_STENCIL_BUFFER = backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER; /** - * Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag. + * The SwapChain contains protected content. Only supported when isProtectedContentSupported() + * is true. + */ + static constexpr uint64_t CONFIG_PROTECTED_CONTENT = backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT; + + /** + * Return whether createSwapChain supports the CONFIG_PROTECTED_CONTENT flag. * The default implementation returns false. * * @param engine A pointer to the filament Engine - * @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise. + * @return true if CONFIG_PROTECTED_CONTENT is supported, false otherwise. + */ + static bool isProtectedContentSupported(Engine& engine) noexcept; + + /** + * Return whether createSwapChain supports the CONFIG_SRGB_COLORSPACE flag. + * The default implementation returns false. + * + * @param engine A pointer to the filament Engine + * @return true if CONFIG_SRGB_COLORSPACE is supported, false otherwise. */ static bool isSRGBSwapChainSupported(Engine& engine) noexcept; diff --git a/filament/src/SwapChain.cpp b/filament/src/SwapChain.cpp index c30bce6941..1800056887 100644 --- a/filament/src/SwapChain.cpp +++ b/filament/src/SwapChain.cpp @@ -18,6 +18,10 @@ #include "details/Engine.h" +#include + +#include + namespace filament { void* SwapChain::getNativeWindow() const noexcept { @@ -37,4 +41,8 @@ bool SwapChain::isSRGBSwapChainSupported(Engine& engine) noexcept { return FSwapChain::isSRGBSwapChainSupported(downcast(engine)); } +bool SwapChain::isProtectedContentSupported(Engine& engine) noexcept { + return FSwapChain::isProtectedContentSupported(downcast(engine)); +} + } // namespace filament diff --git a/filament/src/details/SwapChain.cpp b/filament/src/details/SwapChain.cpp index d9cb80911d..956fa0660f 100644 --- a/filament/src/details/SwapChain.cpp +++ b/filament/src/details/SwapChain.cpp @@ -18,6 +18,12 @@ #include "details/Engine.h" + +#include +#include + +#include + namespace filament { FSwapChain::FSwapChain(FEngine& engine, void* nativeWindow, uint64_t flags) @@ -62,4 +68,8 @@ bool FSwapChain::isSRGBSwapChainSupported(FEngine& engine) noexcept { return engine.getDriverApi().isSRGBSwapChainSupported(); } +bool FSwapChain::isProtectedContentSupported(FEngine& engine) noexcept { + return engine.getDriverApi().isProtectedContentSupported(); +} + } // namespace filament diff --git a/filament/src/details/SwapChain.h b/filament/src/details/SwapChain.h index 3c820b9799..6bee699446 100644 --- a/filament/src/details/SwapChain.h +++ b/filament/src/details/SwapChain.h @@ -73,6 +73,8 @@ public: static bool isSRGBSwapChainSupported(FEngine& engine) noexcept; + static bool isProtectedContentSupported(FEngine& engine) noexcept; + private: FEngine& mEngine; backend::Handle mSwapChain;